diff --git a/abc/CMakeLists.txt b/abc/CMakeLists.txt index 300ce808cbb..cee9bc72fd4 100644 --- a/abc/CMakeLists.txt +++ b/abc/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.3.0...3.13) # ! This line is edited to get rid of a CMake deprecation error +cmake_minimum_required(VERSION 3.3.0) include(CMakeParseArguments) include(CheckCCompilerFlag) @@ -47,9 +47,14 @@ if(ABC_USE_NAMESPACE) set(ABC_USE_NAMESPACE_FLAGS "ABC_USE_NAMESPACE=${ABC_USE_NAMESPACE}") endif() +if( APPLE ) + set(make_env ${CMAKE_COMMAND} -E env SDKROOT=${CMAKE_OSX_SYSROOT}) +endif() + # run make to extract compiler options, linker options and list of source files execute_process( COMMAND + ${make_env} make ${ABC_READLINE_FLAGS} ${ABC_USE_NAMESPACE_FLAGS} diff --git a/abc/Makefile b/abc/Makefile index c59cf11722c..3976cf7b159 100644 --- a/abc/Makefile +++ b/abc/Makefile @@ -1,6 +1,7 @@ CC := gcc CXX := g++ +AR := ar LD := $(CXX) MSG_PREFIX ?= @@ -8,6 +9,7 @@ ABCSRC = . $(info $(MSG_PREFIX)Using CC=$(CC)) $(info $(MSG_PREFIX)Using CXX=$(CXX)) +$(info $(MSG_PREFIX)Using AR=$(AR)) $(info $(MSG_PREFIX)Using LD=$(LD)) PROG := abc @@ -16,7 +18,7 @@ OS := $(shell uname -s) MODULES := \ $(wildcard src/ext*) \ src/base/abc src/base/abci src/base/cmd src/base/io src/base/main src/base/exor \ - src/base/ver src/base/wlc src/base/acb src/base/bac src/base/cba src/base/pla src/base/test \ + src/base/ver src/base/wlc src/base/wln src/base/acb src/base/bac src/base/cba src/base/pla src/base/test \ src/map/mapper src/map/mio src/map/super src/map/if \ src/map/amap src/map/cov src/map/scl src/map/mpm \ src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/nm \ @@ -25,7 +27,7 @@ MODULES := \ src/opt/cut src/opt/fxu src/opt/fxch src/opt/rwr src/opt/mfs src/opt/sim \ src/opt/ret src/opt/fret src/opt/res src/opt/lpk src/opt/nwk src/opt/rwt \ src/opt/cgt src/opt/csw src/opt/dar src/opt/dau src/opt/dsc src/opt/sfm src/opt/sbd \ - src/sat/bsat src/sat/xsat src/sat/satoko src/sat/csat src/sat/msat src/sat/psat src/sat/cnf src/sat/bmc src/sat/glucose \ + src/sat/bsat src/sat/xsat src/sat/satoko src/sat/csat src/sat/msat src/sat/psat src/sat/cnf src/sat/bmc src/sat/glucose src/sat/glucose2 \ src/bool/bdc src/bool/deco src/bool/dec src/bool/kit src/bool/lucky \ src/bool/rsb src/bool/rpo \ src/proof/pdr src/proof/abs src/proof/live src/proof/ssc src/proof/int \ @@ -59,9 +61,9 @@ ifneq ($(findstring arm,$(shell uname -m)),) CFLAGS += -DABC_MEMALIGN=4 endif -# compile ABC using the C++ comipler and put everything in the namespace $(ABC_NAMESPACE) +# compile ABC using the C++ compiler and put everything in the namespace $(ABC_NAMESPACE) ifdef ABC_USE_NAMESPACE - CFLAGS += -DABC_NAMESPACE=$(ABC_USE_NAMESPACE) -fpermissive + CFLAGS += -DABC_NAMESPACE=$(ABC_USE_NAMESPACE) -fpermissive -x c++ CC := $(CXX) $(info $(MSG_PREFIX)Compiling in namespace $(ABC_NAMESPACE)) endif @@ -119,11 +121,16 @@ GCC_MINOR=$(word 2,$(subst .,$(space),$(GCC_VERSION))) $(info $(MSG_PREFIX)Found GCC_VERSION $(GCC_VERSION)) ifeq ($(findstring $(GCC_MAJOR),0 1 2 3),) -$(info $(MSG_PREFIX)Found GCC_MAJOR>=4) +ifeq ($(GCC_MAJOR),4) +$(info $(MSG_PREFIX)Found GCC_MAJOR==4) ifeq ($(findstring $(GCC_MINOR),0 1 2 3 4 5),) $(info $(MSG_PREFIX)Found GCC_MINOR>=6) CFLAGS += -Wno-unused-but-set-variable endif +else +$(info $(MSG_PREFIX)Found GCC_MAJOR>=5) +CFLAGS += -Wno-unused-but-set-variable +endif endif endif @@ -179,15 +186,15 @@ DEP := $(OBJ:.o=.d) %.d: %.c @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< - $(VERBOSE)$(ABCSRC)/depends.sh $(CC) `dirname $*.c` $(OPTFLAGS) $(INCLUDES) $(CFLAGS) $< > $@ + $(VERBOSE)$(ABCSRC)/depends.sh "$(CC)" `dirname $*.c` $(OPTFLAGS) $(INCLUDES) $(CFLAGS) $< > $@ %.d: %.cc @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< - $(VERBOSE)$(ABCSRC)/depends.sh $(CXX) `dirname $*.cc` $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< > $@ + $(VERBOSE)$(ABCSRC)/depends.sh "$(CXX)" `dirname $*.cc` $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< > $@ %.d: %.cpp @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< - $(VERBOSE)$(ABCSRC)/depends.sh $(CXX) `dirname $*.cpp` $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< > $@ + $(VERBOSE)$(ABCSRC)/depends.sh "$(CXX)" `dirname $*.cpp` $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< > $@ ifndef ABC_MAKE_NO_DEPS -include $(DEP) @@ -210,8 +217,7 @@ $(PROG): $(OBJ) lib$(PROG).a: $(LIBOBJ) @echo "$(MSG_PREFIX)\`\` Linking:" $(notdir $@) - $(VERBOSE)ar rv $@ $? - $(VERBOSE)ranlib $@ + $(VERBOSE)$(AR) rsv $@ $? lib$(PROG).so: $(LIBOBJ) @echo "$(MSG_PREFIX)\`\` Linking:" $(notdir $@) diff --git a/abc/README.md b/abc/README.md index be02c72f6f1..2bb34cd036f 100644 --- a/abc/README.md +++ b/abc/README.md @@ -1,9 +1,22 @@ -[![Build Status](https://travis-ci.org/berkeley-abc/abc.svg?branch=master)](https://travis-ci.org/berkeley-abc/abc) -[![Build status](https://ci.appveyor.com/api/projects/status/7q8gopidgvyos00d?svg=true)](https://ci.appveyor.com/project/berkeley-abc/abc) +[![.github/workflows/build-posix.yml](https://github.com/berkeley-abc/abc/actions/workflows/build-posix.yml/badge.svg)](https://github.com/berkeley-abc/abc/actions/workflows/build-posix.yml) +[![.github/workflows/build-windows.yml](https://github.com/berkeley-abc/abc/actions/workflows/build-windows.yml/badge.svg)](https://github.com/berkeley-abc/abc/actions/workflows/build-windows.yml) +[![.github/workflows/build-posix-cmake.yml](https://github.com/berkeley-abc/abc/actions/workflows/build-posix-cmake.yml/badge.svg)](https://github.com/berkeley-abc/abc/actions/workflows/build-posix-cmake.yml) # ABC: System for Sequential Logic Synthesis and Formal Verification -ABC is always changing but the current snapshot is believed to be stable. +ABC is always changing but the current snapshot is believed to be stable. + +## ABC fork with new features + +Here is a [fork](https://github.com/yongshiwo/abc.git) of ABC containing Agdmap, a novel technology mapper for LUT-based FPGAs. Agdmap is based on a technology mapping algorithm with adaptive gate decomposition [1]. It is a cut enumeration based mapping algorithm with bin packing for simultaneous wide gate decomposition, which is a patent pending technology. + +The mapper is developed and maintained by Longfei Fan and Prof. Chang Wu at Fudan University in Shanghai, China. The experimental results presented in [1] indicate that Agdmap can substantially improve area (by 10% or more) when compared against the best LUT mapping solutions in ABC, such as command "if". + +The source code is provided for research and evaluation only. For commercial usage, please contact Prof. Chang Wu at wuchang@fudan.edu.cn. + +References: + +[1] L. Fan and C. Wu, "FPGA technology mapping with adaptive gate decompostion", ACM/SIGDA FPGA International Symposium on FPGAs, 2023. ## Compiling: @@ -18,7 +31,7 @@ APIs of ABC compiled as a static library. To build the demo program - * Copy demo.cc and libabc.a to the working directory + * Copy demo.c and libabc.a to the working directory * Run `gcc -Wall -g -c demo.c -o demo.o` * Run `g++ -g -o demo demo.o libabc.a -lm -ldl -lreadline -lpthread` diff --git a/abc/abc.rc b/abc/abc.rc index e50d12702eb..a3efc0b09a2 100644 --- a/abc/abc.rc +++ b/abc/abc.rc @@ -132,7 +132,9 @@ alias src_rw "st; rw -l; rwz -l; rwz -l" alias src_rs "st; rs -K 6 -N 2 -l; rs -K 9 -N 2 -l; rs -K 12 -N 2 -l" alias src_rws "st; rw -l; rs -K 6 -N 2 -l; rwz -l; rs -K 9 -N 2 -l; rwz -l; rs -K 12 -N 2 -l" alias resyn2rs "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 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" # use this script to convert 1-valued and DC-valued flops for an AIG alias fix_aig "logic; undc; strash; zero" diff --git a/abc/abclib.dsp b/abc/abclib.dsp index 2d1c36f109b..7433c513941 100644 --- a/abc/abclib.dsp +++ b/abc/abclib.dsp @@ -387,6 +387,10 @@ SOURCE=.\src\base\abci\abcOrder.c # End Source File # Begin Source File +SOURCE=.\src\base\abci\abcOrchestration.c +# End Source File +# Begin Source File + SOURCE=.\src\base\abci\abcPart.c # End Source File # Begin Source File @@ -451,6 +455,10 @@ SOURCE=.\src\base\abci\abcRr.c # End Source File # Begin Source File +SOURCE=.\src\base\abci\abcRunGen.c +# End Source File +# Begin Source File + SOURCE=.\src\base\abci\abcSat.c # End Source File # Begin Source File @@ -671,6 +679,10 @@ SOURCE=.\src\base\io\ioWriteDot.c # End Source File # Begin Source File +SOURCE=.\src\base\io\ioWriteEdgelist.c +# End Source File +# Begin Source File + SOURCE=.\src\base\io\ioWriteEqn.c # End Source File # Begin Source File @@ -807,6 +819,10 @@ SOURCE=.\src\base\wlc\wlcJson.c # End Source File # Begin Source File +SOURCE=.\src\base\wlc\wlcMem.c +# End Source File +# Begin Source File + SOURCE=.\src\base\wlc\wlcNdr.c # End Source File # Begin Source File @@ -1099,9 +1115,73 @@ SOURCE=.\src\base\acb\acbSets.h # End Source File # Begin Source File +SOURCE=.\src\base\acb\acbTest.c +# End Source File +# Begin Source File + SOURCE=.\src\base\acb\acbUtil.c # End Source File # End Group +# Begin Group "wln" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\wln\wln.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wln.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnBlast.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnCom.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnGuide.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnNdr.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnNtk.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnRead.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnRetime.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnRtl.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnWlc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnWriteVer.c +# End Source File +# End Group # End Group # Begin Group "bdd" @@ -1131,10 +1211,18 @@ SOURCE=.\src\bdd\extrab\extraBddKmap.c # End Source File # Begin Source File +SOURCE=.\src\bdd\extrab\extraBddMaxMin.c +# End Source File +# Begin Source File + SOURCE=.\src\bdd\extrab\extraBddMisc.c # End Source File # Begin Source File +SOURCE=.\src\bdd\extrab\extraBddSet.c +# End Source File +# Begin Source File + SOURCE=.\src\bdd\extrab\extraBddSymm.c # End Source File # Begin Source File @@ -2306,6 +2394,122 @@ SOURCE=.\src\sat\glucose\Vec.h SOURCE=.\src\sat\glucose\XAlloc.h # End Source File # End Group +# Begin Group "glucose2" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\glucose2\AbcGlucose2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\AbcGlucose2.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\AbcGlucoseCmd2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Alg.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Alloc.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\BoundedQueue.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\CGlucose.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\CGlucoseCore.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Constants.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Dimacs.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Glucose2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Heap.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\IntTypes.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Map.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Options.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Options2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\ParseUtils.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\pstdint.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Queue.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\SimpSolver.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\SimpSolver2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Solver.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\SolverTypes.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Sort.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\System.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\System2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Vec.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\XAlloc.h +# End Source File +# End Group # End Group # Begin Group "opt" @@ -2915,6 +3119,10 @@ SOURCE=.\src\opt\dau\dauCore.c # End Source File # Begin Source File +SOURCE=.\src\opt\dau\dauCount.c +# End Source File +# Begin Source File + SOURCE=.\src\opt\dau\dauDivs.c # End Source File # Begin Source File @@ -2943,6 +3151,14 @@ SOURCE=.\src\opt\dau\dauNonDsd.c # End Source File # Begin Source File +SOURCE=.\src\opt\dau\dauNpn.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dau\dauNpn2.c +# End Source File +# Begin Source File + SOURCE=.\src\opt\dau\dauTree.c # End Source File # End Group @@ -3635,6 +3851,10 @@ SOURCE=.\src\misc\extra\extraUtilCanon.c # End Source File # Begin Source File +SOURCE=.\src\misc\extra\extraUtilCfs.c +# End Source File +# Begin Source File + SOURCE=.\src\misc\extra\extraUtilCube.c # End Source File # Begin Source File @@ -3651,6 +3871,18 @@ SOURCE=.\src\misc\extra\extraUtilFile.c # End Source File # Begin Source File +SOURCE=.\src\misc\extra\extraUtilGen.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilMacc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilMaj.c +# End Source File +# Begin Source File + SOURCE=.\src\misc\extra\extraUtilMemory.c # End Source File # Begin Source File @@ -3659,6 +3891,14 @@ SOURCE=.\src\misc\extra\extraUtilMisc.c # End Source File # Begin Source File +SOURCE=.\src\misc\extra\extraUtilMult.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilPath.c +# End Source File +# Begin Source File + SOURCE=.\src\misc\extra\extraUtilPerm.c # End Source File # Begin Source File @@ -4691,10 +4931,22 @@ SOURCE=.\src\aig\gia\giaCSat2.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaCSat3.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaCSatOld.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaCSatP.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaCSatP.h +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaCTas.c # End Source File # Begin Source File @@ -4703,6 +4955,14 @@ SOURCE=.\src\aig\gia\giaCut.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaDecs.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaDeep.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaDfs.c # End Source File # Begin Source File @@ -4767,6 +5027,10 @@ SOURCE=.\src\aig\gia\giaFx.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaGen.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaGig.c # End Source File # Begin Source File @@ -4839,10 +5103,26 @@ SOURCE=.\src\aig\gia\giaMini.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaMinLut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaMinLut2.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaMuxes.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaNewBdd.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaNewTt.h +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaNf.c # End Source File # Begin Source File @@ -4859,6 +5139,10 @@ SOURCE=.\src\aig\gia\giaPat.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaPat2.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaPf.c # End Source File # Begin Source File @@ -4867,10 +5151,30 @@ SOURCE=.\src\aig\gia\giaQbf.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaReshape1.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaReshape2.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaResub.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaResub2.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaResub3.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaResub6.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaRetime.c # End Source File # Begin Source File @@ -4903,6 +5207,10 @@ SOURCE=.\src\aig\gia\giaSatoko.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaSatSyn.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaScl.c # End Source File # Begin Source File @@ -4927,6 +5235,10 @@ SOURCE=.\src\aig\gia\giaShrink7.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaSif.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaSim.c # End Source File # Begin Source File @@ -4935,6 +5247,10 @@ SOURCE=.\src\aig\gia\giaSim2.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaSimBase.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaSort.c # End Source File # Begin Source File @@ -4951,6 +5267,10 @@ SOURCE=.\src\aig\gia\giaStg.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaStoch.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaStr.c # End Source File # Begin Source File @@ -4963,6 +5283,10 @@ SOURCE=.\src\aig\gia\giaSupp.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaSupps.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaSweep.c # End Source File # Begin Source File @@ -4991,6 +5315,22 @@ SOURCE=.\src\aig\gia\giaTsim.c # End Source File # Begin Source File +SOURCE=.\src\aig\gia\giaTtopt.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaTransduction.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaTransduction.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaTranStoch.c +# End Source File +# Begin Source File + SOURCE=.\src\aig\gia\giaUnate.c # End Source File # Begin Source File @@ -5111,10 +5451,6 @@ SOURCE=.\src\bool\kit\kit.h # End Source File # Begin Source File -SOURCE=.\src\bool\kit\kit_.c -# End Source File -# Begin Source File - SOURCE=.\src\bool\kit\kitAig.c # End Source File # Begin Source File @@ -5299,14 +5635,30 @@ SOURCE=.\src\proof\cec\cecSatG.c # End Source File # Begin Source File +SOURCE=.\src\proof\cec\cecSatG2.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecSatG3.c +# End Source File +# Begin Source File + SOURCE=.\src\proof\cec\cecSeq.c # End Source File # Begin Source File +SOURCE=.\src\proof\cec\cecSim.c +# End Source File +# Begin Source File + SOURCE=.\src\proof\cec\cecSolve.c # End Source File # Begin Source File +SOURCE=.\src\proof\cec\cecSolveG.c +# End Source File +# Begin Source File + SOURCE=.\src\proof\cec\cecSplit.c # End Source File # Begin Source File diff --git a/abc/src/aig/aig/aig.h b/abc/src/aig/aig/aig.h index e92e512c460..5285ae72bbd 100644 --- a/abc/src/aig/aig/aig.h +++ b/abc/src/aig/aig/aig.h @@ -225,7 +225,7 @@ static inline Aig_Cut_t * Aig_CutNext( Aig_Cut_t * pCut ) { return /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// -static inline unsigned Aig_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId & 31)); } +static inline unsigned Aig_ObjCutSign( unsigned ObjId ) { return (1U << (ObjId & 31)); } static inline int Aig_WordCountOnes( unsigned uWord ) { uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); diff --git a/abc/src/aig/aig/aigCanon.c b/abc/src/aig/aig/aigCanon.c index 5ae3cd65a4d..02c9ab8f9df 100644 --- a/abc/src/aig/aig/aigCanon.c +++ b/abc/src/aig/aig/aigCanon.c @@ -631,7 +631,7 @@ void Aig_RManRecord( unsigned * pTruth, int nVarsInit ) // compute the number of words nWords = Abc_TruthWordNum( nVars ); // copy the function - memcpy( s_pRMan->pTruthInit, Kit_DsdObjTruth(pObj), 4*nWords ); + memcpy( s_pRMan->pTruthInit, Kit_DsdObjTruth(pObj), (size_t)(4*nWords) ); Kit_DsdNtkFree( pNtk ); // canonicize the output if ( s_pRMan->pTruthInit[0] & 1 ) diff --git a/abc/src/aig/aig/aigDup.c b/abc/src/aig/aig/aigDup.c index 3ccd8dabc7e..234192cb85f 100644 --- a/abc/src/aig/aig/aigDup.c +++ b/abc/src/aig/aig/aigDup.c @@ -1154,7 +1154,7 @@ Aig_Man_t * Aig_ManDupOneOutput( Aig_Man_t * p, int iPoNum, int fAddRegs ) Aig_Man_t * pNew; Aig_Obj_t * pObj = NULL; int i; - assert( Aig_ManRegNum(p) > 0 ); + //assert( Aig_ManRegNum(p) > 0 ); assert( iPoNum < Aig_ManCoNum(p)-Aig_ManRegNum(p) ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); diff --git a/abc/src/aig/aig/aigShow.c b/abc/src/aig/aig/aigShow.c index d983602a67c..e3d89942aed 100644 --- a/abc/src/aig/aig/aigShow.c +++ b/abc/src/aig/aig/aigShow.c @@ -340,7 +340,7 @@ void Aig_WriteDotAig( Aig_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * ***********************************************************************/ void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) { - extern void Abc_ShowFile( char * FileNameDot ); + extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); char FileNameDot[200]; FILE * pFile; // create the file name @@ -355,7 +355,7 @@ void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) // generate the file Aig_WriteDotAig( pMan, FileNameDot, fHaig, vBold ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); } diff --git a/abc/src/aig/aig/aigUtil.c b/abc/src/aig/aig/aigUtil.c index 767015c9e8d..68be112f181 100644 --- a/abc/src/aig/aig/aigUtil.c +++ b/abc/src/aig/aig/aigUtil.c @@ -725,7 +725,7 @@ void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig ) void Aig_ManDump( Aig_Man_t * p ) { static int Counter = 0; - char FileName[20]; + char FileName[200]; // dump the logic into a file sprintf( FileName, "aigbug\\%03d.blif", ++Counter ); Aig_ManDumpBlif( p, FileName, NULL, NULL ); @@ -1333,7 +1333,7 @@ void Aig_ManCounterExampleValueStart( Aig_Man_t * pAig, Abc_Cex_t * pCex ) pAig->pData2 = ABC_CALLOC( unsigned, Abc_BitWordNum( (pCex->iFrame + 1) * Aig_ManObjNumMax(pAig) ) ); // the register values in the counter-example should be zero Saig_ManForEachLo( pAig, pObj, k ) - assert( Abc_InfoHasBit(pCex->pData, iBit++) == 0 ); + assert( Abc_InfoHasBit(pCex->pData, iBit) == 0 ), iBit++; // iterate through the timeframes nObjs = Aig_ManObjNumMax(pAig); for ( i = 0; i <= pCex->iFrame; i++ ) diff --git a/abc/src/aig/gia/gia.c b/abc/src/aig/gia/gia.c index 8f18f69c4c8..ed6e276ac98 100644 --- a/abc/src/aig/gia/gia.c +++ b/abc/src/aig/gia/gia.c @@ -19,6 +19,7 @@ ***********************************************************************/ #include "gia.h" +#include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START @@ -202,6 +203,196 @@ Gia_Man_t * Slv_ManToAig( Gia_Man_t * pGia ) return pNew; } + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCofPisVars( Gia_Man_t * p, int nVars ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; int i, m; + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManForEachPi( p, pObj, i ) + Gia_ManAppendCi( pNew ); + Gia_ManHashStart( pNew ); + for ( m = 0; m < (1 << nVars); m++ ) + { + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + { + if ( i < nVars ) + pObj->Value = (m >> i) & 1; + else + pObj->Value = Gia_ObjToLit(pNew, Gia_ManCi(pNew, i)); + } + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManStructExperiment( Gia_Man_t * p ) +{ + extern int Cec_ManVerifyTwo( Gia_Man_t * p0, Gia_Man_t * p1, int fVerbose ); + Gia_Man_t * pTemp, * pUsed; + Vec_Ptr_t * vGias = Vec_PtrAlloc( 100 ); + Gia_Obj_t * pObj; int i, k; + Gia_ManForEachCo( p, pObj, i ) + { + int iFan0 = Gia_ObjFaninId0p(p, pObj); + pTemp = Gia_ManDupAndCones( p, &iFan0, 1, 1 ); + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pUsed, k ) + if ( Gia_ManCiNum(pTemp) == Gia_ManCiNum(pUsed) && Cec_ManVerifyTwo(pTemp, pUsed, 0) == 1 ) + { + ABC_SWAP( void *, Vec_PtrArray(vGias)[0], Vec_PtrArray(vGias)[k] ); + break; + } + else + ABC_FREE( pTemp->pCexComb ); + + printf( "\nOut %6d : ", i ); + if ( k == Vec_PtrSize(vGias) ) + printf( "Equiv to none " ); + else + printf( "Equiv to %6d ", k ); + Gia_ManPrintStats( pTemp, NULL ); + + if ( k == Vec_PtrSize(vGias) ) + Vec_PtrPush( vGias, pTemp ); + else + Gia_ManStop( pTemp ); + } + printf( "\nComputed %d classes.\n\n", Vec_PtrSize(vGias) ); + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pTemp, i ) + Gia_ManStop( pTemp ); + Vec_PtrFree( vGias ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_EnumFirstUnused( int * pUsed, int nVars ) +{ + int i; + for ( i = 0; i < nVars; i++ ) + if ( pUsed[i] == 0 ) + return i; + return -1; +} +void Gia_EnumPerms_rec( int * pUsed, int nVars, int * pPerm, int nPerm, int * pCount, FILE * pFile, int nLogVars ) +{ + int i, k, New; + if ( nPerm == nVars ) + { + if ( pFile ) + { + for ( i = 0; i < nLogVars; i++ ) + fprintf( pFile, "%c", '0' + ((*pCount) >> (nLogVars-1-i) & 1) ); + fprintf( pFile, " " ); + for ( i = 0; i < nVars; i++ ) + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, "%c", '0' + (pPerm[i] == k) ); + fprintf( pFile, "\n" ); + } + else + { + if ( *pCount < 20 ) + { + printf( "%5d : ", (*pCount) ); + for ( i = 0; i < nVars; i += 2 ) + printf( "%d %d ", pPerm[i], pPerm[i+1] ); + printf( "\n" ); + } + } + (*pCount)++; + return; + } + New = Gia_EnumFirstUnused( pUsed, nVars ); + assert( New >= 0 ); + pPerm[nPerm] = New; + assert( pUsed[New] == 0 ); + pUsed[New] = 1; + // try remaining ones + for ( i = 0; i < nVars; i++ ) + { + if ( pUsed[i] == 1 ) + continue; + pPerm[nPerm+1] = i; + assert( pUsed[i] == 0 ); + pUsed[i] = 1; + Gia_EnumPerms_rec( pUsed, nVars, pPerm, nPerm+2, pCount, pFile, nLogVars ); + assert( pUsed[i] == 1 ); + pUsed[i] = 0; + } + assert( pUsed[New] == 1 ); + pUsed[New] = 0; +} +void Gia_EnumPerms( int nVars ) +{ + int nLogVars = 0, Count = 0; + int * pUsed = ABC_CALLOC( int, nVars ); + int * pPerm = ABC_CALLOC( int, nVars ); + FILE * pFile = fopen( "pairset.pla", "wb" ); + assert( nVars % 2 == 0 ); + + printf( "Printing sets of pairs for %d objects:\n", nVars ); + Gia_EnumPerms_rec( pUsed, nVars, pPerm, 0, &Count, NULL, -1 ); + if ( Count > 20 ) + printf( "...\n" ); + printf( "Finished enumerating %d sets of pairs.\n", Count ); + + nLogVars = Abc_Base2Log( Count ); + printf( "Need %d variables to encode %d sets.\n", nLogVars, Count ); + Count = 0; + fprintf( pFile, ".i %d\n", nLogVars ); + fprintf( pFile, ".o %d\n", nVars*nVars ); + Gia_EnumPerms_rec( pUsed, nVars, pPerm, 0, &Count, pFile, nLogVars ); + fprintf( pFile, ".e\n" ); + fclose( pFile ); + printf( "Finished dumping file \"%s\".\n", "pairset.pla" ); + + ABC_FREE( pUsed ); + ABC_FREE( pPerm ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/abc/src/aig/gia/gia.h b/abc/src/aig/gia/gia.h index c19680861e4..d4edc1237ab 100644 --- a/abc/src/aig/gia/gia.h +++ b/abc/src/aig/gia/gia.h @@ -52,6 +52,7 @@ ABC_NAMESPACE_HEADER_START typedef struct Gia_MmFixed_t_ Gia_MmFixed_t; typedef struct Gia_MmFlex_t_ Gia_MmFlex_t; typedef struct Gia_MmStep_t_ Gia_MmStep_t; +typedef struct Gia_Dat_t_ Gia_Dat_t; typedef struct Gia_Rpr_t_ Gia_Rpr_t; struct Gia_Rpr_t_ @@ -170,6 +171,7 @@ struct Gia_Man_t_ Vec_Int_t * vCoReqs; // CO required times Vec_Int_t * vCoArrs; // CO arrival times Vec_Int_t * vCoAttrs; // CO attributes + Vec_Int_t * vWeights; // object attributes int And2Delay; // delay of the AND gate float DefInArrs; // default PI arrival times float DefOutReqs; // default PO required times @@ -178,6 +180,7 @@ struct Gia_Man_t_ int nTravIdsAlloc; // the number of trav IDs allocated Vec_Ptr_t * vNamesIn; // the input names Vec_Ptr_t * vNamesOut; // the output names + Vec_Ptr_t * vNamesNode; // the node names Vec_Int_t * vUserPiIds; // numbers assigned to PIs by the user Vec_Int_t * vUserPoIds; // numbers assigned to POs by the user Vec_Int_t * vUserFfIds; // numbers assigned to FFs by the user @@ -204,12 +207,17 @@ struct Gia_Man_t_ int fBuiltInSim; int iPatsPi; int nSimWords; + int nSimWordsT; int iPastPiMax; int nSimWordsMax; Vec_Wrd_t * vSims; + Vec_Wrd_t * vSimsT; Vec_Wrd_t * vSimsPi; + Vec_Wrd_t * vSimsPo; Vec_Int_t * vClassOld; Vec_Int_t * vClassNew; + Vec_Int_t * vPats; + Vec_Bit_t * vPolars; // incremental simulation int fIncrSim; int iNextPi; @@ -231,6 +239,8 @@ struct Gia_Man_t_ Vec_Wrd_t * vSuppWords; // support information Vec_Int_t vCopiesTwo; // intermediate copies Vec_Int_t vSuppVars; // used variables + Vec_Int_t vVarMap; // used variables + Gia_Dat_t * pUData; }; @@ -246,6 +256,7 @@ struct Gps_Par_t_ int fMiter; int fSkipMap; int fSlacks; + int fNoColor; char * pDumpFile; }; @@ -333,6 +344,7 @@ struct Jf_Par_t_ int fCutMin; int fFuncDsd; int fGenCnf; + int fGenLit; int fCnfObjIds; int fAddOrCla; int fCnfMapping; @@ -355,7 +367,7 @@ struct Jf_Par_t_ word WordMapDelay; word WordMapArea; word WordMapDelayTarget; - float MapDelay; + int MapDelay; float MapArea; float MapAreaF; float MapDelayTarget; @@ -471,6 +483,11 @@ static inline int Gia_ObjValue( Gia_Obj_t * pObj ) { static inline void Gia_ObjSetValue( Gia_Obj_t * pObj, int i ) { pObj->Value = i; } static inline int Gia_ObjPhase( Gia_Obj_t * pObj ) { return pObj->fPhase; } static inline int Gia_ObjPhaseReal( Gia_Obj_t * pObj ) { return Gia_Regular(pObj)->fPhase ^ Gia_IsComplement(pObj); } +static inline int Gia_ObjPhaseDiff( Gia_Man_t * p, int i, int k ) { return Gia_ManObj(p, i)->fPhase ^ Gia_ManObj(p, k)->fPhase; } +static inline char * Gia_ObjCiName( Gia_Man_t * p, int i ) { return p->vNamesIn ? (char*)Vec_PtrEntry(p->vNamesIn, i) : NULL; } +static inline char * Gia_ObjCoName( Gia_Man_t * p, int i ) { return p->vNamesOut ? (char*)Vec_PtrEntry(p->vNamesOut, i) : NULL; } +static inline char * Gia_ObjName( Gia_Man_t * p, int i ) { return p->vNamesNode ? (char*)Vec_PtrEntry(p->vNamesNode, i) : NULL; } +static inline char * Gia_ObjNameObj( Gia_Man_t * p, Gia_Obj_t * pObj ) { return p->vNamesNode ? (char*)Vec_PtrEntry(p->vNamesNode, Gia_ObjId(p, pObj)) : NULL; } static inline int Gia_ObjIsTerm( Gia_Obj_t * pObj ) { return pObj->fTerm; } static inline int Gia_ObjIsAndOrConst0( Gia_Obj_t * pObj ) { return!pObj->fTerm; } @@ -510,18 +527,22 @@ static inline int Gia_ObjDiff1( Gia_Obj_t * pObj ) { static inline int Gia_ObjFaninC0( Gia_Obj_t * pObj ) { return pObj->fCompl0; } static inline int Gia_ObjFaninC1( Gia_Obj_t * pObj ) { return pObj->fCompl1; } static inline int Gia_ObjFaninC2( Gia_Man_t * p, Gia_Obj_t * pObj ) { return p->pMuxes && Abc_LitIsCompl(p->pMuxes[Gia_ObjId(p, pObj)]); } +static inline int Gia_ObjFaninC( Gia_Obj_t * pObj, int n ) { return n ? Gia_ObjFaninC1(pObj) : Gia_ObjFaninC0(pObj); } static inline Gia_Obj_t * Gia_ObjFanin0( Gia_Obj_t * pObj ) { return pObj - pObj->iDiff0; } static inline Gia_Obj_t * Gia_ObjFanin1( Gia_Obj_t * pObj ) { return pObj - pObj->iDiff1; } static inline Gia_Obj_t * Gia_ObjFanin2( Gia_Man_t * p, Gia_Obj_t * pObj ) { return p->pMuxes ? Gia_ManObj(p, Abc_Lit2Var(p->pMuxes[Gia_ObjId(p, pObj)])) : NULL; } +static inline Gia_Obj_t * Gia_ObjFanin( Gia_Obj_t * pObj, int n ) { return n ? Gia_ObjFanin1(pObj) : Gia_ObjFanin0(pObj); } static inline Gia_Obj_t * Gia_ObjChild0( Gia_Obj_t * pObj ) { return Gia_NotCond( Gia_ObjFanin0(pObj), Gia_ObjFaninC0(pObj) ); } static inline Gia_Obj_t * Gia_ObjChild1( Gia_Obj_t * pObj ) { return Gia_NotCond( Gia_ObjFanin1(pObj), Gia_ObjFaninC1(pObj) ); } static inline Gia_Obj_t * Gia_ObjChild2( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_NotCond( Gia_ObjFanin2(p, pObj), Gia_ObjFaninC2(p, pObj) ); } static inline int Gia_ObjFaninId0( Gia_Obj_t * pObj, int ObjId ) { return ObjId - pObj->iDiff0; } static inline int Gia_ObjFaninId1( Gia_Obj_t * pObj, int ObjId ) { return ObjId - pObj->iDiff1; } static inline int Gia_ObjFaninId2( Gia_Man_t * p, int ObjId ) { return (p->pMuxes && p->pMuxes[ObjId]) ? Abc_Lit2Var(p->pMuxes[ObjId]) : -1; } +static inline int Gia_ObjFaninId( Gia_Obj_t * pObj, int ObjId, int n ){ return n ? Gia_ObjFaninId1(pObj, ObjId) : Gia_ObjFaninId0(pObj, ObjId); } static inline int Gia_ObjFaninId0p( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjFaninId0( pObj, Gia_ObjId(p, pObj) ); } static inline int Gia_ObjFaninId1p( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjFaninId1( pObj, Gia_ObjId(p, pObj) ); } static inline int Gia_ObjFaninId2p( Gia_Man_t * p, Gia_Obj_t * pObj ) { return (p->pMuxes && p->pMuxes[Gia_ObjId(p, pObj)]) ? Abc_Lit2Var(p->pMuxes[Gia_ObjId(p, pObj)]) : -1; } +static inline int Gia_ObjFaninIdp( Gia_Man_t * p, Gia_Obj_t * pObj, int n){ return n ? Gia_ObjFaninId1p(p, pObj) : Gia_ObjFaninId0p(p, pObj); } 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; } @@ -532,6 +553,7 @@ static inline void Gia_ObjFlipFaninC0( Gia_Obj_t * pObj ) { static inline int Gia_ObjFaninNum( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsMux(p, pObj) ) return 3; if ( Gia_ObjIsAnd(pObj) ) return 2; if ( Gia_ObjIsCo(pObj) ) return 1; return 0; } static inline int Gia_ObjWhatFanin( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanin ) { if ( Gia_ObjFanin0(pObj) == pFanin ) return 0; if ( Gia_ObjFanin1(pObj) == pFanin ) return 1; if ( Gia_ObjFanin2(p, pObj) == pFanin ) return 2; assert(0); return -1; } +static inline int Gia_ManCoDriverId( Gia_Man_t * p, int iCoIndex ) { return Gia_ObjFaninId0p(p, Gia_ManCo(p, iCoIndex)); } static inline int Gia_ManPoIsConst( Gia_Man_t * p, int iPoIndex ) { return Gia_ObjFaninId0p(p, Gia_ManPo(p, iPoIndex)) == 0; } static inline int Gia_ManPoIsConst0( Gia_Man_t * p, int iPoIndex ) { return Gia_ManIsConst0Lit( Gia_ObjFaninLit0p(p, Gia_ManPo(p, iPoIndex)) ); } static inline int Gia_ManPoIsConst1( Gia_Man_t * p, int iPoIndex ) { return Gia_ManIsConst1Lit( Gia_ObjFaninLit0p(p, Gia_ManPo(p, iPoIndex)) ); } @@ -564,6 +586,7 @@ static inline int Gia_ObjPhaseRealLit( Gia_Man_t * p, int iLit ) { static inline int Gia_ObjLevelId( Gia_Man_t * p, int Id ) { return Vec_IntGetEntry(p->vLevels, Id); } static inline int Gia_ObjLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjLevelId( p, Gia_ObjId(p,pObj) ); } +static inline void Gia_ObjUpdateLevelId( Gia_Man_t * p, int Id, int l ) { Vec_IntSetEntry(p->vLevels, Id, Abc_MaxInt(Vec_IntEntry(p->vLevels, Id), l)); } static inline void Gia_ObjSetLevelId( Gia_Man_t * p, int Id, int l ) { Vec_IntSetEntry(p->vLevels, Id, l); } static inline void Gia_ObjSetLevel( Gia_Man_t * p, Gia_Obj_t * pObj, int l ) { Gia_ObjSetLevelId( p, Gia_ObjId(p,pObj), l ); } static inline void Gia_ObjSetCoLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsCo(pObj) ); Gia_ObjSetLevel( p, pObj, Gia_ObjLevel(p,Gia_ObjFanin0(pObj)) ); } @@ -604,9 +627,14 @@ static inline void Gia_ObjSetTravIdCurrent( Gia_Man_t * p, Gia_Obj_t * p static inline void Gia_ObjSetTravIdPrevious( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjId(p, pObj) < p->nTravIdsAlloc ); p->pTravIds[Gia_ObjId(p, pObj)] = p->nTravIds - 1; } static inline int Gia_ObjIsTravIdCurrent( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjId(p, pObj) < p->nTravIdsAlloc ); return (p->pTravIds[Gia_ObjId(p, pObj)] == p->nTravIds); } static inline int Gia_ObjIsTravIdPrevious( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjId(p, pObj) < p->nTravIdsAlloc ); return (p->pTravIds[Gia_ObjId(p, pObj)] == p->nTravIds - 1); } +static inline int Gia_ObjUpdateTravIdCurrent( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 1; Gia_ObjSetTravIdCurrent(p, pObj); return 0; } +static inline int Gia_ObjUpdateTravIdPrevious( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsTravIdPrevious(p, pObj) ) return 1; Gia_ObjSetTravIdPrevious(p, pObj); return 0; } static inline void Gia_ObjSetTravIdCurrentId( Gia_Man_t * p, int Id ) { assert( Id < p->nTravIdsAlloc ); p->pTravIds[Id] = p->nTravIds; } +static inline void Gia_ObjSetTravIdPreviousId( Gia_Man_t * p, int Id ) { assert( Id < p->nTravIdsAlloc ); p->pTravIds[Id] = p->nTravIds - 1; } static inline int Gia_ObjIsTravIdCurrentId( Gia_Man_t * p, int Id ) { assert( Id < p->nTravIdsAlloc ); return (p->pTravIds[Id] == p->nTravIds); } static inline int Gia_ObjIsTravIdPreviousId( Gia_Man_t * p, int Id ) { assert( Id < p->nTravIdsAlloc ); return (p->pTravIds[Id] == p->nTravIds - 1); } +static inline int Gia_ObjUpdateTravIdCurrentId( Gia_Man_t * p, int Id ) { if ( Gia_ObjIsTravIdCurrentId(p, Id) ) return 1; Gia_ObjSetTravIdCurrentId(p, Id); return 0; } +static inline int Gia_ObjUpdateTravIdPreviousId( Gia_Man_t * p, int Id ) { if ( Gia_ObjIsTravIdPreviousId(p, Id) ) return 1; Gia_ObjSetTravIdPreviousId(p, Id); return 0; } static inline void Gia_ManTimeClean( Gia_Man_t * p ) { int i; assert( p->vTiming != NULL ); Vec_FltFill(p->vTiming, 3*Gia_ManObjNum(p), 0); for ( i = 0; i < Gia_ManObjNum(p); i++ ) Vec_FltWriteEntry( p->vTiming, 3*i+1, (float)(ABC_INFINITY) ); } static inline void Gia_ManTimeStart( Gia_Man_t * p ) { assert( p->vTiming == NULL ); p->vTiming = Vec_FltAlloc(0); Gia_ManTimeClean( p ); } @@ -675,17 +703,17 @@ static inline int Gia_ManAppendAnd( Gia_Man_t * p, int iLit0, int iLit1 ) assert( p->fGiaSimple || Abc_Lit2Var(iLit0) != Abc_Lit2Var(iLit1) ); if ( iLit0 < iLit1 ) { - pObj->iDiff0 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); - pObj->fCompl0 = Abc_LitIsCompl(iLit0); - pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1); - pObj->fCompl1 = Abc_LitIsCompl(iLit1); + pObj->iDiff0 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0)); + pObj->fCompl0 = (unsigned)(Abc_LitIsCompl(iLit0)); + pObj->iDiff1 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1)); + pObj->fCompl1 = (unsigned)(Abc_LitIsCompl(iLit1)); } else { - pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); - pObj->fCompl1 = Abc_LitIsCompl(iLit0); - pObj->iDiff0 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1); - pObj->fCompl0 = Abc_LitIsCompl(iLit1); + pObj->iDiff1 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0)); + pObj->fCompl1 = (unsigned)(Abc_LitIsCompl(iLit0)); + pObj->iDiff0 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1)); + pObj->fCompl0 = (unsigned)(Abc_LitIsCompl(iLit1)); } if ( p->pFanData ) { @@ -717,21 +745,21 @@ static inline int Gia_ManAppendXorReal( Gia_Man_t * p, int iLit0, int iLit1 ) assert( iLit0 >= 0 && Abc_Lit2Var(iLit0) < Gia_ManObjNum(p) ); assert( iLit1 >= 0 && Abc_Lit2Var(iLit1) < Gia_ManObjNum(p) ); assert( Abc_Lit2Var(iLit0) != Abc_Lit2Var(iLit1) ); - assert( !Abc_LitIsCompl(iLit0) ); - assert( !Abc_LitIsCompl(iLit1) ); + //assert( !Abc_LitIsCompl(iLit0) ); + //assert( !Abc_LitIsCompl(iLit1) ); if ( Abc_Lit2Var(iLit0) > Abc_Lit2Var(iLit1) ) { - pObj->iDiff0 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); - pObj->fCompl0 = Abc_LitIsCompl(iLit0); - pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1); - pObj->fCompl1 = Abc_LitIsCompl(iLit1); + pObj->iDiff0 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0)); + pObj->fCompl0 = (unsigned)(Abc_LitIsCompl(iLit0)); + pObj->iDiff1 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1)); + pObj->fCompl1 = (unsigned)(Abc_LitIsCompl(iLit1)); } else { - pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); - pObj->fCompl1 = Abc_LitIsCompl(iLit0); - pObj->iDiff0 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1); - pObj->fCompl0 = Abc_LitIsCompl(iLit1); + pObj->iDiff1 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0)); + pObj->fCompl1 = (unsigned)(Abc_LitIsCompl(iLit0)); + pObj->iDiff0 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1)); + pObj->fCompl0 = (unsigned)(Abc_LitIsCompl(iLit1)); } p->nXors++; return Gia_ObjId( p, pObj ) << 1; @@ -749,18 +777,18 @@ static inline int Gia_ManAppendMuxReal( Gia_Man_t * p, int iLitC, int iLit1, int assert( !Vec_IntSize(&p->vHTable) || !Abc_LitIsCompl(iLit1) ); if ( Abc_Lit2Var(iLit0) < Abc_Lit2Var(iLit1) ) { - pObj->iDiff0 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); - pObj->fCompl0 = Abc_LitIsCompl(iLit0); - pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1); - pObj->fCompl1 = Abc_LitIsCompl(iLit1); + pObj->iDiff0 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0)); + pObj->fCompl0 = (unsigned)(Abc_LitIsCompl(iLit0)); + pObj->iDiff1 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1)); + pObj->fCompl1 = (unsigned)(Abc_LitIsCompl(iLit1)); p->pMuxes[Gia_ObjId(p, pObj)] = iLitC; } else { - pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); - pObj->fCompl1 = Abc_LitIsCompl(iLit0); - pObj->iDiff0 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1); - pObj->fCompl0 = Abc_LitIsCompl(iLit1); + pObj->iDiff1 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0)); + pObj->fCompl1 = (unsigned)(Abc_LitIsCompl(iLit0)); + pObj->iDiff0 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1)); + pObj->fCompl0 = (unsigned)(Abc_LitIsCompl(iLit1)); p->pMuxes[Gia_ObjId(p, pObj)] = Abc_LitNot(iLitC); } p->nMuxes++; @@ -849,6 +877,22 @@ static inline int Gia_ManAppendXor2( Gia_Man_t * p, int iLit0, int iLit1 ) return Gia_ManAppendMux2( p, iLit0, Abc_LitNot(iLit1), iLit1 ); } +static inline int Gia_ManAppendXorReal2( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + if ( !p->fGiaSimple ) + { + if ( iLit0 < 2 ) + return iLit0 ? Abc_LitNot(iLit1) : iLit1; + if ( iLit1 < 2 ) + return iLit1 ? Abc_LitNot(iLit0) : iLit0; + if ( iLit0 == iLit1 ) + return 0; + if ( iLit0 == Abc_LitNot(iLit1) ) + return 1; + } + return Gia_ManAppendXorReal( p, iLit0, iLit1 ); +} + static inline void Gia_ManPatchCoDriver( Gia_Man_t * p, int iCoIndex, int iLit0 ) { Gia_Obj_t * pObjCo = Gia_ManCo( p, iCoIndex ); @@ -1044,9 +1088,11 @@ static inline void Gia_ClassUndoPair( Gia_Man_t * p, int i ) { a #define Gia_ManForEachClassReverse( p, i ) \ for ( i = Gia_ManObjNum(p) - 1; i > 0; i-- ) if ( !Gia_ObjIsHead(p, i) ) {} else #define Gia_ClassForEachObj( p, i, iObj ) \ - for ( assert(Gia_ObjIsHead(p, i)), iObj = i; iObj > 0; iObj = Gia_ObjNext(p, iObj) ) + for ( assert(Gia_ObjIsHead(p, i) && i), iObj = i; iObj > 0; iObj = Gia_ObjNext(p, iObj) ) #define Gia_ClassForEachObj1( p, i, iObj ) \ for ( assert(Gia_ObjIsHead(p, i)), iObj = Gia_ObjNext(p, i); iObj > 0; iObj = Gia_ObjNext(p, iObj) ) +#define Gia_ClassForEachObjStart( p, i, iObj, Start ) \ + for ( assert(Gia_ObjIsHead(p, i)), iObj = Gia_ObjNext(p, Start); iObj > 0; iObj = Gia_ObjNext(p, iObj) ) static inline int Gia_ObjFoffsetId( Gia_Man_t * p, int Id ) { return Vec_IntEntry( p->vFanout, Id ); } @@ -1059,10 +1105,12 @@ static inline Gia_Obj_t * Gia_ObjFanout( Gia_Man_t * p, Gia_Obj_t * pObj, int i static inline void Gia_ObjSetFanout( Gia_Man_t * p, Gia_Obj_t * pObj, int i, Gia_Obj_t * pFan ) { Vec_IntWriteEntry( p->vFanout, Gia_ObjFoffset(p, pObj) + i, Gia_ObjId(p, pFan) ); } static inline void Gia_ObjSetFanoutInt( Gia_Man_t * p, Gia_Obj_t * pObj, int i, int x ) { Vec_IntWriteEntry( p->vFanout, Gia_ObjFoffset(p, pObj) + i, x ); } -#define Gia_ObjForEachFanoutStatic( p, pObj, pFanout, i ) \ - for ( i = 0; (i < Gia_ObjFanoutNum(p, pObj)) && (((pFanout) = Gia_ObjFanout(p, pObj, i)), 1); i++ ) -#define Gia_ObjForEachFanoutStaticId( p, Id, FanId, i ) \ - for ( i = 0; (i < Gia_ObjFanoutNumId(p, Id)) && (((FanId) = Gia_ObjFanoutId(p, Id, i)), 1); i++ ) +#define Gia_ObjForEachFanoutStatic( p, pObj, pFanout, i ) \ + for ( i = 0; (i < Gia_ObjFanoutNum(p, pObj)) && (((pFanout) = Gia_ObjFanout(p, pObj, i)), 1); i++ ) +#define Gia_ObjForEachFanoutStaticId( p, Id, FanId, i ) \ + for ( i = 0; (i < Gia_ObjFanoutNumId(p, Id)) && ((FanId = Gia_ObjFanoutId(p, Id, i)), 1); i++ ) +#define Gia_ObjForEachFanoutStaticIndex( p, Id, FanId, i, Index ) \ + for ( i = 0; (i < Gia_ObjFanoutNumId(p, Id)) && (Index = Vec_IntEntry(p->vFanout, Id)+i) && ((FanId = Vec_IntEntry(p->vFanout, Index)), 1); i++ ) static inline int Gia_ManHasMapping( Gia_Man_t * p ) { return p->vMapping != NULL; } static inline int Gia_ObjIsLut( Gia_Man_t * p, int Id ) { return Vec_IntEntry(p->vMapping, Id) != 0; } @@ -1095,6 +1143,8 @@ static inline int Gia_ObjCellId( Gia_Man_t * p, int iLit ) { re for ( i = Gia_ManObjNum(p) - 1; i > 0; i-- ) if ( !Gia_ObjIsLut(p, i) ) {} else #define Gia_LutForEachFanin( p, i, iFan, k ) \ for ( k = 0; k < Gia_ObjLutSize(p,i) && ((iFan = Gia_ObjLutFanins(p,i)[k]),1); k++ ) +#define Gia_LutForEachFaninIndex( p, i, iFan, k, Index ) \ + for ( k = 0; k < Gia_ObjLutSize(p,i) && (Index = Vec_IntEntry(p->vMapping, i)+1+k) && ((iFan = Vec_IntEntry(p->vMapping, Index)),1); k++ ) #define Gia_LutForEachFaninObj( p, i, pFanin, k ) \ for ( k = 0; k < Gia_ObjLutSize(p,i) && ((pFanin = Gia_ManObj(p, Gia_ObjLutFanins(p,i)[k])),1); k++ ) @@ -1126,7 +1176,13 @@ static inline int Gia_ObjCellId( Gia_Man_t * p, int iLit ) { re for ( i = 1; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ ) #define Gia_ManForEachObjVec( vVec, p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) -#define Gia_ManForEachObjVecReverse( vVec, p, pObj, i ) \ +#define Gia_ManForEachObjVecStart( vVec, p, pObj, i, Start ) \ + for ( i = Start; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) +#define Gia_ManForEachObjVecStop( vVec, p, pObj, i, Stop ) \ + for ( i = 0; (i < Stop) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) +#define Gia_ManForEachObjVecStartStop( vVec, p, pObj, i, Start, Stop ) \ + for ( i = Start; (i < Stop) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) +#define Gia_ManForEachObjVecReverse( vVec, p, pObj, i ) \ for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i-- ) #define Gia_ManForEachObjVecLit( vVec, p, pObj, fCompl, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManObj(p, Abc_Lit2Var(Vec_IntEntry(vVec,i)))) && (((fCompl) = Abc_LitIsCompl(Vec_IntEntry(vVec,i))),1); i++ ) @@ -1182,6 +1238,8 @@ static inline int Gia_ObjCellId( Gia_Man_t * p, int iLit ) { re for ( i = 0; (i < Gia_ManRegNum(p)) && ((pObj) = Gia_ManCo(p, Gia_ManPoNum(p)+i)); i++ ) #define Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) \ 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++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// @@ -1191,7 +1249,7 @@ static inline int Gia_ObjCellId( Gia_Man_t * p, int iLit ) { re extern int Gia_FileSize( char * pFileName ); extern Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSimple, int fSkipStrash, int fCheck ); extern Gia_Man_t * Gia_AigerRead( char * pFileName, int fGiaSimple, int fSkipStrash, int fCheck ); -extern void Gia_AigerWrite( Gia_Man_t * p, char * pFileName, int fWriteSymbols, int fCompact ); +extern void Gia_AigerWrite( Gia_Man_t * p, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine ); extern void Gia_DumpAiger( Gia_Man_t * p, char * pFilePrefix, int iFileNum, int nFileNumDigits ); extern Vec_Str_t * Gia_AigerWriteIntoMemoryStr( Gia_Man_t * p ); extern Vec_Str_t * Gia_AigerWriteIntoMemoryStrPart( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs ); @@ -1222,7 +1280,7 @@ extern Cbs_Man_t * Cbs_ManAlloc( Gia_Man_t * pGia ); extern void Cbs_ManStop( Cbs_Man_t * p ); extern int Cbs_ManSolve( Cbs_Man_t * p, Gia_Obj_t * pObj ); extern int Cbs_ManSolve2( Cbs_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ); -extern Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ); +extern Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int f0Proved, int fVerbose ); extern void Cbs_ManSetConflictNum( Cbs_Man_t * p, int Num ); extern Vec_Int_t * Cbs_ReadModel( Cbs_Man_t * p ); /*=== giaCTas.c ============================================================*/ @@ -1232,14 +1290,21 @@ extern void Gia_ManPrintFanio( Gia_Man_t * pGia, int nNodes ); extern Gia_Man_t * Gia_ManDupCof( Gia_Man_t * p, int iVar ); extern Gia_Man_t * Gia_ManDupCofAllInt( Gia_Man_t * p, Vec_Int_t * vSigs, int fVerbose ); extern Gia_Man_t * Gia_ManDupCofAll( Gia_Man_t * p, int nFanLim, int fVerbose ); +/*=== giaDecs.c ============================================================*/ +extern int Gia_ResubVarNum( Vec_Int_t * vResub ); +extern word Gia_ResubToTruth6( Vec_Int_t * vResub ); +extern int Gia_ManEvalSolutionOne( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vSet, int nWords, int fVerbose ); +extern Vec_Int_t * Gia_ManDeriveSolutionOne( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vSet, int nWords, int Type ); /*=== giaDfs.c ============================================================*/ extern void Gia_ManCollectCis( Gia_Man_t * p, int * pNodes, int nNodes, Vec_Int_t * vSupp ); extern void Gia_ManCollectAnds_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vNodes ); extern void Gia_ManCollectAnds( Gia_Man_t * p, int * pNodes, int nNodes, Vec_Int_t * vNodes, Vec_Int_t * vLeaves ); +extern Vec_Int_t * Gia_ManCollectAndsAll( Gia_Man_t * p ); extern Vec_Int_t * Gia_ManCollectNodesCis( Gia_Man_t * p, int * pNodes, int nNodes ); extern int Gia_ManSuppSize( Gia_Man_t * p, int * pNodes, int nNodes ); extern int Gia_ManConeSize( Gia_Man_t * p, int * pNodes, int nNodes ); extern Vec_Vec_t * Gia_ManLevelize( Gia_Man_t * p ); +extern Vec_Wec_t * Gia_ManLevelizeR( Gia_Man_t * p ); extern Vec_Int_t * Gia_ManOrderReverse( Gia_Man_t * p ); extern void Gia_ManCollectTfi( Gia_Man_t * p, Vec_Int_t * vRoots, Vec_Int_t * vNodes ); extern void Gia_ManCollectTfo( Gia_Man_t * p, Vec_Int_t * vRoots, Vec_Int_t * vNodes ); @@ -1248,7 +1313,7 @@ extern void Gia_ManDupRemapLiterals( Vec_Int_t * vLits, Gia_Man_t extern void Gia_ManDupRemapEquiv( Gia_Man_t * pNew, Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupOrderDfs( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupOrderDfsChoices( Gia_Man_t * p ); -extern Gia_Man_t * Gia_ManDupOrderDfsReverse( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupOrderDfsReverse( Gia_Man_t * p, int fRevFans, int fRevOuts ); extern Gia_Man_t * Gia_ManDupOutputGroup( Gia_Man_t * p, int iOutStart, int iOutStop ); extern Gia_Man_t * Gia_ManDupOutputVec( Gia_Man_t * p, Vec_Int_t * vOutPres ); extern Gia_Man_t * Gia_ManDupSelectedOutputs( Gia_Man_t * p, Vec_Int_t * vOutsLeft ); @@ -1257,6 +1322,8 @@ extern Gia_Man_t * Gia_ManDupLastPis( Gia_Man_t * p, int nLastPis ); extern Gia_Man_t * Gia_ManDupFlip( Gia_Man_t * p, int * pInitState ); extern Gia_Man_t * Gia_ManDupCycled( Gia_Man_t * pAig, Abc_Cex_t * pCex, int nFrames ); extern Gia_Man_t * Gia_ManDup( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupNoBuf( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupMap( Gia_Man_t * p, Vec_Int_t * vMap ); extern Gia_Man_t * Gia_ManDup2( Gia_Man_t * p1, Gia_Man_t * p2 ); extern Gia_Man_t * Gia_ManDupWithAttributes( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupRemovePis( Gia_Man_t * p, int nRemPis ); @@ -1273,6 +1340,8 @@ extern Gia_Man_t * Gia_ManDupFlopClass( Gia_Man_t * p, int iClass ); extern Gia_Man_t * Gia_ManDupMarked( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupTimes( Gia_Man_t * p, int nTimes ); extern Gia_Man_t * Gia_ManDupDfs( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupDfsOnePo( Gia_Man_t * p, int iPo ); +extern Gia_Man_t * Gia_ManDupDfsRehash( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupCofactorVar( Gia_Man_t * p, int iVar, int Value ); extern Gia_Man_t * Gia_ManDupCofactorObj( Gia_Man_t * p, int iObj, int Value ); extern Gia_Man_t * Gia_ManDupMux( int iVar, Gia_Man_t * pCof1, Gia_Man_t * pCof0 ); @@ -1294,8 +1363,9 @@ extern Gia_Man_t * Gia_ManPermuteInputs( Gia_Man_t * p, int nPpis, int n extern Gia_Man_t * Gia_ManDupDfsClasses( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupTopAnd( Gia_Man_t * p, int fVerbose ); extern Gia_Man_t * Gia_ManMiter( Gia_Man_t * pAig0, Gia_Man_t * pAig1, int nInsDup, int fDualOut, int fSeq, int fImplic, int fVerbose ); +extern Gia_Man_t * Gia_ManMiterInverse( Gia_Man_t * pBot, Gia_Man_t * pTop, int fDualOut, int fVerbose ); extern Gia_Man_t * Gia_ManDupAndOr( Gia_Man_t * p, int nOuts, int fUseOr, int fCompl ); -extern Gia_Man_t * Gia_ManDupZeroUndc( Gia_Man_t * p, char * pInit, int fGiaSimple, int fVerbose ); +extern Gia_Man_t * Gia_ManDupZeroUndc( Gia_Man_t * p, char * pInit, int nNewPis, int fGiaSimple, int fVerbose ); extern Gia_Man_t * Gia_ManMiter2( Gia_Man_t * p, char * pInit, int fVerbose ); extern Gia_Man_t * Gia_ManTransformMiter( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManTransformMiter2( Gia_Man_t * p ); @@ -1315,6 +1385,7 @@ extern Gia_Man_t * Gia_ManDupDemiter( Gia_Man_t * p, int fVerbose ); extern Gia_Man_t * Gia_ManDemiterToDual( Gia_Man_t * p ); extern int Gia_ManDemiterDual( Gia_Man_t * p, Gia_Man_t ** pp0, Gia_Man_t ** pp1 ); extern int Gia_ManDemiterTwoWords( Gia_Man_t * p, Gia_Man_t ** pp0, Gia_Man_t ** pp1 ); +extern void Gia_ManProdAdderGen( int nArgA, int nArgB, int Seed, int fSigned, int fCla ); /*=== giaEdge.c ==========================================================*/ extern void Gia_ManEdgeFromArray( Gia_Man_t * p, Vec_Int_t * vArray ); extern Vec_Int_t * Gia_ManEdgeToArray( Gia_Man_t * p ); @@ -1372,6 +1443,7 @@ extern void Gia_ManFanoutStart( Gia_Man_t * p ); extern void Gia_ManFanoutStop( Gia_Man_t * p ); extern void Gia_ManStaticFanoutStart( Gia_Man_t * p ); extern void Gia_ManStaticFanoutStop( Gia_Man_t * p ); +extern void Gia_ManStaticMappingFanoutStart( Gia_Man_t * p, Vec_Int_t ** pvIndex ); /*=== giaForce.c =========================================================*/ extern void For_ManExperiment( Gia_Man_t * pGia, int nIters, int fClustered, int fVerbose ); /*=== giaFrames.c =========================================================*/ @@ -1407,6 +1479,7 @@ extern int Gia_ManHashLookupInt( Gia_Man_t * p, int iLit0, int i extern int Gia_ManHashLookup( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 ); extern int Gia_ManHashAndMulti( Gia_Man_t * p, Vec_Int_t * vLits ); extern int Gia_ManHashAndMulti2( Gia_Man_t * p, Vec_Int_t * vLits ); +extern int Gia_ManHashDualMiter( Gia_Man_t * p, Vec_Int_t * vOuts ); /*=== giaIf.c ===========================================================*/ extern void Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile ); extern void Gia_ManPrintPackingStats( Gia_Man_t * p ); @@ -1454,6 +1527,7 @@ extern void Gia_ManPrintStatsMiter( Gia_Man_t * p, int fVerbose ) extern void Gia_ManSetRegNum( Gia_Man_t * p, int nRegs ); extern void Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew ); extern void Gia_ManPrintNpnClasses( Gia_Man_t * p ); +extern void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ); /*=== giaMem.c ===========================================================*/ extern Gia_MmFixed_t * Gia_MmFixedStart( int nEntrySize, int nEntriesMax ); extern void Gia_MmFixedStop( Gia_MmFixed_t * p, int fVerbose ); @@ -1477,15 +1551,18 @@ extern void Mf_ManSetDefaultPars( Jf_Par_t * pPars ); extern Gia_Man_t * Mf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ); extern void * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fMapping, int fVerbose ); /*=== giaMini.c ===========================================================*/ -extern Gia_Man_t * Gia_ManReadMiniAig( char * pFileName ); +extern Gia_Man_t * Gia_ManReadMiniAig( char * pFileName, int fGiaSimple ); extern void Gia_ManWriteMiniAig( Gia_Man_t * pGia, char * pFileName ); extern Gia_Man_t * Gia_ManReadMiniLut( char * pFileName ); extern void Gia_ManWriteMiniLut( Gia_Man_t * pGia, char * pFileName ); +/*=== giaMinLut.c ===========================================================*/ +extern word * Gia_ManCountFraction( Gia_Man_t * p, Vec_Wrd_t * vSimI, Vec_Int_t * vSupp, int Thresh, int fVerbose, int * pCare ); +extern Vec_Int_t * Gia_ManCollectSuppNew( Gia_Man_t * p, int iOut, int nOuts ); /*=== giaMuxes.c ===========================================================*/ extern void Gia_ManCountMuxXor( Gia_Man_t * p, int * pnMuxes, int * pnXors ); extern void Gia_ManPrintMuxStats( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupMuxes( Gia_Man_t * p, int Limit ); -extern Gia_Man_t * Gia_ManDupNoMuxes( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupNoMuxes( Gia_Man_t * p, int fSkipBufs ); /*=== giaPat.c ===========================================================*/ extern void Gia_SatVerifyPattern( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vCex, Vec_Int_t * vVisit ); /*=== giaRetime.c ===========================================================*/ @@ -1530,6 +1607,16 @@ extern void Gia_ManIncrSimStart( Gia_Man_t * p, int nWords, int n extern void Gia_ManIncrSimSet( Gia_Man_t * p, Vec_Int_t * vObjLits ); extern int Gia_ManIncrSimCheckOver( Gia_Man_t * p, int iLit0, int iLit1 ); extern int Gia_ManIncrSimCheckEqual( Gia_Man_t * p, int iLit0, int iLit1 ); +/*=== giaSimBase.c ============================================================*/ +extern Vec_Wrd_t * Gia_ManSimPatSim( Gia_Man_t * p ); +extern Vec_Wrd_t * Gia_ManSimPatSimOut( Gia_Man_t * pGia, Vec_Wrd_t * vSimsPi, int fOuts ); +extern void Gia_ManSim2ArrayOne( Vec_Wrd_t * vSimsPi, Vec_Int_t * vRes ); +extern Vec_Wec_t * Gia_ManSim2Array( Vec_Ptr_t * vSims ); +extern Vec_Wrd_t * Gia_ManArray2SimOne( Vec_Int_t * vRes ); +extern Vec_Ptr_t * Gia_ManArray2Sim( Vec_Wec_t * vRes ); +extern void Gia_ManPtrWrdDumpBin( char * pFileName, Vec_Ptr_t * p, int fVerbose ); +extern Vec_Ptr_t * Gia_ManPtrWrdReadBin( char * pFileName, int fVerbose ); +extern Vec_Str_t * Gia_ManComputeRange( Gia_Man_t * p ); /*=== giaSpeedup.c ============================================================*/ extern float Gia_ManDelayTraceLut( Gia_Man_t * p ); extern float Gia_ManDelayTraceLutPrint( Gia_Man_t * p, int fVerbose ); @@ -1641,6 +1728,7 @@ extern void Gia_ManSetPhase1( Gia_Man_t * p ); extern void Gia_ManCleanPhase( Gia_Man_t * p ); extern int Gia_ManCheckCoPhase( Gia_Man_t * p ); extern int Gia_ManLevelNum( Gia_Man_t * p ); +extern int Gia_ManLevelRNum( Gia_Man_t * p ); extern Vec_Int_t * Gia_ManGetCiLevels( Gia_Man_t * p ); extern int Gia_ManSetLevels( Gia_Man_t * p, Vec_Int_t * vCiLevels ); extern Vec_Int_t * Gia_ManReverseLevel( Gia_Man_t * p ); @@ -1655,7 +1743,9 @@ extern int Gia_ObjRecognizeExor( Gia_Obj_t * pObj, Gia_Obj_t ** extern Gia_Obj_t * Gia_ObjRecognizeMux( Gia_Obj_t * pNode, Gia_Obj_t ** ppNodeT, Gia_Obj_t ** ppNodeE ); extern int Gia_ObjRecognizeMuxLits( Gia_Man_t * p, Gia_Obj_t * pNode, int * iLitT, int * iLitE ); extern int Gia_NodeMffcSize( Gia_Man_t * p, Gia_Obj_t * pNode ); +extern int Gia_NodeMffcSizeMark( Gia_Man_t * p, Gia_Obj_t * pNode ); extern int Gia_NodeMffcSizeSupp( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp ); +extern int Gia_NodeMffcMapping( Gia_Man_t * p ); extern int Gia_ManHasDangling( Gia_Man_t * p ); extern int Gia_ManMarkDangling( Gia_Man_t * p ); extern Vec_Int_t * Gia_ManGetDangling( Gia_Man_t * p ); @@ -1674,6 +1764,18 @@ extern Vec_Int_t * Gia_ManSaveValue( Gia_Man_t * p ); extern void Gia_ManLoadValue( Gia_Man_t * p, Vec_Int_t * vValues ); extern Vec_Int_t * Gia_ManFirstFanouts( Gia_Man_t * p ); extern int Gia_ManCheckSuppOverlap( Gia_Man_t * p, int iNode1, int iNode2 ); +extern int Gia_ManCountPisWithFanout( Gia_Man_t * p ); +extern int Gia_ManCountPosWithNonZeroDrivers( Gia_Man_t * p ); +extern void Gia_ManUpdateCopy( Vec_Int_t * vCopy, Gia_Man_t * p ); +extern Vec_Int_t * Gia_ManComputeDistance( Gia_Man_t * p, int iObj, Vec_Int_t * vObjs, int fVerbose ); + +/*=== giaTtopt.cpp ===========================================================*/ +extern Gia_Man_t * Gia_ManTtopt( Gia_Man_t * p, int nIns, int nOuts, int nRounds ); +extern Gia_Man_t * Gia_ManTtoptCare( Gia_Man_t * p, int nIns, int nOuts, int nRounds, char * pFileName, int nRarity ); + +/*=== giaTransduction.cpp ===========================================================*/ +extern Gia_Man_t * Gia_ManTransductionBdd( Gia_Man_t * pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t * pExdc, int fNewLine, int nVerbose ); +extern Gia_Man_t * Gia_ManTransductionTt( Gia_Man_t * pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t * pExdc, int fNewLine, int nVerbose ); /*=== giaCTas.c ===========================================================*/ typedef struct Tas_Man_t_ Tas_Man_t; @@ -1684,7 +1786,6 @@ extern void Tas_ManSatPrintStats( Tas_Man_t * p ); extern int Tas_ManSolve( Tas_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ); extern int Tas_ManSolveArray( Tas_Man_t * p, Vec_Ptr_t * vObjs ); - ABC_NAMESPACE_HEADER_END diff --git a/abc/src/aig/gia/giaAgi.c b/abc/src/aig/gia/giaAgi.c index 3acf75a65dc..2db087d5191 100644 --- a/abc/src/aig/gia/giaAgi.c +++ b/abc/src/aig/gia/giaAgi.c @@ -76,7 +76,7 @@ static inline int Agi_ObjIsRo( Agi_Man_t * p, int i ) { ret static inline int Agi_ObjIsPo( Agi_Man_t * p, int i ) { return (p->pObjs[i] & AGI_PI) == AGI_PO; } static inline int Agi_ObjIsRi( Agi_Man_t * p, int i ) { return (p->pObjs[i] & AGI_PI) == AGI_RI; } static inline int Agi_ObjIsCi( Agi_Man_t * p, int i ) { return (p->pObjs[i] & AGI_RO) == AGI_RO; } -static inline int Agi_ObjIsCo( Agi_Man_t * p, int i ) { return (p->pObjs[i] & AGI_RO) == AGI_PO; } +static inline int Agi_ObjIsCo( Agi_Man_t * p, int i ) { return (p->pObjs[i] & AGI_PO) == AGI_PO; } static inline int Agi_ObjIsNode( Agi_Man_t * p, int i ) { return p->pObjs[i] < AGI_C0; } static inline int Agi_ObjIsBuf( Agi_Man_t * p, int i ) { return Agi_ObjLit0(p, i) == Agi_ObjLit1(p, i); } static inline int Agi_ObjIsAnd( Agi_Man_t * p, int i ) { return Agi_ObjIsNode(p, i) && Agi_ObjLit0(p, i) < Agi_ObjLit1(p, i); } diff --git a/abc/src/aig/gia/giaAig.c b/abc/src/aig/gia/giaAig.c index dfd4a467be9..c764a099369 100644 --- a/abc/src/aig/gia/giaAig.c +++ b/abc/src/aig/gia/giaAig.c @@ -100,6 +100,41 @@ Gia_Man_t * Gia_ManFromAig( Aig_Man_t * p ) return pNew; } +/**Function************************************************************* + + Synopsis [Checks integrity of choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCheckChoices_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( !pObj || !Gia_ObjIsAnd(pObj) || pObj->fPhase ) + return; + pObj->fPhase = 1; + Gia_ManCheckChoices_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManCheckChoices_rec( p, Gia_ObjFanin1(pObj) ); + Gia_ManCheckChoices_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)) ); +} +void Gia_ManCheckChoices( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, fFound = 0; + Gia_ManCleanPhase( p ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManCheckChoices_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachAnd( p, pObj, i ) + if ( !pObj->fPhase ) + printf( "Object %d is dangling.\n", i ), fFound = 1; + if ( !fFound ) + printf( "There are no dangling objects.\n" ); + Gia_ManCleanPhase( p ); +} + /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order.] @@ -155,6 +190,7 @@ Gia_Man_t * Gia_ManFromAigChoices( Aig_Man_t * p ) Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) ); Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) ); //assert( Gia_ManObjNum(pNew) == Aig_ManObjNum(p) ); + //Gia_ManCheckChoices( pNew ); return pNew; } @@ -575,6 +611,27 @@ Gia_Man_t * Gia_ManCompress2( Gia_Man_t * p, int fUpdateLevel, int fVerbose ) SeeAlso [] ***********************************************************************/ +int Gia_ManTestChoices( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vPointed = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManForEachAnd( p, pObj, i ) + if ( Gia_ObjSibl(p, i) ) + Vec_IntWriteEntry( vPointed, Gia_ObjSibl(p, i), 1 ); + Gia_ManCreateRefs( p ); + Gia_ManForEachAnd( p, pObj, i ) + if ( Vec_IntEntry(vPointed, i) && Gia_ObjRefNumId(p, i) > 0 ) + { + printf( "Gia_ManCheckChoices: Member %d", i ); + printf( " of a choice node has %d fanouts.\n", Gia_ObjRefNumId(p, i) ); + ABC_FREE( p->pRefs ); + Vec_IntFree( vPointed ); + return 0; + } + ABC_FREE( p->pRefs ); + Vec_IntFree( vPointed ); + return 1; +} Gia_Man_t * Gia_ManPerformDch( Gia_Man_t * p, void * pPars ) { int fUseMapping = 0; @@ -592,6 +649,11 @@ Gia_Man_t * Gia_ManPerformDch( Gia_Man_t * p, void * pPars ) // pGia = Gia_ManFromAig( pNew ); pGia = Gia_ManFromAigChoices( pNew ); Aig_ManStop( pNew ); + if ( !p->pManTime && !Gia_ManTestChoices(pGia) ) + { + Gia_ManStop( pGia ); + pGia = Gia_ManDup( p ); + } Gia_ManTransferTiming( pGia, p ); return pGia; } diff --git a/abc/src/aig/gia/giaAiger.c b/abc/src/aig/gia/giaAiger.c index 97f40aea449..e3967e0edf5 100644 --- a/abc/src/aig/gia/giaAiger.c +++ b/abc/src/aig/gia/giaAiger.c @@ -176,6 +176,7 @@ Vec_Str_t * Gia_AigerWriteLiterals( Vec_Int_t * vLits ) Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSimple, int fSkipStrash, int fCheck ) { Gia_Man_t * pNew, * pTemp; + Vec_Ptr_t * vNamesIn = NULL, * vNamesOut = NULL, * vNamesRegIn = NULL, * vNamesRegOut = NULL, * vNamesNode = NULL; Vec_Int_t * vLits = NULL, * vPoTypes = NULL; Vec_Int_t * vNodes, * vDrivers, * vInits = NULL; int iObj, iNode0, iNode1, fHieOnly = 0; @@ -377,6 +378,101 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi pCur = pSymbols; if ( pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' ) { + int fReadNames = 1; + if ( fReadNames ) + { + int fError = 0; + while ( !fError && pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' ) + { + int iTerm; + char * pType = (char *)pCur; + char * pName = NULL; + // check terminal type + if ( *pCur != 'i' && *pCur != 'o' && *pCur != 'l' && *pCur != 'n' ) + { + fError = 1; + break; + } + // get terminal number + iTerm = atoi( (char *)++pCur ); while ( *pCur++ != ' ' ); + // skip spaces + while ( *pCur == ' ' ) + pCur++; + // skip till the end of line + for ( pName = (char *)pCur; *pCur && *pCur != '\n'; pCur++ ); + if ( *pCur == '\n' ) + *pCur = 0; + // save the name + if ( *pType == 'i' ) + { + if ( vNamesIn == NULL ) + vNamesIn = Vec_PtrAlloc( nInputs + nLatches ); + if ( Vec_PtrSize(vNamesIn) != iTerm ) + { + fError = 1; + break; + } + Vec_PtrPush( vNamesIn, Abc_UtilStrsav(pName) ); + } + else if ( *pType == 'o' ) + { + if ( vNamesOut == NULL ) + vNamesOut = Vec_PtrAlloc( nOutputs + nLatches ); + if ( Vec_PtrSize(vNamesOut) != iTerm ) + { + fError = 1; + break; + } + Vec_PtrPush( vNamesOut, Abc_UtilStrsav(pName) ); + } + else if ( *pType == 'l' ) + { + char Buffer[1000]; + assert( strlen(pName) < 995 ); + sprintf( Buffer, "%s_in", pName ); + if ( vNamesRegIn == NULL ) + vNamesRegIn = Vec_PtrAlloc( nLatches ); + if ( vNamesRegOut == NULL ) + vNamesRegOut = Vec_PtrAlloc( nLatches ); + if ( Vec_PtrSize(vNamesRegIn) != iTerm ) + { + fError = 1; + break; + } + Vec_PtrPush( vNamesRegIn, Abc_UtilStrsav(Buffer) ); + Vec_PtrPush( vNamesRegOut, Abc_UtilStrsav(pName) ); + } + else if ( *pType == 'n' ) + { + if ( Vec_IntSize(&pNew->vHTable) != 0 ) + { + printf( "Structural hashing should be disabled to read internal nodes names.\n" ); + fError = 1; + break; + } + if ( vNamesNode == NULL ) + vNamesNode = Vec_PtrStart( Gia_ManObjNum(pNew) ); + Vec_PtrWriteEntry( vNamesNode, iTerm, Abc_UtilStrsav(pName) ); + } + else + { + fError = 1; + break; + } + pCur++; + } + if ( fError ) + { + printf( "Error occurred when reading signal names. Signal names ignored.\n" ); + if ( vNamesIn ) Vec_PtrFreeFree( vNamesIn ), vNamesIn = NULL; + if ( vNamesOut ) Vec_PtrFreeFree( vNamesOut ), vNamesOut = NULL; + if ( vNamesRegIn ) Vec_PtrFreeFree( vNamesRegIn ), vNamesRegIn = NULL; + if ( vNamesRegOut ) Vec_PtrFreeFree( vNamesRegOut ), vNamesRegOut = NULL; + if ( vNamesNode ) Vec_PtrFreeFree( vNamesNode ), vNamesNode = NULL; + } + } + else + { int fBreakUsed = 0; unsigned char * pCurOld = pCur; pNew->vUserPiIds = Vec_IntStartFull( nInputs ); @@ -505,6 +601,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi } Vec_IntFree( vPoNames ); } + } } @@ -525,7 +622,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi { pCur++; vStr = Vec_StrStart( Gia_AigerReadInt(pCur) ); pCur += 4; - memcpy( Vec_StrArray(vStr), pCur, Vec_StrSize(vStr) ); + memcpy( Vec_StrArray(vStr), pCur, (size_t)Vec_StrSize(vStr) ); pCur += Vec_StrSize(vStr); pNew->pAigExtra = Gia_AigerReadFromMemory( Vec_StrArray(vStr), Vec_StrSize(vStr), 0, 0, 0 ); Vec_StrFree( vStr ); @@ -552,7 +649,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi pCur++; nInputs = Gia_AigerReadInt(pCur)/4; pCur += 4; pNew->vInArrs = Vec_FltStart( nInputs ); - memcpy( Vec_FltArray(pNew->vInArrs), pCur, 4*nInputs ); pCur += 4*nInputs; + memcpy( Vec_FltArray(pNew->vInArrs), pCur, (size_t)4*nInputs ); pCur += 4*nInputs; if ( fVerbose ) printf( "Finished reading extension \"i\".\n" ); } else if ( *pCur == 'o' ) @@ -560,7 +657,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi pCur++; nOutputs = Gia_AigerReadInt(pCur)/4; pCur += 4; pNew->vOutReqs = Vec_FltStart( nOutputs ); - memcpy( Vec_FltArray(pNew->vOutReqs), pCur, 4*nOutputs ); pCur += 4*nOutputs; + memcpy( Vec_FltArray(pNew->vOutReqs), pCur, (size_t)4*nOutputs ); pCur += 4*nOutputs; if ( fVerbose ) printf( "Finished reading extension \"o\".\n" ); } // read equivalence classes @@ -580,7 +677,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi pCur++; assert( Gia_AigerReadInt(pCur) == 4*Gia_ManRegNum(pNew) ); pCur += 4; pNew->vFlopClasses = Vec_IntStart( Gia_ManRegNum(pNew) ); - memcpy( Vec_IntArray(pNew->vFlopClasses), pCur, 4*Gia_ManRegNum(pNew) ); pCur += 4*Gia_ManRegNum(pNew); + memcpy( Vec_IntArray(pNew->vFlopClasses), pCur, (size_t)4*Gia_ManRegNum(pNew) ); pCur += 4*Gia_ManRegNum(pNew); if ( fVerbose ) printf( "Finished reading extension \"f\".\n" ); } // read gate classes @@ -589,7 +686,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi pCur++; assert( Gia_AigerReadInt(pCur) == 4*Gia_ManObjNum(pNew) ); pCur += 4; pNew->vGateClasses = Vec_IntStart( Gia_ManObjNum(pNew) ); - memcpy( Vec_IntArray(pNew->vGateClasses), pCur, 4*Gia_ManObjNum(pNew) ); pCur += 4*Gia_ManObjNum(pNew); + memcpy( Vec_IntArray(pNew->vGateClasses), pCur, (size_t)4*Gia_ManObjNum(pNew) ); pCur += 4*Gia_ManObjNum(pNew); if ( fVerbose ) printf( "Finished reading extension \"g\".\n" ); } // read hierarchy information @@ -597,7 +694,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi { pCur++; vStr = Vec_StrStart( Gia_AigerReadInt(pCur) ); pCur += 4; - memcpy( Vec_StrArray(vStr), pCur, Vec_StrSize(vStr) ); + memcpy( Vec_StrArray(vStr), pCur, (size_t)Vec_StrSize(vStr) ); pCur += Vec_StrSize(vStr); pNew->pManTime = Tim_ManLoad( vStr, 1 ); Vec_StrFree( vStr ); @@ -636,6 +733,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi pCur++; if ( (*pCur >= 'a' && *pCur <= 'z') || (*pCur >= 'A' && *pCur <= 'Z') || (*pCur >= '0' && *pCur <= '9') ) { + ABC_FREE( pNew->pName ); pNew->pName = Abc_UtilStrsav( (char *)pCur ); pCur += strlen(pNew->pName) + 1; } else @@ -653,7 +751,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi pCur++; pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; pPlacement = ABC_ALLOC( Gia_Plc_t, Gia_ManObjNum(pNew) ); - memcpy( pPlacement, pCur, 4*Gia_ManObjNum(pNew) ); pCur += 4*Gia_ManObjNum(pNew); + memcpy( pPlacement, pCur, (size_t)4*Gia_ManObjNum(pNew) ); pCur += 4*Gia_ManObjNum(pNew); assert( pCur == pCurTemp ); pNew->pPlacement = pPlacement; if ( fVerbose ) printf( "Finished reading extension \"p\".\n" ); @@ -696,7 +794,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi nSize = nSize - strlen(pNew->pCellStr) - 1; assert( nSize % 4 == 0 ); pNew->vConfigs = Vec_IntAlloc(nSize / 4); -// memcpy(Vec_IntArray(pNew->vConfigs), pCur, nSize); pCur += nSize; +// memcpy(Vec_IntArray(pNew->vConfigs), pCur, (size_t)nSize); pCur += nSize; for ( i = 0; i < nSize / 4; i++ ) Vec_IntPush( pNew->vConfigs, Gia_AigerReadInt(pCur) ), pCur += 4; assert( pCur == pCurTemp ); @@ -728,7 +826,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi pCur++; pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; pSwitching = ABC_ALLOC( unsigned char, Gia_ManObjNum(pNew) ); - memcpy( pSwitching, pCur, Gia_ManObjNum(pNew) ); pCur += Gia_ManObjNum(pNew); + memcpy( pSwitching, pCur, (size_t)Gia_ManObjNum(pNew) ); pCur += Gia_ManObjNum(pNew); assert( pCur == pCurTemp ); if ( fVerbose ) printf( "Finished reading extension \"s\".\n" ); } @@ -737,7 +835,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi { pCur++; vStr = Vec_StrStart( Gia_AigerReadInt(pCur) ); pCur += 4; - memcpy( Vec_StrArray(vStr), pCur, Vec_StrSize(vStr) ); pCur += Vec_StrSize(vStr); + memcpy( Vec_StrArray(vStr), pCur, (size_t)Vec_StrSize(vStr) ); pCur += Vec_StrSize(vStr); pNew->pManTime = Tim_ManLoad( vStr, 0 ); Vec_StrFree( vStr ); if ( fVerbose ) printf( "Finished reading extension \"t\".\n" ); @@ -747,7 +845,7 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi { pCur++; pNew->vObjClasses = Vec_IntStart( Gia_AigerReadInt(pCur)/4 ); pCur += 4; - memcpy( Vec_IntArray(pNew->vObjClasses), pCur, 4*Vec_IntSize(pNew->vObjClasses) ); + memcpy( Vec_IntArray(pNew->vObjClasses), pCur, (size_t)4*Vec_IntSize(pNew->vObjClasses) ); pCur += 4*Vec_IntSize(pNew->vObjClasses); if ( fVerbose ) printf( "Finished reading extension \"v\".\n" ); } @@ -794,19 +892,26 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi if ( !fGiaSimple && !fSkipStrash && Gia_ManHasDangling(pNew) ) { Tim_Man_t * pManTime; - Vec_Int_t * vFlopMap, * vGateMap, * vObjMap; - vFlopMap = pNew->vFlopClasses; pNew->vFlopClasses = NULL; - vGateMap = pNew->vGateClasses; pNew->vGateClasses = NULL; - vObjMap = pNew->vObjClasses; pNew->vObjClasses = NULL; - pManTime = (Tim_Man_t *)pNew->pManTime; pNew->pManTime = NULL; + Gia_Man_t * pAigExtra; + Vec_Int_t * vFlopMap, * vGateMap, * vObjMap, * vRegClasses, * vRegInits; + vRegClasses = pNew->vRegClasses; pNew->vRegClasses = NULL; + vRegInits = pNew->vRegInits; pNew->vRegInits = NULL; + vFlopMap = pNew->vFlopClasses; pNew->vFlopClasses = NULL; + vGateMap = pNew->vGateClasses; pNew->vGateClasses = NULL; + vObjMap = pNew->vObjClasses; pNew->vObjClasses = NULL; + pManTime = (Tim_Man_t *)pNew->pManTime; pNew->pManTime = NULL; + pAigExtra = pNew->pAigExtra; pNew->pAigExtra = NULL; pNew = Gia_ManCleanup( pTemp = pNew ); if ( (vGateMap || vObjMap) && (Gia_ManObjNum(pNew) < Gia_ManObjNum(pTemp)) ) printf( "Cleanup removed objects after reading. Old gate/object abstraction maps are invalid!\n" ); Gia_ManStop( pTemp ); + pNew->vRegClasses = vRegClasses; + pNew->vRegInits = vRegInits; pNew->vFlopClasses = vFlopMap; pNew->vGateClasses = vGateMap; pNew->vObjClasses = vObjMap; pNew->pManTime = pManTime; + pNew->pAigExtra = pAigExtra; } if ( fHieOnly ) @@ -848,9 +953,12 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi } } pInit[i] = 0; - pNew = Gia_ManDupZeroUndc( pTemp = pNew, pInit, fGiaSimple, 1 ); - pNew->nConstrs = pTemp->nConstrs; pTemp->nConstrs = 0; - Gia_ManStop( pTemp ); + if ( !fSkipStrash ) + { + pNew = Gia_ManDupZeroUndc( pTemp = pNew, pInit, 0, fGiaSimple, 1 ); + pNew->nConstrs = pTemp->nConstrs; pTemp->nConstrs = 0; + Gia_ManStop( pTemp ); + } ABC_FREE( pInit ); } Vec_IntFreeP( &vInits ); @@ -859,6 +967,39 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi Abc_Print( 0, "Structural hashing enabled while reading AIGER invalidated the mapping. Consider using \"&r -s\".\n" ); Vec_IntFreeP( &pNew->vMapping ); } + if ( vNamesIn && Gia_ManPiNum(pNew) != Vec_PtrSize(vNamesIn) ) + Abc_Print( 0, "The number of inputs does not match the number of input names.\n" ); + else if ( vNamesOut && Gia_ManPoNum(pNew) != Vec_PtrSize(vNamesOut) ) + Abc_Print( 0, "The number of output does not match the number of output names.\n" ); + else if ( vNamesRegOut && Gia_ManRegNum(pNew) != Vec_PtrSize(vNamesRegOut) ) + Abc_Print( 0, "The number of inputs does not match the number of flop names.\n" ); + else if ( vNamesIn && vNamesOut ) + { + pNew->vNamesIn = vNamesIn; vNamesIn = NULL; + pNew->vNamesOut = vNamesOut; vNamesOut = NULL; + if ( vNamesRegOut ) + { + Vec_PtrAppend( pNew->vNamesIn, vNamesRegOut ); + Vec_PtrClear( vNamesRegOut ); + Vec_PtrFree( vNamesRegOut ); + vNamesRegOut = NULL; + } + if ( vNamesRegIn ) + { + Vec_PtrAppend( pNew->vNamesOut, vNamesRegIn ); + Vec_PtrClear( vNamesRegIn ); + Vec_PtrFree( vNamesRegIn ); + vNamesRegIn = NULL; + } + } + if ( vNamesNode && Gia_ManObjNum(pNew) != Vec_PtrSize(vNamesNode) ) + Abc_Print( 0, "The size of the node name array does not match the number of objects. Names are not entered.\n" ); + else if ( vNamesNode ) + pNew->vNamesNode = vNamesNode, vNamesNode = NULL; + if ( vNamesIn ) Vec_PtrFreeFree( vNamesIn ); + if ( vNamesOut ) Vec_PtrFreeFree( vNamesOut ); + if ( vNamesRegIn ) Vec_PtrFreeFree( vNamesRegIn ); + if ( vNamesRegOut ) Vec_PtrFreeFree( vNamesRegOut ); return pNew; } @@ -1076,7 +1217,7 @@ Vec_Str_t * Gia_AigerWriteIntoMemoryStrPart( Gia_Man_t * p, Vec_Int_t * vCis, Ve SeeAlso [] ***********************************************************************/ -void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact ) +void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine ) { int fVerbose = XAIG_VERBOSE; FILE * pFile; @@ -1110,9 +1251,7 @@ void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int Gia_ManTransferMapping( p, pInit ); Gia_ManTransferPacking( p, pInit ); Gia_ManTransferTiming( p, pInit ); - p->vNamesIn = pInit->vNamesIn; pInit->vNamesIn = NULL; - p->vNamesOut = pInit->vNamesOut; pInit->vNamesOut = NULL; - p->nConstrs = pInit->nConstrs; pInit->nConstrs = 0; + p->nConstrs = pInit->nConstrs; } else p = pInit; @@ -1192,10 +1331,20 @@ void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int Gia_ManForEachPo( p, pObj, i ) fprintf( pFile, "o%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesOut, i) ); } + if ( p->vNamesNode && Vec_PtrSize(p->vNamesNode) != Gia_ManObjNum(p) ) + Abc_Print( 0, "The size of the node name array does not match the number of objects. Names are not written.\n" ); + else if ( p->vNamesNode ) + { + Gia_ManForEachAnd( p, pObj, i ) + if ( Vec_PtrEntry(p->vNamesNode, i) ) + fprintf( pFile, "n%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesNode, i) ); + } // write the comment -// fprintf( pFile, "c\n" ); - fprintf( pFile, "c" ); + if ( fWriteNewLine ) + fprintf( pFile, "c\n" ); + else + fprintf( pFile, "c" ); // write additional AIG if ( p->pAigExtra ) @@ -1406,14 +1555,14 @@ void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fprintf( pFile, "%c", '\0' ); } // write comments + if ( fWriteNewLine ) + fprintf( pFile, "c\n" ); fprintf( pFile, "\nThis file was produced by the GIA package in ABC on %s\n", Gia_TimeStamp() ); fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); fclose( pFile ); if ( p != pInit ) { - pInit->pManTime = p->pManTime; p->pManTime = NULL; - pInit->vNamesIn = p->vNamesIn; p->vNamesIn = NULL; - pInit->vNamesOut = p->vNamesOut; p->vNamesOut = NULL; + Gia_ManTransferTiming( pInit, p ); Gia_ManStop( p ); } } @@ -1433,7 +1582,7 @@ void Gia_DumpAiger( Gia_Man_t * p, char * pFilePrefix, int iFileNum, int nFileNu { char Buffer[100]; sprintf( Buffer, "%s%0*d.aig", pFilePrefix, nFileNumDigits, iFileNum ); - Gia_AigerWrite( p, Buffer, 0, 0 ); + Gia_AigerWrite( p, Buffer, 0, 0, 0 ); } /**Function************************************************************* @@ -1470,6 +1619,148 @@ void Gia_AigerWriteSimple( Gia_Man_t * pInit, char * pFileName ) fclose( pFile ); } + + +/**Function************************************************************* + + Synopsis [Simple AIGER reader/writer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Aiger_ReadUnsigned( FILE * pFile ) +{ + unsigned x = 0, i = 0; + unsigned char ch; + while ((ch = fgetc(pFile)) & 0x80) + x |= (ch & 0x7f) << (7 * i++); + return x | (ch << (7 * i)); +} +static inline void Aiger_WriteUnsigned( FILE * pFile, unsigned x ) +{ + unsigned char ch; + while (x & ~0x7f) + { + ch = (x & 0x7f) | 0x80; + fputc( ch, pFile ); + x >>= 7; + } + ch = x; + fputc( ch, pFile ); +} +int * Aiger_Read( char * pFileName, int * pnObjs, int * pnIns, int * pnLats, int * pnOuts, int * pnAnds ) +{ + int i, Temp, Value = 0, nTotal, nObjs, nIns, nLats, nOuts, nAnds, * pObjs; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Aiger_Read(): Cannot open the output file \"%s\".\n", pFileName ); + return NULL; + } + if ( fgetc(pFile) != 'a' || fgetc(pFile) != 'i' || fgetc(pFile) != 'g' ) + { + fprintf( stdout, "Aiger_Read(): Can only read binary AIGER.\n" ); + fclose( pFile ); + return NULL; + } + if ( fscanf(pFile, "%d %d %d %d %d", &nTotal, &nIns, &nLats, &nOuts, &nAnds) != 5 ) + { + fprintf( stdout, "Aiger_Read(): Cannot read the header line.\n" ); + fclose( pFile ); + return NULL; + } + if ( nTotal != nIns + nLats + nAnds ) + { + fprintf( stdout, "The number of objects does not match.\n" ); + fclose( pFile ); + return NULL; + } + nObjs = 1 + nIns + 2*nLats + nOuts + nAnds; + pObjs = ABC_CALLOC( int, nObjs * 2 ); + // read flop input literals + for ( i = 0; i < nLats; i++ ) + { + while ( fgetc(pFile) != '\n' ); + Value += fscanf( pFile, "%d", &Temp ); + pObjs[2*(nObjs-nLats+i)+0] = Temp; + pObjs[2*(nObjs-nLats+i)+1] = Temp; + } + // read output literals + for ( i = 0; i < nOuts; i++ ) + { + while ( fgetc(pFile) != '\n' ); + Value += fscanf( pFile, "%d", &Temp ); + pObjs[2*(nObjs-nOuts-nLats+i)+0] = Temp; + pObjs[2*(nObjs-nOuts-nLats+i)+1] = Temp; + } + assert( Value == nLats + nOuts ); + // read the binary part + while ( fgetc(pFile) != '\n' ); + for ( i = 0; i < nAnds; i++ ) + { + int uLit = 2*(1 + nIns + nLats + i); + int uLit1 = uLit - Aiger_ReadUnsigned( pFile ); + int uLit0 = uLit1 - Aiger_ReadUnsigned( pFile ); + pObjs[2*(1+nIns+nLats+i)+0] = uLit0; + pObjs[2*(1+nIns+nLats+i)+1] = uLit1; + } + fclose( pFile ); + if ( pnObjs ) *pnObjs = nObjs; + if ( pnIns ) *pnIns = nIns; + if ( pnLats ) *pnLats = nLats; + if ( pnOuts ) *pnOuts = nOuts; + if ( pnAnds ) *pnAnds = nAnds; + return pObjs; +} +void Aiger_Write( char * pFileName, int * pObjs, int nObjs, int nIns, int nLats, int nOuts, int nAnds ) +{ + FILE * pFile = fopen( pFileName, "wb" ); int i; + if ( pFile == NULL ) + { + fprintf( stdout, "Aiger_Write(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "aig %d %d %d %d %d\n", nIns + nLats + nAnds, nIns, nLats, nOuts, nAnds ); + for ( i = 0; i < nLats; i++ ) + fprintf( pFile, "%d\n", pObjs[2*(nObjs-nLats+i)+0] ); + for ( i = 0; i < nOuts; i++ ) + fprintf( pFile, "%d\n", pObjs[2*(nObjs-nOuts-nLats+i)+0] ); + for ( i = 0; i < nAnds; i++ ) + { + int uLit = 2*(1 + nIns + nLats + i); + int uLit0 = pObjs[2*(1+nIns+nLats+i)+0]; + int uLit1 = pObjs[2*(1+nIns+nLats+i)+1]; + Aiger_WriteUnsigned( pFile, uLit - uLit1 ); + Aiger_WriteUnsigned( pFile, uLit1 - uLit0 ); + } + fprintf( pFile, "c\n" ); + fclose( pFile ); +} +void Aiger_Test( char * pFileNameIn, char * pFileNameOut ) +{ + int nObjs, nIns, nLats, nOuts, nAnds, * pObjs = Aiger_Read( pFileNameIn, &nObjs, &nIns, &nLats, &nOuts, &nAnds ); + if ( pObjs == NULL ) + return; + printf( "Read input file \"%s\".\n", pFileNameIn ); + Aiger_Write( pFileNameOut, pObjs, nObjs, nIns, nLats, nOuts, nAnds ); + printf( "Written output file \"%s\".\n", pFileNameOut ); + ABC_FREE( pObjs ); +} + +/* +int main( int argc, char ** argv ) +{ + if ( argc != 3 ) + return 0; + Aiger_Test( argv[1], argv[2] ); + return 1; +} +*/ + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/abc/src/aig/gia/giaAigerExt.c b/abc/src/aig/gia/giaAigerExt.c index 7b7758ff33d..50c3588d942 100644 --- a/abc/src/aig/gia/giaAigerExt.c +++ b/abc/src/aig/gia/giaAigerExt.c @@ -218,7 +218,7 @@ Vec_Str_t * Gia_AigerWriteMapping( Gia_Man_t * p ) ***********************************************************************/ int * Gia_AigerReadMappingSimple( unsigned char ** ppPos, int nSize ) { - int * pMapping = ABC_ALLOC( int, nSize/4 ); + int * pMapping = ABC_ALLOC( int, (size_t)nSize/4 ); memcpy( pMapping, *ppPos, nSize ); assert( nSize % 4 == 0 ); return pMapping; @@ -226,7 +226,7 @@ int * Gia_AigerReadMappingSimple( unsigned char ** ppPos, int nSize ) Vec_Str_t * Gia_AigerWriteMappingSimple( Gia_Man_t * p ) { unsigned char * pBuffer = ABC_ALLOC( unsigned char, 4*Vec_IntSize(p->vMapping) ); - memcpy( pBuffer, Vec_IntArray(p->vMapping), 4*Vec_IntSize(p->vMapping) ); + memcpy( pBuffer, Vec_IntArray(p->vMapping), (size_t)4*Vec_IntSize(p->vMapping) ); assert( Vec_IntSize(p->vMapping) >= Gia_ManObjNum(p) ); return Vec_StrAllocArray( (char *)pBuffer, 4*Vec_IntSize(p->vMapping) ); } diff --git a/abc/src/aig/gia/giaBalAig.c b/abc/src/aig/gia/giaBalAig.c index 018bfcaf71d..5603b4108b6 100644 --- a/abc/src/aig/gia/giaBalAig.c +++ b/abc/src/aig/gia/giaBalAig.c @@ -399,6 +399,12 @@ Gia_Man_t * Gia_ManBalanceInt( Gia_Man_t * p, int fStrict ) Gia_ManForEachCiId( pNew, Id, i ) Vec_IntWriteEntry( pNew->vLevels, Id, Vec_IntEntry(p->vCiArrs, i)/And2Delay ); } + else if ( p->vInArrs ) + { + int Id, And2Delay = p->And2Delay ? p->And2Delay : 1; + Gia_ManForEachCiId( pNew, Id, i ) + Vec_IntWriteEntry( pNew->vLevels, Id, (int)(Vec_FltEntry(p->vInArrs, i)/And2Delay) ); + } // create internal nodes Gia_ManHashStart( pNew ); Gia_ManForEachBuf( p, pObj, i ) @@ -443,7 +449,7 @@ Gia_Man_t * Gia_ManBalance( Gia_Man_t * p, int fSimpleAnd, int fStrict, int fVer Gia_ManTransferTiming( pNew1, pNew ); if ( fVerbose ) Gia_ManPrintStats( pNew1, NULL ); Gia_ManStop( pNew ); - pNew2 = Gia_ManDupNoMuxes( pNew1 ); + pNew2 = Gia_ManDupNoMuxes( pNew1, 0 ); Gia_ManTransferTiming( pNew2, pNew1 ); if ( fVerbose ) Gia_ManPrintStats( pNew2, NULL ); Gia_ManStop( pNew1 ); @@ -1051,6 +1057,12 @@ Gia_Man_t * Gia_ManAreaBalance( Gia_Man_t * p, int fSimpleAnd, int nNewNodesMax, Gia_ManForEachCiId( p, Id, i ) Vec_IntWriteEntry( p->vLevels, Id, Vec_IntEntry(p->vCiArrs, i)/And2Delay ); } + else if ( p->vInArrs ) + { + int i, Id, And2Delay = p->And2Delay ? p->And2Delay : 1; + Gia_ManForEachCiId( p, Id, i ) + Vec_IntWriteEntry( p->vLevels, Id, (int)(Vec_FltEntry(p->vInArrs, i)/And2Delay) ); + } // determine CI levels if ( p->pManTime && p->vLevels == NULL ) Gia_ManLevelWithBoxes( p ); @@ -1071,7 +1083,7 @@ Gia_Man_t * Gia_ManAreaBalance( Gia_Man_t * p, int fSimpleAnd, int nNewNodesMax, Gia_ManStop( pNew ); Vec_IntFreeP( &vCiLevels ); // derive the final result - pNew2 = Gia_ManDupNoMuxes( pNew1 ); + pNew2 = Gia_ManDupNoMuxes( pNew1, 0 ); Gia_ManTransferTiming( pNew2, pNew1 ); if ( fVerbose ) Gia_ManPrintStats( pNew2, NULL ); Gia_ManStop( pNew1 ); diff --git a/abc/src/aig/gia/giaBalLut.c b/abc/src/aig/gia/giaBalLut.c index 4402e36fc02..c90910c9734 100644 --- a/abc/src/aig/gia/giaBalLut.c +++ b/abc/src/aig/gia/giaBalLut.c @@ -965,7 +965,7 @@ Gia_Man_t * Gia_ManBalanceLut( Gia_Man_t * p, int nLutSize, int nCutNum, int fVe pNew1 = Gia_ManBalanceInt( pNew, nLutSize, nCutNum, fVerbose ); if ( fVerbose ) Gia_ManPrintStats( pNew1, NULL ); Gia_ManStop( pNew ); - pNew2 = Gia_ManDupNoMuxes( pNew1 ); + pNew2 = Gia_ManDupNoMuxes( pNew1, 0 ); if ( fVerbose ) Gia_ManPrintStats( pNew2, NULL ); Gia_ManStop( pNew1 ); return pNew2; diff --git a/abc/src/aig/gia/giaCSat.c b/abc/src/aig/gia/giaCSat.c index 503961d4c80..67b62655e0f 100644 --- a/abc/src/aig/gia/giaCSat.c +++ b/abc/src/aig/gia/giaCSat.c @@ -1034,7 +1034,7 @@ void Cbs_ManSatPrintStats( Cbs_Man_t * p ) SeeAlso [] ***********************************************************************/ -Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ) +Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int f0Proved, int fVerbose ) { extern void Gia_ManCollectTest( Gia_Man_t * pAig ); extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); @@ -1105,6 +1105,8 @@ Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvSt } if ( status == 1 ) { + if ( f0Proved ) + Gia_ManPatchCoDriver( pAig, i, 0 ); p->nSatUnsat++; p->nConfUnsat += p->Pars.nBTThis; p->timeSatUnsat += Abc_Clock() - clk; diff --git a/abc/src/aig/gia/giaCSat2.c b/abc/src/aig/gia/giaCSat2.c index ee0ce311d2c..a9739e0287f 100644 --- a/abc/src/aig/gia/giaCSat2.c +++ b/abc/src/aig/gia/giaCSat2.c @@ -1653,9 +1653,12 @@ Vec_Int_t * Cbs2_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvS p->timeTotal = Abc_Clock() - clkTotal; if ( fVerbose ) Cbs2_ManSatPrintStats( p ); + if ( fVerbose ) + { // printf( "RecCalls = %8d. RecClause = %8d. RecNonChro = %8d.\n", p->nRecCall, p->nRecClause, p->nRecNonChro ); printf( "Prop1 = %d. Prop2 = %d. Prop3 = %d. ClaConf = %d. FailJ = %d. FailC = %d. ", p->nPropCalls[0], p->nPropCalls[1], p->nPropCalls[2], p->nClauseConf, p->nFails[0], p->nFails[1] ); Abc_PrintTime( 1, "JFront", p->timeJFront ); + } Cbs2_ManStop( p ); *pvStatus = vStatus; diff --git a/abc/src/aig/gia/giaCSat3.c b/abc/src/aig/gia/giaCSat3.c new file mode 100644 index 00000000000..c34c84ca636 --- /dev/null +++ b/abc/src/aig/gia/giaCSat3.c @@ -0,0 +1,1365 @@ +/**CFile**************************************************************** + + FileName [giaCSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [A simple circuit-based solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaCSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cbs3_Par_t_ Cbs3_Par_t; +struct Cbs3_Par_t_ +{ + // conflict limits + int nBTLimit; // limit on the number of conflicts + int nJustLimit; // limit on the size of justification queue + int nRestLimit; // limit on the number of restarts + // current parameters + int nBTThis; // number of conflicts + int nJustThis; // max size of the frontier + int nBTTotal; // total number of conflicts + int nJustTotal; // total size of the frontier + // other + int fVerbose; +}; + +typedef struct Cbs3_Que_t_ Cbs3_Que_t; +struct Cbs3_Que_t_ +{ + int iHead; // beginning of the queue + int iTail; // end of the queue + int nSize; // allocated size + int * pData; // nodes stored in the queue +}; + +typedef struct Cbs3_Man_t_ Cbs3_Man_t; +struct Cbs3_Man_t_ +{ + Cbs3_Par_t Pars; // parameters + Gia_Man_t * pAig; // AIG manager + Cbs3_Que_t pProp; // propagation queue + Cbs3_Que_t pJust; // justification queue + Cbs3_Que_t pClauses; // clause queue + Vec_Int_t * vModel; // satisfying assignment + Vec_Int_t * vTemp; // temporary storage + // circuit structure + int nVars; + int nVarsAlloc; + int var_inc; + Vec_Int_t vMap; + Vec_Int_t vRef; + Vec_Int_t vFans; + Vec_Wec_t vImps; + // internal data + Vec_Str_t vAssign; + Vec_Str_t vMark; + Vec_Int_t vLevReason; + Vec_Int_t vActs; + Vec_Int_t vWatches; + Vec_Int_t vWatchUpds; + // SAT calls statistics + int nSatUnsat; // the number of proofs + int nSatSat; // the number of failure + int nSatUndec; // the number of timeouts + int nSatTotal; // the number of calls + // conflicts + int nConfUnsat; // conflicts in unsat problems + int nConfSat; // conflicts in sat problems + int nConfUndec; // conflicts in undec problems + // runtime stats + abctime timeJFront; + abctime timeSatLoad; // SAT solver loading time + abctime timeSatUnsat; // unsat + abctime timeSatSat; // sat + abctime timeSatUndec; // undecided + abctime timeTotal; // total runtime + // other statistics + int nPropCalls[3]; + int nFails[2]; + int nClauseConf; + int nDecs; +}; + +static inline int Cbs3_VarUnused( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry(&p->vLevReason, 3*iVar) == -1; } +static inline void Cbs3_VarSetUnused( Cbs3_Man_t * p, int iVar ) { Vec_IntWriteEntry(&p->vLevReason, 3*iVar, -1); } + +static inline int Cbs3_VarMark0( Cbs3_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vMark, iVar); } +static inline void Cbs3_VarSetMark0( Cbs3_Man_t * p, int iVar, int Value ) { Vec_StrWriteEntry(&p->vMark, iVar, (char)Value); } + +static inline int Cbs3_VarIsAssigned( Cbs3_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar) < 2; } +static inline void Cbs3_VarUnassign( Cbs3_Man_t * p, int iVar ) { assert( Cbs3_VarIsAssigned(p, iVar)); Vec_StrWriteEntry(&p->vAssign, iVar, (char)(2+Vec_StrEntry(&p->vAssign, iVar))); Cbs3_VarSetUnused(p, iVar); } + +static inline int Cbs3_VarValue( Cbs3_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar); } +static inline void Cbs3_VarSetValue( Cbs3_Man_t * p, int iVar, int v ) { assert( !Cbs3_VarIsAssigned(p, iVar)); Vec_StrWriteEntry(&p->vAssign, iVar, (char)v); } + +static inline int Cbs3_VarLit0( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry( &p->vFans, Abc_Var2Lit(iVar, 0) ); } +static inline int Cbs3_VarLit1( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry( &p->vFans, Abc_Var2Lit(iVar, 1) ); } +static inline int Cbs3_VarIsPi( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry( &p->vFans, Abc_Var2Lit(iVar, 0) ) == 0; } +static inline int Cbs3_VarIsJust( Cbs3_Man_t * p, int iVar ) { int * pLits = Vec_IntEntryP(&p->vFans, Abc_Var2Lit(iVar, 0)); return pLits[0] > 0 && Cbs3_VarValue(p, Abc_Lit2Var(pLits[0])) >= 2 && Cbs3_VarValue(p, Abc_Lit2Var(pLits[1])) >= 2; } + +static inline int Cbs3_VarDecLevel( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar); } +static inline int Cbs3_VarReason0( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar+1); } +static inline int Cbs3_VarReason1( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar+2); } +static inline int * Cbs3_VarReasonP( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntryP(&p->vLevReason, 3*iVar+1); } +static inline int Cbs3_ClauseDecLevel( Cbs3_Man_t * p, int hClause ) { return Cbs3_VarDecLevel( p, p->pClauses.pData[hClause] ); } + +static inline int Cbs3_ClauseSize( Cbs3_Man_t * p, int hClause ) { return p->pClauses.pData[hClause]; } +static inline int * Cbs3_ClauseLits( Cbs3_Man_t * p, int hClause ) { return p->pClauses.pData+hClause+1; } +static inline int Cbs3_ClauseLit( Cbs3_Man_t * p, int hClause, int i ) { return p->pClauses.pData[hClause+1+i]; } +static inline int * Cbs3_ClauseNext1p( Cbs3_Man_t * p, int hClause ) { return p->pClauses.pData+hClause+Cbs3_ClauseSize(p, hClause)+2; } + +static inline void Cbs3_ClauseSetSize( Cbs3_Man_t * p, int hClause, int x ) { p->pClauses.pData[hClause] = x; } +static inline void Cbs3_ClauseSetLit( Cbs3_Man_t * p, int hClause, int i, int x ) { p->pClauses.pData[hClause+i+1] = x; } +static inline void Cbs3_ClauseSetNext( Cbs3_Man_t * p, int hClause, int n, int x ){ p->pClauses.pData[hClause+Cbs3_ClauseSize(p, hClause)+1+n] = x; } + + +#define Cbs3_QueForEachEntry( Que, iObj, i ) \ + for ( i = (Que).iHead; (i < (Que).iTail) && ((iObj) = (Que).pData[i]); i++ ) + +#define Cbs3_ClauseForEachEntry( p, hClause, iObj, i ) \ + for ( i = 1; i <= Cbs3_ClauseSize(p, hClause) && (iObj = (p)->pClauses.pData[hClause+i]); i++ ) +#define Cbs3_ClauseForEachEntry1( p, hClause, iObj, i ) \ + for ( i = 2; i <= Cbs3_ClauseSize(p, hClause) && (iObj = (p)->pClauses.pData[hClause+i]); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets default values of the parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs3_SetDefaultParams( Cbs3_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Cbs3_Par_t) ); + pPars->nBTLimit = 1000; // limit on the number of conflicts + pPars->nJustLimit = 500; // limit on the size of justification queue + pPars->nRestLimit = 10; // limit on the number of restarts + pPars->fVerbose = 1; // print detailed statistics +} +void Cbs3_ManSetConflictNum( Cbs3_Man_t * p, int Num ) +{ + p->Pars.nBTLimit = Num; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cbs3_Man_t * Cbs3_ManAlloc( Gia_Man_t * pGia ) +{ + Cbs3_Man_t * p; + p = ABC_CALLOC( Cbs3_Man_t, 1 ); + p->pProp.nSize = p->pJust.nSize = p->pClauses.nSize = 10000; + p->pProp.pData = ABC_ALLOC( int, p->pProp.nSize ); + p->pJust.pData = ABC_ALLOC( int, p->pJust.nSize ); + p->pClauses.pData = ABC_ALLOC( int, p->pClauses.nSize ); + p->pClauses.iHead = p->pClauses.iTail = 1; + p->vModel = Vec_IntAlloc( 1000 ); + p->vTemp = Vec_IntAlloc( 1000 ); + p->pAig = pGia; + Cbs3_SetDefaultParams( &p->Pars ); + // circuit structure + Vec_IntPush( &p->vMap, -1 ); + Vec_IntPush( &p->vRef, -1 ); + Vec_IntPushTwo( &p->vFans, -1, -1 ); + Vec_WecPushLevel( &p->vImps ); + Vec_WecPushLevel( &p->vImps ); + p->nVars = 1; + // internal data + p->nVarsAlloc = 1000; + Vec_StrFill( &p->vAssign, p->nVarsAlloc, 2 ); + Vec_StrFill( &p->vMark, p->nVarsAlloc, 0 ); + Vec_IntFill( &p->vLevReason, 3*p->nVarsAlloc, -1 ); + Vec_IntFill( &p->vActs, p->nVarsAlloc, 0 ); + Vec_IntFill( &p->vWatches, 2*p->nVarsAlloc, 0 ); + Vec_IntGrow( &p->vWatchUpds, 1000 ); + return p; +} +static inline void Cbs3_ManReset( Cbs3_Man_t * p ) +{ + assert( p->nVars == Vec_IntSize(&p->vMap) ); + Vec_IntShrink( &p->vMap, 1 ); + Vec_IntShrink( &p->vRef, 1 ); + Vec_IntShrink( &p->vFans, 2 ); + Vec_WecShrink( &p->vImps, 2 ); + p->nVars = 1; +} +static inline void Cbs3_ManGrow( Cbs3_Man_t * p ) +{ + if ( p->nVarsAlloc < p->nVars ) + { + p->nVarsAlloc = 2*p->nVars; + Vec_StrFill( &p->vAssign, p->nVarsAlloc, 2 ); + Vec_StrFill( &p->vMark, p->nVarsAlloc, 0 ); + Vec_IntFill( &p->vLevReason, 3*p->nVarsAlloc, -1 ); + Vec_IntFill( &p->vActs, p->nVarsAlloc, 0 ); + Vec_IntFill( &p->vWatches, 2*p->nVarsAlloc, 0 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs3_ManStop( Cbs3_Man_t * p ) +{ + // circuit structure + Vec_IntErase( &p->vMap ); + Vec_IntErase( &p->vRef ); + Vec_IntErase( &p->vFans ); + Vec_WecErase( &p->vImps ); + // internal data + Vec_StrErase( &p->vAssign ); + Vec_StrErase( &p->vMark ); + Vec_IntErase( &p->vLevReason ); + Vec_IntErase( &p->vActs ); + Vec_IntErase( &p->vWatches ); + Vec_IntErase( &p->vWatchUpds ); + Vec_IntFree( p->vModel ); + Vec_IntFree( p->vTemp ); + ABC_FREE( p->pClauses.pData ); + ABC_FREE( p->pProp.pData ); + ABC_FREE( p->pJust.pData ); + ABC_FREE( p ); +} +int Cbs3_ManMemory( Cbs3_Man_t * p ) +{ + int nMem = sizeof(Cbs3_Man_t); + nMem += (int)Vec_IntMemory( &p->vMap ); + nMem += (int)Vec_IntMemory( &p->vRef ); + nMem += (int)Vec_IntMemory( &p->vFans ); + nMem += (int)Vec_WecMemory( &p->vImps ); + nMem += (int)Vec_StrMemory( &p->vAssign ); + nMem += (int)Vec_StrMemory( &p->vMark ); + nMem += (int)Vec_IntMemory( &p->vActs ); + nMem += (int)Vec_IntMemory( &p->vWatches ); + nMem += (int)Vec_IntMemory( &p->vWatchUpds ); + nMem += (int)Vec_IntMemory( p->vModel ); + nMem += (int)Vec_IntMemory( p->vTemp ); + nMem += 4*p->pClauses.nSize; + nMem += 4*p->pProp.nSize; + nMem += 4*p->pJust.nSize; + return nMem; +} + +/**Function************************************************************* + + Synopsis [Returns satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cbs3_ReadModel( Cbs3_Man_t * p ) +{ + return p->vModel; +} + + +/**Function************************************************************* + + Synopsis [Activity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +//#define USE_ACTIVITY + +#ifdef USE_ACTIVITY +static inline void Cbs3_ActReset( Cbs3_Man_t * p ) +{ + int i, * pAct = Vec_IntArray(&p->vActs); + for ( i = 0; i < p->nVars; i++ ) + pAct[i] = (1 << 10); + p->var_inc = (1 << 5); +} +static inline void Cbs3_ActRescale( Cbs3_Man_t * p ) +{ + int i, * pAct = Vec_IntArray(&p->vActs); + for ( i = 0; i < p->nVars; i++ ) + pAct[i] >>= 19; + p->var_inc >>= 19; + p->var_inc = Abc_MaxInt( (unsigned)p->var_inc, (1<<5) ); +} +static inline void Cbs3_ActBumpVar( Cbs3_Man_t * p, int iVar ) +{ + int * pAct = Vec_IntArray(&p->vActs); + pAct[iVar] += p->var_inc; + if ((unsigned)pAct[iVar] & 0x80000000) + Cbs3_ActRescale(p); +} +static inline void Cbs3_ActDecay( Cbs3_Man_t * p ) +{ + p->var_inc += (p->var_inc >> 4); +} +#else +static inline void Cbs3_ActReset( Cbs3_Man_t * p ) {} +static inline void Cbs3_ActRescale( Cbs3_Man_t * p ) {} +static inline void Cbs3_ActBumpVar( Cbs3_Man_t * p, int iVar ) {} +static inline void Cbs3_ActDecay( Cbs3_Man_t * p ) {} +#endif + + +/**Function************************************************************* + + Synopsis [Returns 1 if the solver is out of limits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManCheckLimits( Cbs3_Man_t * p ) +{ + p->nFails[0] += p->Pars.nJustThis > p->Pars.nJustLimit; + p->nFails[1] += p->Pars.nBTThis > p->Pars.nBTLimit; + return p->Pars.nJustThis > p->Pars.nJustLimit || p->Pars.nBTThis > p->Pars.nBTLimit; +} + +/**Function************************************************************* + + Synopsis [Saves the satisfying assignment as an array of literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManSaveModel( Cbs3_Man_t * p, Vec_Int_t * vCex ) +{ + int i, iLit; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + Cbs3_QueForEachEntry( p->pProp, iLit, i ) + if ( Cbs3_VarIsPi(p, Abc_Lit2Var(iLit)) ) + Vec_IntPush( vCex, Abc_Lit2LitV(Vec_IntArray(&p->vMap), iLit)-2 ); +} +static inline void Cbs3_ManSaveModelAll( Cbs3_Man_t * p, Vec_Int_t * vCex ) +{ + int i, iLit; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + Cbs3_QueForEachEntry( p->pProp, iLit, i ) + { + int iVar = Abc_Lit2Var(iLit); + Vec_IntPush( vCex, Abc_Var2Lit(iVar, !Cbs3_VarValue(p, iVar)) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_QueIsEmpty( Cbs3_Que_t * p ) +{ + return p->iHead == p->iTail; +} +static inline int Cbs3_QueSize( Cbs3_Que_t * p ) +{ + return p->iTail - p->iHead; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_QuePush( Cbs3_Que_t * p, int iObj ) +{ + if ( p->iTail == p->nSize ) + { + p->nSize *= 2; + p->pData = ABC_REALLOC( int, p->pData, p->nSize ); + } + p->pData[p->iTail++] = iObj; +} +static inline void Cbs3_QueGrow( Cbs3_Que_t * p, int Plus ) +{ + if ( p->iTail + Plus > p->nSize ) + { + p->nSize *= 2; + p->pData = ABC_REALLOC( int, p->pData, p->nSize ); + } + assert( p->iTail + Plus <= p->nSize ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the object in the queue.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_QueHasNode( Cbs3_Que_t * p, int iObj ) +{ + int i, iTemp; + Cbs3_QueForEachEntry( *p, iTemp, i ) + if ( iTemp == iObj ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_QueStore( Cbs3_Que_t * p, int * piHeadOld, int * piTailOld ) +{ + int i; + *piHeadOld = p->iHead; + *piTailOld = p->iTail; + for ( i = *piHeadOld; i < *piTailOld; i++ ) + Cbs3_QuePush( p, p->pData[i] ); + p->iHead = *piTailOld; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_QueRestore( Cbs3_Que_t * p, int iHeadOld, int iTailOld ) +{ + p->iHead = iHeadOld; + p->iTail = iTailOld; +} + +/**Function************************************************************* + + Synopsis [Find variable with the highest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManDecide( Cbs3_Man_t * p ) +{ + int i, iObj, iObjMax = 0; +#ifdef USE_ACTIVITY + Cbs3_QueForEachEntry( p->pJust, iObj, i ) + if ( iObjMax == 0 || + Vec_IntEntry(&p->vActs, iObjMax) < Vec_IntEntry(&p->vActs, iObj) || + (Vec_IntEntry(&p->vActs, iObjMax) == Vec_IntEntry(&p->vActs, iObj) && Vec_IntEntry(&p->vMap, iObjMax) < Vec_IntEntry(&p->vMap, iObj)) ) + iObjMax = iObj; +#else + Cbs3_QueForEachEntry( p->pJust, iObj, i ) +// if ( iObjMax == 0 || iObjMax < iObj ) + if ( iObjMax == 0 || Vec_IntEntry(&p->vMap, iObjMax) < Vec_IntEntry(&p->vMap, iObj) ) + iObjMax = iObj; +#endif + return iObjMax; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManCancelUntil( Cbs3_Man_t * p, int iBound ) +{ + int i, iLit; + assert( iBound <= p->pProp.iTail ); + p->pProp.iHead = iBound; + Cbs3_QueForEachEntry( p->pProp, iLit, i ) + Cbs3_VarUnassign( p, Abc_Lit2Var(iLit) ); + p->pProp.iTail = iBound; +} + +/**Function************************************************************* + + Synopsis [Assigns the variables a value.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManAssign( Cbs3_Man_t * p, int iLit, int Level, int iRes0, int iRes1 ) +{ + int iObj = Abc_Lit2Var(iLit); + assert( Cbs3_VarUnused(p, iObj) ); + assert( !Cbs3_VarIsAssigned(p, iObj) ); + Cbs3_VarSetValue( p, iObj, !Abc_LitIsCompl(iLit) ); + Cbs3_QuePush( &p->pProp, iLit ); + Vec_IntWriteEntry( &p->vLevReason, 3*iObj, Level ); + Vec_IntWriteEntry( &p->vLevReason, 3*iObj+1, iRes0 ); + Vec_IntWriteEntry( &p->vLevReason, 3*iObj+2, iRes1 ); +} + + + + +/**Function************************************************************* + + Synopsis [Prints conflict clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManPrintClause( Cbs3_Man_t * p, int Level, int hClause ) +{ + int i, iLit; + assert( Cbs3_QueIsEmpty( &p->pClauses ) ); + printf( "Level %2d : ", Level ); + Cbs3_ClauseForEachEntry( p, hClause, iLit, i ) + printf( "%c%d ", Abc_LitIsCompl(iLit) ? '-':'+', Abc_Lit2Var(iLit) ); +// printf( "%d=%d(%d) ", iObj, Cbs3_VarValue(p, Abc_Lit2Var(iLit)), Cbs3_VarDecLevel(p, Abc_Lit2Var(iLit)) ); + printf( "\n" ); +} +static inline void Cbs3_ManPrintCube( Cbs3_Man_t * p, int Level, int hClause ) +{ + int i, iObj; + assert( Cbs3_QueIsEmpty( &p->pClauses ) ); + printf( "Level %2d : ", Level ); + Cbs3_ClauseForEachEntry( p, hClause, iObj, i ) + printf( "%c%d ", Cbs3_VarValue(p, iObj)? '+':'-', iObj ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Finalized the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManCleanWatch( Cbs3_Man_t * p ) +{ + int i, iLit; + Vec_IntForEachEntry( &p->vWatchUpds, iLit, i ) + Vec_IntWriteEntry( &p->vWatches, iLit, 0 ); + Vec_IntClear( &p->vWatchUpds ); + //Vec_IntForEachEntry( &p->vWatches, iLit, i ) + // assert( iLit == 0 ); +} +static inline void Cbs3_ManWatchClause( Cbs3_Man_t * p, int hClause, int Lit ) +{ + int * pLits = Cbs3_ClauseLits( p, hClause ); + int * pPlace = Vec_IntEntryP( &p->vWatches, Abc_LitNot(Lit) ); + if ( *pPlace == 0 ) + Vec_IntPush( &p->vWatchUpds, Abc_LitNot(Lit) ); +/* + if ( pClause->pLits[0] == Lit ) + pClause->pNext0 = p->pWatches[lit_neg(Lit)]; + else + { + assert( pClause->pLits[1] == Lit ); + pClause->pNext1 = p->pWatches[lit_neg(Lit)]; + } + p->pWatches[lit_neg(Lit)] = pClause; +*/ + assert( Lit == pLits[0] || Lit == pLits[1] ); + Cbs3_ClauseSetNext( p, hClause, Lit == pLits[1], *pPlace ); + *pPlace = hClause; +} +static inline int Cbs3_QueFinish( Cbs3_Man_t * p, int Level ) +{ + Cbs3_Que_t * pQue = &(p->pClauses); + int i, iObj, hClauseC, hClause = pQue->iHead, Size = pQue->iTail - pQue->iHead - 1; + assert( pQue->iHead+1 < pQue->iTail ); + Cbs3_ClauseSetSize( p, pQue->iHead, Size ); + hClauseC = pQue->iHead = pQue->iTail; + //printf( "Adding cube: " ); Cbs3_ManPrintCube(p, Level, hClause); + if ( Size == 1 ) + return hClause; + // create watched clause + pQue->iHead = hClause; + Cbs3_QueForEachEntry( p->pClauses, iObj, i ) + { + if ( i == hClauseC ) + break; + else if ( i == hClause ) // nlits + Cbs3_QuePush( pQue, iObj ); + else // literals + Cbs3_QuePush( pQue, Abc_Var2Lit(iObj, Cbs3_VarValue(p, iObj)) ); // complement + } + Cbs3_QuePush( pQue, 0 ); // next0 + Cbs3_QuePush( pQue, 0 ); // next1 + pQue->iHead = pQue->iTail; + Cbs3_ManWatchClause( p, hClauseC, Cbs3_ClauseLit(p, hClauseC, 0) ); + Cbs3_ManWatchClause( p, hClauseC, Cbs3_ClauseLit(p, hClauseC, 1) ); + //printf( "Adding clause %d: ", hClauseC ); Cbs3_ManPrintClause(p, Level, hClauseC); + Cbs3_ActDecay( p ); + return hClause; +} + +/**Function************************************************************* + + Synopsis [Returns conflict clause.] + + Description [Performs conflict analysis.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManDeriveReason( Cbs3_Man_t * p, int Level ) +{ + Cbs3_Que_t * pQue = &(p->pClauses); + int i, k, iObj, iLitLevel, * pReason; + assert( pQue->pData[pQue->iHead] == 0 ); + assert( pQue->pData[pQue->iHead+1] == 0 ); + assert( pQue->iHead + 2 < pQue->iTail ); + //for ( i = pQue->iHead + 2; i < pQue->iTail; i++ ) + // assert( !Cbs3_VarMark0(p, pQue->pData[i]) ); + // compact literals + Vec_IntClear( p->vTemp ); + for ( i = k = pQue->iHead + 2; i < pQue->iTail; i++ ) + { + iObj = pQue->pData[i]; + if ( Cbs3_VarMark0(p, iObj) ) // unassigned - seen again + continue; + //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 ) + // Vec_IntPush( &p->vActStore, iObj ); + //Vec_IntAddToEntry( &p->vActivity, iObj, 1 ); + // assigned - seen first time + Cbs3_VarSetMark0(p, iObj, 1); + Cbs3_ActBumpVar(p, iObj); + Vec_IntPush( p->vTemp, iObj ); + // check decision level + iLitLevel = Cbs3_VarDecLevel( p, iObj ); + if ( iLitLevel < Level ) + { + pQue->pData[k++] = iObj; + continue; + } + assert( iLitLevel == Level ); + pReason = Cbs3_VarReasonP( p, iObj ); + if ( pReason[0] == 0 && pReason[1] == 0 ) // no reason + { + assert( pQue->pData[pQue->iHead+1] == 0 ); + pQue->pData[pQue->iHead+1] = iObj; + } + else if ( pReason[0] != 0 ) // circuit reason + { + Cbs3_QuePush( pQue, pReason[0] ); + if ( pReason[1] ) + Cbs3_QuePush( pQue, pReason[1] ); + } + else // clause reason + { + int i, * pLits, nLits = Cbs3_ClauseSize( p, pReason[1] ); + assert( pReason[1] ); + Cbs3_QueGrow( pQue, nLits ); + pLits = Cbs3_ClauseLits( p, pReason[1] ); + assert( iObj == Abc_Lit2Var(pLits[0]) ); + for ( i = 1; i < nLits; i++ ) + Cbs3_QuePush( pQue, Abc_Lit2Var(pLits[i]) ); + } + } + assert( pQue->pData[pQue->iHead] == 0 ); + assert( pQue->pData[pQue->iHead+1] != 0 ); + pQue->iTail = k; + // clear the marks + Vec_IntForEachEntry( p->vTemp, iObj, i ) + Cbs3_VarSetMark0(p, iObj, 0); + return Cbs3_QueFinish( p, Level ); +} +static inline int Cbs3_ManAnalyze( Cbs3_Man_t * p, int Level, int iVar, int iFan0, int iFan1 ) +{ + Cbs3_Que_t * pQue = &(p->pClauses); + assert( Cbs3_VarIsAssigned(p, iVar) ); + assert( Cbs3_QueIsEmpty( pQue ) ); + Cbs3_QuePush( pQue, 0 ); + Cbs3_QuePush( pQue, 0 ); + if ( iFan0 ) // circuit conflict + { + assert( Cbs3_VarIsAssigned(p, iFan0) ); + assert( iFan1 == 0 || Cbs3_VarIsAssigned(p, iFan1) ); + Cbs3_QuePush( pQue, iVar ); + Cbs3_QuePush( pQue, iFan0 ); + if ( iFan1 ) + Cbs3_QuePush( pQue, iFan1 ); + } + else // clause conflict + { + int i, * pLits, nLits = Cbs3_ClauseSize( p, iFan1 ); + assert( iFan1 ); + Cbs3_QueGrow( pQue, nLits ); + pLits = Cbs3_ClauseLits( p, iFan1 ); + assert( iVar == Abc_Lit2Var(pLits[0]) ); + assert( Cbs3_VarValue(p, iVar) == Abc_LitIsCompl(pLits[0]) ); + for ( i = 0; i < nLits; i++ ) + Cbs3_QuePush( pQue, Abc_Lit2Var(pLits[i]) ); + } + return Cbs3_ManDeriveReason( p, Level ); +} + + +/**Function************************************************************* + + Synopsis [Propagate one assignment.] + + Description [Returns handle of the conflict clause, if conflict occurs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManPropagateClauses( Cbs3_Man_t * p, int Level, int Lit ) +{ + int i, Value, Cur, LitF = Abc_LitNot(Lit); + int * pPrev = Vec_IntEntryP( &p->vWatches, Lit ); + //for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev ) + for ( Cur = *pPrev; Cur; Cur = *pPrev ) + { + int nLits = Cbs3_ClauseSize( p, Cur ); + int * pLits = Cbs3_ClauseLits( p, Cur ); + p->nPropCalls[1]++; +//printf( " Watching literal %c%d on level %d.\n", Abc_LitIsCompl(Lit) ? '-':'+', Abc_Lit2Var(Lit), Level ); + // make sure the false literal is in the second literal of the clause + //if ( pCur->pLits[0] == LitF ) + if ( pLits[0] == LitF ) + { + //pCur->pLits[0] = pCur->pLits[1]; + pLits[0] = pLits[1]; + //pCur->pLits[1] = LitF; + pLits[1] = LitF; + //pTemp = pCur->pNext0; + //pCur->pNext0 = pCur->pNext1; + //pCur->pNext1 = pTemp; + ABC_SWAP( int, pLits[nLits], pLits[nLits+1] ); + } + //assert( pCur->pLits[1] == LitF ); + assert( pLits[1] == LitF ); + + // if the first literal is true, the clause is satisfied + //if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] ) + if ( Cbs3_VarValue(p, Abc_Lit2Var(pLits[0])) == !Abc_LitIsCompl(pLits[0]) ) + { + //ppPrev = &pCur->pNext1; + pPrev = Cbs3_ClauseNext1p(p, Cur); + continue; + } + + // look for a new literal to watch + for ( i = 2; i < nLits; i++ ) + { + // skip the case when the literal is false + //if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] ) + if ( Cbs3_VarValue(p, Abc_Lit2Var(pLits[i])) == Abc_LitIsCompl(pLits[i]) ) + continue; + // the literal is either true or unassigned - watch it + //pCur->pLits[1] = pCur->pLits[i]; + //pCur->pLits[i] = LitF; + pLits[1] = pLits[i]; + pLits[i] = LitF; + // remove this clause from the watch list of Lit + //*ppPrev = pCur->pNext1; + *pPrev = *Cbs3_ClauseNext1p(p, Cur); + // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) + //Intb_ManWatchClause( p, pCur, pCur->pLits[1] ); + Cbs3_ManWatchClause( p, Cur, Cbs3_ClauseLit(p, Cur, 1) ); + break; + } + if ( i < nLits ) // found new watch + continue; + + // clause is unit - enqueue new implication + //if ( Inta_ManEnqueue(p, pCur->pLits[0], pCur) ) + //{ + // ppPrev = &pCur->pNext1; + // continue; + //} + + // clause is unit - enqueue new implication + Value = Cbs3_VarValue(p, Abc_Lit2Var(pLits[0])); + if ( Value >= 2 ) // unassigned + { + Cbs3_ManAssign( p, pLits[0], Level, 0, Cur ); + pPrev = Cbs3_ClauseNext1p(p, Cur); + continue; + } + + // conflict detected - return the conflict clause + //return pCur; + if ( Value == Abc_LitIsCompl(pLits[0]) ) + { + p->nClauseConf++; + return Cbs3_ManAnalyze( p, Level, Abc_Lit2Var(pLits[0]), 0, Cur ); + } + } + return 0; +} + + +/**Function************************************************************* + + Synopsis [Performs resolution of two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManResolve( Cbs3_Man_t * p, int Level, int hClause0, int hClause1 ) +{ + Cbs3_Que_t * pQue = &(p->pClauses); + int i, iObj, LevelMax = -1, LevelCur; + assert( pQue->pData[hClause0+1] != 0 ); + assert( pQue->pData[hClause0+1] == pQue->pData[hClause1+1] ); + //Cbs3_ClauseForEachEntry1( p, hClause0, iObj, i ) + // assert( !Cbs3_VarMark0(p, iObj) ); + //Cbs3_ClauseForEachEntry1( p, hClause1, iObj, i ) + // assert( !Cbs3_VarMark0(p, iObj) ); + assert( Cbs3_QueIsEmpty( pQue ) ); + Cbs3_QuePush( pQue, 0 ); + Cbs3_QuePush( pQue, 0 ); +// for ( i = hClause0 + 1; (iObj = pQue->pData[i]); i++ ) + Cbs3_ClauseForEachEntry1( p, hClause0, iObj, i ) + { + if ( Cbs3_VarMark0(p, iObj) ) // unassigned - seen again + continue; + //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 ) + // Vec_IntPush( &p->vActStore, iObj ); + //Vec_IntAddToEntry( &p->vActivity, iObj, 1 ); + // assigned - seen first time + Cbs3_VarSetMark0(p, iObj, 1); + Cbs3_ActBumpVar(p, iObj); + Cbs3_QuePush( pQue, iObj ); + LevelCur = Cbs3_VarDecLevel( p, iObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } +// for ( i = hClause1 + 1; (iObj = pQue->pData[i]); i++ ) + Cbs3_ClauseForEachEntry1( p, hClause1, iObj, i ) + { + if ( Cbs3_VarMark0(p, iObj) ) // unassigned - seen again + continue; + //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 ) + // Vec_IntPush( &p->vActStore, iObj ); + //Vec_IntAddToEntry( &p->vActivity, iObj, 1 ); + // assigned - seen first time + Cbs3_VarSetMark0(p, iObj, 1); + Cbs3_ActBumpVar(p, iObj); + Cbs3_QuePush( pQue, iObj ); + LevelCur = Cbs3_VarDecLevel( p, iObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + for ( i = pQue->iHead + 2; i < pQue->iTail; i++ ) + Cbs3_VarSetMark0(p, pQue->pData[i], 0); + return Cbs3_ManDeriveReason( p, LevelMax ); +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns clause handle if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs3_ManUpdateJFrontier( Cbs3_Man_t * p ) +{ + //abctime clk = Abc_Clock(); + int iVar, iLit, i, k = p->pJust.iTail; + Cbs3_QueGrow( &p->pJust, Cbs3_QueSize(&p->pJust) + Cbs3_QueSize(&p->pProp) ); + Cbs3_QueForEachEntry( p->pJust, iVar, i ) + if ( Cbs3_VarIsJust(p, iVar) ) + p->pJust.pData[k++] = iVar; + Cbs3_QueForEachEntry( p->pProp, iLit, i ) + if ( Cbs3_VarIsJust(p, Abc_Lit2Var(iLit)) ) + p->pJust.pData[k++] = Abc_Lit2Var(iLit); + p->pJust.iHead = p->pJust.iTail; + p->pJust.iTail = k; + //p->timeJFront += Abc_Clock() - clk; +} +int Cbs3_ManPropagateNew( Cbs3_Man_t * p, int Level ) +{ + int i, k, iLit, hClause, nLits, * pLits; + p->nPropCalls[0]++; + Cbs3_QueForEachEntry( p->pProp, iLit, i ) + { + if ( (hClause = Cbs3_ManPropagateClauses(p, Level, iLit)) ) + return hClause; + p->nPropCalls[2]++; + nLits = Vec_IntSize(Vec_WecEntry(&p->vImps, iLit)); + pLits = Vec_IntArray(Vec_WecEntry(&p->vImps, iLit)); + for ( k = 0; k < nLits; k += 2 ) + { + int Value0 = Cbs3_VarValue(p, Abc_Lit2Var(pLits[k])); + int Value1 = pLits[k+1] ? Cbs3_VarValue(p, Abc_Lit2Var(pLits[k+1])) : -1; + if ( Value1 == -1 || Value1 == Abc_LitIsCompl(pLits[k+1]) ) // pLits[k+1] is false + { + if ( Value0 >= 2 ) // pLits[k] is unassigned + Cbs3_ManAssign( p, pLits[k], Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k+1]) ); + else if ( Value0 == Abc_LitIsCompl(pLits[k]) ) // pLits[k] is false + return Cbs3_ManAnalyze( p, Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k]), Abc_Lit2Var(pLits[k+1]) ); + } + if ( Value1 != -1 && Value0 == Abc_LitIsCompl(pLits[k]) ) // pLits[k] is false + { + if ( Value1 >= 2 ) // pLits[k+1] is unassigned + Cbs3_ManAssign( p, pLits[k+1], Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k]) ); + else if ( Value1 == Abc_LitIsCompl(pLits[k+1]) ) // pLits[k+1] is false + return Cbs3_ManAnalyze( p, Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k]), Abc_Lit2Var(pLits[k+1]) ); + } + } + } + Cbs3_ManUpdateJFrontier( p ); + // finalize propagation queue + p->pProp.iHead = p->pProp.iTail; + return 0; +} + +/**Function************************************************************* + + Synopsis [Solve the problem recursively.] + + Description [Returns learnt clause if unsat, NULL if sat or undecided.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cbs3_ManSolve2_rec( Cbs3_Man_t * p, int Level ) +{ + Cbs3_Que_t * pQue = &(p->pClauses); + int iPropHead, iJustHead, iJustTail; + int hClause, hLearn0, hLearn1, iVar, iDecLit; + int nRef0, nRef1; + // propagate assignments + assert( !Cbs3_QueIsEmpty(&p->pProp) ); + //if ( (hClause = Cbs3_ManPropagate( p, Level )) ) + if ( (hClause = Cbs3_ManPropagateNew( p, Level )) ) + return hClause; + // check for satisfying assignment + assert( Cbs3_QueIsEmpty(&p->pProp) ); + if ( Cbs3_QueIsEmpty(&p->pJust) ) + return 0; + // quit using resource limits + p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); + if ( Cbs3_ManCheckLimits( p ) ) + return 0; + // remember the state before branching + iPropHead = p->pProp.iHead; + iJustHead = p->pJust.iHead; + iJustTail = p->pJust.iTail; + // find the decision variable + p->nDecs++; + iVar = Cbs3_ManDecide( p ); + assert( !Cbs3_VarIsPi(p, iVar) ); + assert( Cbs3_VarIsJust(p, iVar) ); + // chose decision variable using fanout count + nRef0 = Vec_IntEntry(&p->vRef, Abc_Lit2Var(Cbs3_VarLit0(p, iVar))); + nRef1 = Vec_IntEntry(&p->vRef, Abc_Lit2Var(Cbs3_VarLit1(p, iVar))); +// if ( nRef0 >= nRef1 || (nRef0 == nRef1) && (Abc_Random(0) & 1) ) + if ( nRef0 >= nRef1 ) + iDecLit = Abc_LitNot(Cbs3_VarLit0(p, iVar)); + else + iDecLit = Abc_LitNot(Cbs3_VarLit1(p, iVar)); + // decide on first fanin + Cbs3_ManAssign( p, iDecLit, Level+1, 0, 0 ); + if ( !(hLearn0 = Cbs3_ManSolve2_rec( p, Level+1 )) ) + return 0; + if ( pQue->pData[hLearn0+1] != Abc_Lit2Var(iDecLit) ) + return hLearn0; + Cbs3_ManCancelUntil( p, iPropHead ); + Cbs3_QueRestore( &p->pJust, iJustHead, iJustTail ); + // decide on second fanin + Cbs3_ManAssign( p, Abc_LitNot(iDecLit), Level+1, 0, 0 ); + if ( !(hLearn1 = Cbs3_ManSolve2_rec( p, Level+1 )) ) + return 0; + if ( pQue->pData[hLearn1+1] != Abc_Lit2Var(iDecLit) ) + return hLearn1; + hClause = Cbs3_ManResolve( p, Level, hLearn0, hLearn1 ); + p->Pars.nBTThis++; + return hClause; +} + +/**Function************************************************************* + + Synopsis [Looking for a satisfying assignment of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManSolveInt( Cbs3_Man_t * p, int iLit ) +{ + int RetValue = 0; + assert( !p->pProp.iHead && !p->pProp.iTail ); + assert( !p->pJust.iHead && !p->pJust.iTail ); + p->Pars.nBTThis = p->Pars.nJustThis = 0; + Cbs3_ManAssign( p, iLit, 0, 0, 0 ); + if ( !Cbs3_ManSolve2_rec(p, 0) && !Cbs3_ManCheckLimits(p) ) + Cbs3_ManSaveModel( p, p->vModel ); + else + RetValue = 1; + Cbs3_ManCancelUntil( p, 0 ); + p->pJust.iHead = p->pJust.iTail = 0; + p->Pars.nBTTotal += p->Pars.nBTThis; + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); + if ( Cbs3_ManCheckLimits( p ) ) + RetValue = -1; + return RetValue; +} +int Cbs3_ManSolve( Cbs3_Man_t * p, int iLit, int nRestarts ) +{ + int i, RetValue = -1; + assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 ); + for ( i = 0; i < nRestarts; i++ ) + if ( (RetValue = Cbs3_ManSolveInt(p, iLit)) != -1 ) + break; + Cbs3_ManCleanWatch( p ); + p->pClauses.iHead = p->pClauses.iTail = 1; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Prints statistics of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs3_ManSatPrintStats( Cbs3_Man_t * p ) +{ + printf( "CO = %8d ", Gia_ManCoNum(p->pAig) ); + printf( "AND = %8d ", Gia_ManAndNum(p->pAig) ); + printf( "Conf = %6d ", p->Pars.nBTLimit ); + printf( "Restart = %2d ", p->Pars.nRestLimit ); + printf( "JustMax = %5d ", p->Pars.nJustLimit ); + printf( "\n" ); + printf( "Unsat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal :0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 ); + ABC_PRTP( "Time", p->timeSatUnsat, p->timeTotal ); + printf( "Sat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatSat, p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal :0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 ); + ABC_PRTP( "Time", p->timeSatSat, p->timeTotal ); + printf( "Undef calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal :0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 ); + ABC_PRTP( "Time", p->timeSatUndec, p->timeTotal ); + ABC_PRT( "Total time", p->timeTotal ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManAddVar( Cbs3_Man_t * p, int iGiaObj ) +{ + assert( Vec_IntSize(&p->vMap) == p->nVars ); + Vec_IntPush( &p->vMap, iGiaObj ); + Vec_IntPush( &p->vRef, Gia_ObjRefNumId(p->pAig, iGiaObj) ); + Vec_IntPushTwo( &p->vFans, 0, 0 ); + Vec_WecPushLevel(&p->vImps); + Vec_WecPushLevel(&p->vImps); + return Abc_Var2Lit( p->nVars++, 0 ); +} +static inline void Cbs3_ManAddConstr( Cbs3_Man_t * p, int x, int x0, int x1 ) +{ + Vec_WecPushTwo( &p->vImps, x , x0, 0 ); // ~x + x0 + Vec_WecPushTwo( &p->vImps, x , x1, 0 ); // ~x + x1 + Vec_WecPushTwo( &p->vImps, 1^x0, 1^x , 0 ); // ~x + x0 + Vec_WecPushTwo( &p->vImps, 1^x1, 1^x , 0 ); // ~x + x1 + Vec_WecPushTwo( &p->vImps, 1^x , 1^x0, 1^x1 ); // x + ~x0 + ~x1 + Vec_WecPushTwo( &p->vImps, x0, x , 1^x1 ); // x + ~x0 + ~x1 + Vec_WecPushTwo( &p->vImps, x1, x , 1^x0 ); // x + ~x0 + ~x1 +} +static inline void Cbs3_ManAddAnd( Cbs3_Man_t * p, int x, int x0, int x1 ) +{ + assert( x > 0 && x0 > 0 && x1 > 0 ); + Vec_IntWriteEntry( &p->vFans, x, x0 ); + Vec_IntWriteEntry( &p->vFans, x+1, x1 ); + Cbs3_ManAddConstr( p, x, x0, x1 ); +} +static inline int Cbs3_ManToSolver1_rec( Cbs3_Man_t * pSol, Gia_Man_t * p, int iObj, int Depth ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); int Lit0, Lit1; + if ( Gia_ObjUpdateTravIdCurrentId(p, iObj) ) + return pObj->Value; + pObj->Value = Cbs3_ManAddVar( pSol, iObj ); + if ( Gia_ObjIsCi(pObj) || Depth == 0 ) + return pObj->Value; + assert( Gia_ObjIsAnd(pObj) ); + Lit0 = Cbs3_ManToSolver1_rec( pSol, p, Gia_ObjFaninId0(pObj, iObj), Depth - Gia_ObjFaninC0(pObj) ); + Lit1 = Cbs3_ManToSolver1_rec( pSol, p, Gia_ObjFaninId1(pObj, iObj), Depth - Gia_ObjFaninC1(pObj) ); + Cbs3_ManAddAnd( pSol, pObj->Value, Lit0 ^ Gia_ObjFaninC0(pObj), Lit1 ^ Gia_ObjFaninC1(pObj) ); + return pObj->Value; +} +static inline int Cbs3_ManToSolver1( Cbs3_Man_t * pSol, Gia_Man_t * p, Gia_Obj_t * pRoot, int nRestarts, int Depth ) +{ + //abctime clk = Abc_Clock(); + assert( Gia_ObjIsCo(pRoot) ); + Cbs3_ManReset( pSol ); + Gia_ManIncrementTravId( p ); + Cbs3_ManToSolver1_rec( pSol, p, Gia_ObjFaninId0p(p, pRoot), Depth ); + Cbs3_ManGrow( pSol ); + Cbs3_ActReset( pSol ); + //pSol->timeSatLoad += Abc_Clock() - clk; + return Cbs3_ManSolve( pSol, Gia_ObjFanin0Copy(pRoot), nRestarts ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManPrepare( Cbs3_Man_t * p ) +{ + int x, x0, x1; + Vec_WecInit( &p->vImps, Abc_Var2Lit(p->nVars, 0) ); + Vec_IntForEachEntryDoubleStart( &p->vFans, x0, x1, x, 2 ) + if ( x0 ) Cbs3_ManAddConstr( p, x, x0, x1 ); +} +static inline int Cbs3_ManAddNode( Cbs3_Man_t * p, int iGiaObj, int iLit0, int iLit1 ) +{ + assert( Vec_IntSize(&p->vMap) == p->nVars ); + Vec_IntPush( &p->vMap, iGiaObj ); + Vec_IntPush( &p->vRef, Gia_ObjRefNumId(p->pAig, iGiaObj) ); + Vec_IntPushTwo( &p->vFans, iLit0, iLit1 ); + return Abc_Var2Lit( p->nVars++, 0 ); +} +static inline int Cbs3_ManToSolver2_rec( Cbs3_Man_t * pSol, Gia_Man_t * p, int iObj, int Depth ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); int Lit0, Lit1; + if ( Gia_ObjUpdateTravIdCurrentId(p, iObj) ) + return pObj->Value; + if ( Gia_ObjIsCi(pObj) || Depth == 0 ) + return pObj->Value = Cbs3_ManAddNode(pSol, iObj, 0, 0); + assert( Gia_ObjIsAnd(pObj) ); + Lit0 = Cbs3_ManToSolver2_rec( pSol, p, Gia_ObjFaninId0(pObj, iObj), Depth - Gia_ObjFaninC0(pObj) ); + Lit1 = Cbs3_ManToSolver2_rec( pSol, p, Gia_ObjFaninId1(pObj, iObj), Depth - Gia_ObjFaninC1(pObj) ); + return pObj->Value = Cbs3_ManAddNode(pSol, iObj, Lit0 ^ Gia_ObjFaninC0(pObj), Lit1 ^ Gia_ObjFaninC1(pObj)); +} +static inline int Cbs3_ManToSolver2( Cbs3_Man_t * pSol, Gia_Man_t * p, Gia_Obj_t * pRoot, int nRestarts, int Depth ) +{ + //abctime clk = Abc_Clock(); + assert( Gia_ObjIsCo(pRoot) ); + Cbs3_ManReset( pSol ); + Gia_ManIncrementTravId( p ); + Cbs3_ManToSolver2_rec( pSol, p, Gia_ObjFaninId0p(p, pRoot), Depth ); + Cbs3_ManGrow( pSol ); + Cbs3_ManPrepare( pSol ); + Cbs3_ActReset( pSol ); + //pSol->timeSatLoad += Abc_Clock() - clk; + return Cbs3_ManSolve( pSol, Gia_ObjFanin0Copy(pRoot), nRestarts ); +} + + +/**Function************************************************************* + + Synopsis [Procedure to test the new SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cbs3_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, int nRestarts, Vec_Str_t ** pvStatus, int fVerbose ) +{ + extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); + Cbs3_Man_t * p; + Vec_Int_t * vCex, * vVisit, * vCexStore; + Vec_Str_t * vStatus; + Gia_Obj_t * pRoot; + int i, status; // 1 = unsat, 0 = sat, -1 = undec + abctime clk, clkTotal = Abc_Clock(); + //assert( Gia_ManRegNum(pAig) == 0 ); + Gia_ManCreateRefs( pAig ); + //Gia_ManLevelNum( pAig ); + // create logic network + p = Cbs3_ManAlloc( pAig ); + p->Pars.nBTLimit = nConfs; + p->Pars.nRestLimit = nRestarts; + // create resulting data-structures + vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); + vCexStore = Vec_IntAlloc( 10000 ); + vVisit = Vec_IntAlloc( 100 ); + vCex = Cbs3_ReadModel( p ); + // solve for each output + Gia_ManForEachCo( pAig, pRoot, i ) + { + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) ) + { + Vec_IntClear( vCex ); + Vec_StrPush( vStatus, (char)(!Gia_ObjFaninC0(pRoot)) ); + if ( Gia_ObjFaninC0(pRoot) ) // const1 + Cec_ManSatAddToStore( vCexStore, vCex, i ); // trivial counter-example + continue; + } + clk = Abc_Clock(); + status = Cbs3_ManToSolver2( p, pAig, pRoot, p->Pars.nRestLimit, 10000 ); + Vec_StrPush( vStatus, (char)status ); + if ( status == -1 ) + { + p->nSatUndec++; + p->nConfUndec += p->Pars.nBTThis; + Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout + p->timeSatUndec += Abc_Clock() - clk; + continue; + } + if ( status == 1 ) + { + p->nSatUnsat++; + p->nConfUnsat += p->Pars.nBTThis; + p->timeSatUnsat += Abc_Clock() - clk; + continue; + } + p->nSatSat++; + p->nConfSat += p->Pars.nBTThis; + //Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit ); + Cec_ManSatAddToStore( vCexStore, vCex, i ); + p->timeSatSat += Abc_Clock() - clk; + } + Vec_IntFree( vVisit ); + p->nSatTotal = Gia_ManPoNum(pAig); + p->timeTotal = Abc_Clock() - clkTotal; + if ( fVerbose ) + Cbs3_ManSatPrintStats( p ); + if ( fVerbose ) + { + printf( "Prop1 = %d. Prop2 = %d. Prop3 = %d. ClaConf = %d. FailJ = %d. FailC = %d. ", p->nPropCalls[0], p->nPropCalls[1], p->nPropCalls[2], p->nClauseConf, p->nFails[0], p->nFails[1] ); + printf( "Mem usage %.2f MB.\n", 1.0*Cbs3_ManMemory(p)/(1<<20) ); + //Abc_PrintTime( 1, "JFront", p->timeJFront ); + //Abc_PrintTime( 1, "Loading", p->timeSatLoad ); + //printf( "Decisions = %d.\n", p->nDecs ); + } + Cbs3_ManStop( p ); + *pvStatus = vStatus; + return vCexStore; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaCSatP.c b/abc/src/aig/gia/giaCSatP.c new file mode 100644 index 00000000000..00ab880b248 --- /dev/null +++ b/abc/src/aig/gia/giaCSatP.c @@ -0,0 +1,1209 @@ +/**CFile**************************************************************** + + FileName [giaCSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [A simple circuit-based solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaCSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "giaCSatP.h" + +ABC_NAMESPACE_IMPL_START + + +//#define gia_assert(exp) ((void)0) +//#define gia_assert(exp) (assert(exp)) + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +static inline int CbsP_VarIsAssigned( Gia_Obj_t * pVar ) { return pVar->fMark0; } +static inline void CbsP_VarAssign( Gia_Obj_t * pVar ) { assert(!pVar->fMark0); pVar->fMark0 = 1; } +static inline void CbsP_VarUnassign( CbsP_Man_t * pMan, Gia_Obj_t * pVar ) { assert(pVar->fMark0); pVar->fMark0 = 0; pVar->fMark1 = 0; pMan->vValue->pArray[Gia_ObjId(pMan->pAig,pVar)] = ~0; } +static inline int CbsP_VarValue( Gia_Obj_t * pVar ) { assert(pVar->fMark0); return pVar->fMark1; } +static inline void CbsP_VarSetValue( Gia_Obj_t * pVar, int v ) { assert(pVar->fMark0); pVar->fMark1 = v; } +static inline int CbsP_VarIsJust( Gia_Obj_t * pVar ) { return Gia_ObjIsAnd(pVar) && !CbsP_VarIsAssigned(Gia_ObjFanin0(pVar)) && !CbsP_VarIsAssigned(Gia_ObjFanin1(pVar)); } +static inline int CbsP_VarFanin0Value( Gia_Obj_t * pVar ) { return !CbsP_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (CbsP_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); } +static inline int CbsP_VarFanin1Value( Gia_Obj_t * pVar ) { return !CbsP_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (CbsP_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); } + +static inline int CbsP_VarDecLevel( CbsP_Man_t * p, Gia_Obj_t * pVar ) { int Value = p->vValue->pArray[Gia_ObjId(p->pAig,pVar)]; assert( Value != ~0 ); return Vec_IntEntry(p->vLevReas, 3*Value); } +static inline Gia_Obj_t * CbsP_VarReason0( CbsP_Man_t * p, Gia_Obj_t * pVar ) { int Value = p->vValue->pArray[Gia_ObjId(p->pAig,pVar)]; assert( Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*Value+1); } +static inline Gia_Obj_t * CbsP_VarReason1( CbsP_Man_t * p, Gia_Obj_t * pVar ) { int Value = p->vValue->pArray[Gia_ObjId(p->pAig,pVar)]; assert( Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*Value+2); } +static inline int CbsP_ClauseDecLevel( CbsP_Man_t * p, int hClause ) { return CbsP_VarDecLevel( p, p->pClauses.pData[hClause] ); } + +#define CbsP_QueForEachEntry( Que, pObj, i ) \ + for ( i = (Que).iHead; (i < (Que).iTail) && ((pObj) = (Que).pData[i]); i++ ) + +#define CbsP_ClauseForEachVar( p, hClause, pObj ) \ + for ( (p)->pIter = (p)->pClauses.pData + hClause; (pObj = *pIter); (p)->pIter++ ) +#define CbsP_ClauseForEachVar1( p, hClause, pObj ) \ + for ( (p)->pIter = (p)->pClauses.pData+hClause+1; (pObj = *pIter); (p)->pIter++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets default values of the parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CbsP_SetDefaultParams( CbsP_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(CbsP_Par_t) ); + pPars->nBTLimit = 1000; // limit on the number of conflicts + pPars->nJustLimit = 100; // limit on the size of justification queue + pPars->fUseHighest = 1; // use node with the highest ID + pPars->fUseLowest = 0; // use node with the highest ID + pPars->fUseMaxFF = 0; // use node with the largest fanin fanout + pPars->fVerbose = 1; // print detailed statistics + + pPars->fUseProved = 1; + + + pPars->nJscanThis = 0; + pPars->nRscanThis = 0; + pPars->maxJscanUndec = 0; + pPars->maxRscanUndec = 0; + pPars->maxJscanSolved = 0; + pPars->maxRscanSolved = 0; + + + pPars->accJscanSat = 0; + pPars->accJscanUnsat = 0; + pPars->accJscanUndec = 0; + pPars->accRscanSat = 0; + pPars->accRscanUnsat = 0; + pPars->accRscanUndec = 0; + pPars->nSat = 0; + pPars->nUnsat = 0; + pPars->nUndec = 0; + + pPars->nJscanLimit = 100; + pPars->nRscanLimit = 100; + pPars->nPropLimit = 500; +} +void CbsP_ManSetConflictNum( CbsP_Man_t * p, int Num ) +{ + p->Pars.nBTLimit = Num; +} + +static inline void CbsP_UpdateRecord( CbsP_Par_t * pPars, int res ){ + if( CBS_UNDEC == res ){ + pPars->nUndec ++ ; + if( pPars-> maxJscanUndec < pPars->nJscanThis ) + pPars-> maxJscanUndec = pPars->nJscanThis; + if( pPars-> maxRscanUndec < pPars->nRscanThis ) + pPars-> maxRscanUndec = pPars->nRscanThis; + if( pPars-> maxPropUndec < pPars->nPropThis ) + pPars-> maxPropUndec = pPars->nPropThis; + + pPars->accJscanUndec += pPars->nJscanThis; + pPars->accRscanUndec += pPars->nRscanThis; + pPars-> accPropUndec += pPars->nPropThis; + } else { + if( pPars->maxJscanSolved < pPars->nJscanThis ) + pPars->maxJscanSolved = pPars->nJscanThis; + if( pPars->maxRscanSolved < pPars->nRscanThis ) + pPars->maxRscanSolved = pPars->nRscanThis; + if( pPars-> maxPropSolved < pPars->nPropThis ) + pPars-> maxPropSolved = pPars->nPropThis; + if( CBS_SAT == res ){ + pPars->nSat ++ ; + pPars->accJscanSat += pPars->nJscanThis; + pPars->accRscanSat += pPars->nRscanThis; + pPars-> accPropSat += pPars->nPropThis; + } else + if( CBS_UNSAT == res ){ + pPars->nUnsat ++ ; + pPars->accJscanUnsat += pPars->nJscanThis; + pPars->accRscanUnsat += pPars->nRscanThis; + pPars-> accPropUnsat += pPars->nPropThis; + } + } + +} + +void CbsP_PrintRecord( CbsP_Par_t * pPars ){ + printf("max of solved: jscan# %13d rscan %13d prop %13d\n" , pPars->maxJscanSolved, pPars->maxRscanSolved , pPars->maxPropSolved ); + printf("max of undec: jscan# %13d rscan %13d prop %13d\n" , pPars->maxJscanUndec , pPars->maxRscanUndec , pPars->maxPropUndec ); + printf("acc of sat: jscan# %13ld rscan %13ld prop %13ld\n", pPars->accJscanSat , pPars->accRscanSat , pPars->accPropSat ); + printf("acc of unsat: jscan# %13ld rscan %13ld prop %13ld\n", pPars->accJscanUnsat , pPars->accRscanUnsat , pPars->accPropUnsat ); + printf("acc of undec: jscan# %13ld rscan %13ld prop %13ld\n", pPars->accJscanUndec , pPars->accRscanUndec , pPars->accPropUndec ); + if( pPars->nSat ) + printf("avg of sat: jscan# %13ld rscan %13ld prop %13ld\n", pPars->accJscanSat / pPars->nSat , pPars->accRscanSat / pPars->nSat , pPars->accPropSat / pPars->nSat ); + if( pPars->nUnsat ) + printf("avg of unsat: jscan# %13ld rscan %13ld prop %13ld\n", pPars->accJscanUnsat / pPars->nUnsat , pPars->accRscanUnsat / pPars->nUnsat , pPars->accPropUnsat / pPars->nUnsat ); + if( pPars->nUndec ) + printf("avg of undec: jscan# %13ld rscan %13ld prop %13ld\n", pPars->accJscanUndec / pPars->nUndec , pPars->accRscanUndec / pPars->nUndec , pPars->accPropUndec / pPars->nUndec ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +CbsP_Man_t * CbsP_ManAlloc( Gia_Man_t * pGia ) +{ + CbsP_Man_t * p; + p = ABC_CALLOC( CbsP_Man_t, 1 ); + p->pProp.nSize = p->pJust.nSize = p->pClauses.nSize = 10000; + p->pProp.pData = ABC_ALLOC( Gia_Obj_t *, p->pProp.nSize ); + p->pJust.pData = ABC_ALLOC( Gia_Obj_t *, p->pJust.nSize ); + p->pClauses.pData = ABC_ALLOC( Gia_Obj_t *, p->pClauses.nSize ); + p->pClauses.iHead = p->pClauses.iTail = 1; + p->vModel = Vec_IntAlloc( 1000 ); + p->vLevReas = Vec_IntAlloc( 1000 ); + p->vTemp = Vec_PtrAlloc( 1000 ); + p->pAig = pGia; + p->vValue = Vec_IntAlloc( Gia_ManObjNum(pGia) ); + Vec_IntFill( p->vValue, Gia_ManObjNum(pGia), ~0 ); + //memset( p->vValue->pArray, (unsigned) ~0, sizeof(int) * Gia_ManObjNum(pGia) ); + CbsP_SetDefaultParams( &p->Pars ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CbsP_ManStop( CbsP_Man_t * p ) +{ + Vec_IntFree( p->vLevReas ); + Vec_IntFree( p->vModel ); + Vec_PtrFree( p->vTemp ); + Vec_IntFree( p->vValue ); + ABC_FREE( p->pClauses.pData ); + ABC_FREE( p->pProp.pData ); + ABC_FREE( p->pJust.pData ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Returns satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * CbsP_ReadModel( CbsP_Man_t * p ) +{ + return p->vModel; +} + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the solver is out of limits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +static inline int CbsP_ManCheckPropLimits( CbsP_Man_t * p ) +{ + return p->Pars.nPropThis > p->Pars.nPropLimit; +} +static inline int CbsP_ManCheckLimits( CbsP_Man_t * p ) +{ + return CbsP_ManCheckPropLimits(p) || p->Pars.nJscanThis > p->Pars.nJscanLimit || p->Pars.nRscanThis > p->Pars.nRscanLimit || p->Pars.nJustThis > p->Pars.nJustLimit || p->Pars.nBTThis > p->Pars.nBTLimit; +} + +/**Function************************************************************* + + Synopsis [Saves the satisfying assignment as an array of literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_ManSaveModel( CbsP_Man_t * p, Vec_Int_t * vCex ) +{ + Gia_Obj_t * pVar; + int i; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + CbsP_QueForEachEntry( p->pProp, pVar, i ) + if ( Gia_ObjIsCi(pVar) ) + Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !CbsP_VarValue(pVar)) ); +// Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjCioId(pVar), !CbsP_VarValue(pVar)) ); +} +static inline void CbsP_ManSaveModelAll( CbsP_Man_t * p, Vec_Int_t * vCex ) +{ + Gia_Obj_t * pVar; + int i; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + CbsP_QueForEachEntry( p->pProp, pVar, i ) + Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !CbsP_VarValue(pVar)) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_QueIsEmpty( CbsP_Que_t * p ) +{ + return p->iHead == p->iTail; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_QuePush( CbsP_Que_t * p, Gia_Obj_t * pObj ) +{ + assert( !Gia_IsComplement(pObj) ); + if ( p->iTail == p->nSize ) + { + p->nSize *= 2; + p->pData = ABC_REALLOC( Gia_Obj_t *, p->pData, p->nSize ); + } + p->pData[p->iTail++] = pObj; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the object in the queue.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_QueHasNode( CbsP_Que_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pTemp; + int i; + CbsP_QueForEachEntry( *p, pTemp, i ) + if ( pTemp == pObj ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_QueStore( CbsP_Que_t * p, int * piHeadOld, int * piTailOld ) +{ + int i; + *piHeadOld = p->iHead; + *piTailOld = p->iTail; + for ( i = *piHeadOld; i < *piTailOld; i++ ) + CbsP_QuePush( p, p->pData[i] ); + p->iHead = *piTailOld; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_QueRestore( CbsP_Que_t * p, int iHeadOld, int iTailOld ) +{ + p->iHead = iHeadOld; + p->iTail = iTailOld; +} + +/**Function************************************************************* + + Synopsis [Finalized the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_QueFinish( CbsP_Que_t * p ) +{ + int iHeadOld = p->iHead; + assert( p->iHead < p->iTail ); + CbsP_QuePush( p, NULL ); + p->iHead = p->iTail; + return iHeadOld; +} + + +/**Function************************************************************* + + Synopsis [Max number of fanins fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_VarFaninFanoutMax( CbsP_Man_t * p, Gia_Obj_t * pObj ) +{ + int Count0, Count1; + assert( !Gia_IsComplement(pObj) ); + assert( Gia_ObjIsAnd(pObj) ); + Count0 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin0(pObj) ); + Count1 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin1(pObj) ); + return Abc_MaxInt( Count0, Count1 ); +} + +/**Function************************************************************* + + Synopsis [Find variable with the highest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * CbsP_ManDecideHighest( CbsP_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i; + CbsP_QueForEachEntry( p->pJust, pObj, i ) + if ( pObjMax == NULL || pObjMax < pObj ) + pObjMax = pObj; + return pObjMax; +} + +/**Function************************************************************* + + Synopsis [Find variable with the lowest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * CbsP_ManDecideLowest( CbsP_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMin = NULL; + int i; + CbsP_QueForEachEntry( p->pJust, pObj, i ) + if ( pObjMin == NULL || pObjMin > pObj ) + pObjMin = pObj; + return pObjMin; +} + +/**Function************************************************************* + + Synopsis [Find variable with the maximum number of fanin fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * CbsP_ManDecideMaxFF( CbsP_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i, iMaxFF = 0, iCurFF; + assert( p->pAig->pRefs != NULL ); + CbsP_QueForEachEntry( p->pJust, pObj, i ) + { + iCurFF = CbsP_VarFaninFanoutMax( p, pObj ); + assert( iCurFF > 0 ); + if ( iMaxFF < iCurFF ) + { + iMaxFF = iCurFF; + pObjMax = pObj; + } + } + return pObjMax; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_ManCancelUntil( CbsP_Man_t * p, int iBound ) +{ + Gia_Obj_t * pVar; + int i; + assert( iBound <= p->pProp.iTail ); + p->pProp.iHead = iBound; + CbsP_QueForEachEntry( p->pProp, pVar, i ) + CbsP_VarUnassign( p, pVar ); + p->pProp.iTail = iBound; + Vec_IntShrink( p->vLevReas, 3*iBound ); +} + +//int s_Counter = 0; + +/**Function************************************************************* + + Synopsis [Assigns the variables a value.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_ManAssign( CbsP_Man_t * p, Gia_Obj_t * pObj, int Level, Gia_Obj_t * pRes0, Gia_Obj_t * pRes1 ) +{ + Gia_Obj_t * pObjR = Gia_Regular(pObj); + assert( Gia_ObjIsCand(pObjR) ); + assert( !CbsP_VarIsAssigned(pObjR) ); + CbsP_VarAssign( pObjR ); + CbsP_VarSetValue( pObjR, !Gia_IsComplement(pObj) ); + assert( p->vValue->pArray[Gia_ObjId(p->pAig,pObjR)] == ~0 ); + p->vValue->pArray[Gia_ObjId(p->pAig,pObjR)] = p->pProp.iTail; + CbsP_QuePush( &p->pProp, pObjR ); + Vec_IntPush( p->vLevReas, Level ); + Vec_IntPush( p->vLevReas, pRes0 ? pRes0-pObjR : 0 ); + Vec_IntPush( p->vLevReas, pRes1 ? pRes1-pObjR : 0 ); + assert( Vec_IntSize(p->vLevReas) == 3 * p->pProp.iTail ); + if( pRes0 ) + p->Pars.nPropThis ++ ; +// s_Counter++; +// s_Counter = Abc_MaxIntInt( s_Counter, Vec_IntSize(p->vLevReas)/3 ); +} + + +/**Function************************************************************* + + Synopsis [Returns clause size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_ManClauseSize( CbsP_Man_t * p, int hClause ) +{ + CbsP_Que_t * pQue = &(p->pClauses); + Gia_Obj_t ** pIter; + for ( pIter = pQue->pData + hClause; *pIter; pIter++ ); + return pIter - pQue->pData - hClause ; +} + +/**Function************************************************************* + + Synopsis [Prints conflict clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_ManPrintClause( CbsP_Man_t * p, int Level, int hClause ) +{ + CbsP_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj; + int i; + assert( CbsP_QueIsEmpty( pQue ) ); + printf( "Level %2d : ", Level ); + for ( i = hClause; (pObj = pQue->pData[i]); i++ ) + printf( "%d=%d(%d) ", Gia_ObjId(p->pAig, pObj), CbsP_VarValue(pObj), CbsP_VarDecLevel(p, pObj) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints conflict clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_ManPrintClauseNew( CbsP_Man_t * p, int Level, int hClause ) +{ + CbsP_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj; + int i; + assert( CbsP_QueIsEmpty( pQue ) ); + printf( "Level %2d : ", Level ); + for ( i = hClause; (pObj = pQue->pData[i]); i++ ) + printf( "%c%d ", CbsP_VarValue(pObj)? '+':'-', Gia_ObjId(p->pAig, pObj) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Returns conflict clause.] + + Description [Performs conflict analysis.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_ManDeriveReason( CbsP_Man_t * p, int Level ) +{ + CbsP_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj, * pReason; + int i, k, iLitLevel; + assert( pQue->pData[pQue->iHead] == NULL ); + assert( pQue->iHead + 1 < pQue->iTail ); +/* + for ( i = pQue->iHead + 1; i < pQue->iTail; i++ ) + { + pObj = pQue->pData[i]; + assert( pObj->fMark0 == 1 ); + } +*/ + // compact literals + Vec_PtrClear( p->vTemp ); + for ( i = k = pQue->iHead + 1; i < pQue->iTail; i++ ) + { + pObj = pQue->pData[i]; + if ( !pObj->fMark0 ) // unassigned - seen again + continue; + // assigned - seen first time + pObj->fMark0 = 0; + Vec_PtrPush( p->vTemp, pObj ); + // check decision level + iLitLevel = CbsP_VarDecLevel( p, pObj ); + if ( iLitLevel < Level ) + { + pQue->pData[k++] = pObj; + continue; + } + assert( iLitLevel == Level ); + pReason = CbsP_VarReason0( p, pObj ); + if ( pReason == pObj ) // no reason + { + //assert( pQue->pData[pQue->iHead] == NULL ); + pQue->pData[pQue->iHead] = pObj; + continue; + } + CbsP_QuePush( pQue, pReason ); + pReason = CbsP_VarReason1( p, pObj ); + if ( pReason != pObj ) // second reason + CbsP_QuePush( pQue, pReason ); + } + assert( pQue->pData[pQue->iHead] != NULL ); + pQue->iTail = k; + // clear the marks + Vec_PtrForEachEntry( Gia_Obj_t *, p->vTemp, pObj, i ) + pObj->fMark0 = 1; +} + +/**Function************************************************************* + + Synopsis [Returns conflict clause.] + + Description [Performs conflict analysis.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_ManAnalyze( CbsP_Man_t * p, int Level, Gia_Obj_t * pVar, Gia_Obj_t * pFan0, Gia_Obj_t * pFan1 ) +{ + CbsP_Que_t * pQue = &(p->pClauses); + assert( CbsP_VarIsAssigned(pVar) ); + assert( CbsP_VarIsAssigned(pFan0) ); + assert( pFan1 == NULL || CbsP_VarIsAssigned(pFan1) ); + assert( CbsP_QueIsEmpty( pQue ) ); + CbsP_QuePush( pQue, NULL ); + CbsP_QuePush( pQue, pVar ); + CbsP_QuePush( pQue, pFan0 ); + if ( pFan1 ) + CbsP_QuePush( pQue, pFan1 ); + CbsP_ManDeriveReason( p, Level ); + return CbsP_QueFinish( pQue ); +} + + +/**Function************************************************************* + + Synopsis [Performs resolution of two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_ManResolve( CbsP_Man_t * p, int Level, int hClause0, int hClause1 ) +{ + CbsP_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj; + int i, LevelMax = -1, LevelCur; + assert( pQue->pData[hClause0] != NULL ); + assert( pQue->pData[hClause0] == pQue->pData[hClause1] ); +/* + for ( i = hClause0 + 1; (pObj = pQue->pData[i]); i++ ) + assert( pObj->fMark0 == 1 ); + for ( i = hClause1 + 1; (pObj = pQue->pData[i]); i++ ) + assert( pObj->fMark0 == 1 ); +*/ + assert( CbsP_QueIsEmpty( pQue ) ); + CbsP_QuePush( pQue, NULL ); + for ( i = hClause0 + 1; (pObj = pQue->pData[i]); i++ ) + { + if ( !pObj->fMark0 ) // unassigned - seen again + continue; + // assigned - seen first time + pObj->fMark0 = 0; + CbsP_QuePush( pQue, pObj ); + p->Pars.nRscanThis ++ ; + LevelCur = CbsP_VarDecLevel( p, pObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + for ( i = hClause1 + 1; (pObj = pQue->pData[i]); i++ ) + { + if ( !pObj->fMark0 ) // unassigned - seen again + continue; + // assigned - seen first time + pObj->fMark0 = 0; + CbsP_QuePush( pQue, pObj ); + p->Pars.nRscanThis ++ ; + LevelCur = CbsP_VarDecLevel( p, pObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + for ( i = pQue->iHead + 1; i < pQue->iTail; i++ ) + pQue->pData[i]->fMark0 = 1; + CbsP_ManDeriveReason( p, LevelMax ); + return CbsP_QueFinish( pQue ); +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns clause handle if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_ManPropagateOne( CbsP_Man_t * p, Gia_Obj_t * pVar, int Level ) +{ + int Value0, Value1; + assert( !Gia_IsComplement(pVar) ); + assert( CbsP_VarIsAssigned(pVar) ); + if ( Gia_ObjIsCi(pVar) ) + return 0; + assert( Gia_ObjIsAnd(pVar) ); + Value0 = CbsP_VarFanin0Value(pVar); + Value1 = CbsP_VarFanin1Value(pVar); + if ( CbsP_VarValue(pVar) ) + { // value is 1 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + { + if ( Value0 == 0 && Value1 != 0 ) + return CbsP_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), NULL ); + if ( Value0 != 0 && Value1 == 0 ) + return CbsP_ManAnalyze( p, Level, pVar, Gia_ObjFanin1(pVar), NULL ); + assert( Value0 == 0 && Value1 == 0 ); + return CbsP_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); + } + if ( Value0 == 2 ) // first is unassigned + CbsP_ManAssign( p, Gia_ObjChild0(pVar), Level, pVar, NULL ); + if ( Value1 == 2 ) // first is unassigned + CbsP_ManAssign( p, Gia_ObjChild1(pVar), Level, pVar, NULL ); + return 0; + } + // value is 0 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 0; + if ( Value0 == 1 && Value1 == 1 ) // both are 1 + return CbsP_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); + if ( Value0 == 1 || Value1 == 1 ) // one is 1 + { + if ( Value0 == 2 ) // first is unassigned + CbsP_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) ); + if ( Value1 == 2 ) // second is unassigned + CbsP_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)), Level, pVar, Gia_ObjFanin0(pVar) ); + return 0; + } + assert( CbsP_VarIsJust(pVar) ); + assert( !CbsP_QueHasNode( &p->pJust, pVar ) ); + CbsP_QuePush( &p->pJust, pVar ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_ManPropagateTwo( CbsP_Man_t * p, Gia_Obj_t * pVar, int Level ) +{ + int Value0, Value1; + assert( !Gia_IsComplement(pVar) ); + assert( Gia_ObjIsAnd(pVar) ); + assert( CbsP_VarIsAssigned(pVar) ); + assert( !CbsP_VarValue(pVar) ); + Value0 = CbsP_VarFanin0Value(pVar); + Value1 = CbsP_VarFanin1Value(pVar); + // value is 0 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 0; + if ( Value0 == 1 && Value1 == 1 ) // both are 1 + return CbsP_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); + assert( Value0 == 1 || Value1 == 1 ); + if ( Value0 == 2 ) // first is unassigned + CbsP_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) ); + if ( Value1 == 2 ) // first is unassigned + CbsP_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)), Level, pVar, Gia_ObjFanin0(pVar) ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Propagates all variables.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CbsP_ManPropagate( CbsP_Man_t * p, int Level ) +{ + int hClause; + Gia_Obj_t * pVar; + int i, k; + while ( 1 ) + { + CbsP_QueForEachEntry( p->pProp, pVar, i ) + { + if ( (hClause = CbsP_ManPropagateOne( p, pVar, Level )) ) + return hClause; + if( CbsP_ManCheckPropLimits(p) ) + return 0; + } + p->pProp.iHead = p->pProp.iTail; + k = p->pJust.iHead; + CbsP_QueForEachEntry( p->pJust, pVar, i ) + { + if ( CbsP_VarIsJust( pVar ) ) + p->pJust.pData[k++] = pVar; + else if ( (hClause = CbsP_ManPropagateTwo( p, pVar, Level )) ) + return hClause; + if( CbsP_ManCheckPropLimits(p) ) + return 0; + } + if ( k == p->pJust.iTail ) + break; + p->pJust.iTail = k; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Solve the problem recursively.] + + Description [Returns learnt clause if unsat, NULL if sat or undecided.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CbsP_ManSolve_rec( CbsP_Man_t * p, int Level ) +{ + CbsP_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pVar = NULL, * pDecVar; + int hClause, hLearn0, hLearn1; + int iPropHead, iJustHead, iJustTail; + // propagate assignments + assert( !CbsP_QueIsEmpty(&p->pProp) ); + if ( (hClause = CbsP_ManPropagate( p, Level )) ) + return hClause; + + // quit using resource limits + if ( CbsP_ManCheckLimits( p ) ) + return 0; + // check for satisfying assignment + assert( CbsP_QueIsEmpty(&p->pProp) ); + if ( CbsP_QueIsEmpty(&p->pJust) ) + return 0; + p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); + // remember the state before branching + iPropHead = p->pProp.iHead; + CbsP_QueStore( &p->pJust, &iJustHead, &iJustTail ); + p->Pars.nJscanThis += iJustTail - iJustHead; + if ( CbsP_ManCheckLimits( p ) ) + return 0; + // find the decision variable + if ( p->Pars.fUseHighest ) + pVar = CbsP_ManDecideHighest( p ); + else if ( p->Pars.fUseLowest ) + pVar = CbsP_ManDecideLowest( p ); + else if ( p->Pars.fUseMaxFF ) + pVar = CbsP_ManDecideMaxFF( p ); + else assert( 0 ); + assert( CbsP_VarIsJust( pVar ) ); + // chose decision variable using fanout count + + if ( Gia_ObjRefNum(p->pAig, Gia_ObjFanin0(pVar)) > Gia_ObjRefNum(p->pAig, Gia_ObjFanin1(pVar)) ) + pDecVar = Gia_Not(Gia_ObjChild0(pVar)); + else + pDecVar = Gia_Not(Gia_ObjChild1(pVar)); + +// pDecVar = Gia_NotCond( Gia_Regular(pDecVar), Gia_Regular(pDecVar)->fPhase ); +// pDecVar = Gia_Not(pDecVar); + // decide on first fanin + CbsP_ManAssign( p, pDecVar, Level+1, NULL, NULL ); + if ( !(hLearn0 = CbsP_ManSolve_rec( p, Level+1 )) ) + return 0; + if ( CbsP_ManCheckLimits( p ) ) + return 0; + if ( pQue->pData[hLearn0] != Gia_Regular(pDecVar) ) + return hLearn0; + CbsP_ManCancelUntil( p, iPropHead ); + CbsP_QueRestore( &p->pJust, iJustHead, iJustTail ); + // decide on second fanin + CbsP_ManAssign( p, Gia_Not(pDecVar), Level+1, NULL, NULL ); + if ( !(hLearn1 = CbsP_ManSolve_rec( p, Level+1 )) ) + return 0; + if ( CbsP_ManCheckLimits( p ) ) + return 0; + if ( pQue->pData[hLearn1] != Gia_Regular(pDecVar) ) + return hLearn1; + hClause = CbsP_ManResolve( p, Level, hLearn0, hLearn1 ); +// CbsP_ManPrintClauseNew( p, Level, hClause ); +// if ( Level > CbsP_ClauseDecLevel(p, hClause) ) +// p->Pars.nBTThisNc++; + p->Pars.nBTThis++; + return hClause; +} + +/**Function************************************************************* + + Synopsis [Looking for a satisfying assignment of the node.] + + Description [Assumes that each node has flag pObj->fMark0 set to 0. + Returns 1 if unsatisfiable, 0 if satisfiable, and -1 if undecided. + The node may be complemented. ] + + SideEffects [The two procedures differ in the CEX format.] + + SeeAlso [] + +***********************************************************************/ +int CbsP_ManSolve( CbsP_Man_t * p, Gia_Obj_t * pObj ) +{ + int RetValue = 0; +// s_Counter = 0; + assert( !p->pProp.iHead && !p->pProp.iTail ); + assert( !p->pJust.iHead && !p->pJust.iTail ); + assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 ); + p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0; + CbsP_ManAssign( p, pObj, 0, NULL, NULL ); + if ( !CbsP_ManSolve_rec(p, 0) && !CbsP_ManCheckLimits(p) ) + CbsP_ManSaveModel( p, p->vModel ); + else + RetValue = 1; + CbsP_ManCancelUntil( p, 0 ); + p->pJust.iHead = p->pJust.iTail = 0; + p->pClauses.iHead = p->pClauses.iTail = 1; + p->Pars.nBTTotal += p->Pars.nBTThis; + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); + if ( CbsP_ManCheckLimits( p ) ) + RetValue = -1; +// printf( "%d ", s_Counter ); + return RetValue; +} +int CbsP_ManSolve2( CbsP_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ) +{ + abctime clk = Abc_Clock(); + int RetValue = 0; +// s_Counter = 0; + assert( !p->pProp.iHead && !p->pProp.iTail ); + assert( !p->pJust.iHead && !p->pJust.iTail ); + assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 ); + p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0; + p->Pars.nJscanThis = p->Pars.nRscanThis = p->Pars.nPropThis = 0; + CbsP_ManAssign( p, pObj, 0, NULL, NULL ); + if ( pObj2 ) + CbsP_ManAssign( p, pObj2, 0, NULL, NULL ); + if ( !CbsP_ManSolve_rec(p, 0) && !CbsP_ManCheckLimits(p) ) + CbsP_ManSaveModel( p, p->vModel ); + else + RetValue = 1; + CbsP_ManCancelUntil( p, 0 ); + + p->pJust.iHead = p->pJust.iTail = 0; + p->pClauses.iHead = p->pClauses.iTail = 1; + p->Pars.nBTTotal += p->Pars.nBTThis; + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); + if ( CbsP_ManCheckLimits( p ) ) + RetValue = -1; + + if( CBS_SAT == RetValue ){ + p->nSatSat ++; + p->timeSatSat += Abc_Clock() - clk; + p->nConfSat += p->Pars.nBTThis; + } else + if( CBS_UNSAT == RetValue ){ + p->nSatUnsat ++; + p->timeSatUnsat += Abc_Clock() - clk; + p->nConfUnsat += p->Pars.nBTThis; + } else { + p->nSatUndec ++; + p->timeSatUndec += Abc_Clock() - clk; + p->nConfUndec += p->Pars.nBTThis; + } +// printf( "%d ", s_Counter ); + CbsP_UpdateRecord(&p->Pars,RetValue); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Prints statistics of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CbsP_ManSatPrintStats( CbsP_Man_t * p ) +{ + printf( "CO = %8d ", Gia_ManCoNum(p->pAig) ); + printf( "AND = %8d ", Gia_ManAndNum(p->pAig) ); + printf( "Conf = %6d ", p->Pars.nBTLimit ); + printf( "JustMax = %5d ", p->Pars.nJustLimit ); + printf( "\n" ); + printf( "Unsat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal :0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 ); + ABC_PRTP( "Time", p->timeSatUnsat, p->timeTotal ); + printf( "Sat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatSat, p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal :0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 ); + ABC_PRTP( "Time", p->timeSatSat, p->timeTotal ); + printf( "Undef calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal :0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 ); + ABC_PRTP( "Time", p->timeSatUndec, p->timeTotal ); + ABC_PRT( "Total time", p->timeTotal ); +} + +/**Function************************************************************* + + Synopsis [Procedure to test the new SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * CbsP_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int f0Proved, int fVerbose ) +{ + extern void Gia_ManCollectTest( Gia_Man_t * pAig ); + extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); + CbsP_Man_t * p; + Vec_Int_t * vCex, * vVisit, * vCexStore; + Vec_Str_t * vStatus; + Gia_Obj_t * pRoot; + int i, status; + abctime clk, clkTotal = Abc_Clock(); + assert( Gia_ManRegNum(pAig) == 0 ); +// Gia_ManCollectTest( pAig ); + // prepare AIG + Gia_ManCreateRefs( pAig ); + Gia_ManCleanMark0( pAig ); + Gia_ManCleanMark1( pAig ); + Gia_ManFillValue( pAig ); // maps nodes into trail ids + Gia_ManSetPhase( pAig ); // maps nodes into trail ids + // create logic network + p = CbsP_ManAlloc( pAig ); + p->Pars.nBTLimit = nConfs; + // create resulting data-structures + vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); + vCexStore = Vec_IntAlloc( 10000 ); + vVisit = Vec_IntAlloc( 100 ); + vCex = CbsP_ReadModel( p ); + // solve for each output + Gia_ManForEachCo( pAig, pRoot, i ) + { +// printf( "\n" ); + + Vec_IntClear( vCex ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) ) + { + if ( Gia_ObjFaninC0(pRoot) ) + { +// printf( "Constant 1 output of SRM!!!\n" ); + Cec_ManSatAddToStore( vCexStore, vCex, i ); // trivial counter-example + Vec_StrPush( vStatus, 0 ); + } + else + { +// printf( "Constant 0 output of SRM!!!\n" ); + Vec_StrPush( vStatus, 1 ); + } + continue; + } + clk = Abc_Clock(); + p->Pars.fUseHighest = 1; + p->Pars.fUseLowest = 0; + status = CbsP_ManSolve( p, Gia_ObjChild0(pRoot) ); +// printf( "\n" ); +/* + if ( status == -1 ) + { + p->Pars.fUseHighest = 0; + p->Pars.fUseLowest = 1; + status = CbsP_ManSolve( p, Gia_ObjChild0(pRoot) ); + } +*/ + Vec_StrPush( vStatus, (char)status ); + if ( status == -1 ) + { + p->nSatUndec++; + p->nConfUndec += p->Pars.nBTThis; + Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout + p->timeSatUndec += Abc_Clock() - clk; + continue; + } + if ( status == 1 ) + { + if ( f0Proved ) + Gia_ManPatchCoDriver( pAig, i, 0 ); + p->nSatUnsat++; + p->nConfUnsat += p->Pars.nBTThis; + p->timeSatUnsat += Abc_Clock() - clk; + continue; + } + p->nSatSat++; + p->nConfSat += p->Pars.nBTThis; +// Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit ); + Cec_ManSatAddToStore( vCexStore, vCex, i ); + p->timeSatSat += Abc_Clock() - clk; + } + Vec_IntFree( vVisit ); + p->nSatTotal = Gia_ManPoNum(pAig); + p->timeTotal = Abc_Clock() - clkTotal; + if ( fVerbose ) + CbsP_ManSatPrintStats( p ); +// printf( "RecCalls = %8d. RecClause = %8d. RecNonChro = %8d.\n", p->nRecCall, p->nRecClause, p->nRecNonChro ); + CbsP_ManStop( p ); + *pvStatus = vStatus; + +// printf( "Total number of cex literals = %d. (Ave = %d)\n", +// Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat, +// (Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat)/p->nSatSat ); + return vCexStore; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaCSatP.h b/abc/src/aig/gia/giaCSatP.h new file mode 100644 index 00000000000..4182cd14467 --- /dev/null +++ b/abc/src/aig/gia/giaCSatP.h @@ -0,0 +1,117 @@ +#ifndef ABC__aig__gia__giaCSatP_h +#define ABC__aig__gia__giaCSatP_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "gia.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_HEADER_START + + +typedef struct CbsP_Par_t_ CbsP_Par_t; +struct CbsP_Par_t_ +{ + // conflict limits + int nBTLimit; // limit on the number of conflicts + int nJustLimit; // limit on the size of justification queue + // current parameters + int nBTThis; // number of conflicts + int nBTThisNc; // number of conflicts + int nJustThis; // max size of the frontier + int nBTTotal; // total number of conflicts + int nJustTotal; // total size of the frontier + // decision heuristics + int fUseHighest; // use node with the highest ID + int fUseLowest; // use node with the highest ID + int fUseMaxFF; // use node with the largest fanin fanout + // other + int fVerbose; + int fUseProved; + + // statistics + int nJscanThis; + int nRscanThis; + int nPropThis; + int maxJscanUndec; + int maxRscanUndec; + int maxPropUndec; + int maxJscanSolved; + int maxRscanSolved; + int maxPropSolved; + int nSat, nUnsat, nUndec; + long accJscanSat; + long accJscanUnsat; + long accJscanUndec; + long accRscanSat; + long accRscanUnsat; + long accRscanUndec; + long accPropSat; + long accPropUnsat; + long accPropUndec; + + // other limits + int nJscanLimit; + int nRscanLimit; + int nPropLimit; +}; + +typedef struct CbsP_Que_t_ CbsP_Que_t; +struct CbsP_Que_t_ +{ + int iHead; // beginning of the queue + int iTail; // end of the queue + int nSize; // allocated size + Gia_Obj_t ** pData; // nodes stored in the queue +}; + +typedef struct CbsP_Man_t_ CbsP_Man_t; +struct CbsP_Man_t_ +{ + CbsP_Par_t Pars; // parameters + Gia_Man_t * pAig; // AIG manager + CbsP_Que_t pProp; // propagation queue + CbsP_Que_t pJust; // justification queue + CbsP_Que_t pClauses; // clause queue + Gia_Obj_t ** pIter; // iterator through clause vars + Vec_Int_t * vLevReas; // levels and decisions + Vec_Int_t * vValue; + Vec_Int_t * vModel; // satisfying assignment + Vec_Ptr_t * vTemp; // temporary storage + // SAT calls statistics + int nSatUnsat; // the number of proofs + int nSatSat; // the number of failure + int nSatUndec; // the number of timeouts + int nSatTotal; // the number of calls + // conflicts + int nConfUnsat; // conflicts in unsat problems + int nConfSat; // conflicts in sat problems + int nConfUndec; // conflicts in undec problems + // runtime stats + abctime timeSatUnsat; // unsat + abctime timeSatSat; // sat + abctime timeSatUndec; // undecided + abctime timeTotal; // total runtime +}; + +CbsP_Man_t * CbsP_ManAlloc( Gia_Man_t * pGia ); +void CbsP_ManStop( CbsP_Man_t * p ); +void CbsP_ManSatPrintStats( CbsP_Man_t * p ); +void CbsP_PrintRecord( CbsP_Par_t * pPars ); +int CbsP_ManSolve2( CbsP_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ); + +#define CBS_UNSAT 1 +#define CBS_SAT 0 +#define CBS_UNDEC -1 + +ABC_NAMESPACE_HEADER_END + + +#endif diff --git a/abc/src/aig/gia/giaCTas.c b/abc/src/aig/gia/giaCTas.c index 3dded68b3df..cd0b4f480b5 100644 --- a/abc/src/aig/gia/giaCTas.c +++ b/abc/src/aig/gia/giaCTas.c @@ -1778,6 +1778,7 @@ void Tas_ManSolveMiterNc2( Gia_Man_t * pAig, int nConfs, Gia_Man_t * pAigOld, Ve Tas_ManSatPrintStats( p ); Tas_ManStop( p ); Vec_PtrFree( vPres ); + Vec_StrFree( vStatus ); } diff --git a/abc/src/aig/gia/giaCex.c b/abc/src/aig/gia/giaCex.c index b0e72284f90..d124187309e 100644 --- a/abc/src/aig/gia/giaCex.c +++ b/abc/src/aig/gia/giaCex.c @@ -195,7 +195,7 @@ void Gia_ManCounterExampleValueStart( Gia_Man_t * pGia, Abc_Cex_t * pCex ) pGia->pData2 = ABC_CALLOC( unsigned, Abc_BitWordNum( (pCex->iFrame + 1) * Gia_ManObjNum(pGia) ) ); // the register values in the counter-example should be zero Gia_ManForEachRo( pGia, pObj, k ) - assert( Abc_InfoHasBit(pCex->pData, iBit++) == 0 ); + assert( Abc_InfoHasBit(pCex->pData, iBit) == 0 ), iBit++; // iterate through the timeframes nObjs = Gia_ManObjNum(pGia); for ( i = 0; i <= pCex->iFrame; i++ ) diff --git a/abc/src/aig/gia/giaCut.c b/abc/src/aig/gia/giaCut.c index f70f0fc0829..19e2d8fc9fe 100644 --- a/abc/src/aig/gia/giaCut.c +++ b/abc/src/aig/gia/giaCut.c @@ -20,6 +20,7 @@ #include "gia.h" #include "misc/util/utilTruth.h" +#include "misc/vec/vecHsh.h" ABC_NAMESPACE_IMPL_START @@ -29,7 +30,7 @@ ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// #define GIA_MAX_CUTSIZE 8 -#define GIA_MAX_CUTNUM 51 +#define GIA_MAX_CUTNUM 65 #define GIA_MAX_TT_WORDS ((GIA_MAX_CUTSIZE > 6) ? 1 << (GIA_MAX_CUTSIZE-6) : 1) #define GIA_CUT_NO_LEAF 0xF @@ -602,10 +603,10 @@ void Gia_StoRefObj( Gia_Sto_t * p, int iObj ) } void Gia_StoComputeCuts( Gia_Man_t * pGia ) { - int nCutSize = 6; - int nCutNum = 25; - int fCutMin = 1; - int fTruthMin = 1; + int nCutSize = 8; + int nCutNum = 6; + int fCutMin = 0; + int fTruthMin = 0; int fVerbose = 1; Gia_Sto_t * p = Gia_StoAlloc( pGia, nCutSize, nCutNum, fCutMin, fTruthMin, fVerbose ); Gia_Obj_t * pObj; int i, iObj; @@ -637,6 +638,359 @@ void Gia_StoComputeCuts( Gia_Man_t * pGia ) Gia_StoFree( p ); } + +/**Function************************************************************* + + Synopsis [Extract a given number of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_StoSelectOneCut( Vec_Wec_t * vCuts, int iObj, Vec_Int_t * vCut, int nCutSizeMin ) +{ + Vec_Int_t * vThis = Vec_WecEntry( vCuts, iObj ); + int i, v, * pCut, * pList = Vec_IntArray( vThis ); + if ( pList == NULL ) + return 0; + Vec_IntClear( vCut ); + Sdb_ForEachCut( pList, pCut, i ) + { + if ( pCut[0] < nCutSizeMin ) + continue; + for ( v = 0; v <= pCut[0]; v++ ) + Vec_IntPush( vCut, pCut[v] ); + return 1; + } + return 0; +} +Vec_Wec_t * Gia_ManSelectCuts( Vec_Wec_t * vCuts, int nCuts, int nCutSizeMin ) +{ + Vec_Wec_t * vCutsSel = Vec_WecStart( nCuts ); + int i; srand( time(NULL) ); + for ( i = 0; i < nCuts; i++ ) + while ( !Gia_StoSelectOneCut(vCuts, (rand() | (rand() << 15)) % Vec_WecSize(vCuts), Vec_WecEntry(vCutsSel, i), nCutSizeMin) ); + return vCutsSel; +} +Vec_Wec_t * Gia_ManExtractCuts( Gia_Man_t * pGia, int nCutSize0, int nCuts0, int fVerbose0 ) +{ + int nCutSize = nCutSize0; + int nCutNum = 6; + int fCutMin = 0; + int fTruthMin = 0; + int fVerbose = fVerbose0; + Vec_Wec_t * vCutsSel; + Gia_Sto_t * p = Gia_StoAlloc( pGia, nCutSize, nCutNum, fCutMin, fTruthMin, fVerbose ); + Gia_Obj_t * pObj; int i, iObj; + assert( nCutSize <= GIA_MAX_CUTSIZE ); + assert( nCutNum < GIA_MAX_CUTNUM ); + // prepare references + Gia_ManForEachObj( p->pGia, pObj, iObj ) + Gia_StoRefObj( p, iObj ); + // compute cuts + Gia_StoComputeCutsConst0( p, 0 ); + Gia_ManForEachCiId( p->pGia, iObj, i ) + Gia_StoComputeCutsCi( p, iObj ); + Gia_ManForEachAnd( p->pGia, pObj, iObj ) + Gia_StoComputeCutsNode( p, iObj ); + if ( p->fVerbose ) + { + printf( "Running cut computation with CutSize = %d CutNum = %d CutMin = %s TruthMin = %s\n", + p->nCutSize, p->nCutNum, p->fCutMin ? "yes":"no", p->fTruthMin ? "yes":"no" ); + printf( "CutPair = %.0f ", p->CutCount[0] ); + printf( "Merge = %.0f (%.2f %%) ", p->CutCount[1], 100.0*p->CutCount[1]/p->CutCount[0] ); + printf( "Eval = %.0f (%.2f %%) ", p->CutCount[2], 100.0*p->CutCount[2]/p->CutCount[0] ); + printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] ); + printf( "Cut/Node = %.2f ", p->CutCount[3] / Gia_ManAndNum(p->pGia) ); + printf( "\n" ); + printf( "The number of nodes with cut count over the limit (%d cuts) = %d nodes (out of %d). ", + p->nCutNum, p->nCutsOver, Gia_ManAndNum(pGia) ); + Abc_PrintTime( 0, "Time", Abc_Clock() - p->clkStart ); + } + vCutsSel = Gia_ManSelectCuts( p->vCuts, nCuts0, nCutSize0-1 ); + Gia_StoFree( p ); + return vCutsSel; +} +void Gia_ManCreateWins( Gia_Man_t * pGia, Vec_Wec_t * vCuts ) +{ + Gia_Obj_t * pObj; + Vec_Wec_t * vWins = Vec_WecStart( Gia_ManObjNum(pGia) ); + Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); + Vec_Int_t * vCut; int i, k, Obj, Cut; + Vec_WecForEachLevel( vCuts, vCut, i ) + Vec_IntForEachEntryStart( vCut, Obj, k, 1 ) + Vec_IntPush( Vec_WecEntry(vWins, Obj), i ); + Gia_ManForEachAnd( pGia, pObj, Obj ) + { + Vec_Int_t * vWin = Vec_WecEntry(vWins, Obj); + Vec_Int_t * vWin0 = Vec_WecEntry(vWins, Gia_ObjFaninId0(pObj, Obj)); + Vec_Int_t * vWin1 = Vec_WecEntry(vWins, Gia_ObjFaninId1(pObj, Obj)); + Vec_IntTwoFindCommon( vWin0, vWin1, vTemp ); + Vec_IntForEachEntry( vTemp, Cut, k ) + { + Vec_IntPushUniqueOrder( vWin, Cut ); + Vec_IntPush( Vec_WecEntry(vCuts, Cut), Obj ); + } + } + Vec_WecFree( vWins ); + Vec_IntFree( vTemp ); +} +void Gia_ManPrintWins( Vec_Wec_t * vCuts ) +{ + Vec_Int_t * vCut; int i, k, Obj; + Vec_WecForEachLevel( vCuts, vCut, i ) + { + int nInputs = Vec_IntEntry(vCut, 0); + printf( "Cut %5d : ", i ); + printf( "Supp = %d ", nInputs ); + printf( "Nodes = %d ", Vec_IntSize(vCut) - 1 - nInputs ); + Vec_IntForEachEntryStartStop( vCut, Obj, k, 1, nInputs+1 ) + printf( "%d ", Obj ); + printf( " " ); + Vec_IntForEachEntryStart( vCut, Obj, k, nInputs+1 ) + printf( "%d ", Obj ); + printf( "\n" ); + } +} +void Gia_ManPrintWinStats( Vec_Wec_t * vCuts ) +{ + Vec_Int_t * vCut; int i, nInputs = 0, nNodes = 0; + Vec_WecForEachLevel( vCuts, vCut, i ) + { + nInputs += Vec_IntEntry(vCut, 0); + nNodes += Vec_IntSize(vCut) - 1 - Vec_IntEntry(vCut, 0); + } + printf( "Computed %d windows with average support %.3f and average volume %.3f.\n", + Vec_WecSize(vCuts), 1.0*nInputs/Vec_WecSize(vCuts), 1.0*nNodes/Vec_WecSize(vCuts) ); +} +void Gia_ManExtractTest( Gia_Man_t * pGia ) +{ + extern Vec_Wec_t * Gia_ManExtractCuts2( Gia_Man_t * p, int nCutSize, int nCuts, int fVerbose ); + Vec_Wec_t * vCutsSel = Gia_ManExtractCuts2( pGia, 8, 10000, 1 ); + //Vec_Wec_t * vCutsSel = Gia_ManExtractCuts( pGia, 8, 10000, 1 ); + abctime clk = Abc_Clock(); + Gia_ManCreateWins( pGia, vCutsSel ); + //Gia_ManPrintWins( vCutsSel ); + Gia_ManPrintWinStats( vCutsSel ); + Vec_WecFree( vCutsSel ); + Abc_PrintTime( 0, "Creating windows", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Extract a given number of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_StoCutPrint( int * pCut ) +{ + int v; + printf( "{" ); + for ( v = 1; v <= pCut[0]; v++ ) + printf( " %d", pCut[v] ); + printf( " }\n" ); +} +void Gia_StoPrintCuts( Vec_Int_t * vThis, int iObj, int nCutSize ) +{ + int i, * pCut; + printf( "Cuts of node %d (size = %d):\n", iObj, nCutSize ); + Sdb_ForEachCut( Vec_IntArray(vThis), pCut, i ) + if ( !nCutSize || pCut[0] == nCutSize ) + Gia_StoCutPrint( pCut ); +} +Vec_Wec_t * Gia_ManFilterCuts( Gia_Man_t * pGia, Vec_Wec_t * vStore, int nCutSize, int nCuts ) +{ + abctime clkStart = Abc_Clock(); + Vec_Wec_t * vCutsSel = Vec_WecAlloc( nCuts ); + Vec_Int_t * vLevel, * vCut = Vec_IntAlloc( 10 ); + Vec_Wec_t * vCuts = Vec_WecAlloc( 1000 ); + Hsh_VecMan_t * p = Hsh_VecManStart( 1000 ); int i, s; + Vec_WecForEachLevel( vStore, vLevel, i ) if ( Vec_IntSize(vLevel) ) + { + int v, k, * pCut, Value; + Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) + { + if ( pCut[0] < 2 ) + continue; + + for ( v = 1; v <= pCut[0]; v++ ) + if ( pCut[v] < 9 ) + break; + if ( v <= pCut[0] ) + continue; + + Vec_IntClear( vCut ); + Vec_IntPushArray( vCut, pCut+1, pCut[0] ); + Value = Hsh_VecManAdd( p, vCut ); + if ( Value == Vec_WecSize(vCuts) ) + { + Vec_Int_t * vTemp = Vec_WecPushLevel(vCuts); + Vec_IntPush( vTemp, 0 ); + Vec_IntAppend( vTemp, vCut ); + } + Vec_IntAddToEntry( Vec_WecEntry(vCuts, Value), 0, 1 ); + } + } + printf( "Collected cuts = %d.\n", Vec_WecSize(vCuts) ); + for ( s = 3; s <= nCutSize; s++ ) + Vec_WecForEachLevel( vCuts, vLevel, i ) + if ( Vec_IntSize(vLevel) - 1 == s ) + { + int * pCut = Vec_IntEntryP(vLevel, 1); + int u, v, Value; + for ( u = 0; u < s; u++ ) + { + Vec_IntClear( vCut ); + for ( v = 0; v < s; v++ ) if ( v != u ) + Vec_IntPush( vCut, pCut[v] ); + assert( Vec_IntSize(vCut) == s-1 ); + Value = Hsh_VecManAdd( p, vCut ); + if ( Value < Vec_WecSize(vCuts) ) + Vec_IntAddToEntry( vLevel, 0, Vec_IntEntry(Vec_WecEntry(vCuts, Value), 0) ); + } + } + Hsh_VecManStop( p ); + Vec_IntFree( vCut ); + // collect + Vec_WecSortByFirstInt( vCuts, 1 ); + Vec_WecForEachLevelStop( vCuts, vLevel, i, Abc_MinInt(Vec_WecSize(vCuts), nCuts) ) + Vec_IntAppend( Vec_WecPushLevel(vCutsSel), vLevel ); + Abc_PrintTime( 0, "Cut filtering time", Abc_Clock() - clkStart ); + return vCutsSel; +} +int Gia_ManCountRefs( Gia_Man_t * pGia, Vec_Int_t * vLevel ) +{ + int i, iObj, nRefs = 0; + Vec_IntForEachEntry( vLevel, iObj, i ) + nRefs += Gia_ObjRefNumId(pGia, iObj); + return nRefs; +} +Vec_Wrd_t * Gia_ManGenSims( Gia_Man_t * pGia ) +{ + Vec_Wrd_t * vSims; + Vec_WrdFreeP( &pGia->vSimsPi ); + pGia->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(pGia) ); + vSims = Gia_ManSimPatSim( pGia ); + return vSims; +} +int Gia_ManFindSatDcs( Gia_Man_t * pGia, Vec_Wrd_t * vSims, Vec_Int_t * vLevel ) +{ + int nWords = Vec_WrdSize(pGia->vSimsPi) / Gia_ManCiNum(pGia); + int i, w, iObj, Res = 0, Pres[256] = {0}, nMints = 1 << Vec_IntSize(vLevel); + for ( w = 0; w < 64*nWords; w++ ) + { + int iInMint = 0; + Vec_IntForEachEntry( vLevel, iObj, i ) + if ( Abc_TtGetBit( Vec_WrdEntryP(vSims, iObj*nWords), w ) ) + iInMint |= 1 << i; + Pres[iInMint]++; + } + for ( i = 0; i < nMints; i++ ) + Res += Pres[i] == 0; + return Res; +} + + +int Gia_ManCollectCutDivs( Gia_Man_t * p, Vec_Int_t * vIns ) +{ + Gia_Obj_t * pObj; int i, Res = 0; + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + Vec_IntSort( vIns, 0 ); + + Vec_IntPush( vRes, 0 ); + Vec_IntAppend( vRes, vIns ); + + Gia_ManIncrementTravId( p ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vIns, p, pObj, i ) + Gia_ObjSetTravIdCurrent( p, pObj ); + + Gia_ManForEachAnd( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + continue; + else if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) && Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) + { + if ( !Gia_ObjIsTravIdPrevious(p, pObj) ) + Vec_IntPush( vRes, i ); + Gia_ObjSetTravIdCurrent( p, pObj ); + } +// printf( "Divisors: " ); +// Vec_IntPrint( vRes ); + Res = Vec_IntSize(vRes); + Vec_IntFree( vRes ); + return Res; +} + +void Gia_ManConsiderCuts( Gia_Man_t * pGia, Vec_Wec_t * vCuts ) +{ + Vec_Wrd_t * vSims = Gia_ManGenSims( pGia ); + Vec_Int_t * vLevel; int i; + Gia_ManCreateRefs( pGia ); + Vec_WecForEachLevel( vCuts, vLevel, i ) + { + printf( "Cut %3d ", i ); + printf( "Ref = %3d : ", Vec_IntEntry(vLevel, 0) ); + + Vec_IntShift( vLevel, 1 ); + printf( "Ref = %3d : ", Gia_ManCountRefs(pGia, vLevel) ); + printf( "SDC = %3d : ", Gia_ManFindSatDcs(pGia, vSims, vLevel) ); + printf( "Div = %3d : ", Gia_ManCollectCutDivs(pGia, vLevel) ); + Vec_IntPrint( vLevel ); + Vec_IntShift( vLevel, -1 ); + } + Vec_WrdFree( vSims ); +} + + +Vec_Wec_t * Gia_ManExploreCuts( Gia_Man_t * pGia, int nCutSize0, int nCuts0, int fVerbose0 ) +{ + int nCutSize = nCutSize0; + int nCutNum = 64; + int fCutMin = 0; + int fTruthMin = 0; + int fVerbose = fVerbose0; + Vec_Wec_t * vCutsSel; + Gia_Sto_t * p = Gia_StoAlloc( pGia, nCutSize, nCutNum, fCutMin, fTruthMin, fVerbose ); + Gia_Obj_t * pObj; int i, iObj; + assert( nCutSize <= GIA_MAX_CUTSIZE ); + assert( nCutNum < GIA_MAX_CUTNUM ); + // prepare references + Gia_ManForEachObj( p->pGia, pObj, iObj ) + Gia_StoRefObj( p, iObj ); + // compute cuts + Gia_StoComputeCutsConst0( p, 0 ); + Gia_ManForEachCiId( p->pGia, iObj, i ) + Gia_StoComputeCutsCi( p, iObj ); + Gia_ManForEachAnd( p->pGia, pObj, iObj ) + Gia_StoComputeCutsNode( p, iObj ); + if ( p->fVerbose ) + { + printf( "Running cut computation with CutSize = %d CutNum = %d CutMin = %s TruthMin = %s\n", + p->nCutSize, p->nCutNum, p->fCutMin ? "yes":"no", p->fTruthMin ? "yes":"no" ); + printf( "CutPair = %.0f ", p->CutCount[0] ); + printf( "Merge = %.0f (%.2f %%) ", p->CutCount[1], 100.0*p->CutCount[1]/p->CutCount[0] ); + printf( "Eval = %.0f (%.2f %%) ", p->CutCount[2], 100.0*p->CutCount[2]/p->CutCount[0] ); + printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] ); + printf( "Cut/Node = %.2f ", p->CutCount[3] / Gia_ManAndNum(p->pGia) ); + printf( "\n" ); + printf( "The number of nodes with cut count over the limit (%d cuts) = %d nodes (out of %d). ", + p->nCutNum, p->nCutsOver, Gia_ManAndNum(pGia) ); + Abc_PrintTime( 0, "Time", Abc_Clock() - p->clkStart ); + } + vCutsSel = Gia_ManFilterCuts( pGia, p->vCuts, nCutSize0, nCuts0 ); + Gia_ManConsiderCuts( pGia, vCutsSel ); + Gia_StoFree( p ); + return vCutsSel; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/abc/src/aig/gia/giaDecs.c b/abc/src/aig/gia/giaDecs.c new file mode 100644 index 00000000000..343891d5ee4 --- /dev/null +++ b/abc/src/aig/gia/giaDecs.c @@ -0,0 +1,350 @@ +/**CFile**************************************************************** + + FileName [giaDecs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Calling various decomposition engines.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaDecs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig/gia/gia.h" +#include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" +#include "bool/bdc/bdc.h" +#include "bool/kit/kit.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); +extern Vec_Int_t * Gia_ManResubOne( Vec_Ptr_t * vDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, word * pFunc, int Depth ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ResubVarNum( Vec_Int_t * vResub ) +{ + if ( Vec_IntSize(vResub) == 1 ) + return Vec_IntEntryLast(vResub) >= 2; + return Vec_IntEntryLast(vResub)/2 - Vec_IntSize(vResub)/2 - 1; +} +word Gia_ResubToTruth6_rec( Vec_Int_t * vResub, int iNode, int nVars ) +{ + assert( iNode >= 0 && nVars <= 6 ); + if ( iNode < nVars ) + return s_Truths6[iNode]; + else + { + int iLit0 = Vec_IntEntry( vResub, Abc_Var2Lit(iNode-nVars, 0) ); + int iLit1 = Vec_IntEntry( vResub, Abc_Var2Lit(iNode-nVars, 1) ); + word Res0 = Gia_ResubToTruth6_rec( vResub, Abc_Lit2Var(iLit0)-2, nVars ); + word Res1 = Gia_ResubToTruth6_rec( vResub, Abc_Lit2Var(iLit1)-2, nVars ); + Res0 = Abc_LitIsCompl(iLit0) ? ~Res0 : Res0; + Res1 = Abc_LitIsCompl(iLit1) ? ~Res1 : Res1; + return iLit0 > iLit1 ? Res0 ^ Res1 : Res0 & Res1; + } +} +word Gia_ResubToTruth6( Vec_Int_t * vResub ) +{ + word Res; + int iRoot = Vec_IntEntryLast(vResub); + if ( iRoot < 2 ) + return iRoot ? ~(word)0 : 0; + assert( iRoot != 2 && iRoot != 3 ); + Res = Gia_ResubToTruth6_rec( vResub, Abc_Lit2Var(iRoot)-2, Gia_ResubVarNum(vResub) ); + return Abc_LitIsCompl(iRoot) ? ~Res : Res; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Gia_ManDeriveTruths( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vSet, int nWords ) +{ + int nTtWords = Abc_Truth6WordNum(Vec_IntSize(vSet)); + int nFuncs = Vec_WrdSize(vIsfs) / 2 / nWords; + Vec_Wrd_t * vRes = Vec_WrdStart( 2 * nFuncs * nTtWords ); + Vec_Wrd_t * vIn = Vec_WrdStart( 64*nWords ), * vOut; + int i, f, m, iObj; word Func; + assert( Vec_IntSize(vSet) <= 64 ); + Vec_IntForEachEntry( vSet, iObj, i ) + Abc_TtCopy( Vec_WrdEntryP(vIn, i*nWords), Vec_WrdEntryP(vSims, Vec_IntEntry(vCands, iObj)*nWords), nWords, 0 ); + vOut = Vec_WrdStart( Vec_WrdSize(vIn) ); + Extra_BitMatrixTransposeP( vIn, nWords, vOut, 1 ); + for ( f = 0; f < nFuncs; f++ ) + { + word * pIsf[2] = { Vec_WrdEntryP(vIsfs, (2*f+0)*nWords), + Vec_WrdEntryP(vIsfs, (2*f+1)*nWords) }; + word * pTruth[2] = { Vec_WrdEntryP(vRes, (2*f+0)*nTtWords), + Vec_WrdEntryP(vRes, (2*f+1)*nTtWords) }; + for ( m = 0; m < 64*nWords; m++ ) + { + int iMint = (int)Vec_WrdEntry(vOut, m); + int Value0 = Abc_TtGetBit( pIsf[0], m ); + int Value1 = Abc_TtGetBit( pIsf[1], m ); + if ( !Value0 && !Value1 ) + continue; + if ( Value0 && Value1 ) + printf( "Internal error: Onset and Offset overlap.\n" ); + assert( !Value0 || !Value1 ); + Abc_TtSetBit( pTruth[Value1], iMint ); + } + if ( Abc_TtCountOnesVecMask(pTruth[0], pTruth[1], nTtWords, 0) ) + printf( "Verification for function %d failed for %d minterm pairs.\n", f, + Abc_TtCountOnesVecMask(pTruth[0], pTruth[1], nTtWords, 0) ); + } + if ( Vec_IntSize(vSet) < 6 ) + Vec_WrdForEachEntry( vRes, Func, i ) + Vec_WrdWriteEntry( vRes, i, Abc_Tt6Stretch(Func, Vec_IntSize(vSet)) ); + Vec_WrdFree( vIn ); + Vec_WrdFree( vOut ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCountResub( Vec_Wrd_t * vTruths, int nVars, int fVerbose ) +{ + Vec_Int_t * vResub; int nNodes; + int nTtWords = Abc_Truth6WordNum(nVars); + int v, nFuncs = Vec_WrdSize(vTruths) / 2 / nTtWords; + Vec_Wrd_t * vElems = Vec_WrdStartTruthTables( nVars ); + Vec_Ptr_t * vDivs = Vec_PtrAlloc( 2 + nVars ); + assert( Vec_WrdSize(vElems) == nTtWords * nVars ); + assert( nFuncs == 1 ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(vTruths, (2*0+0)*nTtWords) ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(vTruths, (2*0+1)*nTtWords) ); + for ( v = 0; v < nVars; v++ ) + Vec_PtrPush( vDivs, Vec_WrdEntryP(vElems, v*nTtWords) ); + vResub = Gia_ManResubOne( vDivs, nTtWords, 30, 100, 0, 0, 0, fVerbose, NULL, 0 ); + Vec_PtrFree( vDivs ); + Vec_WrdFree( vElems ); + nNodes = Vec_IntSize(vResub) ? Vec_IntSize(vResub)/2 : 999; + Vec_IntFree( vResub ); + return nNodes; +} +Vec_Int_t * Gia_ManDeriveResub( Vec_Wrd_t * vTruths, int nVars ) +{ + Vec_Int_t * vResub; + int nTtWords = Abc_Truth6WordNum(nVars); + int v, nFuncs = Vec_WrdSize(vTruths) / 2 / nTtWords; + Vec_Wrd_t * vElems = Vec_WrdStartTruthTables( nVars ); + Vec_Ptr_t * vDivs = Vec_PtrAlloc( 2 + nVars ); + assert( Vec_WrdSize(vElems) == nTtWords * nVars ); + assert( nFuncs == 1 ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(vTruths, (2*0+0)*nTtWords) ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(vTruths, (2*0+1)*nTtWords) ); + for ( v = 0; v < nVars; v++ ) + Vec_PtrPush( vDivs, Vec_WrdEntryP(vElems, v*nTtWords) ); + vResub = Gia_ManResubOne( vDivs, nTtWords, 30, 100, 0, 0, 0, 0, NULL, 0 ); + Vec_PtrFree( vDivs ); + Vec_WrdFree( vElems ); + return vResub; +} + +int Gia_ManCountBidec( Vec_Wrd_t * vTruths, int nVars, int fVerbose ) +{ + int nNodes, nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + Abc_TtOr( pTruth[0], pTruth[0], pTruth[1], nTtWords ); + nNodes = Bdc_ManBidecNodeNum( pTruth[1], pTruth[0], nVars, fVerbose ); + Abc_TtSharp( pTruth[0], pTruth[0], pTruth[1], nTtWords ); + return nNodes; +} +Vec_Int_t * Gia_ManDeriveBidec( Vec_Wrd_t * vTruths, int nVars ) +{ + Vec_Int_t * vRes = NULL; + int nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + Abc_TtOr( pTruth[0], pTruth[0], pTruth[1], nTtWords ); + vRes = Bdc_ManBidecResub( pTruth[1], pTruth[0], nVars ); + Abc_TtSharp( pTruth[0], pTruth[0], pTruth[1], nTtWords ); + return vRes; +} + +int Gia_ManCountIsop( Vec_Wrd_t * vTruths, int nVars, int fVerbose ) +{ + int nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + int nNodes = Kit_IsopNodeNum( (unsigned *)pTruth[0], (unsigned *)pTruth[1], nVars, NULL ); + return nNodes; +} +Vec_Int_t * Gia_ManDeriveIsop( Vec_Wrd_t * vTruths, int nVars ) +{ + Vec_Int_t * vRes = NULL; + int nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + vRes = Kit_IsopResub( (unsigned *)pTruth[0], (unsigned *)pTruth[1], nVars, NULL ); + return vRes; +} + +int Gia_ManCountBdd( Vec_Wrd_t * vTruths, int nVars, int fVerbose ) +{ + extern Gia_Man_t * Gia_TryPermOptNew( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + int nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + Gia_Man_t * pGia; int nNodes; + + Abc_TtOr( pTruth[1], pTruth[1], pTruth[0], nTtWords ); + Abc_TtNot( pTruth[0], nTtWords ); + pGia = Gia_TryPermOptNew( pTruth[0], nVars, 1, nTtWords, 50, 0 ); + Abc_TtNot( pTruth[0], nTtWords ); + Abc_TtSharp( pTruth[1], pTruth[1], pTruth[0], nTtWords ); + + nNodes = Gia_ManAndNum(pGia); + Gia_ManStop( pGia ); + return nNodes; +} +Vec_Int_t * Gia_ManDeriveBdd( Vec_Wrd_t * vTruths, int nVars ) +{ + extern Vec_Int_t * Gia_ManToGates( Gia_Man_t * p ); + Vec_Int_t * vRes = NULL; + extern Gia_Man_t * Gia_TryPermOptNew( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + int nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + Gia_Man_t * pGia; + + Abc_TtOr( pTruth[1], pTruth[1], pTruth[0], nTtWords ); + Abc_TtNot( pTruth[0], nTtWords ); + pGia = Gia_TryPermOptNew( pTruth[0], nVars, 1, nTtWords, 50, 0 ); + Abc_TtNot( pTruth[0], nTtWords ); + Abc_TtSharp( pTruth[1], pTruth[1], pTruth[0], nTtWords ); + + vRes = Gia_ManToGates( pGia ); + Gia_ManStop( pGia ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManEvalSolutionOne( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vSet, int nWords, int fVerbose ) +{ + Vec_Wrd_t * vTruths = Gia_ManDeriveTruths( p, vSims, vIsfs, vCands, vSet, nWords ); + int nTtWords = Vec_WrdSize(vTruths)/2, nVars = Vec_IntSize(vSet); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + int nNodesResub = Gia_ManCountResub( vTruths, nVars, 0 ); + int nNodesBidec = nVars > 2 ? Gia_ManCountBidec( vTruths, nVars, 0 ) : 999; + int nNodesIsop = nVars > 2 ? Gia_ManCountIsop( vTruths, nVars, 0 ) : 999; + int nNodesBdd = nVars > 2 ? Gia_ManCountBdd( vTruths, nVars, 0 ) : 999; + int nNodesMin = Abc_MinInt( Abc_MinInt(nNodesResub, nNodesBidec), Abc_MinInt(nNodesIsop, nNodesBdd) ); + if ( fVerbose ) + { + printf( "Size = %2d ", nVars ); + printf( "Resub =%3d ", nNodesResub ); + printf( "Bidec =%3d ", nNodesBidec ); + printf( "Isop =%3d ", nNodesIsop ); + printf( "Bdd =%3d ", nNodesBdd ); + Abc_TtIsfPrint( pTruth[0], pTruth[1], nTtWords ); + if ( nVars <= 6 ) + { + printf( " " ); + Extra_PrintHex( stdout, (unsigned*)pTruth[0], nVars ); + printf( " " ); + Extra_PrintHex( stdout, (unsigned*)pTruth[1], nVars ); + } + printf( "\n" ); + } + Vec_WrdFree( vTruths ); + if ( nNodesMin > 500 ) + return -1; + if ( nNodesMin == nNodesResub ) + return (nNodesMin << 2) | 0; + if ( nNodesMin == nNodesBidec ) + return (nNodesMin << 2) | 1; + if ( nNodesMin == nNodesIsop ) + return (nNodesMin << 2) | 2; + if ( nNodesMin == nNodesBdd ) + return (nNodesMin << 2) | 3; + return -1; +} +Vec_Int_t * Gia_ManDeriveSolutionOne( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vSet, int nWords, int Type ) +{ + Vec_Int_t * vRes = NULL; + Vec_Wrd_t * vTruths = Gia_ManDeriveTruths( p, vSims, vIsfs, vCands, vSet, nWords ); + int nTtWords = Vec_WrdSize(vTruths)/2, nVars = Vec_IntSize(vSet); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + if ( Type == 0 ) + vRes = Gia_ManDeriveResub( vTruths, nVars ); + else if ( Type == 1 ) + vRes = Gia_ManDeriveBidec( vTruths, nVars ); + else if ( Type == 2 ) + vRes = Gia_ManDeriveIsop( vTruths, nVars ); + else if ( Type == 3 ) + vRes = Gia_ManDeriveBdd( vTruths, nVars ); + if ( vRes && Gia_ResubVarNum(vRes) <= 6 ) + { + word Func = Gia_ResubToTruth6( vRes ); + assert( !(Func & pTruth[0][0]) ); + assert( !(pTruth[1][0] & ~Func) ); + } + Vec_WrdFree( vTruths ); + return vRes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaDeep.c b/abc/src/aig/gia/giaDeep.c new file mode 100644 index 00000000000..b58169f4257 --- /dev/null +++ b/abc/src/aig/gia/giaDeep.c @@ -0,0 +1,170 @@ +/**CFile**************************************************************** + + FileName [giaDeep.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Experiments with synthesis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaDeep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "base/main/main.h" +#include "base/cmd/cmd.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDeepSynOne( int nNoImpr, int TimeOut, int nAnds, int Seed, int fUseTwo, int fVerbose ) +{ + abctime nTimeToStop = TimeOut ? Abc_Clock() + TimeOut * CLOCKS_PER_SEC : 0; + abctime clkStart = Abc_Clock(); + int s, i, IterMax = 100000, nAndsMin = -1, iIterLast = -1; + Gia_Man_t * pTemp = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + Gia_Man_t * pNew = Gia_ManDup( pTemp ); + Abc_Random(1); + for ( s = 0; s < 10+Seed; s++ ) + Abc_Random(0); + for ( i = 0; i < IterMax; i++ ) + { + unsigned Rand = Abc_Random(0); + int fDch = Rand & 1; + //int fCom = (Rand >> 1) & 3; + int fCom = (Rand >> 1) & 1; + int fFx = (Rand >> 2) & 1; + int KLut = fUseTwo ? 2 + (i % 5) : 3 + (i % 4); + int fChange = 0; + char Command[1000]; + char * pComp = NULL; + if ( fCom == 3 ) + pComp = "; &put; compress2rs; compress2rs; compress2rs; &get"; + else if ( fCom == 2 ) + pComp = "; &put; compress2rs; compress2rs; &get"; + else if ( fCom == 1 ) + pComp = "; &put; compress2rs; &get"; + else if ( fCom == 0 ) + pComp = "; &dc2"; + sprintf( Command, "&dch%s; &if -a -K %d; &mfs -e -W 20 -L 20%s%s", + fDch ? " -f" : "", KLut, fFx ? "; &fx; &st" : "", pComp ); + if ( Abc_FrameIsBatchMode() ) + { + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), Command) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", Command ); + return NULL; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), Command) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", Command ); + return NULL; + } + Abc_FrameSetBatchMode( 0 ); + } + pTemp = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + if ( Gia_ManAndNum(pNew) > Gia_ManAndNum(pTemp) ) + { + Gia_ManStop( pNew ); + pNew = Gia_ManDup( pTemp ); + fChange = 1; + iIterLast = i; + } + else if ( Gia_ManAndNum(pNew) + Gia_ManAndNum(pNew)/10 < Gia_ManAndNum(pTemp) ) + { + //printf( "Updating\n" ); + //Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), Gia_ManDup(pNew) ); + } + if ( fChange && fVerbose ) + { + printf( "Iter %6d : ", i ); + printf( "Time %8.2f sec : ", (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + printf( "And = %6d ", Gia_ManAndNum(pNew) ); + printf( "Lev = %3d ", Gia_ManLevelNum(pNew) ); + if ( fChange ) + printf( "<== best : " ); + else if ( fVerbose ) + printf( " " ); + printf( "%s", Command ); + printf( "\n" ); + } + if ( nTimeToStop && Abc_Clock() > nTimeToStop ) + { + if ( !Abc_FrameIsBatchMode() ) + printf( "Runtime limit (%d sec) is reached after %d iterations.\n", TimeOut, i ); + break; + } + if ( i - iIterLast > nNoImpr ) + { + printf( "Completed %d iterations without improvement in %.2f seconds.\n", + nNoImpr, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + break; + } + } + if ( i == IterMax ) + printf( "Iteration limit (%d iters) is reached after %.2f seconds.\n", IterMax, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + else if ( nAnds && nAndsMin <= nAnds ) + printf( "Quality goal (%d nodes <= %d nodes) is achieved after %d iterations and %.2f seconds.\n", + nAndsMin, nAnds, i, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + return pNew; +} +Gia_Man_t * Gia_ManDeepSyn( Gia_Man_t * pGia, int nIters, int nNoImpr, int TimeOut, int nAnds, int Seed, int fUseTwo, int fVerbose ) +{ + Gia_Man_t * pInit = Gia_ManDup(pGia); + Gia_Man_t * pBest = Gia_ManDup(pGia); + Gia_Man_t * pThis; + int i; + for ( i = 0; i < nIters; i++ ) + { + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), Gia_ManDup(pInit) ); + pThis = Gia_ManDeepSynOne( nNoImpr, TimeOut, nAnds, Seed+i, fUseTwo, fVerbose ); + if ( Gia_ManAndNum(pBest) > Gia_ManAndNum(pThis) ) + { + Gia_ManStop( pBest ); + pBest = pThis; + } + else + Gia_ManStop( pThis ); + + } + Gia_ManStop( pInit ); + return pBest; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaDfs.c b/abc/src/aig/gia/giaDfs.c index 12cae9409fd..7ed59b9a23b 100644 --- a/abc/src/aig/gia/giaDfs.c +++ b/abc/src/aig/gia/giaDfs.c @@ -141,6 +141,26 @@ void Gia_ManCollectAnds( Gia_Man_t * p, int * pNodes, int nNodes, Vec_Int_t * vN } } +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManCollectAndsAll( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vNodes = Vec_IntAlloc( Gia_ManAndNum(p) ); + Gia_ManForEachAnd( p, pObj, i ) + Vec_IntPush( vNodes, i ); + return vNodes; +} + /**Function************************************************************* Synopsis [Counts the support size of the node.] @@ -396,6 +416,34 @@ Vec_Vec_t * Gia_ManLevelize( Gia_Man_t * p ) return vLevels; } +/**Function************************************************************* + + Synopsis [Levelizes the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManLevelizeR( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + Vec_Wec_t * vLevels; + int nLevels, Level, i; + nLevels = Gia_ManLevelRNum( p ); + vLevels = Vec_WecStart( nLevels + 1 ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( i == 0 || (!Gia_ObjIsCo(pObj) && !Gia_ObjLevel(p, pObj)) ) + continue; + Level = Gia_ObjLevel( p, pObj ); + assert( Level <= nLevels ); + Vec_WecPush( vLevels, Level, i ); + } + return vLevels; +} /**Function************************************************************* Synopsis [Computes reverse topological order.] diff --git a/abc/src/aig/gia/giaDup.c b/abc/src/aig/gia/giaDup.c index 01c01f394ec..6dee2c26fe9 100644 --- a/abc/src/aig/gia/giaDup.c +++ b/abc/src/aig/gia/giaDup.c @@ -21,6 +21,7 @@ #include "gia.h" #include "misc/tim/tim.h" #include "misc/vec/vecWec.h" +#include "proof/cec/cec.h" ABC_NAMESPACE_IMPL_START @@ -465,7 +466,16 @@ Gia_Man_t * Gia_ManDupOrderDfsChoices( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ -Gia_Man_t * Gia_ManDupOrderDfsReverse( Gia_Man_t * p ) +int Gia_ManDupOrderDfs2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupOrderDfs2_rec( pNew, p, Gia_ObjFanin1(pObj) ); + Gia_ManDupOrderDfs2_rec( pNew, p, Gia_ObjFanin0(pObj) ); + return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManDupOrderDfsReverse( Gia_Man_t * p, int fRevFans, int fRevOuts ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; @@ -475,12 +485,28 @@ Gia_Man_t * Gia_ManDupOrderDfsReverse( Gia_Man_t * p ) pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; - Gia_ManForEachCoReverse( p, pObj, i ) - Gia_ManDupOrderDfs_rec( pNew, p, pObj ); Gia_ManForEachCi( p, pObj, i ) - if ( !~pObj->Value ) - pObj->Value = Gia_ManAppendCi(pNew); - assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) ); + pObj->Value = Gia_ManAppendCi(pNew); + if ( fRevOuts ) + { + if ( fRevFans ) + Gia_ManForEachCoReverse( p, pObj, i ) + Gia_ManDupOrderDfs2_rec( pNew, p, Gia_ObjFanin0(pObj) ); + else + Gia_ManForEachCoReverse( p, pObj, i ) + Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + } + else + { + if ( fRevFans ) + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupOrderDfs2_rec( pNew, p, Gia_ObjFanin0(pObj) ); + else + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + } + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManDupRemapCis( pNew, p ); Gia_ManDupRemapCos( pNew, p ); Gia_ManDupRemapEquiv( pNew, p ); @@ -785,6 +811,76 @@ Gia_Man_t * Gia_ManDupRemovePis( Gia_Man_t * p, int nRemPis ) Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } +Gia_Man_t * Gia_ManDupNoBuf( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManDupMap( Gia_Man_t * p, Vec_Int_t * vMap ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Vec_IntEntry(vMap, i) >= 0 ) + pObj->Value = Gia_ManObj( p, Vec_IntEntry(vMap, i) )->Value; + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManDupAddBufs( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) + Gia_ManCiNum(p) + Gia_ManCoNum(p) ); + Gia_ManHashStart( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendBuf( pNew, pObj->Value ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ManHashStop( pNew ); + return pNew; +} /**Function************************************************************* @@ -839,7 +935,9 @@ Gia_Man_t * Gia_ManDupPerm( Gia_Man_t * p, Vec_Int_t * vPiPerm ) // Vec_IntFree( vPiPermInv ); Gia_ManForEachObj1( p, pObj, i ) { - if ( Gia_ObjIsAnd(pObj) ) + if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsCi(pObj) ) { @@ -854,12 +952,12 @@ Gia_Man_t * Gia_ManDupPerm( Gia_Man_t * p, Vec_Int_t * vPiPerm ) } Gia_Man_t * Gia_ManDupPermFlop( Gia_Man_t * p, Vec_Int_t * vFfPerm ) { - Vec_Int_t * vPermInv; + //Vec_Int_t * vPermInv; Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; assert( Vec_IntSize(vFfPerm) == Gia_ManRegNum(p) ); - vPermInv = Vec_IntInvert( vFfPerm, -1 ); + //vPermInv = Vec_IntInvert( vFfPerm, -1 ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); @@ -867,14 +965,16 @@ Gia_Man_t * Gia_ManDupPermFlop( Gia_Man_t * p, Vec_Int_t * vFfPerm ) Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManForEachRo( p, pObj, i ) - Gia_ManRo(p, Vec_IntEntry(vPermInv, i))->Value = Gia_ManAppendCi(pNew); + //Gia_ManRo(p, Vec_IntEntry(vPermInv, i))->Value = Gia_ManAppendCi(pNew); + Gia_ManRo(p, Vec_IntEntry(vFfPerm, i))->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachPo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManForEachRi( p, pObj, i ) - pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy( Gia_ManRi(p, Vec_IntEntry(vPermInv, i)) ) ); - Vec_IntFree( vPermInv ); + //pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy( Gia_ManRi(p, Vec_IntEntry(vPermInv, i)) ) ); + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy( Gia_ManRi(p, Vec_IntEntry(vFfPerm, i)) ) ); + //Vec_IntFree( vPermInv ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } @@ -924,6 +1024,96 @@ Gia_Man_t * Gia_ManDupPermFlopGap( Gia_Man_t * p, Vec_Int_t * vFfMask ) return pSpread; } +/**Function************************************************************* + + Synopsis [Appends second AIG without any changes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupPiPerm( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pOne; + Gia_Obj_t * pObj; + int i; + Gia_ManRandom(1); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + { + int iLit0 = Gia_ObjFanin0Copy(pObj); + int iLit1 = Gia_ObjFanin1Copy(pObj); + int iPlace0 = Gia_ManRandom(0) % Gia_ManCiNum(p); + int iPlace1 = Gia_ManRandom(0) % Gia_ManCiNum(p); + if ( Abc_Lit2Var(iLit0) <= Gia_ManCiNum(p) ) + iLit0 = Abc_Var2Lit( iPlace0+1, Abc_LitIsCompl(iLit0) ); + if ( Abc_Lit2Var(iLit1) <= Gia_ManCiNum(p) ) + iLit1 = Abc_Var2Lit( iPlace1+1, Abc_LitIsCompl(iLit1) ); + pObj->Value = Gia_ManHashAnd( pNew, iLit0, iLit1 ); + } + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pOne = pNew ); + Gia_ManStop( pOne ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManCreatePerm( int n ) +{ + Vec_Int_t * vPerm = Vec_IntStartNatural( n ); + int i, * pPerm = Vec_IntArray( vPerm ); + for ( i = 0; i < n; i++ ) + { + int j = Abc_Random(0) % n; + ABC_SWAP( int, pPerm[i], pPerm[j] ); + + } + return vPerm; +} +Gia_Man_t * Gia_ManDupRandPerm( Gia_Man_t * p ) +{ + Vec_Int_t * vPiPerm = Gia_ManCreatePerm( Gia_ManCiNum(p) ); + Vec_Int_t * vPoPerm = Gia_ManCreatePerm( Gia_ManCoNum(p) ); + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + Gia_ManPi(p, Vec_IntEntry(vPiPerm,i))->Value = Gia_ManAppendCi(pNew) ^ (Abc_Random(0) & 1); + 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(Gia_ManPo(p, Vec_IntEntry(vPoPerm,i))) ^ (Abc_Random(0) & 1) ); + Vec_IntFree( vPiPerm ); + Vec_IntFree( vPoPerm ); + return pNew; +} + /**Function************************************************************* Synopsis [Appends second AIG without any changes.] @@ -1013,6 +1203,23 @@ Gia_Man_t * Gia_ManDupAppendNew( Gia_Man_t * pOne, Gia_Man_t * pTwo ) Gia_ManSetRegNum( pNew, Gia_ManRegNum(pOne) + Gia_ManRegNum(pTwo) ); return pNew; } +void Gia_ManDupRebuild( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Int_t * vLits, int fBufs ) +{ + Gia_Obj_t * pObj; int i; + assert( Vec_IntSize(vLits) == Gia_ManCiNum(p) ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Vec_IntEntry(vLits, i); + Gia_ManForEachAnd( p, pObj, i ) + if ( fBufs && Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else + 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) ); +} /**Function************************************************************* @@ -1279,7 +1486,7 @@ Gia_Man_t * Gia_ManDupMarked( Gia_Man_t * p ) { Gia_Obj_t * pRepr; pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pNew) ); - for ( i = 0; i < Gia_ManObjNum(p); i++ ) + for ( i = 0; i < Gia_ManObjNum(pNew); i++ ) Gia_ObjSetRepr( pNew, i, GIA_VOID ); Gia_ManForEachObj1( p, pObj, i ) { @@ -1397,6 +1604,47 @@ Gia_Man_t * Gia_ManDupTimes( Gia_Man_t * p, int nTimes ) return pNew; } +/**Function************************************************************* + + Synopsis [Duplicates while adding self-loops to the registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupMiterCones( Gia_Man_t * p, Vec_Int_t * vPairs ) +{ + Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iLit0, iLit1; + pNew = Gia_ManStart( Gia_ManObjNum(p) + 3 * Vec_IntSize(vPairs) ); + pNew->pName = Abc_UtilStrsav( "miter" ); + Gia_ManHashAlloc( pNew ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Vec_IntForEachEntryDouble( vPairs, iLit0, iLit1, i ) + { + int Lit0 = Abc_LitNotCond( Gia_ManObj(p, Abc_Lit2Var(iLit0))->Value, Abc_LitIsCompl(iLit0) ); + int Lit1 = Abc_LitNotCond( Gia_ManObj(p, Abc_Lit2Var(iLit1))->Value, Abc_LitIsCompl(iLit1) ); + Vec_IntPush( vTemp, Gia_ManHashXor(pNew, Lit0, Lit1) ); + } + Vec_IntForEachEntry( vTemp, iLit0, i ) + Gia_ManAppendCo( pNew, iLit0 ); + Vec_IntFree( vTemp ); + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] @@ -1510,6 +1758,76 @@ Gia_Man_t * Gia_ManDupDfs( Gia_Man_t * p ) pNew->pCexSeq = Abc_CexDup( p->pCexSeq, Gia_ManRegNum(p) ); return pNew; } +Gia_Man_t * Gia_ManDupDfsOnePo( Gia_Man_t * p, int iPo ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + assert( iPo >= 0 && iPo < Gia_ManPoNum(p) ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachCo( p, pObj, i ) + if ( !Gia_ObjIsPo(p, pObj) || i == iPo ) + Gia_ManDupDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + if ( !Gia_ObjIsPo(p, pObj) || i == iPo ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupDfsRehash_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupDfsRehash_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManDupDfsRehash_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManDupDfsRehash( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupDfsRehash_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew->nConstrs = p->nConstrs; + if ( p->pCexSeq ) + pNew->pCexSeq = Abc_CexDup( p->pCexSeq, Gia_ManRegNum(p) ); + return pNew; +} /**Function************************************************************* @@ -2223,13 +2541,38 @@ Gia_Man_t * Gia_ManDupTrimmed2( Gia_Man_t * p ) assert( !Gia_ManHasDangling( pNew ) ); return pNew; } - -/**Function************************************************************* - - Synopsis [Duplicates AIG in the DFS order while putting CIs first.] - - Description [] - +Gia_Man_t * Gia_ManDupTrimmed3( Gia_Man_t * p ) +{ + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // mark duplicated POs + Gia_ManForEachPo( p, pObj, i ) + Vec_IntWriteEntry( vMap, Gia_ObjFaninId0p(p, pObj), i ); + Gia_ManForEachPo( p, pObj, i ) + if ( Vec_IntEntry(vMap, Gia_ObjFaninId0p(p, pObj)) == i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Vec_IntFree( vMap ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order while putting CIs first.] + + Description [] + SideEffects [] SeeAlso [] @@ -2764,6 +3107,92 @@ Gia_Man_t * Gia_ManMiter( Gia_Man_t * p0, Gia_Man_t * p1, int nInsDup, int fDual return pNew; } +/**Function************************************************************* + + Synopsis [Creates miter of two designs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManMiterInverse( Gia_Man_t * pBot, Gia_Man_t * pTop, int fDualOut, int fVerbose ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iLit; + int nInputs1 = Gia_ManCiNum(pTop) - Gia_ManCoNum(pBot); + int nInputs2 = Gia_ManCiNum(pBot) - Gia_ManCoNum(pTop); + if ( nInputs1 == nInputs2 ) + printf( "Assuming that the circuits have %d shared inputs, ordered first.\n", nInputs1 ); + else + { + printf( "The number of inputs and outputs does not match.\n" ); + return NULL; + } + pNew = Gia_ManStart( Gia_ManObjNum(pBot) + Gia_ManObjNum(pTop) ); + pNew->pName = Abc_UtilStrsav( "miter" ); + Gia_ManFillValue( pBot ); + Gia_ManFillValue( pTop ); + Gia_ManConst0(pBot)->Value = 0; + Gia_ManConst0(pTop)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCi( pBot, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); +// Gia_ManForEachCo( pBot, pObj, i ) +// Gia_ManMiter_rec( pNew, pBot, Gia_ObjFanin0(pObj) ); + Gia_ManForEachAnd( pBot, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + Gia_ManForEachCo( pBot, pObj, i ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + Gia_ManForEachCi( pTop, pObj, i ) + if ( i < nInputs1 ) + pObj->Value = Gia_ManCi(pBot, i)->Value; + else + pObj->Value = Gia_ManCo(pBot, i-nInputs1)->Value; +// Gia_ManForEachCo( pTop, pObj, i ) +// Gia_ManMiter_rec( pNew, pTop, Gia_ObjFanin0(pObj) ); + Gia_ManForEachAnd( pTop, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + Gia_ManForEachCo( pTop, pObj, i ) + { + if ( fDualOut ) + { + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManAppendCo( pNew, Gia_ManCi(pBot, i+nInputs1)->Value ); + } + else + { + iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ManCi(pBot, i+nInputs1)->Value ); + Gia_ManAppendCo( pNew, iLit ); + } + } + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + assert( (pBot->vBarBufs == NULL) == (pTop->vBarBufs == NULL) ); + if ( pBot->vBarBufs ) + { + pNew->vBarBufs = Vec_IntAlloc( 1000 ); + Vec_IntAppend( pNew->vBarBufs, pBot->vBarBufs ); + Vec_IntAppend( pNew->vBarBufs, pTop->vBarBufs ); + //printf( "Miter has %d buffers (%d groups).\n", pNew->nBufs, Vec_IntSize(pNew->vBarBufs) ); + } + return pNew; +} + /**Function************************************************************* Synopsis [Computes the AND of all POs.] @@ -2813,6 +3242,73 @@ Gia_Man_t * Gia_ManDupAndOr( Gia_Man_t * p, int nOuts, int fUseOr, int fCompl ) return pNew; } +/**Function************************************************************* + + Synopsis [Transforms output names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Gia_ManMiterNames( Vec_Ptr_t * p, int nOuts ) +{ + char * pName1, * pName2, pBuffer[1000]; int i; + Vec_Ptr_t * pNew = Vec_PtrAlloc( Vec_PtrSize(p) - nOuts/2 ); + assert( nOuts % 2 == 0 ); + assert( nOuts <= Vec_PtrSize(p) ); + Vec_PtrForEachEntryDouble( char *, char *, p, pName1, pName2, i ) + { + if ( i == nOuts ) + break; + sprintf( pBuffer, "%s_xor_%s", pName1, pName2 ); + Vec_PtrPush( pNew, Abc_UtilStrsav(pBuffer) ); + } + Vec_PtrForEachEntryStart( char *, p, pName1, i, i ) + Vec_PtrPush( pNew, Abc_UtilStrsav(pName1) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Pair-wise miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPairWiseMiter( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pObj2; + int i, k, iLit; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManForEachPo( p, pObj2, k ) + { + if ( i >= k ) + continue; + iLit = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(pObj2) ); + Gia_ManAppendCo( pNew, iLit ); + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + /**Function************************************************************* Synopsis [Transforms the circuit into a regular miter.] @@ -2851,6 +3347,10 @@ Gia_Man_t * Gia_ManTransformMiter( Gia_Man_t * p ) Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); + if ( p->vNamesIn ) + pNew->vNamesIn = Vec_PtrDupStr(p->vNamesIn); + if ( p->vNamesOut ) + pNew->vNamesOut = Gia_ManMiterNames(p->vNamesOut, Gia_ManPoNum(p)); return pNew; } Gia_Man_t * Gia_ManTransformMiter2( Gia_Man_t * p ) @@ -3013,7 +3513,7 @@ Gia_Man_t * Gia_ManTransformDualOutput( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ -Gia_Man_t * Gia_ManDupZeroUndc( Gia_Man_t * p, char * pInit, int fGiaSimple, int fVerbose ) +Gia_Man_t * Gia_ManDupZeroUndc( Gia_Man_t * p, char * pInit, int nNewPis, int fGiaSimple, int fVerbose ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; @@ -3038,6 +3538,9 @@ Gia_Man_t * Gia_ManDupZeroUndc( Gia_Man_t * p, char * pInit, int fGiaSimple, int // create additional primary inputs for ( i = Gia_ManPiNum(p); i < CountPis; i++ ) Gia_ManAppendCi( pNew ); + // create additional primary inputs + for ( i = 0; i < nNewPis; i++ ) + Gia_ManAppendCi( pNew ); // create flop outputs Gia_ManForEachRo( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); @@ -3103,7 +3606,7 @@ Gia_Man_t * Gia_ManMiter2( Gia_Man_t * pStart, char * pInit, int fVerbose ) for ( i = 0; i < Gia_ManPiNum(pStart); i++ ) assert( pInit[i] == 'x' || pInit[i] == 'X' ); // normalize the manager - pUndc = Gia_ManDupZeroUndc( pStart, pInit + Gia_ManPiNum(pStart), 0, fVerbose ); + pUndc = Gia_ManDupZeroUndc( pStart, pInit + Gia_ManPiNum(pStart), 0, 0, fVerbose ); // create new init string pInitNew = ABC_ALLOC( char, Gia_ManPiNum(pUndc)+1 ); for ( i = 0; i < Gia_ManPiNum(pStart); i++ ) @@ -3340,7 +3843,7 @@ Gia_Man_t * Gia_ManDupCones( Gia_Man_t * p, int * pPos, int nPos, int fTrimPis ) Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); Vec_PtrForEachEntry( Gia_Obj_t *, vRoots, pObj, i ) Gia_ManDupCones_rec( p, pObj, vLeaves, vNodes, vRoots ); - Vec_PtrSort( vLeaves, (int (*)(void))Gia_ObjCompareByCioId ); + Vec_PtrSort( vLeaves, (int (*)(const void *, const void *))Gia_ObjCompareByCioId ); // start the new manager // Gia_ManFillValue( p ); @@ -3352,6 +3855,8 @@ Gia_Man_t * Gia_ManDupCones( Gia_Man_t * p, int * pPos, int nPos, int fTrimPis ) // create PIs if ( fTrimPis ) { + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = ~0; Vec_PtrForEachEntry( Gia_Obj_t *, vLeaves, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); } @@ -3365,7 +3870,10 @@ Gia_Man_t * Gia_ManDupCones( Gia_Man_t * p, int * pPos, int nPos, int fTrimPis ) Gia_ObjRiToRo(p, pObj)->Value = Gia_ManAppendCi( pNew ); // create internal nodes Vec_PtrForEachEntry( Gia_Obj_t *, vNodes, pObj, i ) - pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( Gia_ObjIsXor(pObj) ) + pObj->Value = Gia_ManAppendXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // create COs Vec_PtrForEachEntry( Gia_Obj_t *, vRoots, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); @@ -3397,7 +3905,7 @@ Gia_Man_t * Gia_ManDupAndCones( Gia_Man_t * p, int * pAnds, int nAnds, int fTrim Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); Vec_PtrForEachEntry( Gia_Obj_t *, vRoots, pObj, i ) Gia_ManDupCones_rec( p, pObj, vLeaves, vNodes, vRoots ); - Vec_PtrSort( vLeaves, (int (*)(void))Gia_ObjCompareByCioId ); + Vec_PtrSort( vLeaves, (int (*)(const void *, const void *))Gia_ObjCompareByCioId ); // start the new manager // Gia_ManFillValue( p ); @@ -4134,7 +4642,7 @@ Gia_Man_t * Gia_ManDupDemiter( Gia_Man_t * p, int fVerbose ) vSuperPtr = Vec_PtrAlloc( Vec_IntSize(vSuper) ); Vec_IntForEachEntry( vSuper, iLit, i ) Vec_PtrPush( vSuperPtr, Gia_Lit2Obj(p, iLit) ); - Vec_PtrSort( vSuperPtr, (int (*)(void))Gia_ManSortByValue ); + Vec_PtrSort( vSuperPtr, (int (*)(const void *, const void *))Gia_ManSortByValue ); // create new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); @@ -4548,6 +5056,669 @@ int Gia_ManDemiterTwoWords( Gia_Man_t * p, Gia_Man_t ** pp0, Gia_Man_t ** pp1 ) return 1; } + + +/**Function************************************************************* + + Synopsis [Extracts "half" of the sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupHalfSeq( Gia_Man_t * p, int fSecond ) +{ + int i; Gia_Obj_t * pObj; + Gia_Man_t * 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; + if ( fSecond ) + { + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManDupOrderDfs_rec( pNew, p, pObj ); + Gia_ManForEachRi( p, pObj, i ) + if ( i >= Gia_ManRegNum(p)/2 ) + Gia_ManDupOrderDfs_rec( pNew, p, pObj ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p)- Gia_ManRegNum(p)/2 ); + } + else + { + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachRo( p, pObj, i ) + if ( i >= Gia_ManRegNum(p)/2 ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachRo( p, pObj, i ) + if ( i < Gia_ManRegNum(p)/2 ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManDupOrderDfs_rec( pNew, p, pObj ); + Gia_ManForEachRi( p, pObj, i ) + if ( i < Gia_ManRegNum(p)/2 ) + Gia_ManDupOrderDfs_rec( pNew, p, pObj ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p)/2 ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Merge two sets of sequential equivalences.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSeqEquivMerge( Gia_Man_t * p, Gia_Man_t * pPart[2] ) +{ + int i, iObj, * pClasses = ABC_FALLOC( int, Gia_ManObjNum(p) ); + int n, Repr, * pClass2Repr = ABC_FALLOC( int, Gia_ManObjNum(p) ); + // initialize equiv class representation in the big AIG + assert( p->pReprs == NULL && p->pNexts == NULL ); + p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + Gia_ObjSetRepr( p, i, GIA_VOID ); + // map equivalences of p into classes + pClasses[0] = 0; + for ( n = 0; n < 2; n++ ) + { + assert( pPart[n]->pReprs != NULL && pPart[n]->pNexts != NULL ); + for ( i = 0; i < Gia_ManObjNum(pPart[n]); i++ ) + if ( Gia_ObjRepr(pPart[n], i) == 0 ) + pClasses[Gia_ManObj(pPart[n], i)->Value] = 0; + Gia_ManForEachClass( pPart[n], i ) + { + Repr = Gia_ManObj(pPart[n], i)->Value; + if ( n == 1 ) + { + Gia_ClassForEachObj( pPart[n], i, iObj ) + if ( pClasses[Gia_ManObj(pPart[n], iObj)->Value] != -1 ) + Repr = pClasses[Gia_ManObj(pPart[n], iObj)->Value]; + } + Gia_ClassForEachObj( pPart[n], i, iObj ) + pClasses[Gia_ManObj(pPart[n], iObj)->Value] = Repr; + } + } + // map representatives of each class + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( pClasses[i] != -1 && pClass2Repr[pClasses[i]] == -1 ) + { + pClass2Repr[pClasses[i]] = i; + pClasses[i] = -1; + } + // remap the remaining classes + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( pClasses[i] != -1 ) + p->pReprs[i].iRepr = pClass2Repr[pClasses[i]]; + ABC_FREE(pClasses); + ABC_FREE(pClass2Repr); + // create next pointers + p->pNexts = Gia_ManDeriveNexts( p ); +} + +/**Function************************************************************* + + Synopsis [Print equivalences.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintEquivs( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int i, iObj; + printf( "Const0:" ); + Gia_ManForEachAnd( p, pObj, i ) + if ( Gia_ObjRepr(p, i) == 0 ) + printf( " %d", i ); + printf( "\n" ); + Gia_ManForEachClass( p, i ) + { + printf( "%d:", i ); + Gia_ClassForEachObj1( p, i, iObj ) + printf( " %d", iObj ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Computing seq equivs by dividing AIG into two parts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSeqEquivDivide( Gia_Man_t * p, Cec_ParCor_t * pPars ) +{ + Gia_Man_t * pParts[2]; + Gia_Obj_t * pObj; + int n, i; + for ( n = 0; n < 2; n++ ) + { + // derive n-th part of the AIG + pParts[n] = Gia_ManDupHalfSeq( p, n ); + //Gia_ManPrintStats( pParts[n], NULL ); + // compute equivalences (recorded internally using pReprs and pNexts) + Cec_ManLSCorrespondenceClasses( pParts[n], pPars ); + // make the nodes of the part AIG point to their prototypes in the AIG + Gia_ManForEachObj( p, pObj, i ) + if ( ~pObj->Value ) + Gia_ManObj( pParts[n], Abc_Lit2Var(pObj->Value) )->Value = i; + } + Gia_ManSeqEquivMerge( p, pParts ); + Gia_ManStop( pParts[0] ); + Gia_ManStop( pParts[1] ); +} +Gia_Man_t * Gia_ManScorrDivideTest( Gia_Man_t * p, Cec_ParCor_t * pPars ) +{ + extern Gia_Man_t * Gia_ManCorrReduce( Gia_Man_t * p ); + Gia_Man_t * pNew, * pTemp; + ABC_FREE( p->pReprs ); p->pReprs = NULL; + ABC_FREE( p->pNexts ); p->pNexts = NULL; + Gia_ManSeqEquivDivide( p, pPars ); + //Gia_ManPrintEquivs( p ); + pNew = Gia_ManCorrReduce( p ); + pNew = Gia_ManSeqCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicate AIG by creating a cut between logic fed by PIs] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManHighLightFlopLogic( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManForEachPi( p, pObj, i ) + pObj->fMark0 = 0; + Gia_ManForEachRo( p, pObj, i ) + pObj->fMark0 = 1; + Gia_ManForEachAnd( p, pObj, i ) + pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 | Gia_ObjFanin1(pObj)->fMark0; + Gia_ManForEachCo( p, pObj, i ) + pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0; +} +Gia_Man_t * Gia_ManDupReplaceCut( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; int i; + Gia_Obj_t * pObj, * pFanin; + Gia_ManHighLightFlopLogic( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // create PIs for nodes pointed to from above the cut + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachAnd( p, pObj, i ) + { + if ( !pObj->fMark0 ) + continue; + pFanin = Gia_ObjFanin0(pObj); + if ( !pFanin->fMark0 && !~pFanin->Value ) + pFanin->Value = Gia_ManAppendCi(pNew); + pFanin = Gia_ObjFanin1(pObj); + if ( !pFanin->fMark0 && !~pFanin->Value ) + pFanin->Value = Gia_ManAppendCi(pNew); + } + // create flop outputs + Gia_ManForEachRo( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + // create internal nodes + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupOrderDfs_rec( pNew, p, pObj ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Gia_ManCleanMark0( p ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicate AIG by creating a cut between logic fed by PIs] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupAddPis( Gia_Man_t * p, int nMulti ) +{ + Gia_Man_t * pNew; int i, k; + Gia_Obj_t * pObj; + pNew = Gia_ManStart( Gia_ManObjNum(p) + Gia_ManCiNum(p) * nMulti ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + { + pObj->Value = Gia_ManAppendCi(pNew); + for ( k = 1; k < nMulti; k++ ) + Gia_ManAppendCi(pNew); + } + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + assert( Gia_ManCiNum(pNew) == nMulti * Gia_ManCiNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManDupUifBoxTypes( Vec_Int_t * vBarBufs ) +{ + Vec_Int_t * vTypes = Vec_IntAlloc( 10 ); + int i, Entry; + Vec_IntForEachEntry( vBarBufs, Entry, i ) + if ( Vec_IntFind(vTypes, Entry & 0xFFFE) < 0 ) + Vec_IntPush( vTypes, Entry & 0xFFFE ); + return vTypes; +} +Vec_Wec_t ** Gia_ManDupUifBuildMap( Gia_Man_t * p ) +{ + Vec_Int_t * vTypes = Gia_ManDupUifBoxTypes( p->vBarBufs ); + Vec_Wec_t ** pvMap = ABC_ALLOC( Vec_Wec_t *, 2*Vec_IntSize(vTypes) ); + Vec_Int_t * vBufs = Vec_IntAlloc( p->nBufs ); + Gia_Obj_t * pObj; int i, Item, j, k = 0; + Gia_ManForEachObj1( p, pObj, i ) + if ( Gia_ObjIsBuf(pObj) ) + Vec_IntPush( vBufs, i ); + assert( p->nBufs == Vec_IntSize(vBufs) ); + for ( i = 0; i < 2*Vec_IntSize(vTypes); i++ ) + pvMap[i] = Vec_WecAlloc( 10 ); + Vec_IntForEachEntry( p->vBarBufs, Item, i ) + { + int Type = Vec_IntFind( vTypes, Item & 0xFFFE ); + Vec_Int_t * vVec = Vec_WecPushLevel(pvMap[2*Type + (Item&1)]); + for ( j = 0; j < (Item >> 16); j++ ) + Vec_IntPush( vVec, Vec_IntEntry(vBufs, k++) ); + } + assert( p->nBufs == k ); + for ( i = 0; i < Vec_IntSize(vTypes); i++ ) + assert( Vec_WecSize(pvMap[2*i+0]) == Vec_WecSize(pvMap[2*i+1]) ); + Vec_IntFree( vTypes ); + Vec_IntFree( vBufs ); + return pvMap; +} +int Gia_ManDupUifConstrOne( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Int_t * vVec0, Vec_Int_t * vVec1 ) +{ + Vec_Int_t * vTemp = Vec_IntAlloc( Vec_IntSize(vVec0) ); + int i, o0, o1, iRes; + Vec_IntForEachEntryTwo( vVec0, vVec1, o0, o1, i ) + Vec_IntPush( vTemp, Gia_ManHashXor(pNew, Gia_ManObj(p, o0)->Value, Abc_LitNot(Gia_ManObj(p, o1)->Value)) ); + iRes = Gia_ManHashAndMulti( pNew, vTemp ); + Vec_IntFree( vTemp ); + return iRes; +} +int Gia_ManDupUifConstr( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Wec_t ** pvMap, int nTypes ) +{ + int t, i, k, iUif = 1; + for ( t = 0; t < nTypes; t++ ) + { + assert( Vec_WecSize(pvMap[2*t+0]) == Vec_WecSize(pvMap[2*t+1]) ); + for ( i = 0; i < Vec_WecSize(pvMap[2*t+0]); i++ ) + for ( k = i + 1; k < Vec_WecSize(pvMap[2*t+0]); k++ ) + { + int iCond1 = Gia_ManDupUifConstrOne( pNew, p, Vec_WecEntry(pvMap[2*t+0], i), Vec_WecEntry(pvMap[2*t+0], k) ); + int iCond2 = Gia_ManDupUifConstrOne( pNew, p, Vec_WecEntry(pvMap[2*t+1], i), Vec_WecEntry(pvMap[2*t+1], k) ); + int iRes = Gia_ManHashOr( pNew, Abc_LitNot(iCond1), iCond2 ); + iUif = Gia_ManHashAnd( pNew, iUif, iRes ); + } + } + return iUif; +} +Gia_Man_t * Gia_ManDupUif( Gia_Man_t * p ) +{ + Vec_Int_t * vTypes = Gia_ManDupUifBoxTypes( p->vBarBufs ); + Vec_Wec_t ** pvMap = Gia_ManDupUifBuildMap( p ); + Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; + int i, iUif = 0; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + } + iUif = Gia_ManDupUifConstr( pNew, p, pvMap, Vec_IntSize(vTypes) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, pObj->Value, iUif) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + for ( i = 0; i < 2*Vec_IntSize(vTypes); i++ ) + Vec_WecFree( pvMap[i] ); + ABC_FREE( pvMap ); + if ( p->vBarBufs ) + pNew->vBarBufs = Vec_IntDup( p->vBarBufs ); + printf( "Added UIF constraints for %d type%s of boxes.\n", Vec_IntSize(vTypes), Vec_IntSize(vTypes) > 1 ? "s" :"" ); + Vec_IntFree( vTypes ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManDupBlackBoxBuildMap( Gia_Man_t * p ) +{ + Vec_Int_t * vMap = Vec_IntAlloc( p->nBufs ); int i, Item; + Vec_IntForEachEntry( p->vBarBufs, Item, i ) + Vec_IntFillExtra( vMap, Vec_IntSize(vMap) + (Item >> 16), Item & 1 ); + assert( p->nBufs == Vec_IntSize(vMap) ); + return vMap; +} +Gia_Man_t * Gia_ManDupBlackBox( Gia_Man_t * p ) +{ + Vec_Int_t * vMap = Gia_ManDupBlackBoxBuildMap( p ); + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, k = 0, iCi = 0, nCis = Gia_ManCiNum(p) + Vec_IntSum(vMap); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + for ( i = 0; i < nCis; i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + { + if ( Vec_IntEntry(vMap, k++) ) // out + pObj->Value = Gia_ManCiLit(pNew, iCi++); + else + pObj->Value = Gia_ObjFanin0Copy(pObj); + } + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManCiLit(pNew, iCi++); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + assert( k == p->nBufs && iCi == nCis ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vMap ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates with the care set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupWithCare( Gia_Man_t * p, Gia_Man_t * pCare ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iCare = -1; + assert( Gia_ManCiNum(pCare) == Gia_ManCiNum(p) ); + assert( Gia_ManCoNum(pCare) == 1 ); + assert( Gia_ManRegNum(p) == 0 ); + assert( Gia_ManRegNum(pCare) == 0 ); + pNew = Gia_ManStart( 2*Gia_ManObjNum(p) + Gia_ManObjNum(pCare) ); + pNew->pName = Abc_UtilStrsavTwo( pNew->pName ? pNew->pName : (char *)"test", (char *)"_care" ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(pCare)->Value = 0; + Gia_ManForEachCi( pCare, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( pCare, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( pCare, pObj, i ) + iCare = Gia_ObjFanin0Copy(pObj); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManCi(pCare, i)->Value; + Gia_ManForEachAnd( p, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, iCare, pObj->Value ); + } + Gia_ManForEachCo( p, pObj, i ) + { + pObj->Value = Gia_ObjFanin0Copy(pObj); + pObj->Value = Gia_ManHashAnd( pNew, iCare, pObj->Value ); + Gia_ManAppendCo( pNew, pObj->Value ); + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManProdAdderGen( int nArgA, int nArgB, int Seed, int fSigned, int fCla ) +{ + extern void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vLevels, Vec_Int_t * vRes, int fSigned, int fCla ); + int i, k, x, fCompl, iLit; char pNameP[32], pNameT[32]; + Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB ); + Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB ); + Vec_Int_t * vRes = Vec_IntAlloc( nArgA + nArgB ); + Vec_Int_t * vArgA = Vec_IntAlloc( nArgA ); + Vec_Int_t * vArgB = Vec_IntAlloc( nArgB ), * vLevel; + Gia_Man_t * pProd = Gia_ManStart( 1000 ); + Gia_Man_t * pTree = Gia_ManStart( 1000 ), * pTemp; + Gia_ManHashAlloc( pTree ); + pProd->pName = Abc_UtilStrsav( "prod" ); + pTree->pName = Abc_UtilStrsav( "tree" ); + for ( x = 0; x < nArgA; x++ ) + Vec_IntPush( vArgA, Gia_ManAppendCi(pProd) ); + for ( x = 0; x < nArgB; x++ ) + Vec_IntPush( vArgB, Gia_ManAppendCi(pProd) ); + for ( x = 0; x < nArgA + nArgB; x++ ) + { + for ( i = 0; i < nArgA; i++ ) + for ( k = 0; k < nArgB; k++ ) + { + if ( i + k != x ) + continue; + fCompl = fSigned && ((i == nArgA-1) ^ (k == nArgB-1)); + iLit = Abc_LitNotCond(Gia_ManAppendAnd(pProd, Vec_IntEntry(vArgA, i), Vec_IntEntry(vArgB, k)), fCompl); + Gia_ManAppendCo( pProd, iLit ); + Vec_WecPush( vProds, i+k, Gia_ManAppendCi(pTree) ); + Vec_WecPush( vLevels, i+k, 0 ); + } + } + if ( fSigned ) + { + Vec_WecPush( vProds, nArgA, 1 ); + Vec_WecPush( vLevels, nArgA, 0 ); + + Vec_WecPush( vProds, nArgA+nArgB-1, 1 ); + Vec_WecPush( vLevels, nArgA+nArgB-1, 0 ); + } + if ( Seed ) + { + Abc_Random( 1 ); + for ( x = 0; x < Seed; x++ ) + Abc_Random( 0 ); + Vec_WecForEachLevel( vProds, vLevel, x ) + if ( Vec_IntSize(vLevel) > 1 ) + Vec_IntRandomizeOrder( vLevel ); + } + Wlc_BlastReduceMatrix( pTree, vProds, vLevels, vRes, fSigned, fCla ); + Vec_IntShrink( vRes, nArgA + nArgB ); + assert( Vec_IntSize(vRes) == nArgA + nArgB ); + Vec_IntForEachEntry( vRes, iLit, x ) + Gia_ManAppendCo( pTree, iLit ); + pTree = Gia_ManCleanup( pTemp = pTree ); + Gia_ManStop( pTemp ); + + sprintf( pNameP, "prod%d%d.aig", nArgA, nArgB ); + sprintf( pNameT, "tree%d%d.aig", nArgA, nArgB ); + Gia_AigerWrite( pProd, pNameP, 0, 0, 0 ); + Gia_AigerWrite( pTree, pNameT, 0, 0, 0 ); + Gia_ManStop( pProd ); + Gia_ManStop( pTree ); + printf( "Dumped files \"%s\" and \"%s\".\n", pNameP, pNameT ); + + Vec_WecFree( vProds ); + Vec_WecFree( vLevels ); + Vec_IntFree( vArgA ); + Vec_IntFree( vArgB ); + Vec_IntFree( vRes ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupAddFlop( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) + 2 ); + pNew->pName = Abc_UtilStrsav(p->pName); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManAppendCo( pNew, 0 ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p)+1 ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ) +{ + Vec_Int_t * vLits; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iLit; + if ( Gia_ManBufNum(p1) == 0 ) { + printf( "The first AIG should have a boundary.\n" ); + return NULL; + } + if ( Gia_ManBufNum(p2) != 0 ) { + printf( "The second AIG should have no boundary.\n" ); + return NULL; + } + assert( Gia_ManBufNum(p1) > 0 ); + assert( Gia_ManBufNum(p2) == 0 ); + assert( Gia_ManRegNum(p1) == 0 ); + assert( Gia_ManRegNum(p2) == 0 ); + assert( Gia_ManCiNum(p1) == Gia_ManCiNum(p2) ); + assert( Gia_ManCoNum(p1) == Gia_ManCoNum(p2) ); + vLits = Vec_IntAlloc( Gia_ManBufNum(p1) ); + if ( fVerbose ) + printf( "Creating a boundary miter with %d inputs, %d outputs, and %d buffers.\n", + Gia_ManCiNum(p1), Gia_ManCoNum(p1), Gia_ManBufNum(p1) ); + pNew = Gia_ManStart( Gia_ManObjNum(p1) + Gia_ManObjNum(p2) ); + pNew->pName = ABC_ALLOC( char, strlen(p1->pName) + 10 ); + sprintf( pNew->pName, "%s_bmiter", p1->pName ); + Gia_ManHashStart( pNew ); + Gia_ManConst0(p1)->Value = 0; + Gia_ManConst0(p2)->Value = 0; + Gia_ManForEachCi( p1, pObj, i ) + pObj->Value = Gia_ManCi(p2, i)->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p2, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachAnd( p1, pObj, i ) { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( Gia_ObjIsBuf(pObj) ) + Vec_IntPush( vLits, pObj->Value ); + } + Gia_ManForEachCo( p2, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachCo( p1, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Vec_IntForEachEntry( vLits, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Vec_IntFree( vLits ); + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/abc/src/aig/gia/giaEmbed.c b/abc/src/aig/gia/giaEmbed.c index b646a311211..28d28483f84 100644 --- a/abc/src/aig/gia/giaEmbed.c +++ b/abc/src/aig/gia/giaEmbed.c @@ -32,7 +32,7 @@ ABC_NAMESPACE_IMPL_START http://www.emis.de/journals/JGAA/accepted/2004/HarelKoren2004.8.2.pdf Iterative refinement is described in the paper: F. A. Aloul, I. L. Markov, and K. A. Sakallah. - "FORCE: A Fast and Easy-To-Implement Variable-Ordering Heuristic", Proc. GLSVLSI’03. + "FORCE: A Fast and Easy-To-Implement Variable-Ordering Heuristic", Proc. GLSVLSI 03. http://www.eecs.umich.edu/~imarkov/pubs/conf/glsvlsi03-force.pdf */ diff --git a/abc/src/aig/gia/giaEquiv.c b/abc/src/aig/gia/giaEquiv.c index 84d9f1b1eb7..1c3aa4311a7 100644 --- a/abc/src/aig/gia/giaEquiv.c +++ b/abc/src/aig/gia/giaEquiv.c @@ -185,6 +185,7 @@ Gia_Man_t * Gia_ManComputeGiaEquivs( Gia_Man_t * pGia, int nConfs, int fVerbose Gia_Man_t * pTemp; Cec_ParFra_t ParsFra, * pPars = &ParsFra; Cec_ManFraSetDefaultParams( pPars ); + pPars->nItersMax = 100; pPars->fUseOrigIds = 1; pPars->fSatSweeping = 1; pPars->nBTLimit = nConfs; @@ -268,6 +269,7 @@ int * Gia_ManDeriveNexts( Gia_Man_t * p ) pTails[i] = i; for ( i = 0; i < Gia_ManObjNum(p); i++ ) { + //if ( p->pReprs[i].iRepr == GIA_VOID ) if ( !p->pReprs[i].iRepr || p->pReprs[i].iRepr == GIA_VOID ) continue; pNexts[ pTails[p->pReprs[i].iRepr] ] = i; @@ -479,8 +481,10 @@ void Gia_ManEquivPrintClasses( Gia_Man_t * p, int fVerbose, float Mem ) } CounterX -= Gia_ManCoNum(p); nLits = Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX; - Abc_Print( 1, "cst =%8d cls =%7d lit =%8d unused =%8d proof =%6d mem =%5.2f MB\n", - Counter0, Counter, nLits, CounterX, Proved, (Mem == 0.0) ? 8.0*Gia_ManObjNum(p)/(1<<20) : Mem ); +// Abc_Print( 1, "cst =%8d cls =%7d lit =%8d unused =%8d proof =%6d mem =%5.2f MB\n", +// Counter0, Counter, nLits, CounterX, Proved, (Mem == 0.0) ? 8.0*Gia_ManObjNum(p)/(1<<20) : Mem ); + Abc_Print( 1, "cst =%8d cls =%7d lit =%8d unused =%8d proof =%6d\n", + Counter0, Counter, nLits, CounterX, Proved ); assert( Gia_ManEquivCheckLits( p, nLits ) ); if ( fVerbose ) { @@ -508,6 +512,67 @@ void Gia_ManEquivPrintClasses( Gia_Man_t * p, int fVerbose, float Mem ) } } + +/**Function************************************************************* + + Synopsis [Map representatives into class members with minimum level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManChoiceMinLevel_rec( Gia_Man_t * p, int iPivot, int fDiveIn, Vec_Int_t * vMap ) +{ + int Level0, Level1, LevelMax; + Gia_Obj_t * pPivot = Gia_ManObj( p, iPivot ); + if ( Gia_ObjIsCi(pPivot) || iPivot == 0 ) + return 0; + if ( Gia_ObjLevel(p, pPivot) ) + return Gia_ObjLevel(p, pPivot); + if ( fDiveIn && Gia_ObjIsClass(p, iPivot) ) + { + int iObj, ObjMin = -1, iRepr = Gia_ObjRepr(p, iPivot), LevMin = ABC_INFINITY; + Gia_ClassForEachObj( p, iRepr, iObj ) + { + int LevCur = Gia_ManChoiceMinLevel_rec( p, iObj, 0, vMap ); + if ( LevMin > LevCur ) + { + LevMin = LevCur; + ObjMin = iObj; + } + } + assert( LevMin > 0 ); + Vec_IntWriteEntry( vMap, iRepr, ObjMin ); + Gia_ClassForEachObj( p, iRepr, iObj ) + Gia_ObjSetLevelId( p, iObj, LevMin ); + return LevMin; + } + assert( Gia_ObjIsAnd(pPivot) ); + Level0 = Gia_ManChoiceMinLevel_rec( p, Gia_ObjFaninId0(pPivot, iPivot), 1, vMap ); + Level1 = Gia_ManChoiceMinLevel_rec( p, Gia_ObjFaninId1(pPivot, iPivot), 1, vMap ); + LevelMax = 1 + Abc_MaxInt(Level0, Level1); + Gia_ObjSetLevel( p, pPivot, LevelMax ); + return LevelMax; +} +Vec_Int_t * Gia_ManChoiceMinLevel( Gia_Man_t * p ) +{ + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; + int i, LevelCur, LevelMax = 0; +// assert( Gia_ManRegNum(p) == 0 ); + Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); + Gia_ManForEachCo( p, pObj, i ) + { + LevelCur = Gia_ManChoiceMinLevel_rec( p, Gia_ObjFaninId0p(p, pObj), 1, vMap ); + LevelMax = Abc_MaxInt(LevelMax, LevelCur); + } + //printf( "Max level %d\n", LevelMax ); + return vMap; +} + /**Function************************************************************* Synopsis [Returns representative node.] @@ -581,6 +646,27 @@ Gia_Man_t * Gia_ManEquivReduce( Gia_Man_t * p, int fUseAll, int fDualOut, int fS Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; + if ( !p->pReprs && p->pSibls ) + { + int * pMap = ABC_FALLOC( int, Gia_ManObjNum(p) ); + p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + Gia_ObjSetRepr( p, i, GIA_VOID ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( p->pSibls[i] > 0 ) + { + if ( pMap[p->pSibls[i]] == -1 ) + pMap[p->pSibls[i]] = p->pSibls[i]; + pMap[i] = pMap[p->pSibls[i]]; + } + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( p->pSibls[i] > 0 ) + Gia_ObjSetRepr( p, i, pMap[i] ); + //printf( "Created equivalence classes.\n" ); + ABC_FREE( p->pNexts ); + p->pNexts = Gia_ManDeriveNexts( p ); + ABC_FREE( pMap ); + } if ( !p->pReprs ) { Abc_Print( 1, "Gia_ManEquivReduce(): Equivalence classes are not available.\n" ); @@ -598,7 +684,8 @@ Gia_Man_t * Gia_ManEquivReduce( Gia_Man_t * p, int fUseAll, int fDualOut, int fS if ( i == Gia_ManObjNum(p) ) { // Abc_Print( 1, "Gia_ManEquivReduce(): There are no equivalences to reduce.\n" ); - return NULL; +// return NULL; + return Gia_ManDup( p ); } /* if ( !Gia_ManCheckTopoOrder( p ) ) @@ -628,6 +715,101 @@ Gia_Man_t * Gia_ManEquivReduce( Gia_Man_t * p, int fUseAll, int fDualOut, int fS return pNew; } +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEquivReduce2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vMap, int fDiveIn ) +{ + Gia_Obj_t * pRepr; + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + if ( fDiveIn && (pRepr = Gia_ManEquivRepr(p, pObj, 1, 0)) ) + { + int iTemp, iRepr = Gia_ObjId(p, pRepr); + Gia_Obj_t * pRepr2 = Gia_ManObj( p, Vec_IntEntry(vMap, iRepr) ); + Gia_ManEquivReduce2_rec( pNew, p, pRepr2, vMap, 0 ); + Gia_ClassForEachObj( p, iRepr, iTemp ) + { + Gia_Obj_t * pTemp = Gia_ManObj(p, iTemp); + pTemp->Value = Abc_LitNotCond( pRepr2->Value, Gia_ObjPhaseReal(pRepr2) ^ Gia_ObjPhaseReal(pTemp) ); + } + assert( ~pObj->Value ); + assert( ~pRepr->Value ); + assert( ~pRepr2->Value ); + return; + } + Gia_ManEquivReduce2_rec( pNew, p, Gia_ObjFanin0(pObj), vMap, 1 ); + Gia_ManEquivReduce2_rec( pNew, p, Gia_ObjFanin1(pObj), vMap, 1 ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManEquivReduce2( Gia_Man_t * p ) +{ + Vec_Int_t * vMap; + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + if ( !p->pReprs && p->pSibls ) + { + int * pMap = ABC_FALLOC( int, Gia_ManObjNum(p) ); + p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + Gia_ObjSetRepr( p, i, GIA_VOID ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( p->pSibls[i] > 0 ) + { + if ( pMap[p->pSibls[i]] == -1 ) + pMap[p->pSibls[i]] = p->pSibls[i]; + pMap[i] = pMap[p->pSibls[i]]; + } + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( p->pSibls[i] > 0 ) + Gia_ObjSetRepr( p, i, pMap[i] ); + //printf( "Created equivalence classes.\n" ); + ABC_FREE( p->pNexts ); + p->pNexts = Gia_ManDeriveNexts( p ); + ABC_FREE( pMap ); + } + if ( !p->pReprs ) + { + Abc_Print( 1, "Gia_ManEquivReduce(): Equivalence classes are not available.\n" ); + return NULL; + } + // check if there are any equivalences defined + Gia_ManForEachObj( p, pObj, i ) + if ( Gia_ObjReprObj(p, i) != NULL ) + break; + if ( i == Gia_ManObjNum(p) ) + return Gia_ManDup( p ); + vMap = Gia_ManChoiceMinLevel( p ); + Gia_ManSetPhase( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManEquivReduce2_rec( pNew, p, Gia_ObjFanin0(pObj), vMap, 1 ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Vec_IntFree( vMap ); + return pNew; +} + + /**Function************************************************************* Synopsis [Reduces AIG using equivalence classes.] @@ -1687,7 +1869,7 @@ void Gia_ManEquivToChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pOb Gia_Obj_t * pRepr, * pReprNew, * pObjNew; if ( ~pObj->Value ) return; - if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) + if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) && !Gia_ObjFailed(p,Gia_ObjId(p,pObj)) ) { if ( Gia_ObjIsConst0(pRepr) ) { @@ -1806,7 +1988,7 @@ Gia_Man_t * Gia_ManEquivToChoices( Gia_Man_t * p, int nSnapshots ) pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); pNew->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p) ); for ( i = 0; i < Gia_ManObjNum(p); i++ ) - Gia_ObjSetRepr( pNew, i, GIA_VOID ); + pNew->pReprs[i].iRepr = GIA_VOID; Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) @@ -1994,14 +2176,14 @@ int Gia_CommandSpecI( Gia_Man_t * pGia, int nFramesInit, int nBTLimitInit, int f } } // write equivalence classes - Gia_AigerWrite( pGia, "gore.aig", 0, 0 ); + Gia_AigerWrite( pGia, "gore.aig", 0, 0, 0 ); // reduce the model pReduce = Gia_ManSpecReduce( pGia, 0, 0, 1, 0, 0 ); if ( pReduce ) { pReduce = Gia_ManSeqStructSweep( pAux = pReduce, 1, 1, 0 ); Gia_ManStop( pAux ); - Gia_AigerWrite( pReduce, "gsrm.aig", 0, 0 ); + Gia_AigerWrite( pReduce, "gsrm.aig", 0, 0, 0 ); // Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", "gsrm.aig" ); // Gia_ManPrintStatsShort( pReduce ); Gia_ManStop( pReduce ); @@ -2408,6 +2590,294 @@ void Gia_ManFilterEquivsUsingLatches( Gia_Man_t * pGia, int fFlopsOnly, int fFlo Abc_Print( 1, "The number of literals: Before = %d. After = %d.\n", iLitsOld, iLitsNew ); } +/**Function************************************************************* + + Synopsis [Changing node order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManChangeOrder_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + if ( Gia_ObjIsCi(pObj) ) + return pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManChangeOrder_rec( pNew, p, Gia_ObjFanin0(pObj) ); + if ( Gia_ObjIsCo(pObj) ) + return pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManChangeOrder_rec( pNew, p, Gia_ObjFanin1(pObj) ); + return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManChangeOrder( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, k; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachClass( p, i ) + Gia_ClassForEachObj( p, i, k ) + Gia_ManChangeOrder_rec( pNew, p, Gia_ManObj(p, k) ); + Gia_ManForEachConst( p, k ) + Gia_ManChangeOrder_rec( pNew, p, Gia_ManObj(p, k) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManChangeOrder_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + assert( Gia_ManObjNum(pNew) == Gia_ManObjNum(p) ); + return pNew; +} +void Gia_ManTransferEquivs( Gia_Man_t * p, Gia_Man_t * pNew ) +{ + Vec_Int_t * vClass; + int i, k, iNode, iRepr; + assert( Gia_ManObjNum(p) == Gia_ManObjNum(pNew) ); + assert( p->pReprs != NULL ); + assert( p->pNexts != NULL ); + assert( pNew->pReprs == NULL ); + assert( pNew->pNexts == NULL ); + // start representatives + pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pNew) ); + for ( i = 0; i < Gia_ManObjNum(pNew); i++ ) + Gia_ObjSetRepr( pNew, i, GIA_VOID ); + // iterate over constant candidates + Gia_ManForEachConst( p, i ) + Gia_ObjSetRepr( pNew, Abc_Lit2Var(Gia_ManObj(p, i)->Value), 0 ); + // iterate over class candidates + vClass = Vec_IntAlloc( 100 ); + Gia_ManForEachClass( p, i ) + { + Vec_IntClear( vClass ); + Gia_ClassForEachObj( p, i, k ) + Vec_IntPushUnique( vClass, Abc_Lit2Var(Gia_ManObj(p, k)->Value) ); + assert( Vec_IntSize( vClass ) > 1 ); + Vec_IntSort( vClass, 0 ); + iRepr = Vec_IntEntry( vClass, 0 ); + Vec_IntForEachEntryStart( vClass, iNode, k, 1 ) + Gia_ObjSetRepr( pNew, iNode, iRepr ); + } + Vec_IntFree( vClass ); + pNew->pNexts = Gia_ManDeriveNexts( pNew ); +} +void Gia_ManTransferTest( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int i; + Gia_Rpr_t * pReprs = p->pReprs; // representatives (for CIs and ANDs) + int * pNexts = p->pNexts; // next nodes in the equivalence classes + Gia_Man_t * pNew = Gia_ManChangeOrder(p); + //Gia_ManEquivPrintClasses( p, 1, 0 ); + assert( Gia_ManObjNum(p) == Gia_ManObjNum(pNew) ); + Gia_ManTransferEquivs( p, pNew ); + p->pReprs = NULL; + p->pNexts = NULL; + // make new point to old + Gia_ManForEachObj( p, pObj, i ) + { + assert( !Abc_LitIsCompl(pObj->Value) ); + Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value))->Value = Abc_Var2Lit(i, 0); + } + Gia_ManTransferEquivs( pNew, p ); + //Gia_ManEquivPrintClasses( p, 1, 0 ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + pReprs[i].fProved = 0; + //printf( "%5d : %5d %5d %5d %5d\n", i, *(int*)&p->pReprs[i], *(int*)&pReprs[i], (int)p->pNexts[i], (int)pNexts[i] ); + if ( memcmp(p->pReprs, pReprs, sizeof(int)*Gia_ManObjNum(p)) ) + printf( "Verification of reprs failed.\n" ); + else + printf( "Verification of reprs succeeded.\n" ); + if ( memcmp(p->pNexts, pNexts, sizeof(int)*Gia_ManObjNum(p)) ) + printf( "Verification of nexts failed.\n" ); + else + printf( "Verification of nexts succeeded.\n" ); + ABC_FREE( pNew->pReprs ); + ABC_FREE( pNew->pNexts ); + ABC_FREE( pReprs ); + ABC_FREE( pNexts ); + Gia_ManStop( pNew ); +} + + +/**Function************************************************************* + + Synopsis [Converting AIG after SAT sweeping into AIG with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec4_ManMarkIndependentClasses_rec( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; + assert( iObj > 0 ); + if ( Gia_ObjIsTravIdPreviousId(p, iObj) ) // failed + return 0; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) // passed + return 1; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return 1; + assert( Gia_ObjIsAnd(pObj) ); + if ( Cec4_ManMarkIndependentClasses_rec( p, Gia_ObjFaninId0(pObj, iObj) ) && + Cec4_ManMarkIndependentClasses_rec( p, Gia_ObjFaninId1(pObj, iObj) ) ) + return 1; + Gia_ObjSetTravIdPreviousId(p, iObj); + return 0; +} +int Cec4_ManMarkIndependentClasses( Gia_Man_t * p, Gia_Man_t * pNew ) +{ + int iObjNew, iRepr, iObj, Res, fHaveChoices = 0; + Gia_ManCleanMark01(p); + Gia_ManForEachClass( p, iRepr ) + { + Gia_ManIncrementTravId( pNew ); + Gia_ManIncrementTravId( pNew ); + iObjNew = Abc_Lit2Var( Gia_ManObj(p, iRepr)->Value ); + Res = Cec4_ManMarkIndependentClasses_rec( pNew, iObjNew ); + assert( Res == 1 ); + Gia_ObjSetTravIdPreviousId( pNew, iObjNew ); + p->pReprs[iRepr].fColorA = 1; + Gia_ClassForEachObj1( p, iRepr, iObj ) + { + assert( p->pReprs[iObj].iRepr == (unsigned)iRepr ); + iObjNew = Abc_Lit2Var( Gia_ManObj(p, iObj)->Value ); + if ( Cec4_ManMarkIndependentClasses_rec( pNew, iObjNew ) ) + { + p->pReprs[iObj].fColorA = 1; + fHaveChoices = 1; + } + Gia_ObjSetTravIdPreviousId( pNew, iObjNew ); + } + } + return fHaveChoices; +} +int Cec4_ManSatSolverAnd_rec( Gia_Man_t * pCho, Gia_Man_t * p, Gia_Man_t * pNew, int iObj ) +{ + return 0; +} +int Cec4_ManSatSolverChoices_rec( Gia_Man_t * pCho, Gia_Man_t * p, Gia_Man_t * pNew, int iObj ) +{ + if ( !Gia_ObjIsClass(p, iObj) ) + return Cec4_ManSatSolverAnd_rec( pCho, p, pNew, iObj ); + else + { + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + int i, iHead, iNext, iRepr = Gia_ObjIsHead(p, iObj) ? iObj : Gia_ObjRepr(p, iObj); + Gia_ClassForEachObj( p, iRepr, iObj ) + if ( p->pReprs[iObj].fColorA ) + Vec_IntPush( vLits, Cec4_ManSatSolverAnd_rec( pCho, p, pNew, iObj ) ); + Vec_IntSort( vLits, 1 ); + iHead = Abc_Lit2Var( Vec_IntEntry(vLits, 0) ); + if ( Vec_IntSize(vLits) > 1 ) + { + Vec_IntForEachEntryStart( vLits, iNext, i, 1 ) + { + pCho->pSibls[iHead] = Abc_Lit2Var(iNext); + iHead = Abc_Lit2Var(iNext); + } + } + return Abc_LitNotCond( Vec_IntEntry(vLits, 0), Gia_ManObj(p, iHead)->fPhase ); + } +} +Gia_Man_t * Cec4_ManSatSolverChoices( Gia_Man_t * p, Gia_Man_t * pNew ) +{ + Gia_Man_t * pCho; + Gia_Obj_t * pObj; + int i, DriverId; + // mark topologically dependent equivalent nodes + if ( !Cec4_ManMarkIndependentClasses( p, pNew ) ) + return Gia_ManDup( pNew ); + // rebuild AIG in a different order with choices + pCho = Gia_ManStart( Gia_ManObjNum(pNew) ); + pCho->pName = Abc_UtilStrsav( p->pName ); + pCho->pSpec = Abc_UtilStrsav( p->pSpec ); + pCho->pSibls = ABC_CALLOC( int, Gia_ManObjNum(pNew) ); + Gia_ManFillValue(pNew); + Gia_ManConst0(pNew)->Value = 0; + for ( i = 0; i < Gia_ManCiNum(pNew); i++ ) + Gia_ManCi(pNew, i)->Value = Gia_ManAppendCi( pCho ); + Gia_ManForEachCoDriverId( p, DriverId, i ) + Cec4_ManSatSolverChoices_rec( pCho, p, pNew, DriverId ); + Gia_ManForEachCo( pNew, pObj, i ) + pObj->Value = Gia_ManAppendCo( pCho, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pCho, Gia_ManRegNum(p) ); + return pCho; +} + +/**Function************************************************************* + + Synopsis [Converting AIG after SAT sweeping into AIG with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCombSpecReduce( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pRepr; int i, iLit; + Vec_Int_t * vXors = Vec_IntAlloc( 100 ); + Gia_Man_t * pTemp, * pNew = Gia_ManStart( Gia_ManObjNum(p) ); + assert( p->pReprs && p->pNexts ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManLevelNum(p); + Gia_ManSetPhase(p); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pRepr = Gia_ObjReprObj( p, i ); + if ( pRepr && Abc_Lit2Var(pObj->Value) != Abc_Lit2Var(pRepr->Value) ) + { + //if ( Gia_ObjLevel(p, pRepr) > Gia_ObjLevel(p, pObj) + 50 ) + //printf( "%d %d ", Gia_ObjLevel(p, pRepr), Gia_ObjLevel(p, pObj) ); + iLit = Abc_LitNotCond( pRepr->Value, pObj->fPhase ^ pRepr->fPhase ); + Vec_IntPush( vXors, Gia_ManHashXor( pNew, pObj->Value, iLit ) ); + pObj->Value = iLit; + } + } + Gia_ManHashStop( pNew ); + if ( Vec_IntSize(vXors) == 0 ) + Vec_IntPush( vXors, 0 ); + Vec_IntForEachEntry( vXors, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Vec_IntFree( vXors ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +void Gia_ManCombSpecReduceTest( Gia_Man_t * p, char * pFileName ) +{ + Gia_Man_t * pSrm = Gia_ManCombSpecReduce( p ); + if ( pFileName == NULL ) + pFileName = "test.aig"; + Gia_AigerWrite( pSrm, pFileName, 0, 0, 0 ); + Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", pFileName ); + Gia_ManStop( pSrm ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/abc/src/aig/gia/giaFalse.c b/abc/src/aig/gia/giaFalse.c index a055b5bcf5f..50cb8ea72f0 100644 --- a/abc/src/aig/gia/giaFalse.c +++ b/abc/src/aig/gia/giaFalse.c @@ -457,7 +457,7 @@ Gia_Man_t * Gia_ManCheckOne( Gia_Man_t * p, int iOut, int iObj, int nTimeOut, in if ( pNew ) { Gia_Man_t * pTemp = Gia_ManDupDfsNode( p, Gia_ManObj(p, iObj) ); - Gia_AigerWrite( pTemp, "false.aig", 0, 0 ); + Gia_AigerWrite( pTemp, "false.aig", 0, 0, 0 ); Abc_Print( 1, "Dumping cone with %d nodes into file \"%s\".\n", Gia_ManAndNum(pTemp), "false.aig" ); Gia_ManStop( pTemp ); } diff --git a/abc/src/aig/gia/giaFanout.c b/abc/src/aig/gia/giaFanout.c index 6a94035432e..fd58bfeb85b 100644 --- a/abc/src/aig/gia/giaFanout.c +++ b/abc/src/aig/gia/giaFanout.c @@ -214,7 +214,7 @@ Vec_Int_t * Gia_ManStartFanoutMap( Gia_Man_t * p, Vec_Int_t * vFanoutNums ) Gia_Obj_t * pObj; int i, iOffset; iOffset = Gia_ManObjNum(p); - vEdgeMap = Vec_IntStart( iOffset + Gia_ManMuxNum(p) + 2 * Gia_ManAndNum(p) + Gia_ManCoNum(p) ); + vEdgeMap = Vec_IntStart( iOffset + Gia_ManMuxNum(p) + 2 * Gia_ManAndNum(p) + Gia_ManCoNum(p) - Gia_ManBufNum(p) ); Gia_ManForEachObj( p, pObj, i ) { Vec_IntWriteEntry( vEdgeMap, i, iOffset ); @@ -261,9 +261,8 @@ void Gia_ManStaticFanoutStart( Gia_Man_t * p ) Gia_ObjSetFanout( p, pFanin, iFanout, pObj ); Vec_IntAddToEntry( vCounts, Gia_ObjId(p, pFanin), 1 ); } - if ( Gia_ObjIsAnd(pObj) ) + if ( Gia_ObjIsAnd(pObj) && !Gia_ObjIsBuf(pObj) ) { - pFanin = Gia_ObjFanin1(pObj); iFanout = Vec_IntEntry( vCounts, Gia_ObjId(p, pFanin) ); Gia_ObjSetFanout( p, pFanin, iFanout, pObj ); @@ -284,6 +283,102 @@ void Gia_ManStaticFanoutStart( Gia_Man_t * p ) Vec_IntFree( vCounts ); } + +/**Function************************************************************* + + Synopsis [Compute the map of all edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManStartMappingFanoutMap( Gia_Man_t * p, Vec_Int_t * vFanoutNums ) +{ + Gia_Obj_t * pObj; + int i, iOffset = Gia_ManObjNum(p); + Vec_Int_t * vEdgeMap = Vec_IntAlloc( 2 * iOffset ); + Vec_IntFill( vEdgeMap, iOffset, 0 ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( Vec_IntEntry(vFanoutNums, i) == 0 ) + continue; + Vec_IntWriteEntry( vEdgeMap, i, iOffset ); + iOffset += Vec_IntEntry( vFanoutNums, i ); + Vec_IntFillExtra( vEdgeMap, iOffset, 0 ); + } + //printf( "Fanout map is %.2fx larger than AIG manager.\n", 1.0*Vec_IntSize(vEdgeMap)/Gia_ManObjNum(p) ); + return vEdgeMap; +} + +/**Function************************************************************* + + Synopsis [Allocates static fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjCheckDupMappingFanins( Gia_Man_t * p, int iObj ) +{ + int * pFanins = Gia_ObjLutFanins( p, iObj ); + int i, k, nFanins = Gia_ObjLutSize( p, iObj ); + for ( i = 0; i < nFanins; i++ ) + for ( k = i + 1; k < nFanins; k++ ) + assert( pFanins[i] != pFanins[k] ); +} +void Gia_ManStaticMappingFanoutStart( Gia_Man_t * p, Vec_Int_t ** pvIndex ) +{ + Vec_Int_t * vCounts; + int * pRefsOld; + Gia_Obj_t * pObj, * pFanin; + int i, k, iFan, iFanout, Index; + assert( p->vFanoutNums == NULL ); + assert( p->vFanout == NULL ); + // recompute reference counters + pRefsOld = p->pLutRefs; p->pLutRefs = NULL; + Gia_ManSetLutRefs(p); + p->vFanoutNums = Vec_IntAllocArray( p->pLutRefs, Gia_ManObjNum(p) ); + p->pLutRefs = pRefsOld; + // start the fanout maps + p->vFanout = Gia_ManStartMappingFanoutMap( p, p->vFanoutNums ); + if ( pvIndex ) + *pvIndex = Vec_IntStart( Vec_IntSize(p->vFanout) ); + // incrementally add fanouts + vCounts = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManForEachLut( p, i ) + { + Gia_ObjCheckDupMappingFanins( p, i ); + pObj = Gia_ManObj( p, i ); + Gia_LutForEachFaninIndex( p, i, iFan, k, Index ) + { + pFanin = Gia_ManObj( p, iFan ); + iFanout = Vec_IntEntry( vCounts, iFan ); + Gia_ObjSetFanout( p, pFanin, iFanout, pObj ); + Vec_IntAddToEntry( vCounts, iFan, 1 ); + if ( pvIndex ) + Vec_IntWriteEntry( *pvIndex, Vec_IntEntry(p->vFanout, iFan) + iFanout, Index ); + } + } + Gia_ManForEachCo( p, pObj, i ) + { + iFan = Gia_ObjFaninId0p(p, pObj); + pFanin = Gia_ManObj( p, iFan ); + iFanout = Vec_IntEntry( vCounts, iFan ); + Gia_ObjSetFanout( p, pFanin, iFanout, pObj ); + Vec_IntAddToEntry( vCounts, iFan, 1 ); + } + // double-check the current number of fanouts added + Gia_ManForEachObj( p, pObj, i ) + assert( Vec_IntEntry(vCounts, i) == Gia_ObjFanoutNum(p, pObj) ); + Vec_IntFree( vCounts ); +} + /**Function************************************************************* Synopsis [Deallocates static fanout.] diff --git a/abc/src/aig/gia/giaFx.c b/abc/src/aig/gia/giaFx.c index c6eae6c7de6..032ae5fc472 100644 --- a/abc/src/aig/gia/giaFx.c +++ b/abc/src/aig/gia/giaFx.c @@ -460,7 +460,11 @@ Gia_Man_t * Gia_ManPerformFx( Gia_Man_t * p, int nNewNodesMax, int LitCountMax, Vec_Wec_t * vCubes; Vec_Str_t * vCompl; if ( Gia_ManAndNum(p) == 0 ) - return Gia_ManDup(p); + { + pNew = Gia_ManDup(p); + Gia_ManTransferTiming( pNew, p ); + return pNew; + } // abctime clk; assert( Gia_ManHasMapping(p) ); // collect information diff --git a/abc/src/aig/gia/giaGen.c b/abc/src/aig/gia/giaGen.c new file mode 100644 index 00000000000..cb56ef64d23 --- /dev/null +++ b/abc/src/aig/gia/giaGen.c @@ -0,0 +1,933 @@ +/**CFile**************************************************************** + + FileName [giaGen.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaGen.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_DeriveAig( Vec_Wrd_t * vSims, Vec_Str_t * vSimsOut ) +{ + int nInputs = 32*32*24; + int nWords = nInputs/64; + int nExamps = 64; + int i, e, iLitOut[10] = {0}; + Gia_Man_t * pNew; + assert( Vec_WrdSize(vSims) % nInputs == 0 ); + pNew = Gia_ManStart( nInputs * nExamps + 10000 ); + for ( i = 0; i < nInputs; i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashStart( pNew ); + for ( e = 0; e < nExamps; e++ ) + { + int Class = Vec_StrEntry( vSimsOut, e ); + int This = 1; + word * pSim = Vec_WrdEntryP( vSims, e*nWords ); + for ( i = 0; i < nInputs; i++ ) + This = Gia_ManHashAnd( pNew, This, Abc_Var2Lit(i+1, !Abc_TtGetBit(pSim, i)) ); + assert( Class >= 0 && Class <= 9 ); + iLitOut[Class] = Gia_ManHashOr( pNew, iLitOut[Class], This ); + //printf( "Finished example %d\n", e ); + } + for ( i = 0; i < 10; i++ ) + Gia_ManAppendCo( pNew, iLitOut[i] ); + //pNew = Gia_ManCleanup( pTemp = pNew ); + //Gia_ManStop( pTemp ); + return pNew; +} +void Gia_DeriveAigTest() +{ + extern int Gia_ManReadCifar10File( char * pFileName, Vec_Wrd_t ** pvSimsIn, Vec_Str_t ** pvSimsOut, int * pnExamples ); + char pFileName[100] = "test"; + Vec_Wrd_t * vSimsIn; + Vec_Str_t * vSimsOut; + int nExamples = 0; + int nInputs = Gia_ManReadCifar10File( pFileName, &vSimsIn, &vSimsOut, &nExamples ); + Gia_Man_t * pThis = Gia_DeriveAig( vSimsIn, vSimsOut ); + Gia_AigerWrite( pThis, "examples64.aig", 0, 0, 0 ); + printf( "Dumped file \"%s\".\n", "examples64.aig" ); + Gia_ManStop( pThis ); + Vec_WrdFree( vSimsIn ); + Vec_StrFree( vSimsOut ); + nInputs = 0; +} + + +/**Function************************************************************* + + Synopsis [Populate internal simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word * Gia_ManObjSim( Gia_Man_t * p, int iObj ) +{ + return Vec_WrdEntryP( p->vSims, p->nSimWords * iObj ); +} +static inline void Gia_ManObjSimPi( Gia_Man_t * p, int iObj ) +{ + int w; + word * pSim = Gia_ManObjSim( p, iObj ); + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = Gia_ManRandomW( 0 ); +// pSim[0] <<= 1; +} +static inline void Gia_ManObjSimPo( Gia_Man_t * p, int iObj ) +{ + int w; + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + word * pSimCo = Gia_ManObjSim( p, iObj ); + word * pSimDri = Gia_ManObjSim( p, Gia_ObjFaninId0(pObj, iObj) ); + if ( Gia_ObjFaninC0(pObj) ) + for ( w = 0; w < p->nSimWords; w++ ) + pSimCo[w] = ~pSimDri[w]; + else + for ( w = 0; w < p->nSimWords; w++ ) + pSimCo[w] = pSimDri[w]; +} +static inline void Gia_ManObjSimAnd( Gia_Man_t * p, int iObj ) +{ + int w; + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + word * pSim = Gia_ManObjSim( p, iObj ); + word * pSim0 = Gia_ManObjSim( p, Gia_ObjFaninId0(pObj, iObj) ); + word * pSim1 = Gia_ManObjSim( p, Gia_ObjFaninId1(pObj, iObj) ); + if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = ~pSim0[w] & ~pSim1[w]; + else if ( Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ) + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = ~pSim0[w] & pSim1[w]; + else if ( !Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = pSim0[w] & ~pSim1[w]; + else + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = pSim0[w] & pSim1[w]; +} +int Gia_ManSimulateWords( Gia_Man_t * p, int nWords ) +{ + Gia_Obj_t * pObj; int i; + // allocate simulation info for one timeframe + Vec_WrdFreeP( &p->vSims ); + p->vSims = Vec_WrdStart( Gia_ManObjNum(p) * nWords ); + p->nSimWords = nWords; + // perform simulation + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + Gia_ManObjSimAnd( p, i ); + else if ( Gia_ObjIsCi(pObj) ) + Gia_ManObjSimPi( p, i ); + else if ( Gia_ObjIsCo(pObj) ) + Gia_ManObjSimPo( p, i ); + else assert( 0 ); + } + return 1; +} + +int Gia_ManSimulateWordsInit( Gia_Man_t * p, Vec_Wrd_t * vSimsIn ) +{ + Gia_Obj_t * pObj; int i, Id; + int nWords = Vec_WrdSize(vSimsIn) / Gia_ManCiNum(p); + assert( Vec_WrdSize(vSimsIn) == nWords * Gia_ManCiNum(p) ); + // allocate simulation info for one timeframe + Vec_WrdFreeP( &p->vSims ); + p->vSims = Vec_WrdStart( Gia_ManObjNum(p) * nWords ); + p->nSimWords = nWords; + // set input sim info + Gia_ManForEachCiId( p, Id, i ) + memcpy( Vec_WrdEntryP(p->vSims, Id*nWords), Vec_WrdEntryP(vSimsIn, i*nWords), sizeof(word)*nWords ); + // perform simulation + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + Gia_ManObjSimAnd( p, i ); + else if ( Gia_ObjIsCi(pObj) ) + continue; + else if ( Gia_ObjIsCo(pObj) ) + Gia_ManObjSimPo( p, i ); + else assert( 0 ); + } + return 1; +} + +Vec_Wrd_t * Gia_ManSimulateWordsOut( Gia_Man_t * p, Vec_Wrd_t * vSimsIn ) +{ + Gia_Obj_t * pObj; int i, Id; + int nWords = Vec_WrdSize(vSimsIn) / Gia_ManCiNum(p); + Vec_Wrd_t * vSimsOut = Vec_WrdStart( nWords * Gia_ManCoNum(p) ); + assert( Vec_WrdSize(vSimsIn) == nWords * Gia_ManCiNum(p) ); + // allocate simulation info for one timeframe + Vec_WrdFreeP( &p->vSims ); + p->vSims = Vec_WrdStart( Gia_ManObjNum(p) * nWords ); + p->nSimWords = nWords; + // set input sim info + Gia_ManForEachCiId( p, Id, i ) + memcpy( Vec_WrdEntryP(p->vSims, Id*nWords), Vec_WrdEntryP(vSimsIn, i*nWords), sizeof(word)*nWords ); + // perform simulation + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + Gia_ManObjSimAnd( p, i ); + else if ( Gia_ObjIsCi(pObj) ) + continue; + else if ( Gia_ObjIsCo(pObj) ) + Gia_ManObjSimPo( p, i ); + else assert( 0 ); + } + // set output sim info + Gia_ManForEachCoId( p, Id, i ) + memcpy( Vec_WrdEntryP(vSimsOut, i*nWords), Vec_WrdEntryP(p->vSims, Id*nWords), sizeof(word)*nWords ); + Vec_WrdFreeP( &p->vSims ); + p->nSimWords = -1; + return vSimsOut; +} + +/**Function************************************************************* + + Synopsis [Dump data files.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDumpFiles( Gia_Man_t * p, int nCexesT, int nCexesV, int Seed, char * pFileName ) +{ + int n, nSize[2] = {nCexesT*64, nCexesV*64}; + + char pFileNameOutTX[100]; + char pFileNameOutTY[100]; + char pFileNameOutVX[100]; + char pFileNameOutVY[100]; + char pFileNameOut[100]; + + //sprintf( pFileNameOutTX, "train_%s_%d_%d.data", pFileName ? pFileName : Gia_ManName(p), nSize[0], Gia_ManCiNum(p) ); + //sprintf( pFileNameOutTY, "train_%s_%d_%d.data", pFileName ? pFileName : Gia_ManName(p), nSize[0], Gia_ManCoNum(p) ); + //sprintf( pFileNameOutVX, "test_%s_%d_%d.data", pFileName ? pFileName : Gia_ManName(p), nSize[1], Gia_ManCiNum(p) ); + //sprintf( pFileNameOutVY, "test_%s_%d_%d.data", pFileName ? pFileName : Gia_ManName(p), nSize[1], Gia_ManCoNum(p) ); + + sprintf( pFileNameOutTX, "%s_x.train.data", pFileName ? pFileName : Gia_ManName(p) ); + sprintf( pFileNameOutTY, "%s_y.train.data", pFileName ? pFileName : Gia_ManName(p) ); + sprintf( pFileNameOutVX, "%s_x.test.data", pFileName ? pFileName : Gia_ManName(p) ); + sprintf( pFileNameOutVY, "%s_y.test.data", pFileName ? pFileName : Gia_ManName(p) ); + + Gia_ManRandomW( 1 ); + for ( n = 0; n < Seed; n++ ) + Gia_ManRandomW( 0 ); + for ( n = 0; n < 2; n++ ) + { + int Res = Gia_ManSimulateWords( p, nSize[n] ); + + Vec_Bit_t * vBitX = Vec_BitAlloc( nSize[n] * Gia_ManCiNum(p) ); + Vec_Bit_t * vBitY = Vec_BitAlloc( nSize[n] * Gia_ManCoNum(p) ); + + FILE * pFileOutX = fopen( n ? pFileNameOutVX : pFileNameOutTX, "wb" ); + FILE * pFileOutY = fopen( n ? pFileNameOutVY : pFileNameOutTY, "wb" ); + + int i, k, Id, Num, Value, nBytes; + for ( k = 0; k < nSize[n]; k++ ) + { + Gia_ManForEachCiId( p, Id, i ) + { + Vec_BitPush( vBitX, Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + //printf( "%d", Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + } + //printf( " " ); + Gia_ManForEachCoId( p, Id, i ) + { + Vec_BitPush( vBitY, Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + //printf( "%d", Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + } + //printf( "\n" ); + } + assert( Vec_BitSize(vBitX) <= Vec_BitCap(vBitX) ); + assert( Vec_BitSize(vBitY) <= Vec_BitCap(vBitY) ); + + Num = 2; Value = fwrite( &Num, 1, 4, pFileOutX ); assert( Value == 4 ); + Num = nSize[n]; Value = fwrite( &Num, 1, 4, pFileOutX ); assert( Value == 4 ); + Num = Gia_ManCiNum(p); Value = fwrite( &Num, 1, 4, pFileOutX ); assert( Value == 4 ); + + nBytes = nSize[n] * Gia_ManCiNum(p) / 8; + assert( nSize[n] * Gia_ManCiNum(p) % 8 == 0 ); + Value = fwrite( Vec_BitArray(vBitX), 1, nBytes, pFileOutX ); + assert( Value == nBytes ); + + Num = 2; Value = fwrite( &Num, 1, 4, pFileOutY ); assert( Value == 4 ); + Num = nSize[n]; Value = fwrite( &Num, 1, 4, pFileOutY ); assert( Value == 4 ); + Num = Gia_ManCoNum(p); Value = fwrite( &Num, 1, 4, pFileOutY ); assert( Value == 4 ); + + nBytes = nSize[n] * Gia_ManCoNum(p) / 8; + assert( nSize[n] * Gia_ManCoNum(p) % 8 == 0 ); + Value = fwrite( Vec_BitArray(vBitY), 1, nBytes, pFileOutY ); + assert( Value == nBytes ); + + fclose( pFileOutX ); + fclose( pFileOutY ); + + Vec_BitFree( vBitX ); + Vec_BitFree( vBitY ); + + Res = 0; + } + printf( "Finished dumping files \"%s\" and \"%s\".\n", pFileNameOutTX, pFileNameOutTY ); + printf( "Finished dumping files \"%s\" and \"%s\".\n", pFileNameOutVX, pFileNameOutVY ); + + sprintf( pFileNameOut, "%s.flist", pFileName ? pFileName : Gia_ManName(p) ); + { + FILE * pFile = fopen( pFileNameOut, "wb" ); + fprintf( pFile, "%s\n", pFileNameOutTX ); + fprintf( pFile, "%s\n", pFileNameOutTY ); + fprintf( pFile, "%s\n", pFileNameOutVX ); + fprintf( pFile, "%s\n", pFileNameOutVY ); + fclose( pFile ); + printf( "Finished dumping file list \"%s\".\n", pFileNameOut ); + } +} + +/**Function************************************************************* + + Synopsis [Dump data files.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDumpPlaFiles( Gia_Man_t * p, int nCexesT, int nCexesV, int Seed, char * pFileName ) +{ + int n, nSize[3] = {nCexesT, nCexesV, nCexesV}; + + char pFileNameOut[3][100]; + + sprintf( pFileNameOut[0], "%s.train.pla", pFileName ? pFileName : Gia_ManName(p) ); + sprintf( pFileNameOut[1], "%s.valid.pla", pFileName ? pFileName : Gia_ManName(p) ); + sprintf( pFileNameOut[2], "%s.test.pla", pFileName ? pFileName : Gia_ManName(p) ); + + Gia_ManRandomW( 1 ); + for ( n = 0; n < Seed; n++ ) + Gia_ManRandomW( 0 ); + for ( n = 0; n < 3; n++ ) + { + int Res = Gia_ManSimulateWords( p, nSize[n] ); + int i, k, Id; + + FILE * pFileOut = fopen( pFileNameOut[n], "wb" ); + + fprintf( pFileOut, ".i %d\n", Gia_ManCiNum(p) ); + fprintf( pFileOut, ".o %d\n", Gia_ManCoNum(p) ); + fprintf( pFileOut, ".p %d\n", nSize[n]*64 ); + fprintf( pFileOut, ".type fr\n" ); + for ( k = 0; k < nSize[n]*64; k++ ) + { + Gia_ManForEachCiId( p, Id, i ) + { + //Vec_BitPush( vBitX, Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + fprintf( pFileOut, "%d", Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + } + fprintf( pFileOut, " " ); + Gia_ManForEachCoId( p, Id, i ) + { + //Vec_BitPush( vBitY, Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + fprintf( pFileOut, "%d", Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + } + fprintf( pFileOut, "\n" ); + } + fprintf( pFileOut, ".e\n" ); + + fclose( pFileOut ); + + Res = 0; + } + printf( "Finished dumping files: \"%s.{train, valid, test}.pla\".\n", pFileName ? pFileName : Gia_ManName(p) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimLogStats( Gia_Man_t * p, char * pDumpFile, int Total, int Correct, int Guess ) +{ + FILE * pTable = fopen( pDumpFile, "wb" ); + fprintf( pTable, "{\n" ); + fprintf( pTable, " \"name\" : \"%s\",\n", p->pName ); + fprintf( pTable, " \"input\" : %d,\n", Gia_ManCiNum(p) ); + fprintf( pTable, " \"output\" : %d,\n", Gia_ManCoNum(p) ); + fprintf( pTable, " \"and\" : %d,\n", Gia_ManAndNum(p) ); + fprintf( pTable, " \"level\" : %d,\n", Gia_ManLevelNum(p) ); + fprintf( pTable, " \"total\" : %d,\n", Total ); + fprintf( pTable, " \"correct\" : %d,\n", Correct ); + fprintf( pTable, " \"guess\" : %d\n", Guess ); + fprintf( pTable, "}\n" ); + fclose( pTable ); +} +int Gia_ManSimParamRead( char * pFileName, int * pnIns, int * pnWords ) +{ + int c, nIns = -1, nLines = 0, Count = 0, fReadDot = 0; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return 0; + } + while ( (c = fgetc(pFile)) != EOF ) + { + if ( c == '.' ) + fReadDot = 1; + if ( c == '\n' ) + { + if ( !fReadDot ) + { + if ( nIns == -1 ) + nIns = Count; + else if ( nIns != Count ) + { + printf( "The number of symbols (%d) does not match other lines (%d).\n", Count, nIns ); + fclose( pFile ); + return 0; + } + Count = 0; + nLines++; + } + fReadDot = 0; + } + if ( fReadDot ) + continue; + if ( c != '0' && c != '1' ) + continue; + Count++; + } + if ( nLines % 64 > 0 ) + { + printf( "The number of lines (%d) is not divisible by 64.\n", nLines ); + fclose( pFile ); + return 0; + } + *pnIns = nIns - 1; + *pnWords = nLines / 64; + //printf( "Expecting %d inputs and %d words of simulation data.\n", *pnIns, *pnWords ); + fclose( pFile ); + return 1; +} +void Gia_ManSimFileRead( char * pFileName, int nIns, int nWords, Vec_Wrd_t * vSimsIn, Vec_Int_t * vValues ) +{ + int c, nPats = 0, Count = 0, fReadDot = 0; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return; + } + assert( Vec_WrdSize(vSimsIn) % nWords == 0 ); + while ( (c = fgetc(pFile)) != EOF ) + { + if ( c == '.' ) + fReadDot = 1; + if ( c == '\n' ) + fReadDot = 0; + if ( fReadDot ) + continue; + if ( c != '0' && c != '1' ) + continue; + if ( Count == nIns ) + { + Vec_IntPush( vValues, c - '0' ); + Count = 0; + nPats++; + } + else + { + if ( c == '1' ) + Abc_TtSetBit( Vec_WrdEntryP(vSimsIn, Count * nWords), nPats ); + Count++; + } + } + assert( nPats == 64*nWords ); + fclose( pFile ); + printf( "Finished reading %d simulation patterns for %d inputs. Probability of 1 at the output is %6.2f %%.\n", 64*nWords, nIns, 100.0*Vec_IntSum(vValues)/nPats ); +} +void Gia_ManCompareValues( Gia_Man_t * p, Vec_Wrd_t * vSimsIn, Vec_Int_t * vValues, char * pDumpFile ) +{ + int i, Value, Guess, Count = 0, nWords = Vec_WrdSize(vSimsIn) / Gia_ManCiNum(p); + word * pSims; + assert( Vec_IntSize(vValues) == nWords * 64 ); + Gia_ManSimulateWordsInit( p, vSimsIn ); + assert( p->nSimWords == nWords ); + pSims = Gia_ManObjSim( p, Gia_ObjId(p, Gia_ManCo(p, 0)) ); + Vec_IntForEachEntry( vValues, Value, i ) + if ( Abc_TtGetBit(pSims, i) == Value ) + Count++; + Guess = (Vec_IntSum(vValues) > nWords * 32) ? Vec_IntSum(vValues) : nWords * 64 - Vec_IntSum(vValues); + printf( "Total = %6d. Errors = %6d. Correct = %6d. (%6.2f %%) Naive guess = %6d. (%6.2f %%)\n", + Vec_IntSize(vValues), Vec_IntSize(vValues) - Count, + Count, 100.0*Count/Vec_IntSize(vValues), + Guess, 100.0*Guess/Vec_IntSize(vValues)); + if ( pDumpFile == NULL ) + return; + Gia_ManSimLogStats( p, pDumpFile, Vec_IntSize(vValues), Count, Guess ); + printf( "Finished dumping statistics into file \"%s\".\n", pDumpFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManReadSimFile( char * pFileName, int * pnIns, int * pnOuts, int * pnPats, Vec_Wrd_t ** pvSimsIn, Vec_Wrd_t ** pvSimsOut ) +{ + char * pTemp, pBuffer[1000]; + Vec_Wrd_t * vSimsIn = NULL, * vSimsOut = NULL; + int i, iPat = 0, nWordsI, nWordsO, nIns = -1, nOuts = -1, nPats = -1; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return; + } + while ( fgets( pBuffer, 1000, pFile ) != NULL ) + { + pTemp = pBuffer; + if ( pTemp[0] == '\0' || pTemp[0] == '#' || pTemp[0] == ' ' ) + continue; + if ( pTemp[0] != '.' ) + break; + if ( pTemp[1] == 'i' ) + nIns = atoi(pTemp+2); + else if ( pTemp[1] == 'o' ) + nOuts = atoi(pTemp+2); + else if ( pTemp[1] == 'p' ) + { + if ( atoi(pTemp+2) % 64 == 0 ) + printf( "Expecting the number of patterns divisible by 64.\n" ); + nPats = atoi(pTemp+2) / 64; + } + } + if ( nIns == -1 || nOuts == -1 || nPats == -1 ) + { + printf( "Some of the parameters (inputs, outputs, patterns) is not specified.\n" ); + fclose( pFile ); + return; + } + nWordsI = (nIns + 63) / 64; + nWordsO = (nOuts + 63) / 64; + + vSimsIn = Vec_WrdStart( nPats * nWordsI ); + vSimsOut = Vec_WrdStart( nPats * nWordsO ); + rewind(pFile); + while ( fgets( pBuffer, 1000, pFile ) != NULL ) + { + if ( pTemp[0] == '\0' || pTemp[0] == '.' ) + continue; + for ( i = 0, pTemp = pBuffer; *pTemp != '\n'; pTemp++ ) + if ( *pTemp == '0' || *pTemp == '1' ) + { + if ( *pTemp == '1' ) + { + if ( i < nIns ) + Abc_TtSetBit( Vec_WrdEntryP(vSimsIn, nWordsI*iPat), i ); + else + Abc_TtSetBit( Vec_WrdEntryP(vSimsOut, nWordsO*iPat), i-nIns ); + } + i++; + } + iPat++; + } + if ( iPat != nPats ) + printf( "The number of patterns does not match.\n" ); + fclose( pFile ); + *pnIns = nIns; + *pnOuts = nOuts; + *pnPats = nPats; + *pvSimsIn = vSimsIn; + *pvSimsOut = vSimsOut; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManReadBinaryFile( char * pFileName, Vec_Wrd_t ** pvSimsIn, Vec_Str_t ** pvSimsOut ) +{ + extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + int nFileSize = Extra_FileSize( pFileName ); + int nExamples = 1 << 16; + int nInputs = nFileSize / nExamples - 1; + int nWords = (8*nInputs + 63)/64, i; + char * pContents = Extra_FileReadContents( pFileName ); + Vec_Wrd_t * vSimsIn = Vec_WrdStart( nExamples * nWords ); + Vec_Wrd_t * vSimsIn2 = Vec_WrdStart( nExamples * nWords ); + Vec_Str_t * vSimsOut = Vec_StrAlloc( nExamples ); + assert( nFileSize % nExamples == 0 ); + for ( i = 0; i < nExamples; i++ ) + { + memcpy( (void *)Vec_WrdEntryP(vSimsIn, i*nWords), (void *)(pContents + i*(nInputs+1)), nInputs ); + Vec_StrPush( vSimsOut, pContents[i*(nInputs+1) + nInputs] ); + } + Extra_BitMatrixTransposeP( vSimsIn, nWords, vSimsIn2, nExamples/64 ); + Vec_WrdShrink( vSimsIn2, 8*nInputs * nExamples/64 ); + Vec_WrdFree( vSimsIn ); + *pvSimsIn = vSimsIn2; + *pvSimsOut = vSimsOut; + ABC_FREE( pContents ); + return nInputs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimLogStats2( Gia_Man_t * p, char * pDumpFile, int Total, int nPositives, float ErrorTotal, float GuessTotal ) +{ + FILE * pTable = fopen( pDumpFile, "wb" ); + fprintf( pTable, "{\n" ); + fprintf( pTable, " \"name\" : \"%s\",\n", p->pName ); + fprintf( pTable, " \"input\" : %d,\n", Gia_ManCiNum(p) ); + fprintf( pTable, " \"output\" : %d,\n", Gia_ManCoNum(p) ); + fprintf( pTable, " \"and\" : %d,\n", Gia_ManAndNum(p) ); + fprintf( pTable, " \"level\" : %d,\n", Gia_ManLevelNum(p) ); + fprintf( pTable, " \"total\" : %d,\n", Total ); + fprintf( pTable, " \"positive\" : %d,\n", nPositives ); + fprintf( pTable, " \"error\" : %e,\n", ErrorTotal ); + fprintf( pTable, " \"guess\" : %e\n", GuessTotal ); + fprintf( pTable, "}\n" ); + fclose( pTable ); +} +int Gia_ManGetExampleValue( word ** ppSims, int nSims, int iExample ) +{ + int o, Sign = 0, ValueSim = 0; + for ( o = 0; o < nSims; o++ ) + if ( (Sign = Abc_TtGetBit(ppSims[o], iExample)) ) + ValueSim |= (1 << o); + if ( Sign ) + ValueSim |= ~0 << nSims; + return ValueSim; +} +void Gia_ManCompareValues2( int nInputs, Gia_Man_t * p, Vec_Wrd_t * vSimsIn, Vec_Str_t * vValues, char * pDumpFile ) +{ + float Error1, ErrorTotal = 0, Guess1, GuessTotal = 0; + int i, o, nPositives = 0, nWords = Vec_WrdSize(vSimsIn) / Gia_ManCiNum(p); + word ** ppSims = ABC_CALLOC( word *, Gia_ManCoNum(p) ); + Gia_Obj_t * pObj; + assert( nWords == (1<<10) ); + assert( Vec_WrdSize(vSimsIn) % Gia_ManCiNum(p) == 0 ); + assert( Vec_StrSize(vValues) == (1 << 16) ); + assert( nWords*64 == (1 << 16) ); + // simulate examples given in vSimsIn + Gia_ManSimulateWordsInit( p, vSimsIn ); + // collect simulation info for the outputs + assert( p->nSimWords == nWords ); + Gia_ManForEachCo( p, pObj, o ) + ppSims[o] = Gia_ManObjSim( p, Gia_ObjId(p, pObj) ); + // compare the output for each example + for ( i = 0; i < nWords*64; i++ ) + { + int ValueGold = (int)Vec_StrEntry( vValues, i ); + int ValueImpl = Gia_ManGetExampleValue( ppSims, Gia_ManCoNum(p), i ); + // compute error for this example + Error1 = (float)(ValueGold - ValueImpl)/256; + ErrorTotal += Error1 * Error1; + // compute error of zero-output + Guess1 = ValueGold > 0 ? Abc_AbsInt(ValueImpl) : 0; + GuessTotal += Guess1 * Guess1; + // count positive values (disregard negative values due to Leaky ReLU) + nPositives += (int)(ValueGold > 0); + } + ABC_FREE( ppSims ); + printf( "Total = %6d. Positive = %6d. (%6.2f %%) Errors = %e. Guess = %e. (%6.2f %%)\n", + Vec_StrSize(vValues), nPositives, 100.0*nPositives/Vec_StrSize(vValues), + ErrorTotal, GuessTotal, 100.0*ErrorTotal/GuessTotal ); + if ( pDumpFile == NULL ) + return; + Gia_ManSimLogStats2( p, pDumpFile, Vec_StrSize(vValues), nPositives, ErrorTotal, GuessTotal ); + printf( "Finished dumping statistics into file \"%s\".\n", pDumpFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTestWordFileUnused( Gia_Man_t * p, char * pFileName, char * pDumpFile ) +{ + Vec_Wrd_t * vSimsIn; + Vec_Str_t * vSimsOut; + int nInputs = Gia_ManReadBinaryFile( pFileName, &vSimsIn, &vSimsOut ); + if ( Gia_ManCiNum(p) == 8*nInputs ) + Gia_ManCompareValues2( nInputs, p, vSimsIn, vSimsOut, pDumpFile ); + else + printf( "The number of inputs in the AIG (%d) and in the file (%d) does not match.\n", Gia_ManCiNum(p), 8*nInputs ); + Vec_WrdFree( vSimsIn ); + Vec_StrFree( vSimsOut ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTestOneFile( Gia_Man_t * p, char * pFileName, char * pDumpFile ) +{ + Vec_Wrd_t * vSimsIn; + Vec_Int_t * vValues; + int nIns, nWords; + if ( !Gia_ManSimParamRead( pFileName, &nIns, &nWords ) ) + return; + if ( nIns != Gia_ManCiNum(p) ) + { + printf( "The number of inputs in the file \"%s\" (%d) does not match the AIG (%d).\n", pFileName, nIns, Gia_ManCiNum(p) ); + return; + } + vSimsIn = Vec_WrdStart( nIns * nWords ); + vValues = Vec_IntAlloc( nWords * 64 ); + Gia_ManSimFileRead( pFileName, nIns, nWords, vSimsIn, vValues ); + Gia_ManCompareValues( p, vSimsIn, vValues, pDumpFile ); + Vec_WrdFree( vSimsIn ); + Vec_IntFree( vValues ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManReadCifar10File( char * pFileName, Vec_Wrd_t ** pvSimsIn, Vec_Str_t ** pvSimsOut, int * pnExamples ) +{ + int nPixels = 32*32*3; + int nFileSize = Extra_FileSize( pFileName ); + int nExamples = nFileSize / (nPixels + 1); + int nWordsIn = nPixels / 8; + int nWordsOut = (nExamples + 63) / 64; int e; + if ( nFileSize % (nPixels + 1) ) + { + printf( "The input file \"%s\" with image data does not appear to be in CIFAR10 format.\n", pFileName ); + return 0; + } + else + { + Vec_Wrd_t * vSimsIn = Vec_WrdStart( 64 * nWordsOut * nWordsIn ); + Vec_Str_t * vSimsOut = Vec_StrAlloc( 64 * nWordsOut ); + unsigned char * pBuffer = ABC_ALLOC( unsigned char, nFileSize ); + FILE * pFile = fopen( pFileName, "rb" ); + int Value = fread( pBuffer, 1, nFileSize, pFile ); + fclose( pFile ); + assert( Value == nFileSize ); + printf( "Successfully read %5.2f MB (%d images) from file \"%s\".\n", (float)nFileSize/(1<<20), nExamples, pFileName ); + for ( e = 0; e < nExamples; e++ ) + { + Vec_StrPush( vSimsOut, (char)pBuffer[e*(nPixels + 1)] ); + memcpy( Vec_WrdEntryP(vSimsIn, e*nWordsIn), pBuffer + e*(nPixels + 1) + 1, nPixels ); + } + ABC_FREE( pBuffer ); + for ( ; e < 64 * nWordsOut; e++ ) + Vec_StrPush( vSimsOut, (char)0 ); + memset( Vec_WrdEntryP(vSimsIn, nExamples*nWordsIn), 0, (64*nWordsOut - nExamples)*nWordsIn ); + *pvSimsIn = vSimsIn; + *pvSimsOut = vSimsOut; + *pnExamples = nExamples; + return 8*nPixels; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSimulateBatch( Gia_Man_t * p, Vec_Wrd_t * vSimsIn, Vec_Str_t * vSimsOut, Vec_Str_t * vSimsOut2, int b, int Limit ) +{ + Gia_Obj_t * pObj; + word * ppSims[10]; + int i, o, Count = 0; + assert( Gia_ManCiNum(p) == Vec_WrdSize(vSimsIn) ); + assert( Gia_ManCoNum(p) == 10 ); + Gia_ManSimulateWordsInit( p, vSimsIn ); + Gia_ManForEachCo( p, pObj, o ) + ppSims[o] = Gia_ManObjSim( p, Gia_ObjId(p, pObj) ); + for ( i = 0; i < Limit; i++ ) + { + int Value = 0; + for ( o = 0; o < 10; o++ ) + if ( Abc_TtGetBit(ppSims[o], i) ) + { + Value = o; + break; + } + Vec_StrPush( vSimsOut, (char)Value ); + Count += Value == (int)Vec_StrEntry( vSimsOut2, 64*b+i ); + } + return Count; +} +Vec_Str_t * Gia_ManSimulateAll( Gia_Man_t * p, Vec_Wrd_t * vSimsIn, Vec_Str_t * vSimsOut, int nExamples, int fVerbose ) +{ + extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + Vec_Str_t * vRes = Vec_StrAlloc( 100 ); int b, Count; + int nWordsIn = 32*32*24/64; // one image + int nWordsOut = Vec_WrdSize(vSimsIn)/(nWordsIn*64); + assert( Vec_WrdSize(vSimsIn) % nWordsIn == 0 ); + for ( b = 0; b < nWordsOut; b++ ) + { + int Limit = b == nWordsOut-1 ? nExamples-b*64 : 64; + Vec_Wrd_t * vSimsIn1 = Vec_WrdStart( nWordsIn*64 ); + Vec_Wrd_t * vSimsIn2 = Vec_WrdStart( nWordsIn*64 ); + memcpy( Vec_WrdArray(vSimsIn1), Vec_WrdEntryP(vSimsIn, b*nWordsIn*64), sizeof(word)*nWordsIn*64 ); + Extra_BitMatrixTransposeP( vSimsIn1, nWordsIn, vSimsIn2, 1 ); + Vec_WrdFree( vSimsIn1 ); + Count = Gia_ManSimulateBatch( p, vSimsIn2, vRes, vSimsOut, b, Limit ); + Vec_WrdFree( vSimsIn2 ); + if ( fVerbose ) + printf( "Finished simulating word %4d (out of %4d). Correct = %2d. (Limit = %2d.)\n", b, nWordsOut, Count, Limit ); + } + assert( Vec_StrSize(vRes) == nExamples ); + return vRes; +} +void Gia_ManCompareCifar10Values( Gia_Man_t * p, Vec_Str_t * vRes, Vec_Str_t * vSimsOut, char * pDumpFile, int nExamples ) +{ + int i, Guess = (nExamples+9)/10, Count = 0; + for ( i = 0; i < nExamples; i++ ) + { + char ValueReal = Vec_StrEntry(vRes, i); + char ValueGold = Vec_StrEntry(vSimsOut, i); + if ( ValueReal == ValueGold ) + Count++; + } + printf( "Summary: Total = %6d. Errors = %6d. Correct = %6d. (%6.2f %%) Naive guess = %6d. (%6.2f %%)\n", + nExamples, nExamples - Count, + Count, 100.0*Count/nExamples, + Guess, 100.0*Guess/nExamples); + if ( pDumpFile == NULL ) + return; + Gia_ManSimLogStats( p, pDumpFile, nExamples, Count, Guess ); + printf( "Finished dumping statistics into file \"%s\".\n", pDumpFile ); +} +void Gia_ManTestWordFile( Gia_Man_t * p, char * pFileName, char * pDumpFile, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Vec_Wrd_t * vSimsIn; + Vec_Str_t * vSimsOut; + int i, nExamples = 0; + int nInputs = Gia_ManReadCifar10File( pFileName, &vSimsIn, &vSimsOut, &nExamples ); + char * pKnownFileNames[3] = {"small.aig", "medium.aig", "large.aig"}; + int pLimitFileSizes[3] = {10000, 100000, 1000000}; + for ( i = 0; i < 3; i++ ) + if ( p->pSpec && !strncmp(p->pSpec, pKnownFileNames[i], 5) && Gia_ManAndNum(p) > pLimitFileSizes[i] ) + printf( "Warning: The input file \"%s\" contains more than %d internal and-nodes.\n", pKnownFileNames[i], pLimitFileSizes[i] ); + if ( nInputs == Gia_ManCiNum(p) ) + { + Vec_Str_t * vRes = Gia_ManSimulateAll( p, vSimsIn, vSimsOut, nExamples, fVerbose ); + Gia_ManCompareCifar10Values( p, vRes, vSimsOut, pDumpFile, nExamples ); + Vec_StrFree( vRes ); + } + else + printf( "The primary input counts in the AIG (%d) and in the image data (%d) do not match.\n", Gia_ManCiNum(p), nInputs ); + Vec_WrdFree( vSimsIn ); + Vec_StrFree( vSimsOut ); + Abc_PrintTime( 1, "Total checking time", Abc_Clock() - clk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaHash.c b/abc/src/aig/gia/giaHash.c index d9873d76bb4..063cfd31ab1 100644 --- a/abc/src/aig/gia/giaHash.c +++ b/abc/src/aig/gia/giaHash.c @@ -806,6 +806,335 @@ int Gia_ManHashAndMulti2( Gia_Man_t * p, Vec_Int_t * vLits ) iRes = Gia_ManHashAnd( p, iRes, iLit ); return iRes; } +int Gia_ManHashDualMiter( Gia_Man_t * p, Vec_Int_t * vOuts ) +{ + int i, iLit0, iLit1, iRes = 0; + Vec_IntForEachEntryDouble( vOuts, iLit0, iLit1, i ) + iRes = Gia_ManHashOr( p, iRes, Gia_ManHashXor(p, iLit0, iLit1) ); + return iRes; +} + + + +/**Function************************************************************* + + Synopsis [Create multi-input tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Gia_ManCollectLiterals( int nVars ) +{ + int i, * pRes = ABC_CALLOC( int, nVars ); + for ( i = 0; i < nVars; i++ ) + pRes[i] = Abc_Var2Lit( i+1, 0 ); + return pRes; +} +int * Gia_ManGenZero( int nBits ) +{ + return ABC_CALLOC( int, nBits ); +} +int * Gia_ManGenPerm( int nBits ) +{ + int i, * pRes = ABC_CALLOC( int, nBits ); + srand( time(NULL) ); + for ( i = 0; i < nBits; i++ ) + pRes[i] = i; + for ( i = 0; i < nBits; i++ ) + { + int iPerm = rand() % nBits; + ABC_SWAP( int, pRes[i], pRes[iPerm] ); + } + return pRes; +} +int * Gia_ManGenPerm2( int nBits ) +{ + int i, * pRes = ABC_CALLOC( int, nBits ); + srand( time(NULL) ); + for ( i = 0; i < nBits; i++ ) + pRes[i] = rand() % nBits; + return pRes; +} +int Gia_ManMultiCheck( int * pPerm, int nPerm ) +{ + int i; + for ( i = 1; i < nPerm; i++ ) + if ( pPerm[i-1] <= pPerm[i] ) + return 0; + return 1; +} +int Gia_ManMultiInputPerm( Gia_Man_t * pNew, int * pVars, int nVars, int * pPerm, int fOr, int fXor ) +{ + int fPrint = 1; + int i, iLit; + if ( fPrint ) + { + for ( i = 0; i < nVars; i++ ) + printf( "%d ", pPerm[i] ); + printf( "\n" ); + } + while ( 1 ) + { + for ( i = 1; i < nVars; i++ ) + if ( pPerm[i-1] >= pPerm[i] ) + break; + if ( i == nVars ) + break; + assert( pPerm[i-1] >= pPerm[i] ); + if ( pPerm[i-1] > pPerm[i] ) + { + ABC_SWAP( int, pPerm[i-1], pPerm[i] ); + ABC_SWAP( int, pVars[i-1], pVars[i] ); + } + else + { + assert( pPerm[i-1] == pPerm[i] ); + pPerm[i-1]++; + if ( fXor ) + pVars[i-1] = Gia_ManHashXor( pNew, pVars[i-1], pVars[i] ); + else if ( fOr ) + pVars[i-1] = Gia_ManHashOr( pNew, pVars[i-1], pVars[i] ); + else + pVars[i-1] = Gia_ManHashAnd( pNew, pVars[i-1], pVars[i] ); + for ( i = i+1; i < nVars; i++ ) + { + pPerm[i-1] = pPerm[i]; + pVars[i-1] = pVars[i]; + } + nVars--; + } + if ( fPrint ) + { + for ( i = 0; i < nVars; i++ ) + printf( "%d ", pPerm[i] ); + printf( "\n" ); + } + } + iLit = pVars[0]; + for ( i = 1; i < nVars; i++ ) + if ( fXor ) + iLit = Gia_ManHashXor( pNew, iLit, pVars[i] ); + else if ( fOr ) + iLit = Gia_ManHashOr( pNew, iLit, pVars[i] ); + else + iLit = Gia_ManHashAnd( pNew, iLit, pVars[i] ); + return iLit; +} +Gia_Man_t * Gia_ManMultiInputTest( int nBits ) +{ + Gia_Man_t * pNew; + int i, iRes, * pPerm; + int * pMulti = Gia_ManCollectLiterals( nBits ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "multi" ); + for ( i = 0; i < nBits; i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + pPerm = Gia_ManGenPerm2( nBits ); + //pPerm = Gia_ManGenZero( nBits ); + iRes = Gia_ManMultiInputPerm( pNew, pMulti, nBits, pPerm, 0, 0 ); + Gia_ManAppendCo( pNew, iRes ); + ABC_FREE( pPerm ); + ABC_FREE( pMulti ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Create MUX tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCube( Gia_Man_t * pNew, int Vars, int nVars, int * pLits ) +{ + int i, iLit = 1; + for ( i = 0; i < nVars; i++ ) + iLit = Gia_ManHashAnd( pNew, iLit, Abc_LitNotCond(pLits[i], !((Vars >> i) & 1)) ); + return iLit; +} +int Gia_ManMuxTree_rec( Gia_Man_t * pNew, int * pCtrl, int nCtrl, int * pData ) +{ + int iLit0, iLit1; + if ( nCtrl == 0 ) + return pData[0]; + iLit0 = Gia_ManMuxTree_rec( pNew, pCtrl, nCtrl-1, pData ); + iLit1 = Gia_ManMuxTree_rec( pNew, pCtrl, nCtrl-1, pData + (1<<(nCtrl-1)) ); + return Gia_ManHashMux( pNew, pCtrl[nCtrl-1], iLit1, iLit0 ); +} +void Gia_ManUsePerm( int * pTree, int nBits, int * pPerm ) +{ + int fPrint = 0; + int i, k, m, nVars = nBits + (1 << nBits); + if ( fPrint ) + { + for ( i = 0; i < nVars; i++ ) + printf( "%d ", pPerm[i] ); + printf( "\n" ); + } + for ( i = 0; i < nBits; i++ ) + { + for ( k = i+1; k < nBits; k++ ) + if ( pPerm[i] > pPerm[k] ) + break; + if ( k == nBits ) + break; + assert( pPerm[i] > pPerm[k] ); + ABC_SWAP( int, pPerm[i], pPerm[k] ); + ABC_SWAP( int, pTree[i], pTree[k] ); + for ( m = 0; m < (1 << nBits); m++ ) + if ( ((m >> i) & 1) && !((m >> k) & 1) ) + { + ABC_SWAP( int, pTree[nBits+m], pTree[nBits+(m^(1<> i) & 1) ) + return Abc_LitNotCond( pLits[i], (iLate1 >> i) & 1 ); + return -1; +} +int Gia_ManLatest( int * pPerm, int nVars, int iPrev1, int iPrev2, int iPrev3 ) +{ + int i, Value = -1, iLate = -1; + for ( i = 0; i < nVars; i++ ) + if ( Value < pPerm[i] && i != iPrev1 && i != iPrev2 && i != iPrev3 ) + { + Value = pPerm[i]; + iLate = i; + } + return iLate; +} +int Gia_ManEarliest( int * pPerm, int nVars ) +{ + int i, Value = ABC_INFINITY, iLate = -1; + for ( i = 0; i < nVars; i++ ) + if ( Value > pPerm[i] ) + { + Value = pPerm[i]; + iLate = i; + } + return iLate; +} +int Gia_ManDecompOne( Gia_Man_t * pNew, int * pTree, int nBits, int * pPerm, int iLate ) +{ + int iRes, iData; + assert( iLate >= 0 && iLate < (1<= 0 && iLate1 < (1<= 0 && iLate2 < (1<= 0 && iLate1 < (1<= 0 && iLate2 < (1<= 0 && iLate3 < (1< BaseValue && pPerm[nBits+iLate2] > BaseValue && pPerm[nBits+iLate3] > BaseValue && pPerm[nBits+iLate4] == BaseValue ) + return Gia_ManDecompThree( pNew, pTree, nBits, pPerm, iLate1, iLate2, iLate3 ); + if ( pPerm[nBits+iLate1] > BaseValue && pPerm[nBits+iLate2] > BaseValue && pPerm[nBits+iLate3] == BaseValue ) + return Gia_ManDecompTwo( pNew, pTree, nBits, pPerm, iLate1, iLate2 ); + if ( pPerm[nBits+iLate1] > BaseValue && pPerm[nBits+iLate2] == BaseValue ) + return Gia_ManDecompOne( pNew, pTree, nBits, pPerm, iLate1 ); + return Gia_ManMuxTree_rec( pNew, pTree, nBits, pTree+nBits ); + } +} +Gia_Man_t * Gia_ManMuxTreeTest( int nBits ) +{ + Gia_Man_t * pNew; + int i, iLit, nVars = nBits + (1 << nBits); + int * pPerm, * pTree = Gia_ManCollectLiterals( nVars ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "mux_tree" ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + pPerm = Gia_ManGenPerm( nVars ); + //pPerm = Gia_ManGenZero( nVars ); + pPerm[nBits+1] = 100; + pPerm[nBits+5] = 100; + pPerm[nBits+4] = 100; + Gia_ManUsePerm( pTree, nBits, pPerm ); + iLit = Gia_ManDecomp( pNew, pTree, nBits, pPerm ); + Gia_ManAppendCo( pNew, iLit ); + ABC_FREE( pPerm ); + ABC_FREE( pTree ); + return pNew; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/abc/src/aig/gia/giaHcd.c b/abc/src/aig/gia/giaHcd.c index 5d3e28f5fcd..8e8461e12c2 100644 --- a/abc/src/aig/gia/giaHcd.c +++ b/abc/src/aig/gia/giaHcd.c @@ -626,7 +626,7 @@ Aig_Man_t * Hcd_ComputeChoices( Aig_Man_t * pAig, int nBTLimit, int fSynthesis, Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) Gia_ManStop( pGia ); - Gia_AigerWrite( pMiter, "m3.aig", 0, 0 ); + Gia_AigerWrite( pMiter, "m3.aig", 0, 0, 0 ); } else { diff --git a/abc/src/aig/gia/giaIf.c b/abc/src/aig/gia/giaIf.c index 0c39cae4f71..7c5e706e89d 100644 --- a/abc/src/aig/gia/giaIf.c +++ b/abc/src/aig/gia/giaIf.c @@ -39,6 +39,8 @@ ABC_NAMESPACE_IMPL_START extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); extern int Abc_RecToGia3( Gia_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, Vec_Int_t * vLeaves, int fHash ); +extern void Gia_ManPrintGetMuxFanins( Gia_Man_t * p, Gia_Obj_t * pObj, int * pFanins ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -200,6 +202,7 @@ int Gia_ManLutLevel( Gia_Man_t * p, int ** ppLevels ) ***********************************************************************/ void Gia_ManLutParams( Gia_Man_t * p, int * pnCurLuts, int * pnCurEdges, int * pnCurLevels ) { + int fDisable2Lut = 1; if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t *)p->pManTime) ) { int i; @@ -219,20 +222,37 @@ void Gia_ManLutParams( Gia_Man_t * p, int * pnCurLuts, int * pnCurEdges, int * p int * pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); *pnCurLuts = 0; *pnCurEdges = 0; + *pnCurLevels = 0; Gia_ManForEachLut( p, i ) { - int Level = 0; + if ( Gia_ObjLutIsMux(p, i) && !(fDisable2Lut && Gia_ObjLutSize(p, i) == 2) ) + { + int pFanins[3]; + if ( Gia_ObjLutSize(p, i) == 3 ) + { + Gia_ManPrintGetMuxFanins( p, Gia_ManObj(p, i), pFanins ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[0]]+1 ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[1]] ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[2]] ); + } + else if ( Gia_ObjLutSize(p, i) == 2 ) + { + pObj = Gia_ManObj( p, i ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[Gia_ObjFaninId0(pObj, i)] ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[Gia_ObjFaninId1(pObj, i)] ); + } + *pnCurLevels = Abc_MaxInt( *pnCurLevels, pLevels[i] ); + (*pnCurEdges)++; + //nMuxF++; + continue; + } (*pnCurLuts)++; (*pnCurEdges) += Gia_ObjLutSize(p, i); Gia_LutForEachFanin( p, i, iFan, k ) - if ( Level < pLevels[iFan] ) - Level = pLevels[iFan]; - pLevels[i] = Level + 1; + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[iFan] ); + pLevels[i]++; + *pnCurLevels = Abc_MaxInt( *pnCurLevels, pLevels[i] ); } - *pnCurLevels = 0; - Gia_ManForEachCo( p, pObj, k ) - if ( *pnCurLevels < pLevels[Gia_ObjFaninId0p(p, pObj)] ) - *pnCurLevels = pLevels[Gia_ObjFaninId0p(p, pObj)]; ABC_FREE( pLevels ); } } @@ -452,6 +472,7 @@ int Gia_ManCountDupLut( Gia_Man_t * p ) void Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile ) { + int fDisable2Lut = 1; Gia_Obj_t * pObj; int * pLevels; int i, k, iFan, nLutSize = 0, nLuts = 0, nFanins = 0, LevelMax = 0, Ave = 0, nMuxF = 0; @@ -460,7 +481,7 @@ void Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile ) pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachLut( p, i ) { - if ( Gia_ObjLutIsMux(p, i) ) + if ( Gia_ObjLutIsMux(p, i) && !(fDisable2Lut && Gia_ObjLutSize(p, i) == 2) ) { int pFanins[3]; if ( Gia_ObjLutSize(p, i) == 3 ) @@ -537,11 +558,12 @@ void Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile ) FILE * pTable = fopen( pDumpFile, "a+" ); if ( strcmp( FileNameOld, p->pName ) ) { - sprintf( FileNameOld, "%s", p->pName ); + sprintf( FileNameOld, "%s_out", p->pName ); fprintf( pTable, "\n" ); fprintf( pTable, "%s ", p->pName ); fprintf( pTable, " " ); - fprintf( pTable, "%d ", Gia_ManAndNum(p) ); + //fprintf( pTable, "%d ", Gia_ManAndNum(p) ); + fprintf( pTable, "%d ", Gia_ManRegNum(p) ); fprintf( pTable, "%d ", nLuts ); fprintf( pTable, "%d ", Gia_ManLutLevelWithBoxes(p) ); //fprintf( pTable, "%d ", Gia_ManRegBoxNum(p) ); @@ -554,11 +576,13 @@ void Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile ) //printf( "This part of the code is currently not used.\n" ); //assert( 0 ); fprintf( pTable, " " ); + fprintf( pTable, " " ); + fprintf( pTable, "%d ", Gia_ManRegNum(p) ); fprintf( pTable, "%d ", nLuts ); fprintf( pTable, "%d ", Gia_ManLutLevelWithBoxes(p) ); //fprintf( pTable, "%d ", Gia_ManRegBoxNum(p) ); //fprintf( pTable, "%d ", Gia_ManNonRegBoxNum(p) ); - fprintf( pTable, "%.2f", 1.0*(Abc_Clock() - clk)/CLOCKS_PER_SEC ); +// fprintf( pTable, "%.2f", 1.0*(Abc_Clock() - clk)/CLOCKS_PER_SEC ); clk = Abc_Clock(); } fclose( pTable ); @@ -756,6 +780,43 @@ int Gia_ManChoiceLevel( Gia_Man_t * p ) } +/**Function************************************************************* + + Synopsis [Checks integrity of choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManCheckChoices_rec( If_Man_t * pIfMan, If_Obj_t * pIfObj ) +{ + if ( !pIfObj || pIfObj->Type != IF_AND || pIfObj->fDriver ) + return; + pIfObj->fDriver = 1; + If_ManCheckChoices_rec( pIfMan, If_ObjFanin0(pIfObj) ); + If_ManCheckChoices_rec( pIfMan, If_ObjFanin1(pIfObj) ); + If_ManCheckChoices_rec( pIfMan, pIfObj->pEquiv ); +} +void If_ManCheckChoices( If_Man_t * pIfMan ) +{ + If_Obj_t * pIfObj; + int i, fFound = 0; + If_ManForEachObj( pIfMan, pIfObj, i ) + pIfObj->fDriver = 0; + If_ManForEachCo( pIfMan, pIfObj, i ) + If_ManCheckChoices_rec( pIfMan, If_ObjFanin0(pIfObj) ); + If_ManForEachNode( pIfMan, pIfObj, i ) + if ( !pIfObj->fDriver ) + printf( "Object %d is dangling.\n", i ), fFound = 1; + if ( !fFound ) + printf( "There are no dangling objects.\n" ); + If_ManForEachObj( pIfMan, pIfObj, i ) + pIfObj->fDriver = 0; +} + /**Function************************************************************* @@ -824,6 +885,7 @@ If_Man_t * Gia_ManToIf( Gia_Man_t * p, If_Par_t * pPars ) } if ( Gia_ManHasChoices(p) ) Gia_ManCleanMark0( p ); + //If_ManCheckChoices( pIfMan ); return pIfMan; } @@ -1091,6 +1153,34 @@ int Gia_ManFromIfLogicNode( void * pIfMan, Gia_Man_t * pNew, int iObj, Vec_Int_t } return Gia_ManFromIfLogicCreateLutSpecial( pNew, pRes, vLeaves, vLeavesTemp, vCover, vMapping, vMapping2, vPacking ); } + if ( ((If_Man_t *)pIfMan)->pPars->fLut6Filter && Vec_IntSize(vLeaves) == 6 ) + { + extern word If_Dec6Perform( word t, int fDerive ); + extern void If_Dec6Verify( word t, word z ); + Vec_Int_t * vLeaves2 = Vec_IntAlloc( 4 ); + word t = pRes[0]; + word z = If_Dec6Perform( t, 1 ); + //If_DecPrintConfig( z ); + If_Dec6Verify( t, z ); + + t = Abc_Tt6Stretch( z & 0xffff, 4 ); + Vec_IntClear( vLeaves2 ); + for ( i = 0; i < 4; i++ ) + Vec_IntPush( vLeaves2, Vec_IntEntry( vLeaves, (int)((z >> (16+i*4)) & 7) ) ); + iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, &t, vLeaves2, vCover, vMapping, vMapping2 ); + + t = Abc_Tt6Stretch( (z >> 32) & 0xffff, 4 ); + Vec_IntClear( vLeaves2 ); + for ( i = 0; i < 4; i++ ) + if ( ((z >> (48+i*4)) & 7) == 7 ) + Vec_IntPush( vLeaves2, iObjLit1 ); + else + Vec_IntPush( vLeaves2, Vec_IntEntry( vLeaves, (int)((z >> (48+i*4)) & 7) ) ); + iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, &t, vLeaves2, vCover, vMapping, vMapping2 ); + + Vec_IntFree( vLeaves2 ); + return iObjLit1; + } // check if there is no LUT structures if ( pStr == NULL ) return Gia_ManFromIfLogicCreateLut( pNew, pRes, vLeaves, vCover, vMapping, vMapping2 ); @@ -1804,7 +1894,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->fUseCofVars && !pIfMan->pPars->fUseAndVars && !pIfMan->pPars->fUseCheck1 && !pIfMan->pPars->fUseCheck2 ) If_CutRotatePins( pIfMan, pCutBest ); // collect leaves of the best cut Vec_IntClear( vLeaves ); @@ -1959,6 +2049,7 @@ Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan ) pFile = fopen( Buffer, "wb" ); if ( pFile == NULL ) { + Vec_StrFree( vConfigsStr ); printf( "Cannot open file \"%s\".\n", Buffer ); return pNew; } @@ -2132,11 +2223,13 @@ void Gia_ManTransferTiming( Gia_Man_t * p, Gia_Man_t * pGia ) p->vOutReqs = pGia->vOutReqs; pGia->vOutReqs = NULL; p->DefInArrs = pGia->DefInArrs; p->DefOutReqs = pGia->DefOutReqs; + p->And2Delay = pGia->And2Delay; } - if ( pGia->vNamesIn || pGia->vNamesOut ) + if ( pGia->vNamesIn || pGia->vNamesOut || pGia->vNamesNode ) { p->vNamesIn = pGia->vNamesIn; pGia->vNamesIn = NULL; p->vNamesOut = pGia->vNamesOut; pGia->vNamesOut = NULL; + p->vNamesNode = pGia->vNamesNode; pGia->vNamesNode = NULL; } if ( pGia->vConfigs || pGia->pCellStr ) { @@ -2231,7 +2324,7 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars ) { extern void Gia_ManIffTest( Gia_Man_t * pGia, If_LibLut_t * pLib, int fVerbose ); Gia_Man_t * pNew; - If_Man_t * pIfMan; int i, Entry; + If_Man_t * pIfMan; int i, Entry;//, Id, EntryF; assert( pPars->pTimesArr == NULL ); assert( pPars->pTimesReq == NULL ); if ( p->vCiArrs ) @@ -2241,6 +2334,15 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars ) Vec_IntForEachEntry( p->vCiArrs, Entry, i ) pPars->pTimesArr[i] = (float)Entry; } +/* // uncommenting this leads to a mysterious memory corruption + else if ( p->vInArrs ) + { + assert( Vec_FltSize(p->vInArrs) == Gia_ManCiNum(p) ); + pPars->pTimesArr = ABC_CALLOC( float, Gia_ManCiNum(p)); + Gia_ManForEachCiId( p, Id, i ) + pPars->pTimesArr[i] = Vec_FltEntry(p->vInArrs, i); + } +*/ if ( p->vCoReqs ) { assert( Vec_IntSize(p->vCoReqs) == Gia_ManCoNum(p) ); @@ -2248,6 +2350,15 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars ) Vec_IntForEachEntry( p->vCoReqs, Entry, i ) pPars->pTimesReq[i] = (float)Entry; } +/* // uncommenting this leads to a mysterious memory corruption + else if ( p->vOutReqs ) + { + assert( Vec_FltSize(p->vOutReqs) == Gia_ManCoNum(p) ); + pPars->pTimesReq = ABC_CALLOC( float, Gia_ManCoNum(p) ); + Vec_FltForEachEntry( p->vOutReqs, EntryF, i ) + pPars->pTimesReq[i] = EntryF; + } +*/ ABC_FREE( p->pCellStr ); Vec_IntFreeP( &p->vConfigs ); // disable cut minimization when GIA strucure is needed @@ -2310,8 +2421,16 @@ Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars ) // transfer name assert( pNew->pName == NULL ); pNew->pName = Abc_UtilStrsav( p->pName ); + ABC_FREE( pNew->pSpec ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // print delay trace + if ( pPars->fVerboseTrace ) + { + pNew->pLutLib = pPars->pLutLib; + Gia_ManDelayTraceLutPrint( pNew, 1 ); + pNew->pLutLib = NULL; + } return pNew; } Gia_Man_t * Gia_ManPerformMapping( Gia_Man_t * p, void * pp ) diff --git a/abc/src/aig/gia/giaIso.c b/abc/src/aig/gia/giaIso.c index 0e040b6ca28..fcfa34488c5 100644 --- a/abc/src/aig/gia/giaIso.c +++ b/abc/src/aig/gia/giaIso.c @@ -894,7 +894,7 @@ void Gia_ManFindCaninicalOrder( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAn Vec_PtrClear( vTemp ); Gia_ManForEachPi( p, pObj, i ) Vec_PtrPush( vTemp, pObj ); - Vec_PtrSort( vTemp, (int (*)(void))Gia_ObjCompareByValue ); + Vec_PtrSort( vTemp, (int (*)(const void *, const void *))Gia_ObjCompareByValue ); // create the result Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i ) Vec_IntPush( vCis, Gia_ObjId(p, pObj) ); @@ -917,7 +917,7 @@ void Gia_ManFindCaninicalOrder( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAn pObj->Value = Abc_Var2Lit( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); Vec_PtrPush( vTemp, pObj ); } - Vec_PtrSort( vTemp, (int (*)(void))Gia_ObjCompareByValue ); + Vec_PtrSort( vTemp, (int (*)(const void *, const void *))Gia_ObjCompareByValue ); Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i ) Vec_IntPush( vCos, Gia_ObjId(p, pObj) ); } @@ -926,7 +926,7 @@ void Gia_ManFindCaninicalOrder( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAn Vec_PtrClear( vTemp ); Gia_ManForEachRo( p, pObj, i ) Vec_PtrPush( vTemp, pObj ); - Vec_PtrSort( vTemp, (int (*)(void))Gia_ObjCompareByValue ); + Vec_PtrSort( vTemp, (int (*)(const void *, const void *))Gia_ObjCompareByValue ); // create the result Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i ) { @@ -1293,7 +1293,7 @@ void Gia_IsoTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose ) // create AIG with two primary outputs (original and permuted) pPerm = Gia_ManDupPerm( p, vPiPerm ); pDouble = Gia_ManDupAppendNew( p, pPerm ); -//Gia_AigerWrite( pDouble, "test.aig", 0, 0 ); +//Gia_AigerWrite( pDouble, "test.aig", 0, 0, 0 ); // analyze the two-output miter pAig = Gia_ManIsoReduce( pDouble, &vPosEquivs, &vPisPerm, 0, 0, 0, 0 ); diff --git a/abc/src/aig/gia/giaIso2.c b/abc/src/aig/gia/giaIso2.c index 576b118f51c..22b1d09eca1 100644 --- a/abc/src/aig/gia/giaIso2.c +++ b/abc/src/aig/gia/giaIso2.c @@ -328,7 +328,7 @@ int Gia_Iso2ManUniqify( Gia_Iso2Man_t * p ) } Vec_IntShrink( p->vTied, k ); // sort singletons - Vec_PtrSort( p->vSingles, (int (*)(void))Gia_ObjCompareByValue2 ); + Vec_PtrSort( p->vSingles, (int (*)(const void *, const void *))Gia_ObjCompareByValue2 ); // add them to unique and increment signature Vec_PtrForEachEntry( Gia_Obj_t *, p->vSingles, pObj, i ) { diff --git a/abc/src/aig/gia/giaIso3.c b/abc/src/aig/gia/giaIso3.c index a88a0569afb..8bea4bbfae1 100644 --- a/abc/src/aig/gia/giaIso3.c +++ b/abc/src/aig/gia/giaIso3.c @@ -158,6 +158,97 @@ void Gia_Iso3Test( Gia_Man_t * p ) Vec_IntFreeP( &vSign ); } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_Iso4Gia( Gia_Man_t * p ) +{ + Vec_Wec_t * vLevs = Gia_ManLevelizeR( p ); + Vec_Int_t * vLevel; int l; + Abc_Random( 1 ); + Vec_WecForEachLevel( vLevs, vLevel, l ) + { + Gia_Obj_t * pObj; int i; + int RandC[2] = { Abc_Random(0), Abc_Random(0) }; + if ( l == 0 ) + { + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + { + assert( Gia_ObjIsCo(pObj) ); + pObj->Value = Abc_Random(0); + Gia_ObjFanin0(pObj)->Value += pObj->Value + RandC[Gia_ObjFaninC0(pObj)]; + } + } + else + { + Gia_ManForEachObjVec( vLevel, p, pObj, i ) if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjFanin0(pObj)->Value += pObj->Value + RandC[Gia_ObjFaninC0(pObj)]; + Gia_ObjFanin1(pObj)->Value += pObj->Value + RandC[Gia_ObjFaninC1(pObj)]; + } + } + } + return vLevs; +} +void Gia_Iso4Test( Gia_Man_t * p ) +{ + Vec_Wec_t * vLevs = Gia_Iso4Gia( p ); + Vec_Int_t * vLevel; int l; + Vec_WecForEachLevel( vLevs, vLevel, l ) + { + Gia_Obj_t * pObj; int i; + printf( "Level %d\n", l ); + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + printf( "Obj = %5d. Value = %08x.\n", Gia_ObjId(p, pObj), pObj->Value ); + } + Vec_WecFree( vLevs ); +} +Vec_Int_t * Gia_IsoCollectData( Gia_Man_t * p, Vec_Int_t * vObjs ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vData = Vec_IntAlloc( Vec_IntSize(vObjs) ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + Vec_IntPush( vData, pObj->Value ); + return vData; +} +void Gia_IsoCompareVecs( Gia_Man_t * pGia0, Vec_Wec_t * vLevs0, Gia_Man_t * pGia1, Vec_Wec_t * vLevs1 ) +{ + int i, Common, nLevels = Abc_MinInt( Vec_WecSize(vLevs0), Vec_WecSize(vLevs1) ); + Gia_ManPrintStats( pGia0, NULL ); + Gia_ManPrintStats( pGia1, NULL ); + printf( "Printing %d shared levels:\n", nLevels ); + for ( i = 0; i < nLevels; i++ ) + { + Vec_Int_t * vLev0 = Vec_WecEntry(vLevs0, i); + Vec_Int_t * vLev1 = Vec_WecEntry(vLevs1, i); + Vec_Int_t * vData0 = Gia_IsoCollectData( pGia0, vLev0 ); + Vec_Int_t * vData1 = Gia_IsoCollectData( pGia1, vLev1 ); + Vec_IntSort( vData0, 0 ); + Vec_IntSort( vData1, 0 ); + Common = Vec_IntTwoCountCommon( vData0, vData1 ); + printf( "Level = %3d. One = %6d. Two = %6d. Common = %6d.\n", + i, Vec_IntSize(vData0)-Common, Vec_IntSize(vData1)-Common, Common ); + Vec_IntFree( vData0 ); + Vec_IntFree( vData1 ); + } +} +void Gia_Iso4TestTwo( Gia_Man_t * pGia0, Gia_Man_t * pGia1 ) +{ + Vec_Wec_t * vLevs0 = Gia_Iso4Gia( pGia0 ); + Vec_Wec_t * vLevs1 = Gia_Iso4Gia( pGia1 ); + Gia_IsoCompareVecs( pGia0, vLevs0, pGia1, vLevs1 ); + Vec_WecFree( vLevs0 ); + Vec_WecFree( vLevs1 ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/abc/src/aig/gia/giaKf.c b/abc/src/aig/gia/giaKf.c index a823f726218..6909851f1a3 100644 --- a/abc/src/aig/gia/giaKf.c +++ b/abc/src/aig/gia/giaKf.c @@ -21,13 +21,18 @@ #include "gia.h" #include "misc/vec/vecSet.h" +#ifdef _MSC_VER +#define unlink _unlink +#else +#include +#endif + #ifdef ABC_USE_PTHREADS #ifdef _WIN32 #include "../lib/pthread.h" #else #include -#include #endif #endif diff --git a/abc/src/aig/gia/giaLf.c b/abc/src/aig/gia/giaLf.c index 45a22db0b41..13066005038 100644 --- a/abc/src/aig/gia/giaLf.c +++ b/abc/src/aig/gia/giaLf.c @@ -1158,7 +1158,11 @@ static inline void Lf_CutParams( Lf_Man_t * p, Lf_Cut_t * pCut, int Required, fl if ( pCut->Flow >= (float)1e32 || pBest->Flow[Index] >= (float)1e32 ) pCut->Flow = (float)1e32; else + { pCut->Flow += pBest->Flow[Index]; + if ( pCut->Flow > (float)1e32 ) + pCut->Flow = (float)1e32; + } } Delay = pBest->Delay[Index]; } @@ -1172,7 +1176,11 @@ static inline void Lf_CutParams( Lf_Man_t * p, Lf_Cut_t * pCut, int Required, fl if ( p->fUseEla ) pCut->Flow = Lf_CutAreaDerefed(p, pCut) / FlowRefs; else + { pCut->Flow = (pCut->Flow + Lf_CutArea(p, pCut)) / FlowRefs; + if ( pCut->Flow > (float)1e32 ) + pCut->Flow = (float)1e32; + } } void Lf_ObjMergeOrder( Lf_Man_t * p, int iObj ) @@ -1542,7 +1550,7 @@ int Lf_ManSetMapRefs( Lf_Man_t * p ) } if ( p->pGia->pManTime != NULL ) { - assert( Gia_ManBufNum(p->pGia) ); + assert( !Gia_ManBufNum(p->pGia) ); Tim_ManIncrementTravId( (Tim_Man_t*)p->pGia->pManTime ); if ( p->pPars->fDoAverage ) for ( i = 0; i < Gia_ManCoNum(p->pGia); i++ ) diff --git a/abc/src/aig/gia/giaMan.c b/abc/src/aig/gia/giaMan.c index 98907491bcb..e8f9bca3279 100644 --- a/abc/src/aig/gia/giaMan.c +++ b/abc/src/aig/gia/giaMan.c @@ -18,10 +18,13 @@ ***********************************************************************/ +#include + #include "gia.h" #include "misc/tim/tim.h" #include "proof/abs/abs.h" #include "opt/dar/dar.h" +#include "misc/extra/extra.h" #ifdef WIN32 #include @@ -85,13 +88,18 @@ void Gia_ManStop( Gia_Man_t * p ) assert( p->pManTime == NULL ); Vec_PtrFreeFree( p->vNamesIn ); Vec_PtrFreeFree( p->vNamesOut ); + Vec_PtrFreeFree( p->vNamesNode ); Vec_IntFreeP( &p->vSwitching ); Vec_IntFreeP( &p->vSuper ); Vec_IntFreeP( &p->vStore ); Vec_IntFreeP( &p->vClassNew ); Vec_IntFreeP( &p->vClassOld ); + Vec_IntFreeP( &p->vPats ); + Vec_BitFreeP( &p->vPolars ); Vec_WrdFreeP( &p->vSims ); + Vec_WrdFreeP( &p->vSimsT ); Vec_WrdFreeP( &p->vSimsPi ); + Vec_WrdFreeP( &p->vSimsPo ); Vec_IntFreeP( &p->vTimeStamps ); Vec_FltFreeP( &p->vTiming ); Vec_VecFreeP( &p->vClockDoms ); @@ -122,6 +130,7 @@ void Gia_ManStop( Gia_Man_t * p ) Vec_IntFreeP( &p->vVar2Obj ); Vec_IntErase( &p->vCopiesTwo ); Vec_IntErase( &p->vSuppVars ); + Vec_IntErase( &p->vVarMap ); Vec_WrdFreeP( &p->vSuppWords ); Vec_IntFreeP( &p->vTtNums ); Vec_IntFreeP( &p->vTtNodes ); @@ -140,6 +149,7 @@ void Gia_ManStop( Gia_Man_t * p ) Vec_IntFreeP( &p->vCoReqs ); Vec_IntFreeP( &p->vCoArrs ); Vec_IntFreeP( &p->vCoAttrs ); + Vec_IntFreeP( &p->vWeights ); Gia_ManStopP( &p->pAigExtra ); Vec_IntFree( p->vCis ); Vec_IntFree( p->vCos ); @@ -194,6 +204,7 @@ double Gia_ManMemory( Gia_Man_t * p ) Memory += Vec_FltMemory( p->vOutReqs ); Memory += Vec_PtrMemory( p->vNamesIn ); Memory += Vec_PtrMemory( p->vNamesOut ); + Memory += Vec_PtrMemory( p->vNamesNode ); return Memory; } @@ -240,10 +251,10 @@ void Gia_ManPrintClasses_old( Gia_Man_t * p ) { Gia_Man_t * pTemp; pTemp = Gia_ManDupFlopClass( p, 1 ); - Gia_AigerWrite( pTemp, "dom1.aig", 0, 0 ); + Gia_AigerWrite( pTemp, "dom1.aig", 0, 0, 0 ); Gia_ManStop( pTemp ); pTemp = Gia_ManDupFlopClass( p, 2 ); - Gia_AigerWrite( pTemp, "dom2.aig", 0, 0 ); + Gia_AigerWrite( pTemp, "dom2.aig", 0, 0, 0 ); Gia_ManStop( pTemp ); } } @@ -430,6 +441,43 @@ int Gia_ManPrintEdges( Gia_Man_t * p ) return 0; } +/**Function************************************************************* + + Synopsis [Prints stats for the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +void Gia_ManLogAigStats( Gia_Man_t * p, char * pDumpFile ) +{ + FILE * pTable = fopen( pDumpFile, "wb" ); + fprintf( pTable, "Name = %24s ", p->pName ); + fprintf( pTable, "In = %6d ", Gia_ManCiNum(p) ); + fprintf( pTable, "Out = %6d ", Gia_ManCoNum(p) ); + fprintf( pTable, "And = %8d ", Gia_ManAndNum(p) ); + fprintf( pTable, "Lev = %6d", Gia_ManLevelNum(p) ); + fprintf( pTable, "\n" ); + fclose( pTable ); +} +*/ +void Gia_ManLogAigStats( Gia_Man_t * p, char * pDumpFile ) +{ + FILE * pTable = fopen( pDumpFile, "wb" ); + fprintf( pTable, "{\n" ); + fprintf( pTable, " \"name\" : \"%s\",\n", p->pName ); + fprintf( pTable, " \"input\" : %d,\n", Gia_ManCiNum(p) ); + fprintf( pTable, " \"output\" : %d,\n", Gia_ManCoNum(p) ); + fprintf( pTable, " \"and\" : %d,\n", Gia_ManAndNum(p) ); + fprintf( pTable, " \"level\" : %d\n", Gia_ManLevelNum(p) ); + fprintf( pTable, "}\n" ); + fclose( pTable ); +} + /**Function************************************************************* Synopsis [Prints stats for the AIG.] @@ -444,11 +492,19 @@ int Gia_ManPrintEdges( Gia_Man_t * p ) void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars ) { extern float Gia_ManLevelAve( Gia_Man_t * p ); + int fHaveLevels = p->vLevels != NULL; if ( pPars && pPars->fMiter ) { Gia_ManPrintStatsMiter( p, 0 ); return; } + if ( pPars && pPars->fNoColor ) + { + if ( p->pName ) + Abc_Print( 1, "%-8s : ", p->pName ); + } + else + { #ifdef WIN32 SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 15 ); // bright if ( p->pName ) @@ -458,6 +514,7 @@ void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars ) if ( p->pName ) Abc_Print( 1, "%s%-8s%s : ", "\033[1;37m", p->pName, "\033[0m" ); // bright #endif + } Abc_Print( 1, "i/o =%7d/%7d", Gia_ManPiNum(p) - Gia_ManBoxCiNum(p) - Gia_ManRegBoxNum(p), Gia_ManPoNum(p) - Gia_ManBoxCoNum(p) - Gia_ManRegBoxNum(p) ); @@ -467,7 +524,14 @@ void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars ) Abc_Print( 1, " ff =%7d", Gia_ManRegNum(p) ); if ( Gia_ManRegBoxNum(p) ) Abc_Print( 1, " boxff =%d(%d)", Gia_ManRegBoxNum(p), Gia_ManClockDomainNum(p) ); - + if ( pPars && pPars->fNoColor ) + { + Abc_Print( 1, " %s =%8d", p->pMuxes? "nod" : "and", Gia_ManAndNum(p) ); + Abc_Print( 1, " lev =%5d", Gia_ManLevelNum(p) ); + Abc_Print( 1, " (%.2f)", Gia_ManLevelAve(p) ); + } + else + { #ifdef WIN32 { HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); @@ -475,7 +539,7 @@ void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars ) Abc_Print( 1, " %s =%8d", p->pMuxes? "nod" : "and", Gia_ManAndNum(p) ); SetConsoleTextAttribute( hConsole, 13 ); // magenta Abc_Print( 1, " lev =%5d", Gia_ManLevelNum(p) ); - Abc_Print( 1, " (%.2f)", Gia_ManLevelAve(p) ); + Abc_Print( 1, " (%7.2f)", Gia_ManLevelAve(p) ); SetConsoleTextAttribute( hConsole, 7 ); // normal } #else @@ -483,7 +547,9 @@ void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars ) Abc_Print( 1, " %slev =%5d%s", "\033[1;35m", Gia_ManLevelNum(p), "\033[0m" ); // magenta Abc_Print( 1, " %s(%.2f)%s", "\033[1;35m", Gia_ManLevelAve(p), "\033[0m" ); #endif - Vec_IntFreeP( &p->vLevels ); + } + if ( !fHaveLevels ) + Vec_IntFreeP( &p->vLevels ); if ( pPars && pPars->fCut ) Abc_Print( 1, " cut = %d(%d)", Gia_ManCrossCut(p, 0), Gia_ManCrossCut(p, 1) ); Abc_Print( 1, " mem =%5.2f MB", Gia_ManMemory(p)/(1<<20) ); @@ -495,6 +561,8 @@ void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars ) Abc_Print( 1, " bb = %d", Gia_ManBlackBoxNum(p) ); if ( Gia_ManBufNum(p) ) Abc_Print( 1, " buf = %d", Gia_ManBufNum(p) ); + if ( Gia_ManXorNum(p) && p->pMuxes == NULL ) + Abc_Print( 1, " xor = %d", Gia_ManXorNum(p) ); if ( pPars && pPars->fMuxXor ) printf( "\nXOR/MUX " ), Gia_ManPrintMuxStats( p ); if ( pPars && pPars->fSwitch ) @@ -516,7 +584,9 @@ void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars ) Gia_ManEquivPrintClasses( p, 0, 0.0 ); if ( Gia_ManHasMapping(p) && (pPars == NULL || !pPars->fSkipMap) ) Gia_ManPrintMappingStats( p, pPars ? pPars->pDumpFile : NULL ); - if ( pPars && pPars->fNpn && Gia_ManHasMapping(p) && Gia_ManLutSizeMax(p) <= 4 ) + else if ( pPars && pPars->pDumpFile ) + Gia_ManLogAigStats( p, pPars->pDumpFile ); + if ( pPars && pPars->fNpn && Gia_ManHasMapping(p) ) Gia_ManPrintNpnClasses( p ); if ( p->vPacking ) Gia_ManPrintPackingStats( p ); @@ -733,7 +803,7 @@ void Gia_ManPrintNpnClasses( Gia_Man_t * p ) Vec_Int_t * vLeaves, * vTruth, * vVisited; int * pLutClass, ClassCounts[222] = {0}; int i, k, iFan, Class, OtherClasses, OtherClasses2, nTotal, Counter, Counter2; - unsigned * pTruth; + unsigned * pTruth; int nLutSize = 0; assert( Gia_ManHasMapping(p) ); assert( Gia_ManLutSizeMax( p ) <= 4 ); vLeaves = Vec_IntAlloc( 100 ); @@ -743,6 +813,7 @@ void Gia_ManPrintNpnClasses( Gia_Man_t * p ) Gia_ManCleanTruth( p ); Gia_ManForEachLut( p, i ) { + nLutSize = Abc_MaxInt( nLutSize, Gia_ObjLutSize(p,i) ); if ( Gia_ObjLutSize(p,i) > 4 ) continue; Vec_IntClear( vLeaves ); @@ -802,6 +873,55 @@ void Gia_ManPrintNpnClasses( Gia_Man_t * p ) Abc_Print( 1, "Approximate number of 4:1 MUX structures: All = %6d (%7.2f %%) MFFC = %6d (%7.2f %%)\n", OtherClasses, 100.0 * OtherClasses / (nTotal+1), OtherClasses2, 100.0 * OtherClasses2 / (nTotal+1) ); + // print information about LUT pairs + if ( nLutSize <= 4 ) + { + int nTopPairs = 100, nTopShow = 30; + int i, j, k, iFan, * pVec = NULL; + Vec_Int_t * vPairs = Vec_IntAlloc( 3 * nTopPairs ); + Gia_ManForEachLut( p, j ) { + Gia_LutForEachFanin( p, j, iFan, k ) { + int Num1 = pLutClass[iFan]; + int Num2 = pLutClass[j]; + assert( Vec_IntSize(vPairs) % 3 == 0 ); + for ( i = 0; i < Vec_IntSize(vPairs); i += 3 ) + if ( Vec_IntEntry(vPairs, i+0) == Num1 && Vec_IntEntry(vPairs, i+1) == Num2 ) + break; + if ( i == Vec_IntSize(vPairs) ) { + if ( Vec_IntSize(vPairs) < 3*nTopPairs ) { + Vec_IntPush( vPairs, Num1 ); + Vec_IntPush( vPairs, Num2 ); + Vec_IntPush( vPairs, 1 ); + } + continue; + } + // found this pair + assert( Vec_IntEntry(vPairs, i+0) == Num1 ); + assert( Vec_IntEntry(vPairs, i+1) == Num2 ); + Vec_IntAddToEntry( vPairs, i+2, 1 ); + // sort + pVec = Vec_IntArray( vPairs ); + while ( i > 0 && pVec[i+2] > pVec[i-1] ) { + ABC_SWAP( int, pVec[i+0], pVec[i-3] ) + ABC_SWAP( int, pVec[i+1], pVec[i-2] ) + ABC_SWAP( int, pVec[i+2], pVec[i-1] ) + i -= 3; + } + while ( i < Vec_IntSize(vPairs) - 3 && pVec[i+2] < pVec[i+5] ) { + ABC_SWAP( int, pVec[i+0], pVec[i+3] ) + ABC_SWAP( int, pVec[i+1], pVec[i+4] ) + ABC_SWAP( int, pVec[i+2], pVec[i+5] ) + i += 3; + assert( 0 ); + } + } + } + pVec = Vec_IntArray( vPairs ); + nTopShow = Abc_MinInt( nTopShow, Vec_IntSize(vPairs)/3 ); + for ( i = 0; i < 3*nTopShow; i += 3 ) + printf( "%3d : (%3d %3d) x %3d\n", i/3, pVec[i+0], pVec[i+1], pVec[i+2] ); + Vec_IntFree( vPairs ); + } ABC_FREE( pLutClass ); } @@ -1121,6 +1241,353 @@ void Gia_ManDfsSlacksPrint( Gia_Man_t * p ) } +/**Function************************************************************* + + Synopsis [Dump interface module] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManWriteNamesInter( FILE * pFile, char c, int n, int Start, int Skip, int nRegs ) +{ + int Length = Start, i, fFirst = 1; + char pName[100]; + for ( i = 0; i < n-nRegs; i++ ) + { + sprintf( pName, "%c[%d]", c, i ); + Length += strlen(pName) + 2; + if ( Length > 60 ) + { + fprintf( pFile, ",\n " ); + Length = Skip; + fFirst = 1; + } + fprintf( pFile, "%s%s", fFirst ? "":", ", pName ); + fFirst = 0; + } + for ( i = n-nRegs; i < n; i++ ) + { + sprintf( pName, "%c%c[%d]", c, c, i ); + Length += strlen(pName) + 2; + if ( Length > 60 ) + { + fprintf( pFile, ",\n " ); + Length = Skip; + fFirst = 1; + } + fprintf( pFile, "%s%s", fFirst ? "":", ", pName ); + fFirst = 0; + }} +void Gia_ManDumpModuleName( FILE * pFile, char * pName ) +{ + int i; + for ( i = 0; i < (int)strlen(pName); i++ ) + if ( isalpha(pName[i]) || isdigit(pName[i]) ) + fprintf( pFile, "%c", pName[i] ); + else + fprintf( pFile, "_" ); +} +void Gia_ManDumpInterface( Gia_Man_t * p, FILE * pFile ) +{ + int fPrintClk = 0; + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, "_wrapper" ); + fprintf( pFile, " (%s i, o );\n\n", fPrintClk && Gia_ManRegNum(p) ? " clk," : "" ); + if ( fPrintClk && Gia_ManRegNum(p) ) + fprintf( pFile, " input clk;\n" ); + fprintf( pFile, " input [%d:0] i;\n", Gia_ManPiNum(p)-1 ); + fprintf( pFile, " output [%d:0] o;\n\n", Gia_ManPoNum(p)-1 ); + + if ( Gia_ManRegNum(p) ) { + fprintf( pFile, " wire [%d:%d] ii;\n", Gia_ManCiNum(p)-1, Gia_ManPiNum(p) ); + fprintf( pFile, " wire [%d:%d] oo;\n\n", Gia_ManCoNum(p)-1, Gia_ManPoNum(p) ); + fprintf( pFile, " always @ (posedge %s)\n ii <= oo;\n\n", fPrintClk ? "clk" : "i[0]" ); + } + + fprintf( pFile, " " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, " " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, "_inst" ); + + fprintf( pFile, " (\n " ); + Gia_ManWriteNamesInter( pFile, 'i', Gia_ManCiNum(p), 4, 4, Gia_ManRegNum(p) ); + fprintf( pFile, ",\n " ); + Gia_ManWriteNamesInter( pFile, 'o', Gia_ManCoNum(p), 4, 4, Gia_ManRegNum(p) ); + fprintf( pFile, "\n );\n\n" ); + + fprintf( pFile, "endmodule\n\n" ); +} + + +/**Function************************************************************* + + Synopsis [Compute arrival/required times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Bit_t * Gia_ManGenUsed( Gia_Man_t * p, int fBuf ) +{ + Gia_Obj_t * pObj; int i; + Vec_Bit_t * vUsed = Vec_BitStart( Gia_ManObjNum(p) ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( fBuf ) + Vec_BitWriteEntry( vUsed, i, 1 ); + if ( Gia_ObjFaninC0(pObj) ^ fBuf ) + Vec_BitWriteEntry( vUsed, Gia_ObjFaninId0(pObj, i), 1 ); + if ( Gia_ObjFaninC1(pObj) ^ fBuf ) + Vec_BitWriteEntry( vUsed, Gia_ObjFaninId1(pObj, i), 1 ); + } + Gia_ManForEachCo( p, pObj, i ) + if ( Gia_ObjFaninC0(pObj) ^ fBuf ) + Vec_BitWriteEntry( vUsed, Gia_ObjFaninId0p(p, pObj), 1 ); + Vec_BitWriteEntry( vUsed, 0, 0 ); // clean zero + return vUsed; +} +int Gia_ManNameIsLegalInVerilog( char * pName ) +{ + // identifier ::= simple_identifier | escaped_identifier + // simple_identifier ::= [a-zA-Z_][a-zA-Z0-9_$] + // escaped_identifier ::= \ {Any_ASCII_character_except_white_space} white_space + // white_space ::= space | tab | newline + assert( pName != NULL && *pName != '\0' ); + if ( *pName == '\\' ) + return 1; + if ( (*pName < 'a' || *pName > 'z') && (*pName < 'A' || *pName > 'Z') && *pName != '_' ) + return 0; + while ( *(++pName) ) + if ( (*pName < 'a' || *pName > 'z') && (*pName < 'A' || *pName > 'Z') && (*pName < '0' || *pName > '9') && *pName != '_' && *pName != '$' ) + return 0; + return 1; +} +char * Gia_ObjGetDumpName( Vec_Ptr_t * vNames, char c, int i, int d ) +{ + static char pBuffer[10000]; + if ( vNames ) + { + char * pName = (char *)Vec_PtrEntry(vNames, i); + if ( Gia_ManNameIsLegalInVerilog(pName) ) + sprintf( pBuffer, "%s", pName ); + else + sprintf( pBuffer, "\\%s ", pName ); + } + else + sprintf( pBuffer, "%c%0*d%c", c, d, i, c ); + return pBuffer; +} +void Gia_ManWriteNames( FILE * pFile, char c, int n, Vec_Ptr_t * vNames, int Start, int Skip, Vec_Bit_t * vObjs ) +{ + int Digits = Abc_Base10Log( n ); + int Length = Start, i, fFirst = 1; + char * pName; + for ( i = 0; i < n; i++ ) + { + if ( vObjs && !Vec_BitEntry(vObjs, i) ) + continue; + pName = Gia_ObjGetDumpName( vNames, c, i, Digits ); + Length += strlen(pName) + 2; + if ( Length > 60 ) + { + fprintf( pFile, ",\n " ); + Length = Skip; + fFirst = 1; + } + fprintf( pFile, "%s%s", fFirst ? "":", ", pName ); + fFirst = 0; + } +} +void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ) +{ + Gia_Obj_t * pObj; + Vec_Bit_t * vInvs, * vUsed; + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); + int i, k, iObj, nRegs = Gia_ManRegNum(p); + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + + if ( fInter || nRegs ) + Gia_ManDumpInterface( p, pFile ); + //Gia_ManSetRegNum( p, 0 ); + p->nRegs = 0; + + vInvs = Gia_ManGenUsed( p, 0 ); + vUsed = Gia_ManGenUsed( p, 1 ); + + //fprintf( pFile, "// This Verilog file is written by ABC on %s\n\n", Extra_TimeStamp() ); + + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + + if ( fVerBufs ) + { + fprintf( pFile, " (\n " ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 4, 4, NULL ); + fprintf( pFile, ",\n " ); + + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 4, 4, NULL ); + fprintf( pFile, "\n );\n\n" ); + + fprintf( pFile, " input " ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 8, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " output " ); + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 9, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + Gia_ManForEachPi( p, pObj, i ) + { + fprintf( pFile, " buf ( %s,", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(NULL, 'a', i, nDigitsI) ); + } + fprintf( pFile, "\n" ); + + Gia_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, " buf ( %s,", Gia_ObjGetDumpName(NULL, 'y', i, nDigitsO) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + } + fprintf( pFile, "\n" ); + } + else + { + fprintf( pFile, " (\n " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 4, 4, NULL ); + fprintf( pFile, ",\n " ); + + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 4, 4, NULL ); + fprintf( pFile, "\n );\n\n" ); + + fprintf( pFile, " input " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " output " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vUsed) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vInvs) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs ); + fprintf( pFile, ";\n\n" ); + } + + if ( vObjs ) + { + fprintf( pFile, " wire " ); + Vec_IntForEachEntry( vObjs, iObj, i ) + fprintf( pFile, " t_%d%s", i, i==Vec_IntSize(vObjs)-1 ? "" : "," ); + fprintf( pFile, ";\n\n" ); + Vec_IntForEachEntry( vObjs, iObj, i ) + { + fprintf( pFile, " buf ( %s,", Gia_ObjGetDumpName(NULL, 'n', iObj, nDigits) ); + fprintf( pFile, " t_%d );\n", i ); + } + fprintf( pFile, "\n" ); + } + + // input inverters + Gia_ManForEachPi( p, pObj, i ) + { + if ( Vec_BitEntry(vUsed, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " buf ( %s,", Gia_ObjGetDumpName(NULL, 'n', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + if ( Vec_BitEntry(vInvs, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " not ( %s,", Gia_ObjGetDumpName(NULL, 'i', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + } + + // internal nodes and their inverters + fprintf( pFile, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + { + int fSkip = 0; + if ( vObjs ) + { + Vec_IntForEachEntry( vObjs, iObj, k ) + if ( iObj == i ) + break; + if ( k < Vec_IntSize(vObjs) ) + fSkip = 1; + } + if ( !fSkip ) + { + fprintf( pFile, " and ( %s,", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + fprintf( pFile, " %s,", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0(pObj, i), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC1(pObj)? 'i':'n'), Gia_ObjFaninId1(pObj, i), nDigits) ); + } + if ( Vec_BitEntry(vInvs, i) ) + { + fprintf( pFile, " not ( %s,", Gia_ObjGetDumpName(NULL, 'i', i, nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + } + } + + // output drivers + fprintf( pFile, "\n" ); + Gia_ManForEachPo( p, pObj, i ) + { +/* + fprintf( pFile, " assign %s = ", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigits2) ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + fprintf( pFile, "1\'b%d;\n", Gia_ObjFaninC0(pObj) ); + else + fprintf( pFile, "%s;\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0p(p, pObj), nDigits) ); +*/ + fprintf( pFile, " buf ( %s, ", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + fprintf( pFile, "1\'b%d );\n", Gia_ObjFaninC0(pObj) ); + else + fprintf( pFile, "%s );\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0p(p, pObj), nDigits) ); + } + + fprintf( pFile, "\nendmodule\n\n" ); + fclose( pFile ); + + Vec_BitFree( vInvs ); + Vec_BitFree( vUsed ); + + Gia_ManSetRegNum( p, nRegs ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/abc/src/aig/gia/giaMf.c b/abc/src/aig/gia/giaMf.c index 7e699d9b631..0e1ae9a975f 100644 --- a/abc/src/aig/gia/giaMf.c +++ b/abc/src/aig/gia/giaMf.c @@ -24,6 +24,7 @@ #include "misc/extra/extra.h" #include "sat/cnf/cnf.h" #include "opt/dau/dau.h" +#include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START @@ -557,8 +558,8 @@ static inline int Mf_CutComputeTruth6( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t assert( (int)(t & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, &t); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); - if ( p->pPars->fGenCnf && truthId == Vec_IntSize(&p->vCnfSizes) ) - Vec_IntPush( &p->vCnfSizes, Abc_Tt6CnfSize(t, pCutR->nLeaves) ); + if ( (p->pPars->fGenCnf || p->pPars->fGenLit) && truthId == Vec_IntSize(&p->vCnfSizes) ) + Vec_IntPush( &p->vCnfSizes, p->pPars->fGenCnf ? Abc_Tt6CnfSize(t, pCutR->nLeaves) : Kit_TruthLitNum((unsigned *)&t, pCutR->nLeaves, &p->vCnfMem) ); // p->nCutMux += Mf_ManTtIsMux( t ); assert( (int)pCutR->nLeaves <= nOldSupp ); // Mf_ManTruthCanonicize( &t, pCutR->nLeaves ); @@ -588,8 +589,8 @@ static inline int Mf_CutComputeTruth( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t * //Kit_DsdPrintFromTruth( uTruth, pCutR->nLeaves ), printf("\n" ), printf("\n" ); truthId = Vec_MemHashInsert(p->vTtMem, uTruth); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); - if ( p->pPars->fGenCnf && truthId == Vec_IntSize(&p->vCnfSizes) && LutSize <= 8 ) - Vec_IntPush( &p->vCnfSizes, Abc_Tt8CnfSize(uTruth, pCutR->nLeaves) ); + if ( (p->pPars->fGenCnf || p->pPars->fGenLit) && truthId == Vec_IntSize(&p->vCnfSizes) && LutSize <= 8 ) + Vec_IntPush( &p->vCnfSizes, p->pPars->fGenCnf ? Abc_Tt8CnfSize(uTruth, pCutR->nLeaves) : Kit_TruthLitNum((unsigned *)uTruth, pCutR->nLeaves, &p->vCnfMem) ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } @@ -612,8 +613,8 @@ static inline int Mf_CutComputeTruthMux6( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut assert( (int)(t & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, &t); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); - if ( p->pPars->fGenCnf && truthId == Vec_IntSize(&p->vCnfSizes) ) - Vec_IntPush( &p->vCnfSizes, Abc_Tt6CnfSize(t, pCutR->nLeaves) ); + if ( (p->pPars->fGenCnf || p->pPars->fGenLit) && truthId == Vec_IntSize(&p->vCnfSizes) ) + Vec_IntPush( &p->vCnfSizes, p->pPars->fGenCnf ? Abc_Tt6CnfSize(t, pCutR->nLeaves) : Kit_TruthLitNum((unsigned *)&t, pCutR->nLeaves, &p->vCnfMem) ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } @@ -642,8 +643,8 @@ static inline int Mf_CutComputeTruthMux( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_ assert( (uTruth[0] & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, uTruth); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); - if ( p->pPars->fGenCnf && truthId == Vec_IntSize(&p->vCnfSizes) && LutSize <= 8 ) - Vec_IntPush( &p->vCnfSizes, Abc_Tt8CnfSize(uTruth, pCutR->nLeaves) ); + if ( (p->pPars->fGenCnf || p->pPars->fGenLit) && truthId == Vec_IntSize(&p->vCnfSizes) && LutSize <= 8 ) + Vec_IntPush( &p->vCnfSizes, p->pPars->fGenCnf ? Abc_Tt8CnfSize(uTruth, pCutR->nLeaves) : Kit_TruthLitNum((unsigned *)uTruth, pCutR->nLeaves, &p->vCnfMem) ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } @@ -699,6 +700,8 @@ static inline void Mf_CutPrint( Mf_Man_t * p, Mf_Cut_t * pCut ) { if ( p->pPars->fGenCnf ) printf( "CNF = %2d ", Vec_IntEntry(&p->vCnfSizes, Abc_Lit2Var(pCut->iFunc)) ); + if ( p->pPars->fGenLit ) + printf( "Lit = %2d ", Vec_IntEntry(&p->vCnfSizes, Abc_Lit2Var(pCut->iFunc)) ); Dau_DsdPrintFromTruth( Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut->iFunc)), pCut->nLeaves ); } else @@ -998,7 +1001,7 @@ static inline int Mf_CutArea( Mf_Man_t * p, int nLeaves, int iFunc ) { if ( nLeaves < 2 ) return 0; - if ( p->pPars->fGenCnf ) + if ( p->pPars->fGenCnf || p->pPars->fGenLit ) return Vec_IntEntry(&p->vCnfSizes, Abc_Lit2Var(iFunc)); if ( p->pPars->fOptEdge ) return nLeaves + p->pPars->nAreaTuner; @@ -1202,7 +1205,7 @@ int Mf_ManSetMapRefs( Mf_Man_t * p ) Mf_ObjMapRefInc( p, pCut[k] ); p->pPars->Edge += Mf_CutSize(pCut); p->pPars->Area++; - if ( p->pPars->fGenCnf ) + if ( p->pPars->fGenCnf || p->pPars->fGenLit ) p->pPars->Clause += Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); } // blend references @@ -1394,7 +1397,7 @@ Mf_Man_t * Mf_ManAlloc( Gia_Man_t * pGia, Jf_Par_t * pPars ) p->pLfObjs = ABC_CALLOC( Mf_Obj_t, Gia_ManObjNum(pGia) ); p->iCur = 2; Vec_PtrGrow( &p->vPages, 256 ); - if ( pPars->fGenCnf ) + if ( pPars->fGenCnf || pPars->fGenLit ) { Vec_IntGrow( &p->vCnfSizes, 10000 ); Vec_IntPush( &p->vCnfSizes, 1 ); @@ -1410,7 +1413,7 @@ Mf_Man_t * Mf_ManAlloc( Gia_Man_t * pGia, Jf_Par_t * pPars ) } void Mf_ManFree( Mf_Man_t * p ) { - assert( !p->pPars->fGenCnf || Vec_IntSize(&p->vCnfSizes) == Vec_MemEntryNum(p->vTtMem) ); + assert( !p->pPars->fGenCnf || !p->pPars->fGenLit || Vec_IntSize(&p->vCnfSizes) == Vec_MemEntryNum(p->vTtMem) ); if ( p->pPars->fCutMin ) Vec_MemHashFree( p->vTtMem ); if ( p->pPars->fCutMin ) @@ -1453,6 +1456,7 @@ void Mf_ManSetDefaultPars( Jf_Par_t * pPars ) pPars->fCoarsen = 1; pPars->fCutMin = 0; pPars->fGenCnf = 0; + pPars->fGenLit = 0; pPars->fPureAig = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; @@ -1469,6 +1473,8 @@ void Mf_ManPrintStats( Mf_Man_t * p, char * pTitle ) printf( "Edge =%9lu ", (long)p->pPars->Edge ); if ( p->pPars->fGenCnf ) printf( "CNF =%9lu ", (long)p->pPars->Clause ); + if ( p->pPars->fGenLit ) + printf( "FFL =%9lu ", (long)p->pPars->Clause ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); fflush( stdout ); } @@ -1483,6 +1489,7 @@ void Mf_ManPrintInit( Mf_Man_t * p ) printf( "CutMin = %d ", p->pPars->fCutMin ); printf( "Coarse = %d ", p->pPars->fCoarsen ); printf( "CNF = %d ", p->pPars->fGenCnf ); + printf( "FFL = %d ", p->pPars->fGenLit ); printf( "\n" ); printf( "Computing cuts...\r" ); fflush( stdout ); @@ -1541,51 +1548,97 @@ void Mf_ManComputeCuts( Mf_Man_t * p ) SeeAlso [] ***********************************************************************/ -int Mf_CutRef2_rec( Mf_Man_t * p, int * pCut, Vec_Int_t * vTemp, int Limit ) +int Mf_CutRef_rec( Mf_Man_t * p, int * pCut ) { int i, Count = Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); - if ( Limit == 0 ) return Count; for ( i = 1; i <= Mf_CutSize(pCut); i++ ) - { - Vec_IntPush( vTemp, pCut[i] ); if ( !Mf_ObjMapRefInc(p, pCut[i]) && Mf_ManObj(p, pCut[i])->iCutSet ) - Count += Mf_CutRef2_rec( p, Mf_ObjCutBest(p, pCut[i]), vTemp, Limit-1 ); - } + Count += Mf_CutRef_rec( p, Mf_ObjCutBest(p, pCut[i]) ); return Count; } -static inline int Mf_CutAreaDerefed2( Mf_Man_t * p, int * pCut ) +int Mf_CutDeref_rec( Mf_Man_t * p, int * pCut ) { - int Ela1, iObj, i; - Vec_IntClear( &p->vTemp ); - Ela1 = Mf_CutRef2_rec( p, pCut, &p->vTemp, 8 ); - Vec_IntForEachEntry( &p->vTemp, iObj, i ) - Mf_ObjMapRefDec( p, iObj ); + int i, Count = Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); + for ( i = 1; i <= Mf_CutSize(pCut); i++ ) + if ( !Mf_ObjMapRefDec(p, pCut[i]) && Mf_ManObj(p, pCut[i])->iCutSet ) + Count += Mf_CutDeref_rec( p, Mf_ObjCutBest(p, pCut[i]) ); + return Count; +} +static inline int Mf_CutAreaRefed( Mf_Man_t * p, int * pCut ) +{ + int Ela1 = Mf_CutDeref_rec( p, pCut ); + int Ela2 = Mf_CutRef_rec( p, pCut ); + assert( Ela1 == Ela2 ); + return Ela1; +} +static inline int Mf_CutAreaDerefed( Mf_Man_t * p, int * pCut ) +{ + int Ela1 = Mf_CutRef_rec( p, pCut ); + int Ela2 = Mf_CutDeref_rec( p, pCut ); + assert( Ela1 == Ela2 ); return Ela1; } +static inline int Mf_CutAreaMffc( Mf_Man_t * p, int iObj ) +{ + return Mf_ObjMapRefNum(p, iObj) ? + Mf_CutAreaRefed (p, Mf_ObjCutBest(p, iObj)) : + Mf_CutAreaDerefed(p, Mf_ObjCutBest(p, iObj)); +} -int Mf_CutRef_rec( Mf_Man_t * p, int * pCut ) +int Mf_CutRef2_rec( Mf_Man_t * p, int * pCut, Vec_Int_t * vTemp, int Limit ) { int i, Count = Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); + if ( Limit == 0 ) return Count; for ( i = 1; i <= Mf_CutSize(pCut); i++ ) + { + Vec_IntPush( vTemp, pCut[i] ); if ( !Mf_ObjMapRefInc(p, pCut[i]) && Mf_ManObj(p, pCut[i])->iCutSet ) - Count += Mf_CutRef_rec( p, Mf_ObjCutBest(p, pCut[i]) ); + Count += Mf_CutRef2_rec( p, Mf_ObjCutBest(p, pCut[i]), vTemp, Limit-1 ); + } return Count; } -int Mf_CutDeref_rec( Mf_Man_t * p, int * pCut ) +int Mf_CutDeref2_rec( Mf_Man_t * p, int * pCut, Vec_Int_t * vTemp, int Limit ) { int i, Count = Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); + if ( Limit == 0 ) return Count; for ( i = 1; i <= Mf_CutSize(pCut); i++ ) + { + Vec_IntPush( vTemp, pCut[i] ); if ( !Mf_ObjMapRefDec(p, pCut[i]) && Mf_ManObj(p, pCut[i])->iCutSet ) - Count += Mf_CutDeref_rec( p, Mf_ObjCutBest(p, pCut[i]) ); + Count += Mf_CutDeref2_rec( p, Mf_ObjCutBest(p, pCut[i]), vTemp, Limit-1 ); + } return Count; } -static inline int Mf_CutAreaDerefed( Mf_Man_t * p, int * pCut ) +static inline int Mf_CutAreaRefed2( Mf_Man_t * p, int * pCut ) { - int Ela1 = Mf_CutRef_rec( p, pCut ); - int Ela2 = Mf_CutDeref_rec( p, pCut ); - assert( Ela1 == Ela2 ); + int Ela1, iObj, i; + Vec_IntClear( &p->vTemp ); + Ela1 = Mf_CutDeref2_rec( p, pCut, &p->vTemp, 8 ); + Vec_IntForEachEntry( &p->vTemp, iObj, i ) + Mf_ObjMapRefInc( p, iObj ); return Ela1; } +static inline int Mf_CutAreaDerefed2( Mf_Man_t * p, int * pCut ) +{ + int Ela1, iObj, i; + Vec_IntClear( &p->vTemp ); + Ela1 = Mf_CutRef2_rec( p, pCut, &p->vTemp, 8 ); + Vec_IntForEachEntry( &p->vTemp, iObj, i ) + Mf_ObjMapRefDec( p, iObj ); + return Ela1; +} +static inline int Mf_CutAreaRefed2Multi( Mf_Man_t * p, int iObj, int ** ppCuts, int nCuts ) +{ + int Ela1 = 0, iTemp, i; + Vec_IntClear( &p->vTemp ); + for ( i = 0; i < nCuts; i++ ) + Ela1 += Mf_CutDeref2_rec( p, ppCuts[i], &p->vTemp, ABC_INFINITY ); + assert( Mf_ObjMapRefNum(p, iObj) == 0 ); + Vec_IntForEachEntry( &p->vTemp, iTemp, i ) + Mf_ObjMapRefInc( p, iTemp ); + return Ela1; +} + static inline float Mf_CutFlow( Mf_Man_t * p, int * pCut, int * pTime ) { Mf_Obj_t * pObj; @@ -1633,6 +1686,120 @@ static inline void Mf_ObjComputeBestCut( Mf_Man_t * p, int iObj ) } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mf_ManMappingFromMapping( Mf_Man_t * p ) +{ + Gia_Man_t * pGia = p->pGia0; + Gia_Obj_t * pObj; + int i, iObj, Count = 0; + Vec_Int_t * vMapping = Vec_IntAlloc( 3 * Gia_ManObjNum(pGia) ); + Vec_IntFill( vMapping, Gia_ManObjNum(pGia), 0 ); + Gia_ManForEachAnd( pGia, pObj, iObj ) + if ( Mf_ObjMapRefNum(p, iObj) ) + { + int * pCut = Mf_ObjCutBest(p, iObj); + Vec_IntWriteEntry( vMapping, iObj, Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Mf_CutSize(pCut) ); + for ( i = 1; i <= Mf_CutSize(pCut); i++ ) + Vec_IntPush( vMapping, pCut[i] ); + Vec_IntPush( vMapping, iObj ); + Count++; + } + assert( pGia->vMapping == NULL ); + pGia->vMapping = vMapping; + printf( "Mapping is %.2fx larger than AIG manager.\n", 1.0*Vec_IntSize(vMapping)/Gia_ManObjNum(pGia) ); + return Count; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mf_ManPrintFanoutProfile( Mf_Man_t * p, Vec_Int_t * vFanCounts ) +{ + Gia_Man_t * pGia = p->pGia0; + int i, Count, nMax = Vec_IntFindMax( vFanCounts ); + Vec_Int_t * vCounts = Vec_IntStart( nMax + 1 ); + Vec_IntForEachEntry( vFanCounts, Count, i ) + if ( Count && Gia_ObjIsAnd(Gia_ManObj(pGia, i)) ) + Vec_IntAddToEntry( vCounts, Count, 1 ); + printf( "\nFanout distribution for internal nodes:\n" ); + Vec_IntForEachEntry( vCounts, Count, i ) + if ( Count ) printf( "Fanout = %5d : Nodes = %5d.\n", i, Count ); + printf( "Total nodes with fanout = %d. Max fanout = %d.\n\n", Vec_IntCountPositive(vCounts), nMax ); + Vec_IntFree( vCounts ); +} +int Mf_ManPrintMfccStats( Mf_Man_t * p, int iObj ) +{ + Gia_Man_t * pGia = p->pGia0; + int Area; + printf( "%5d : Level = %5d Refs = %5d Mffc = %5d\n", + iObj, Gia_ObjLevelId(pGia, iObj), Mf_ObjMapRefNum(p, iObj), (Area = Mf_CutAreaMffc(p, iObj)) ); + return Area; +} +void Mf_ManOptimizationOne( Mf_Man_t * p, int iObj ) +{ + Gia_Man_t * pGia = p->pGia0; + int * ppCuts[32], nCuts = 0; + int iFanout, i, nAreaSum = 0, nAreaBest = 0; + // skip pivots whose MFFC fanouts are pointed to by COs + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + if ( Gia_ObjIsCo(Gia_ManObj(pGia, iFanout)) ) + return; + // the pivot is used in the mapping as well as all of its fanouts + assert( Mf_ObjMapRefNum(p, iObj) > 1 ); + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + assert( Mf_ObjMapRefNum(p, iFanout) > 0 ); + // print this pivot and its fanouts + printf( "\nPivot node = %d\n", iObj ); + printf( "Pivot " ), Mf_ManPrintMfccStats( p, iObj ); + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + printf( "Node " ), nAreaSum += Mf_ManPrintMfccStats( p, iFanout ); + // calculate the shared MFFC + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + Mf_ObjMapRefInc( p, iFanout ); + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + ppCuts[nCuts++] = Mf_ObjCutBest( p, iFanout ); + nAreaBest = Mf_CutAreaRefed2Multi( p, iObj, ppCuts, nCuts ); + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + Mf_ObjMapRefDec( p, iFanout ); + printf( "Sum of MFFC sizes = %d\n", nAreaSum ); + printf( "Shared MFFC size = %d\n", nAreaBest ); +} +void Mf_ManOptimization( Mf_Man_t * p ) +{ + int nOutMax = 3; + Gia_Man_t * pGia = p->pGia0; + int i, Count, nNodes = Mf_ManMappingFromMapping( p ); + Gia_ManLevelNum( pGia ); + Gia_ManStaticMappingFanoutStart( pGia, NULL ); + Mf_ManPrintFanoutProfile( p, pGia->vFanoutNums ); + printf( "\nIndividual logic cones for mapping with %d nodes:\n", nNodes ); + Vec_IntForEachEntry( pGia->vFanoutNums, Count, i ) + if ( Count >= 2 && Count <= nOutMax && Gia_ObjIsAnd(Gia_ManObj(pGia, i)) ) + Mf_ManOptimizationOne( p, i ); + printf( "\nFinished printing individual logic cones.\n" ); + Gia_ManStaticFanoutStop( pGia ); + Vec_IntFreeP( &pGia->vMapping ); +} + /**Function************************************************************* Synopsis [Technology mappping.] @@ -1656,7 +1823,7 @@ Gia_Man_t * Mf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) { Mf_Man_t * p; Gia_Man_t * pNew, * pCls; - if ( pPars->fGenCnf ) + if ( pPars->fGenCnf || pPars->fGenLit ) pPars->fCutMin = 1; if ( Gia_ManHasChoices(pGia) ) pPars->fCutMin = 1, pPars->fCoarsen = 0; @@ -1675,6 +1842,7 @@ Gia_Man_t * Mf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) p->fUseEla = 1; for ( ; p->Iter < p->pPars->nRounds + pPars->nRoundsEla; p->Iter++ ) Mf_ManComputeMapping( p ); + //Mf_ManOptimization( p ); if ( pPars->fVeryVerbose && pPars->fCutMin ) Vec_MemDumpTruthTables( p->vTtMem, Gia_ManName(p->pGia), pPars->nLutSize ); if ( pPars->fCutMin ) @@ -1685,8 +1853,8 @@ Gia_Man_t * Mf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) pNew = Mf_ManDeriveMapping( p ); if ( p->pPars->fGenCnf ) pGia->pData = Mf_ManDeriveCnf( p, p->pPars->fCnfObjIds, p->pPars->fAddOrCla ); -// if ( p->pPars->fGenCnf ) -// Mf_ManProfileTruths( p ); + //if ( p->pPars->fGenCnf || p->pPars->fGenLit ) + // Mf_ManProfileTruths( p ); Gia_ManMappingVerify( pNew ); Mf_ManPrintQuit( p, pNew ); Mf_ManFree( p ); diff --git a/abc/src/aig/gia/giaMfs.c b/abc/src/aig/gia/giaMfs.c index 23038efff82..a0e6caed4fb 100644 --- a/abc/src/aig/gia/giaMfs.c +++ b/abc/src/aig/gia/giaMfs.c @@ -46,7 +46,7 @@ ABC_NAMESPACE_IMPL_START ***********************************************************************/ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p ) { - word uTruth, uTruths6[6] = { + word uTruth, * pTruth, uTruths6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), @@ -60,14 +60,19 @@ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p ) Vec_Str_t * vEmpty; // mfs data Vec_Wrd_t * vTruths; // mfs data Vec_Int_t * vArray; + Vec_Int_t * vStarts; + Vec_Wrd_t * vTruths2; Vec_Int_t * vLeaves; Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; int nBoxes = Gia_ManBoxNum(p), nVars; int nRealPis = nBoxes ? Tim_ManPiNum(pManTime) : Gia_ManPiNum(p); int nRealPos = nBoxes ? Tim_ManPoNum(pManTime) : Gia_ManPoNum(p); - int i, j, k, curCi, curCo, nBoxIns, nBoxOuts; + int i, j, k, curCi, curCo, nBoxIns, nBoxOuts, w, nWords; int Id, iFan, nMfsVars, nBbIns = 0, nBbOuts = 0, Counter = 0; - assert( !p->pAigExtra || Gia_ManPiNum(p->pAigExtra) <= 6 ); + int nLutSizeMax = Gia_ManLutSizeMax( p ); + nLutSizeMax = Abc_MaxInt( nLutSizeMax, 6 ); + assert( nLutSizeMax < 16 ); + //assert( !p->pAigExtra || Gia_ManPiNum(p->pAigExtra) <= 6 ); if ( pManTime ) Tim_ManBlackBoxIoNum( pManTime, &nBbIns, &nBbOuts ); // skip PIs due to box outputs Counter += nBbOuts; @@ -77,6 +82,8 @@ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p ) vFixed = Vec_StrStart( nMfsVars ); vEmpty = Vec_StrStart( nMfsVars ); vTruths = Vec_WrdStart( nMfsVars ); + vStarts = Vec_IntStart( nMfsVars ); + vTruths2 = Vec_WrdAlloc( 10000 ); // set internal PIs Gia_ManCleanCopyArray( p ); Gia_ManForEachCiId( p, Id, i ) @@ -86,8 +93,8 @@ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p ) Vec_WrdWriteEntry( vTruths, Counter, (word)0 ); Gia_ObjSetCopyArray( p, 0, Counter++ ); // set internal LUTs - vLeaves = Vec_IntAlloc( 6 ); - Gia_ObjComputeTruthTableStart( p, 6 ); + vLeaves = Vec_IntAlloc( nLutSizeMax ); + Gia_ObjComputeTruthTableStart( p, nLutSizeMax ); Gia_ManForEachLut( p, Id ) { Vec_IntClear( vLeaves ); @@ -99,12 +106,18 @@ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p ) Vec_IntPush( vArray, Gia_ObjCopyArray(p, iFan) ); Vec_IntPush( vLeaves, iFan ); } - assert( Vec_IntSize(vLeaves) <= 6 ); + assert( Vec_IntSize(vLeaves) < 16 ); assert( Vec_IntSize(vLeaves) == Gia_ObjLutSize(p, Id) ); - uTruth = *Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, Id), vLeaves ); - nVars = Abc_Tt6MinBase( &uTruth, Vec_IntArray(vArray), Vec_IntSize(vArray) ); +// uTruth = *Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, Id), vLeaves ); +// nVars = Abc_Tt6MinBase( &uTruth, Vec_IntArray(vArray), Vec_IntSize(vArray) ); + pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, Id), vLeaves ); + nVars = Abc_TtMinBase( pTruth, Vec_IntArray(vArray), Vec_IntSize(vArray), Vec_IntSize(vLeaves) ); Vec_IntShrink( vArray, nVars ); - Vec_WrdWriteEntry( vTruths, Counter, uTruth ); + Vec_WrdWriteEntry( vTruths, Counter, pTruth[0] ); + nWords = Abc_Truth6WordNum( nVars ); + Vec_IntWriteEntry( vStarts, Counter, Vec_WrdSize(vTruths2) ); + for ( w = 0; w < nWords; w++ ) + Vec_WrdPush( vTruths2, pTruth[w] ); if ( Gia_ObjLutIsMux(p, Id) ) { Vec_StrWriteEntry( vFixed, Counter, (char)1 ); @@ -126,6 +139,8 @@ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p ) Vec_StrWriteEntry( vEmpty, Counter, (char)1 ); uTruth = Gia_ObjFaninC0(pObj) ? ~uTruths6[0]: uTruths6[0]; Vec_WrdWriteEntry( vTruths, Counter, uTruth ); + Vec_IntWriteEntry( vStarts, Counter, Vec_WrdSize(vTruths2) ); + Vec_WrdPush( vTruths2, uTruth ); } Gia_ObjSetCopyArray( p, Gia_ObjId(p, pObj), Counter++ ); } @@ -136,20 +151,21 @@ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p ) if ( p->pAigExtra ) { int iBbIn = 0, iBbOut = 0; - Gia_ObjComputeTruthTableStart( p->pAigExtra, 6 ); + assert( Gia_ManCiNum(p->pAigExtra) < 16 ); + Gia_ObjComputeTruthTableStart( p->pAigExtra, Gia_ManCiNum(p->pAigExtra) ); curCi = nRealPis; curCo = 0; for ( k = 0; k < nBoxes; k++ ) { nBoxIns = Tim_ManBoxInputNum( pManTime, k ); nBoxOuts = Tim_ManBoxOutputNum( pManTime, k ); - // collect truth table leaves - Vec_IntClear( vLeaves ); - for ( i = 0; i < nBoxIns; i++ ) - Vec_IntPush( vLeaves, Gia_ObjId(p->pAigExtra, Gia_ManCi(p->pAigExtra, i)) ); // iterate through box outputs - if ( !Tim_ManBoxIsBlack(pManTime, k) ) + if ( !Tim_ManBoxIsBlack(pManTime, k) ) //&& Tim_ManBoxInputNum(pManTime, k) <= 6 ) { + // collect truth table leaves + Vec_IntClear( vLeaves ); + for ( i = 0; i < nBoxIns; i++ ) + Vec_IntPush( vLeaves, Gia_ObjId(p->pAigExtra, Gia_ManCi(p->pAigExtra, i)) ); for ( j = 0; j < nBoxOuts; j++ ) { // CI corresponding to the box outputs @@ -168,17 +184,39 @@ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p ) // box output in the extra manager pObjExtra = Gia_ManCo( p->pAigExtra, curCi - nRealPis + j ); // compute truth table + pTruth = NULL; if ( Gia_ObjFaninId0p(p->pAigExtra, pObjExtra) == 0 ) + { uTruth = 0; + uTruth = Gia_ObjFaninC0(pObjExtra) ? ~uTruth : uTruth; + pTruth = &uTruth; + } else if ( Gia_ObjIsCi(Gia_ObjFanin0(pObjExtra)) ) + { uTruth = uTruths6[Gia_ObjCioId(Gia_ObjFanin0(pObjExtra))]; + uTruth = Gia_ObjFaninC0(pObjExtra) ? ~uTruth : uTruth; + pTruth = &uTruth; + } else - uTruth = *Gia_ObjComputeTruthTableCut( p->pAigExtra, Gia_ObjFanin0(pObjExtra), vLeaves ); - uTruth = Gia_ObjFaninC0(pObjExtra) ? ~uTruth : uTruth; + { + pTruth = Gia_ObjComputeTruthTableCut( p->pAigExtra, Gia_ObjFanin0(pObjExtra), vLeaves ); + if ( Gia_ObjFaninC0(pObjExtra) ) + Abc_TtNot( pTruth, Abc_Truth6WordNum(Vec_IntSize(vLeaves)) ); + } + //uTruth = Gia_ObjFaninC0(pObjExtra) ? ~uTruth : uTruth; //Dau_DsdPrintFromTruth( &uTruth, Vec_IntSize(vArray) ); - nVars = Abc_Tt6MinBase( &uTruth, Vec_IntArray(vArray), Vec_IntSize(vArray) ); + //nVars = Abc_Tt6MinBase( &uTruth, Vec_IntArray(vArray), Vec_IntSize(vArray) ); + nVars = Abc_TtMinBase( pTruth, Vec_IntArray(vArray), Vec_IntSize(vArray), Vec_IntSize(vLeaves) ); Vec_IntShrink( vArray, nVars ); - Vec_WrdWriteEntry( vTruths, Counter, uTruth ); + if ( nVars <= 6 ) + Vec_WrdWriteEntry( vTruths, Counter, pTruth[0] ); + else + { + int w, nWords = Abc_Truth6WordNum( nVars ); + Vec_IntWriteEntry( vStarts, Counter, Vec_WrdSize(vTruths2) ); + for ( w = 0; w < nWords; w++ ) + Vec_WrdPush( vTruths2, pTruth[w] ); + } } } else // create buffers for black box inputs and outputs @@ -230,7 +268,7 @@ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p ) } // finalize Vec_IntFree( vLeaves ); - return Sfm_NtkConstruct( vFanins, nBbOuts + nRealPis, nRealPos + nBbIns, vFixed, vEmpty, vTruths ); + return Sfm_NtkConstruct( vFanins, nBbOuts + nRealPis, nRealPos + nBbIns, vFixed, vEmpty, vTruths, vStarts, vTruths2 ); } /**Function************************************************************* @@ -354,7 +392,8 @@ Gia_Man_t * Gia_ManInsertMfs( Gia_Man_t * p, Sfm_Ntk_t * pNtk, int fAllBoxes ) if ( Gia_ObjLutIsMux(p, Vec_IntEntry(vMfs2Old, iMfsId)) ) { int MapSize = Vec_IntSize(vMapping2); - int nVarsNew, Res = Abc_TtSimplify( pTruth, Vec_IntArray(vLeaves), Vec_IntSize(vLeaves), &nVarsNew ); + int nVarsNew; + Abc_TtSimplify( pTruth, Vec_IntArray(vLeaves), Vec_IntSize(vLeaves), &nVarsNew ); Vec_IntShrink( vLeaves, nVarsNew ); iLitNew = Gia_ManFromIfLogicCreateLut( pNew, pTruth, vLeaves, vCover, vMapping, vMapping2 ); if ( MapSize < Vec_IntSize(vMapping2) ) @@ -392,6 +431,8 @@ Gia_Man_t * Gia_ManInsertMfs( Gia_Man_t * p, Sfm_Ntk_t * pNtk, int fAllBoxes ) if ( Vec_IntFind(vMfsTopo, iGroup) >= 0 ) { iLitNew = Vec_IntEntry( vMfs2Gia, iMfsId ); + if ( iLitNew < 0 ) + continue; assert( iLitNew >= 0 ); } continue; @@ -427,6 +468,7 @@ Gia_Man_t * Gia_ManInsertMfs( Gia_Man_t * p, Sfm_Ntk_t * pNtk, int fAllBoxes ) // duplicated initial state if ( p->vRegInits ) pNew->vRegInits = Vec_IntDup( p->vRegInits ); + pNew->nAnd2Delay = p->nAnd2Delay; // cleanup Vec_WecFree( vGroups ); @@ -461,11 +503,16 @@ Gia_Man_t * Gia_ManPerformMfs( Gia_Man_t * p, Sfm_Par_t * pPars ) Abc_Print( 1, "Timing manager is given but there is no GIA of boxes.\n" ); return NULL; } + if ( p->pManTime != NULL && p->pAigExtra != NULL && Gia_ManCiNum(p->pAigExtra) > 15 ) + { + Abc_Print( 1, "Currently \"&mfs\" cannot process the network containing white-boxes with more than 15 inputs.\n" ); + return NULL; + } // count fanouts nFaninMax = Gia_ManLutSizeMax( p ); - if ( nFaninMax > 6 ) + if ( nFaninMax > 15 ) { - Abc_Print( 1, "Currently \"&mfs\" cannot process the network containing nodes with more than 6 fanins.\n" ); + Abc_Print( 1, "Currently \"&mfs\" cannot process the network containing nodes with more than 15 fanins.\n" ); return NULL; } // collect information diff --git a/abc/src/aig/gia/giaMinLut.c b/abc/src/aig/gia/giaMinLut.c new file mode 100644 index 00000000000..5304486de4b --- /dev/null +++ b/abc/src/aig/gia/giaMinLut.c @@ -0,0 +1,1058 @@ +/**CFile**************************************************************** + + FileName [giaMinLut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Collapsing AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaMinLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "giaAig.h" +#include "base/main/mainInt.h" +#include "opt/sfm/sfm.h" + +#ifdef ABC_USE_CUDD +#include "bdd/extrab/extraBdd.h" +#include "bdd/dsd/dsd.h" +#endif + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Vec_WrdReadLayerText( char * pFileName, int * pnIns, int * pnOuts ) +{ + char * pThis, pLine[1000]; + Vec_Wec_t * vRes; int iLine; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + vRes = Vec_WecAlloc(100); + for ( iLine = 0; fgets( pLine, 1000, pFile ); iLine++ ) + { + if ( iLine == 0 ) + { + pThis = strstr( pLine, "[" ); + *pnIns = atoi( pThis+1 ) + 1; + pThis = strstr( pThis+1, "[" ); + *pnOuts = atoi( pThis+1 ) + 1; + } + else + { + Vec_Int_t * vLevel = NULL; + for ( pThis = pLine; (pThis = strstr(pThis, "M0[")); pThis++ ) + { + if ( vLevel == NULL ) + vLevel = Vec_WecPushLevel( vRes ); + Vec_IntPush( vLevel, atoi( pThis+3 ) ); + } + if ( vLevel ) + Vec_IntReverseOrder( vLevel ); + } + } + fclose( pFile ); + //Vec_WecPrint( vRes, 0 ); + return vRes; +} +int Vec_WrdReadTruthTextOne( char * pFileName, int nIns, int nOuts, word * pRes ) +{ + int i, nWords = Abc_TtWordNum( nIns ); + char * pStart, * pBuffer = Extra_FileReadContents( pFileName ); + if ( pBuffer == NULL ) + { + printf( "Cannot read file \"%s\".\n", pFileName ); + return 0; + } + pStart = pBuffer; + for ( i = 0; i < nOuts; i++ ) + { + pStart = strstr( pStart + 1, "0x" ); + if ( !Extra_ReadHex( (unsigned *)(pRes + i*nWords), pStart + 2, nWords*16 ) ) + { + printf( "Cannot read truth table %d (out of %d) in file \"%s\".\n", i, nOuts, pFileName ); + ABC_FREE( pBuffer ); + return 0; + } + } + ABC_FREE( pBuffer ); + return 1; +} +word * Vec_WrdReadTruthText( char * pFileName, int nIns, int nOuts, int nFiles ) +{ + char FileName[1000]; + int i, nWords = Abc_TtWordNum( nIns ); + word * pRes = ABC_CALLOC( word, nOuts*nFiles*nWords ); + for ( i = 0; i < nFiles; i++ ) + { + assert( strlen(pFileName) < 900 ); + strcpy( FileName, pFileName ); + sprintf( FileName + strlen(FileName) - 2, "_N%d.bench", i ); + if ( !Vec_WrdReadTruthTextOne( FileName, nIns, nOuts, pRes + i*nOuts*nWords ) ) + { + ABC_FREE( pRes ); + return NULL; + } + } + return pRes; +} +Gia_Man_t * Vec_WrdReadTest( char * pFileName ) +{ + extern int Gia_ManPerformLNetOpt_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ); + extern Gia_Man_t * Gia_TryPermOptCare( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + Gia_Man_t * pPart, * pNew = NULL; Gia_Obj_t * pObj; + int i, k, nIns, nOuts, iLit; + Vec_Wec_t * vRes = Vec_WrdReadLayerText( pFileName, &nIns, &nOuts ); + int nBitsI = vRes ? Vec_WecMaxLevelSize(vRes) : 0; + int nBitsO = vRes ? nOuts / Vec_WecSize(vRes) : 0; + int nWords = Abc_TtWordNum(nBitsI); + word * pFuncs = vRes ? Vec_WrdReadTruthText( pFileName, nBitsI, nBitsO, Vec_WecSize(vRes) ) : NULL; + Vec_Int_t * vPart, * vLits = Vec_IntAlloc( nOuts ); + if ( vRes == NULL || pFuncs == NULL ) + { + Vec_WecFreeP( &vRes ); + Vec_IntFreeP( &vLits ); + ABC_FREE( pFuncs ); + return NULL; + } + assert( nOuts % Vec_WecSize(vRes) == 0 ); + pNew = Gia_ManStart( 10000 ); + pNew->pName = Abc_UtilStrsav( pFileName ); + pNew->pSpec = NULL; + for ( i = 0; i < nIns; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashStart( pNew ); + Vec_WecForEachLevel( vRes, vPart, i ) + { + assert( Vec_IntSize(vPart) <= nBitsI ); + pPart = Gia_TryPermOptCare( pFuncs + i * nBitsO * nWords, nBitsI, nBitsO, nWords, 20, 0 ); + Gia_ManFillValue( pPart ); + Gia_ManConst0(pPart)->Value = 0; + Gia_ManForEachCi( pPart, pObj, k ) + pObj->Value = Abc_Var2Lit( 1+Vec_IntEntry(vPart, k), 0 ); + Gia_ManForEachCo( pPart, pObj, k ) + { + Gia_ManPerformLNetOpt_rec( pNew, pPart, Gia_ObjFanin0(pObj) ); + Vec_IntPush( vLits, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManStop( pPart ); + } + Gia_ManHashStop( pNew ); + Vec_IntForEachEntry( vLits, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + ABC_FREE( pFuncs ); + Vec_WecFree( vRes ); + Vec_IntFree( vLits ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Vec_WrdReadText( char * pFileName, Vec_Wrd_t ** pvSimI, Vec_Wrd_t ** pvSimO, int nIns, int nOuts ) +{ + int i, nSize, iLine, nLines, nWords; + char pLine[1000]; + Vec_Wrd_t * vSimI, * vSimO; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return; + } + fseek( pFile, 0, SEEK_END ); + nSize = ftell( pFile ); + if ( nSize % (nIns + nOuts + 1) > 0 ) + { + printf( "Cannot read file with simulation data that is not aligned at 8 bytes (remainder = %d).\n", nSize % (nIns + nOuts + 1) ); + fclose( pFile ); + return; + } + rewind( pFile ); + nLines = nSize / (nIns + nOuts + 1); + nWords = (nLines + 63)/64; + vSimI = Vec_WrdStart( nIns *nWords ); + vSimO = Vec_WrdStart( nOuts*nWords ); + for ( iLine = 0; fgets( pLine, 1000, pFile ); iLine++ ) + { + for ( i = 0; i < nIns; i++ ) + if ( pLine[nIns-1-i] == '1' ) + Abc_TtXorBit( Vec_WrdArray(vSimI) + i*nWords, iLine ); + else assert( pLine[nIns-1-i] == '0' ); + for ( i = 0; i < nOuts; i++ ) + if ( pLine[nIns+nOuts-1-i] == '1' ) + Abc_TtXorBit( Vec_WrdArray(vSimO) + i*nWords, iLine ); + else assert( pLine[nIns+nOuts-1-i] == '0' ); + } + fclose( pFile ); + *pvSimI = vSimI; + *pvSimO = vSimO; + printf( "Read %d words of simulation data for %d inputs and %d outputs (padded %d zero-patterns).\n", nWords, nIns, nOuts, nWords*64-nLines ); +} +int Vec_WrdReadText2( char * pFileName, Vec_Wrd_t ** pvSimI ) +{ + int i, nSize, iLine, nLines, nWords, nIns; + char pLine[1000]; + Vec_Wrd_t * vSimI; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return 0; + } + if ( !fgets(pLine, 1000, pFile) || (nIns = strlen(pLine)-1) < 1 ) + { + printf( "Cannot find the number of inputs in file \"%s\".\n", pFileName ); + fclose( pFile ); + return 0; + } + fseek( pFile, 0, SEEK_END ); + nSize = ftell( pFile ); + if ( nSize % (nIns + 1) > 0 ) + { + printf( "Cannot read file with simulation data that is not aligned at 8 bytes (remainder = %d).\n", nSize % (nIns + 1) ); + fclose( pFile ); + return 0; + } + rewind( pFile ); + nLines = nSize / (nIns + 1); + nWords = (nLines + 63)/64; + vSimI = Vec_WrdStart( nIns *nWords ); + for ( iLine = 0; fgets( pLine, 1000, pFile ); iLine++ ) + { + for ( i = 0; i < nIns; i++ ) + if ( pLine[nIns-1-i] == '1' ) + Abc_TtXorBit( Vec_WrdArray(vSimI) + i*nWords, iLine ); + else assert( pLine[nIns-1-i] == '0' ); + } + fclose( pFile ); + *pvSimI = vSimI; + printf( "Read %d words of simulation data for %d inputs (padded to 64-bit boundary with %d zero-patterns).\n", nWords, nIns, nWords*64-nLines ); + return nIns; +} +Vec_Int_t * Vec_WrdReadNumsOut( char * pFileName, int fVerbose ) +{ + char pLine[1000]; + Vec_Int_t * vNums; int iLine; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + vNums = Vec_IntAlloc( 1000 ); + for ( iLine = 0; fgets( pLine, 1000, pFile ); iLine++ ) + Vec_IntPush( vNums, atoi(pLine) ); + fclose( pFile ); + if ( fVerbose ) + printf( "Finished reading %d output values from file \"%s\".\n", Vec_IntSize(vNums), pFileName ); + return vNums; +} +Vec_Wrd_t * Vec_WrdReadTextOut( char * pFileName, int nOuts ) +{ + int i, iLine, nLines, nWords; + Vec_Wrd_t * vSimO; + Vec_Int_t * vNums = Vec_WrdReadNumsOut( pFileName, 1 ); + if ( vNums == NULL ) + return NULL; + nLines = Vec_IntSize(vNums); + nWords = (nLines + 63)/64; + vSimO = Vec_WrdStart( nOuts*nWords ); + Vec_IntForEachEntry( vNums, i, iLine ) + Abc_TtXorBit( Vec_WrdArray(vSimO) + i*nWords, iLine ); + Vec_IntFree( vNums ); + printf( "Read %d words of simulation data for %d outputs (padded %d zero-patterns).\n", nWords, nOuts, nWords*64-nLines ); + return vSimO; +} +void Gia_ManReadSimInfoInputs( char * pFileName, char * pFileOut1, int fVerbose ) +{ + Vec_Wrd_t * vSimI; + Vec_WrdReadText2( pFileName, &vSimI ); + Vec_WrdDumpBin( pFileOut1, vSimI, fVerbose ); + Vec_WrdFree( vSimI ); +} +void Gia_ManReadSimInfoOutputs( char * pFileName, char * pFileOut, int nOuts ) +{ + Vec_Wrd_t * vSimO = Vec_WrdReadTextOut( pFileName, nOuts ); + Vec_WrdDumpBin( pFileOut, vSimO, 1 ); + Vec_WrdFree( vSimO ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Vec_WrdZoneExtract( int ZoneSize, Vec_Wrd_t * p, int iWord, int nWords ) +{ + int z, nZones = Vec_WrdSize(p)/ZoneSize; + int w, Limit = Abc_MinInt( nWords, ZoneSize-iWord ); + Vec_Wrd_t * pNew = Vec_WrdStart( nZones*nWords ); + for ( z = 0; z < nZones; z++ ) + for ( w = 0; w < Limit; w++ ) + Vec_WrdWriteEntry( pNew, z*nWords + w, Vec_WrdEntry(p, z*ZoneSize + iWord + w) ); + return pNew; +} +void Vec_WrdZoneInsert( Vec_Wrd_t * pNew, int ZoneSize, Vec_Wrd_t * p, int iWord, int nWords ) +{ + int z, nZones = Vec_WrdSize(pNew)/ZoneSize; + int w, Limit = Abc_MinInt( nWords, ZoneSize-iWord ); + for ( z = 0; z < nZones; z++ ) + for ( w = 0; w < Limit; w++ ) + Vec_WrdWriteEntry( pNew, z*ZoneSize + iWord + w, Vec_WrdEntry(p, z*nWords + w) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimInfoPrintOne( Gia_Man_t * p, Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nWords, int nPats ) +{ + int Id, i, k; + for ( k = 0; k < nPats; k++ ) + { + Gia_ManForEachCiId( p, Id, i ) + // printf( "%d", Vec_WrdEntry(p->vSims, p->nSimWords*Id) & 1 ); + printf( "%d", (int)(Vec_WrdEntry(vSimsIn, nWords*i) >> k) & 1 ); + printf( " " ); + Gia_ManForEachCoId( p, Id, i ) + // printf( "%d", Vec_WrdEntry(p->vSims, p->nSimWords*Id) & 1 ); + printf( "%d", (int)(Vec_WrdEntry(vSimsOut, nWords*i) >> k) & 1 ); + printf( "\n" ); + } +} +Vec_Wrd_t * Gia_ManSimInfoTryOne( Gia_Man_t * p, Vec_Wrd_t * vSimI, int fPrint ) +{ + extern Vec_Wrd_t * Gia_ManSimulateWordsOut( Gia_Man_t * p, Vec_Wrd_t * vSimsIn ); + Vec_Wrd_t * vSimsOut = Gia_ManSimulateWordsOut( p, vSimI ); + int nWords = Vec_WrdSize(vSimI) / Gia_ManCiNum(p); + assert( Vec_WrdSize(vSimI) % Gia_ManCiNum(p) == 0 ); + if ( fPrint ) + Gia_ManSimInfoPrintOne( p, vSimI, vSimsOut, nWords, 6 ); + return vSimsOut; +} +int Gia_ManSimEvalOne( Gia_Man_t * p, Vec_Wrd_t * vSimO, Vec_Wrd_t * vSimO_new ) +{ + int i, Count = 0, nWords = Vec_WrdSize(vSimO) / Gia_ManCoNum(p); + word * pSim0 = ABC_CALLOC( word, nWords ); + assert( Vec_WrdSize(vSimO) == Vec_WrdSize(vSimO_new) ); + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + { + word * pSimGold = Vec_WrdEntryP( vSimO, i * nWords ); + word * pSimImpl = Vec_WrdEntryP( vSimO_new, i * nWords ); + Abc_TtOrXor( pSim0, pSimImpl, pSimGold, nWords ); + } + Count = Abc_TtCountOnesVec( pSim0, nWords ); + printf( "Number of failed patterns is %d (%8.4f %% of %d). The first one is %d.\n", + Count, 100.0*Count/(64*nWords), 64*nWords, Abc_TtFindFirstBit2(pSim0, nWords) ); + ABC_FREE( pSim0 ); + return Count; +} +int Gia_ManSimEvalOne2( Gia_Man_t * p, Vec_Wrd_t * vSimO, Vec_Wrd_t * vSimO_new ) +{ + int i, Count = 0, nWords = Vec_WrdSize(vSimO) / Gia_ManCoNum(p); + word * pSim0 = ABC_CALLOC( word, nWords ); + assert( Vec_WrdSize(vSimO) == Vec_WrdSize(vSimO_new) ); + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + { + word * pSimGold = Vec_WrdEntryP( vSimO, i * nWords ); + word * pSimImpl = Vec_WrdEntryP( vSimO_new, i * nWords ); + Abc_TtXor( pSim0, pSimImpl, pSimGold, nWords, 0 ); + Count += Abc_TtCountOnesVec( pSim0, nWords ); + } + printf( "Number of failed patterns is %d (%8.4f %% of %d). The first one is %d.\n", + Count, 100.0*Count/(64*nWords*Gia_ManCoNum(p)), 64*nWords*Gia_ManCoNum(p), Abc_TtFindFirstBit2(pSim0, nWords) ); + ABC_FREE( pSim0 ); + return Count; +} +int Gia_ManSimEvalMaxValue( Vec_Wrd_t * vSimO, int nWords, int nOuts, int nBits, int iPat ) +{ + int o, ValueMax = -1, OutMax = -1; + for ( o = 0; o < nOuts; o++ ) + { + int i, Value = 0; + for ( i = 0; i < nBits; i++ ) + { + word * pSim = Vec_WrdEntryP( vSimO, (o*nBits+i) * nWords ); + if ( Abc_TtGetBit(pSim, iPat) ) + Value |= 1 << i; + } + if ( ValueMax <= Value ) + { + ValueMax = Value; + OutMax = o; + } + } + return OutMax; +} +int Gia_ManSimEvalOne3( Gia_Man_t * p, Vec_Wrd_t * vSimO, Vec_Int_t * vValues, int nBits ) +{ + int i, Value, nOuts = Gia_ManCoNum(p) / nBits; + int First = -1, Count = 0, nWords = Vec_WrdSize(vSimO) / Gia_ManCoNum(p); + assert( Gia_ManCoNum(p) % nBits == 0 ); + assert( 64*(nWords-1) < Vec_IntSize(vValues) && Vec_IntSize(vValues) <= 64*nWords ); + Vec_IntForEachEntry( vValues, Value, i ) + if ( Value == Gia_ManSimEvalMaxValue(vSimO, nWords, nOuts, nBits, i) ) + { + Count++; + if ( First == -1 ) + First = i; + } + printf( "The accuracy is %8.4f %% (%d out of %d output are correct, for example, output number %d).\n", + 100.0*Count/Vec_IntSize(vValues), Count, Vec_IntSize(vValues), First ); + if ( 0 ) + { + FILE * pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%0.2f \n", 100.0*Count/Vec_IntSize(vValues) ); + fclose( pTable ); + } + return Count; +} +Vec_Wrd_t * Gia_ManSimInfoTry( Gia_Man_t * p, Vec_Wrd_t * vSimI ) +{ + int nWords = Vec_WrdSize(vSimI) / Gia_ManCiNum(p); + int w, nWordsOne = 200, nWordBatches = (nWords + nWordsOne - 1)/nWordsOne; + Vec_Wrd_t * vSimO_new = Vec_WrdStart( nWords * Gia_ManCoNum(p) ); + for ( w = 0; w < nWordBatches; w++ ) + { + //int Value = printf( "%3d / %3d : ", w, nWordBatches ); + Vec_Wrd_t * vSimI_ = Vec_WrdZoneExtract( nWords, vSimI, w*nWordsOne, nWordsOne ); + Vec_Wrd_t * vSimO_ = Gia_ManSimInfoTryOne( p, vSimI_, 0 ); + Vec_WrdZoneInsert( vSimO_new, nWords, vSimO_, w*nWordsOne, nWordsOne ); + Vec_WrdFree( vSimI_ ); + Vec_WrdFree( vSimO_ ); + //Value = 0; + } + return vSimO_new; +} +int Gia_ManSimInfoEval_old( Gia_Man_t * p, Vec_Wrd_t * vSimO, Vec_Wrd_t * vSimO_new ) +{ + int nResult = Gia_ManSimEvalOne2(p, vSimO, vSimO_new); + //Vec_WrdDumpBin( "temp.simo", vSimO_new, 1 ); + printf( "Total errors = %d. ", nResult ); + printf( "Density of output patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSimO_new), Vec_WrdSize(vSimO_new))/(64*Vec_WrdSize(vSimO_new)) ); + return nResult; +} +void Gia_ManSimInfoPassTest( Gia_Man_t * p, char * pFileName, char * pFileName2, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Vec_Wrd_t * vSimI = Vec_WrdReadBin( pFileName, fVerbose ); + Vec_Wrd_t * vSimO = Gia_ManSimInfoTry( p, vSimI ); + if ( fVerbose ) + printf( "Density of input patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSimI), Vec_WrdSize(vSimI))/(64*Vec_WrdSize(vSimI)) ); + if ( fVerbose ) + printf( "Density of output patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSimO), Vec_WrdSize(vSimO))/(64*Vec_WrdSize(vSimO)) ); + Vec_WrdDumpBin( pFileName2, vSimO, fVerbose ); + Vec_WrdFree( vSimI ); + Vec_WrdFree( vSimO ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} +void Gia_ManSimInfoEval( Gia_Man_t * p, char * pFileName, char * pFileName2, int nOuts, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Vec_Wrd_t * vSim1 = Vec_WrdReadBin( pFileName, fVerbose ); + Vec_Int_t * vNums = Vec_WrdReadNumsOut( pFileName2, fVerbose ); + assert( nOuts > 0 ); + if ( fVerbose ) + printf( "Density of input patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSim1), Vec_WrdSize(vSim1))/(64*Vec_WrdSize(vSim1)) ); + Gia_ManSimEvalOne3( p, vSim1, vNums, nOuts ); + Vec_WrdFree( vSim1 ); + Vec_IntFree( vNums ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word * Gia_ManCountFraction( Gia_Man_t * p, Vec_Wrd_t * vSimI, Vec_Int_t * vSupp, int Thresh, int fVerbose, int * pCare ) +{ + Gia_Obj_t * pObj; + int i, k, nUsed = 0, nGood = 0; + int nWords = Vec_WrdSize(vSimI) / Gia_ManCiNum(p); + int nMints = 1 << Vec_IntSize(vSupp); + word ** pSims = ABC_ALLOC( word *, Vec_IntSize(vSupp) ); + word * pRes = ABC_CALLOC( word, Abc_Truth6WordNum(Vec_IntSize(vSupp)) ); + int * pCounts = ABC_CALLOC( int, nMints ); + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + pSims[i] = Vec_WrdEntryP( vSimI, Gia_ObjCioId(pObj) * nWords ); + for ( k = 0; k < 64*nWords; k++ ) + { + int iMint = 0; + for ( i = 0; i < Vec_IntSize(vSupp); i++ ) + if ( Abc_TtGetBit(pSims[i], k) ) + iMint |= 1 << i; + assert( iMint < nMints ); + pCounts[iMint]++; + } + for ( k = 0; k < nMints; k++ ) + { + nUsed += (pCounts[k] > 0); + nGood += (pCounts[k] >= Thresh); + if ( pCounts[k] >= Thresh ) + Abc_TtXorBit( pRes, k ); + //printf( "%d ", pCounts[k] ); + } + if ( Vec_IntSize(vSupp) < 6 ) + pRes[0] = Abc_Tt6Stretch( pRes[0], Vec_IntSize(vSupp) ); + //printf( "\n" ); + if ( fVerbose ) + printf( "Used %4d and good %4d (out of %4d).\n", nUsed, nGood, nMints ); + ABC_FREE( pSims ); + ABC_FREE( pCounts ); + *pCare = nGood; + return pRes; +} +void Gia_ManPermuteSupp_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vLevels, Vec_Int_t * vCounts ) +{ + Gia_Obj_t * pObj; int n; + if ( !iObj || Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManPermuteSupp_rec( p, Gia_ObjFaninId0(pObj, iObj), vLevels, vCounts ); + Gia_ManPermuteSupp_rec( p, Gia_ObjFaninId1(pObj, iObj), vLevels, vCounts ); + for ( n = 0; n < 2; n++ ) + { + Gia_Obj_t * pFanin = n ? Gia_ObjFanin1(pObj) : Gia_ObjFanin0(pObj); + if ( !Gia_ObjIsCi(pFanin) ) + continue; + Vec_IntAddToEntry( vLevels, Gia_ObjCioId(pFanin), Gia_ObjLevel(p, pObj) ); + Vec_IntAddToEntry( vCounts, Gia_ObjCioId(pFanin), 1 ); + } +} +void Gia_ManPermuteSupp( Gia_Man_t * p, int iOut, int nOuts, Vec_Int_t * vSupp ) +{ + Vec_Int_t * vLevels = Vec_IntStart( Gia_ManCiNum(p) ); + Vec_Int_t * vCounts = Vec_IntStart( Gia_ManCiNum(p) ); + int i, * pCost = ABC_CALLOC( int, Gia_ManCiNum(p) ); + Gia_Obj_t * pObj; + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManPermuteSupp_rec( p, Gia_ObjFaninId0p(p, Gia_ManCo(p, iOut+i)), vLevels, vCounts ); + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + pCost[i] = 10000 * Vec_IntEntry(vLevels, Gia_ObjCioId(pObj)) / Abc_MaxInt(1, Vec_IntEntry(vCounts, Gia_ObjCioId(pObj))); + Vec_IntFree( vCounts ); + Vec_IntFree( vLevels ); + Vec_IntSelectSortCost2( Vec_IntArray(vSupp), Vec_IntSize(vSupp), pCost ); + assert( Vec_IntSize(vSupp) < 2 || pCost[0] <= pCost[1] ); + ABC_FREE( pCost ); +} +void Gia_ManCollectSupp_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vSupp ) +{ + Gia_Obj_t * pObj; + if ( !iObj || Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + { + //Vec_IntPush( vSupp, Gia_ObjCioId(pObj) ); + Vec_IntPush( vSupp, Gia_ObjId(p, pObj) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManCollectSupp_rec( p, Gia_ObjFaninId0(pObj, iObj), vSupp ); + Gia_ManCollectSupp_rec( p, Gia_ObjFaninId1(pObj, iObj), vSupp ); +} +Vec_Int_t * Gia_ManCollectSupp( Gia_Man_t * p, int iOut, int nOuts ) +{ + Vec_Int_t * vSupp = Vec_IntAlloc( 16 ); int i; + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManCollectSupp_rec( p, Gia_ObjFaninId0p(p, Gia_ManCo(p, iOut+i)), vSupp ); + return vSupp; +} +Vec_Int_t * Gia_ManCollectSuppNew( Gia_Man_t * p, int iOut, int nOuts ) +{ + Vec_Int_t * vRes = Gia_ManCollectSupp( p, iOut, nOuts ); + Gia_ManPermuteSupp( p, iOut, nOuts, vRes ); + return vRes; +} +int Gia_ManPerformLNetOpt_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManPerformLNetOpt_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManPerformLNetOpt_rec( pNew, p, Gia_ObjFanin1(pObj) ); + return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManPerformLNetOpt( Gia_Man_t * p, int fTryNew, char * pFileName, int nIns, int nOuts, int Thresh, int nRounds, int fVerbose ) +{ + extern Gia_Man_t * Gia_TryPermOpt( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + extern Gia_Man_t * Gia_TryPermOptCare( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + extern int Kit_TruthToGia2( Gia_Man_t * p, unsigned * pTruth0, unsigned * pTruth1, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); + abctime clk = Abc_Clock(); + Gia_Man_t * pNew; Gia_Obj_t * pObj; + Vec_Int_t * vMemory = Vec_IntAlloc( 1 << 18 ); + Vec_Int_t * vLeaves = Vec_IntAlloc( nIns ); + Vec_Wrd_t * vSimI = pFileName ? Vec_WrdReadBin( pFileName, fVerbose ) : NULL; + word * pTruth0 = ABC_CALLOC( word, Abc_Truth6WordNum(nIns) ); + word * pTruth1 = ABC_CALLOC( word, Abc_Truth6WordNum(nIns) ); int g, k; float CareAve = 0; + word * pTruthsTry = ABC_CALLOC( word, 2*nOuts*Abc_Truth6WordNum(nIns) ); + if ( vSimI && fVerbose ) + { + //int nPats = 64*Vec_WrdSize(vSimI)/Gia_ManCiNum(p); + printf( "Density of input patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSimI), Vec_WrdSize(vSimI))/(64*Vec_WrdSize(vSimI)) ); + printf( "Using patterns with count %d and higher as cares.\n", Thresh ); + } + Gia_ManLevelNum( p ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, k ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ObjComputeTruthTableStart( p, nIns ); + Gia_ManHashStart( pNew ); + for ( g = 0; g < Gia_ManCoNum(p); g += nOuts ) + { + Vec_Int_t * vSupp = Gia_ManCollectSuppNew( p, g, nOuts ); + int Care = 1 << Vec_IntSize(vSupp), Temp = fVerbose ? printf( "Group %3d / %3d / %3d : Supp = %3d %s", g, nOuts, Gia_ManCoNum(p), Vec_IntSize(vSupp), vSimI ? "":"\n" ) : 0; + word * pCare = vSimI ? Gia_ManCountFraction( p, vSimI, vSupp, Thresh, fVerbose, &Care ) : ABC_FALLOC( word, Abc_Truth6WordNum(Vec_IntSize(vSupp)) ); + int nWords = Abc_Truth6WordNum( Vec_IntSize(vSupp) ); + CareAve += 100.0*Care/(1 << Vec_IntSize(vSupp)); + assert( Vec_IntSize(vSupp) <= nIns ); + Vec_IntClear( vLeaves ); + Gia_ManForEachObjVec( vSupp, p, pObj, k ) + Vec_IntPush( vLeaves, pObj->Value ); + for ( k = 0; k < nOuts; k++ ) + { + Gia_Obj_t * pObj = Gia_ManCo( p, g+k ); + word * pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); + Abc_TtSharp( pTruth0, pCare, pTruth, nWords ); + Abc_TtAnd( pTruth1, pCare, pTruth, nWords, 0 ); + if ( vSimI ) + { + Abc_TtCopy( pTruthsTry + (2*k+0)*nWords, pTruth1, nWords, 0 ); + Abc_TtCopy( pTruthsTry + (2*k+1)*nWords, pTruth0, nWords, 0 ); + } + else + Abc_TtCopy( pTruthsTry + k*nWords, pTruth1, nWords, 0 ); + if ( !fTryNew ) + { + pObj->Value = Kit_TruthToGia2( pNew, (unsigned *)pTruth0, (unsigned *)pTruth1, Vec_IntSize(vLeaves), vMemory, vLeaves, 1 ); + pObj->Value ^= Gia_ObjFaninC0(pObj); + } + } + if ( fTryNew ) + { + Gia_Man_t * pMin; + if ( vSimI ) + pMin = Gia_TryPermOpt( pTruthsTry, Vec_IntSize(vSupp), 2*nOuts, nWords, nRounds, fVerbose ); + else + pMin = Gia_TryPermOptCare( pTruthsTry, Vec_IntSize(vSupp), nOuts, nWords, nRounds, fVerbose ); + Gia_ManFillValue( pMin ); + Gia_ManConst0(pMin)->Value = 0; + Gia_ManForEachCi( pMin, pObj, k ) + pObj->Value = Vec_IntEntry( vLeaves, k ); + for ( k = 0; k < nOuts; k++ ) + { + Gia_Obj_t * pObj = Gia_ManCo( p, g+k ); + Gia_Obj_t * pObj2 = Gia_ManCo( pMin, k ); + pObj->Value = Gia_ManPerformLNetOpt_rec( pNew, pMin, Gia_ObjFanin0(pObj2) ); + pObj->Value ^= Gia_ObjFaninC0(pObj2); + pObj->Value ^= Gia_ObjFaninC0(pObj); + } + Gia_ManStop( pMin ); + } + ABC_FREE( pCare ); + Vec_IntFree( vSupp ); + Temp = 0; + } + CareAve /= Gia_ManCoNum(p)/nOuts; + Gia_ManHashStop( pNew ); + Gia_ManForEachCo( p, pObj, k ) + pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ObjComputeTruthTableStop( p ); + ABC_FREE( pTruth0 ); + ABC_FREE( pTruth1 ); + Vec_IntFree( vLeaves ); + Vec_IntFree( vMemory ); + Vec_WrdFreeP( &vSimI ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + printf( "Using patterns with count %d and higher as cares. Average care set is %8.4f %%. ", Thresh, CareAve ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( 0 ) + { + FILE * pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%0.2f ", CareAve ); + fclose( pTable ); + } + ABC_FREE( pTruthsTry ); + return pNew; +} +Gia_Man_t * Gia_ManPerformLNetOptNew( Gia_Man_t * p, char * pFileName, int nIns, int nOuts, int Thresh, int nRounds, int fVerbose ) +{ + extern Gia_Man_t * Gia_TryPermOptNew( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + abctime clk = Abc_Clock(); + Gia_Man_t * pNew, * pMin; Gia_Obj_t * pObj; + Vec_Int_t * vLeaves = Vec_IntAlloc( nIns ); + Vec_Wrd_t * vSimI = pFileName ? Vec_WrdReadBin( pFileName, fVerbose ) : NULL; + word * pTruthsTry = ABC_CALLOC( word, (nOuts+1)*Abc_Truth6WordNum(nIns) ); + int k, g; float CareAve = 0; + if ( vSimI && fVerbose ) + { + //int nPats = 64*Vec_WrdSize(vSimI)/Gia_ManCiNum(p); + printf( "Density of input patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSimI), Vec_WrdSize(vSimI))/(64*Vec_WrdSize(vSimI)) ); + printf( "Using patterns with count %d and higher as cares.\n", Thresh ); + } + Gia_ManLevelNum( p ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, k ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ObjComputeTruthTableStart( p, nIns ); + Gia_ManHashStart( pNew ); + for ( g = 0; g < Gia_ManCoNum(p); g += nOuts ) + { + for ( k = 0; k < nOuts; k++ ) + if ( Gia_ObjIsAnd(Gia_ObjFanin0(Gia_ManCo( p, g+k ))) ) + break; + if ( k == nOuts ) + { + for ( k = 0; k < nOuts; k++ ) + { + Gia_Obj_t * pObj = Gia_ManCo( p, g+k ); + pObj->Value = Gia_ObjFanin0Copy(pObj); + } + continue; + } + else + { + + Vec_Int_t * vSupp = Gia_ManCollectSuppNew( p, g, nOuts ); + int Care = 1 << Vec_IntSize(vSupp), Temp = fVerbose ? printf( "Group %3d / %3d / %3d : Supp = %3d %s", g, nOuts, Gia_ManCoNum(p), Vec_IntSize(vSupp), vSimI ? "":"\n" ) : 0; + word * pCare = vSimI ? Gia_ManCountFraction( p, vSimI, vSupp, Thresh, fVerbose, &Care ) : ABC_FALLOC( word, Abc_Truth6WordNum(Vec_IntSize(vSupp)) ); + int nWords = Abc_Truth6WordNum( Vec_IntSize(vSupp) ); + CareAve += 100.0*Care/(1 << Vec_IntSize(vSupp)); + assert( Vec_IntSize(vSupp) <= nIns ); + Vec_IntClear( vLeaves ); + Gia_ManForEachObjVec( vSupp, p, pObj, k ) + Vec_IntPush( vLeaves, pObj->Value ); + for ( k = 0; k < nOuts; k++ ) + { + Gia_Obj_t * pObj = Gia_ManCo( p, g+k ); + word * pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); + Abc_TtCopy( pTruthsTry + k*nWords, pTruth, nWords, Gia_ObjFaninC0(pObj) ); + } + Abc_TtCopy( pTruthsTry + nOuts*nWords, pCare, nWords, 0 ); + ABC_FREE( pCare ); + pMin = Gia_TryPermOptNew( pTruthsTry, Vec_IntSize(vSupp), nOuts, nWords, nRounds, fVerbose ); + Gia_ManFillValue( pMin ); + Gia_ManConst0(pMin)->Value = 0; + Gia_ManForEachCi( pMin, pObj, k ) + pObj->Value = Vec_IntEntry( vLeaves, k ); + Gia_ManForEachCo( pMin, pObj, k ) + { + Gia_Obj_t * pObj0 = Gia_ManCo( p, g+k ); + pObj0->Value = Gia_ManPerformLNetOpt_rec( pNew, pMin, Gia_ObjFanin0(pObj) ); + pObj0->Value ^= Gia_ObjFaninC0(pObj); + } + Gia_ManStop( pMin ); + Vec_IntFree( vSupp ); + Temp = 0; + + } + } + CareAve /= Gia_ManCoNum(p)/nOuts; + Gia_ManHashStop( pNew ); + Gia_ManForEachCo( p, pObj, k ) + pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ObjComputeTruthTableStop( p ); + Vec_IntFree( vLeaves ); + Vec_WrdFreeP( &vSimI ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + printf( "Using patterns with count %d and higher as cares. Average care set is %8.4f %%. ", Thresh, CareAve ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( 0 ) + { + FILE * pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%0.2f ", CareAve ); + fclose( pTable ); + } + ABC_FREE( pTruthsTry ); + return pNew; +} + +#ifdef ABC_USE_CUDD + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDoMuxMapping( Gia_Man_t * p ) +{ + extern Gia_Man_t * Gia_ManPerformMfs( Gia_Man_t * p, Sfm_Par_t * pPars ); + Gia_Man_t * pTemp, * pNew = Gia_ManDup( p ); + Jf_Par_t Pars, * pPars = &Pars; int c, nIters = 2; + Sfm_Par_t Pars2, * pPars2 = &Pars2; + Lf_ManSetDefaultPars( pPars ); + Sfm_ParSetDefault( pPars2 ); + pPars2->nTfoLevMax = 5; + pPars2->nDepthMax = 100; + pPars2->nWinSizeMax = 2000; + for ( c = 0; c < nIters; c++ ) + { + pNew = Lf_ManPerformMapping( pTemp = pNew, pPars ); + Gia_ManStop( pTemp ); + pNew = Gia_ManPerformMfs( pTemp = pNew, pPars2 ); + Gia_ManStop( pTemp ); + if ( c == nIters-1 ) + break; + pNew = (Gia_Man_t *)Dsm_ManDeriveGia( pTemp = pNew, 0 ); + Gia_ManStop( pTemp ); + } + return pNew; +} +Gia_Man_t * Gia_ManDoMuxTransform( Gia_Man_t * p, int fReorder ) +{ + extern Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk ); + extern int Abc_NtkBddToMuxesPerformGlo( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int Limit, int fReorder, int fUseAdd ); + Gia_Man_t * pRes = NULL; + Aig_Man_t * pMan = Gia_ManToAig( p, 0 ); + Abc_Ntk_t * pNtk = Abc_NtkFromAigPhase( pMan ); + Abc_Ntk_t * pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + pNtk->pName = Extra_UtilStrsav( pMan->pName ); + Aig_ManStop( pMan ); + //pNtkNew = Abc_NtkBddToMuxes( pNtk, 1, 1000000, 1 ); + if ( Abc_NtkBddToMuxesPerformGlo( pNtk, pNtkNew, 1000000, fReorder, 0 ) ) + { + Abc_Ntk_t * pStrash = Abc_NtkStrash( pNtkNew, 1, 1, 0 ); + pRes = Abc_NtkStrashToGia( pStrash ); + Abc_NtkDelete( pStrash ); + } + Abc_NtkDelete( pNtkNew ); + Abc_NtkDelete( pNtk ); + return pRes; +} +int Gia_ManDoTest1( Gia_Man_t * p, int fReorder ) +{ + Gia_Man_t * pTemp, * pNew; int Res; + pNew = Gia_ManDoMuxTransform( p, fReorder ); + pNew = Gia_ManDoMuxMapping( pTemp = pNew ); + Gia_ManStop( pTemp ); + Res = Gia_ManLutNum( pNew ); + Gia_ManStop( pNew ); + return Res; +} +Abc_Ntk_t * Gia_ManDoTest2( Gia_Man_t * p, int fReorder, int fTryNew ) +{ + extern Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p, int fFindEnables, int fUseBuffs ); + Abc_Ntk_t * pNtkNew; + Gia_Man_t * pTemp, * pNew; + pNew = fTryNew ? Gia_ManDup(p) : Gia_ManDoMuxTransform( p, fReorder ); + pNew = Gia_ManDoMuxMapping( pTemp = pNew ); + Gia_ManStop( pTemp ); + pNtkNew = Abc_NtkFromMappedGia( pNew, 0, 0 ); + pNtkNew->pName = Extra_UtilStrsav(p->pName); + Gia_ManStop( pNew ); + Abc_NtkToSop( pNtkNew, 1, ABC_INFINITY ); + return pNtkNew; +} +Abc_Ntk_t * Abc_NtkMapTransform( Gia_Man_t * p, int nOuts, int fUseFixed, int fTryNew, int fVerbose ) +{ + extern Abc_Ntk_t * Abc_NtkSpecialMapping( Abc_Ntk_t * pNtk, int fVerbose ); + int i, k, g, nGroups = Gia_ManCoNum(p) / nOuts, CountsAll[3] = {0}; + Abc_Obj_t * pObjNew, * pFaninNew; Gia_Obj_t * pObj; + Abc_Ntk_t * pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + assert( Gia_ManCoNum(p) % nOuts == 0 ); + pNtkNew->pName = Extra_UtilStrsav(p->pName); + pNtkNew->pSpec = Extra_UtilStrsav(p->pSpec); + Gia_ManFillValue( p ); + Gia_ManForEachPi( p, pObj, i ) + Abc_NtkCreatePi( pNtkNew ); + Gia_ManForEachPo( p, pObj, i ) + Abc_NtkCreatePo( pNtkNew ); + assert( nOuts <= 64 ); + for ( g = 0; g < nGroups; g++ ) + { + Gia_Man_t * pNew; Aig_Man_t * pMan; + Abc_Ntk_t * pNtk, * pNtkRes, * pNtkMap; + int pPos[64], Counter = 0, Counts[3] = {0}; + for ( i = 0; i < nOuts; i++ ) + pPos[i] = g*nOuts+i; + pNew = Gia_ManDupCones( p, pPos, nOuts, 1 ); + if ( !fUseFixed ) + pNtkMap = Gia_ManDoTest2( pNew, 1, fTryNew ); + else + { + pMan = Gia_ManToAig( pNew, 0 ); + pNtk = Abc_NtkFromAigPhase( pMan ); + Aig_ManStop( pMan ); + pNtkRes = Abc_NtkBddToMuxes( pNtk, 1, 1000000, 1 ); + Abc_NtkDelete( pNtk ); + pNtkMap = Abc_NtkSpecialMapping( pNtkRes, 0 ); + Abc_NtkDelete( pNtkRes ); + } + Gia_ManStop( pNew ); + Gia_ManForEachCi( p, pObj, i ) + if ( ~pObj->Value ) + Abc_NtkCi(pNtkMap, Counter++)->pCopy = Abc_NtkCi(pNtkNew, i); + assert( Counter == Abc_NtkCiNum(pNtkMap) ); + Abc_NtkForEachNode( pNtkMap, pObjNew, i ) + { + pObjNew->pCopy = Abc_NtkDupObj( pNtkNew, pObjNew, 0 ); + pObjNew->pCopy->fPersist = pObjNew->fPersist; + if ( pObjNew->fPersist ) + Counts[1]++; + else + Counts[0]++; + Abc_ObjForEachFanin( pObjNew, pFaninNew, k ) + Abc_ObjAddFanin( pObjNew->pCopy, pFaninNew->pCopy ); + } + Abc_NtkForEachCo( pNtkMap, pObjNew, i ) + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, g*nOuts+i), Abc_ObjFanin0(pObjNew)->pCopy ); + Abc_NtkDelete( pNtkMap ); + + if ( fVerbose ) + { + printf( "%3d / %3d : ", g, nGroups ); + printf( "Test = %4d ", Counts[0] ); + printf( "MarkA = %4d ", Counts[1] ); + printf( "MarkB = %4d ", Counts[2] ); + printf( "\n" ); + } + + CountsAll[0] += Counts[0]; + CountsAll[1] += Counts[1]; + CountsAll[2] += Counts[2]; + } + if ( fVerbose ) + printf( "Total LUT count = %5d. MarkA = %5d. MarkB = %5d.\n", CountsAll[0], CountsAll[1], CountsAll[2] ); + // create names + Abc_NtkAddDummyPiNames( pNtkNew ); + Abc_NtkAddDummyPoNames( pNtkNew ); + Abc_NtkAddDummyBoxNames( pNtkNew ); + // check the resulting AIG + if ( !Abc_NtkCheck( pNtkNew ) ) + Abc_Print( 1, "Abc_NtkFromMappedGia(): Network check has failed.\n" ); + return pNtkNew; +} + +Abc_Ntk_t * Gia_ManPerformLNetMap( Gia_Man_t * p, int GroupSize, int fUseFixed, int fTryNew, int fVerbose ) +{ + int fPrintOnly = 0; + int Res1, Res2, Result = 0; + int g, nGroups = Gia_ManCoNum(p) / GroupSize; + assert( Gia_ManCoNum(p) % GroupSize == 0 ); + assert( GroupSize <= 64 ); + if ( fPrintOnly ) + { + for ( g = 0; g < nGroups; g++ ) + { + Gia_Man_t * pNew; + int o, pPos[64]; + for ( o = 0; o < GroupSize; o++ ) + pPos[o] = g*GroupSize+o; + pNew = Gia_ManDupCones( p, pPos, GroupSize, 0 ); + printf( "%3d / %3d : ", g, nGroups ); + printf( "Test1 = %4d ", Res1 = Gia_ManDoTest1(pNew, 0) ); + printf( "Test2 = %4d ", Res2 = Gia_ManDoTest1(pNew, 1) ); + printf( "Test = %4d ", Abc_MinInt(Res1, Res2) ); + printf( "\n" ); + Result += Abc_MinInt(Res1, Res2); + //Gia_ManPrintStats( pNew, NULL ); + Gia_ManStop( pNew ); + } + printf( "Total LUT count = %d.\n", Result ); + return NULL; + + } + return Abc_NtkMapTransform( p, GroupSize, fUseFixed, fTryNew, fVerbose ); +} + +#else + +Abc_Ntk_t * Gia_ManPerformLNetMap( Gia_Man_t * p, int GroupSize, int fUseFixed, int fTryNew, int fVerbose ) +{ + return NULL; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaMinLut2.c b/abc/src/aig/gia/giaMinLut2.c new file mode 100644 index 00000000000..85cae0d2772 --- /dev/null +++ b/abc/src/aig/gia/giaMinLut2.c @@ -0,0 +1,1372 @@ +/**CFile**************************************************************** + + FileName [giaMinLut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Collapsing AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaMinLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "giaAig.h" +#include "base/main/mainInt.h" +#include "opt/sfm/sfm.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define TREE_MAX_VARS 16 + +typedef struct Tree_Sto_t_ Tree_Sto_t; +struct Tree_Sto_t_ +{ + int nIns; + int nOuts; + int pTried[TREE_MAX_VARS]; + int pPerm[TREE_MAX_VARS]; + int pIPerm[TREE_MAX_VARS]; + int nNodes[TREE_MAX_VARS]; + Vec_Int_t vCofs[TREE_MAX_VARS]; + word * pMem; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Tree_Sto_t * Gia_ManTreeDup( Tree_Sto_t * p ) +{ + Tree_Sto_t * pSto = ABC_CALLOC( Tree_Sto_t, 1 ); + int i, k, Obj; + *pSto = *p; + pSto->pMem = Abc_TtDup( pSto->pMem, p->nOuts*Abc_TtWordNum(p->nIns), 0 ); + memset( pSto->vCofs, 0, sizeof(Vec_Int_t)*TREE_MAX_VARS ); + for ( i = 0; i < TREE_MAX_VARS; i++ ) + Vec_IntForEachEntry( p->vCofs+i, Obj, k ) + Vec_IntPush( pSto->vCofs+i, Obj ); + return pSto; +} +void Gia_ManTreeFree( Tree_Sto_t * p ) +{ + int i; + for ( i = 0; i < TREE_MAX_VARS; i++ ) + ABC_FREE( p->vCofs[i].pArray ); + ABC_FREE( p->pMem ); + ABC_FREE( p ); +} +int Gia_ManTreeCountNodes( Tree_Sto_t * p ) +{ + int i, nNodes = 0; + for ( i = 0; i < TREE_MAX_VARS; i++ ) + nNodes += p->nNodes[i]; + return nNodes; +} +void Gia_ManTreePrint( Tree_Sto_t * p ) +{ + int i; + printf( "Tree with %d nodes:\n", Gia_ManTreeCountNodes(p) ); + for ( i = p->nIns-1; i >= 0; i-- ) + printf( "Level %2d Var %2d : %s Nodes = %3d Cofs = %3d\n", + i, p->pIPerm[i], p->pTried[i]?"*":" ", p->nNodes[i], Vec_IntSize(p->vCofs+i) ); +// for ( i = p->nIns-1; i >= 0; i-- ) +// printf( "Var %2d Level %2d\n", i, p->pPerm[i] ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFindOrAddNode( Tree_Sto_t * pSto, int iVar, int Truth, word * pCof ) +{ + int k, Obj; + if ( iVar > 5 ) + { + int nWords = Abc_TtWordNum(iVar); + Vec_IntForEachEntry( pSto->vCofs+iVar, Obj, k ) + if ( Abc_TtEqual( pSto->pMem + Obj, pCof, nWords ) ) + return 1; + Vec_IntPush( pSto->vCofs+iVar, pCof - pSto->pMem ); + } + else + { + Vec_IntForEachEntry( pSto->vCofs+iVar, Obj, k ) + if ( Obj == Truth ) + return 1; + Vec_IntPush( pSto->vCofs+iVar, Truth ); + } + return 0; +} +int Gia_ManProcessLevel( Tree_Sto_t * pSto, int iVar ) +{ + int k, Obj, nNodes = 0; + //Vec_IntPrint( pSto->vCofs+iVar ); + Vec_IntClear( pSto->vCofs+iVar ); + if ( iVar > 5 ) + { + int nWords = Abc_TtWordNum(iVar); + Vec_IntForEachEntry( pSto->vCofs+iVar+1, Obj, k ) + { + word * pCof0 = pSto->pMem + Obj; + word * pCof1 = pCof0 + nWords; + Gia_ManFindOrAddNode( pSto, iVar, -1, pCof0 ); + if ( Abc_TtEqual( pCof0, pCof1, nWords ) ) + continue; + Gia_ManFindOrAddNode( pSto, iVar, -1, pCof1 ); + nNodes++; + } + } + else + { + Vec_IntForEachEntry( pSto->vCofs+iVar+1, Obj, k ) + { + unsigned Cof0 = iVar < 5 ? Abc_Tt5Cofactor0( Obj, iVar ) : (unsigned) pSto->pMem[Obj]; + unsigned Cof1 = iVar < 5 ? Abc_Tt5Cofactor1( Obj, iVar ) : (unsigned)(pSto->pMem[Obj] >> 32); + Gia_ManFindOrAddNode( pSto, iVar, Cof0, NULL ); + if ( Cof0 == Cof1 ) + continue; + Gia_ManFindOrAddNode( pSto, iVar, Cof1, NULL ); + nNodes++; + } + } + //printf( "Level %2d : Nodes = %3d Cofs = %3d\n", iVar, nNodes, Vec_IntSize(pSto->vCofs+iVar) ); + //Vec_IntPrint( pSto->vCofs+iVar ); + //printf( "\n" ); + return nNodes; +} +Tree_Sto_t * Gia_ManContructTree( word * pTruths, int nIns, int nOuts, int nWords ) +{ + Tree_Sto_t * pSto = ABC_CALLOC( Tree_Sto_t, 1 ); int i; + assert( Abc_TtWordNum(nIns) == nWords ); + assert( nIns+1 <= TREE_MAX_VARS ); + pSto->pMem = Abc_TtDup(pTruths, nOuts*nWords, 0); + pSto->nIns = nIns; + pSto->nOuts = nOuts; + for ( i = 0; i < nIns; i++ ) + pSto->pPerm[i] = pSto->pIPerm[i] = i; + for ( i = 0; i < nOuts; i++ ) + Gia_ManFindOrAddNode( pSto, nIns, (unsigned)pSto->pMem[i], pSto->pMem + i*nWords ); + for ( i = nIns-1; i >= 0; i-- ) + pSto->nNodes[i] = Gia_ManProcessLevel( pSto, i ); + return pSto; +} +void Gia_ManContructTreeTest( word * pTruths, int nIns, int nOuts, int nWords ) +{ + Tree_Sto_t * pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + printf( "Total nodes = %d.\n", Gia_ManTreeCountNodes(pSto) ); + Gia_ManTreeFree( pSto ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSwapTree( Tree_Sto_t * pSto, int i ) +{ + int nNodes = pSto->nNodes[i+1] + pSto->nNodes[i]; + int v, o, nWords = Abc_TtWordNum(pSto->nIns); + //printf( "Swapping %2d and %2d ", i, i+1 ); + assert( i >= 0 && i < pSto->nIns-1 ); + for ( o = 0; o < pSto->nOuts; o++ ) + Abc_TtSwapAdjacent( pSto->pMem + o*nWords, nWords, i ); + for ( v = 5; v > i+1; v-- ) + pSto->nNodes[v] = Gia_ManProcessLevel( pSto, v ); + pSto->nNodes[i+1] = Gia_ManProcessLevel( pSto, i+1 ); + pSto->nNodes[i] = Gia_ManProcessLevel( pSto, i ); + ABC_SWAP( int, pSto->pTried[i], pSto->pTried[i+1] ); + ABC_SWAP( int, pSto->pIPerm[i], pSto->pIPerm[i+1] ); + pSto->pPerm[pSto->pIPerm[i+1]] = i+1; + pSto->pPerm[pSto->pIPerm[i]] = i; + return pSto->nNodes[i+1] + pSto->nNodes[i] - nNodes; +} +int Gia_ManFindBestPosition( word * pTruths, int nIns, int nOuts, int nWords, word * pStore, int fMoveMore, int * pnNodesMin, int fVerbose ) +{ + Tree_Sto_t * pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + //int v, vBest = nIns-1, nNodesCur = Gia_ManTreeCountNodes(pSto), nNodesMin = nNodesCur; + int v, vBest = -1, nNodesCur = Gia_ManTreeCountNodes(pSto), nNodesMin = ABC_INFINITY; + if ( fVerbose ) + Gia_ManTreePrint( pSto ); + Abc_TtCopy( pStore+(nIns-1)*nOuts*nWords, pSto->pMem, nOuts*nWords, 0 ); + for ( v = nIns-2; v >= 0; v-- ) + { + nNodesCur += Gia_ManSwapTree( pSto, v ); + if ( fMoveMore ? nNodesMin >= nNodesCur : nNodesMin > nNodesCur ) + { + nNodesMin = nNodesCur; + vBest = v; + } + if ( fVerbose ) + printf( "Level %2d -> %2d : Nodes = %4d. ", v+1, v, nNodesCur ); + Abc_TtCopy( pStore+v*nOuts*nWords, pSto->pMem, nOuts*nWords, 0 ); + if ( fVerbose ) + Gia_ManContructTreeTest( pSto->pMem, nIns, nOuts, nWords ); + } + assert( vBest != nIns-1 ); + Gia_ManTreeFree( pSto ); + if ( fVerbose ) + printf( "Best level = %d. Best nodes = %d.\n", vBest, nNodesMin ); + if ( pnNodesMin ) + *pnNodesMin = nNodesMin; + return vBest; +} +void Gia_ManPermStats( int nIns, int * pIPerm, int * pTried ) +{ + int v; + for ( v = nIns-1; v >= 0; v-- ) + printf( "Level = %2d : Var = %2d Tried = %2d\n", v, pIPerm[v], pTried[v] ); + printf( "\n" ); +} +int Gia_ManPermuteTreeOne( word * pTruths, int nIns, int nOuts, int nWords, int fRandom, int * pIPermOut, int fVeryVerbose, int fVerbose ) +{ + extern void Gia_ManDumpMuxes( Tree_Sto_t * p, char * pFileName, int * pIPerm ); + word * pStore = ABC_ALLOC( word, nIns*nOuts*nWords ); + int pTried[TREE_MAX_VARS] = {0}; + int pIPerm[TREE_MAX_VARS] = {0}; + int v, r, Pos, nNodesPrev = -1, nNodesMin = 0, nNoChange = 0; + int nNodesBeg, nNodesEnd; + Tree_Sto_t * pSto; + for ( v = 0; v < nIns; v++ ) + pIPerm[v] = v; + pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + nNodesBeg = Gia_ManTreeCountNodes(pSto); + //Gia_ManDumpMuxes( pSto, "from_tt1.aig", pIPerm ); + Gia_ManTreeFree( pSto ); + if ( fRandom ) + for ( v = 0; v < nIns; v++ ) + { + //int o, vRand = rand() % nIns; + int o, vRand = Gia_ManRandom(0) % nIns; + for ( o = 0; o < nOuts; o++ ) + Abc_TtSwapVars( pTruths + o*nWords, nIns, v, vRand ); + ABC_SWAP( int, pIPerm[vRand], pIPerm[v] ); + } + for ( r = 0; r < 10*nIns; r++ ) + { + nNodesPrev = nNodesMin; + if ( fVeryVerbose ) + printf( "\nRound %d:\n", r ); + Pos = Gia_ManFindBestPosition( pTruths, nIns, nOuts, nWords, pStore, r&1, &nNodesMin, fVeryVerbose ); + Abc_TtCopy( pTruths, pStore+Pos*nOuts*nWords, nOuts*nWords, 0 ); + pTried[nIns-1]++; + for ( v = nIns-2; v >= Pos; v-- ) + { + ABC_SWAP( int, pTried[v+1], pTried[v] ); + ABC_SWAP( int, pIPerm[v+1], pIPerm[v] ); + } + if ( fVeryVerbose ) + Gia_ManPermStats( nIns, pIPerm, pTried ); + nNoChange = nNodesPrev == nNodesMin ? nNoChange + 1 : 0; + if ( nNoChange == 4 ) + break; + } + pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + nNodesEnd = Gia_ManTreeCountNodes(pSto); + //Gia_ManDumpMuxes( pSto, "from_tt2.aig", pIPerm ); + if ( fVerbose ) + printf( "Nodes %5d -> %5d. ", nNodesBeg, nNodesEnd ); + Gia_ManTreeFree( pSto ); + ABC_FREE( pStore ); + if ( pIPermOut ) + memcpy( pIPermOut, pIPerm, sizeof(int)*nIns ); + return nNodesEnd; +} +void Gia_ManPermuteTree( word * pTruths, int nIns, int nOuts, int nWords, int fRandom, int fVerbose ) +{ + abctime clk = Abc_Clock(); + word * pTruthDup = Abc_TtDup( pTruths, nOuts*nWords, 0 ); + int r; + //srand( time(NULL) ); + Gia_ManRandom(1); + for ( r = 0; r < 100; r++ ) + { + Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, fRandom, NULL, 0, fVerbose ); + Abc_TtCopy( pTruthDup, pTruths, nOuts*nWords, 0 ); + } + ABC_FREE( pTruthDup ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +#define TT_UNDEF ABC_CONST(0x1234567887654321) + +static inline word Abc_Tt6Min_rec( word uF, word uR, int nVars, Vec_Wrd_t * vNodes ) +{ + word uF0, uF1, uR0, uR1, uRes0, uRes1, uRes2; int i, Var; + assert( nVars <= 6 ); + assert( (uF & uR) == 0 ); + if ( !uF && !uR ) + return TT_UNDEF; + if ( !uF && !~uR ) + return 0; + if ( !~uF && !uR ) + return ~(word)0; + assert( nVars > 0 ); + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt6HasVar( uF, Var ) || Abc_Tt6HasVar( uR, Var ) ) + break; + assert( Var >= 0 ); + if ( 1 && vNodes ) + Vec_WrdForEachEntry( vNodes, uRes2, i ) + if ( !(uF & ~uRes2) && !(uRes2 & uR) ) + return uRes2; +// else if ( !(uF & uRes2) && !(~uRes2 & uR) ) +// return ~uRes2; + uF0 = Abc_Tt6Cofactor0( uF, Var ); + uF1 = Abc_Tt6Cofactor1( uF, Var ); + uR0 = Abc_Tt6Cofactor0( uR, Var ); + uR1 = Abc_Tt6Cofactor1( uR, Var ); + uRes0 = Abc_Tt6Min_rec( uF0, uR0, Var, vNodes ); + uRes1 = Abc_Tt6Min_rec( uF1, uR1, Var, vNodes ); + if ( uRes0 == TT_UNDEF && uRes1 == TT_UNDEF ) + return TT_UNDEF; + if ( uRes0 == TT_UNDEF ) + return uRes1; + if ( uRes1 == TT_UNDEF ) + return uRes0; + if ( uRes0 == uRes1 ) + return uRes0; +// if ( (uRes0 & ~uRes1) == 0 ) +// printf( "0" ); +// else if ( (~uRes0 & uRes1) == 0 ) +// printf( "1" ); +// else +// printf( "*" ); + uRes2 = (uRes0 & s_Truths6Neg[Var]) | (uRes1 & s_Truths6[Var]); + assert( !(uF & ~uRes2) ); + assert( !(uRes2 & uR) ); + if ( vNodes ) + Vec_WrdPush( vNodes, uRes2 ); + return uRes2; +} +word * Abc_TtMin_rec( word * pF, word * pR, int nVars, Vec_Wrd_t * vMemory, Vec_Wrd_t * vNodes, Vec_Wec_t * vNodes2 ) +{ + int i, Entry, nWords = Abc_TtWordNum(nVars); + word * pRes0, * pRes1, * pRes2 = Vec_WrdFetch( vMemory, nWords ); + if ( nVars <= 6 ) + { + pRes2[0] = Abc_Tt6Min_rec( pF[0], pR[0], nVars, vNodes ); + return pRes2; + } + assert( !Abc_TtIntersect(pF, pR, nWords, 0) ); + if ( Abc_TtIsConst0(pF, nWords) && Abc_TtIsConst0(pR, nWords) ) + return NULL; + if ( Abc_TtIsConst0(pF, nWords) && Abc_TtIsConst1(pR, nWords) ) + { + Abc_TtClear( pRes2, nWords ); + return pRes2; + } + if ( Abc_TtIsConst1(pF, nWords) && Abc_TtIsConst0(pR, nWords) ) + { + Abc_TtFill( pRes2, nWords ); + return pRes2; + } + nWords >>= 1; + if ( !Abc_TtHasVar( pF, nVars, nVars-1 ) && !Abc_TtHasVar( pR, nVars, nVars-1 ) ) + { + pRes0 = Abc_TtMin_rec( pF, pR, nVars-1, vMemory, vNodes, vNodes2 ); + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0, nWords, 0 ); + return pRes2; + } + if ( 1 && vNodes2 ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); + Vec_IntForEachEntry( vLayer, Entry, i ) + { + word * pTemp = Vec_WrdEntryP( vMemory, Entry ); + if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 1) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 0) ) + return pTemp; +/* + if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 0) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 1) ) + { + Abc_TtCopy( pRes2, pTemp, 2*nWords, 1 ); + return pRes2; + } +*/ + } + } + assert( nVars > 6 ); + pRes0 = Abc_TtMin_rec( pF, pR, nVars-1, vMemory, vNodes, vNodes2 ); + pRes1 = Abc_TtMin_rec( pF + nWords, pR + nWords, nVars-1, vMemory, vNodes, vNodes2 ); + if ( pRes0 == NULL && pRes1 == NULL ) + return NULL; + if ( pRes0 == NULL || pRes1 == NULL || Abc_TtEqual(pRes0, pRes1, nWords) ) + { + Abc_TtCopy( pRes2, pRes0 ? pRes0 : pRes1, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0 ? pRes0 : pRes1, nWords, 0 ); + return pRes2; + } + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes1, nWords, 0 ); + assert( !Abc_TtIntersect(pRes2, pF, 2*nWords, 1) ); // assert( !(uF & ~uRes2) ); + assert( !Abc_TtIntersect(pRes2, pR, 2*nWords, 0) ); // assert( !(uRes2 & uR) ); + if ( vNodes2 ) + Vec_WecPush( vNodes2, nVars, pRes2 - Vec_WrdArray(vMemory) ); + return pRes2; +} +word * Abc_TtMin( word * pF, word * pR, int nVars, Vec_Wrd_t * vMemory, Vec_Wrd_t * vNodes, Vec_Wec_t * vNodes2 ) +{ + word * pResult; + int i, nWords = Abc_TtWordNum(nVars); + assert( nVars >= 0 && nVars <= 16 ); + for ( i = nVars; i < 6; i++ ) + assert( !Abc_Tt6HasVar(pF[0], i) && !Abc_Tt6HasVar(pR[0], i) ); + Vec_WrdClear( vMemory ); + Vec_WrdGrow( vMemory, 1 << 20 ); + pResult = Abc_TtMin_rec( pF, pR, nVars, vMemory, vNodes, vNodes2 ); + if ( pResult == NULL ) + { + Vec_WrdFill( vMemory, nWords, 0 ); + return Vec_WrdArray( vMemory ); + } + //printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords ); + Abc_TtCopy( Vec_WrdArray(vMemory), pResult, nWords, 0 ); + Vec_WrdShrink( vMemory, nWords ); + return Vec_WrdArray(vMemory); +} +word * Abc_TtMinArray( word * p, int nOuts, int nVars, int * pnNodes, int fVerbose ) +{ + int o, i, nWords = Abc_TtWordNum(nVars); + word * pRes, * pResult = ABC_ALLOC( word, nOuts*nWords/2 ); + Vec_Wrd_t * vMemory = Vec_WrdAlloc( 100 ); + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + Vec_Wec_t * vNodes2 = Vec_WecStart( nVars+1 ); + Vec_WrdGrow( vMemory, 1 << 20 ); + for ( o = 0; o < nOuts/2; o++ ) + { + word * pF = p + (2*o+0)*nWords; + word * pR = p + (2*o+1)*nWords; + for ( i = nVars; i < 6; i++ ) + assert( !Abc_Tt6HasVar(pF[0], i) && !Abc_Tt6HasVar(pR[0], i) ); + pRes = Abc_TtMin_rec( pF, pR, nVars, vMemory, vNodes, vNodes2 ); + if ( pResult == NULL ) + Abc_TtClear( pResult + o*nWords, nWords ); + else + Abc_TtCopy( pResult + o*nWords, pRes, nWords, 0 ); + } + if ( fVerbose ) + printf( "Nodes = %5d. Nodes2 = %5d. Total = %5d. ", + Vec_WrdSize(vNodes), Vec_WecSizeSize(vNodes2), Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2) ); + //printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords ); + if ( pnNodes ) + *pnNodes = Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2); + Vec_WrdFree( vMemory ); + Vec_WrdFree( vNodes ); + Vec_WecFree( vNodes2 ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word Abc_TtSimple6Min_rec( Gia_Man_t * p, word uF, word uC, int nVars, Vec_Wrd_t * vNodes, int * piLit, int * pPerm ) +{ + word uF0, uF1, uC0, uC1, uRes0, uRes1, uRes2; int i, Var, iLit0, iLit1; + word uFC = uF & uC; + word uRC = ~uF & uC; + assert( nVars <= 6 ); + *piLit = 0; + if ( !uFC ) + { + *piLit = 0; + return 0; + } + if ( !uRC ) + { + *piLit = 1; + return ~(word)0; + } + assert( nVars > 0 ); + if ( 1 && vNodes ) + { + int iLit; + Vec_WrdForEachEntryDouble( vNodes, uRes2, iLit, i ) + if ( !((uF ^ uRes2) & uC) ) + { + *piLit = (unsigned)iLit; + return uRes2; + } + else if ( !((uF ^ ~uRes2) & uC) ) + { + *piLit = Abc_LitNot( (unsigned)iLit ); + return ~uRes2; + } + } + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt6HasVar( uF, Var ) ) + break; + else + uC = Abc_Tt6Cofactor0(uC, Var) | Abc_Tt6Cofactor1(uC, Var); + assert( Var >= 0 ); + uF0 = Abc_Tt6Cofactor0( uF, Var ); + uF1 = Abc_Tt6Cofactor1( uF, Var ); + uC0 = Abc_Tt6Cofactor0( uC, Var ); + uC1 = Abc_Tt6Cofactor1( uC, Var ); + uRes0 = Abc_TtSimple6Min_rec( p, uF0, uC0, Var, vNodes, &iLit0, pPerm ); + uRes1 = Abc_TtSimple6Min_rec( p, uF1, uC1, Var, vNodes, &iLit1, pPerm ); + if ( uRes0 == uRes1 ) + { + *piLit = iLit0; + return uRes0; + } + uRes2 = (uRes0 & s_Truths6Neg[Var]) | (uRes1 & s_Truths6[Var]); + Var = pPerm ? pPerm[Var] : Var; + //if ( !(uRes0 & ~uRes1 & uC1) ) + if ( !(uRes0 & ~uRes1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 0), iLit1), iLit0 ); + //else if ( !(uRes1 & ~uRes0 & uC0) ) + else if ( !(uRes1 & ~uRes0) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 1), iLit0), iLit1 ); + else + *piLit = Gia_ManHashMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); + assert( !(uFC & ~uRes2) ); + assert( !(uRes2 & uRC) ); + if ( vNodes ) + Vec_WrdPushTwo( vNodes, uRes2, (word)*piLit ); + return uRes2; +} +word * Abc_TtSimpleMin_rec( Gia_Man_t * p, word * pF, word * pC, int nVars, Vec_Wrd_t * vMemory, Vec_Wrd_t * vNodes, Vec_Wec_t * vNodes2, int * piLit, int * pPerm ) +{ + int i, Entry, Var, iLit0, iLit1, nWords = Abc_TtWordNum(nVars); + word * pRes0, * pRes1, * pRes2 = Vec_WrdFetch( vMemory, nWords ); + *piLit = 0; + if ( nVars <= 6 ) + { + pRes2[0] = Abc_TtSimple6Min_rec( p, pF[0], pC[0], nVars, vNodes, piLit, pPerm ); + return pRes2; + } + if ( !Abc_TtIntersect(pF, pC, nWords, 0) ) + { + *piLit = 0; + Abc_TtClear( pRes2, nWords ); + return pRes2; + } + if ( !Abc_TtIntersect(pF, pC, nWords, 1) ) + { + *piLit = 1; + Abc_TtFill( pRes2, nWords ); + return pRes2; + } + nWords >>= 1; + if ( !Abc_TtHasVar( pF, nVars, nVars-1 ) ) + { + word * pCn = Vec_WrdFetch( vMemory, nWords ); + Abc_TtOr( pCn, pC, pC + nWords, nWords ); + pRes0 = Abc_TtSimpleMin_rec( p, pF, pCn, nVars-1, vMemory, vNodes, vNodes2, piLit, pPerm ); + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0, nWords, 0 ); + return pRes2; + } + if ( 1 && vNodes2 ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); int iLit; + Vec_IntForEachEntryDouble( vLayer, Entry, iLit, i ) + { + word * pTemp = Vec_WrdEntryP( vMemory, Entry ); + if ( Abc_TtEqualCare(pTemp, pF, pC, 0, 2*nWords) ) + { + *piLit = iLit; + return pTemp; + } + else if ( Abc_TtEqualCare(pTemp, pF, pC, 1, 2*nWords) ) + { + *piLit = Abc_LitNot(iLit); + Abc_TtCopy( pRes2, pTemp, 2*nWords, 1 ); + return pRes2; + } + } + } + assert( nVars > 6 ); + pRes0 = Abc_TtSimpleMin_rec( p, pF, pC, nVars-1, vMemory, vNodes, vNodes2, &iLit0, pPerm ); + pRes1 = Abc_TtSimpleMin_rec( p, pF + nWords, pC + nWords, nVars-1, vMemory, vNodes, vNodes2, &iLit1, pPerm ); + if ( Abc_TtEqual(pRes0, pRes1, nWords) ) + { + *piLit = iLit0; + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0, nWords, 0 ); + return pRes2; + } + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes1, nWords, 0 ); + Var = pPerm ? pPerm[nVars-1] : nVars-1; + //if ( !Abc_TtIntersectCare(pRes1, pRes0, pC + nWords, nWords, 1) ) + if ( !Abc_TtIntersect(pRes1, pRes0, nWords, 1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 0), iLit1), iLit0 ); + //else if ( !Abc_TtIntersectCare(pRes0, pRes1, pC, nWords, 1) ) + else if ( !Abc_TtIntersect(pRes0, pRes1, nWords, 1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 1), iLit0), iLit1 ); + else + *piLit = Gia_ManHashMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); + assert( Abc_TtEqualCare(pRes2, pF, pC, 0, 2*nWords) ); + if ( vNodes2 ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); + Vec_IntPushTwo( vLayer, pRes2 - Vec_WrdArray(vMemory), *piLit ); + } + return pRes2; +} +Gia_Man_t * Abc_TtSimpleMinArrayNew( word * p, int nVars, int nOuts, int * pnNodes, int fVerbose, int * pIPerm ) +{ + Gia_Man_t * pNew, * pTemp; + int o, i, iLit, nWords = Abc_TtWordNum(nVars); + word * pF = ABC_ALLOC( word, nWords ); + word * pR = ABC_ALLOC( word, nWords ); + Vec_Wrd_t * vMemory = Vec_WrdAlloc( 100 ); + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + Vec_Wec_t * vNodes2 = Vec_WecStart( nVars+1 ); + Vec_WrdGrow( vMemory, 1 << 20 ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "muxes" ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + + for ( o = 0; o < nOuts; o++ ) + { + word * pCare = p + nOuts*nWords; + word * pTruth = p + o*nWords; + for ( i = nVars; i < 6; i++ ) + assert( !Abc_Tt6HasVar(pTruth[0], i) && !Abc_Tt6HasVar(pCare[0], i) ); + Abc_TtSimpleMin_rec( pNew, pTruth, pCare, nVars, vMemory, vNodes, vNodes2, &iLit, pIPerm ); + Gia_ManAppendCo( pNew, iLit ); + } + if ( fVerbose ) + printf( "Nodes = %5d. Nodes2 = %5d. Total = %5d. ", + Vec_WrdSize(vNodes), Vec_WecSizeSize(vNodes2), Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2) ); + //printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords ); + if ( pnNodes ) + *pnNodes = Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2); + Vec_WrdFree( vMemory ); + Vec_WrdFree( vNodes ); + Vec_WecFree( vNodes2 ); + ABC_FREE( pF ); + ABC_FREE( pR ); + + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word Abc_TtGia6Min_rec( Gia_Man_t * p, word uF, word uR, int nVars, Vec_Wrd_t * vNodes, int * piLit, int * pPerm ) +{ + word uF0, uF1, uR0, uR1, uRes0, uRes1, uRes2; int i, Var, iLit0, iLit1; + assert( nVars <= 6 ); + assert( (uF & uR) == 0 ); + *piLit = 0; + if ( !uF && !uR ) + return TT_UNDEF; + if ( !uF && !~uR ) + { + *piLit = 0; + return 0; + } + if ( !~uF && !uR ) + { + *piLit = 1; + return ~(word)0; + } + assert( nVars > 0 ); + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt6HasVar( uF, Var ) || Abc_Tt6HasVar( uR, Var ) ) + break; + assert( Var >= 0 ); + if ( 1 && vNodes ) + { + int iLit; + Vec_WrdForEachEntryDouble( vNodes, uRes2, iLit, i ) + if ( !(uF & ~uRes2) && !(uRes2 & uR) ) + { + *piLit = (unsigned)iLit; + return uRes2; + } + else if ( !(uF & uRes2) && !(~uRes2 & uR) ) + { + *piLit = Abc_LitNot( (unsigned)iLit ); + return ~uRes2; + } + } + uF0 = Abc_Tt6Cofactor0( uF, Var ); + uF1 = Abc_Tt6Cofactor1( uF, Var ); + uR0 = Abc_Tt6Cofactor0( uR, Var ); + uR1 = Abc_Tt6Cofactor1( uR, Var ); + uRes0 = Abc_TtGia6Min_rec( p, uF0, uR0, Var, vNodes, &iLit0, pPerm ); + uRes1 = Abc_TtGia6Min_rec( p, uF1, uR1, Var, vNodes, &iLit1, pPerm ); + if ( uRes0 == TT_UNDEF && uRes1 == TT_UNDEF ) + return TT_UNDEF; + if ( uRes0 == TT_UNDEF ) + { + *piLit = iLit1; + return uRes1; + } + if ( uRes1 == TT_UNDEF || uRes0 == uRes1 ) + { + *piLit = iLit0; + return uRes0; + } +// if ( (uRes0 & ~uRes1) == 0 ) +// printf( "0" ); +// else if ( (~uRes0 & uRes1) == 0 ) +// printf( "1" ); +// else +// printf( "*" ); + uRes2 = (uRes0 & s_Truths6Neg[Var]) | (uRes1 & s_Truths6[Var]); + Var = pPerm ? pPerm[Var] : Var; + if ( !(uRes0 & ~uRes1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 0), iLit1), iLit0 ); + else if ( !(uRes1 & ~uRes0) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 1), iLit0), iLit1 ); + else + *piLit = Gia_ManHashMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); + assert( !(uF & ~uRes2) ); + assert( !(uRes2 & uR) ); + if ( vNodes ) + Vec_WrdPushTwo( vNodes, uRes2, (word)*piLit ); + return uRes2; +} +word * Abc_TtGiaMin_rec( Gia_Man_t * p, word * pF, word * pR, int nVars, Vec_Wrd_t * vMemory, Vec_Wrd_t * vNodes, Vec_Wec_t * vNodes2, int * piLit, int * pPerm ) +{ + int i, Entry, Var, iLit0, iLit1, nWords = Abc_TtWordNum(nVars); + word * pRes0, * pRes1, * pRes2 = Vec_WrdFetch( vMemory, nWords ); + *piLit = 0; + if ( nVars <= 6 ) + { + pRes2[0] = Abc_TtGia6Min_rec( p, pF[0], pR[0], nVars, vNodes, piLit, pPerm ); + return pRes2; + } + assert( !Abc_TtIntersect(pF, pR, nWords, 0) ); + if ( Abc_TtIsConst0(pF, nWords) && Abc_TtIsConst0(pR, nWords) ) + return NULL; + if ( Abc_TtIsConst0(pF, nWords) && Abc_TtIsConst1(pR, nWords) ) + { + *piLit = 0; + Abc_TtClear( pRes2, nWords ); + return pRes2; + } + if ( Abc_TtIsConst1(pF, nWords) && Abc_TtIsConst0(pR, nWords) ) + { + *piLit = 1; + Abc_TtFill( pRes2, nWords ); + return pRes2; + } + nWords >>= 1; + if ( !Abc_TtHasVar( pF, nVars, nVars-1 ) && !Abc_TtHasVar( pR, nVars, nVars-1 ) ) + { + pRes0 = Abc_TtGiaMin_rec( p, pF, pR, nVars-1, vMemory, vNodes, vNodes2, piLit, pPerm ); + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0, nWords, 0 ); + return pRes2; + } + if ( 1 && vNodes2 ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); int iLit; + Vec_IntForEachEntryDouble( vLayer, Entry, iLit, i ) + { + word * pTemp = Vec_WrdEntryP( vMemory, Entry ); + if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 1) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 0) ) + { + *piLit = iLit; + return pTemp; + } + else if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 0) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 1) ) + { + *piLit = Abc_LitNot(iLit); + Abc_TtCopy( pRes2, pTemp, 2*nWords, 1 ); + return pRes2; + } + } +/* + if ( nVars > 7 ) + { + vLayer = Vec_WecEntry( vNodes2, nVars-1 ); + Vec_IntForEachEntryDouble( vLayer, Entry, iLit, i ) + { + word * pTemp = Vec_WrdEntryP( vMemory, Entry ); + if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 1) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 0) ) + { + *piLit = iLit; + return pTemp; + } + else if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 0) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 1) ) + { + *piLit = Abc_LitNot(iLit); + Abc_TtCopy( pRes2, pTemp, 2*nWords, 1 ); + return pRes2; + } + } + } +*/ + } + assert( nVars > 6 ); + pRes0 = Abc_TtGiaMin_rec( p, pF, pR, nVars-1, vMemory, vNodes, vNodes2, &iLit0, pPerm ); + pRes1 = Abc_TtGiaMin_rec( p, pF + nWords, pR + nWords, nVars-1, vMemory, vNodes, vNodes2, &iLit1, pPerm ); + if ( pRes0 == NULL && pRes1 == NULL ) + return NULL; + if ( pRes0 == NULL || pRes1 == NULL || Abc_TtEqual(pRes0, pRes1, nWords) ) + { + *piLit = pRes0 ? iLit0 : iLit1; + Abc_TtCopy( pRes2, pRes0 ? pRes0 : pRes1, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0 ? pRes0 : pRes1, nWords, 0 ); + return pRes2; + } + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes1, nWords, 0 ); + Var = pPerm ? pPerm[nVars-1] : nVars-1; + if ( !Abc_TtIntersect(pRes1, pRes0, nWords, 1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 0), iLit1), iLit0 ); + else if ( !Abc_TtIntersect(pRes0, pRes1, nWords, 1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 1), iLit0), iLit1 ); + else + *piLit = Gia_ManHashMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); + assert( !Abc_TtIntersect(pRes2, pF, 2*nWords, 1) ); // assert( !(uF & ~uRes2) ); + assert( !Abc_TtIntersect(pRes2, pR, 2*nWords, 0) ); // assert( !(uRes2 & uR) ); + if ( vNodes2 ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); + Vec_IntPushTwo( vLayer, pRes2 - Vec_WrdArray(vMemory), *piLit ); + } + return pRes2; +} +Gia_Man_t * Abc_TtGiaMinArray( word * p, int nVars, int nOuts, int * pnNodes, int fVerbose, int * pIPerm ) +{ + Gia_Man_t * pNew, * pTemp; + int o, i, iLit, nWords = Abc_TtWordNum(nVars); + word * pRes, * pResult = ABC_ALLOC( word, nOuts*nWords/2 ); + Vec_Wrd_t * vMemory = Vec_WrdAlloc( 100 ); + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + Vec_Wec_t * vNodes2 = Vec_WecStart( nVars+1 ); + Vec_WrdGrow( vMemory, 1 << 20 ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "muxes" ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + + for ( o = 0; o < nOuts/2; o++ ) + { + word * pF = p + (2*o+0)*nWords; + word * pR = p + (2*o+1)*nWords; + for ( i = nVars; i < 6; i++ ) + assert( !Abc_Tt6HasVar(pF[0], i) && !Abc_Tt6HasVar(pR[0], i) ); + pRes = Abc_TtGiaMin_rec( pNew, pF, pR, nVars, vMemory, vNodes, vNodes2, &iLit, pIPerm ); + if ( pResult == NULL ) + { + Abc_TtClear( pResult + o*nWords, nWords ); + Gia_ManAppendCo( pNew, 0 ); + } + else + { + Abc_TtCopy( pResult + o*nWords, pRes, nWords, 0 ); + Gia_ManAppendCo( pNew, iLit ); + } + } + if ( fVerbose ) + printf( "Nodes = %5d. Nodes2 = %5d. Total = %5d. ", + Vec_WrdSize(vNodes), Vec_WecSizeSize(vNodes2), Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2) ); + //printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords ); + if ( pnNodes ) + *pnNodes = Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2); + Vec_WrdFree( vMemory ); + Vec_WrdFree( vNodes ); + Vec_WecFree( vNodes2 ); + ABC_FREE( pResult ); + + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Abc_TtGiaMinArrayNew( word * p, int nVars, int nOuts, int * pnNodes, int fVerbose, int * pIPerm ) +{ + Gia_Man_t * pNew, * pTemp; + int o, i, iLit, nWords = Abc_TtWordNum(nVars); + word * pF = ABC_ALLOC( word, nWords ); + word * pR = ABC_ALLOC( word, nWords ); + Vec_Wrd_t * vMemory = Vec_WrdAlloc( 100 ); + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + Vec_Wec_t * vNodes2 = Vec_WecStart( nVars+1 ); + Vec_WrdGrow( vMemory, 1 << 20 ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "muxes" ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + + for ( o = 0; o < nOuts; o++ ) + { + word * pCare = p + nOuts*nWords; + word * pTruth = p + o*nWords; + Abc_TtAnd( pF, pCare, pTruth, nWords, 0 ); + Abc_TtSharp( pR, pCare, pTruth, nWords ); + for ( i = nVars; i < 6; i++ ) + assert( !Abc_Tt6HasVar(pF[0], i) && !Abc_Tt6HasVar(pR[0], i) ); + Abc_TtGiaMin_rec( pNew, pF, pR, nVars, vMemory, vNodes, vNodes2, &iLit, pIPerm ); + Gia_ManAppendCo( pNew, iLit ); + } + if ( fVerbose ) + printf( "Nodes = %5d. Nodes2 = %5d. Total = %5d. ", + Vec_WrdSize(vNodes), Vec_WecSizeSize(vNodes2), Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2) ); + //printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords ); + if ( pnNodes ) + *pnNodes = Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2); + Vec_WrdFree( vMemory ); + Vec_WrdFree( vNodes ); + Vec_WecFree( vNodes2 ); + ABC_FREE( pF ); + ABC_FREE( pR ); + + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManBuildMuxes6_rec( Gia_Man_t * p, word t, int nVars, int * pPerm ) +{ + int iLit0, iLit1, Var; + assert( nVars <= 6 ); + if ( t == 0 ) + return 0; + if ( ~t == 0 ) + return 1; + assert( nVars > 0 ); + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt6HasVar( t, Var ) ) + break; + assert( Var >= 0 ); + iLit0 = Gia_ManBuildMuxes6_rec( p, Abc_Tt6Cofactor0(t, Var), Var, pPerm ); + iLit1 = Gia_ManBuildMuxes6_rec( p, Abc_Tt6Cofactor1(t, Var), Var, pPerm ); + Var = pPerm ? pPerm[Var] : Var; + return Gia_ManAppendMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); +} +int Gia_ManBuildMuxes_rec( Gia_Man_t * p, word * pTruth, int nVars, int * pPerm ) +{ + int iLit0, iLit1, Var, nWords = Abc_TtWordNum(nVars); + if ( nVars <= 6 ) + return Gia_ManBuildMuxes6_rec( p, pTruth[0], nVars, pPerm ); + if ( Abc_TtIsConst0(pTruth, nWords) ) + return 0; + if ( Abc_TtIsConst1(pTruth, nWords) ) + return 1; +/* + assert( nVars > 0 ); + if ( !Abc_TtHasVar( pTruth, nVars, nVars-1 ) ) + return Gia_ManBuildMuxes_rec( p, pTruth, nVars-1 ); + assert( nVars > 6 ); + iLit0 = Gia_ManBuildMuxes_rec( p, pTruth, nVars-1 ); + iLit1 = Gia_ManBuildMuxes_rec( p, pTruth+nWords/2, nVars-1 ); +*/ + assert( nVars > 0 ); + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_TtHasVar( pTruth, nVars, Var ) ) + break; + assert( Var >= 0 ); + if ( Var < 6 ) + return Gia_ManBuildMuxes6_rec( p, pTruth[0], Var+1, pPerm ); + iLit0 = Gia_ManBuildMuxes_rec( p, pTruth, Var, pPerm ); + iLit1 = Gia_ManBuildMuxes_rec( p, pTruth+Abc_TtWordNum(Var), Var, pPerm ); + Var = pPerm ? pPerm[Var] : Var; + return Gia_ManAppendMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); +} +Gia_Man_t * Gia_ManBuildMuxesTest( word * pTruth, int nIns, int nOuts, int * pPerm ) +{ + Gia_Man_t * pNew, * pTemp; + int i, nWords = Abc_TtWordNum(nIns); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "muxes" ); + for ( i = 0; i < nIns; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManAppendCo( pNew, Gia_ManBuildMuxes_rec( pNew, pTruth+i*nWords, nIns, pPerm ) ); + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Gia_ManBuildMuxes( Tree_Sto_t * p, int * pIPerm ) +{ + return Gia_ManBuildMuxesTest( p->pMem, p->nIns, p->nOuts, pIPerm ? pIPerm : p->pIPerm ); +} +void Gia_ManDumpMuxes( Tree_Sto_t * p, char * pFileName, int * pIPerm ) +{ + Gia_Man_t * pNew = Gia_ManBuildMuxes( p, pIPerm ); + Gia_AigerWrite( pNew, pFileName, 0, 0, 0 ); + Gia_ManStop( pNew ); + printf( "Finished dumping tree into AIG file \"%s\".\n", pFileName ); +} +Gia_Man_t * Gia_ManCreateMuxGia( word * pTruths, int nIns, int nOuts, int nWords, int * pIPerm ) +{ + Tree_Sto_t * pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + Gia_Man_t * pNew = Gia_ManBuildMuxes( pSto, pIPerm ); + //printf( "Internal nodes = %5d.\n", Gia_ManTreeCountNodes(pSto) ); + Gia_ManTreeFree( pSto ); + return pNew; +} +void Gia_ManDumpMuxGia( word * pTruths, int nIns, int nOuts, int nWords, int * pIPerm, char * pFileName ) +{ + Tree_Sto_t * pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + Gia_ManDumpMuxes( pSto, pFileName, pIPerm ); + Gia_ManTreeFree( pSto ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_TryPermOptCare( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Man_t * pNew; + word * pTruthDup = Abc_TtDup( pTruths, nOuts*nWords, 0 ); + word * pTruthBest = ABC_FALLOC( word, (nOuts+1)*nWords ); + int pIPermBest[TREE_MAX_VARS] = {0}; + int pIPerm[TREE_MAX_VARS] = {0}; + int r, rBest = -1, nNodes = -1, nNodesBest = ABC_INFINITY; + //Gia_ManDumpMuxGia( pTruths, nIns, nOuts, nWords, NULL, "tt_beg.aig" ); + //srand( time(NULL) ); + Gia_ManRandom(1); + for ( r = 0; r < nRounds; r++ ) + { + nNodes = Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, r>0, pIPerm, 0, fVerbose ); + if ( nNodesBest > nNodes ) + { + nNodesBest = nNodes; + memcpy( pIPermBest, pIPerm, sizeof(int)*nIns ); + Abc_TtCopy( pTruthBest, pTruthDup, nOuts*nWords, 0 ); + rBest = r; + } + Abc_TtCopy( pTruthDup, pTruths, nOuts*nWords, 0 ); + if ( fVerbose ) + printf( "\n" ); + } + if ( fVerbose ) + printf( "Best round %3d. Best nodes %5d. ", rBest, nNodesBest ); + ABC_FREE( pTruthDup ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + //pNew = Gia_ManCreateMuxGia( pTruthBest, nIns, nOuts, nWords, pIPermBest ); + pNew = Abc_TtSimpleMinArrayNew( pTruthBest, nIns, nOuts, NULL, 0, pIPermBest ); + //Gia_ManDumpMuxGia( pTruthBest, nIns, nOuts, nWords, pIPermBest, "tt_end.aig" ); + ABC_FREE( pTruthBest ); + return pNew; +} +Gia_Man_t * Gia_TryPermOpt2( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Man_t * pNew; + word * pRes, * pTruthDup = Abc_TtDup( pTruths, nOuts*nWords, 0 ); + word * pTruthBest = ABC_ALLOC( word, nOuts*nWords/2 ); + int pIPermBest[TREE_MAX_VARS] = {0}; + int pIPerm[TREE_MAX_VARS] = {0}; + int r, rBest = -1, nNodes = -1, nNodesBest = ABC_INFINITY; + assert( nOuts % 2 == 0 ); + // collect onsets + //for ( r = 0; r < nOuts/2; r++ ) + // Abc_TtCopy( pTruthBest+r*nWords, pTruths+2*r*nWords, nWords, 0 ); + //Gia_ManDumpMuxGia( pTruthBest, nIns, nOuts/2, nWords, NULL, "tt_beg.aig" ); + //srand( time(NULL) ); + Gia_ManRandom(1); + for ( r = 0; r < nRounds; r++ ) + { + int nNodesAll = Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, r>0, pIPerm, 0, fVerbose ); + pRes = Abc_TtMinArray( pTruthDup, nOuts, nIns, &nNodes, fVerbose ); + if ( nNodesBest > nNodes ) + { + nNodesBest = nNodes; + memcpy( pIPermBest, pIPerm, sizeof(int)*nIns ); + Abc_TtCopy( pTruthBest, pRes, nOuts*nWords/2, 0 ); + rBest = r; + } + ABC_FREE( pRes ); + Abc_TtCopy( pTruthDup, pTruths, nOuts*nWords, 0 ); + if ( fVerbose ) + printf( "\n" ); + nNodesAll = 0; + } + if ( fVerbose ) + printf( "Best round %3d. Best nodes %5d. ", rBest, nNodesBest ); + ABC_FREE( pTruthDup ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + pNew = Gia_ManCreateMuxGia( pTruthBest, nIns, nOuts/2, nWords, pIPermBest ); + //Gia_ManDumpMuxGia( pTruthBest, nIns, nOuts/2, nWords, pIPermBest, "tt_end.aig" ); + ABC_FREE( pTruthBest ); + return pNew; +} +Gia_Man_t * Gia_TryPermOpt( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Man_t * pBest = NULL; + word * pTruthDup = Abc_TtDup( pTruths, nOuts*nWords, 0 ); + int pIPermBest[TREE_MAX_VARS] = {0}; + int pIPerm[TREE_MAX_VARS] = {0}; + int r, rBest = -1, nNodes2 = -1, nNodesBest = ABC_INFINITY; + assert( nOuts % 2 == 0 ); + //srand( time(NULL) ); + Gia_ManRandom(1); + for ( r = 0; r < nRounds; r++ ) + { + int nNodesAll = Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, r>0, pIPerm, 0, fVerbose ); + Gia_Man_t * pTemp = Abc_TtGiaMinArray( pTruthDup, nIns, nOuts, NULL, 0, pIPerm ); + nNodes2 = Gia_ManAndNum(pTemp); + if ( nNodesBest > nNodes2 ) + { + nNodesBest = nNodes2; + memcpy( pIPermBest, pIPerm, sizeof(int)*nIns ); + rBest = r; + + Gia_ManStopP( &pBest ); + pBest = pTemp; + pTemp = NULL; + } + Gia_ManStopP( &pTemp ); + Abc_TtCopy( pTruthDup, pTruths, nOuts*nWords, 0 ); + if ( fVerbose ) + printf( "Permuted = %5d. AIG = %5d.\n", nNodesAll, nNodes2 ); + nNodesAll = 0; + } + if ( fVerbose ) + printf( "Best round %3d. Best nodes %5d. ", rBest, nNodesBest ); + ABC_FREE( pTruthDup ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return pBest; +} +Gia_Man_t * Gia_TryPermOptNew( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Man_t * pTemp, * pBest = NULL; + word * pTruthDup = Abc_TtDup( pTruths, (nOuts+1)*nWords, 0 ); + int pIPermBest[TREE_MAX_VARS] = {0}; + int pIPerm[TREE_MAX_VARS] = {0}; + int r, rBest = -1, nNodes2 = -1, nNodesBest = ABC_INFINITY; + //srand( time(NULL) ); + Gia_ManRandom(1); + for ( r = 0; r < nRounds; r++ ) + { + int nNodesAll = Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, r>0, pIPerm, 0, fVerbose ); + Abc_TtPermute( pTruthDup + nOuts*nWords, pIPerm, nIns ); + //pTemp = Abc_TtGiaMinArrayNew( pTruthDup, nIns, nOuts, NULL, 0, pIPerm ); + pTemp = Abc_TtSimpleMinArrayNew( pTruthDup, nIns, nOuts, NULL, 0, pIPerm ); + nNodes2 = Gia_ManAndNum(pTemp); + if ( nNodesBest > nNodes2 ) + { + nNodesBest = nNodes2; + memcpy( pIPermBest, pIPerm, sizeof(int)*nIns ); + rBest = r; + + Gia_ManStopP( &pBest ); + pBest = pTemp; + pTemp = NULL; + } + Gia_ManStopP( &pTemp ); +/* + for ( i = 0; i <= nOuts; i++ ) + { + Abc_TtUnpermute( pTruthDup + i*nWords, pIPerm, nIns ); + if ( !Abc_TtEqual(pTruthDup + i*nWords, pTruths + i*nWords, nWords) ) + printf( "Verification failed for output %d (out of %d).\n", i, nOuts ); + } +*/ + Abc_TtCopy( pTruthDup, pTruths, (nOuts+1)*nWords, 0 ); + if ( fVerbose ) + printf( "Permuted = %5d. AIG = %5d.\n", nNodesAll, nNodes2 ); + nNodesAll = 0; + } + if ( fVerbose ) + printf( "Best round %3d. Best nodes %5d. ", rBest, nNodesBest ); + ABC_FREE( pTruthDup ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return pBest; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_Tt6MinTest3( Gia_Man_t * p ) +{ + word f = ABC_CONST(0x513B00000819050F); + //word r = ABC_CONST(0xA000571507200000); + word r = ~f; + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + word Res = Abc_Tt6Min_rec( f, r, 6, vNodes ); + printf( "Nodes = %d.\n", Vec_WrdSize(vNodes) ); + if ( Res == f ) + printf( "Verification successful.\n" ); + else + printf( "Verification FAILED.\n" ); + Vec_WrdFree( vNodes ); +} +void Abc_Tt6MinTest2( Gia_Man_t * p ) +{ + int fVerbose = 0; + int i, nWords = Abc_TtWordNum(Gia_ManCiNum(p)); + word * pTruth = ABC_ALLOC( word, 3*nWords ); + word * pRes = NULL, * pTruths[3] = { pTruth, pTruth+nWords, pTruth+2*nWords }; + + Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + Vec_Wec_t * vNodes2 = Vec_WecAlloc( 100 ); + Vec_Wrd_t * vMemory = Vec_WrdAlloc( 0 ); + + Gia_Obj_t * pObj; + Gia_ManForEachCi( p, pObj, i ) + Vec_IntPush( vSupp, Gia_ObjId(p, pObj) ); + + Gia_ObjComputeTruthTableStart( p, Gia_ManCiNum(p) ); + assert( Gia_ManCoNum(p) == 3 ); + Gia_ManForEachCo( p, pObj, i ) + { + word * pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); + Abc_TtCopy( pTruths[i], pTruth, nWords, Gia_ObjFaninC0(pObj) ); + } + Gia_ObjComputeTruthTableStop( p ); + + + //Abc_TtSharp( pTruths[0], pTruths[0], pTruths[1], nWords ); + Abc_TtReverseVars( pTruths[0], Gia_ManCiNum(p) ); + Abc_TtCopy( pTruths[1], pTruths[0], nWords, 1 ); + + pRes = Abc_TtMin( pTruths[0], pTruths[1], Gia_ManCiNum(p), vMemory, vNodes, vNodes2 ); + printf( "Nodes = %d.\n", Vec_WrdSize(vNodes) ); + printf( "Nodes2 = %d.\n", Vec_WecSizeSize(vNodes2) ); + if ( Abc_TtEqual(pRes, pTruths[0], nWords) ) + printf( "Verification successful.\n" ); + else + printf( "Verification FAILED.\n" ); + + //printf( "Printing the tree:\n" ); +// Gia_ManPermuteTree( pTruths[0], Gia_ManCiNum(p), 1, nWords, fVerbose ); + Gia_ManPermuteTree( pTruth, Gia_ManCiNum(p), 3, nWords, 0, fVerbose ); + + +/* + Abc_TtReverseVars( pTruths[0], Gia_ManCiNum(p) ); + Abc_TtReverseVars( pTruths[1], Gia_ManCiNum(p) ); + Abc_TtReverseVars( pTruths[2], Gia_ManCiNum(p) ); + printf( "Printing the tree:\n" ); + Gia_ManContructTree( pTruth, Gia_ManCiNum(p), 3, nWords ); +*/ + +/* + pNew = Gia_ManBuildMuxesTest( pTruth, Gia_ManCiNum(p), Gia_ManCoNum(p), NULL ); + Gia_AigerWrite( pNew, "from_tt.aig", 0, 0, 0 ); + printf( "Dumping file \"%s\".\n", "from_tt.aig" ); + Gia_ManStop( pNew ); +*/ + + Vec_WrdFree( vMemory ); + Vec_WrdFree( vNodes ); + Vec_WecFree( vNodes2 ); + Vec_IntFree( vSupp ); + ABC_FREE( pTruth ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaMini.c b/abc/src/aig/gia/giaMini.c index e14a9a9e939..c0473fea3d4 100644 --- a/abc/src/aig/gia/giaMini.c +++ b/abc/src/aig/gia/giaMini.c @@ -32,6 +32,8 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -57,7 +59,7 @@ int Gia_ObjFromMiniFanin1Copy( Gia_Man_t * pGia, Vec_Int_t * vCopies, Mini_Aig_t int Lit = Mini_AigNodeFanin1( p, Id ); return Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(Lit)), Abc_LitIsCompl(Lit) ); } -Gia_Man_t * Gia_ManFromMiniAig( Mini_Aig_t * p, Vec_Int_t ** pvCopies ) +Gia_Man_t * Gia_ManFromMiniAig( Mini_Aig_t * p, Vec_Int_t ** pvCopies, int fGiaSimple ) { Gia_Man_t * pGia, * pTemp; Vec_Int_t * vCopies; @@ -71,7 +73,10 @@ Gia_Man_t * Gia_ManFromMiniAig( Mini_Aig_t * p, Vec_Int_t ** pvCopies ) vCopies = Vec_IntAlloc( nNodes ); Vec_IntPush( vCopies, 0 ); // iterate through the objects - Gia_ManHashAlloc( pGia ); + if ( fGiaSimple ) + pGia->fGiaSimple = fGiaSimple; + else + Gia_ManHashAlloc( pGia ); for ( i = 1; i < nNodes; i++ ) { if ( Mini_AigNodeIsPi( p, i ) ) @@ -83,17 +88,19 @@ Gia_Man_t * Gia_ManFromMiniAig( Mini_Aig_t * p, Vec_Int_t ** pvCopies ) else assert( 0 ); Vec_IntPush( vCopies, iGiaLit ); } - Gia_ManHashStop( pGia ); assert( Vec_IntSize(vCopies) == nNodes ); if ( pvCopies ) *pvCopies = vCopies; else Vec_IntFree( vCopies ); Gia_ManSetRegNum( pGia, Mini_AigRegNum(p) ); - pGia = Gia_ManCleanup( pTemp = pGia ); - if ( pvCopies ) - Gia_ManDupRemapLiterals( *pvCopies, pTemp ); - Gia_ManStop( pTemp ); + if ( !fGiaSimple ) + { + pGia = Gia_ManCleanup( pTemp = pGia ); + if ( pvCopies ) + Gia_ManDupRemapLiterals( *pvCopies, pTemp ); + Gia_ManStop( pTemp ); + } return pGia; } @@ -148,7 +155,7 @@ void Abc_FrameGiaInputMiniAig( Abc_Frame_t * pAbc, void * p ) printf( "ABC framework is not initialized by calling Abc_Start()\n" ); Gia_ManStopP( &pAbc->pGiaMiniAig ); Vec_IntFreeP( &pAbc->vCopyMiniAig ); - pGia = Gia_ManFromMiniAig( (Mini_Aig_t *)p, &pAbc->vCopyMiniAig ); + pGia = Gia_ManFromMiniAig( (Mini_Aig_t *)p, &pAbc->vCopyMiniAig, 0 ); Abc_FrameUpdateGia( pAbc, pGia ); pAbc->pGiaMiniAig = Gia_ManDup( pGia ); // Gia_ManDelete( pGia ); @@ -175,13 +182,56 @@ void * Abc_FrameGiaOutputMiniAig( Abc_Frame_t * pAbc ) SeeAlso [] ***********************************************************************/ -Gia_Man_t * Gia_ManReadMiniAig( char * pFileName ) +void Gia_ManReadMiniAigNames( char * pFileName, Gia_Man_t * pGia ) +{ + char * filename3 = Abc_UtilStrsavTwo( pFileName, ".ilo" ); + FILE * pFile = fopen( filename3, "rb" ); + if ( pFile ) + { + char Buffer[5000], * pName; int i, iLines = 0; + Vec_Ptr_t * vTemp = Vec_PtrAlloc( Gia_ManRegNum(pGia) ); + assert( pGia->vNamesIn == NULL ); + pGia->vNamesIn = Vec_PtrAlloc( Gia_ManCiNum(pGia) ); + assert( pGia->vNamesOut == NULL ); + pGia->vNamesOut = Vec_PtrAlloc( Gia_ManCoNum(pGia) ); + while ( fgets(Buffer, 5000, pFile) ) + { + if ( Buffer[strlen(Buffer)-1] == '\n' ) + Buffer[strlen(Buffer)-1] = 0; + if ( iLines < Gia_ManPiNum(pGia) ) + Vec_PtrPush( pGia->vNamesIn, Abc_UtilStrsav(Buffer) ); + else if ( iLines < Gia_ManCiNum(pGia) ) + Vec_PtrPush( vTemp, Abc_UtilStrsav(Buffer) ); + else + Vec_PtrPush( pGia->vNamesOut, Abc_UtilStrsav(Buffer) ); + iLines++; + } + Vec_PtrForEachEntry( char *, vTemp, pName, i ) + { + Vec_PtrPush( pGia->vNamesIn, Abc_UtilStrsav(pName) ); + Vec_PtrPush( pGia->vNamesOut, Abc_UtilStrsavTwo(pName, "_in") ); + } + Vec_PtrFreeFree( vTemp ); + fclose( pFile ); + printf( "Read ILO names into file \"%s\".\n", filename3 ); + } + ABC_FREE( filename3 ); +} +Gia_Man_t * Gia_ManReadMiniAig( char * pFileName, int fGiaSimple ) { Mini_Aig_t * p = Mini_AigLoad( pFileName ); - Gia_Man_t * pGia = Gia_ManFromMiniAig( p, NULL ); + Gia_Man_t * pTemp, * pGia = Gia_ManFromMiniAig( p, NULL, fGiaSimple ); ABC_FREE( pGia->pName ); pGia->pName = Extra_FileNameGeneric( pFileName ); Mini_AigStop( p ); + Gia_ManReadMiniAigNames( pFileName, pGia ); + if ( !Gia_ManIsNormalized(pGia) ) + { + pGia = Gia_ManDupNormalize( pTemp = pGia, 0 ); + ABC_SWAP( Vec_Ptr_t *, pTemp->vNamesIn, pGia->vNamesIn ); + ABC_SWAP( Vec_Ptr_t *, pTemp->vNamesOut, pGia->vNamesOut ); + Gia_ManStop( pTemp ); + } return pGia; } void Gia_ManWriteMiniAig( Gia_Man_t * pGia, char * pFileName ) @@ -260,6 +310,65 @@ Gia_Man_t * Gia_ManFromMiniLut( Mini_Lut_t * p, Vec_Int_t ** pvCopies ) return pGia; } + +/**Function************************************************************* + + Synopsis [Converts MiniLUT into GIA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFromMiniLut2( Mini_Lut_t * p, Vec_Int_t ** pvCopies ) +{ + Gia_Man_t * pGia; + Vec_Int_t * vCopies; + Vec_Int_t * vCover = Vec_IntAlloc( 1000 ); + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + int i, k, Fan, iGiaLit, nNodes; + // get the number of nodes + nNodes = Mini_LutNodeNum(p); + // create ABC network + pGia = Gia_ManStart( 3 * nNodes ); + pGia->pName = Abc_UtilStrsav( "MiniLut" ); + // create mapping from MiniLUT objects into ABC objects + vCopies = Vec_IntAlloc( nNodes ); + Vec_IntPush( vCopies, 0 ); + Vec_IntPush( vCopies, 1 ); + // iterate through the objects + pGia->fGiaSimple = 1; + for ( i = 2; i < nNodes; i++ ) + { + if ( Mini_LutNodeIsPi( p, i ) ) + iGiaLit = Gia_ManAppendCi(pGia); + else if ( Mini_LutNodeIsPo( p, i ) ) + iGiaLit = Gia_ManAppendCo(pGia, Vec_IntEntry(vCopies, Mini_LutNodeFanin(p, i, 0))); + else if ( Mini_LutNodeIsNode( p, i ) ) + { + unsigned * puTruth = Mini_LutNodeTruth( p, i ); + Vec_IntClear( vLits ); + Mini_LutForEachFanin( p, i, Fan, k ) + Vec_IntPush( vLits, Vec_IntEntry(vCopies, Fan) ); + iGiaLit = Kit_TruthToGia( pGia, puTruth, Vec_IntSize(vLits), vCover, vLits, 0 ); + } + else assert( 0 ); + Vec_IntPush( vCopies, iGiaLit ); + } + Vec_IntFree( vCover ); + Vec_IntFree( vLits ); + assert( Vec_IntSize(vCopies) == nNodes ); + if ( pvCopies ) + *pvCopies = vCopies; + else + Vec_IntFree( vCopies ); + Gia_ManSetRegNum( pGia, Mini_LutRegNum(p) ); + return pGia; +} + + /**Function************************************************************* Synopsis [Marks LUTs that should be complemented.] @@ -305,6 +414,7 @@ Mini_Lut_t * Gia_ManToMiniLut( Gia_Man_t * pGia ) Vec_Bit_t * vMarks; Gia_Obj_t * pObj, * pFanin; Vec_Int_t * vLeaves = Vec_IntAlloc( 16 ); + Vec_Int_t * vInvMap = Vec_IntStart( Gia_ManObjNum(pGia) ); int i, k, iFanin, LutSize, nWords, Count = 0, pVars[16]; word * pTruth; assert( Gia_ManHasMapping(pGia) ); @@ -316,6 +426,7 @@ Mini_Lut_t * Gia_ManToMiniLut( Gia_Man_t * pGia ) p = Mini_LutStart( LutSize ); // create primary inputs Gia_ManFillValue( pGia ); + Gia_ManConst0(pGia)->Value = 0; Gia_ManForEachCi( pGia, pObj, i ) pObj->Value = Mini_LutCreatePi(p); // create internal nodes @@ -361,12 +472,17 @@ Mini_Lut_t * Gia_ManToMiniLut( Gia_Man_t * pGia ) pObj->Value = Mini_LutCreatePo( p, Gia_ObjFanin0(pObj)->Value ); else // add inverter LUT { - int Fanin = Gia_ObjFanin0(pObj)->Value; - int LutInv = Mini_LutCreateNode( p, 1, &Fanin, (unsigned *)pTruth ); + int LutInv, Fanin = Gia_ObjFanin0(pObj)->Value; + if ( (LutInv = Vec_IntEntry(vInvMap, Fanin)) == 0 ) + { + LutInv = Mini_LutCreateNode( p, 1, &Fanin, (unsigned *)pTruth ); + Vec_IntWriteEntry( vInvMap, Fanin, LutInv ); + Count++; + } pObj->Value = Mini_LutCreatePo( p, LutInv ); - Count++; } } + Vec_IntFree( vInvMap ); Vec_BitFree( vMarks ); Gia_ObjComputeTruthTableStop( pGia ); // set registers @@ -405,6 +521,15 @@ void Abc_FrameGiaInputMiniLut( Abc_Frame_t * pAbc, void * p ) Abc_FrameUpdateGia( pAbc, pGia ); // Gia_ManDelete( pGia ); } +void Abc_FrameGiaInputMiniLut2( Abc_Frame_t * pAbc, void * p ) +{ + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + Vec_IntFreeP( &pAbc->vCopyMiniLut ); + Gia_ManStopP( &pAbc->pGiaMiniLut ); + pAbc->pGiaMiniLut = Gia_ManFromMiniLut2( (Mini_Lut_t *)p, &pAbc->vCopyMiniLut ); +// Abc_FrameUpdateGia( pAbc, pGia ); +} void * Abc_FrameGiaOutputMiniLut( Abc_Frame_t * pAbc ) { Mini_Lut_t * pRes = NULL; @@ -567,7 +692,7 @@ int * Abc_FrameReadMiniLutNameMapping( Abc_Frame_t * pAbc ) if ( pAbc->pGiaMiniAig == NULL || pAbc->pGiaMiniLut == NULL ) return NULL; pGia = Gia_ManDup2( pAbc->pGiaMiniAig, pAbc->pGiaMiniLut ); - //Gia_AigerWrite( pGia, "aig_m_lut.aig", 0, 0 ); + //Gia_AigerWrite( pGia, "aig_m_lut.aig", 0, 0, 0 ); // compute equivalences in this AIG pTemp = Gia_ManComputeGiaEquivs( pGia, nConfs, fVerbose ); Gia_ManStop( pTemp ); @@ -582,7 +707,526 @@ int * Abc_FrameReadMiniLutNameMapping( Abc_Frame_t * pAbc ) Gia_ManStop( pGia ); return pRes; } +int * Abc_FrameReadMiniLutSwitching( Abc_Frame_t * pAbc ) +{ + Vec_Int_t * vSwitching; + int i, iObj, * pRes = NULL; + if ( pAbc->pGiaMiniLut == NULL ) + { + printf( "GIA derived from MiniLut is not available.\n" ); + return NULL; + } + vSwitching = Gia_ManComputeSwitchProbs( pAbc->pGiaMiniLut, 48, 16, 0 ); + pRes = ABC_CALLOC( int, Vec_IntSize(pAbc->vCopyMiniLut) ); + Vec_IntForEachEntry( pAbc->vCopyMiniLut, iObj, i ) + if ( iObj >= 0 ) + pRes[i] = (int)(10000*Vec_FltEntry( (Vec_Flt_t *)vSwitching, Abc_Lit2Var(iObj) )); + Vec_IntFree( vSwitching ); + return pRes; +} +int * Abc_FrameReadMiniLutSwitchingPo( Abc_Frame_t * pAbc ) +{ + Vec_Int_t * vSwitching; + int i, iObj, * pRes = NULL; + if ( pAbc->pGiaMiniAig == NULL ) + { + printf( "GIA derived from MiniAIG is not available.\n" ); + return NULL; + } + vSwitching = Gia_ManComputeSwitchProbs( pAbc->pGiaMiniAig, 48, 16, 0 ); + pRes = ABC_CALLOC( int, Gia_ManCoNum(pAbc->pGiaMiniAig) ); + Gia_ManForEachCoDriverId( pAbc->pGiaMiniAig, iObj, i ) + pRes[i] = (int)(10000*Vec_FltEntry( (Vec_Flt_t *)vSwitching, iObj )); + Vec_IntFree( vSwitching ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [Returns equivalences of MiniAig nodes.] + + Description [The resulting array contains as many entries as there are objects + in the initial MiniAIG. If the i-th entry of the array is equal to -1, it means + that the i-th MiniAIG object is not equivalent to any other object. Otherwise, + the i-th entry contains the literal of the representative of the equivalence + class of objects, to which the i-th object belongs. The representative is defined + as the first object belonging to the equivalence class in the current topological + order. It can be the constant 0 node, a flop output or an internal node. It is + the user's responsibility to free the resulting array when it is not needed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManMapEquivAfterScorr( Gia_Man_t * p, Vec_Int_t * vMap ) +{ + Vec_Int_t * vRes = Vec_IntStartFull( Vec_IntSize(vMap) ); + Vec_Int_t * vGia2Mini = Vec_IntStartFull( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj, * pRepr; + int i, iObjLit, iReprLit, fCompl, iReprGia, iReprMini; + Vec_IntForEachEntry( vMap, iObjLit, i ) + { + if ( iObjLit == -1 ) + continue; +// if ( Gia_ObjHasRepr(p, Abc_Lit2Var(iObjLit)) && !Gia_ObjProved(p, Abc_Lit2Var(iObjLit)) ) +// continue; + iReprGia = Gia_ObjReprSelf( p, Abc_Lit2Var(iObjLit) ); + iReprMini = Vec_IntEntry( vGia2Mini, iReprGia ); + if ( iReprMini == -1 ) + { + Vec_IntWriteEntry( vGia2Mini, iReprGia, i ); + continue; + } + if ( iReprMini == i ) + continue; + assert( iReprMini < i ); + Vec_IntWriteEntry( vRes, i, iReprMini ); + } + Vec_IntFree( vGia2Mini ); + Gia_ManSetPhase( p ); + Vec_IntForEachEntry( vRes, iReprMini, i ) + { + if ( iReprMini == -1 ) + continue; + iObjLit = Vec_IntEntry(vMap, i); + iReprLit = Vec_IntEntry(vMap, iReprMini); + pObj = Gia_ManObj( p, Abc_Lit2Var(iObjLit) ); + pRepr = Gia_ManObj( p, Abc_Lit2Var(iReprLit) ); + fCompl = Abc_LitIsCompl(iObjLit) ^ Abc_LitIsCompl(iReprLit) ^ pObj->fPhase ^ pRepr->fPhase; + Vec_IntWriteEntry( vRes, i, Abc_Var2Lit(iReprMini, fCompl) ); + } + return vRes; +} +int * Abc_FrameReadMiniAigEquivClasses( Abc_Frame_t * pAbc ) +{ + Vec_Int_t * vRes; + int * pRes; + if ( pAbc->pGiaMiniAig == NULL ) + printf( "GIA derived from MiniAig is not available.\n" ); + if ( pAbc->vCopyMiniAig == NULL ) + printf( "Mapping of MiniAig nodes is not available.\n" ); + if ( pAbc->pGia2 == NULL ) + printf( "Internal GIA with equivalence classes is not available.\n" ); + if ( pAbc->pGia2->pReprs == NULL ) + { + printf( "Equivalence classes of internal GIA are not available.\n" ); + return NULL; + } + else if ( 0 ) + { + int i; + for ( i = 1; i < Gia_ManObjNum(pAbc->pGia2); i++ ) + if ( Gia_ObjHasRepr(pAbc->pGia2, i) ) + printf( "Obj %3d : Repr %3d Proved %d Failed %d\n", i, Gia_ObjRepr(pAbc->pGia2, i), Gia_ObjProved(pAbc->pGia2, i), Gia_ObjFailed(pAbc->pGia2, i) ); + } + if ( Gia_ManObjNum(pAbc->pGia2) != Gia_ManObjNum(pAbc->pGiaMiniAig) ) + printf( "Internal GIA with equivalence classes is not directly derived from MiniAig.\n" ); + // derive the set of equivalent node pairs + vRes = Gia_ManMapEquivAfterScorr( pAbc->pGia2, pAbc->vCopyMiniAig ); + pRes = Vec_IntReleaseArray( vRes ); + Vec_IntFree( vRes ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [Verifies equivalences of MiniAig nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_MiniAigReduce( Mini_Aig_t * p, int * pEquivs ) +{ + Gia_Man_t * pGia, * pTemp; + Vec_Int_t * vCopies; + int i, iGiaLit = 0, nNodes; + // get the number of nodes + nNodes = Mini_AigNodeNum(p); + // create ABC network + pGia = Gia_ManStart( nNodes ); + pGia->pName = Abc_UtilStrsav( "MiniAig" ); + // create mapping from MiniAIG objects into ABC objects + vCopies = Vec_IntAlloc( nNodes ); + Vec_IntPush( vCopies, 0 ); + // iterate through the objects + Gia_ManHashAlloc( pGia ); + for ( i = 1; i < nNodes; i++ ) + { + if ( Mini_AigNodeIsPi( p, i ) ) + iGiaLit = Gia_ManAppendCi(pGia); + else if ( Mini_AigNodeIsPo( p, i ) ) + iGiaLit = Gia_ManAppendCo(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i)); + else if ( Mini_AigNodeIsAnd( p, i ) ) + iGiaLit = Gia_ManHashAnd(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i), Gia_ObjFromMiniFanin1Copy(pGia, vCopies, p, i)); + else assert( 0 ); + if ( pEquivs[i] != -1 ) + iGiaLit = Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(pEquivs[i])), Abc_LitIsCompl(pEquivs[i]) ); + Vec_IntPush( vCopies, iGiaLit ); + } + Gia_ManHashStop( pGia ); + assert( Vec_IntSize(vCopies) == nNodes ); + Vec_IntFree( vCopies ); + Gia_ManSetRegNum( pGia, Mini_AigRegNum(p) ); + pGia = Gia_ManSeqCleanup( pTemp = pGia ); + Gia_ManStop( pTemp ); + return pGia; +} +Gia_Man_t * Gia_MiniAigMiter( Mini_Aig_t * p, int * pEquivs ) +{ + Gia_Man_t * pGia, * pTemp; + Vec_Int_t * vCopies; + int i, iGiaLit = 0, iGiaLit2, nNodes, iPos = 0, nPos = 0, Temp; + // get the number of nodes + nNodes = Mini_AigNodeNum(p); + // create ABC network + pGia = Gia_ManStart( 2 * nNodes ); + pGia->pName = Abc_UtilStrsav( "MiniAig" ); + // create mapping from MiniAIG objects into ABC objects + vCopies = Vec_IntAlloc( nNodes ); + Vec_IntPush( vCopies, 0 ); + // iterate through the objects + Gia_ManHashAlloc( pGia ); + for ( i = 1; i < nNodes; i++ ) + { + if ( Mini_AigNodeIsPi( p, i ) ) + iGiaLit = Gia_ManAppendCi(pGia); + else if ( Mini_AigNodeIsPo( p, i ) ) + { + nPos++; + Vec_IntPush( vCopies, -1 ); + continue; + } + else if ( Mini_AigNodeIsAnd( p, i ) ) + iGiaLit = Gia_ManHashAnd(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i), Gia_ObjFromMiniFanin1Copy(pGia, vCopies, p, i)); + else assert( 0 ); + Vec_IntPush( vCopies, iGiaLit ); + } + assert( Vec_IntSize(vCopies) == nNodes ); + assert( nPos > Mini_AigRegNum(p) ); + // create miters for each equiv class + for ( i = 1; i < nNodes; i++ ) + { + if ( pEquivs[i] == -1 ) + continue; + iGiaLit = Vec_IntEntry(vCopies, i); + iGiaLit2 = Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(pEquivs[i])), Abc_LitIsCompl(pEquivs[i]) ); + Gia_ManAppendCo( pGia, Gia_ManHashXor(pGia, iGiaLit, iGiaLit2) ); + } + // create flop inputs + Temp = Gia_ManCoNum(pGia); + for ( i = 1; i < nNodes; i++ ) + { + if ( !Mini_AigNodeIsPo( p, i ) ) + continue; + if ( iPos++ >= nPos - Mini_AigRegNum(p) ) + Gia_ManAppendCo(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i)); + } + assert( iPos == nPos ); + assert( Mini_AigRegNum(p) == Gia_ManCoNum(pGia) - Temp ); + Gia_ManSetRegNum( pGia, Mini_AigRegNum(p) ); + Gia_ManHashStop( pGia ); + Vec_IntFree( vCopies ); + pGia = Gia_ManCleanup( pTemp = pGia ); + Gia_ManStop( pTemp ); + return pGia; +} +void Gia_MiniAigVerify( Abc_Frame_t * pAbc, char * pFileName ) +{ + int * pEquivs; + Gia_Man_t * pGia; + char * pFileMiter = "mini_aig_miter.aig"; + char * pFileReduced = "mini_aig_reduced.aig"; + Mini_Aig_t * p = Mini_AigLoad( pFileName ); + Abc_FrameGiaInputMiniAig( pAbc, p ); + Cmd_CommandExecute( pAbc, "&ps; &scorr; &ps" ); + pEquivs = Abc_FrameReadMiniAigEquivClasses( pAbc ); + // dump miter for verification + pGia = Gia_MiniAigMiter( p, pEquivs ); + Gia_AigerWrite( pGia, pFileMiter, 0, 0, 0 ); + printf( "Dumped miter AIG in file \"%s\".\n", pFileMiter ); + Gia_ManStop( pGia ); + // dump reduced AIG + pGia = Gia_MiniAigReduce( p, pEquivs ); + Gia_AigerWrite( pGia, pFileReduced, 0, 0, 0 ); + printf( "Dumped reduced AIG in file \"%s\".\n", pFileReduced ); + Gia_ManStop( pGia ); + // cleanup + ABC_FREE( pEquivs ); + Mini_AigStop( p ); +} + +/**Function************************************************************* + + Synopsis [Collects supergate for the outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] +***********************************************************************/ +void Gia_MiniAigSuperGates_rec( Mini_Aig_t * p, int iObj, Vec_Int_t * vRes, Vec_Int_t * vMap ) +{ + int iFan0, iFan1; + if ( Mini_AigNodeIsPi(p, iObj) ) + { + assert( Vec_IntEntry(vMap, iObj) >= 0 ); + Vec_IntPush( vRes, Vec_IntEntry(vMap, iObj) ); + return; + } + iFan0 = Mini_AigNodeFanin0( p, iObj ); + iFan1 = Mini_AigNodeFanin1( p, iObj ); + assert( !Abc_LitIsCompl(iFan0) ); + assert( !Abc_LitIsCompl(iFan1) ); + Gia_MiniAigSuperGates_rec( p, Abc_Lit2Var(iFan0), vRes, vMap ); + Gia_MiniAigSuperGates_rec( p, Abc_Lit2Var(iFan1), vRes, vMap ); +} +Vec_Wec_t * Gia_MiniAigSuperGates( Mini_Aig_t * p ) +{ + Vec_Wec_t * vRes = Vec_WecStart( Mini_AigPoNum(p) ); + Vec_Int_t * vMap = Vec_IntStartFull( Mini_AigNodeNum(p) ); + int i, Index = 0; + Mini_AigForEachPi( p, i ) + Vec_IntWriteEntry( vMap, i, Index++ ); + assert( Index == Mini_AigPiNum(p) ); + Index = 0; + Mini_AigForEachPo( p, i ) + { + int iFan0 = Mini_AigNodeFanin0( p, i ); + assert( !Abc_LitIsCompl(iFan0) ); + Gia_MiniAigSuperGates_rec( p, Abc_Lit2Var(iFan0), Vec_WecEntry(vRes, Index++), vMap ); + } + assert( Index == Mini_AigPoNum(p) ); + Vec_IntFree( vMap ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Transform.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_MiniAigSuperPrintDouble( Vec_Int_t * p, int nPis ) +{ + int i, Entry; + printf( "\n" ); + Vec_IntForEachEntry( p, Entry, i ) + printf( "%d(%d) ", Entry%nPis, Entry/nPis ); + printf( " Total = %d\n", Vec_IntSize(p) ); +} +int Gia_MiniAigSuperMerge( Vec_Int_t * p, int nPis ) +{ + int i, k = 0, This, Prev = -1, fChange = 0; + Vec_IntForEachEntry( p, This, i ) + { + if ( Prev == This ) + { + Vec_IntWriteEntry( p, k++, (This/nPis+1)*nPis + This%nPis ); + Prev = -1; + fChange = 1; + } + else + { + if ( Prev != -1 ) + Vec_IntWriteEntry( p, k++, Prev ); + Prev = This; + } + } + if ( Prev != -1 ) + Vec_IntWriteEntry( p, k++, Prev ); + Vec_IntShrink( p, k ); + return fChange; +} +int Gia_MiniAigSuperPreprocess( Mini_Aig_t * p, Vec_Wec_t * vSuper, int nPis, int fVerbose ) +{ + Vec_Int_t * vRes; + int i, nIters, Multi = 1; + Vec_WecForEachLevel( vSuper, vRes, i ) + { + Vec_IntSort( vRes, 0 ); + if ( fVerbose ) + printf( "\nOutput %d\n", i ); + if ( fVerbose ) + Gia_MiniAigSuperPrintDouble( vRes, nPis ); + for ( nIters = 1; Gia_MiniAigSuperMerge(vRes, nPis); nIters++ ) + { + if ( fVerbose ) + Gia_MiniAigSuperPrintDouble( vRes, nPis ); + } + Multi = Abc_MaxInt( Multi, nIters ); + } + if ( fVerbose ) + printf( "Multi = %d.\n", Multi ); + return Multi; +} + +/**Function************************************************************* + + Synopsis [Derive AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_MiniAigSuperDeriveGia( Vec_Wec_t * p, int nPis, int Multi ) +{ + Gia_Man_t * pNew; + Vec_Int_t * vTemp, * vLits = Vec_IntAlloc( 100 ); + Vec_Int_t * vDrivers = Vec_IntAlloc(100); + int i, k, iObj, iLit, nInputs = nPis*Multi; + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "tree" ); + for ( i = 0; i < nInputs; i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + Vec_WecForEachLevel( p, vTemp, i ) + { + Vec_IntClear( vLits ); + Vec_IntForEachEntry( vTemp, iObj, k ) + { + assert( iObj < nInputs ); + Vec_IntPush( vLits, 2+2*((iObj%nPis)*Multi+iObj/nPis) ); + } + Vec_IntPush( vDrivers, Gia_ManHashAndMulti2(pNew, vLits) ); + } + Gia_ManHashStop( pNew ); + Vec_IntFree( vLits ); + Vec_IntForEachEntry( vDrivers, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Vec_IntFree( vDrivers ); + return pNew; +} +Gia_Man_t * Gia_MiniAigSuperDerive( char * pFileName, int fVerbose ) +{ + Mini_Aig_t * p = Mini_AigLoad( pFileName ); + Vec_Wec_t * vSuper = Gia_MiniAigSuperGates( p ); + int Multi = Gia_MiniAigSuperPreprocess( p, vSuper, Mini_AigPiNum(p), fVerbose ); + Gia_Man_t * pNew = Gia_MiniAigSuperDeriveGia( vSuper, Mini_AigPiNum(p), Multi ); + Vec_WecFree( vSuper ); + Mini_AigStop( p ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Process file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_MiniAigProcessFile() +{ + Vec_Int_t * vTriples = Vec_IntAlloc( 100 ); + char * pFileName = "test.txt"; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + printf( "Cannot open the file.\n" ); + else + { + int nLines = 0, nLinesAll = 0; + char * pToken; + char Buffer[1000]; + while ( fgets( Buffer, 1000, pFile ) != NULL ) + { + nLinesAll++; + if ( Buffer[0] != '#' ) + continue; + //printf( "%s", Buffer ); + nLines++; + pToken = strtok( Buffer+3, " \r\n\r+=" ); + while ( pToken ) + { + Vec_IntPush( vTriples, atoi(pToken) ); + pToken = strtok( NULL, " \r\n\r+=" ); + } + } + fclose( pFile ); + printf( "Collected %d (out of %d) lines.\n", nLines, nLinesAll ); + printf( "Entries = %d\n", Vec_IntSize(vTriples) ); + } + return vTriples; +} +void Gia_MiniAigGenerate_rec( Mini_Aig_t * p, Vec_Int_t * vTriples, int iObj, Vec_Int_t * vDefs, Vec_Int_t * vMap ) +{ + int Index, Entry0, Entry1, Entry2, Value; + if ( Vec_IntEntry(vMap, iObj) >= 0 ) + return; + Index = Vec_IntEntry( vDefs, iObj ); + Entry0 = Vec_IntEntry( vTriples, 3*Index+0 ); + Entry1 = Vec_IntEntry( vTriples, 3*Index+1 ); + Entry2 = Vec_IntEntry( vTriples, 3*Index+2 ); + Gia_MiniAigGenerate_rec( p, vTriples, Entry1, vDefs, vMap ); + Gia_MiniAigGenerate_rec( p, vTriples, Entry2, vDefs, vMap ); + assert( Vec_IntEntry(vMap, Entry1) >= 0 ); + assert( Vec_IntEntry(vMap, Entry2) >= 0 ); + Value = Mini_AigAnd( p, Vec_IntEntry(vMap, Entry1), Vec_IntEntry(vMap, Entry2) ); + Vec_IntWriteEntry( vMap, Entry0, Value ); +} +void Gia_MiniAigGenerateFromFile() +{ + Mini_Aig_t * p = Mini_AigStart(); + Vec_Int_t * vTriples = Gia_MiniAigProcessFile(); + Vec_Int_t * vDefs = Vec_IntStartFull( Vec_IntSize(vTriples) ); + Vec_Int_t * vMap = Vec_IntStartFull( Vec_IntSize(vTriples) ); + Vec_Int_t * vMapIn = Vec_IntStart( Vec_IntSize(vTriples) ); + Vec_Int_t * vMapOut = Vec_IntStart( Vec_IntSize(vTriples) ); + Vec_Int_t * vPis = Vec_IntAlloc( 100 ); + Vec_Int_t * vPos = Vec_IntAlloc( 100 ); + int i, ObjOut, ObjIn; + assert( Vec_IntSize(vTriples) % 3 == 0 ); + for ( i = 0; i < Vec_IntSize(vTriples)/3; i++ ) + { + int Entry0 = Vec_IntEntry(vTriples, 3*i+0); + int Entry1 = Vec_IntEntry(vTriples, 3*i+1); + int Entry2 = Vec_IntEntry(vTriples, 3*i+2); + Vec_IntWriteEntry( vDefs, Entry0, i ); + Vec_IntAddToEntry( vMapOut, Entry0, 1 ); + Vec_IntAddToEntry( vMapIn, Entry1, 1 ); + Vec_IntAddToEntry( vMapIn, Entry2, 1 ); + } + Vec_IntForEachEntryTwo( vMapOut, vMapIn, ObjOut, ObjIn, i ) + if ( !ObjOut && ObjIn ) + Vec_IntPush( vPis, i ); + else if ( ObjOut && !ObjIn ) + Vec_IntPush( vPos, i ); + Vec_IntForEachEntry( vPis, ObjIn, i ) + Vec_IntWriteEntry( vMap, ObjIn, Mini_AigCreatePi(p) ); + Vec_IntForEachEntry( vPos, ObjOut, i ) + Gia_MiniAigGenerate_rec( p, vTriples, ObjOut, vDefs, vMap ); + Vec_IntForEachEntry( vPos, ObjOut, i ) + { + assert( Vec_IntEntry(vMap, ObjOut) >= 0 ); + Mini_AigCreatePo( p, Vec_IntEntry(vMap, ObjOut) ); + } + Vec_IntFree( vTriples ); + Vec_IntFree( vDefs ); + Vec_IntFree( vMap ); + Vec_IntFree( vMapIn ); + Vec_IntFree( vMapOut ); + Vec_IntFree( vPis ); + Vec_IntFree( vPos ); + Mini_AigDump( p, "test.miniaig" ); + Mini_AigStop( p ); +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/abc/src/aig/gia/giaMuxes.c b/abc/src/aig/gia/giaMuxes.c index 4ce109f6ea8..ff542c30539 100644 --- a/abc/src/aig/gia/giaMuxes.c +++ b/abc/src/aig/gia/giaMuxes.c @@ -20,6 +20,7 @@ #include "gia.h" #include "misc/util/utilNam.h" +#include "misc/util/utilTruth.h" #include "misc/vec/vecWec.h" #include "misc/vec/vecHsh.h" @@ -146,6 +147,73 @@ Gia_Man_t * Gia_ManDupMuxes( Gia_Man_t * p, int Limit ) return pNew; } +/**Function************************************************************* + + Synopsis [Creates AIG with XORs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCreateXors( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; Gia_Obj_t * pObj, * pFan0, * pFan1; + Vec_Int_t * vRefs = Vec_IntStart( Gia_ManObjNum(p) ); + int i, iLit0, iLit1, nXors = 0, nObjs = 0; + Gia_ManForEachObj( p, pObj, i ) + pObj->fMark0 = 0; + Gia_ManForEachAnd( p, pObj, i ) + { + if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) + { + Vec_IntAddToEntry( vRefs, Gia_ObjId(p, Gia_Regular(pFan0)), 1 ); + Vec_IntAddToEntry( vRefs, Gia_ObjId(p, Gia_Regular(pFan1)), 1 ); + pObj->fMark0 = 1; + nXors++; + } + else + { + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId0(pObj, i), 1 ); + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId1(pObj, i), 1 ); + } + } + Gia_ManForEachCo( p, pObj, i ) + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId0p(p, pObj), 1 ); + Gia_ManForEachAnd( p, pObj, i ) + nObjs += Vec_IntEntry(vRefs, i) > 0; + pNew = Gia_ManStart( 1 + Gia_ManCiNum(p) + Gia_ManCoNum(p) + nObjs ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( pObj->fMark0 ) + { + Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1); + iLit0 = Abc_LitNotCond( Gia_Regular(pFan0)->Value, Gia_IsComplement(pFan0) ); + iLit1 = Abc_LitNotCond( Gia_Regular(pFan1)->Value, Gia_IsComplement(pFan1) ); + pObj->Value = Gia_ManAppendXorReal( pNew, iLit0, iLit1 ); + } + else if ( Vec_IntEntry(vRefs, i) > 0 ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + assert( pNew->nObjs == pNew->nObjsAlloc ); + pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjs ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Vec_IntFree( vRefs ); + //printf( "Created %d XORs.\n", nXors ); + return pNew; +} + /**Function************************************************************* Synopsis [Derives GIA without MUXes.] @@ -157,12 +225,12 @@ Gia_Man_t * Gia_ManDupMuxes( Gia_Man_t * p, int Limit ) SeeAlso [] ***********************************************************************/ -Gia_Man_t * Gia_ManDupNoMuxes( Gia_Man_t * p ) +Gia_Man_t * Gia_ManDupNoMuxes( Gia_Man_t * p, int fSkipBufs ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; - assert( p->pMuxes != NULL ); + assert( p->pMuxes != NULL || Gia_ManXorNum(p) ); // start the new manager pNew = Gia_ManStart( 5000 ); pNew->pName = Abc_UtilStrsav( p->pName ); @@ -176,7 +244,7 @@ Gia_Man_t * Gia_ManDupNoMuxes( Gia_Man_t * p ) else if ( Gia_ObjIsCo(pObj) ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); else if ( Gia_ObjIsBuf(pObj) ) - pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + pObj->Value = fSkipBufs ? Gia_ObjFanin0Copy(pObj) : Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); else if ( Gia_ObjIsMuxId(p, i) ) pObj->Value = Gia_ManHashMux( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); else if ( Gia_ObjIsXor(pObj) ) @@ -207,7 +275,7 @@ Gia_Man_t * Gia_ManDupMuxesTest( Gia_Man_t * p ) { Gia_Man_t * pNew, * pNew2; pNew = Gia_ManDupMuxes( p, 2 ); - pNew2 = Gia_ManDupNoMuxes( pNew ); + pNew2 = Gia_ManDupNoMuxes( pNew, 0 ); Gia_ManPrintStats( p, NULL ); Gia_ManPrintStats( pNew, NULL ); Gia_ManPrintStats( pNew2, NULL ); @@ -217,6 +285,80 @@ Gia_Man_t * Gia_ManDupMuxesTest( Gia_Man_t * p ) } +/**Function************************************************************* + + Synopsis [Test these procedures.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManMuxRestructure( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, nNodes = 0; + Vec_Bit_t * vUsed = Vec_BitStart( Gia_ManObjNum(p) ); + assert( !Gia_ManHasChoices(p) ); + assert( !Gia_ManHasMapping(p) ); + assert( p->pMuxes != NULL ); + ABC_FREE( p->pRefs ); + Gia_ManCreateRefs( p ); + // start the new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashStart( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsMuxId(p, i) && + Gia_ObjIsMuxId(p, Gia_ObjFaninId0(pObj, i)) && !Vec_BitEntry(vUsed, Gia_ObjFaninId0(pObj, i)) && + Gia_ObjIsMuxId(p, Gia_ObjFaninId1(pObj, i)) && !Vec_BitEntry(vUsed, Gia_ObjFaninId1(pObj, i)) && + Gia_ObjFaninId2(p, Gia_ObjFaninId0(pObj, i)) == Gia_ObjFaninId2(p, Gia_ObjFaninId1(pObj, i)) ) + { + Gia_Obj_t * pFan1 = Gia_ObjFanin1(pObj); + int Value0 = Gia_ManHashMux( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin2Copy(p, pFan1), Gia_ObjFanin0Copy(pObj) ); + int Value1 = Gia_ManHashMux( pNew, Value0, Gia_ObjFanin1Copy(pFan1), Gia_ObjFanin0Copy(pFan1) ); + pObj->Value = Gia_ManHashMux( pNew, Gia_ObjFanin2Copy(p, pObj), Value1, Value0 ); + Vec_BitWriteEntry( vUsed, Gia_ObjFaninId0(pObj, i), 1 ); + Vec_BitWriteEntry( vUsed, Gia_ObjFaninId1(pObj, i), 1 ); + Vec_BitWriteEntry( vUsed, i, 1 ); + nNodes++; + } + else if ( Gia_ObjIsMuxId(p, i) ) + pObj->Value = Gia_ManHashMux( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsXor(pObj) ) + pObj->Value = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + Vec_BitFree( vUsed ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // perform cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Gia_ManDupMuxRestructure( Gia_Man_t * p ) +{ + Gia_Man_t * pTemp, * pNew = Gia_ManDupMuxes( p, 2 ); + pNew = Gia_ManMuxRestructure( pTemp = pNew ); Gia_ManStop( pTemp ); + pNew = Gia_ManDupNoMuxes( pTemp = pNew, 0 ); Gia_ManStop( pTemp ); + return pNew; +} + /**Function************************************************************* Synopsis [Returns the size of MUX structure.] @@ -906,6 +1048,186 @@ void Gia_ManProfileStructures( Gia_Man_t * p, int nLimit, int fVerbose ) } } +/**Function************************************************************* + + Synopsis [Circuit restructuring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManMarkTfi_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( !Gia_ObjIsAnd(pObj) ) + return; + Gia_ManMarkTfi_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManMarkTfi_rec( p, Gia_ObjFanin1(pObj) ); +} +Vec_Int_t * Gia_ManFindSharedInputs( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObj2; int i, k, Value; + Vec_Int_t * vRes = Vec_IntStart( Gia_ManCiNum(p) ); + Gia_ManForEachCo( p, pObj, i ) + { + Gia_ManIncrementTravId( p ); + Gia_ManMarkTfi_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCi( p, pObj2, k ) + if ( Gia_ObjIsTravIdCurrent(p, pObj2) ) + Vec_IntAddToEntry( vRes, k, 1 ); + } + k = 0; + Vec_IntForEachEntry( vRes, Value, i ) + if ( Value == Gia_ManCoNum(p) ) + Vec_IntWriteEntry( vRes, k++, i ); + Vec_IntShrink( vRes, k ); + //printf( "Found %d candidate inputs.\n", Vec_IntSize(vRes) ); + if ( Vec_IntSize(vRes) == 0 || Vec_IntSize(vRes) > 10 ) + Vec_IntFreeP(&vRes); + return vRes; +} +Vec_Wec_t * Gia_ManFindCofs( Gia_Man_t * p, Vec_Int_t * vRes, Gia_Man_t ** ppNew ) +{ + Gia_Obj_t * pObj; + Vec_Wec_t * vCofs = Vec_WecStart( 1 << Vec_IntSize(vRes) ); + int Value, i, m, nMints = 1 << Vec_IntSize(vRes); + Gia_Man_t * pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Gia_ManHashAlloc( pNew ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + assert( Vec_IntSize(vRes) < Gia_ManCiNum(p) ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + for ( m = 0; m < nMints; m++ ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vCofs, m ); + Vec_IntForEachEntry( vRes, Value, i ) + Gia_ManCi(p, Value)->Value = (unsigned)((m >> i) & 1); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + Vec_IntPush( vLayer, Gia_ObjFanin0Copy(pObj) ); + assert( Vec_IntSize(vLayer) == Gia_ManCoNum(p) ); + //printf( "%3d : ", m ); Vec_IntPrint( vLayer ); + } + if ( ppNew != NULL ) + *ppNew = pNew; + return vCofs; +} +Vec_Int_t * Gia_ManFindEquivClasses( Vec_Wec_t * vCofs ) +{ + Vec_Int_t * vVec; int i, k, Lev; + Vec_Int_t * vMap = Vec_IntAlloc( Vec_WecSize(vCofs) ); + Vec_Int_t * vUnique = Vec_IntAlloc( Vec_WecSize(vCofs) ); + Vec_WecForEachLevel( vCofs, vVec, i ) + { + Vec_IntForEachEntry( vUnique, Lev, k ) + if ( Vec_IntEqual(vVec, Vec_WecEntry(vCofs, Lev)) ) + break; + Vec_IntPush( vMap, k ); + if ( k == Vec_IntSize(vUnique) ) + Vec_IntPush( vUnique, i ); + } + //printf( "Found %d equiv clasess.\n", Vec_IntSize(vUnique) ); + //Vec_IntPrint( vUnique ); + Vec_IntFree( vUnique ); + assert( Vec_IntSize(vMap) == Vec_WecSize(vCofs) ); + //Vec_IntPrint( vMap ); + return vMap; +} +int Gia_ManFindMuxTree_rec( Gia_Man_t * pNew, int * pCtrl, int nCtrl, Vec_Int_t * vData, int Shift ) +{ + int iLit0, iLit1; + if ( nCtrl-- == 0 ) + return Vec_IntEntry( vData, Shift ); + iLit0 = Gia_ManFindMuxTree_rec( pNew, pCtrl, nCtrl, vData, Shift ); + iLit1 = Gia_ManFindMuxTree_rec( pNew, pCtrl, nCtrl, vData, Shift + (1<> i) & 1 ) + Abc_TtSetBit( pTruth, k ); + if ( nBits < 6 ) + pTruth[0] = Abc_Tt6Stretch( pTruth[0], Vec_IntSize(vIns) ); + Vec_IntPush( vBits, Kit_TruthToGia(pNew, (unsigned*)pTruth, Vec_IntSize(vIns), vMemory, vLeaves, 1) ); + //printf( "Bit %d : ", i ); Dau_DsdPrintFromTruth( pTruth, Vec_IntSize(vIns) ); + } + for ( i = 0; i < nValues; i++ ) + { + int Cof = Vec_IntFind(vMap, i); + assert( Cof >= 0 && Cof < Vec_WecSize(vCofs) ); + Vec_IntWriteEntry( vUsed, Cof, 1 ); + } + for ( i = 0; i < nOuts; i++ ) + { + Vec_Int_t * vLevel; + Vec_IntClear( vData ); + Vec_WecForEachLevel( vCofs, vLevel, k ) + if ( Vec_IntEntry(vUsed, k) ) + Vec_IntPush( vData, Vec_IntEntry(vLevel, i) ); + while ( Vec_IntSize(vData) < (1 << nBits) ) + Vec_IntPush( vData, 0 ); + assert( Vec_IntSize(vData) == (1 << nBits) ); + assert( Vec_IntSize(vBits) == nBits ); + Value = Gia_ManFindMuxTree_rec( pNew, Vec_IntArray(vBits), Vec_IntSize(vBits), vData, 0 ); + Gia_ManAppendCo( pNew, Value ); + } + ABC_FREE( pTruth ); + Vec_IntFree( vUsed ); + Vec_IntFree( vBits ); + Vec_IntFree( vData ); + Vec_IntFree( vLeaves ); + Vec_IntFree( vMemory ); +} +Gia_Man_t * Gia_ManCofStructure( Gia_Man_t * p ) +{ + Gia_Man_t * pNew = NULL; + Vec_Int_t * vIns = Gia_ManFindSharedInputs( p ); + Vec_Wec_t * vCfs = vIns ? Gia_ManFindCofs( p, vIns, &pNew ) : NULL; + Vec_Int_t * vMap = vCfs ? Gia_ManFindEquivClasses( vCfs ) : NULL; + if ( vMap && Abc_Base2Log(Vec_IntFindMax(vMap)+1) < Vec_IntSize(vIns) ) + { + Gia_Man_t * pTemp; + Gia_ManFindDerive( pNew, Gia_ManCoNum(p), vIns, vCfs, vMap ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + } + else + Gia_ManStopP( &pNew ); + Vec_WecFreeP( &vCfs ); + Vec_IntFreeP( &vMap ); + Vec_IntFreeP( &vIns ); + return pNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/abc/src/aig/gia/giaNewBdd.h b/abc/src/aig/gia/giaNewBdd.h new file mode 100644 index 00000000000..6d75f4d99c5 --- /dev/null +++ b/abc/src/aig/gia/giaNewBdd.h @@ -0,0 +1,839 @@ +/**CFile**************************************************************** + + FileName [giaNewBdd.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of transduction method.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 2023.] + + Revision [$Id: giaNewBdd.h,v 1.00 2023/05/10 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__gia__giaNewBdd_h +#define ABC__aig__gia__giaNewBdd_h + +#include +#include +#include +#include +#include + +ABC_NAMESPACE_CXX_HEADER_START + +namespace NewBdd { + + typedef unsigned short var; + typedef int bvar; + typedef unsigned lit; + typedef unsigned short ref; + typedef unsigned long long size; + typedef unsigned edge; + typedef unsigned uniq; + typedef unsigned cac; + static inline var VarMax() { return std::numeric_limits::max(); } + static inline bvar BvarMax() { return std::numeric_limits::max(); } + static inline lit LitMax() { return std::numeric_limits::max(); } + static inline ref RefMax() { return std::numeric_limits::max(); } + static inline size SizeMax() { return std::numeric_limits::max(); } + static inline uniq UniqHash(lit Arg0, lit Arg1) { return Arg0 + 4256249 * Arg1; } + static inline cac CacHash(lit Arg0, lit Arg1) { return Arg0 + 4256249 * Arg1; } + + class Cache { + private: + cac nSize; + cac nMax; + cac Mask; + size nLookups; + size nHits; + size nThold; + double HitRate; + int nVerbose; + std::vector vCache; + + public: + Cache(int nCacheSizeLog, int nCacheMaxLog, int nVerbose): nVerbose(nVerbose) { + if(nCacheMaxLog < nCacheSizeLog) + throw std::invalid_argument("nCacheMax must not be smaller than nCacheSize"); + nMax = (cac)1 << nCacheMaxLog; + if(!(nMax << 1)) + throw std::length_error("Memout (nCacheMax) in init"); + nSize = (cac)1 << nCacheSizeLog; + if(nVerbose) + std::cout << "Allocating " << nSize << " cache entries" << std::endl; + vCache.resize(nSize * 3); + Mask = nSize - 1; + nLookups = 0; + nHits = 0; + nThold = (nSize == nMax)? SizeMax(): nSize; + HitRate = 1; + } + ~Cache() { + if(nVerbose) + std::cout << "Free " << nSize << " cache entries" << std::endl; + } + inline lit Lookup(lit x, lit y) { + nLookups++; + if(nLookups > nThold) { + double NewHitRate = (double)nHits / nLookups; + if(nVerbose >= 2) + std::cout << "Cache Hits: " << std::setw(10) << nHits << ", " + << "Lookups: " << std::setw(10) << nLookups << ", " + << "Rate: " << std::setw(10) << NewHitRate + << std::endl; + if(NewHitRate > HitRate) + Resize(); + if(nSize == nMax) + nThold = SizeMax(); + else { + nThold <<= 1; + if(!nThold) + nThold = SizeMax(); + } + HitRate = NewHitRate; + } + cac i = (CacHash(x, y) & Mask) * 3; + if(vCache[i] == x && vCache[i + 1] == y) { + if(nVerbose >= 3) + std::cout << "Cache hit: " + << "x = " << std::setw(10) << x << ", " + << "y = " << std::setw(10) << y << ", " + << "z = " << std::setw(10) << vCache[i + 2] << ", " + << "hash = " << std::hex << (CacHash(x, y) & Mask) << std::dec + << std::endl; + nHits++; + return vCache[i + 2]; + } + return LitMax(); + } + inline void Insert(lit x, lit y, lit z) { + cac i = (CacHash(x, y) & Mask) * 3; + vCache[i] = x; + vCache[i + 1] = y; + vCache[i + 2] = z; + if(nVerbose >= 3) + std::cout << "Cache ent: " + << "x = " << std::setw(10) << x << ", " + << "y = " << std::setw(10) << y << ", " + << "z = " << std::setw(10) << z << ", " + << "hash = " << std::hex << (CacHash(x, y) & Mask) << std::dec + << std::endl; + } + inline void Clear() { + std::fill(vCache.begin(), vCache.end(), 0); + } + void Resize() { + cac nSizeOld = nSize; + nSize <<= 1; + if(nVerbose >= 2) + std::cout << "Reallocating " << nSize << " cache entries" << std::endl; + vCache.resize(nSize * 3); + Mask = nSize - 1; + for(cac j = 0; j < nSizeOld; j++) { + cac i = j * 3; + if(vCache[i] || vCache[i + 1]) { + cac hash = (CacHash(vCache[i], vCache[i + 1]) & Mask) * 3; + vCache[hash] = vCache[i]; + vCache[hash + 1] = vCache[i + 1]; + vCache[hash + 2] = vCache[i + 2]; + if(nVerbose >= 3) + std::cout << "Cache mov: " + << "x = " << std::setw(10) << vCache[i] << ", " + << "y = " << std::setw(10) << vCache[i + 1] << ", " + << "z = " << std::setw(10) << vCache[i + 2] << ", " + << "hash = " << std::hex << (CacHash(vCache[i], vCache[i + 1]) & Mask) << std::dec + << std::endl; + } + } + } + }; + + struct Param { + int nObjsAllocLog; + int nObjsMaxLog; + int nUniqueSizeLog; + double UniqueDensity; + int nCacheSizeLog; + int nCacheMaxLog; + int nCacheVerbose; + bool fCountOnes; + int nGbc; + bvar nReo; + double MaxGrowth; + bool fReoVerbose; + int nVerbose; + std::vector *pVar2Level; + Param() { + nObjsAllocLog = 20; + nObjsMaxLog = 25; + nUniqueSizeLog = 10; + UniqueDensity = 4; + nCacheSizeLog = 15; + nCacheMaxLog = 20; + nCacheVerbose = 0; + fCountOnes = false; + nGbc = 0; + nReo = BvarMax(); + MaxGrowth = 1.2; + fReoVerbose = false; + nVerbose = 0; + pVar2Level = NULL; + } + }; + + class Man { + private: + var nVars; + bvar nObjs; + bvar nObjsAlloc; + bvar nObjsMax; + bvar RemovedHead; + int nGbc; + bvar nReo; + double MaxGrowth; + bool fReoVerbose; + int nVerbose; + std::vector vVars; + std::vector Var2Level; + std::vector Level2Var; + std::vector vObjs; + std::vector vNexts; + std::vector vMarks; + std::vector vRefs; + std::vector vEdges; + std::vector vOneCounts; + std::vector vUniqueMasks; + std::vector vUniqueCounts; + std::vector vUniqueTholds; + std::vector > vvUnique; + Cache *cache; + + public: + inline lit Bvar2Lit(bvar a) const { return (lit)a << 1; } + inline lit Bvar2Lit(bvar a, bool c) const { return ((lit)a << 1) ^ (lit)c; } + inline bvar Lit2Bvar(lit x) const { return (bvar)(x >> 1); } + inline var VarOfBvar(bvar a) const { return vVars[a]; } + inline lit ThenOfBvar(bvar a) const { return vObjs[Bvar2Lit(a)]; } + inline lit ElseOfBvar(bvar a) const { return vObjs[Bvar2Lit(a, true)]; } + inline ref RefOfBvar(bvar a) const { return vRefs[a]; } + inline lit Const0() const { return (lit)0; } + inline lit Const1() const { return (lit)1; } + inline bool IsConst0(lit x) const { return x == Const0(); } + inline bool IsConst1(lit x) const { return x == Const1(); } + inline lit IthVar(var v) const { return Bvar2Lit((bvar)v + 1); } + inline lit LitRegular(lit x) const { return x & ~(lit)1; } + inline lit LitIrregular(lit x) const { return x | (lit)1; } + inline lit LitNot(lit x) const { return x ^ (lit)1; } + inline lit LitNotCond(lit x, bool c) const { return x ^ (lit)c; } + inline bool LitIsCompl(lit x) const { return x & (lit)1; } + inline bool LitIsEq(lit x, lit y) const { return x == y; } + inline var Var(lit x) const { return vVars[Lit2Bvar(x)]; } + inline var Level(lit x) const { return Var2Level[Var(x)]; } + inline lit Then(lit x) const { return LitNotCond(vObjs[LitRegular(x)], LitIsCompl(x)); } + inline lit Else(lit x) const { return LitNotCond(vObjs[LitIrregular(x)], LitIsCompl(x)); } + 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"); + if(LitIsCompl(x)) + return std::pow(2.0, nVars) - vOneCounts[Lit2Bvar(x)]; + return vOneCounts[Lit2Bvar(x)]; + } + + public: + inline void IncRef(lit x) { if(!vRefs.empty() && Ref(x) != RefMax()) vRefs[Lit2Bvar(x)]++; } + inline void DecRef(lit x) { if(!vRefs.empty() && Ref(x) != RefMax()) vRefs[Lit2Bvar(x)]--; } + + private: + inline bool Mark(lit x) const { return vMarks[Lit2Bvar(x)]; } + inline edge Edge(lit x) const { return vEdges[Lit2Bvar(x)]; } + inline void SetMark(lit x) { vMarks[Lit2Bvar(x)] = true; } + inline void ResetMark(lit x) { vMarks[Lit2Bvar(x)] = false; } + inline void IncEdge(lit x) { vEdges[Lit2Bvar(x)]++; } + inline void DecEdge(lit x) { vEdges[Lit2Bvar(x)]--; } + inline bool MarkOfBvar(bvar a) const { return vMarks[a]; } + inline edge EdgeOfBvar(bvar a) const { return vEdges[a]; } + inline void SetVarOfBvar(bvar a, var v) { vVars[a] = v; } + inline void SetThenOfBvar(bvar a, lit x) { vObjs[Bvar2Lit(a)] = x; } + inline void SetElseOfBvar(bvar a, lit x) { vObjs[Bvar2Lit(a, true)] = x; } + inline void SetMarkOfBvar(bvar a) { vMarks[a] = true; } + inline void ResetMarkOfBvar(bvar a) { vMarks[a] = false; } + inline void RemoveBvar(bvar a) { + var v = VarOfBvar(a); + SetVarOfBvar(a, VarMax()); + std::vector::iterator q = vvUnique[v].begin() + (UniqHash(ThenOfBvar(a), ElseOfBvar(a)) & vUniqueMasks[v]); + for(; *q; q = vNexts.begin() + *q) + if(*q == a) + break; + bvar next = vNexts[*q]; + vNexts[*q] = RemovedHead; + RemovedHead = *q; + *q = next; + vUniqueCounts[v]--; + } + + private: + void SetMark_rec(lit x) { + if(x < 2 || Mark(x)) + return; + SetMark(x); + SetMark_rec(Then(x)); + SetMark_rec(Else(x)); + } + void ResetMark_rec(lit x) { + if(x < 2 || !Mark(x)) + return; + ResetMark(x); + ResetMark_rec(Then(x)); + ResetMark_rec(Else(x)); + } + bvar CountNodes_rec(lit x) { + if(x < 2 || Mark(x)) + return 0; + SetMark(x); + return 1 + CountNodes_rec(Then(x)) + CountNodes_rec(Else(x)); + } + void CountEdges_rec(lit x) { + if(x < 2) + return; + IncEdge(x); + if(Mark(x)) + return; + SetMark(x); + CountEdges_rec(Then(x)); + CountEdges_rec(Else(x)); + } + void CountEdges() { + vEdges.resize(nObjsAlloc); + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + CountEdges_rec(Bvar2Lit(a)); + for(bvar a = 1; a <= (bvar)nVars; a++) + vEdges[a]++; + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + ResetMark_rec(Bvar2Lit(a)); + } + + public: + bool Resize() { + if(nObjsAlloc == nObjsMax) + return false; + lit nObjsAllocLit = (lit)nObjsAlloc << 1; + if(nObjsAllocLit > (lit)BvarMax()) + nObjsAlloc = BvarMax(); + else + nObjsAlloc = (bvar)nObjsAllocLit; + if(nVerbose >= 2) + std::cout << "Reallocating " << nObjsAlloc << " nodes" << std::endl; + vVars.resize(nObjsAlloc); + vObjs.resize((lit)nObjsAlloc * 2); + vNexts.resize(nObjsAlloc); + vMarks.resize(nObjsAlloc); + if(!vRefs.empty()) + vRefs.resize(nObjsAlloc); + if(!vEdges.empty()) + vEdges.resize(nObjsAlloc); + if(!vOneCounts.empty()) + vOneCounts.resize(nObjsAlloc); + return true; + } + void ResizeUnique(var v) { + uniq nUniqueSize, nUniqueSizeOld; + nUniqueSize = nUniqueSizeOld = vvUnique[v].size(); + nUniqueSize <<= 1; + if(!nUniqueSize) { + vUniqueTholds[v] = BvarMax(); + return; + } + if(nVerbose >= 2) + std::cout << "Reallocating " << nUniqueSize << " unique table entries for Var " << v << std::endl; + vvUnique[v].resize(nUniqueSize); + vUniqueMasks[v] = nUniqueSize - 1; + for(uniq i = 0; i < nUniqueSizeOld; i++) { + std::vector::iterator q, tail, tail1, tail2; + q = tail1 = vvUnique[v].begin() + i; + tail2 = q + nUniqueSizeOld; + while(*q) { + uniq hash = UniqHash(ThenOfBvar(*q), ElseOfBvar(*q)) & vUniqueMasks[v]; + if(hash == i) + tail = tail1; + else + tail = tail2; + if(tail != q) + *tail = *q, *q = 0; + q = vNexts.begin() + *tail; + if(tail == tail1) + tail1 = q; + else + tail2 = q; + } + } + vUniqueTholds[v] <<= 1; + if((lit)vUniqueTholds[v] > (lit)BvarMax()) + vUniqueTholds[v] = BvarMax(); + } + bool Gbc() { + if(nVerbose >= 2) + std::cout << "Garbage collect" << std::endl; + if(!vEdges.empty()) { + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(!EdgeOfBvar(a) && VarOfBvar(a) != VarMax()) + RemoveBvar(a); + } else { + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + SetMark_rec(Bvar2Lit(a)); + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(!MarkOfBvar(a) && VarOfBvar(a) != VarMax()) + RemoveBvar(a); + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + ResetMark_rec(Bvar2Lit(a)); + } + cache->Clear(); + return RemovedHead; + } + + private: + inline lit UniqueCreateInt(var v, lit x1, lit x0) { + std::vector::iterator p, q; + p = q = vvUnique[v].begin() + (UniqHash(x1, x0) & vUniqueMasks[v]); + for(; *q; q = vNexts.begin() + *q) + if(VarOfBvar(*q) == v && ThenOfBvar(*q) == x1 && ElseOfBvar(*q) == x0) + return Bvar2Lit(*q); + bvar next = *p; + if(nObjs < nObjsAlloc) + *p = nObjs++; + else if(RemovedHead) + *p = RemovedHead, RemovedHead = vNexts[*p]; + else + return LitMax(); + SetVarOfBvar(*p, v); + SetThenOfBvar(*p, x1); + SetElseOfBvar(*p, x0); + vNexts[*p] = next; + if(!vOneCounts.empty()) + vOneCounts[*p] = OneCount(x1) / 2 + OneCount(x0) / 2; + if(nVerbose >= 3) { + std::cout << "Create node " << std::setw(10) << *p << ": " + << "Var = " << std::setw(6) << v << ", " + << "Then = " << std::setw(10) << x1 << ", " + << "Else = " << std::setw(10) << x0; + if(!vOneCounts.empty()) + std::cout << ", Ones = " << std::setw(10) << vOneCounts[*q]; + std::cout << std::endl; + } + vUniqueCounts[v]++; + if(vUniqueCounts[v] > vUniqueTholds[v]) { + bvar a = *p; + ResizeUnique(v); + return Bvar2Lit(a); + } + return Bvar2Lit(*p); + } + inline lit UniqueCreate(var v, lit x1, lit x0) { + if(x1 == x0) + return x1; + lit x; + while(true) { + if(!LitIsCompl(x0)) + x = UniqueCreateInt(v, x1, x0); + else + x = UniqueCreateInt(v, LitNot(x1), LitNot(x0)); + if(x == LitMax()) { + bool fRemoved = false; + if(nGbc > 1) + fRemoved = Gbc(); + if(!Resize() && !fRemoved && (nGbc != 1 || !Gbc())) + throw std::length_error("Memout (node)"); + } else + break; + } + return LitIsCompl(x0)? LitNot(x): x; + } + lit And_rec(lit x, lit y) { + if(x == 0 || y == 1) + return x; + if(x == 1 || y == 0) + return y; + if(Lit2Bvar(x) == Lit2Bvar(y)) + return (x == y)? x: 0; + if(x > y) + std::swap(x, y); + lit z = cache->Lookup(x, y); + if(z != LitMax()) + return z; + var v; + lit x0, x1, y0, y1; + if(Level(x) < Level(y)) + v = Var(x), x1 = Then(x), x0 = Else(x), y0 = y1 = y; + else if(Level(x) > Level(y)) + v = Var(y), x0 = x1 = x, y1 = Then(y), y0 = Else(y); + else + v = Var(x), x1 = Then(x), x0 = Else(x), y1 = Then(y), y0 = Else(y); + lit z1 = And_rec(x1, y1); + IncRef(z1); + lit z0 = And_rec(x0, y0); + IncRef(z0); + z = UniqueCreate(v, z1, z0); + DecRef(z1); + DecRef(z0); + cache->Insert(x, y, z); + return z; + } + + private: + bvar Swap(var i) { + var v1 = Level2Var[i]; + var v2 = Level2Var[i + 1]; + bvar f = 0; + bvar diff = 0; + for(std::vector::iterator p = vvUnique[v1].begin(); p != vvUnique[v1].end(); p++) { + std::vector::iterator q = p; + while(*q) { + if(!EdgeOfBvar(*q)) { + SetVarOfBvar(*q, VarMax()); + bvar next = vNexts[*q]; + vNexts[*q] = RemovedHead; + RemovedHead = *q; + *q = next; + vUniqueCounts[v1]--; + continue; + } + lit f1 = ThenOfBvar(*q); + lit f0 = ElseOfBvar(*q); + if(Var(f1) == v2 || Var(f0) == v2) { + DecEdge(f1); + if(Var(f1) == v2 && !Edge(f1)) + DecEdge(Then(f1)), DecEdge(Else(f1)), diff--; + DecEdge(f0); + if(Var(f0) == v2 && !Edge(f0)) + DecEdge(Then(f0)), DecEdge(Else(f0)), diff--; + bvar next = vNexts[*q]; + vNexts[*q] = f; + f = *q; + *q = next; + vUniqueCounts[v1]--; + continue; + } + q = vNexts.begin() + *q; + } + } + while(f) { + lit f1 = ThenOfBvar(f); + lit f0 = ElseOfBvar(f); + lit f00, f01, f10, f11; + if(Var(f1) == v2) + f11 = Then(f1), f10 = Else(f1); + else + f10 = f11 = f1; + if(Var(f0) == v2) + f01 = Then(f0), f00 = Else(f0); + else + f00 = f01 = f0; + if(f11 == f01) + f1 = f11; + else { + f1 = UniqueCreate(v1, f11, f01); + if(!Edge(f1)) + IncEdge(f11), IncEdge(f01), diff++; + } + IncEdge(f1); + IncRef(f1); + if(f10 == f00) + f0 = f10; + else { + f0 = UniqueCreate(v1, f10, f00); + if(!Edge(f0)) + IncEdge(f10), IncEdge(f00), diff++; + } + IncEdge(f0); + DecRef(f1); + SetVarOfBvar(f, v2); + SetThenOfBvar(f, f1); + SetElseOfBvar(f, f0); + std::vector::iterator q = vvUnique[v2].begin() + (UniqHash(f1, f0) & vUniqueMasks[v2]); + lit next = vNexts[f]; + vNexts[f] = *q; + *q = f; + vUniqueCounts[v2]++; + f = next; + } + Var2Level[v1] = i + 1; + Var2Level[v2] = i; + Level2Var[i] = v2; + Level2Var[i + 1] = v1; + return diff; + } + void Sift() { + bvar count = CountNodes(); + std::vector sift_order(nVars); + for(var v = 0; v < nVars; v++) + sift_order[v] = v; + for(var i = 0; i < nVars; i++) { + var max_j = i; + for(var j = i + 1; j < nVars; j++) + if(vUniqueCounts[sift_order[j]] > vUniqueCounts[sift_order[max_j]]) + max_j = j; + if(max_j != i) + std::swap(sift_order[max_j], sift_order[i]); + } + for(var v = 0; v < nVars; v++) { + bvar lev = Var2Level[sift_order[v]]; + bool UpFirst = lev < (bvar)(nVars / 2); + bvar min_lev = lev; + bvar min_diff = 0; + bvar diff = 0; + bvar thold = count * (MaxGrowth - 1); + if(fReoVerbose) + std::cout << "Sift " << sift_order[v] << " : Level = " << lev << " Count = " << count << " Thold = " << thold << std::endl; + if(UpFirst) { + lev--; + for(; lev >= 0; lev--) { + diff += Swap(lev); + if(fReoVerbose) + std::cout << "\tSwap " << lev << " : Diff = " << diff << " Thold = " << thold << std::endl; + if(diff < min_diff) + min_lev = lev, min_diff = diff, thold = (count + diff) * (MaxGrowth - 1); + else if(diff > thold) { + lev--; + break; + } + } + lev++; + } + for(; lev < (bvar)nVars - 1; lev++) { + diff += Swap(lev); + if(fReoVerbose) + std::cout << "\tSwap " << lev << " : Diff = " << diff << " Thold = " << thold << std::endl; + if(diff <= min_diff) + min_lev = lev + 1, min_diff = diff, thold = (count + diff) * (MaxGrowth - 1); + else if(diff > thold) { + lev++; + break; + } + } + lev--; + if(UpFirst) { + for(; lev >= min_lev; lev--) { + diff += Swap(lev); + if(fReoVerbose) + std::cout << "\tSwap " << lev << " : Diff = " << diff << " Thold = " << thold << std::endl; + } + } else { + for(; lev >= 0; lev--) { + diff += Swap(lev); + if(fReoVerbose) + std::cout << "\tSwap " << lev << " : Diff = " << diff << " Thold = " << thold << std::endl; + if(diff <= min_diff) + min_lev = lev, min_diff = diff, thold = (count + diff) * (MaxGrowth - 1); + else if(diff > thold) { + lev--; + break; + } + } + lev++; + for(; lev < min_lev; lev++) { + diff += Swap(lev); + if(fReoVerbose) + std::cout << "\tSwap " << lev << " : Diff = " << diff << " Thold = " << thold << std::endl; + } + } + count += min_diff; + if(fReoVerbose) + std::cout << "Sifted " << sift_order[v] << " : Level = " << min_lev << " Count = " << count << " Thold = " << thold << std::endl; + } + } + + public: + Man(int nVars_, Param p) { + nVerbose = p.nVerbose; + // parameter sanity check + if(p.nObjsMaxLog < p.nObjsAllocLog) + throw std::invalid_argument("nObjsMax must not be smaller than nObjsAlloc"); + if(nVars_ >= (int)VarMax()) + throw std::length_error("Memout (nVars) in init"); + nVars = nVars_; + lit nObjsMaxLit = (lit)1 << p.nObjsMaxLog; + if(!nObjsMaxLit) + throw std::length_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"); + if(nObjsAllocLit > (lit)BvarMax()) + nObjsAlloc = BvarMax(); + else + nObjsAlloc = (bvar)nObjsAllocLit; + if(nObjsAlloc <= (bvar)nVars) + throw std::invalid_argument("nObjsAlloc must be larger than nVars"); + uniq nUniqueSize = (uniq)1 << p.nUniqueSizeLog; + if(!nUniqueSize) + throw std::length_error("Memout (nUniqueSize) in init"); + // allocation + if(nVerbose) + std::cout << "Allocating " << nObjsAlloc << " nodes and " << nVars << " x " << nUniqueSize << " unique table entries" << std::endl; + vVars.resize(nObjsAlloc); + vObjs.resize((lit)nObjsAlloc * 2); + vNexts.resize(nObjsAlloc); + vMarks.resize(nObjsAlloc); + vvUnique.resize(nVars); + vUniqueMasks.resize(nVars); + vUniqueCounts.resize(nVars); + vUniqueTholds.resize(nVars); + for(var v = 0; v < nVars; v++) { + vvUnique[v].resize(nUniqueSize); + vUniqueMasks[v] = nUniqueSize - 1; + if((lit)(nUniqueSize * p.UniqueDensity) > (lit)BvarMax()) + vUniqueTholds[v] = BvarMax(); + else + vUniqueTholds[v] = (bvar)(nUniqueSize * p.UniqueDensity); + } + if(p.fCountOnes) { + if(nVars > 1023) + throw std::length_error("nVars must be less than 1024 to count ones"); + vOneCounts.resize(nObjsAlloc); + } + // set up cache + cache = new Cache(p.nCacheSizeLog, p.nCacheMaxLog, p.nCacheVerbose); + // create nodes for variables + nObjs = 1; + vVars[0] = VarMax(); + for(var v = 0; v < nVars; v++) + UniqueCreateInt(v, 1, 0); + // set up variable order + Var2Level.resize(nVars); + Level2Var.resize(nVars); + for(var v = 0; v < nVars; v++) { + if(p.pVar2Level) + Var2Level[v] = (*p.pVar2Level)[v]; + else + Var2Level[v] = v; + Level2Var[Var2Level[v]] = v; + } + // set other parameters + RemovedHead = 0; + nGbc = p.nGbc; + nReo = p.nReo; + MaxGrowth = p.MaxGrowth; + fReoVerbose = p.fReoVerbose; + if(nGbc || nReo != BvarMax()) + vRefs.resize(nObjsAlloc); + } + ~Man() { + if(nVerbose) { + std::cout << "Free " << nObjsAlloc << " nodes (" << nObjs << " live nodes)" << std::endl; + std::cout << "Free {"; + std::string delim; + for(var v = 0; v < nVars; v++) { + std::cout << delim << vvUnique[v].size(); + delim = ", "; + } + std::cout << "} unique table entries" << std::endl; + if(!vRefs.empty()) + std::cout << "Free " << vRefs.size() << " refs" << std::endl; + } + delete cache; + } + void Reorder() { + if(nVerbose >= 2) + std::cout << "Reorder" << std::endl; + int nGbc_ = nGbc; + nGbc = 0; + CountEdges(); + Sift(); + vEdges.clear(); + cache->Clear(); + nGbc = nGbc_; + } + inline lit And(lit x, lit y) { + if(nObjs > nReo) { + Reorder(); + while(nReo < nObjs) { + nReo <<= 1; + if((lit)nReo > (lit)BvarMax()) + nReo = BvarMax(); + } + } + return And_rec(x, y); + } + inline lit Or(lit x, lit y) { + return LitNot(And(LitNot(x), LitNot(y))); + } + + public: + void SetRef(std::vector const &vLits) { + vRefs.clear(); + vRefs.resize(nObjsAlloc); + for(size_t i = 0; i < vLits.size(); i++) + IncRef(vLits[i]); + } + void TurnOffReo() { + nReo = BvarMax(); + if(!nGbc) + vRefs.clear(); + } + bvar CountNodes() { + bvar count = 1; + if(!vEdges.empty()) { + for(bvar a = 1; a < nObjs; a++) + if(EdgeOfBvar(a)) + count++; + return count; + } + for(bvar a = 1; a <= (bvar)nVars; a++) { + count++; + SetMarkOfBvar(a); + } + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + count += CountNodes_rec(Bvar2Lit(a)); + for(bvar a = 1; a <= (bvar)nVars; a++) + ResetMarkOfBvar(a); + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + ResetMark_rec(Bvar2Lit(a)); + return count; + } + bvar CountNodes(std::vector const &vLits) { + bvar count = 1; + for(size_t i = 0; i < vLits.size(); i++) + count += CountNodes_rec(vLits[i]); + for(size_t i = 0; i < vLits.size(); i++) + ResetMark_rec(vLits[i]); + return count; + } + void PrintStats() { + bvar nRemoved = 0; + bvar a = RemovedHead; + while(a) + a = vNexts[a], nRemoved++; + bvar nLive = 1; + for(var v = 0; v < nVars; v++) + nLive += vUniqueCounts[v]; + std::cout << "ref: " << std::setw(10) << (vRefs.empty()? 0: CountNodes()) << ", " + << "used: " << std::setw(10) << nObjs << ", " + << "live: " << std::setw(10) << nLive << ", " + << "dead: " << std::setw(10) << nRemoved << ", " + << "alloc: " << std::setw(10) << nObjsAlloc + << std::endl; + } + }; + +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/abc/src/aig/gia/giaNewTt.h b/abc/src/aig/gia/giaNewTt.h new file mode 100644 index 00000000000..494b8636b68 --- /dev/null +++ b/abc/src/aig/gia/giaNewTt.h @@ -0,0 +1,281 @@ +/**CFile**************************************************************** + + FileName [giaNewTt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of transduction method.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 2023.] + + Revision [$Id: giaNewTt.h,v 1.00 2023/05/10 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__gia__giaNewTt_h +#define ABC__aig__gia__giaNewTt_h + +#include +#include +#include +#include +#include + +ABC_NAMESPACE_CXX_HEADER_START + +namespace NewTt { + + typedef int bvar; + typedef unsigned lit; + typedef unsigned short ref; + typedef unsigned long long size; + + static inline bvar BvarMax() { return std::numeric_limits::max(); } + static inline lit LitMax() { return std::numeric_limits::max(); } + static inline ref RefMax() { return std::numeric_limits::max(); } + static inline size SizeMax() { return std::numeric_limits::max(); } + + struct Param { + int nObjsAllocLog; + int nObjsMaxLog; + int nVerbose; + bool fCountOnes; + int nGbc; + int nReo; // dummy + Param() { + nObjsAllocLog = 15; + nObjsMaxLog = 20; + nVerbose = 0; + fCountOnes = false; + nGbc = 0; + nReo = BvarMax(); + } + }; + + class Man { + private: + typedef unsigned long long word; + typedef std::bitset<64> bsw; + static inline int ww() { return 64; } // word width + static inline int lww() { return 6; } // log word width + static inline word one() {return 0xffffffffffffffffull; } + static inline word vars(int i) { + static const word vars[] = {0xaaaaaaaaaaaaaaaaull, + 0xccccccccccccccccull, + 0xf0f0f0f0f0f0f0f0ull, + 0xff00ff00ff00ff00ull, + 0xffff0000ffff0000ull, + 0xffffffff00000000ull}; + return vars[i]; + } + static inline word ones(int i) { + static const word ones[] = {0x0000000000000001ull, + 0x0000000000000003ull, + 0x000000000000000full, + 0x00000000000000ffull, + 0x000000000000ffffull, + 0x00000000ffffffffull, + 0xffffffffffffffffull}; + return ones[i]; + } + + private: + int nVars; + bvar nObjs; + bvar nObjsAlloc; + bvar nObjsMax; + size nSize; + size nTotalSize; + std::vector vVals; + std::vector vDeads; + std::vector vRefs; + int nGbc; + int nVerbose; + + public: + inline lit Bvar2Lit(bvar a) const { return (lit)a << 1; } + inline bvar Lit2Bvar(lit x) const { return (bvar)(x >> 1); } + inline lit IthVar(int v) const { return ((lit)v + 1) << 1; } + inline lit LitNot(lit x) const { return x ^ (lit)1; } + inline lit LitNotCond(lit x, bool c) const { return x ^ (lit)c; } + inline bool LitIsCompl(lit x) const { return x & (lit)1; } + inline ref Ref(lit x) const { return vRefs[Lit2Bvar(x)]; } + inline lit Const0() const { return (lit)0; } + inline lit Const1() const { return (lit)1; } + inline bool IsConst0(lit x) const { + bvar a = Lit2Bvar(x); + word c = LitIsCompl(x)? one(): 0; + for(size j = 0; j < nSize; j++) + if(vVals[nSize * a + j] ^ c) + return false; + return true; + } + inline bool IsConst1(lit x) const { + bvar a = Lit2Bvar(x); + word c = LitIsCompl(x)? one(): 0; + for(size j = 0; j < nSize; j++) + if(~(vVals[nSize * a + j] ^ c)) + return false; + return true; + } + inline bool LitIsEq(lit x, lit y) const { + if(x == y) + return true; + if(x == LitMax() || y == LitMax()) + return false; + bvar xvar = Lit2Bvar(x); + bvar yvar = Lit2Bvar(y); + word c = LitIsCompl(x) ^ LitIsCompl(y)? one(): 0; + for(size j = 0; j < nSize; j++) + if(vVals[nSize * xvar + j] ^ vVals[nSize * yvar + j] ^ c) + return false; + return true; + } + inline size OneCount(lit x) const { + bvar a = Lit2Bvar(x); + size count = 0; + if(nVars > 6) { + for(size j = 0; j < nSize; j++) + count += bsw(vVals[nSize * a + j]).count(); + } else + count = bsw(vVals[nSize * a] & ones(nVars)).count(); + return LitIsCompl(x)? ((size)1 << nVars) - count: count; + } + + public: + inline void IncRef(lit x) { if(!vRefs.empty() && Ref(x) != RefMax()) vRefs[Lit2Bvar(x)]++; } + inline void DecRef(lit x) { if(!vRefs.empty() && Ref(x) != RefMax()) vRefs[Lit2Bvar(x)]--; } + + public: + bool Resize() { + if(nObjsAlloc == nObjsMax) + return false; + lit nObjsAllocLit = (lit)nObjsAlloc << 1; + if(nObjsAllocLit > (lit)BvarMax()) + nObjsAlloc = BvarMax(); + else + nObjsAlloc = (bvar)nObjsAllocLit; + nTotalSize = nTotalSize << 1; + if(nVerbose >= 2) + std::cout << "Reallocating " << nObjsAlloc << " nodes" << std::endl; + vVals.resize(nTotalSize); + if(!vRefs.empty()) + vRefs.resize(nObjsAlloc); + return true; + } + bool Gbc() { + if(nVerbose >= 2) + std::cout << "Garbage collect" << std::endl; + for(bvar a = nVars + 1; a < nObjs; a++) + if(!vRefs[a]) + vDeads.push_back(a); + return vDeads.size(); + } + + public: + Man(int nVars, Param p): nVars(nVars) { + if(p.nObjsMaxLog < p.nObjsAllocLog) + throw std::invalid_argument("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"); + if(!(nSize << p.nObjsMaxLog)) + throw std::length_error("Memout (nObjsMax) in init"); + lit nObjsMaxLit = (lit)1 << p.nObjsMaxLog; + if(!nObjsMaxLit) + throw std::length_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"); + if(nObjsAllocLit > (lit)BvarMax()) + nObjsAlloc = BvarMax(); + else + nObjsAlloc = (bvar)nObjsAllocLit; + if(nObjsAlloc <= (bvar)nVars) + throw std::invalid_argument("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"); + nObjs = 1; + for(int i = 0; i < 6 && i < nVars; i++) { + for(size j = 0; j < nSize; j++) + vVals[nSize * nObjs + j] = vars(i); + nObjs++; + } + for(int i = 0; i < nVars - 6; i++) { + for(size j = 0; j < nSize; j += (2ull << i)) + for(size k = 0; k < (1ull << i); k++) + vVals[nSize * nObjs + j + k] = one(); + nObjs++; + } + nVerbose = p.nVerbose; + nGbc = p.nGbc; + if(nGbc || p.nReo != BvarMax()) + vRefs.resize(nObjsAlloc); + } + inline lit And(lit x, lit y) { + bvar xvar = Lit2Bvar(x); + bvar yvar = Lit2Bvar(y); + word xcompl = LitIsCompl(x)? one(): 0; + word ycompl = LitIsCompl(y)? one(): 0; + unsigned j; + if(nObjs >= nObjsAlloc && vDeads.empty()) { + bool fRemoved = false; + if(nGbc > 1) + fRemoved = Gbc(); + if(!Resize() && !fRemoved && (nGbc != 1 || !Gbc())) + throw std::length_error("Memout (node)"); + } + bvar zvar; + if(nObjs < nObjsAlloc) + zvar = nObjs++; + else + zvar = vDeads.back(), vDeads.resize(vDeads.size() - 1); + for(j = 0; j < nSize; j++) + vVals[nSize * zvar + j] = (vVals[nSize * xvar + j] ^ xcompl) & (vVals[nSize * yvar + j] ^ ycompl); + return zvar << 1; + } + inline lit Or(lit x, lit y) { + return LitNot(And(LitNot(x), LitNot(y))); + } + void Reorder() {} // dummy + + public: + void SetRef(std::vector const &vLits) { + vRefs.clear(); + vRefs.resize(nObjsAlloc); + for(size_t i = 0; i < vLits.size(); i++) + IncRef(vLits[i]); + } + void TurnOffReo() { + if(!nGbc) + vRefs.clear(); + } + void PrintNode(lit x) const { + bvar a = Lit2Bvar(x); + word c = LitIsCompl(x)? one(): 0; + for(size j = 0; j < nSize; j++) + std::cout << bsw(vVals[nSize * a + j] ^ c); + std::cout << std::endl; + } + }; + +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/abc/src/aig/gia/giaNf.c b/abc/src/aig/gia/giaNf.c index 9a374ddad33..eaaf24e9e0d 100644 --- a/abc/src/aig/gia/giaNf.c +++ b/abc/src/aig/gia/giaNf.c @@ -2407,11 +2407,13 @@ Gia_Man_t * Nf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) } Nf_ManFixPoDrivers( p ); pNew = Nf_ManDeriveMapping( p ); +/* if ( pPars->fAreaOnly ) { int Sbm_ManTestSat( void * pMan ); Sbm_ManTestSat( p ); } +*/ Nf_StoDelete( p ); return pNew; } diff --git a/abc/src/aig/gia/giaPat2.c b/abc/src/aig/gia/giaPat2.c new file mode 100644 index 00000000000..3f928e4dddb --- /dev/null +++ b/abc/src/aig/gia/giaPat2.c @@ -0,0 +1,1360 @@ +/**CFile**************************************************************** + + FileName [giaPat2.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Pattern generation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaPat2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/vec/vecHsh.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satStore.h" +#include "misc/util/utilTruth.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Min_Man_t_ Min_Man_t; +struct Min_Man_t_ +{ + int nCis; + int nCos; + int FirstAndLit; + int FirstCoLit; + Vec_Int_t vFans; + Vec_Str_t vValsN; + Vec_Str_t vValsL; + Vec_Int_t vVis; + Vec_Int_t vPat; +}; + +static inline int Min_ManCiNum( Min_Man_t * p ) { return p->nCis; } +static inline int Min_ManCoNum( Min_Man_t * p ) { return p->nCos; } +static inline int Min_ManObjNum( Min_Man_t * p ) { return Vec_IntSize(&p->vFans) >> 1; } +static inline int Min_ManAndNum( Min_Man_t * p ) { return Min_ManObjNum(p) - p->nCis - p->nCos - 1; } + +static inline int Min_ManCi( Min_Man_t * p, int i ) { return 1 + i; } +static inline int Min_ManCo( Min_Man_t * p, int i ) { return Min_ManObjNum(p) - Min_ManCoNum(p) + i; } + +static inline int Min_ObjIsCi( Min_Man_t * p, int i ) { return i > 0 && i <= Min_ManCiNum(p); } +static inline int Min_ObjIsNode( Min_Man_t * p, int i ) { return i > Min_ManCiNum(p) && i < Min_ManObjNum(p) - Min_ManCoNum(p); } +static inline int Min_ObjIsAnd( Min_Man_t * p, int i ) { return Min_ObjIsNode(p, i) && Vec_IntEntry(&p->vFans, 2*i) < Vec_IntEntry(&p->vFans, 2*i+1); } +static inline int Min_ObjIsXor( Min_Man_t * p, int i ) { return Min_ObjIsNode(p, i) && Vec_IntEntry(&p->vFans, 2*i) > Vec_IntEntry(&p->vFans, 2*i+1); } +static inline int Min_ObjIsBuf( Min_Man_t * p, int i ) { return Min_ObjIsNode(p, i) && Vec_IntEntry(&p->vFans, 2*i) ==Vec_IntEntry(&p->vFans, 2*i+1); } +static inline int Min_ObjIsCo( Min_Man_t * p, int i ) { return i >= Min_ManObjNum(p) - Min_ManCoNum(p) && i < Min_ManObjNum(p); } + +static inline int Min_ObjLit( Min_Man_t * p, int i, int n ) { return Vec_IntEntry(&p->vFans, i + i + n); } +static inline int Min_ObjLit0( Min_Man_t * p, int i ) { return Vec_IntEntry(&p->vFans, i + i + 0); } +static inline int Min_ObjLit1( Min_Man_t * p, int i ) { return Vec_IntEntry(&p->vFans, i + i + 1); } +static inline int Min_ObjCioId( Min_Man_t * p, int i ) { assert( i && !Min_ObjIsNode(p, i) ); return Min_ObjLit1(p, i); } + +static inline int Min_ObjFan0( Min_Man_t * p, int i ) { return Abc_Lit2Var( Min_ObjLit0(p, i) ); } +static inline int Min_ObjFan1( Min_Man_t * p, int i ) { return Abc_Lit2Var( Min_ObjLit1(p, i) ); } + +static inline int Min_ObjFanC0( Min_Man_t * p, int i ) { return Abc_LitIsCompl( Min_ObjLit0(p, i) ); } +static inline int Min_ObjFanC1( Min_Man_t * p, int i ) { return Abc_LitIsCompl( Min_ObjLit1(p, i) ); } + +static inline char Min_ObjValN( Min_Man_t * p, int i ) { return Vec_StrEntry(&p->vValsN, i); } +static inline void Min_ObjSetValN( Min_Man_t * p, int i, char v ){ Vec_StrWriteEntry(&p->vValsN, i, v); } + +static inline char Min_LitValL( Min_Man_t * p, int i ) { return Vec_StrEntry(&p->vValsL, i); } +static inline void Min_LitSetValL( Min_Man_t * p, int i, char v ){ assert(v==0 || v==1); Vec_StrWriteEntry(&p->vValsL, i, v); Vec_StrWriteEntry(&p->vValsL, i^1, (char)!v); Vec_IntPush(&p->vVis, Abc_Lit2Var(i)); } +static inline void Min_ObjCleanValL( Min_Man_t * p, int i ) { ((short *)Vec_StrArray(&p->vValsL))[i] = 0x0202; } +static inline void Min_ObjMarkValL( Min_Man_t * p, int i ) { ((short *)Vec_StrArray(&p->vValsL))[i] |= 0x0404; } +static inline void Min_ObjMark2ValL( Min_Man_t * p, int i ) { ((short *)Vec_StrArray(&p->vValsL))[i] |= 0x0808; } +static inline void Min_ObjUnmark2ValL( Min_Man_t * p, int i ) { ((short *)Vec_StrArray(&p->vValsL))[i] &= 0xF7F7; } + +static inline int Min_LitIsCi( Min_Man_t * p, int v ) { return v > 1 && v < p->FirstAndLit; } +static inline int Min_LitIsNode( Min_Man_t * p, int v ) { return v >= p->FirstAndLit && v < p->FirstCoLit; } +static inline int Min_LitIsCo( Min_Man_t * p, int v ) { return v >= p->FirstCoLit; } + +static inline int Min_LitIsAnd( int v, int v0, int v1 ) { return Abc_LitIsCompl(v) ^ (v0 < v1); } +static inline int Min_LitIsXor( int v, int v0, int v1 ) { return Abc_LitIsCompl(v) ^ (v0 > v1); } +static inline int Min_LitIsBuf( int v, int v0, int v1 ) { return v0 == v1; } + +static inline int Min_LitFan( Min_Man_t * p, int v ) { return Vec_IntEntry(&p->vFans, v); } +static inline int Min_LitFanC( Min_Man_t * p, int v ) { return Abc_LitIsCompl( Min_LitFan(p, v) ); } + +static inline void Min_ManStartValsN( Min_Man_t * p ) { Vec_StrGrow(&p->vValsN, Vec_IntCap(&p->vFans)/2); Vec_StrFill(&p->vValsN, Min_ManObjNum(p), 2); } +static inline void Min_ManStartValsL( Min_Man_t * p ) { Vec_StrGrow(&p->vValsL, Vec_IntCap(&p->vFans)); Vec_StrFill(&p->vValsL, Vec_IntSize(&p->vFans), 2); } +static inline int Min_ManCheckCleanValsL( Min_Man_t * p ) { int i; char c; Vec_StrForEachEntry( &p->vValsL, c, i ) if ( c != 2 ) return 0; return 1; } +static inline void Min_ManCleanVisitedValL( Min_Man_t * p ) { int i, iObj; Vec_IntForEachEntry(&p->vVis, iObj, i) Min_ObjCleanValL(p, iObj); Vec_IntClear(&p->vVis); } + + +#define Min_ManForEachObj( p, i ) \ + for ( i = 0; i < Min_ManObjNum(p); i++ ) +#define Min_ManForEachCi( p, i ) \ + for ( i = 1; i <= Min_ManCiNum(p); i++ ) +#define Min_ManForEachCo( p, i ) \ + for ( i = Min_ManObjNum(p) - Min_ManCoNum(p); i < Min_ManObjNum(p); i++ ) +#define Min_ManForEachAnd( p, i ) \ + for ( i = 1 + Min_ManCiNum(p); i < Min_ManObjNum(p) - Min_ManCoNum(p); i++ ) + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Min_Man_t * Min_ManStart( int nObjMax ) +{ + Min_Man_t * p = ABC_CALLOC( Min_Man_t, 1 ); + Vec_IntGrow( &p->vFans, nObjMax ); + Vec_IntPushTwo( &p->vFans, -1, -1 ); + return p; +} +static inline void Min_ManStop( Min_Man_t * p ) +{ + Vec_IntErase( &p->vFans ); + Vec_StrErase( &p->vValsN ); + Vec_StrErase( &p->vValsL ); + Vec_IntErase( &p->vVis ); + Vec_IntErase( &p->vPat ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Min_ManAppendObj( Min_Man_t * p, int iLit0, int iLit1 ) +{ + int iLit = Vec_IntSize(&p->vFans); + Vec_IntPushTwo( &p->vFans, iLit0, iLit1 ); + return iLit; +} +static inline int Min_ManAppendCi( Min_Man_t * p ) +{ + p->nCis++; + p->FirstAndLit = Vec_IntSize(&p->vFans) + 2; + return Min_ManAppendObj( p, 0, p->nCis-1 ); +} +static inline int Min_ManAppendCo( Min_Man_t * p, int iLit0 ) +{ + p->nCos++; + if ( p->FirstCoLit == 0 ) + p->FirstCoLit = Vec_IntSize(&p->vFans); + return Min_ManAppendObj( p, iLit0, p->nCos-1 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Min_ManFromGia_rec( Min_Man_t * pNew, Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Min_ManFromGia_rec( pNew, p, Gia_ObjFaninId0(pObj, iObj) ); + Min_ManFromGia_rec( pNew, p, Gia_ObjFaninId1(pObj, iObj) ); + pObj->Value = Min_ManAppendObj( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Min_Man_t * Min_ManFromGia( Gia_Man_t * p, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i; + Min_Man_t * pNew = Min_ManStart( Gia_ManObjNum(p) ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Min_ManAppendCi( pNew ); + if ( vOuts == NULL ) + { + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Min_ManAppendObj( pNew, Gia_ObjFaninLit0(pObj, i), Gia_ObjFaninLit1(pObj, i) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Min_ManAppendCo( pNew, Gia_ObjFaninLit0p(p, pObj) ); + } + else + { + Gia_ManForEachCoVec( vOuts, p, pObj, i ) + Min_ManFromGia_rec( pNew, p, Gia_ObjFaninId0p(p, pObj) ); + Gia_ManForEachCoVec( vOuts, p, pObj, i ) + Min_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline char Min_XsimNot( char Val ) +{ + if ( Val < 2 ) + return Val ^ 1; + return 2; +} +static inline char Min_XsimXor( char Val0, char Val1 ) +{ + if ( Val0 < 2 && Val1 < 2 ) + return Val0 ^ Val1; + return 2; +} +static inline char Min_XsimAnd( char Val0, char Val1 ) +{ + if ( Val0 == 0 || Val1 == 0 ) + return 0; + if ( Val0 == 1 && Val1 == 1 ) + return 1; + return 2; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char Min_LitVerify_rec( Min_Man_t * p, int iLit ) +{ + char Val = Min_LitValL(p, iLit); + if ( Val == 2 && Min_LitIsNode(p, iLit) ) // unassigned + { + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitVerify_rec( p, iLit0 ); + char Val1 = Min_LitVerify_rec( p, iLit1 ); + assert( Val0 < 3 && Val1 < 3 ); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + else + Vec_IntPush( &p->vVis, Abc_Lit2Var(iLit) ); + Min_ObjMark2ValL( p, Abc_Lit2Var(iLit) ); + } + return Val&3; +} +char Min_LitVerify( Min_Man_t * p, int iLit, Vec_Int_t * vLits ) +{ + int i, Entry; char Res; + if ( iLit < 2 ) return 1; + assert( !Min_LitIsCo(p, iLit) ); + //assert( Min_ManCheckCleanValsL(p) ); + assert( Vec_IntSize(&p->vVis) == 0 ); + Vec_IntForEachEntry( vLits, Entry, i ) + Min_LitSetValL( p, Entry, 1 ); // ms notation + Res = Min_LitVerify_rec( p, iLit ); + Min_ManCleanVisitedValL( p ); + return Res; +} + +void Min_LitMinimize( Min_Man_t * p, int iLit, Vec_Int_t * vLits ) +{ + int i, iObj, iTemp; char Res; + Vec_IntClear( &p->vPat ); + if ( iLit < 2 ) return; + assert( !Min_LitIsCo(p, iLit) ); + //assert( Min_ManCheckCleanValsL(p) ); + assert( Vec_IntSize(&p->vVis) == 0 ); + Vec_IntForEachEntry( vLits, iTemp, i ) + Min_LitSetValL( p, iTemp, 1 ); // ms notation + Res = Min_LitVerify_rec( p, iLit ); + assert( Res == 1 ); + Min_ObjMarkValL( p, Abc_Lit2Var(iLit) ); + Vec_IntForEachEntryReverse( &p->vVis, iObj, i ) + { + int iLit = Abc_Var2Lit( iObj, 0 ); + int Value = 7 & Min_LitValL(p, iLit); + if ( Value >= 4 ) + { + if ( Min_LitIsCi(p, iLit) ) + Vec_IntPush( &p->vPat, Abc_LitNotCond(iLit, !(Value&1)) ); + else + { + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL( p, iLit0 ); + char Val1 = Min_LitValL( p, iLit1 ); + if ( Value&1 ) // value == 1 + { + assert( (Val0&1) && (Val1&1) ); + Min_ObjMarkValL( p, Abc_Lit2Var(iLit0) ); + Min_ObjMarkValL( p, Abc_Lit2Var(iLit1) ); + } + else // value == 0 + { + int Zero0 = !(Val0&3); + int Zero1 = !(Val1&3); + assert( Zero0 || Zero1 ); + if ( Zero0 && !Zero1 ) + Min_ObjMarkValL( p, Abc_Lit2Var(iLit0) ); + else if ( !Zero0 && Zero1 ) + Min_ObjMarkValL( p, Abc_Lit2Var(iLit1) ); + else if ( Val0 == 4 && Val1 != 4 ) + Min_ObjMarkValL( p, Abc_Lit2Var(iLit0) ); + else if ( Val1 == 4 && Val0 != 4 ) + Min_ObjMarkValL( p, Abc_Lit2Var(iLit1) ); + else if ( Abc_Random(0) & 1 ) + Min_ObjMarkValL( p, Abc_Lit2Var(iLit0) ); + else + Min_ObjMarkValL( p, Abc_Lit2Var(iLit1) ); + } + } + } + Min_ObjCleanValL( p, Abc_Lit2Var(iLit) ); + } + Vec_IntClear( &p->vVis ); + //Min_ManCleanVisitedValL( p ); + //assert( Min_LitVerify(p, iLit, &p->vPat) == 1 ); + assert( Vec_IntSize(&p->vPat) <= Vec_IntSize(vLits) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline char Min_LitIsImplied1( Min_Man_t * p, int iLit ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} +static inline char Min_LitIsImplied2( Min_Man_t * p, int iLit ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) + Val0 = Min_LitIsImplied1(p, iLit0); + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + Val1 = Min_LitIsImplied1(p, iLit1); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} +static inline char Min_LitIsImplied3( Min_Man_t * p, int iLit ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) + Val0 = Min_LitIsImplied2(p, iLit0); + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + Val1 = Min_LitIsImplied2(p, iLit1); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} +static inline char Min_LitIsImplied4( Min_Man_t * p, int iLit ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) + Val0 = Min_LitIsImplied3(p, iLit0); + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + Val1 = Min_LitIsImplied3(p, iLit1); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} +static inline char Min_LitIsImplied5( Min_Man_t * p, int iLit ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) + Val0 = Min_LitIsImplied4(p, iLit0); + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + Val1 = Min_LitIsImplied4(p, iLit1); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} + +// this recursive procedure is about 10% slower +char Min_LitIsImplied_rec( Min_Man_t * p, int iLit, int Depth ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Depth > 0 ); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Depth > 1 && Val0 == 2 && Min_LitIsNode(p, iLit0) ) + { + Val0 = Min_LitIsImplied_rec(p, iLit0, Depth-1); + Val1 = Min_LitValL(p, iLit1); + } + if ( Depth > 1 && Val1 == 2 && Min_LitIsNode(p, iLit1) ) + { + Val1 = Min_LitIsImplied_rec(p, iLit1, Depth-1); + Val0 = Min_LitValL(p, iLit0); + } + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} +int Min_LitJustify_rec( Min_Man_t * p, int iLit ) +{ + int Res = 1, LitValue = !Abc_LitIsCompl(iLit); + int Val = (int)Min_LitValL(p, iLit); + if ( Val < 2 ) // assigned + return Val == LitValue; + // unassigned + if ( Min_LitIsCi(p, iLit) ) + Vec_IntPush( &p->vPat, iLit ); // ms notation + else + { + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + { + if ( Val0 < 2 && Val1 < 2 ) + Res = LitValue == (Val0 ^ Val1); + else if ( Val0 < 2 ) + Res = Min_LitJustify_rec(p, iLit1^Val0^!LitValue); + else if ( Val1 < 2 ) + Res = Min_LitJustify_rec(p, iLit0^Val1^!LitValue); + else if ( Abc_Random(0) & 1 ) + Res = Min_LitJustify_rec(p, iLit0) && Min_LitJustify_rec(p, iLit1^ LitValue); + else + Res = Min_LitJustify_rec(p, iLit0^1) && Min_LitJustify_rec(p, iLit1^!LitValue); + assert( !Res || LitValue == Min_XsimXor(Min_LitValL(p, iLit0), Min_LitValL(p, iLit1)) ); + } + else if ( LitValue ) // value 1 + { + if ( Val0 == 0 || Val1 == 0 ) + Res = 0; + else if ( Val0 == 1 && Val1 == 1 ) + Res = 1; + else if ( Val0 == 1 ) + Res = Min_LitJustify_rec(p, iLit1); + else if ( Val1 == 1 ) + Res = Min_LitJustify_rec(p, iLit0); + else + Res = Min_LitJustify_rec(p, iLit0) && Min_LitJustify_rec(p, iLit1); + assert( !Res || 1 == Min_XsimAnd(Min_LitValL(p, iLit0), Min_LitValL(p, iLit1)) ); + } + else // value 0 + { +/* + int Depth = 3; + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) + { + Val0 = Min_LitIsImplied_rec(p, iLit0, Depth); + Val1 = Min_LitValL(p, iLit1); + } + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + { + Val1 = Min_LitIsImplied_rec(p, iLit1, Depth); + Val0 = Min_LitValL(p, iLit0); + } +*/ + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) + { + Val0 = Min_LitIsImplied3(p, iLit0); + Val1 = Min_LitValL(p, iLit1); + } + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + { + Val1 = Min_LitIsImplied3(p, iLit1); + Val0 = Min_LitValL(p, iLit0); + } + if ( Val0 == 0 || Val1 == 0 ) + Res = 1; + else if ( Val0 == 1 && Val1 == 1 ) + Res = 0; + else if ( Val0 == 1 ) + Res = Min_LitJustify_rec(p, iLit1^1); + else if ( Val1 == 1 ) + Res = Min_LitJustify_rec(p, iLit0^1); + else if ( Abc_Random(0) & 1 ) + //else if ( (p->Random >> (iLit & 0x1F)) & 1 ) + Res = Min_LitJustify_rec(p, iLit0^1); + else + Res = Min_LitJustify_rec(p, iLit1^1); + //Val0 = Min_LitValL(p, iLit0); + //Val1 = Min_LitValL(p, iLit1); + assert( !Res || 0 == Min_XsimAnd(Min_LitValL(p, iLit0), Min_LitValL(p, iLit1)) ); + } + } + if ( Res ) + Min_LitSetValL( p, iLit, 1 ); + return Res; +} +int Min_LitJustify( Min_Man_t * p, int iLit ) +{ + int Res, fCheck = 0; + Vec_IntClear( &p->vPat ); + if ( iLit < 2 ) return 1; + assert( !Min_LitIsCo(p, iLit) ); + //assert( Min_ManCheckCleanValsL(p) ); + assert( Vec_IntSize(&p->vVis) == 0 ); + //p->Random = Abc_Random(0); + Res = Min_LitJustify_rec( p, iLit ); + Min_ManCleanVisitedValL( p ); + if ( Res ) + { + if ( fCheck && Min_LitVerify(p, iLit, &p->vPat) != 1 ) + printf( "Verification FAILED for literal %d.\n", iLit ); + //else + // printf( "Verification succeeded for literal %d.\n", iLit ); + } + //else + // printf( "Could not justify literal %d.\n", iLit ); + return Res; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Min_TargGenerateCexes( Min_Man_t * p, Vec_Int_t * vCoErrs, int nCexes, int nCexesStop, int * pnComputed, int fVerbose ) +{ + abctime clk = Abc_Clock(); + int t, iObj, Count = 0, CountPos = 0, CountPosSat = 0, nRuns[2] = {0}, nCountCexes[2] = {0}; + Vec_Int_t * vPats = Vec_IntAlloc( 1000 ); + Vec_Int_t * vPatBest = Vec_IntAlloc( Min_ManCiNum(p) ); + Hsh_VecMan_t * pHash = Hsh_VecManStart( 10000 ); + Min_ManForEachCo( p, iObj ) if ( Min_ObjLit0(p, iObj) > 1 ) + { + int nCexesGenSim0 = 0; + int nCexesGenSim = 0; + int nCexesGenSat = 0; + if ( vCoErrs && Vec_IntEntry(vCoErrs, Min_ObjCioId(p, iObj)) >= nCexesStop ) + continue; + //printf( "%d ", i ); + for ( t = 0; t < nCexes; t++ ) + { + nRuns[0]++; + if ( Min_LitJustify( p, Min_ObjLit0(p, iObj) ) ) + { + int Before, After; + assert( Vec_IntSize(&p->vPat) > 0 ); + //printf( "%d ", Vec_IntSize(vPat) ); + Vec_IntClear( vPatBest ); + if ( 1 ) // no minimization + Vec_IntAppend( vPatBest, &p->vPat ); + else + { +/* + for ( k = 0; k < 10; k++ ) + { + Vec_IntClear( vPat2 ); + Gia_ManIncrementTravId( p ); + Cexes_MinimizePattern_rec( p, Gia_ObjFanin0(pObj), !Gia_ObjFaninC0(pObj), vPat2 ); + assert( Vec_IntSize(vPat2) <= Vec_IntSize(vPat) ); + if ( Vec_IntSize(vPatBest) == 0 || Vec_IntSize(vPatBest) > Vec_IntSize(vPat2) ) + { + Vec_IntClear( vPatBest ); + Vec_IntAppend( vPatBest, vPat2 ); + } + //printf( "%d ", Vec_IntSize(vPat2) ); + } +*/ + } + + //Gia_CexVerify( p, Gia_ObjFaninId0p(p, pObj), !Gia_ObjFaninC0(pObj), vPatBest ); + //printf( "\n" ); + Before = Hsh_VecSize( pHash ); + Vec_IntSort( vPatBest, 0 ); + Hsh_VecManAdd( pHash, vPatBest ); + After = Hsh_VecSize( pHash ); + if ( Before != After ) + { + Vec_IntPush( vPats, Min_ObjCioId(p, iObj) ); + Vec_IntPush( vPats, Vec_IntSize(vPatBest) ); + Vec_IntAppend( vPats, vPatBest ); + nCexesGenSim++; + } + nCexesGenSim0++; + if ( nCexesGenSim0 > nCexesGenSim*10 ) + { + printf( "**** Skipping output %d (out of %d)\n", Min_ObjCioId(p, iObj), Min_ManCoNum(p) ); + break; + } + } + if ( nCexesGenSim == nCexesStop ) + break; + } + //printf( "(%d %d) ", nCexesGenSim0, nCexesGenSim ); + //printf( "%d ", t/nCexesGenSim ); + + //printf( "The number of CEXes = %d\n", nCexesGen ); + //if ( fVerbose ) + // printf( "%d ", nCexesGen ); + nCountCexes[0] += nCexesGenSim; + nCountCexes[1] += nCexesGenSat; + Count += nCexesGenSim + nCexesGenSat; + CountPos++; + + if ( nCexesGenSim0 == 0 && t == nCexes ) + printf( "#### Output %d (out of %d)\n", Min_ObjCioId(p, iObj), Min_ManCoNum(p) ); + } + //printf( "\n" ); + if ( fVerbose ) + printf( "\n" ); + if ( fVerbose ) + printf( "Got %d unique CEXes using %d sim (%d) and %d SAT (%d) runs (ave size %.1f). PO = %d ErrPO = %d SatPO = %d ", + Count, nRuns[0], nCountCexes[0], nRuns[1], nCountCexes[1], + 1.0*Vec_IntSize(vPats)/Abc_MaxInt(1, Count)-2, Min_ManCoNum(p), CountPos, CountPosSat ); + if ( fVerbose ) + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + Hsh_VecManStop( pHash ); + Vec_IntFree( vPatBest ); + *pnComputed = Count; + return vPats; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Min_ManTest3( Gia_Man_t * p, Vec_Int_t * vCoErrs ) +{ + int fXor = 0; + int nComputed; + Vec_Int_t * vPats; + Gia_Man_t * pXor = fXor ? Gia_ManDupMuxes(p, 1) : NULL; + Min_Man_t * pNew = Min_ManFromGia( fXor ? pXor : p, NULL ); + Gia_ManStopP( &pXor ); + Min_ManStartValsL( pNew ); + //Vec_IntFill( vCoErrs, Vec_IntSize(vCoErrs), 0 ); + //vPats = Min_TargGenerateCexes( pNew, vCoErrs, 10000, 10, &nComputed, 1 ); + vPats = Min_TargGenerateCexes( pNew, vCoErrs, 10000, 10, &nComputed, 1 ); + Vec_IntFree( vPats ); + Min_ManStop( pNew ); +} +void Min_ManTest4( Gia_Man_t * p ) +{ + Vec_Int_t * vCoErrs = Vec_IntStartNatural( Gia_ManCoNum(p) ); + Min_ManTest3(p, vCoErrs); + Vec_IntFree( vCoErrs ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupCones2CollectPis_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vMap ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjUpdateTravIdCurrentId(p, iObj) ) + return; + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManDupCones2CollectPis_rec( p, Gia_ObjFaninId0(pObj, iObj), vMap ); + Gia_ManDupCones2CollectPis_rec( p, Gia_ObjFaninId1(pObj, iObj), vMap ); + } + else if ( Gia_ObjIsCi(pObj) ) + Vec_IntPush( vMap, iObj ); + else assert( 0 ); +} +void Gia_ManDupCones2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsCi(pObj) || Gia_ObjUpdateTravIdCurrent(p, pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupCones2_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManDupCones2_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManDupCones2( Gia_Man_t * p, int * pOuts, int nOuts, Vec_Int_t * vMap ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; int i; + Vec_IntClear( vMap ); + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManDupCones2CollectPis_rec( p, Gia_ManCoDriverId(p, pOuts[i]), vMap ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObjVec( vMap, p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManDupCones2_rec( pNew, p, Gia_ObjFanin0(Gia_ManCo(p, pOuts[i])) ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManCo(p, pOuts[i])) ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Min_ManRemoveItem( Vec_Wec_t * vCexes, int iItem, int iFirst, int iLimit ) +{ + Vec_Int_t * vLevel = NULL, * vLevel0 = Vec_WecEntry(vCexes, iItem); int i; + assert( iFirst <= iItem && iItem < iLimit ); + Vec_WecForEachLevelReverseStartStop( vCexes, vLevel, i, iLimit, iFirst ) + if ( Vec_IntSize(vLevel) > 0 ) + break; + assert( iFirst <= i && iItem <= i ); + Vec_IntClear( vLevel0 ); + if ( iItem < i ) + ABC_SWAP( Vec_Int_t, *vLevel0, *vLevel ); + return -1; +} +int Min_ManAccumulate( Vec_Wec_t * vCexes, int iFirst, int iLimit, Vec_Int_t * vCex ) +{ + Vec_Int_t * vLevel; int i, nCommon, nDiff = 0; + Vec_WecForEachLevelStartStop( vCexes, vLevel, i, iFirst, iLimit ) + { + if ( Vec_IntSize(vLevel) == 0 ) + { + Vec_IntAppend(vLevel, vCex); + return nDiff+1; + } + nCommon = Vec_IntTwoCountCommon( vLevel, vCex ); + if ( nCommon == Vec_IntSize(vLevel) ) // ignore vCex + return nDiff; + if ( nCommon == Vec_IntSize(vCex) ) // remove vLevel + nDiff += Min_ManRemoveItem( vCexes, i, iFirst, iLimit ); + } + assert( 0 ); + return ABC_INFINITY; +} +int Min_ManCountSize( Vec_Wec_t * vCexes, int iFirst, int iLimit ) +{ + Vec_Int_t * vLevel; int i, nTotal = 0; + Vec_WecForEachLevelStartStop( vCexes, vLevel, i, iFirst, iLimit ) + nTotal += Vec_IntSize(vLevel) > 0; + return nTotal; +} +Vec_Wec_t * Min_ManComputeCexes( Gia_Man_t * p, Vec_Int_t * vOuts0, int nMaxTries, int nMinCexes, Vec_Int_t * vStats[3], int fUseSim, int fUseSat, int fVerbose ) +{ + int fUseSynthesis = 1; + abctime clkSim = Abc_Clock(), clkSat = Abc_Clock(); + Vec_Int_t * vOuts = vOuts0 ? vOuts0 : Vec_IntStartNatural( Gia_ManCoNum(p) ); + Min_Man_t * pNew = Min_ManFromGia( p, vOuts ); + Vec_Wec_t * vCexes = Vec_WecStart( Vec_IntSize(vOuts) * nMinCexes ); + Vec_Int_t * vPatBest = Vec_IntAlloc( 100 ); + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i, iObj, nOuts = 0, nSimOuts = 0, nSatOuts = 0; + vStats[0] = Vec_IntAlloc( Vec_IntSize(vOuts) ); // total calls + vStats[1] = Vec_IntAlloc( Vec_IntSize(vOuts) ); // successful calls + SAT runs + vStats[2] = Vec_IntAlloc( Vec_IntSize(vOuts) ); // results + Min_ManStartValsL( pNew ); + Min_ManForEachCo( pNew, iObj ) + { + int nAllCalls = 0; + int nGoodCalls = 0; + int nCurrCexes = 0; + if ( fUseSim && Min_ObjLit0(pNew, iObj) >= 2 ) + { + while ( nAllCalls++ < nMaxTries ) + { + if ( Min_LitJustify( pNew, Min_ObjLit0(pNew, iObj) ) ) + { + Vec_IntClearAppend( vLits, &pNew->vPat ); + Vec_IntClearAppend( vPatBest, &pNew->vPat ); + if ( 1 ) // minimization + { + //printf( "%d -> ", Vec_IntSize(vPatBest) ); + for ( i = 0; i < 20; i++ ) + { + Min_LitMinimize( pNew, Min_ObjLit0(pNew, iObj), vLits ); + if ( Vec_IntSize(vPatBest) > Vec_IntSize(&pNew->vPat) ) + Vec_IntClearAppend( vPatBest, &pNew->vPat ); + } + //printf( "%d ", Vec_IntSize(vPatBest) ); + } + assert( Vec_IntSize(vPatBest) > 0 ); + Vec_IntSort( vPatBest, 0 ); + nCurrCexes += Min_ManAccumulate( vCexes, nOuts*nMinCexes, (nOuts+1)*nMinCexes, vPatBest ); + nGoodCalls++; + } + if ( nCurrCexes == nMinCexes || nGoodCalls > 10*nCurrCexes ) + break; + } + nSimOuts++; + } + assert( nCurrCexes <= nMinCexes ); + assert( nCurrCexes == Min_ManCountSize(vCexes, nOuts*nMinCexes, (nOuts+1)*nMinCexes) ); + Vec_IntPush( vStats[0], nAllCalls ); + Vec_IntPush( vStats[1], nGoodCalls ); + Vec_IntPush( vStats[2], nCurrCexes ); + nOuts++; + } + assert( Vec_IntSize(vOuts) == nOuts ); + assert( Vec_IntSize(vOuts) == Vec_IntSize(vStats[0]) ); + assert( Vec_IntSize(vOuts) == Vec_IntSize(vStats[1]) ); + assert( Vec_IntSize(vOuts) == Vec_IntSize(vStats[2]) ); + clkSim = Abc_Clock() - clkSim; + + if ( fUseSat ) + Gia_ManForEachCoVec( vOuts, p, pObj, i ) + { + if ( Vec_IntEntry(vStats[2], i) >= nMinCexes || Vec_IntEntry(vStats[1], i) > 10*Vec_IntEntry(vStats[2], i) ) + continue; + { + abctime clk = Abc_Clock(); + int iObj = Min_ManCo(pNew, i); + int Index = Gia_ObjCioId(pObj); + Vec_Int_t * vMap = Vec_IntAlloc( 100 ); + Gia_Man_t * pCon = Gia_ManDupCones2( p, &Index, 1, vMap ); + Gia_Man_t * pCon1= fUseSynthesis ? Gia_ManAigSyn2( pCon, 0, 1, 0, 100, 0, 0, 0 ) : NULL; + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( fUseSynthesis ? pCon1 : pCon, 8, 0, 0, 0, 0 ); + sat_solver* pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + int Lit = Abc_Var2Lit( 1, 0 ); + int status = sat_solver_addclause( pSat, &Lit, &Lit+1 ); + int nAllCalls = 0; + int nCurrCexes = Vec_IntEntry(vStats[2], i); + //Gia_AigerWrite( pCon, "temp_miter.aig", 0, 0, 0 ); + if ( status == l_True ) + { + nSatOuts++; + //printf( "Running SAT for output %d\n", i ); + if ( Min_ObjLit0(pNew, iObj) >= 2 ) + { + while ( nAllCalls++ < 100 ) + { + int v, iVar = pCnf->nVars - Gia_ManPiNum(pCon), nVars = Gia_ManPiNum(pCon); + if ( nAllCalls > 1 ) + sat_solver_randomize( pSat, iVar, nVars ); + status = sat_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 ); + if ( status != l_True ) + break; + assert( status == l_True ); + Vec_IntClear( vLits ); + for ( v = 0; v < nVars; v++ ) + Vec_IntPush( vLits, Abc_Var2Lit(Vec_IntEntry(vMap, v), !sat_solver_var_value(pSat, iVar + v)) ); + Min_LitMinimize( pNew, Min_ObjLit0(pNew, iObj), vLits ); + Vec_IntClearAppend( vPatBest, &pNew->vPat ); + if ( 1 ) // minimization + { + //printf( "%d -> ", Vec_IntSize(vPatBest) ); + for ( v = 0; v < 20; v++ ) + { + Min_LitMinimize( pNew, Min_ObjLit0(pNew, iObj), vLits ); + if ( Vec_IntSize(vPatBest) > Vec_IntSize(&pNew->vPat) ) + Vec_IntClearAppend( vPatBest, &pNew->vPat ); + } + //printf( "%d ", Vec_IntSize(vPatBest) ); + } + Vec_IntSort( vPatBest, 0 ); + nCurrCexes += Min_ManAccumulate( vCexes, i*nMinCexes, (i+1)*nMinCexes, vPatBest ); + if ( nCurrCexes == nMinCexes || nAllCalls > 10*nCurrCexes ) + break; + } + } + } + Vec_IntWriteEntry( vStats[0], i, nAllCalls*nMaxTries ); + Vec_IntWriteEntry( vStats[1], i, nAllCalls*nMaxTries ); + Vec_IntWriteEntry( vStats[2], i, nCurrCexes ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + Gia_ManStop( pCon ); + Gia_ManStopP( &pCon1 ); + Vec_IntFree( vMap ); + if ( fVerbose ) + { + printf( "SAT solving for output %3d (cexes = %5d) : ", i, nCurrCexes ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + } + } + clkSat = Abc_Clock() - clkSat - clkSim; + if ( fVerbose ) + printf( "Used simulation for %d and SAT for %d outputs (out of %d).\n", nSimOuts, nSatOuts, nOuts ); + if ( fVerbose ) + Abc_PrintTime( 1, "Simulation time ", clkSim ); + if ( fVerbose ) + Abc_PrintTime( 1, "SAT solving time ", clkSat ); + //Vec_WecPrint( vCexes, 0 ); + if ( vOuts != vOuts0 ) + Vec_IntFreeP( &vOuts ); + Min_ManStop( pNew ); + Vec_IntFree( vPatBest ); + Vec_IntFree( vLits ); + return vCexes; +} + +/**Function************************************************************* + + Synopsis [Bit-packing for selected patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Min_ManBitPackTry( Vec_Wrd_t * vSimsPi, int nWords, int iPat, Vec_Int_t * vLits ) +{ + int i, Lit; + assert( iPat >= 0 && iPat < 64 * nWords ); + Vec_IntForEachEntry( vLits, Lit, i ) + { + word * pInfo = Vec_WrdEntryP( vSimsPi, nWords * Abc_Lit2Var(Lit-2) ); // Lit is based on ObjId + word * pCare = pInfo + Vec_WrdSize(vSimsPi); + if ( Abc_InfoHasBit( (unsigned *)pCare, iPat ) && + Abc_InfoHasBit( (unsigned *)pInfo, iPat ) == Abc_LitIsCompl(Lit) ) // Lit is in ms notation + return 0; + } + Vec_IntForEachEntry( vLits, Lit, i ) + { + word * pInfo = Vec_WrdEntryP( vSimsPi, nWords * Abc_Lit2Var(Lit-2) ); // Lit is based on ObjId + word * pCare = pInfo + Vec_WrdSize(vSimsPi); + Abc_InfoSetBit( (unsigned *)pCare, iPat ); + if ( Abc_InfoHasBit( (unsigned *)pInfo, iPat ) == Abc_LitIsCompl(Lit) ) // Lit is in ms notation + Abc_InfoXorBit( (unsigned *)pInfo, iPat ); + } + return 1; +} +int Min_ManBitPackOne( Vec_Wrd_t * vSimsPi, int iPat0, int nWords, Vec_Int_t * vLits ) +{ + int iPat, nTotal = 64*nWords; + for ( iPat = iPat0 + 1; iPat != iPat0; iPat = (iPat + 1) % nTotal ) + if ( Min_ManBitPackTry( vSimsPi, nWords, iPat, vLits ) ) + break; + return iPat; +} +Vec_Ptr_t * Min_ReloadCexes( Vec_Wec_t * vCexes, int nMinCexes ) +{ + Vec_Ptr_t * vRes = Vec_PtrAlloc( Vec_WecSize(vCexes) ); + int i, c, nOuts = Vec_WecSize(vCexes)/nMinCexes; + for ( i = 0; i < nMinCexes; i++ ) + for ( c = 0; c < nOuts; c++ ) + { + Vec_Int_t * vLevel = Vec_WecEntry( vCexes, c*nMinCexes+i ); + if ( Vec_IntSize(vLevel) ) + Vec_PtrPush( vRes, vLevel ); + } + return vRes; +} + +Vec_Wrd_t * Min_ManBitPack( Gia_Man_t * p, int nWords0, Vec_Wec_t * vCexes, int fRandom, int nMinCexes, Vec_Int_t * vScores, int fVerbose ) +{ + abctime clk = Abc_Clock(); + //int fVeryVerbose = 0; + Vec_Wrd_t * vSimsPi = NULL; + Vec_Int_t * vLevel; + int w, nBits, nTotal = 0, fFailed = ABC_INFINITY; + Vec_Int_t * vOrder = NULL; + Vec_Ptr_t * vReload = NULL; + if ( 0 ) + { + vOrder = Vec_IntStartNatural( Vec_WecSize(vCexes)/nMinCexes ); + assert( Vec_IntSize(vOrder) == Vec_IntSize(vScores) ); + assert( Vec_WecSize(vCexes)%nMinCexes == 0 ); + Abc_MergeSortCost2Reverse( Vec_IntArray(vOrder), Vec_IntSize(vOrder), Vec_IntArray(vScores) ); + } + else + vReload = Min_ReloadCexes( vCexes, nMinCexes ); + if ( fVerbose ) + printf( "Packing: " ); + for ( w = nWords0 ? nWords0 : 1; nWords0 ? w <= nWords0 : fFailed > 0; w++ ) + { + int i, iPatUsed, iPat = 0; + //int k, iOut; + Vec_WrdFreeP( &vSimsPi ); + vSimsPi = fRandom ? Vec_WrdStartRandom(2 * Gia_ManCiNum(p) * w) : Vec_WrdStart(2 * Gia_ManCiNum(p) * w); + Vec_WrdShrink( vSimsPi, Vec_WrdSize(vSimsPi)/2 ); + Abc_TtClear( Vec_WrdLimit(vSimsPi), Vec_WrdSize(vSimsPi) ); + fFailed = nTotal = 0; + //Vec_IntForEachEntry( vOrder, iOut, k ) + //Vec_WecForEachLevelStartStop( vCexes, vLevel, i, iOut*nMinCexes, (iOut+1)*nMinCexes ) + Vec_PtrForEachEntry( Vec_Int_t *, vReload, vLevel, i ) + { + //if ( fVeryVerbose && i%nMinCexes == 0 ) + // printf( "\n" ); + if ( Vec_IntSize(vLevel) == 0 ) + continue; + iPatUsed = Min_ManBitPackOne( vSimsPi, iPat, w, vLevel ); + fFailed += iPatUsed == iPat; + iPat = (iPatUsed + 1) % (64*(w-1) - 1); + //if ( fVeryVerbose ) + //printf( "Adding output %3d cex %3d to pattern %3d ", i/nMinCexes, i%nMinCexes, iPatUsed ); + //if ( fVeryVerbose ) + //Vec_IntPrint( vLevel ); + nTotal++; + } + if ( fVerbose ) + printf( "W = %d (F = %d) ", w, fFailed ); +// printf( "Failed patterns = %d\n", fFailed ); + } + if ( fVerbose ) + printf( "Total = %d\n", nTotal ); + if ( fVerbose ) + { + nBits = Abc_TtCountOnesVec( Vec_WrdLimit(vSimsPi), Vec_WrdSize(vSimsPi) ); + printf( "Bit-packing is using %d words and %d bits. Density =%8.4f %%. ", + Vec_WrdSize(vSimsPi)/Gia_ManCiNum(p), nBits, 100.0*nBits/64/Vec_WrdSize(vSimsPi) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + Vec_IntFreeP( &vOrder ); + Vec_PtrFreeP( &vReload ); + return vSimsPi; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Patt_ManOutputErrorCoverage( Vec_Wrd_t * vErrors, int nOuts ) +{ + Vec_Int_t * vCounts = Vec_IntAlloc( nOuts ); + int i, nWords = Vec_WrdSize(vErrors)/nOuts; + assert( Vec_WrdSize(vErrors) == nOuts * nWords ); + for ( i = 0; i < nOuts; i++ ) + Vec_IntPush( vCounts, Abc_TtCountOnesVec(Vec_WrdEntryP(vErrors, nWords * i), nWords) ); + return vCounts; +} +Vec_Wrd_t * Patt_ManTransposeErrors( Vec_Wrd_t * vErrors, int nOuts ) +{ + extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + int nWordsIn = Vec_WrdSize(vErrors) / nOuts; + int nWordsOut = Abc_Bit6WordNum(nOuts); + Vec_Wrd_t * vSims1 = Vec_WrdStart( 64*nWordsIn*nWordsOut ); + Vec_Wrd_t * vSims2 = Vec_WrdStart( 64*nWordsIn*nWordsOut ); + assert( Vec_WrdSize(vErrors) == nWordsIn * nOuts ); + Abc_TtCopy( Vec_WrdArray(vSims1), Vec_WrdArray(vErrors), Vec_WrdSize(vErrors), 0 ); + Extra_BitMatrixTransposeP( vSims1, nWordsIn, vSims2, nWordsOut ); + Vec_WrdFree( vSims1 ); + return vSims2; +} +Vec_Int_t * Patt_ManPatternErrorCoverage( Vec_Wrd_t * vErrors, int nOuts ) +{ + int nWords = Vec_WrdSize(vErrors)/nOuts; + Vec_Wrd_t * vErrors2 = Patt_ManTransposeErrors( vErrors, nOuts ); + Vec_Int_t * vPatErrs = Patt_ManOutputErrorCoverage( vErrors2, 64*nWords ); + Vec_WrdFree( vErrors2 ); + return vPatErrs; +} + +#define ERR_REPT_SIZE 32 +void Patt_ManProfileErrors( Vec_Int_t * vOutErrs, Vec_Int_t * vPatErrs ) +{ + int nOuts = Vec_IntSize(vOutErrs); + int nPats = Vec_IntSize(vPatErrs); + int ErrOuts[ERR_REPT_SIZE+1] = {0}; + int ErrPats[ERR_REPT_SIZE+1] = {0}; + int i, Errs, nErrors1 = 0, nErrors2 = 0; + Vec_IntForEachEntry( vOutErrs, Errs, i ) + { + nErrors1 += Errs; + ErrOuts[Errs < ERR_REPT_SIZE ? Errs : ERR_REPT_SIZE]++; + } + Vec_IntForEachEntry( vPatErrs, Errs, i ) + { + nErrors2 += Errs; + ErrPats[Errs < ERR_REPT_SIZE ? Errs : ERR_REPT_SIZE]++; + } + assert( nErrors1 == nErrors2 ); + // errors/error_outputs/error_patterns + //printf( "\nError statistics:\n" ); + printf( "Errors =%6d ", nErrors1 ); + printf( "ErrPOs =%5d (Ave = %5.2f) ", nOuts-ErrOuts[0], 1.0*nErrors1/Abc_MaxInt(1, nOuts-ErrOuts[0]) ); + printf( "Patterns =%5d (Ave = %5.2f) ", nPats, 1.0*nErrors1/nPats ); + printf( "Density =%8.4f %%\n", 100.0*nErrors1/nPats/Abc_MaxInt(1, nOuts-ErrOuts[0]) ); + // how many times each output fails + printf( "Outputs: " ); + for ( i = 0; i <= ERR_REPT_SIZE; i++ ) + if ( ErrOuts[i] ) + printf( "%s%d=%d ", i == ERR_REPT_SIZE? ">" : "", i, ErrOuts[i] ); + printf( "\n" ); + // how many times each patterns fails an output + printf( "Patterns: " ); + for ( i = 0; i <= ERR_REPT_SIZE; i++ ) + if ( ErrPats[i] ) + printf( "%s%d=%d ", i == ERR_REPT_SIZE? ">" : "", i, ErrPats[i] ); + printf( "\n" ); +} +int Patt_ManProfileErrorsOne( Vec_Wrd_t * vErrors, int nOuts ) +{ + Vec_Int_t * vCoErrs = Patt_ManOutputErrorCoverage( vErrors, nOuts ); + Vec_Int_t * vPatErrs = Patt_ManPatternErrorCoverage( vErrors, nOuts ); + Patt_ManProfileErrors( vCoErrs, vPatErrs ); + Vec_IntFree( vPatErrs ); + Vec_IntFree( vCoErrs ); + return 1; +} + +Vec_Int_t * Min_ManGetUnsolved( Gia_Man_t * p ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + int i, Driver; + Gia_ManForEachCoDriverId( p, Driver, i ) + if ( Driver > 0 ) + Vec_IntPush( vRes, i ); + if ( Vec_IntSize(vRes) == 0 ) + Vec_IntFreeP( &vRes ); + return vRes; +} +Vec_Wrd_t * Min_ManRemapSims( int nInputs, Vec_Int_t * vMap, Vec_Wrd_t * vSimsPi ) +{ + int i, iObj, nWords = Vec_WrdSize(vSimsPi)/Vec_IntSize(vMap); + Vec_Wrd_t * vSimsNew = Vec_WrdStart( 2 * nInputs * nWords ); + //Vec_Wrd_t * vSimsNew = Vec_WrdStartRandom( nInputs * nWords ); + //Vec_WrdFillExtra( vSimsNew, 2 * nInputs * nWords, 0 ); + assert( Vec_WrdSize(vSimsPi)%Vec_IntSize(vMap) == 0 ); + Vec_WrdShrink( vSimsNew, Vec_WrdSize(vSimsNew)/2 ); + Vec_IntForEachEntry( vMap, iObj, i ) + { + Abc_TtCopy( Vec_WrdArray(vSimsNew) + (iObj-1)*nWords, Vec_WrdArray(vSimsPi) + i*nWords, nWords, 0 ); + Abc_TtCopy( Vec_WrdLimit(vSimsNew) + (iObj-1)*nWords, Vec_WrdLimit(vSimsPi) + i*nWords, nWords, 0 ); + } + return vSimsNew; +} +Vec_Wrd_t * Gia_ManCollectSims( Gia_Man_t * pSwp, int nWords, Vec_Int_t * vOuts, int nMaxTries, int nMinCexes, int fUseSim, int fUseSat, int fVerbose, int fVeryVerbose ) +{ + Vec_Int_t * vStats[3] = {0}; int i, iObj; + Vec_Int_t * vMap = Vec_IntAlloc( 100 ); + Gia_Man_t * pSwp2 = Gia_ManDupCones2( pSwp, Vec_IntArray(vOuts), Vec_IntSize(vOuts), vMap ); + Vec_Wec_t * vCexes = Min_ManComputeCexes( pSwp2, NULL, nMaxTries, nMinCexes, vStats, fUseSim, fUseSat, fVerbose ); + if ( Vec_IntSum(vStats[2]) == 0 ) + { + for ( i = 0; i < 3; i++ ) + Vec_IntFree( vStats[i] ); + Vec_IntFree( vMap ); + Gia_ManStop( pSwp2 ); + Vec_WecFree( vCexes ); + return NULL; + } + else + { + Vec_Wrd_t * vSimsPi = Min_ManBitPack( pSwp2, nWords, vCexes, 1, nMinCexes, vStats[0], fVerbose ); + Vec_Wrd_t * vSimsPo = Gia_ManSimPatSimOut( pSwp2, vSimsPi, 1 ); + Vec_Int_t * vCounts = Patt_ManOutputErrorCoverage( vSimsPo, Vec_IntSize(vOuts) ); + if ( fVerbose ) + Patt_ManProfileErrorsOne( vSimsPo, Vec_IntSize(vOuts) ); + if ( fVeryVerbose ) + { + printf( "Unsolved = %4d ", Vec_IntSize(vOuts) ); + Gia_ManPrintStats( pSwp2, NULL ); + Vec_IntForEachEntry( vOuts, iObj, i ) + { + printf( "%4d : ", i ); + printf( "Out = %5d ", Vec_IntEntry(vMap, i) ); + printf( "SimAll =%8d ", Vec_IntEntry(vStats[0], i) ); + printf( "SimGood =%8d ", Vec_IntEntry(vStats[1], i) ); + printf( "PatsAll =%8d ", Vec_IntEntry(vStats[2], i) ); + printf( "Count = %5d ", Vec_IntEntry(vCounts, i) ); + printf( "\n" ); + if ( i == 20 ) + break; + } + } + for ( i = 0; i < 3; i++ ) + Vec_IntFree( vStats[i] ); + Vec_IntFree( vCounts ); + Vec_WrdFree( vSimsPo ); + Vec_WecFree( vCexes ); + Gia_ManStop( pSwp2 ); + //printf( "Compressing inputs: %5d -> %5d\n", Gia_ManCiNum(pSwp), Vec_IntSize(vMap) ); + vSimsPi = Min_ManRemapSims( Gia_ManCiNum(pSwp), vMap, vSimsPo = vSimsPi ); + Vec_WrdFree( vSimsPo ); + Vec_IntFree( vMap ); + return vSimsPi; + } +} +Vec_Wrd_t * Min_ManCollect( Gia_Man_t * p, int nConf, int nConf2, int nMaxTries, int nMinCexes, int fUseSim, int fUseSat, int fVerbose, int fVeryVerbose ) +{ + abctime clk = Abc_Clock(); + extern Gia_Man_t * Cec4_ManSimulateTest4( Gia_Man_t * p, int nBTLimit, int nBTLimitPo, int fVerbose ); + Gia_Man_t * pSwp = Cec4_ManSimulateTest4( p, nConf, nConf2, 0 ); + abctime clkSweep = Abc_Clock() - clk; + int nArgs = fVerbose ? printf( "Generating patterns: Conf = %d (%d). Tries = %d. Pats = %d. Sim = %d. SAT = %d.\n", + nConf, nConf2, nMaxTries, nMinCexes, fUseSim, fUseSat ) : 0; + Vec_Int_t * vOuts = Min_ManGetUnsolved( pSwp ); + Vec_Wrd_t * vSimsPi = vOuts ? Gia_ManCollectSims( pSwp, 0, vOuts, nMaxTries, nMinCexes, fUseSim, fUseSat, fVerbose, fVeryVerbose ) : NULL; + if ( vOuts == NULL ) + printf( "There is no satisfiable outputs.\n" ); + if ( fVerbose ) + Abc_PrintTime( 1, "Sweep time", clkSweep ); + if ( fVerbose ) + Abc_PrintTime( 1, "Total time", Abc_Clock() - clk ); + Vec_IntFreeP( &vOuts ); + Gia_ManStop( pSwp ); + nArgs = 0; + return vSimsPi; +} +void Min_ManTest2( Gia_Man_t * p ) +{ + Vec_Wrd_t * vSimsPi = Min_ManCollect( p, 100000, 100000, 10000, 20, 1, 0, 1, 1 ); + Vec_WrdFreeP( &vSimsPi ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaPf.c b/abc/src/aig/gia/giaPf.c index 703e39129e0..c453dc56af9 100644 --- a/abc/src/aig/gia/giaPf.c +++ b/abc/src/aig/gia/giaPf.c @@ -908,7 +908,7 @@ void Pf_ManPrintStats( Pf_Man_t * p, char * pTitle ) if ( !p->pPars->fVerbose ) return; printf( "%s : ", pTitle ); - printf( "Delay =%8.2f ", p->pPars->MapDelay ); + printf( "Delay =%8.2f ", (float)p->pPars->MapDelay ); printf( "Area =%12.2f ", p->pPars->MapArea ); printf( "Gate =%6d ", (int)p->pPars->Area ); printf( "Inv =%6d ", (int)p->nInvs ); diff --git a/abc/src/aig/gia/giaQbf.c b/abc/src/aig/gia/giaQbf.c index 247c3dad5a2..6ccbe460530 100644 --- a/abc/src/aig/gia/giaQbf.c +++ b/abc/src/aig/gia/giaQbf.c @@ -23,6 +23,7 @@ #include "sat/bsat/satStore.h" #include "misc/extra/extra.h" #include "sat/glucose/AbcGlucose.h" +#include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START @@ -132,11 +133,11 @@ Vec_Int_t * Gia_GenCreateMuxes( Gia_Man_t * p, Gia_Man_t * pNew, Vec_Int_t * vFl } return vLits; } -Gia_Man_t * Gia_GenQbfMiter( Gia_Man_t * p, int nFrames, int nLutNum, int nLutSize, char * pStr, int fVerbose ) +Gia_Man_t * Gia_GenQbfMiter( Gia_Man_t * p, int nFrames, int nLutNum, int nLutSize, char * pStr, int fUseOut, int fVerbose ) { Gia_Obj_t * pObj; Gia_Man_t * pTemp, * pNew; - int i, iMiter, nPars = nLutNum * (1 << nLutSize); + int i, iMiter, iLut0, iLut1, nPars = nLutNum * (1 << nLutSize); Vec_Int_t * vLits0, * vLits1, * vParLits; Vec_Int_t * vFlops = Gia_GenCollectFlopIndexes( pStr, nLutNum, nLutSize, Gia_ManRegNum(p) ); // collect parameter literals (data vars) @@ -160,7 +161,18 @@ Gia_Man_t * Gia_GenQbfMiter( Gia_Man_t * p, int nFrames, int nLutNum, int nLutSi vLits0 = Gia_GenCreateMuxes( p, pNew, vFlops, nLutNum, nLutSize, vParLits, 0 ); vLits1 = Gia_GenCreateMuxes( p, pNew, vFlops, nLutNum, nLutSize, vParLits, 1 ); // create miter output - iMiter = Gia_ManHashAnd( pNew, Vec_IntEntry(vLits0, 0), Abc_LitNot(Vec_IntEntry(vLits1, 0)) ); + //iMiter = Gia_ManHashAnd( pNew, Vec_IntEntry(vLits0, 0), Abc_LitNot(Vec_IntEntry(vLits1, 0)) ); + /////////////////////////////////////////////////////////////////////////// + iLut0 = Vec_IntEntry(vLits0, 0); + iLut1 = Vec_IntEntry(vLits1, 0); + if ( fUseOut ) + { + Gia_Obj_t * pObjPoLast = Gia_ManPo( p, Gia_ManPoNum(p)-1 ); + int iOut = Abc_LitNotCond( Gia_ObjFanin0Copy(pObjPoLast), 0 ); + iLut1 = Gia_ManHashAnd( pNew, iLut1, Abc_LitNot(iOut) ); + } + iMiter = Gia_ManHashAnd( pNew, iLut0, Abc_LitNot(iLut1) ); + /////////////////////////////////////////////////////////////////////////// iMiter = Gia_ManHashAnd( pNew, Abc_LitNot(iMiter), Abc_Var2Lit(1, 0) ); Gia_ManAppendCo( pNew, iMiter ); // cleanup @@ -173,6 +185,202 @@ Gia_Man_t * Gia_GenQbfMiter( Gia_Man_t * p, int nFrames, int nLutNum, int nLutSi return pNew; } + +/**Function************************************************************* + + Synopsis [Generate miter for the encoding problem.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Gen2CreateMux_rec( Gia_Man_t * pNew, int * pCtrl, int nCtrl, Vec_Int_t * vData, int Shift ) +{ + int iLit0, iLit1; + if ( nCtrl == 0 ) + return Vec_IntEntry( vData, Shift ); + iLit0 = Gia_Gen2CreateMux_rec( pNew, pCtrl, nCtrl-1, vData, Shift ); + iLit1 = Gia_Gen2CreateMux_rec( pNew, pCtrl, nCtrl-1, vData, Shift + (1<<(nCtrl-1)) ); + return Gia_ManHashMux( pNew, pCtrl[nCtrl-1], iLit1, iLit0 ); +} +Vec_Int_t * Gia_Gen2CreateMuxes( Gia_Man_t * pNew, int nLutSize, int nLutNum, Vec_Int_t * vPLits, Vec_Int_t * vXLits ) +{ + Vec_Int_t * vLits = Vec_IntAlloc( nLutNum ); + int i, iMux; + // add MUXes for each group of flops + assert( Vec_IntSize(vPLits) == nLutNum * (1 << nLutSize) ); + assert( Vec_IntSize(vXLits) == nLutSize ); + for ( i = 0; i < nLutNum; i++ ) + { + iMux = Gia_Gen2CreateMux_rec( pNew, Vec_IntArray(vXLits), nLutSize, vPLits, i * (1 << nLutSize) ); + Vec_IntPush( vLits, iMux ); + } + return vLits; +} +Gia_Man_t * Gia_Gen2CreateMiter( int nLutSize, int nLutNum ) +{ + // |<-- PVars(0)-->|...|<-- PVars(nLutNum-1)-->|<-- XVars-->|<-- YVars-->| + Vec_Int_t * vPLits = Vec_IntAlloc( nLutNum * (1 << nLutSize) ); + Vec_Int_t * vXLits = Vec_IntAlloc( nLutSize ); + Vec_Int_t * vYLits = Vec_IntAlloc( nLutSize ); + Vec_Int_t * vXYLits = Vec_IntAlloc( nLutSize ); + Vec_Int_t * vXRes, * vYRes, * vXYRes; + Vec_Int_t * vXYRes2 = Vec_IntAlloc( 2 * nLutNum ); + Gia_Man_t * pTemp, * pNew = Gia_ManStart( 1000 ); int i, k, v, Cond, Res; + pNew->pName = Abc_UtilStrsav( "homoqbf" ); + Gia_ManHashAlloc( pNew ); + for ( i = 0; i < nLutNum * (1 << nLutSize); i++ ) + Vec_IntPush( vPLits, Gia_ManAppendCi(pNew) ); + for ( i = 0; i < nLutSize; i++ ) + Vec_IntPush( vXLits, Gia_ManAppendCi(pNew) ); + for ( i = 0; i < nLutSize; i++ ) + Vec_IntPush( vYLits, Gia_ManAppendCi(pNew) ); + for ( i = 0; i < nLutSize; i++ ) + Vec_IntPush( vXYLits, Abc_LitNot(Gia_ManHashAnd(pNew, Vec_IntEntry(vXLits, i), Vec_IntEntry(vYLits, i))) ); + vXRes = Gia_Gen2CreateMuxes( pNew, nLutSize, nLutNum, vPLits, vXLits ); + vYRes = Gia_Gen2CreateMuxes( pNew, nLutSize, nLutNum, vPLits, vYLits ); + vXYRes = Gia_Gen2CreateMuxes( pNew, nLutSize, nLutNum, vPLits, vXYLits ); + for ( i = 0; i < nLutNum; i++ ) + { + Vec_IntPush( vXYRes2, Vec_IntEntry(vXYRes, i) ); + Vec_IntPush( vXYRes2, Abc_LitNot(Gia_ManHashAnd(pNew, Vec_IntEntry(vXRes, i), Vec_IntEntry(vYRes, i))) ); + } + Res = Gia_ManHashDualMiter( pNew, vXYRes2 ); + // uniqueness of codes + for ( i = 0; i < (1 << nLutSize); i++ ) + { + Vec_Int_t * vCondA = Vec_IntAlloc( nLutNum ); + Vec_Int_t * vCondB = Vec_IntAlloc( nLutNum ); + for ( v = 0; v < nLutNum; v++ ) + Vec_IntPush( vCondA, Vec_IntEntry(vPLits, v*(1 << nLutSize)+i) ); + for ( k = i+1; k < (1 << nLutSize); k++ ) + { + Vec_IntClear( vCondB ); + for ( v = 0; v < nLutNum; v++ ) + { + Vec_IntPush( vCondB, Vec_IntEntry(vCondA, v) ); + Vec_IntPush( vCondB, Vec_IntEntry(vPLits, v*(1 << nLutSize)+k) ); + } + Cond = Gia_ManHashDualMiter( pNew, vCondB ); + Res = Gia_ManHashOr( pNew, Res, Abc_LitNot(Cond) ); + } + Vec_IntFree( vCondA ); + Vec_IntFree( vCondB ); + } + Gia_ManAppendCo( pNew, Abc_LitNot(Res) ); + Gia_ManHashStop( pNew ); + Vec_IntFree( vPLits ); + Vec_IntFree( vXLits ); + Vec_IntFree( vYLits ); + Vec_IntFree( vXYLits ); + Vec_IntFree( vXRes ); + Vec_IntFree( vYRes ); + Vec_IntFree( vXYRes ); + Vec_IntFree( vXYRes2 ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + printf( "Generated QBF miter with %d parameters, %d functional variables, and %d AIG nodes.\n", + nLutNum * (1 << nLutSize), 2*nLutSize, Gia_ManAndNum(pNew) ); + return pNew; +} +int Gia_Gen2CodeOne( int nLutSize, int nLutNum, Vec_Int_t * vCode, int x ) +{ + int k, Code = 0; + for ( k = 0; k < nLutNum; k++ ) + if ( Vec_IntEntry(vCode, k*(1 << nLutSize)+x) ) + Code |= (1 << k); + return Code; +} +word * Gia_Gen2CodeOneP( int nLutSize, int nLutNum, Vec_Int_t * vCode, int x ) +{ + word * pRes = ABC_CALLOC( word, Abc_Bit6WordNum(nLutNum) ); + int k; + for ( k = 0; k < nLutNum; k++ ) + if ( Vec_IntEntry(vCode, k*(1 << nLutSize)+x) ) + Abc_InfoSetBit( (unsigned *)pRes, k ); + return pRes; +} +void Gia_Gen2CodePrint( int nLutSize, int nLutNum, Vec_Int_t * vCode ) +{ + // |<-- PVars(0)-->|...|<-- PVars(nLutNum-1)-->| + int i, n, nPairs = 16; + printf( "%d-input %d-output code table:\n", nLutSize, nLutNum ); + for ( i = 0; i < (1 << nLutSize); i++ ) + { + word * CodeX = Gia_Gen2CodeOneP( nLutSize, nLutNum, vCode, i ); + printf( "%3d ", i ); + Extra_PrintBinary( stdout, (unsigned *)&i, nLutSize ); + printf( " --> " ); + if ( nLutNum <= 16 ) + printf( "%5d ", (int)CodeX[0] ); + Extra_PrintBinary( stdout, (unsigned *)CodeX, nLutNum ); + printf( "\n" ); + ABC_FREE( CodeX ); + } + // create several different pairs + srand( time(NULL) ); + printf( "Simulation of the encoding with %d random pairs:\n", nPairs ); + for ( n = 0; n < nPairs; n++ ) + { + unsigned MaskIn = Abc_InfoMask( nLutSize ); + int NumX = 0, NumY = 0, NumXY, nWords = Abc_Bit6WordNum(nLutNum); + word * CodeX, * CodeY, * CodeXY; + word * CodeXCodeY = ABC_CALLOC( word, nWords ); + while ( NumX == NumY ) + { + NumX = rand() % (1 << nLutSize); + NumY = rand() % (1 << nLutSize); + NumXY = MaskIn & ~(NumX & NumY); + } + CodeX = Gia_Gen2CodeOneP( nLutSize, nLutNum, vCode, NumX ); + CodeY = Gia_Gen2CodeOneP( nLutSize, nLutNum, vCode, NumY ); + CodeXY = Gia_Gen2CodeOneP( nLutSize, nLutNum, vCode, NumXY ); + Abc_TtAnd( CodeXCodeY, CodeX, CodeY, nWords, 1 ); + if ( nLutNum < 64*nWords ) + CodeXCodeY[nWords-1] &= Abc_Tt6Mask(nLutNum % 64); + + printf( "%2d :", n ); + printf( " x =%3d ", NumX ); + Extra_PrintBinary( stdout,(unsigned *) &NumX, nLutSize ); + printf( " y =%3d ", NumY ); + Extra_PrintBinary( stdout, (unsigned *)&NumY, nLutSize ); + printf( " nand =%3d ", NumXY ); + Extra_PrintBinary( stdout, (unsigned *)&NumXY, nLutSize ); + printf( " " ); + + printf( " c(x) = " ); + Extra_PrintBinary( stdout, (unsigned *)CodeX, nLutNum ); + printf( " c(y) = " ); + Extra_PrintBinary( stdout, (unsigned *)CodeY, nLutNum ); + printf( " c(nand) = " ); + Extra_PrintBinary( stdout, (unsigned *)CodeXY, nLutNum ); + printf( " nand(c(x),c(y)) = " ); + Extra_PrintBinary( stdout, (unsigned *)CodeXCodeY, nLutNum ); + printf( " " ); + + printf( "%s", Abc_TtEqual(CodeXCodeY, CodeXY, nWords) ? "yes" : "no" ); + printf( "\n" ); + + ABC_FREE( CodeX ); + ABC_FREE( CodeY ); + ABC_FREE( CodeXY ); + ABC_FREE( CodeXCodeY ); + } +} +void Gia_Gen2CodeTest() +{ + int i, nLutSize = 1, nLutNum = 2; + Vec_Int_t * vCode = Vec_IntAlloc( (1 << nLutSize) * nLutNum ); + srand( time(NULL) ); + for ( i = 0; i < (1 << nLutSize) * nLutNum; i++ ) + Vec_IntPush( vCode, rand() & 1 ); + Gia_Gen2CodePrint( nLutSize, nLutNum, vCode ); + Vec_IntFree( vCode ); +} + /**Function************************************************************* Synopsis [Naive way to enumerate SAT assignments.] @@ -274,6 +482,45 @@ void Gia_QbfDumpFile( Gia_Man_t * pGia, int nPars ) Vec_IntFree( vVarMap ); printf( "The 2QBF formula was written into file \"%s\".\n", pFileName ); } +void Gia_QbfDumpFileInv( Gia_Man_t * pGia, int nPars ) +{ + // original problem: \exists p \forall x \exists y. M(p,x,y) + // negated problem: \forall p \exists x \exists y. !M(p,x,y) + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pGia, 8, 0, 1, 0, 0 ); + Vec_Int_t * vVarMap, * vForAlls, * vExists1, * vExists2; + Gia_Obj_t * pObj; + char * pFileName; + int i, Entry; + // complement the last clause + //int * pLit = pCnf->pClauses[pCnf->nClauses] - 1; *pLit ^= 1; + // create var map + vVarMap = Vec_IntStart( pCnf->nVars ); + Gia_ManForEachCi( pGia, pObj, i ) + Vec_IntWriteEntry( vVarMap, pCnf->pVarNums[Gia_ManCiIdToId(pGia, i)], i < nPars ? 1 : 2 ); + // create various maps + vExists1 = Vec_IntAlloc( nPars ); + vForAlls = Vec_IntAlloc( Gia_ManCiNum(pGia) - nPars ); + vExists2 = Vec_IntAlloc( pCnf->nVars - Gia_ManCiNum(pGia) ); + Vec_IntForEachEntry( vVarMap, Entry, i ) + if ( Entry == 1 ) + Vec_IntPush( vExists1, i ); + else if ( Entry == 2 ) + Vec_IntPush( vForAlls, i ); + else + Vec_IntPush( vExists2, i ); + // generate CNF + pFileName = Extra_FileNameGenericAppend( pGia->pSpec, ".qdimacs" ); + Cnf_DataWriteIntoFileInv( pCnf, pFileName, 0, vExists1, vForAlls, vExists2 ); + Cnf_DataFree( pCnf ); + Vec_IntFree( vExists1 ); + Vec_IntFree( vForAlls ); + Vec_IntFree( vExists2 ); + Vec_IntFree( vVarMap ); + printf( "The 2QBF formula was written into file \"%s\".\n", pFileName ); +} + + + /**Function************************************************************* @@ -621,7 +868,7 @@ void Gia_QbfLearnConstraint( Qbf_Man_t * p, Vec_Int_t * vValues ) SeeAlso [] ***********************************************************************/ -int Gia_QbfSolve( Gia_Man_t * pGia, int nPars, int nIterLimit, int nConfLimit, int nTimeOut, int fGlucose, int fVerbose ) +int Gia_QbfSolve( Gia_Man_t * pGia, int nPars, int nIterLimit, int nConfLimit, int nTimeOut, int nEncVars, int fGlucose, int fVerbose ) { Qbf_Man_t * p = Gia_QbfAlloc( pGia, nPars, fGlucose, fVerbose ); Gia_Man_t * pCof; @@ -668,6 +915,12 @@ int Gia_QbfSolve( Gia_Man_t * pGia, int nPars, int nIterLimit, int nConfLimit, i assert( Vec_IntSize(p->vValues) == nPars ); Vec_IntPrintBinary( p->vValues ); printf( " Statistics: 0=%d 1=%d\n", nZeros, Vec_IntSize(p->vValues) - nZeros ); + if ( nEncVars ) + { + int nBits = Vec_IntSize(p->vValues)/(1 << nEncVars); + assert( Vec_IntSize(p->vValues) == (1 << nEncVars) * nBits ); + Gia_Gen2CodePrint( nEncVars, nBits, p->vValues ); + } } if ( RetValue == -1 && nTimeOut && (Abc_Clock() - p->clkStart)/CLOCKS_PER_SEC >= nTimeOut ) printf( "The problem timed out after %d sec. ", nTimeOut ); diff --git a/abc/src/aig/gia/giaReshape1.c b/abc/src/aig/gia/giaReshape1.c new file mode 100644 index 00000000000..52b40bdcf1f --- /dev/null +++ b/abc/src/aig/gia/giaReshape1.c @@ -0,0 +1,56 @@ +/**CFile**************************************************************** + + FileName [giaReshape.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManReshape1( Gia_Man_t * p, int fUseSimple, int fVerbose, int fVeryVerbose ) +{ + return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaReshape2.c b/abc/src/aig/gia/giaReshape2.c new file mode 100644 index 00000000000..98a4d85594e --- /dev/null +++ b/abc/src/aig/gia/giaReshape2.c @@ -0,0 +1,55 @@ +/**CFile**************************************************************** + + FileName [giaReshape.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManReshape2( Gia_Man_t * p, int fUseSimple, int fVerbose, int fVeryVerbose ) +{ + return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaResub.c b/abc/src/aig/gia/giaResub.c index b8c0e2941e4..33fd5276d41 100644 --- a/abc/src/aig/gia/giaResub.c +++ b/abc/src/aig/gia/giaResub.c @@ -22,10 +22,10 @@ #include "misc/vec/vecWec.h" #include "misc/vec/vecQue.h" #include "misc/vec/vecHsh.h" +#include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START - //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// @@ -271,6 +271,520 @@ Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); } + + + +/**Function************************************************************* + + Synopsis [Resubstitution data-structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +typedef struct Gia_ResbMan_t_ Gia_ResbMan_t; +struct Gia_ResbMan_t_ +{ + int nWords; + int nLimit; + int nDivsMax; + int iChoice; + int fUseXor; + int fDebug; + int fVerbose; + int fVeryVerbose; + Vec_Ptr_t * vDivs; + Vec_Int_t * vGates; + Vec_Int_t * vUnateLits[2]; + Vec_Int_t * vNotUnateVars[2]; + Vec_Int_t * vUnatePairs[2]; + Vec_Int_t * vBinateVars; + Vec_Int_t * vUnateLitsW[2]; + Vec_Int_t * vUnatePairsW[2]; + Vec_Wec_t * vSorter; + word * pSets[2]; + word * pDivA; + word * pDivB; + Vec_Wrd_t * vSims; +}; +Gia_ResbMan_t * Gia_ResbAlloc( int nWords ) +{ + Gia_ResbMan_t * p = ABC_CALLOC( Gia_ResbMan_t, 1 ); + p->nWords = nWords; + p->vUnateLits[0] = Vec_IntAlloc( 100 ); + p->vUnateLits[1] = Vec_IntAlloc( 100 ); + p->vNotUnateVars[0] = Vec_IntAlloc( 100 ); + p->vNotUnateVars[1] = Vec_IntAlloc( 100 ); + p->vUnatePairs[0] = Vec_IntAlloc( 100 ); + p->vUnatePairs[1] = Vec_IntAlloc( 100 ); + p->vUnateLitsW[0] = Vec_IntAlloc( 100 ); + p->vUnateLitsW[1] = Vec_IntAlloc( 100 ); + p->vUnatePairsW[0] = Vec_IntAlloc( 100 ); + p->vUnatePairsW[1] = Vec_IntAlloc( 100 ); + p->vSorter = Vec_WecAlloc( nWords*64 ); + p->vBinateVars = Vec_IntAlloc( 100 ); + p->vGates = Vec_IntAlloc( 100 ); + p->vDivs = Vec_PtrAlloc( 100 ); + p->pSets[0] = ABC_CALLOC( word, nWords ); + p->pSets[1] = ABC_CALLOC( word, nWords ); + p->pDivA = ABC_CALLOC( word, nWords ); + p->pDivB = ABC_CALLOC( word, nWords ); + p->vSims = Vec_WrdAlloc( 100 ); + return p; +} +void Gia_ResbInit( Gia_ResbMan_t * p, Vec_Ptr_t * vDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, int fVeryVerbose ) +{ + assert( p->nWords == nWords ); + p->nLimit = nLimit; + p->nDivsMax = nDivsMax; + p->iChoice = iChoice; + p->fUseXor = fUseXor; + p->fDebug = fDebug; + p->fVerbose = fVerbose; + p->fVeryVerbose = fVeryVerbose; + Abc_TtCopy( p->pSets[0], (word *)Vec_PtrEntry(vDivs, 0), nWords, 0 ); + Abc_TtCopy( p->pSets[1], (word *)Vec_PtrEntry(vDivs, 1), nWords, 0 ); + Vec_PtrClear( p->vDivs ); + Vec_PtrAppend( p->vDivs, vDivs ); + Vec_IntClear( p->vGates ); + Vec_IntClear( p->vUnateLits[0] ); + Vec_IntClear( p->vUnateLits[1] ); + Vec_IntClear( p->vNotUnateVars[0] ); + Vec_IntClear( p->vNotUnateVars[1] ); + Vec_IntClear( p->vUnatePairs[0] ); + Vec_IntClear( p->vUnatePairs[1] ); + Vec_IntClear( p->vUnateLitsW[0] ); + Vec_IntClear( p->vUnateLitsW[1] ); + Vec_IntClear( p->vUnatePairsW[0] ); + Vec_IntClear( p->vUnatePairsW[1] ); + Vec_IntClear( p->vBinateVars ); +} +void Gia_ResbFree( Gia_ResbMan_t * p ) +{ + Vec_IntFree( p->vUnateLits[0] ); + Vec_IntFree( p->vUnateLits[1] ); + Vec_IntFree( p->vNotUnateVars[0] ); + Vec_IntFree( p->vNotUnateVars[1] ); + Vec_IntFree( p->vUnatePairs[0] ); + Vec_IntFree( p->vUnatePairs[1] ); + Vec_IntFree( p->vUnateLitsW[0] ); + Vec_IntFree( p->vUnateLitsW[1] ); + Vec_IntFree( p->vUnatePairsW[0] ); + Vec_IntFree( p->vUnatePairsW[1] ); + Vec_IntFree( p->vBinateVars ); + Vec_IntFree( p->vGates ); + Vec_WrdFree( p->vSims ); + Vec_PtrFree( p->vDivs ); + Vec_WecFree( p->vSorter ); + ABC_FREE( p->pSets[0] ); + ABC_FREE( p->pSets[1] ); + ABC_FREE( p->pDivA ); + ABC_FREE( p->pDivB ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Print resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManResubPrintNode( Vec_Int_t * vRes, int nVars, int Node, int fCompl ) +{ + extern void Gia_ManResubPrintLit( Vec_Int_t * vRes, int nVars, int iLit ); + int iLit0 = Vec_IntEntry( vRes, 2*Node + 0 ); + int iLit1 = Vec_IntEntry( vRes, 2*Node + 1 ); + assert( iLit0 != iLit1 ); + if ( iLit0 > iLit1 && Abc_LitIsCompl(fCompl) ) // xor + { + printf( "~" ); + fCompl = 0; + } + printf( "(" ); + Gia_ManResubPrintLit( vRes, nVars, Abc_LitNotCond(iLit0, fCompl) ); + printf( " %c ", iLit0 > iLit1 ? '^' : (fCompl ? '|' : '&') ); + Gia_ManResubPrintLit( vRes, nVars, Abc_LitNotCond(iLit1, fCompl) ); + printf( ")" ); +} +void Gia_ManResubPrintLit( Vec_Int_t * vRes, int nVars, int iLit ) +{ + if ( Abc_Lit2Var(iLit) < nVars ) + { + if ( nVars < 26 ) + printf( "%s%c", Abc_LitIsCompl(iLit) ? "~":"", 'a' + Abc_Lit2Var(iLit)-2 ); + else + printf( "%si%d", Abc_LitIsCompl(iLit) ? "~":"", Abc_Lit2Var(iLit)-2 ); + } + else + Gia_ManResubPrintNode( vRes, nVars, Abc_Lit2Var(iLit) - nVars, Abc_LitIsCompl(iLit) ); +} +int Gia_ManResubPrint( Vec_Int_t * vRes, int nVars ) +{ + int iTopLit; + if ( Vec_IntSize(vRes) == 0 ) + return printf( "none" ); + assert( Vec_IntSize(vRes) % 2 == 1 ); + iTopLit = Vec_IntEntryLast(vRes); + if ( iTopLit == 0 ) + return printf( "const0" ); + if ( iTopLit == 1 ) + return printf( "const1" ); + Gia_ManResubPrintLit( vRes, nVars, iTopLit ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Verify resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManResubVerify( Gia_ResbMan_t * p, word * pFunc ) +{ + int nVars = Vec_PtrSize(p->vDivs); + int iTopLit, RetValue; + word * pDivRes; + if ( Vec_IntSize(p->vGates) == 0 ) + return -1; + iTopLit = Vec_IntEntryLast(p->vGates); + assert( iTopLit >= 0 ); + if ( iTopLit == 0 ) + { + if ( pFunc ) Abc_TtClear( pFunc, p->nWords ); + return Abc_TtIsConst0( p->pSets[1], p->nWords ); + } + if ( iTopLit == 1 ) + { + if ( pFunc ) Abc_TtFill( pFunc, p->nWords ); + return Abc_TtIsConst0( p->pSets[0], p->nWords ); + } + if ( Abc_Lit2Var(iTopLit) < nVars ) + { + assert( Vec_IntSize(p->vGates) == 1 ); + pDivRes = (word *)Vec_PtrEntry( p->vDivs, Abc_Lit2Var(iTopLit) ); + } + else + { + int i, iLit0, iLit1; + assert( Vec_IntSize(p->vGates) > 1 ); + assert( Vec_IntSize(p->vGates) % 2 == 1 ); + assert( Abc_Lit2Var(iTopLit)-nVars == Vec_IntSize(p->vGates)/2-1 ); + Vec_WrdFill( p->vSims, p->nWords * Vec_IntSize(p->vGates)/2, 0 ); + Vec_IntForEachEntryDouble( p->vGates, iLit0, iLit1, i ) + { + int iVar0 = Abc_Lit2Var(iLit0); + int iVar1 = Abc_Lit2Var(iLit1); + word * pDiv0 = iVar0 < nVars ? (word *)Vec_PtrEntry(p->vDivs, iVar0) : Vec_WrdEntryP(p->vSims, p->nWords*(iVar0 - nVars)); + word * pDiv1 = iVar1 < nVars ? (word *)Vec_PtrEntry(p->vDivs, iVar1) : Vec_WrdEntryP(p->vSims, p->nWords*(iVar1 - nVars)); + word * pDiv = Vec_WrdEntryP(p->vSims, p->nWords*i/2); + if ( iVar0 < iVar1 ) + Abc_TtAndCompl( pDiv, pDiv0, Abc_LitIsCompl(iLit0), pDiv1, Abc_LitIsCompl(iLit1), p->nWords ); + else if ( iVar0 > iVar1 ) + { + assert( !Abc_LitIsCompl(iLit0) ); + assert( !Abc_LitIsCompl(iLit1) ); + Abc_TtXor( pDiv, pDiv0, pDiv1, p->nWords, 0 ); + } + else assert( 0 ); + } + pDivRes = Vec_WrdEntryP( p->vSims, p->nWords*(Vec_IntSize(p->vGates)/2-1) ); + } + if ( Abc_LitIsCompl(iTopLit) ) + RetValue = !Abc_TtIntersectOne(p->pSets[1], 0, pDivRes, 0, p->nWords) && !Abc_TtIntersectOne(p->pSets[0], 0, pDivRes, 1, p->nWords); + else + RetValue = !Abc_TtIntersectOne(p->pSets[0], 0, pDivRes, 0, p->nWords) && !Abc_TtIntersectOne(p->pSets[1], 0, pDivRes, 1, p->nWords); + if ( pFunc ) Abc_TtCopy( pFunc, pDivRes, p->nWords, Abc_LitIsCompl(iTopLit) ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Construct AIG manager from gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManConstructFromMap( Gia_Man_t * pNew, Vec_Int_t * vGates, int nVars, Vec_Int_t * vUsed, Vec_Int_t * vCopy, int fHash ) +{ + int i, iLit0, iLit1, iLitRes, iTopLit = Vec_IntEntryLast( vGates ); + assert( Vec_IntSize(vUsed) == nVars ); + assert( Vec_IntSize(vGates) > 1 ); + assert( Vec_IntSize(vGates) % 2 == 1 ); + assert( Abc_Lit2Var(iTopLit)-nVars == Vec_IntSize(vGates)/2-1 ); + Vec_IntClear( vCopy ); + Vec_IntForEachEntryDouble( vGates, iLit0, iLit1, i ) + { + int iVar0 = Abc_Lit2Var(iLit0); + int iVar1 = Abc_Lit2Var(iLit1); + int iRes0 = iVar0 < nVars ? Vec_IntEntry(vUsed, iVar0) : Vec_IntEntry(vCopy, iVar0 - nVars); + int iRes1 = iVar1 < nVars ? Vec_IntEntry(vUsed, iVar1) : Vec_IntEntry(vCopy, iVar1 - nVars); + if ( iVar0 < iVar1 ) + { + if ( fHash ) + iLitRes = Gia_ManHashAnd( pNew, Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)), Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)) ); + else + iLitRes = Gia_ManAppendAnd( pNew, Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)), Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)) ); + } + else if ( iVar0 > iVar1 ) + { + assert( !Abc_LitIsCompl(iLit0) ); + assert( !Abc_LitIsCompl(iLit1) ); + if ( fHash ) + iLitRes = Gia_ManHashXor( pNew, Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)), Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)) ); + else + iLitRes = Gia_ManAppendXor( pNew, Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)), Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)) ); + } + else assert( 0 ); + Vec_IntPush( vCopy, iLitRes ); + } + assert( Vec_IntSize(vCopy) == Vec_IntSize(vGates)/2 ); + iLitRes = Vec_IntEntry( vCopy, Vec_IntSize(vGates)/2-1 ); + return iLitRes; +} +Gia_Man_t * Gia_ManConstructFromGates( Vec_Wec_t * vFuncs, int nDivs ) +{ + Vec_Int_t * vGates; int i, k, iLit; + Vec_Int_t * vCopy = Vec_IntAlloc( 100 ); + Vec_Int_t * vUsed = Vec_IntStartFull( nDivs ); + Gia_Man_t * pNew = Gia_ManStart( 100 ); + pNew->pName = Abc_UtilStrsav( "resub" ); + Vec_WecForEachLevel( vFuncs, vGates, i ) + { + assert( Vec_IntSize(vGates) % 2 == 1 ); + Vec_IntForEachEntry( vGates, iLit, k ) + { + int iVar = Abc_Lit2Var(iLit); + if ( iVar > 0 && iVar < nDivs && Vec_IntEntry(vUsed, iVar) == -1 ) + Vec_IntWriteEntry( vUsed, iVar, Gia_ManAppendCi(pNew) ); + } + } + Vec_WecForEachLevel( vFuncs, vGates, i ) + { + int iLitRes, iTopLit = Vec_IntEntryLast( vGates ); + if ( Abc_Lit2Var(iTopLit) == 0 ) + iLitRes = 0; + else if ( Abc_Lit2Var(iTopLit) < nDivs ) + iLitRes = Vec_IntEntry( vUsed, Abc_Lit2Var(iTopLit) ); + else + iLitRes = Gia_ManConstructFromMap( pNew, vGates, nDivs, vUsed, vCopy, 0 ); + Gia_ManAppendCo( pNew, Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iTopLit) ) ); + } + Vec_IntFree( vCopy ); + Vec_IntFree( vUsed ); + return pNew; +} +Gia_Man_t * Gia_ManConstructFromGates2( Vec_Wec_t * vFuncs, Vec_Wec_t * vDivs, int nObjs, Vec_Int_t ** pvSupp ) +{ + Vec_Int_t * vGates; int i, k, iVar, iLit; + Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); + Vec_Int_t * vCopy = Vec_IntAlloc( 100 ); + Vec_Wec_t * vUseds = Vec_WecStart( Vec_WecSize(vDivs) ); + Vec_Int_t * vMap = Vec_IntStartFull( nObjs ); + Gia_Man_t * pNew = Gia_ManStart( 100 ); + pNew->pName = Abc_UtilStrsav( "resub" ); + assert( Vec_WecSize(vFuncs) == Vec_WecSize(vDivs) ); + Vec_WecForEachLevel( vFuncs, vGates, i ) + { + Vec_Int_t * vDiv = Vec_WecEntry( vDivs, i ); + assert( Vec_IntSize(vGates) % 2 == 1 ); + Vec_IntForEachEntry( vGates, iLit, k ) + { + int iVar = Abc_Lit2Var(iLit); + if ( iVar > 0 && iVar < Vec_IntSize(vDiv) && Vec_IntEntry(vMap, Vec_IntEntry(vDiv, iVar)) == -1 ) + Vec_IntWriteEntry( vMap, Vec_IntPushReturn(vSupp, Vec_IntEntry(vDiv, iVar)), 0 ); + } + } + Vec_IntSort( vSupp, 0 ); + Vec_IntForEachEntry( vSupp, iVar, k ) + Vec_IntWriteEntry( vMap, iVar, Gia_ManAppendCi(pNew) ); + Vec_WecForEachLevel( vFuncs, vGates, i ) + { + Vec_Int_t * vDiv = Vec_WecEntry( vDivs, i ); + Vec_Int_t * vUsed = Vec_WecEntry( vUseds, i ); + Vec_IntFill( vUsed, Vec_IntSize(vDiv), -1 ); + Vec_IntForEachEntry( vGates, iLit, k ) + { + int iVar = Abc_Lit2Var(iLit); + if ( iVar > 0 && iVar < Vec_IntSize(vDiv) ) + { + assert( Vec_IntEntry(vMap, Vec_IntEntry(vDiv, iVar)) > 0 ); + Vec_IntWriteEntry( vUsed, iVar, Vec_IntEntry(vMap, Vec_IntEntry(vDiv, iVar)) ); + } + } + } + Vec_WecForEachLevel( vFuncs, vGates, i ) + { + Vec_Int_t * vDiv = Vec_WecEntry( vDivs, i ); + Vec_Int_t * vUsed = Vec_WecEntry( vUseds, i ); + int iLitRes, iTopLit = Vec_IntEntryLast( vGates ); + if ( Abc_Lit2Var(iTopLit) == 0 ) + iLitRes = 0; + else if ( Abc_Lit2Var(iTopLit) < Vec_IntSize(vDiv) ) + iLitRes = Vec_IntEntry( vUsed, Abc_Lit2Var(iTopLit) ); + else + iLitRes = Gia_ManConstructFromMap( pNew, vGates, Vec_IntSize(vDiv), vUsed, vCopy, 0 ); + Gia_ManAppendCo( pNew, Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iTopLit) ) ); + } + Vec_IntFree( vMap ); + Vec_IntFree( vCopy ); + Vec_WecFree( vUseds ); + if ( pvSupp ) + *pvSupp = vSupp; + else + Vec_IntFree( vSupp ); + return pNew; +} +Vec_Int_t * Gia_ManToGates( Gia_Man_t * p ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( 2*Gia_ManAndNum(p) + 1 ); + Gia_Obj_t * pRoot = Gia_ManCo( p, 0 ); + int iRoot = Gia_ObjFaninId0p(p, pRoot) - 1; + int nVars = Gia_ManCiNum(p); + assert( Gia_ManCoNum(p) == 1 ); + if ( iRoot == -1 ) + Vec_IntPush( vRes, Gia_ObjFaninC0(pRoot) ); + else if ( iRoot < nVars ) + Vec_IntPush( vRes, 4 + Abc_Var2Lit(iRoot, Gia_ObjFaninC0(pRoot)) ); + else + { + Gia_Obj_t * pObj, * pLast = NULL; int i; + Gia_ManForEachCi( p, pObj, i ) + assert( Gia_ObjId(p, pObj) == i+1 ); + Gia_ManForEachAnd( p, pObj, i ) + { + int iLit0 = Abc_Var2Lit( Gia_ObjFaninId0(pObj, i) - 1, Gia_ObjFaninC0(pObj) ); + int iLit1 = Abc_Var2Lit( Gia_ObjFaninId1(pObj, i) - 1, Gia_ObjFaninC1(pObj) ); + if ( iLit0 > iLit1 ) + iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1; + Vec_IntPushTwo( vRes, 4 + iLit0, 4 + iLit1 ); + pLast = pObj; + } + assert( pLast == Gia_ObjFanin0(pRoot) ); + Vec_IntPush( vRes, 4 + Abc_Var2Lit(iRoot, Gia_ObjFaninC0(pRoot)) ); + } + assert( Vec_IntSize(vRes) == 2*Gia_ManAndNum(p) + 1 ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Construct AIG manager from gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManInsertOrder_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vObjs, Vec_Wec_t * vFuncs, Vec_Int_t * vNodes ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + if ( iObj == 0 ) + return; + if ( pObj->fPhase ) + { + int nVars = Gia_ManObjNum(p); + int k, iLit, Index = Vec_IntFind( vObjs, iObj ); + Vec_Int_t * vGates = Vec_WecEntry( vFuncs, Index ); + assert( Gia_ObjIsCo(pObj) || Gia_ObjIsAnd(pObj) ); + Vec_IntForEachEntry( vGates, iLit, k ) + if ( Abc_Lit2Var(iLit) < nVars ) + Gia_ManInsertOrder_rec( p, Abc_Lit2Var(iLit), vObjs, vFuncs, vNodes ); + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ManInsertOrder_rec( p, Gia_ObjFaninId0p(p, pObj), vObjs, vFuncs, vNodes ); + else if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManInsertOrder_rec( p, Gia_ObjFaninId0p(p, pObj), vObjs, vFuncs, vNodes ); + Gia_ManInsertOrder_rec( p, Gia_ObjFaninId1p(p, pObj), vObjs, vFuncs, vNodes ); + } + else assert( Gia_ObjIsCi(pObj) ); + if ( !Gia_ObjIsCi(pObj) ) + Vec_IntPush( vNodes, iObj ); +} +Vec_Int_t * Gia_ManInsertOrder( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wec_t * vFuncs ) +{ + int i, Id; + Vec_Int_t * vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_ManForEachCoId( p, Id, i ) + Gia_ManInsertOrder_rec( p, Id, vObjs, vFuncs, vNodes ); + return vNodes; +} +Gia_Man_t * Gia_ManInsertFromGates( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wec_t * vFuncs ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, nVars = Gia_ManObjNum(p); + Vec_Int_t * vUsed = Vec_IntStartFull( nVars ); + Vec_Int_t * vNodes, * vCopy = Vec_IntAlloc(100); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->fPhase = 1; + vNodes = Gia_ManInsertOrder( p, vObjs, vFuncs ); + pNew = Gia_ManStart( Gia_ManObjNum(p) + 1000 ); + Gia_ManHashStart( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + if ( !pObj->fPhase ) + { + if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else assert( 0 ); + } + else + { + int k, iLit, Index = Vec_IntFind( vObjs, Gia_ObjId(p, pObj) ); + Vec_Int_t * vGates = Vec_WecEntry( vFuncs, Index ); + int iLitRes, iTopLit = Vec_IntEntryLast( vGates ); + if ( Abc_Lit2Var(iTopLit) == 0 ) + iLitRes = 0; + else if ( Abc_Lit2Var(iTopLit) < nVars ) + iLitRes = Gia_ManObj(p, Abc_Lit2Var(iTopLit))->Value; + else + { + Vec_IntForEachEntry( vGates, iLit, k ) + Vec_IntWriteEntry( vUsed, Abc_Lit2Var(iLit), Gia_ManObj(p, Abc_Lit2Var(iLit))->Value ); + iLitRes = Gia_ManConstructFromMap( pNew, vGates, nVars, vUsed, vCopy, 1 ); + Vec_IntForEachEntry( vGates, iLit, k ) + Vec_IntWriteEntry( vUsed, Abc_Lit2Var(iLit), -1 ); + } + pObj->Value = Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iTopLit) ); + } + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->fPhase = 0; + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vNodes ); + Vec_IntFree( vUsed ); + Vec_IntFree( vCopy ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + /**Function************************************************************* Synopsis [Perform resubstitution.] @@ -282,6 +796,1257 @@ Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); SeeAlso [] ***********************************************************************/ +static inline int Gia_ManFindFirstCommonLit( Vec_Int_t * vArr1, Vec_Int_t * vArr2, int fVerbose ) +{ + int * pBeg1 = vArr1->pArray; + int * pBeg2 = vArr2->pArray; + int * pEnd1 = vArr1->pArray + vArr1->nSize; + int * pEnd2 = vArr2->pArray + vArr2->nSize; + int * pStart1 = vArr1->pArray; + int * pStart2 = vArr2->pArray; + int nRemoved = 0; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( Abc_Lit2Var(*pBeg1) == Abc_Lit2Var(*pBeg2) ) + { + if ( *pBeg1 != *pBeg2 ) + return *pBeg1; + else + pBeg1++, pBeg2++; + nRemoved++; + } + else if ( *pBeg1 < *pBeg2 ) + *pStart1++ = *pBeg1++; + else + *pStart2++ = *pBeg2++; + } + while ( pBeg1 < pEnd1 ) + *pStart1++ = *pBeg1++; + while ( pBeg2 < pEnd2 ) + *pStart2++ = *pBeg2++; + Vec_IntShrink( vArr1, pStart1 - vArr1->pArray ); + Vec_IntShrink( vArr2, pStart2 - vArr2->pArray ); + //if ( fVerbose ) printf( "Removed %d duplicated entries. Array1 = %d. Array2 = %d.\n", nRemoved, Vec_IntSize(vArr1), Vec_IntSize(vArr2) ); + return -1; +} + +void Gia_ManFindOneUnateInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits, Vec_Int_t * vNotUnateVars ) +{ + word * pDiv; int i; + Vec_IntClear( vUnateLits ); + Vec_IntClear( vNotUnateVars ); + Vec_PtrForEachEntryStart( word *, vDivs, pDiv, i, 2 ) + if ( !Abc_TtIntersectOne( pOff, 0, pDiv, 0, nWords ) ) + Vec_IntPush( vUnateLits, Abc_Var2Lit(i, 0) ); + else if ( !Abc_TtIntersectOne( pOff, 0, pDiv, 1, nWords ) ) + Vec_IntPush( vUnateLits, Abc_Var2Lit(i, 1) ); + else + Vec_IntPush( vNotUnateVars, i ); +} +int Gia_ManFindOneUnate( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits[2], Vec_Int_t * vNotUnateVars[2], int fVerbose ) +{ + int n; + if ( fVerbose ) printf( " " ); + for ( n = 0; n < 2; n++ ) + { + Gia_ManFindOneUnateInt( pSets[n], pSets[!n], vDivs, nWords, vUnateLits[n], vNotUnateVars[n] ); + if ( fVerbose ) printf( "U%d =%4d ", n, Vec_IntSize(vUnateLits[n]) ); + } + return Gia_ManFindFirstCommonLit( vUnateLits[0], vUnateLits[1], fVerbose ); +} + +static inline int Gia_ManDivCover( word * pOff, word * pOn, word * pDivA, int ComplA, word * pDivB, int ComplB, int nWords ) +{ + //assert( !Abc_TtIntersectOne(pOff, 0, pDivA, ComplA, nWords) ); + //assert( !Abc_TtIntersectOne(pOff, 0, pDivB, ComplB, nWords) ); + return !Abc_TtIntersectTwo( pOn, 0, pDivA, !ComplA, pDivB, !ComplB, nWords ); +} +int Gia_ManFindTwoUnateInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits, Vec_Int_t * vUnateLitsW, int * pnPairs ) +{ + int i, k, iDiv0_, iDiv1_, Cover0, Cover1; + int nTotal = Abc_TtCountOnesVec( pOn, nWords ); + (*pnPairs) = 0; + Vec_IntForEachEntryTwo( vUnateLits, vUnateLitsW, iDiv0_, Cover0, i ) + { + if ( 2*Cover0 < nTotal ) + break; + Vec_IntForEachEntryTwoStart( vUnateLits, vUnateLitsW, iDiv1_, Cover1, k, i+1 ) + { + int iDiv0 = Abc_MinInt( iDiv0_, iDiv1_ ); + int iDiv1 = Abc_MaxInt( iDiv0_, iDiv1_ ); + word * pDiv0 = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iDiv0)); + word * pDiv1 = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iDiv1)); + if ( Cover0 + Cover1 < nTotal ) + break; + (*pnPairs)++; + if ( Gia_ManDivCover(pOff, pOn, pDiv1, Abc_LitIsCompl(iDiv1), pDiv0, Abc_LitIsCompl(iDiv0), nWords) ) + return Abc_Var2Lit((Abc_LitNot(iDiv1) << 15) | Abc_LitNot(iDiv0), 1); + } + } + return -1; +} +int Gia_ManFindTwoUnate( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits[2], Vec_Int_t * vUnateLitsW[2], int fVerbose ) +{ + int n, iLit, nPairs; + if ( fVerbose ) printf( " " ); + for ( n = 0; n < 2; n++ ) + { + //int nPairsAll = Vec_IntSize(vUnateLits[n])*(Vec_IntSize(vUnateLits[n])-1)/2; + iLit = Gia_ManFindTwoUnateInt( pSets[n], pSets[!n], vDivs, nWords, vUnateLits[n], vUnateLitsW[n], &nPairs ); + if ( fVerbose ) printf( "UU%d =%5d ", n, nPairs ); + if ( iLit >= 0 ) + return Abc_LitNotCond(iLit, n); + } + return -1; +} + +void Gia_ManFindXorInt( word * pOff, word * pOn, Vec_Int_t * vBinate, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnatePairs ) +{ + int i, k, iDiv0_, iDiv1_; + int Limit2 = Vec_IntSize(vBinate);//Abc_MinInt( Vec_IntSize(vBinate), 100 ); + Vec_IntForEachEntryStop( vBinate, iDiv1_, i, Limit2 ) + Vec_IntForEachEntryStop( vBinate, iDiv0_, k, i ) + { + int iDiv0 = Abc_MinInt( iDiv0_, iDiv1_ ); + int iDiv1 = Abc_MaxInt( iDiv0_, iDiv1_ ); + word * pDiv0 = (word *)Vec_PtrEntry(vDivs, iDiv0); + word * pDiv1 = (word *)Vec_PtrEntry(vDivs, iDiv1); + if ( !Abc_TtIntersectXor( pOff, 0, pDiv0, pDiv1, 0, nWords ) ) + Vec_IntPush( vUnatePairs, Abc_Var2Lit((Abc_Var2Lit(iDiv0, 0) << 15) | Abc_Var2Lit(iDiv1, 0), 0) ); + else if ( !Abc_TtIntersectXor( pOff, 0, pDiv0, pDiv1, 1, nWords ) ) + Vec_IntPush( vUnatePairs, Abc_Var2Lit((Abc_Var2Lit(iDiv0, 0) << 15) | Abc_Var2Lit(iDiv1, 0), 1) ); + } +} +int Gia_ManFindXor( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vBinateVars, Vec_Int_t * vUnatePairs[2], int fVerbose ) +{ + int n; + if ( fVerbose ) printf( " " ); + for ( n = 0; n < 2; n++ ) + { + Vec_IntClear( vUnatePairs[n] ); + Gia_ManFindXorInt( pSets[n], pSets[!n], vBinateVars, vDivs, nWords, vUnatePairs[n] ); + if ( fVerbose ) printf( "UX%d =%5d ", n, Vec_IntSize(vUnatePairs[n]) ); + } + return Gia_ManFindFirstCommonLit( vUnatePairs[0], vUnatePairs[1], fVerbose ); +} + +void Gia_ManFindUnatePairsInt( word * pOff, word * pOn, Vec_Int_t * vBinate, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnatePairs ) +{ + int n, i, k, iDiv0_, iDiv1_; + int Limit2 = Vec_IntSize(vBinate);//Abc_MinInt( Vec_IntSize(vBinate), 100 ); + Vec_IntForEachEntryStop( vBinate, iDiv1_, i, Limit2 ) + Vec_IntForEachEntryStop( vBinate, iDiv0_, k, i ) + { + int iDiv0 = Abc_MinInt( iDiv0_, iDiv1_ ); + int iDiv1 = Abc_MaxInt( iDiv0_, iDiv1_ ); + word * pDiv0 = (word *)Vec_PtrEntry(vDivs, iDiv0); + word * pDiv1 = (word *)Vec_PtrEntry(vDivs, iDiv1); + for ( n = 0; n < 4; n++ ) + { + int iLit0 = Abc_Var2Lit( iDiv0, n&1 ); + int iLit1 = Abc_Var2Lit( iDiv1, n>>1 ); + //if ( !Abc_TtIntersectTwo( pOff, 0, pDiv1, n>>1, pDiv0, n&1, nWords ) ) + if ( !Abc_TtIntersectTwo( pOff, 0, pDiv1, n>>1, pDiv0, n&1, nWords ) && Abc_TtIntersectTwo( pOn, 0, pDiv1, n>>1, pDiv0, n&1, nWords ) ) + Vec_IntPush( vUnatePairs, Abc_Var2Lit((iLit1 << 15) | iLit0, 0) ); + } + } +} +void Gia_ManFindUnatePairs( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vBinateVars, Vec_Int_t * vUnatePairs[2], int fVerbose ) +{ + int n, RetValue; + if ( fVerbose ) printf( " " ); + for ( n = 0; n < 2; n++ ) + { + int nBefore = Vec_IntSize(vUnatePairs[n]); + Gia_ManFindUnatePairsInt( pSets[n], pSets[!n], vBinateVars, vDivs, nWords, vUnatePairs[n] ); + if ( fVerbose ) printf( "UP%d =%5d ", n, Vec_IntSize(vUnatePairs[n])-nBefore ); + } + RetValue = Gia_ManFindFirstCommonLit( vUnatePairs[0], vUnatePairs[1], fVerbose ); + assert( RetValue == -1 ); +} + +void Gia_ManDeriveDivPair( int iDiv, Vec_Ptr_t * vDivs, int nWords, word * pRes ) +{ + int fComp = Abc_LitIsCompl(iDiv); + int iDiv0 = Abc_Lit2Var(iDiv) & 0x7FFF; + int iDiv1 = Abc_Lit2Var(iDiv) >> 15; + word * pDiv0 = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iDiv0)); + word * pDiv1 = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iDiv1)); + if ( iDiv0 < iDiv1 ) + { + assert( !fComp ); + Abc_TtAndCompl( pRes, pDiv0, Abc_LitIsCompl(iDiv0), pDiv1, Abc_LitIsCompl(iDiv1), nWords ); + } + else + { + assert( !Abc_LitIsCompl(iDiv0) ); + assert( !Abc_LitIsCompl(iDiv1) ); + Abc_TtXor( pRes, pDiv0, pDiv1, nWords, 0 ); + } +} +int Gia_ManFindDivGateInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits, Vec_Int_t * vUnatePairs, Vec_Int_t * vUnateLitsW, Vec_Int_t * vUnatePairsW, word * pDivTemp ) +{ + int i, k, iDiv0, iDiv1, Cover0, Cover1; + int nTotal = Abc_TtCountOnesVec( pOn, nWords ); + Vec_IntForEachEntryTwo( vUnateLits, vUnateLitsW, iDiv0, Cover0, i ) + { + word * pDiv0 = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iDiv0)); + if ( 2*Cover0 < nTotal ) + break; + Vec_IntForEachEntryTwo( vUnatePairs, vUnatePairsW, iDiv1, Cover1, k ) + { + int fComp1 = Abc_LitIsCompl(iDiv1); + if ( Cover0 + Cover1 < nTotal ) + break; + Gia_ManDeriveDivPair( iDiv1, vDivs, nWords, pDivTemp ); + if ( Gia_ManDivCover(pOff, pOn, pDiv0, Abc_LitIsCompl(iDiv0), pDivTemp, fComp1, nWords) ) + return Abc_Var2Lit((Abc_Var2Lit(k, 1) << 15) | Abc_LitNot(iDiv0), 1); + } + } + return -1; +} +int Gia_ManFindDivGate( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits[2], Vec_Int_t * vUnatePairs[2], Vec_Int_t * vUnateLitsW[2], Vec_Int_t * vUnatePairsW[2], word * pDivTemp ) +{ + int n, iLit; + for ( n = 0; n < 2; n++ ) + { + iLit = Gia_ManFindDivGateInt( pSets[n], pSets[!n], vDivs, nWords, vUnateLits[n], vUnatePairs[n], vUnateLitsW[n], vUnatePairsW[n], pDivTemp ); + if ( iLit >= 0 ) + return Abc_LitNotCond( iLit, n ); + } + return -1; +} + +int Gia_ManFindGateGateInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnatePairs, Vec_Int_t * vUnatePairsW, word * pDivTempA, word * pDivTempB ) +{ + int i, k, iDiv0, iDiv1, Cover0, Cover1; + int nTotal = Abc_TtCountOnesVec( pOn, nWords ); + Vec_IntForEachEntryTwo( vUnatePairs, vUnatePairsW, iDiv0, Cover0, k ) + { + int fCompA = Abc_LitIsCompl(iDiv0); + if ( 2*Cover0 < nTotal ) + break; + Gia_ManDeriveDivPair( iDiv0, vDivs, nWords, pDivTempA ); + Vec_IntForEachEntryTwoStart( vUnatePairs, vUnatePairsW, iDiv1, Cover1, i, k+1 ) + { + int fCompB = Abc_LitIsCompl(iDiv1); + if ( Cover0 + Cover1 < nTotal ) + break; + Gia_ManDeriveDivPair( iDiv1, vDivs, nWords, pDivTempB ); + if ( Gia_ManDivCover(pOff, pOn, pDivTempA, fCompA, pDivTempB, fCompB, nWords) ) + return Abc_Var2Lit((Abc_Var2Lit(i, 1) << 15) | Abc_Var2Lit(k, 1), 1); + } + } + return -1; +} +int Gia_ManFindGateGate( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnatePairs[2], Vec_Int_t * vUnatePairsW[2], word * pDivTempA, word * pDivTempB ) +{ + int n, iLit; + for ( n = 0; n < 2; n++ ) + { + iLit = Gia_ManFindGateGateInt( pSets[n], pSets[!n], vDivs, nWords, vUnatePairs[n], vUnatePairsW[n], pDivTempA, pDivTempB ); + if ( iLit >= 0 ) + return Abc_LitNotCond( iLit, n ); + } + return -1; +} + +void Gia_ManSortUnatesInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits, Vec_Int_t * vUnateLitsW, Vec_Wec_t * vSorter ) +{ + int i, k, iLit; + Vec_Int_t * vLevel; + Vec_WecInit( vSorter, nWords*64 ); + Vec_IntForEachEntry( vUnateLits, iLit, i ) + { + word * pDiv = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iLit)); + //assert( !Abc_TtIntersectOne( pOff, 0, pDiv, Abc_LitIsCompl(iLit), nWords ) ); + Vec_WecPush( vSorter, Abc_TtCountOnesVecMask(pDiv, pOn, nWords, Abc_LitIsCompl(iLit)), iLit ); + } + Vec_IntClear( vUnateLits ); + Vec_IntClear( vUnateLitsW ); + Vec_WecForEachLevelReverse( vSorter, vLevel, k ) + Vec_IntForEachEntry( vLevel, iLit, i ) + { + Vec_IntPush( vUnateLits, iLit ); + Vec_IntPush( vUnateLitsW, k ); + } + //Vec_IntPrint( Vec_WecEntry(vSorter, 0) ); + Vec_WecClear( vSorter ); +} +void Gia_ManSortUnates( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits[2], Vec_Int_t * vUnateLitsW[2], Vec_Wec_t * vSorter ) +{ + int n; + for ( n = 0; n < 2; n++ ) + Gia_ManSortUnatesInt( pSets[n], pSets[!n], vDivs, nWords, vUnateLits[n], vUnateLitsW[n], vSorter ); +} + +void Gia_ManSortPairsInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnatePairs, Vec_Int_t * vUnatePairsW, Vec_Wec_t * vSorter ) +{ + int i, k, iPair; + Vec_Int_t * vLevel; + Vec_WecInit( vSorter, nWords*64 ); + Vec_IntForEachEntry( vUnatePairs, iPair, i ) + { + int fComp = Abc_LitIsCompl(iPair); + int iLit0 = Abc_Lit2Var(iPair) & 0x7FFF; + int iLit1 = Abc_Lit2Var(iPair) >> 15; + word * pDiv0 = (word *)Vec_PtrEntry( vDivs, Abc_Lit2Var(iLit0) ); + word * pDiv1 = (word *)Vec_PtrEntry( vDivs, Abc_Lit2Var(iLit1) ); + if ( iLit0 < iLit1 ) + { + assert( !fComp ); + //assert( !Abc_TtIntersectTwo( pOff, 0, pDiv0, Abc_LitIsCompl(iLit0), pDiv1, Abc_LitIsCompl(iLit1), nWords ) ); + Vec_WecPush( vSorter, Abc_TtCountOnesVecMask2(pDiv0, pDiv1, Abc_LitIsCompl(iLit0), Abc_LitIsCompl(iLit1), pOn, nWords), iPair ); + } + else + { + assert( !Abc_LitIsCompl(iLit0) ); + assert( !Abc_LitIsCompl(iLit1) ); + //assert( !Abc_TtIntersectXor( pOff, 0, pDiv0, pDiv1, fComp, nWords ) ); + Vec_WecPush( vSorter, Abc_TtCountOnesVecXorMask(pDiv0, pDiv1, fComp, pOn, nWords), iPair ); + } + } + Vec_IntClear( vUnatePairs ); + Vec_IntClear( vUnatePairsW ); + Vec_WecForEachLevelReverse( vSorter, vLevel, k ) + Vec_IntForEachEntry( vLevel, iPair, i ) + { + Vec_IntPush( vUnatePairs, iPair ); + Vec_IntPush( vUnatePairsW, k ); + } + //Vec_IntPrint( Vec_WecEntry(vSorter, 0) ); + Vec_WecClear( vSorter ); + +} +void Gia_ManSortPairs( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits[2], Vec_Int_t * vUnateLitsW[2], Vec_Wec_t * vSorter ) +{ + int n; + for ( n = 0; n < 2; n++ ) + Gia_ManSortPairsInt( pSets[n], pSets[!n], vDivs, nWords, vUnateLits[n], vUnateLitsW[n], vSorter ); +} + +void Gia_ManSortBinate( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vBinateVars, Vec_Wec_t * vSorter ) +{ + Vec_Int_t * vLevel; + int nMints[2] = { Abc_TtCountOnesVec(pSets[0], nWords), Abc_TtCountOnesVec(pSets[1], nWords) }; + word * pBig = nMints[0] > nMints[1] ? pSets[0] : pSets[1]; + word * pSmo = nMints[0] > nMints[1] ? pSets[1] : pSets[0]; + int Big = Abc_MaxInt( nMints[0], nMints[1] ); + int Smo = Abc_MinInt( nMints[0], nMints[1] ); + int i, k, iDiv, Gain; + + Vec_WecInit( vSorter, nWords*64 ); + Vec_IntForEachEntry( vBinateVars, iDiv, i ) + { + word * pDiv = (word *)Vec_PtrEntry( vDivs, iDiv ); + int nInter[2] = { Abc_TtCountOnesVecMask(pBig, pDiv, nWords, 0), Abc_TtCountOnesVecMask(pSmo, pDiv, nWords, 0) }; + if ( nInter[0] < Big/2 ) // complement the divisor + { + nInter[0] = Big - nInter[0]; + nInter[1] = Smo - nInter[1]; + } + assert( nInter[0] >= Big/2 ); + Gain = Abc_MaxInt( 0, nInter[0] - Big/2 + Smo/2 - nInter[1] ); + Vec_WecPush( vSorter, Gain, iDiv ); + } + + Vec_IntClear( vBinateVars ); + Vec_WecForEachLevelReverse( vSorter, vLevel, k ) + Vec_IntForEachEntry( vLevel, iDiv, i ) + Vec_IntPush( vBinateVars, iDiv ); + Vec_WecClear( vSorter ); + + if ( Vec_IntSize(vBinateVars) > 2000 ) + Vec_IntShrink( vBinateVars, 2000 ); +} + +/**Function************************************************************* + + Synopsis [Perform resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManResubFindBestBinate( Gia_ResbMan_t * p ) +{ + int nMintsAll = Abc_TtCountOnesVec(p->pSets[0], p->nWords) + Abc_TtCountOnesVec(p->pSets[1], p->nWords); + int i, iDiv, iLitBest = -1, CostBest = -1; +//Vec_IntPrint( p->vBinateVars ); +//Dau_DsdPrintFromTruth( p->pSets[0], 6 ); +//Dau_DsdPrintFromTruth( p->pSets[1], 6 ); + Vec_IntForEachEntry( p->vBinateVars, iDiv, i ) + { + word * pDiv = (word *)Vec_PtrEntry(p->vDivs, iDiv); + int nMints0 = Abc_TtCountOnesVecMask( pDiv, p->pSets[0], p->nWords, 0 ); + int nMints1 = Abc_TtCountOnesVecMask( pDiv, p->pSets[1], p->nWords, 0 ); + if ( CostBest < nMints0 + nMints1 ) + { + CostBest = nMints0 + nMints1; + iLitBest = Abc_Var2Lit( iDiv, 0 ); + } + if ( CostBest < nMintsAll - nMints0 - nMints1 ) + { + CostBest = nMintsAll - nMints0 - nMints1; + iLitBest = Abc_Var2Lit( iDiv, 1 ); + } + } + return iLitBest; +} +int Gia_ManResubAddNode( Gia_ResbMan_t * p, int iLit0, int iLit1, int Type ) +{ + int iNode = Vec_PtrSize(p->vDivs) + Vec_IntSize(p->vGates)/2; + int fFlip = (Type == 2) ^ (iLit0 > iLit1); + int iFan0 = fFlip ? iLit1 : iLit0; + int iFan1 = fFlip ? iLit0 : iLit1; + assert( iLit0 != iLit1 ); + if ( Type == 2 ) + assert( iFan0 > iFan1 ); + else + assert( iFan0 < iFan1 ); + Vec_IntPushTwo( p->vGates, Abc_LitNotCond(iFan0, Type==1), Abc_LitNotCond(iFan1, Type==1) ); + return Abc_Var2Lit( iNode, Type==1 ); +} +int Gia_ManResubPerformMux_rec( Gia_ResbMan_t * p, int nLimit, int Depth ) +{ + extern int Gia_ManResubPerform_rec( Gia_ResbMan_t * p, int nLimit, int Depth ); + int iDivBest, iResLit0, iResLit1, nNodes; + word * pDiv, * pCopy[2]; + if ( Depth == 0 ) + return -1; + if ( nLimit < 3 ) + return -1; + iDivBest = Gia_ManResubFindBestBinate( p ); + if ( iDivBest == -1 ) + return -1; + pCopy[0] = ABC_CALLOC( word, p->nWords ); + pCopy[1] = ABC_CALLOC( word, p->nWords ); + Abc_TtCopy( pCopy[0], p->pSets[0], p->nWords, 0 ); + Abc_TtCopy( pCopy[1], p->pSets[1], p->nWords, 0 ); + pDiv = (word *)Vec_PtrEntry( p->vDivs, Abc_Lit2Var(iDivBest) ); + Abc_TtAndSharp( p->pSets[0], pCopy[0], pDiv, p->nWords, !Abc_LitIsCompl(iDivBest) ); + Abc_TtAndSharp( p->pSets[1], pCopy[1], pDiv, p->nWords, !Abc_LitIsCompl(iDivBest) ); + nNodes = Vec_IntSize(p->vGates)/2; + //iResLit0 = Gia_ManResubPerform_rec( p, nLimit-3 ); + iResLit0 = Gia_ManResubPerform_rec( p, nLimit, 0 ); + if ( iResLit0 == -1 ) + iResLit0 = Gia_ManResubPerformMux_rec( p, nLimit, Depth-1 ); + if ( iResLit0 == -1 ) + { + ABC_FREE( pCopy[0] ); + ABC_FREE( pCopy[1] ); + return -1; + } + Abc_TtAndSharp( p->pSets[0], pCopy[0], pDiv, p->nWords, Abc_LitIsCompl(iDivBest) ); + Abc_TtAndSharp( p->pSets[1], pCopy[1], pDiv, p->nWords, Abc_LitIsCompl(iDivBest) ); + ABC_FREE( pCopy[0] ); + ABC_FREE( pCopy[1] ); + nNodes = Vec_IntSize(p->vGates)/2 - nNodes; + if ( nLimit-nNodes < 3 ) + return -1; + //iResLit1 = Gia_ManResubPerform_rec( p, nLimit-3-nNodes ); + iResLit1 = Gia_ManResubPerform_rec( p, nLimit, 0 ); + if ( iResLit1 == -1 ) + iResLit1 = Gia_ManResubPerformMux_rec( p, nLimit, Depth-1 ); + if ( iResLit1 == -1 ) + return -1; + else + { + int iLit0 = Gia_ManResubAddNode( p, Abc_LitNot(iDivBest), iResLit0, 0 ); + int iLit1 = Gia_ManResubAddNode( p, iDivBest, iResLit1, 0 ); + return Gia_ManResubAddNode( p, iLit0, iLit1, 1 ); + } +} + +/**Function************************************************************* + + Synopsis [Perform resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManResubPerform_rec( Gia_ResbMan_t * p, int nLimit, int Depth ) +{ + int TopOneW[2] = {0}, TopTwoW[2] = {0}, Max1, Max2, iResLit, nVars = Vec_PtrSize(p->vDivs); + if ( p->fVerbose ) + { + int nMints[2] = { Abc_TtCountOnesVec(p->pSets[0], p->nWords), Abc_TtCountOnesVec(p->pSets[1], p->nWords) }; + printf( " " ); + printf( "ISF: " ); + printf( "0=%5d (%5.2f %%) ", nMints[0], 100.0*nMints[0]/(64*p->nWords) ); + printf( "1=%5d (%5.2f %%) ", nMints[1], 100.0*nMints[1]/(64*p->nWords) ); + } + if ( Abc_TtIsConst0( p->pSets[1], p->nWords ) ) + return 0; + if ( Abc_TtIsConst0( p->pSets[0], p->nWords ) ) + return 1; + iResLit = Gia_ManFindOneUnate( p->pSets, p->vDivs, p->nWords, p->vUnateLits, p->vNotUnateVars, p->fVerbose ); + if ( iResLit >= 0 ) // buffer + return iResLit; + if ( nLimit == 0 ) + return -1; + Gia_ManSortUnates( p->pSets, p->vDivs, p->nWords, p->vUnateLits, p->vUnateLitsW, p->vSorter ); + iResLit = Gia_ManFindTwoUnate( p->pSets, p->vDivs, p->nWords, p->vUnateLits, p->vUnateLitsW, p->fVerbose ); + if ( iResLit >= 0 ) // and + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + int fComp = Abc_LitIsCompl(iResLit); + int iDiv0 = Abc_Lit2Var(iResLit) & 0x7FFF; + int iDiv1 = Abc_Lit2Var(iResLit) >> 15; + assert( iDiv0 < iDiv1 ); + Vec_IntPushTwo( p->vGates, iDiv0, iDiv1 ); + return Abc_Var2Lit( iNode, fComp ); + } + Vec_IntTwoFindCommon( p->vNotUnateVars[0], p->vNotUnateVars[1], p->vBinateVars ); + if ( Depth ) + return Gia_ManResubPerformMux_rec( p, nLimit, Depth ); + if ( Vec_IntSize(p->vBinateVars) > p->nDivsMax ) + Vec_IntShrink( p->vBinateVars, p->nDivsMax ); + if ( p->fVerbose ) printf( " B = %3d", Vec_IntSize(p->vBinateVars) ); + //Gia_ManSortBinate( p->pSets, p->vDivs, p->nWords, p->vBinateVars, p->vSorter ); + if ( p->fUseXor ) + { + iResLit = Gia_ManFindXor( p->pSets, p->vDivs, p->nWords, p->vBinateVars, p->vUnatePairs, p->fVerbose ); + if ( iResLit >= 0 ) // xor + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + int fComp = Abc_LitIsCompl(iResLit); + int iDiv0 = Abc_Lit2Var(iResLit) & 0x7FFF; + int iDiv1 = Abc_Lit2Var(iResLit) >> 15; + assert( !Abc_LitIsCompl(iDiv0) ); + assert( !Abc_LitIsCompl(iDiv1) ); + assert( iDiv0 > iDiv1 ); + Vec_IntPushTwo( p->vGates, iDiv0, iDiv1 ); + return Abc_Var2Lit( iNode, fComp ); + } + } + if ( nLimit == 1 ) + return -1; + Gia_ManFindUnatePairs( p->pSets, p->vDivs, p->nWords, p->vBinateVars, p->vUnatePairs, p->fVerbose ); + Gia_ManSortPairs( p->pSets, p->vDivs, p->nWords, p->vUnatePairs, p->vUnatePairsW, p->vSorter ); + iResLit = Gia_ManFindDivGate( p->pSets, p->vDivs, p->nWords, p->vUnateLits, p->vUnatePairs, p->vUnateLitsW, p->vUnatePairsW, p->pDivA ); + if ( iResLit >= 0 ) // and(div,pair) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + + int fComp = Abc_LitIsCompl(iResLit); + int iDiv0 = Abc_Lit2Var(iResLit) & 0x7FFF; // div + int iDiv1 = Abc_Lit2Var(iResLit) >> 15; // pair + + int Div1 = Vec_IntEntry( p->vUnatePairs[!fComp], Abc_Lit2Var(iDiv1) ); + int fComp1 = Abc_LitIsCompl(Div1) ^ Abc_LitIsCompl(iDiv1); + int iDiv10 = Abc_Lit2Var(Div1) & 0x7FFF; + int iDiv11 = Abc_Lit2Var(Div1) >> 15; + + Vec_IntPushTwo( p->vGates, iDiv10, iDiv11 ); + Vec_IntPushTwo( p->vGates, iDiv0, Abc_Var2Lit(iNode, fComp1) ); + return Abc_Var2Lit( iNode+1, fComp ); + } +// if ( nLimit == 2 ) +// return -1; + if ( nLimit >= 3 ) + { + iResLit = Gia_ManFindGateGate( p->pSets, p->vDivs, p->nWords, p->vUnatePairs, p->vUnatePairsW, p->pDivA, p->pDivB ); + if ( iResLit >= 0 ) // and(pair,pair) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + + int fComp = Abc_LitIsCompl(iResLit); + int iDiv0 = Abc_Lit2Var(iResLit) & 0x7FFF; // pair + int iDiv1 = Abc_Lit2Var(iResLit) >> 15; // pair + + int Div0 = Vec_IntEntry( p->vUnatePairs[!fComp], Abc_Lit2Var(iDiv0) ); + int fComp0 = Abc_LitIsCompl(Div0) ^ Abc_LitIsCompl(iDiv0); + int iDiv00 = Abc_Lit2Var(Div0) & 0x7FFF; + int iDiv01 = Abc_Lit2Var(Div0) >> 15; + + int Div1 = Vec_IntEntry( p->vUnatePairs[!fComp], Abc_Lit2Var(iDiv1) ); + int fComp1 = Abc_LitIsCompl(Div1) ^ Abc_LitIsCompl(iDiv1); + int iDiv10 = Abc_Lit2Var(Div1) & 0x7FFF; + int iDiv11 = Abc_Lit2Var(Div1) >> 15; + + Vec_IntPushTwo( p->vGates, iDiv00, iDiv01 ); + Vec_IntPushTwo( p->vGates, iDiv10, iDiv11 ); + Vec_IntPushTwo( p->vGates, Abc_Var2Lit(iNode, fComp0), Abc_Var2Lit(iNode+1, fComp1) ); + return Abc_Var2Lit( iNode+2, fComp ); + } + } +// if ( nLimit == 3 ) +// return -1; + if ( Vec_IntSize(p->vUnateLits[0]) + Vec_IntSize(p->vUnateLits[1]) + Vec_IntSize(p->vUnatePairs[0]) + Vec_IntSize(p->vUnatePairs[1]) == 0 ) + return -1; + + TopOneW[0] = Vec_IntSize(p->vUnateLitsW[0]) ? Vec_IntEntry(p->vUnateLitsW[0], 0) : 0; + TopOneW[1] = Vec_IntSize(p->vUnateLitsW[1]) ? Vec_IntEntry(p->vUnateLitsW[1], 0) : 0; + + TopTwoW[0] = Vec_IntSize(p->vUnatePairsW[0]) ? Vec_IntEntry(p->vUnatePairsW[0], 0) : 0; + TopTwoW[1] = Vec_IntSize(p->vUnatePairsW[1]) ? Vec_IntEntry(p->vUnatePairsW[1], 0) : 0; + + Max1 = Abc_MaxInt(TopOneW[0], TopOneW[1]); + Max2 = Abc_MaxInt(TopTwoW[0], TopTwoW[1]); + if ( Abc_MaxInt(Max1, Max2) == 0 ) + return -1; + + if ( Max1 > Max2/2 ) + { + if ( nLimit >= 2 && (Max1 == TopOneW[0] || Max1 == TopOneW[1]) ) + { + int fUseOr = Max1 == TopOneW[0]; + int iDiv = Vec_IntEntry( p->vUnateLits[!fUseOr], 0 ); + int fComp = Abc_LitIsCompl(iDiv); + word * pDiv = (word *)Vec_PtrEntry( p->vDivs, Abc_Lit2Var(iDiv) ); + Abc_TtAndSharp( p->pSets[fUseOr], p->pSets[fUseOr], pDiv, p->nWords, !fComp ); + if ( p->fVerbose ) + printf( "\n" ); + iResLit = Gia_ManResubPerform_rec( p, nLimit-1, Depth ); + if ( iResLit >= 0 ) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + if ( iDiv < iResLit ) + Vec_IntPushTwo( p->vGates, Abc_LitNot(iDiv), Abc_LitNotCond(iResLit, fUseOr) ); + else + Vec_IntPushTwo( p->vGates, Abc_LitNotCond(iResLit, fUseOr), Abc_LitNot(iDiv) ); + return Abc_Var2Lit( iNode, fUseOr ); + } + } + if ( Max2 == 0 ) + return -1; +/* + if ( Max2 == TopTwoW[0] || Max2 == TopTwoW[1] ) + { + int fUseOr = Max2 == TopTwoW[0]; + int iDiv = Vec_IntEntry( p->vUnatePairs[!fUseOr], 0 ); + int fComp = Abc_LitIsCompl(iDiv); + Gia_ManDeriveDivPair( iDiv, p->vDivs, p->nWords, p->pDivA ); + Abc_TtAndSharp( p->pSets[fUseOr], p->pSets[fUseOr], p->pDivA, p->nWords, !fComp ); + if ( p->fVerbose ) + printf( "\n " ); + iResLit = Gia_ManResubPerform_rec( p, nLimit-2 ); + if ( iResLit >= 0 ) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + int iDiv0 = Abc_Lit2Var(iDiv) & 0x7FFF; + int iDiv1 = Abc_Lit2Var(iDiv) >> 15; + Vec_IntPushTwo( p->vGates, iDiv0, iDiv1 ); + Vec_IntPushTwo( p->vGates, Abc_LitNotCond(iResLit, fUseOr), Abc_Var2Lit(iNode, !fComp) ); + return Abc_Var2Lit( iNode+1, fUseOr ); + } + } +*/ + } + else + { + if ( nLimit >= 3 && (Max2 == TopTwoW[0] || Max2 == TopTwoW[1]) ) + { + int fUseOr = Max2 == TopTwoW[0]; + int iDiv = Vec_IntEntry( p->vUnatePairs[!fUseOr], 0 ); + int fComp = Abc_LitIsCompl(iDiv); + Gia_ManDeriveDivPair( iDiv, p->vDivs, p->nWords, p->pDivA ); + Abc_TtAndSharp( p->pSets[fUseOr], p->pSets[fUseOr], p->pDivA, p->nWords, !fComp ); + if ( p->fVerbose ) + printf( "\n" ); + iResLit = Gia_ManResubPerform_rec( p, nLimit-2, Depth ); + if ( iResLit >= 0 ) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + int iDiv0 = Abc_Lit2Var(iDiv) & 0x7FFF; + int iDiv1 = Abc_Lit2Var(iDiv) >> 15; + Vec_IntPushTwo( p->vGates, iDiv0, iDiv1 ); + Vec_IntPushTwo( p->vGates, Abc_LitNotCond(iResLit, fUseOr), Abc_Var2Lit(iNode, !fComp) ); + return Abc_Var2Lit( iNode+1, fUseOr ); + } + } + if ( Max1 == 0 ) + return -1; +/* + if ( Max1 == TopOneW[0] || Max1 == TopOneW[1] ) + { + int fUseOr = Max1 == TopOneW[0]; + int iDiv = Vec_IntEntry( p->vUnateLits[!fUseOr], 0 ); + int fComp = Abc_LitIsCompl(iDiv); + word * pDiv = (word *)Vec_PtrEntry( p->vDivs, Abc_Lit2Var(iDiv) ); + Abc_TtAndSharp( p->pSets[fUseOr], p->pSets[fUseOr], pDiv, p->nWords, !fComp ); + if ( p->fVerbose ) + printf( "\n " ); + iResLit = Gia_ManResubPerform_rec( p, nLimit-1 ); + if ( iResLit >= 0 ) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + Vec_IntPushTwo( p->vGates, Abc_LitNot(iDiv), Abc_LitNotCond(iResLit, fUseOr) ); + return Abc_Var2Lit( iNode, fUseOr ); + } + } +*/ + } + return -1; +} +void Gia_ManResubPerform( Gia_ResbMan_t * p, Vec_Ptr_t * vDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, int Depth ) +{ + int Res; + Gia_ResbInit( p, vDivs, nWords, nLimit, nDivsMax, iChoice, fUseXor, fDebug, fVerbose, fVerbose ); + Res = Gia_ManResubPerform_rec( p, nLimit, Depth ); + if ( Res >= 0 ) + Vec_IntPush( p->vGates, Res ); + else + Vec_IntClear( p->vGates ); + if ( fVerbose ) + printf( "\n" ); +} +Vec_Int_t * Gia_ManResubOne( Vec_Ptr_t * vDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, word * pFunc, int Depth ) +{ + Vec_Int_t * vRes; + Gia_ResbMan_t * p = Gia_ResbAlloc( nWords ); + Gia_ManResubPerform( p, vDivs, nWords, nLimit, nDivsMax, iChoice, fUseXor, fDebug, fVerbose, Depth ); + if ( fVerbose ) + Gia_ManResubPrint( p->vGates, Vec_PtrSize(vDivs) ); + //if ( fVerbose ) + // printf( "\n" ); + if ( !Gia_ManResubVerify(p, pFunc) ) + { + Gia_ManResubPrint( p->vGates, Vec_PtrSize(vDivs) ); + printf( "Verification FAILED.\n" ); + } + else if ( fDebug && fVerbose ) + printf( "Verification succeeded." ); + if ( fVerbose ) + printf( "\n" ); + vRes = Vec_IntDup( p->vGates ); + Gia_ResbFree( p ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Top level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Gia_ResbMan_t * s_pResbMan = NULL; + +void Abc_ResubPrepareManager( int nWords ) +{ + if ( s_pResbMan != NULL ) + Gia_ResbFree( s_pResbMan ); + s_pResbMan = NULL; + if ( nWords > 0 ) + s_pResbMan = Gia_ResbAlloc( nWords ); +} + +int Abc_ResubComputeFunction( void ** ppDivs, int nDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, int ** ppArray ) +{ + Vec_Ptr_t Divs = { nDivs, nDivs, ppDivs }; + assert( s_pResbMan != NULL ); // first call Abc_ResubPrepareManager() + Gia_ManResubPerform( s_pResbMan, &Divs, nWords, nLimit, nDivsMax, iChoice, fUseXor, fDebug, fVerbose==2, 0 ); + if ( fVerbose ) + { + int nGates = Vec_IntSize(s_pResbMan->vGates)/2; + if ( nGates ) + { + printf( " Gain = %2d Gates = %2d __________ F = ", nLimit+1-nGates, nGates ); + Gia_ManResubPrint( s_pResbMan->vGates, nDivs ); + printf( "\n" ); + } + } + if ( fDebug ) + { + if ( !Gia_ManResubVerify(s_pResbMan, NULL) ) + { + Gia_ManResubPrint( s_pResbMan->vGates, nDivs ); + printf( "Verification FAILED.\n" ); + } + //else + // printf( "Verification succeeded.\n" ); + } + *ppArray = Vec_IntArray(s_pResbMan->vGates); + assert( Vec_IntSize(s_pResbMan->vGates)/2 <= nLimit ); + return Vec_IntSize(s_pResbMan->vGates); +} + +void Abc_ResubDumpProblem( char * pFileName, void ** ppDivs, int nDivs, int nWords ) +{ + Vec_Wrd_t * vSims = Vec_WrdAlloc( nDivs * nWords ); + word ** pDivs = (word **)ppDivs; + int d, w; + for ( d = 0; d < nDivs; d++ ) + for ( w = 0; w < nWords; w++ ) + Vec_WrdPush( vSims, pDivs[d][w] ); + Vec_WrdDumpHex( pFileName, vSims, nWords, 1 ); + Vec_WrdFree( vSims ); +} + +/**Function************************************************************* + + Synopsis [Top level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +extern void Extra_PrintHex( FILE * pFile, unsigned * pTruth, int nVars ); +extern void Dau_DsdPrintFromTruth2( word * pTruth, int nVarsInit ); + +void Gia_ManResubTest3() +{ + int nVars = 4; + int fVerbose = 1; + word Divs[6] = { 0, 0, + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00) + }; + Vec_Ptr_t * vDivs = Vec_PtrAlloc( 6 ); + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + int i, k, ArraySize, * pArray; + for ( i = 0; i < 6; i++ ) + Vec_PtrPush( vDivs, Divs+i ); + Abc_ResubPrepareManager( 1 ); + for ( i = 0; i < (1<<(1<vGates, Vec_PtrSize(vDivs) ); + printf( "\n" ); + //Vec_PtrFree( vDivs ); + Gia_ResbFree( p ); +} + +/**Function************************************************************* + + Synopsis [Top level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCheckResub( Vec_Ptr_t * vDivs, int nWords ) +{ + //int i, nVars = 6, pVarSet[10] = { 2, 189, 2127, 2125, 177, 178 }; + int i, nVars = 3, pVarSet[10] = { 2, 3, 4 }; + word * pOff = (word *)Vec_PtrEntry( vDivs, 0 ); + word * pOn = (word *)Vec_PtrEntry( vDivs, 1 ); + Vec_Int_t * vValue = Vec_IntStartFull( 1 << 6 ); + printf( "Verifying resub:\n" ); + for ( i = 0; i < 64*nWords; i++ ) + { + int v, Mint = 0, Value = Abc_TtGetBit(pOn, i); + if ( !Abc_TtGetBit(pOff, i) && !Value ) + continue; + for ( v = 0; v < nVars; v++ ) + if ( Abc_TtGetBit((word *)Vec_PtrEntry(vDivs, pVarSet[v]), i) ) + Mint |= 1 << v; + if ( Vec_IntEntry(vValue, Mint) == -1 ) + Vec_IntWriteEntry(vValue, Mint, Value); + else if ( Vec_IntEntry(vValue, Mint) != Value ) + printf( "Mismatch in pattern %d\n", i ); + } + printf( "Finished verifying resub.\n" ); + Vec_IntFree( vValue ); +} +Vec_Ptr_t * Gia_ManDeriveDivs( Vec_Wrd_t * vSims, int nWords ) +{ + int i, nDivs = Vec_WrdSize(vSims)/nWords; + Vec_Ptr_t * vDivs = Vec_PtrAlloc( nDivs ); + for ( i = 0; i < nDivs; i++ ) + Vec_PtrPush( vDivs, Vec_WrdEntryP(vSims, nWords*i) ); + return vDivs; +} +Gia_Man_t * Gia_ManResub2( Gia_Man_t * pGia, int nNodes, int nSupp, int nDivs, int iChoice, int fUseXor, int fVerbose, int fVeryVerbose ) +{ + return NULL; +} +Gia_Man_t * Gia_ManResub1( char * pFileName, int nNodes, int nSupp, int nDivs, int iChoice, int fUseXor, int fVerbose, int fVeryVerbose ) +{ + int nWords = 0; + Gia_Man_t * pMan = NULL; + Vec_Wrd_t * vSims = Vec_WrdReadHex( pFileName, &nWords, 1 ); + Vec_Ptr_t * vDivs = vSims ? Gia_ManDeriveDivs( vSims, nWords ) : NULL; + Gia_ResbMan_t * p = Gia_ResbAlloc( nWords ); + //Gia_ManCheckResub( vDivs, nWords ); + if ( Vec_PtrSize(vDivs) >= (1<<14) ) + { + printf( "Reducing all divs from %d to %d.\n", Vec_PtrSize(vDivs), (1<<14)-1 ); + Vec_PtrShrink( vDivs, (1<<14)-1 ); + } + assert( Vec_PtrSize(vDivs) < (1<<14) ); + Gia_ManResubPerform( p, vDivs, nWords, 100, 50, iChoice, fUseXor, 1, 1, 0 ); + if ( Vec_IntSize(p->vGates) ) + { + Vec_Wec_t * vGates = Vec_WecStart(1); + Vec_IntAppend( Vec_WecEntry(vGates, 0), p->vGates ); + pMan = Gia_ManConstructFromGates( vGates, Vec_PtrSize(vDivs) ); + Vec_WecFree( vGates ); + } + else + printf( "Decomposition did not succeed.\n" ); + Gia_ResbFree( p ); + Vec_PtrFree( vDivs ); + Vec_WrdFree( vSims ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManUnivTfo_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vNodes, Vec_Int_t * vPos ) +{ + int i, iFan, Count = 1; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return 0; + Gia_ObjSetTravIdCurrentId(p, iObj); + if ( vNodes && Gia_ObjIsCo(Gia_ManObj(p, iObj)) ) + Vec_IntPush( vNodes, iObj ); + if ( vPos && Gia_ObjIsCo(Gia_ManObj(p, iObj)) ) + Vec_IntPush( vPos, iObj ); + Gia_ObjForEachFanoutStaticId( p, iObj, iFan, i ) + Count += Gia_ManUnivTfo_rec( p, iFan, vNodes, vPos ); + return Count; +} +int Gia_ManUnivTfo( Gia_Man_t * p, int * pObjs, int nObjs, Vec_Int_t ** pvNodes, Vec_Int_t ** pvPos ) +{ + int i, Count = 0; + if ( pvNodes ) + { + if ( *pvNodes ) + Vec_IntClear( *pvNodes ); + else + *pvNodes = Vec_IntAlloc( 100 ); + } + if ( pvPos ) + { + if ( *pvPos ) + Vec_IntClear( *pvPos ); + else + *pvPos = Vec_IntAlloc( 100 ); + } + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nObjs; i++ ) + Count += Gia_ManUnivTfo_rec( p, pObjs[i], pvNodes ? *pvNodes : NULL, pvPos ? *pvPos : NULL ); + if ( pvNodes ) + Vec_IntSort( *pvNodes, 0 ); + if ( pvPos ) + Vec_IntSort( *pvPos, 0 ); + return Count; +} + +/**Function************************************************************* + + Synopsis [Tuning resub.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTryResub( Gia_Man_t * p ) +{ + int nLimit = 20; + int nDivsMax = 200; + int iChoice = 0; + int fUseXor = 1; + int fDebug = 1; + int fVerbose = 0; + abctime clk, clkResub = 0, clkStart = Abc_Clock(); + Vec_Ptr_t * vvSims = Vec_PtrAlloc( 100 ); + Vec_Wrd_t * vSims; + word * pSets[2], * pFunc; + Gia_Obj_t * pObj, * pObj2; + int i, i2, nWords, nNonDec = 0, nTotal = 0; + assert( Gia_ManCiNum(p) < 16 ); + Vec_WrdFreeP( &p->vSimsPi ); + p->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + //Vec_WrdPrintHex( p->vSimsPi, nWords ); + pSets[0] = ABC_CALLOC( word, nWords ); + pSets[1] = ABC_CALLOC( word, nWords ); + vSims = Gia_ManSimPatSim( p ); + Gia_ManLevelNum(p); + Gia_ManCreateRefs(p); + Abc_ResubPrepareManager( nWords ); + Gia_ManStaticFanoutStart( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + Vec_Int_t vGates; + int * pArray, nArray, nTfo, iObj = Gia_ObjId(p, pObj); + int Level = Gia_ObjLevel(p, pObj); + int nMffc = Gia_NodeMffcSizeMark(p, pObj); + pFunc = Vec_WrdEntryP( vSims, nWords*iObj ); + Abc_TtCopy( pSets[0], pFunc, nWords, 1 ); + Abc_TtCopy( pSets[1], pFunc, nWords, 0 ); + Vec_PtrClear( vvSims ); + Vec_PtrPushTwo( vvSims, pSets[0], pSets[1] ); + nTfo = Gia_ManUnivTfo( p, &iObj, 1, NULL, NULL ); + Gia_ManForEachCi( p, pObj2, i2 ) + Vec_PtrPush( vvSims, Vec_WrdEntryP(vSims, nWords*Gia_ObjId(p, pObj2)) ); + Gia_ManForEachAnd( p, pObj2, i2 ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj2) && !Gia_ObjIsTravIdPrevious(p, pObj2) && Gia_ObjLevel(p, pObj2) <= Level ) + Vec_PtrPush( vvSims, Vec_WrdEntryP(vSims, nWords*Gia_ObjId(p, pObj2)) ); + if ( fVerbose ) + printf( "%3d : Lev = %2d Mffc = %2d Divs = %3d Tfo = %3d\n", iObj, Level, nMffc, Vec_PtrSize(vvSims)-2, nTfo ); + clk = Abc_Clock(); + nArray = Abc_ResubComputeFunction( (void **)Vec_PtrArray(vvSims), Vec_PtrSize(vvSims), nWords, Abc_MinInt(nMffc-1, nLimit), nDivsMax, iChoice, fUseXor, fDebug, fVerbose, &pArray ); + clkResub += Abc_Clock() - clk; + vGates.nSize = vGates.nCap = nArray; + vGates.pArray = pArray; + assert( nMffc > Vec_IntSize(&vGates)/2 ); + if ( Vec_IntSize(&vGates) > 0 ) + nTotal += nMffc - Vec_IntSize(&vGates)/2; + nNonDec += Vec_IntSize(&vGates) == 0; + } + printf( "Total nodes = %5d. Non-realizable = %5d. Gain = %6d. ", Gia_ManAndNum(p), nNonDec, nTotal ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + Abc_PrintTime( 1, "Pure resub time", clkResub ); + Abc_ResubPrepareManager( 0 ); + Gia_ManStaticFanoutStop( p ); + Vec_PtrFree( vvSims ); + Vec_WrdFree( vSims ); + ABC_FREE( pSets[0] ); + ABC_FREE( pSets[1] ); +} + + +/**Function************************************************************* + + Synopsis [Deriving a subset.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManDeriveShrink( Vec_Wrd_t * vFuncs, int nWords ) +{ + int i, k = 0, nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc0 = Vec_WrdEntryP(vFuncs, (2*i+0)*nWords); + word * pFunc1 = Vec_WrdEntryP(vFuncs, (2*i+1)*nWords); + if ( Abc_TtIsConst0(pFunc0, nWords) || Abc_TtIsConst0(pFunc1, nWords) ) + continue; + if ( k < i ) Abc_TtCopy( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), pFunc0, nWords, 0 ); + if ( k < i ) Abc_TtCopy( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), pFunc1, nWords, 0 ); + k++; + } + Vec_WrdShrink( vFuncs, 2*k*nWords ); + return k; +} +void Gia_ManDeriveCounts( Vec_Wrd_t * vFuncs, int nWords, Vec_Int_t * vCounts ) +{ + int i, nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + Vec_IntClear( vCounts ); + for ( i = 0; i < 2*nFuncs; i++ ) + Vec_IntPush( vCounts, Abc_TtCountOnesVec(Vec_WrdEntryP(vFuncs, i*nWords), nWords) ); +} +int Gia_ManDeriveCost( Vec_Wrd_t * vFuncs, int nWords, word * pMask, Vec_Int_t * vCounts ) +{ + int i, Res = 0, nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + assert( Vec_IntSize(vCounts) * nWords == Vec_WrdSize(vFuncs) ); + for ( i = 0; i < nFuncs; i++ ) + { + int Total[2] = { Vec_IntEntry(vCounts, 2*i+0), Vec_IntEntry(vCounts, 2*i+1) }; + int This[2] = { Abc_TtCountOnesVecMask(Vec_WrdEntryP(vFuncs, (2*i+0)*nWords), pMask, nWords, 0), + Abc_TtCountOnesVecMask(Vec_WrdEntryP(vFuncs, (2*i+1)*nWords), pMask, nWords, 0) }; + assert( Total[0] >= This[0] && Total[1] >= This[1] ); + Res += This[0] * This[1] + (Total[0] - This[0]) * (Total[1] - This[1]); + } + return Res; +} +int Gia_ManDeriveSimpleCost( Vec_Int_t * vCounts ) +{ + int i, Ent1, Ent2, Res = 0; + Vec_IntForEachEntryDouble( vCounts, Ent1, Ent2, i ) + Res += Ent1*Ent2; + return Res; +} +void Gia_ManDeriveNext( Vec_Wrd_t * vFuncs, int nWords, word * pMask ) +{ + int i, iStop = Vec_WrdSize(vFuncs); word Data; + int nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + Vec_WrdForEachEntryStop( vFuncs, Data, i, iStop ) + Vec_WrdPush( vFuncs, Data ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc0n = Vec_WrdEntryP(vFuncs, (2*i+0)*nWords); + word * pFunc1n = Vec_WrdEntryP(vFuncs, (2*i+1)*nWords); + word * pFunc0p = Vec_WrdEntryP(vFuncs, (2*i+0)*nWords + iStop); + word * pFunc1p = Vec_WrdEntryP(vFuncs, (2*i+1)*nWords + iStop); + Abc_TtAnd( pFunc0p, pFunc0n, pMask, nWords, 0 ); + Abc_TtAnd( pFunc1p, pFunc1n, pMask, nWords, 0 ); + Abc_TtSharp( pFunc0n, pFunc0n, pMask, nWords ); + Abc_TtSharp( pFunc1n, pFunc1n, pMask, nWords ); + } +} +Vec_Int_t * Gia_ManDeriveSubset( Gia_Man_t * p, Vec_Wrd_t * vFuncs, Vec_Int_t * vObjs, Vec_Wrd_t * vSims, int nWords, int fVerbose ) +{ + int i, k, iObj, CostBestPrev, nFuncs = Vec_WrdSize(vFuncs) / nWords; + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + Vec_Int_t * vCounts = Vec_IntAlloc( nFuncs * 2 ); + Vec_Wrd_t * vFSims = Vec_WrdDup( vFuncs ); + assert( nFuncs * nWords == Vec_WrdSize(vFuncs) ); + assert( Gia_ManObjNum(p) * nWords == Vec_WrdSize(vSims) ); + assert( Vec_IntSize(vObjs) <= Gia_ManCandNum(p) ); + nFuncs = Gia_ManDeriveShrink( vFSims, nWords ); + Gia_ManDeriveCounts( vFSims, nWords, vCounts ); + assert( Vec_IntSize(vCounts) * nWords == Vec_WrdSize(vFSims) ); + CostBestPrev = Gia_ManDeriveSimpleCost( vCounts ); + if ( fVerbose ) + printf( "Processing %d functions and %d objects with cost %d\n", nFuncs, Vec_IntSize(vObjs), CostBestPrev ); + for ( i = 0; nFuncs > 0; i++ ) + { + int iObjBest = -1, CountThis, Count0 = ABC_INFINITY, CountBest = ABC_INFINITY; + Vec_IntForEachEntry( vObjs, iObj, k ) + { + if ( Vec_IntFind(vRes, iObj) >= 0 ) + continue; + CountThis = Gia_ManDeriveCost( vFSims, nWords, Vec_WrdEntryP(vSims, iObj*nWords), vCounts ); + if ( CountBest > CountThis ) + { + CountBest = CountThis; + iObjBest = iObj; + } + if ( !k ) Count0 = CountThis; + } + if ( Count0 < CostBestPrev ) + { + CountBest = Count0; + iObjBest = Vec_IntEntry(vObjs, 0); + } + Gia_ManDeriveNext( vFSims, nWords, Vec_WrdEntryP(vSims, iObjBest*nWords) ); + nFuncs = Gia_ManDeriveShrink( vFSims, nWords ); + Gia_ManDeriveCounts( vFSims, nWords, vCounts ); + assert( CountBest == Gia_ManDeriveSimpleCost(vCounts) ); + Vec_IntPush( vRes, iObjBest ); + CostBestPrev = CountBest; + if ( fVerbose ) + printf( "Iter %2d : Funcs = %6d. Object %6d. Cost %6d.\n", i, nFuncs, iObjBest, CountBest ); + } + Vec_IntFree( vCounts ); + Vec_WrdFree( vFSims ); + return vRes; +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/abc/src/aig/gia/giaResub2.c b/abc/src/aig/gia/giaResub2.c new file mode 100644 index 00000000000..10c5a9e0e9e --- /dev/null +++ b/abc/src/aig/gia/giaResub2.c @@ -0,0 +1,1558 @@ +/**CFile**************************************************************** + + FileName [giaResub2.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaResub2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilTruth.h" +#include "misc/vec/vecHsh.h" +#include "opt/dau/dau.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Gia_Rsb2Man_t_ Gia_Rsb2Man_t; +struct Gia_Rsb2Man_t_ +{ + // hyper-parameters + int nDivsMax; + int nLevelIncrease; + int fUseXor; + int fUseZeroCost; + int fDebug; + int fVerbose; + // input AIG + int nObjs; + int nPis; + int nNodes; + int nPos; + int iFirstPo; + int Level; + int nMffc; + // intermediate data + Vec_Int_t vObjs; + Vec_Wrd_t vSims; + Vec_Ptr_t vpDivs; + Vec_Int_t vDivs; + Vec_Int_t vLevels; + Vec_Int_t vRefs; + Vec_Int_t vCopies; + Vec_Int_t vTried; + word Truth0; + word Truth1; + word CareSet; +}; + +extern void Abc_ResubPrepareManager( int nWords ); +extern int Abc_ResubComputeFunction( void ** ppDivs, int nDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, int ** ppArray ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Rsb2Man_t * Gia_Rsb2ManAlloc() +{ + Gia_Rsb2Man_t * p = ABC_CALLOC( Gia_Rsb2Man_t, 1 ); + return p; +} +void Gia_Rsb2ManFree( Gia_Rsb2Man_t * p ) +{ + Vec_IntErase( &p->vObjs ); + Vec_WrdErase( &p->vSims ); + Vec_PtrErase( &p->vpDivs ); + Vec_IntErase( &p->vDivs ); + Vec_IntErase( &p->vLevels ); + Vec_IntErase( &p->vRefs ); + Vec_IntErase( &p->vCopies ); + Vec_IntErase( &p->vTried ); + ABC_FREE( p ); +} +void Gia_Rsb2ManStart( Gia_Rsb2Man_t * p, int * pObjs, int nObjs, int nDivsMax, int nLevelIncrease, int fUseXor, int fUseZeroCost, int fDebug, int fVerbose ) +{ + int i; + // hyper-parameters + p->nDivsMax = nDivsMax; + p->nLevelIncrease = nLevelIncrease; + p->fUseXor = fUseXor; + p->fUseZeroCost = fUseZeroCost; + p->fDebug = fDebug; + p->fVerbose = fVerbose; + // user data + Vec_IntClear( &p->vObjs ); + Vec_IntPushArray( &p->vObjs, pObjs, 2*nObjs ); + assert( pObjs[0] == 0 ); + assert( pObjs[1] == 0 ); + p->nObjs = nObjs; + p->nPis = 0; + p->nNodes = 0; + p->nPos = 0; + p->iFirstPo = 0; + for ( i = 1; i < nObjs; i++ ) + { + if ( pObjs[2*i+0] == 0 && pObjs[2*i+1] == 0 ) + p->nPis++; + else if ( pObjs[2*i+0] == pObjs[2*i+1] ) + p->nPos++; + else + p->nNodes++; + } + assert( nObjs == 1 + p->nPis + p->nNodes + p->nPos ); + p->iFirstPo = nObjs - p->nPos; + Vec_WrdClear( &p->vSims ); + Vec_WrdGrow( &p->vSims, 2*nObjs ); + Vec_WrdPush( &p->vSims, 0 ); + Vec_WrdPush( &p->vSims, 0 ); + for ( i = 0; i < p->nPis; i++ ) + { + Vec_WrdPush( &p->vSims, s_Truths6[i] ); + Vec_WrdPush( &p->vSims, ~s_Truths6[i] ); + } + p->vSims.nSize = 2*p->nObjs; + Vec_IntClear( &p->vDivs ); + Vec_IntClear( &p->vLevels ); + Vec_IntClear( &p->vRefs ); + Vec_IntClear( &p->vCopies ); + Vec_IntClear( &p->vTried ); + Vec_PtrClear( &p->vpDivs ); + Vec_IntGrow( &p->vDivs, nObjs ); + Vec_IntGrow( &p->vLevels, nObjs ); + Vec_IntGrow( &p->vRefs, nObjs ); + Vec_IntGrow( &p->vCopies, nObjs ); + Vec_IntGrow( &p->vTried, nObjs ); + Vec_PtrGrow( &p->vpDivs, nObjs ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_Rsb2ManPrint( Gia_Rsb2Man_t * p ) +{ + int i, * pObjs = Vec_IntArray( &p->vObjs ); + printf( "PI = %d. PO = %d. Obj = %d.\n", p->nPis, p->nPos, p->nObjs ); + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + printf( "%2d = %c%2d & %c%2d;\n", i, + Abc_LitIsCompl(pObjs[2*i+0]) ? '!' : ' ', Abc_Lit2Var(pObjs[2*i+0]), + Abc_LitIsCompl(pObjs[2*i+1]) ? '!' : ' ', Abc_Lit2Var(pObjs[2*i+1]) ); + for ( i = p->iFirstPo; i < p->nObjs; i++ ) + printf( "%2d = %c%2d;\n", i, + Abc_LitIsCompl(pObjs[2*i+0]) ? '!' : ' ', Abc_Lit2Var(pObjs[2*i+0]) ); +} + +int Gia_Rsb2ManLevel( Gia_Rsb2Man_t * p ) +{ + int i, * pLevs, Level = 0; + Vec_IntClear( &p->vLevels ); + Vec_IntGrow( &p->vLevels, p->nObjs ); + pLevs = Vec_IntArray( &p->vLevels ); + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + pLevs[i] = 1 + Abc_MaxInt( pLevs[2*i+0]/2, pLevs[2*i+1]/2 ); + for ( i = p->iFirstPo; i < p->nObjs; i++ ) + Level = Abc_MaxInt( Level, pLevs[i] = pLevs[2*i+0]/2 ); + return Level; +} +word Gia_Rsb2ManOdcs( Gia_Rsb2Man_t * p, int iNode ) +{ + int i; word Res = 0; + int * pObjs = Vec_IntArray( &p->vObjs ); + word * pSims = Vec_WrdArray( &p->vSims ); + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + { + if ( pObjs[2*i+0] < pObjs[2*i+1] ) + pSims[2*i+0] = pSims[pObjs[2*i+0]] & pSims[pObjs[2*i+1]]; + else if ( pObjs[2*i+0] > pObjs[2*i+1] ) + pSims[2*i+0] = pSims[pObjs[2*i+0]] ^ pSims[pObjs[2*i+1]]; + else assert( 0 ); + pSims[2*i+1] = ~pSims[2*i+0]; + } + for ( i = p->iFirstPo; i < p->nObjs; i++ ) + pSims[2*i+0] = pSims[pObjs[2*i+0]]; + ABC_SWAP( word, pSims[2*iNode+0], pSims[2*iNode+1] ); + for ( i = iNode + 1; i < p->iFirstPo; i++ ) + { + if ( pObjs[2*i+0] < pObjs[2*i+1] ) + pSims[2*i+0] = pSims[pObjs[2*i+0]] & pSims[pObjs[2*i+1]]; + else if ( pObjs[2*i+0] < pObjs[2*i+1] ) + pSims[2*i+0] = pSims[pObjs[2*i+0]] ^ pSims[pObjs[2*i+1]]; + else assert( 0 ); + pSims[2*i+1] = ~pSims[2*i+0]; + } + for ( i = p->iFirstPo; i < p->nObjs; i++ ) + Res |= pSims[2*i+0] ^ pSims[pObjs[2*i+0]]; + ABC_SWAP( word, pSims[2*iNode+0], pSims[2*iNode+1] ); + return Res; +} +// marks MFFC and returns its size +int Gia_Rsb2ManDeref_rec( Gia_Rsb2Man_t * p, int * pObjs, int * pRefs, int iNode ) +{ + int Counter = 1; + if ( iNode <= p->nPis ) + return 0; + if ( --pRefs[Abc_Lit2Var(pObjs[2*iNode+0])] == 0 ) + Counter += Gia_Rsb2ManDeref_rec( p, pObjs, pRefs, Abc_Lit2Var(pObjs[2*iNode+0]) ); + if ( --pRefs[Abc_Lit2Var(pObjs[2*iNode+1])] == 0 ) + Counter += Gia_Rsb2ManDeref_rec( p, pObjs, pRefs, Abc_Lit2Var(pObjs[2*iNode+1]) ); + return Counter; +} +int Gia_Rsb2ManMffc( Gia_Rsb2Man_t * p, int iNode ) +{ + int i, * pRefs, * pObjs; + Vec_IntFill( &p->vRefs, p->nObjs, 0 ); + pRefs = Vec_IntArray( &p->vRefs ); + pObjs = Vec_IntArray( &p->vObjs ); + assert( pObjs[2*iNode+0] != pObjs[2*iNode+1] ); + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + pRefs[Abc_Lit2Var(pObjs[2*i+0])]++, + pRefs[Abc_Lit2Var(pObjs[2*i+1])]++; + for ( i = p->iFirstPo; i < p->nObjs; i++ ) + pRefs[Abc_Lit2Var(pObjs[2*i+0])]++; + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + assert( pRefs[i] ); + pRefs[iNode] = 0; + for ( i = iNode + 1; i < p->iFirstPo; i++ ) + if ( !pRefs[Abc_Lit2Var(pObjs[2*i+0])] || !pRefs[Abc_Lit2Var(pObjs[2*i+1])] ) + pRefs[i] = 0; + return Gia_Rsb2ManDeref_rec( p, pObjs, pRefs, iNode ); +} +// collects divisors and maps them into nodes +// assumes MFFC is already marked +int Gia_Rsb2ManDivs( Gia_Rsb2Man_t * p, int iNode ) +{ + int i, iNodeLevel = 0; + int * pRefs = Vec_IntArray( &p->vRefs ); + p->CareSet = Gia_Rsb2ManOdcs( p, iNode ); + p->Truth1 = p->CareSet & Vec_WrdEntry(&p->vSims, 2*iNode); + p->Truth0 = p->CareSet & ~p->Truth1; + Vec_PtrClear( &p->vpDivs ); + Vec_PtrPush( &p->vpDivs, &p->Truth0 ); + Vec_PtrPush( &p->vpDivs, &p->Truth1 ); + Vec_IntClear( &p->vDivs ); + Vec_IntPushTwo( &p->vDivs, -1, -1 ); + for ( i = 1; i <= p->nPis; i++ ) + { + Vec_PtrPush( &p->vpDivs, Vec_WrdEntryP(&p->vSims, 2*i) ); + Vec_IntPush( &p->vDivs, i ); + } + p->nMffc = Gia_Rsb2ManMffc( p, iNode ); + if ( p->nLevelIncrease >= 0 ) + { + p->Level = Gia_Rsb2ManLevel(p); + iNodeLevel = Vec_IntEntry(&p->vLevels, iNode); + } + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + { + if ( !pRefs[i] || (p->nLevelIncrease >= 0 && Vec_IntEntry(&p->vLevels, i) > iNodeLevel + p->nLevelIncrease) ) + continue; + Vec_PtrPush( &p->vpDivs, Vec_WrdEntryP(&p->vSims, 2*i) ); + Vec_IntPush( &p->vDivs, i ); + } + assert( Vec_IntSize(&p->vDivs) == Vec_PtrSize(&p->vpDivs) ); + return Vec_IntSize(&p->vDivs); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Rsb2AddNode( Vec_Int_t * vRes, int iLit0, int iLit1, int iRes0, int iRes1 ) +{ + int iLitMin = iRes0 < iRes1 ? Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)) : Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)); + int iLitMax = iRes0 < iRes1 ? Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)) : Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)); + int iLitRes = Vec_IntSize(vRes); + if ( iLit0 < iLit1 ) // and + { + if ( iLitMin == 0 ) + return 0; + if ( iLitMin == 1 ) + return iLitMax; + if ( iLitMin == Abc_LitNot(iLitMax) ) + return 0; + } + else if ( iLit0 > iLit1 ) // xor + { + if ( iLitMin == 0 ) + return iLitMax; + if ( iLitMin == 1 ) + return Abc_LitNot(iLitMax); + if ( iLitMin == Abc_LitNot(iLitMax) ) + return 1; + } + else assert( 0 ); + assert( iLitMin >= 2 && iLitMax >= 2 ); + if ( iLit0 < iLit1 ) // and + Vec_IntPushTwo( vRes, iLitMin, iLitMax ); + else if ( iLit0 > iLit1 ) // xor + { + assert( !Abc_LitIsCompl(iLit0) ); + assert( !Abc_LitIsCompl(iLit1) ); + Vec_IntPushTwo( vRes, iLitMax, iLitMin ); + } + else assert( 0 ); + return iLitRes; +} +int Gia_Rsb2ManInsert_rec( Vec_Int_t * vRes, int nPis, Vec_Int_t * vObjs, int iNode, Vec_Int_t * vResub, Vec_Int_t * vDivs, Vec_Int_t * vCopies, int iObj ) +{ + if ( Vec_IntEntry(vCopies, iObj) >= 0 ) + return Vec_IntEntry(vCopies, iObj); + assert( iObj > nPis ); + if ( iObj == iNode ) + { + int nVars = Vec_IntSize(vDivs); + int iLitRes = -1, iTopLit = Vec_IntEntryLast( vResub ); + if ( Abc_Lit2Var(iTopLit) == 0 ) + iLitRes = 0; + else if ( Abc_Lit2Var(iTopLit) < nVars ) + iLitRes = Gia_Rsb2ManInsert_rec( vRes, nPis, vObjs, -1, vResub, vDivs, vCopies, Vec_IntEntry(vDivs, Abc_Lit2Var(iTopLit)) ); + else + { + Vec_Int_t * vCopy = Vec_IntAlloc( 10 ); + int k, iLit, iLit0, iLit1; + Vec_IntForEachEntryStop( vResub, iLit, k, Vec_IntSize(vResub)-1 ) + if ( Abc_Lit2Var(iLit) < nVars ) + Gia_Rsb2ManInsert_rec( vRes, nPis, vObjs, -1, vResub, vDivs, vCopies, Vec_IntEntry(vDivs, Abc_Lit2Var(iLit)) ); + Vec_IntForEachEntryDouble( vResub, iLit0, iLit1, k ) + { + int iVar0 = Abc_Lit2Var(iLit0); + int iVar1 = Abc_Lit2Var(iLit1); + int iRes0 = iVar0 < nVars ? Vec_IntEntry(vCopies, Vec_IntEntry(vDivs, iVar0)) : Vec_IntEntry(vCopy, iVar0 - nVars); + int iRes1 = iVar1 < nVars ? Vec_IntEntry(vCopies, Vec_IntEntry(vDivs, iVar1)) : Vec_IntEntry(vCopy, iVar1 - nVars); + iLitRes = Gia_Rsb2AddNode( vRes, iLit0, iLit1, iRes0, iRes1 ); + Vec_IntPush( vCopy, iLitRes ); + } + Vec_IntFree( vCopy ); + } + iLitRes = Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iTopLit) ); + Vec_IntWriteEntry( vCopies, iObj, iLitRes ); + return iLitRes; + } + else + { + int iLit0 = Vec_IntEntry( vObjs, 2*iObj+0 ); + int iLit1 = Vec_IntEntry( vObjs, 2*iObj+1 ); + int iRes0 = Gia_Rsb2ManInsert_rec( vRes, nPis, vObjs, iNode, vResub, vDivs, vCopies, Abc_Lit2Var(iLit0) ); + int iRes1 = Gia_Rsb2ManInsert_rec( vRes, nPis, vObjs, iNode, vResub, vDivs, vCopies, Abc_Lit2Var(iLit1) ); + int iLitRes = Gia_Rsb2AddNode( vRes, iLit0, iLit1, iRes0, iRes1 ); + Vec_IntWriteEntry( vCopies, iObj, iLitRes ); + return iLitRes; + } +} +Vec_Int_t * Gia_Rsb2ManInsert( int nPis, int nPos, Vec_Int_t * vObjs, int iNode, Vec_Int_t * vResub, Vec_Int_t * vDivs, Vec_Int_t * vCopies ) +{ + int i, nObjs = Vec_IntSize(vObjs)/2, iFirstPo = nObjs - nPos; + Vec_Int_t * vRes = Vec_IntAlloc( Vec_IntSize(vObjs) ); +//Vec_IntPrint( vDivs ); +//Vec_IntPrint( vResub ); + Vec_IntFill( vCopies, Vec_IntSize(vObjs), -1 ); + Vec_IntFill( vRes, 2*(nPis + 1), 0 ); + for ( i = 0; i <= nPis; i++ ) + Vec_IntWriteEntry( vCopies, i, 2*i ); + for ( i = iFirstPo; i < nObjs; i++ ) + Gia_Rsb2ManInsert_rec( vRes, nPis, vObjs, iNode, vResub, vDivs, vCopies, Abc_Lit2Var( Vec_IntEntry(vObjs, 2*i) ) ); + for ( i = iFirstPo; i < nObjs; i++ ) + { + int iLitNew = Abc_Lit2LitL( Vec_IntArray(vCopies), Vec_IntEntry(vObjs, 2*i) ); + Vec_IntPushTwo( vRes, iLitNew, iLitNew ); + } + return vRes; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ResubPrintDivs( void ** ppDivs, int nDivs ) +{ + word ** pDivs = (word **)ppDivs; + int i; + for ( i = 0; i < nDivs; i++ ) + { + printf( "Div %2d : ", i ); + Dau_DsdPrintFromTruth( pDivs[i], 6 ); + } +} +int Abc_ResubNodeToTry( Vec_Int_t * vTried, int iFirst, int iLast ) +{ + int iNode; + //for ( iNode = iFirst; iNode < iLast; iNode++ ) + for ( iNode = iLast - 1; iNode >= iFirst; iNode-- ) + if ( Vec_IntFind(vTried, iNode) == -1 ) + return iNode; + return -1; +} +int Abc_ResubComputeWindow( int * pObjs, int nObjs, int nDivsMax, int nLevelIncrease, int fUseXor, int fUseZeroCost, int fDebug, int fVerbose, int ** ppArray, int * pnResubs ) +{ + int iNode, nChanges = 0, RetValue = 0; + Gia_Rsb2Man_t * p = Gia_Rsb2ManAlloc(); + Gia_Rsb2ManStart( p, pObjs, nObjs, nDivsMax, nLevelIncrease, fUseXor, fUseZeroCost, fDebug, fVerbose ); + *ppArray = NULL; + while ( (iNode = Abc_ResubNodeToTry(&p->vTried, p->nPis+1, p->iFirstPo)) > 0 ) + { + int nDivs = Gia_Rsb2ManDivs( p, iNode ); + int * pResub, nResub = Abc_ResubComputeFunction( Vec_PtrArray(&p->vpDivs), nDivs, 1, p->nMffc-1, nDivsMax, 0, fUseXor, fDebug, fVerbose, &pResub ); + if ( nResub == 0 ) + Vec_IntPush( &p->vTried, iNode ); + else + { + int i, k = 0, iTried; + Vec_Int_t vResub = { nResub, nResub, pResub }; + Vec_Int_t * vRes = Gia_Rsb2ManInsert( p->nPis, p->nPos, &p->vObjs, iNode, &vResub, &p->vDivs, &p->vCopies ); + //printf( "\nResubing node %d:\n", iNode ); + //Gia_Rsb2ManPrint( p ); + p->nObjs = Vec_IntSize(vRes)/2; + p->iFirstPo = p->nObjs - p->nPos; + Vec_IntClear( &p->vObjs ); + Vec_IntAppend( &p->vObjs, vRes ); + Vec_IntFree( vRes ); + Vec_IntForEachEntry( &p->vTried, iTried, i ) + if ( Vec_IntEntry(&p->vCopies, iTried) > Abc_Var2Lit(p->nPis, 0) ) // internal node + Vec_IntWriteEntry( &p->vTried, k++, Abc_Lit2Var(Vec_IntEntry(&p->vCopies, iTried)) ); + Vec_IntShrink( &p->vTried, k ); + nChanges++; + //Gia_Rsb2ManPrint( p ); + } + } + if ( nChanges ) + { + RetValue = p->nObjs; + *ppArray = p->vObjs.pArray; + Vec_IntZero( &p->vObjs ); + } + Gia_Rsb2ManFree( p ); + if ( pnResubs ) + *pnResubs = nChanges; + return RetValue; +} +int Abc_ResubComputeWindow2( int * pObjs, int nObjs, int nDivsMax, int nLevelIncrease, int fUseXor, int fUseZeroCost, int fDebug, int fVerbose, int ** ppArray, int * pnResubs ) +{ + *ppArray = ABC_ALLOC( int, 2*nObjs ); + memmove( *ppArray, pObjs, 2*nObjs * sizeof(int) ); + if ( pnResubs ) + *pnResubs = 0; + return nObjs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Gia_ManToResub( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, * pObjs = ABC_CALLOC( int, 2*Gia_ManObjNum(p) ); + assert( Gia_ManIsNormalized(p) ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + continue; + pObjs[2*i+0] = Gia_ObjFaninLit0(Gia_ManObj(p, i), i); + if ( Gia_ObjIsCo(pObj) ) + pObjs[2*i+1] = pObjs[2*i+0]; + else if ( Gia_ObjIsAnd(pObj) ) + pObjs[2*i+1] = Gia_ObjFaninLit1(Gia_ManObj(p, i), i); + else assert( 0 ); + } + return pObjs; +} +Gia_Man_t * Gia_ManFromResub( int * pObjs, int nObjs, int nIns ) +{ + Gia_Man_t * pNew = Gia_ManStart( nObjs ); + int i; + for ( i = 1; i < nObjs; i++ ) + { + if ( pObjs[2*i] == 0 && i <= nIns ) // pi + Gia_ManAppendCi( pNew ); + else if ( pObjs[2*i] == pObjs[2*i+1] ) // po + Gia_ManAppendCo( pNew, pObjs[2*i] ); + else if ( pObjs[2*i] < pObjs[2*i+1] ) + Gia_ManAppendAnd( pNew, pObjs[2*i], pObjs[2*i+1] ); + else if ( pObjs[2*i] > pObjs[2*i+1] ) + Gia_ManAppendXor( pNew, pObjs[2*i], pObjs[2*i+1] ); + else assert( 0 ); + } + return pNew; +} +Gia_Man_t * Gia_ManResub2Test( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + int nResubs, nObjsNew, * pObjsNew, * pObjs = Gia_ManToResub( p ); +//Gia_ManPrint( p ); + Abc_ResubPrepareManager( 1 ); + nObjsNew = Abc_ResubComputeWindow( pObjs, Gia_ManObjNum(p), 1000, -1, 0, 0, 0, 0, &pObjsNew, &nResubs ); + //printf( "Performed resub %d times. Reduced %d nodes.\n", nResubs, nObjsNew ? Gia_ManObjNum(p) - nObjsNew : 0 ); + Abc_ResubPrepareManager( 0 ); + if ( nObjsNew ) + { + pNew = Gia_ManFromResub( pObjsNew, nObjsNew, Gia_ManCiNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + } + else + pNew = Gia_ManDup( p ); + ABC_FREE( pObjs ); + ABC_FREE( pObjsNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Creating a window with support composed of primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +// returns the number of nodes added to the window when is iPivot is added +// the window nodes in vNodes are labeled with the current traversal ID +// the new node iPivot and its fanout are temporarily labeled and then unlabeled +int Gia_WinTryAddingNode( Gia_Man_t * p, int iPivot, int iPivot2, Vec_Wec_t * vLevels, Vec_Int_t * vNodes ) +{ + Vec_Int_t * vLevel; + Gia_Obj_t * pObj, * pFanout; + int k, i, f, Count = 0; + // precondition: the levelized structure is empty + assert( Vec_WecSizeSize(vLevels) == 0 ); + // precondition: the new object to be added (iPivot) is not in the window + assert( !Gia_ObjIsTravIdCurrentId(p, iPivot) ); + // add the object to the window and to the levelized structure + Gia_ObjSetTravIdCurrentId( p, iPivot ); + Vec_WecPush( vLevels, Gia_ObjLevelId(p, iPivot), iPivot ); + // the same about the second node if it is given + if ( iPivot2 != -1 ) + { + // precondition: the new object to be added (iPivot2) is not in the window + assert( !Gia_ObjIsTravIdCurrentId(p, iPivot2) ); + // add the object to the window and to the levelized structure + Gia_ObjSetTravIdCurrentId( p, iPivot2 ); + Vec_WecPush( vLevels, Gia_ObjLevelId(p, iPivot2), iPivot2 ); + } + // iterate through all objects and explore their fanouts + Vec_WecForEachLevel( vLevels, vLevel, k ) + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + Gia_ObjForEachFanoutStatic( p, pObj, pFanout, f ) + { + if ( f == 5 ) // explore first 5 fanouts of the node + break; + if ( Gia_ObjIsAnd(pFanout) && // internal node + !Gia_ObjIsTravIdCurrent(p, pFanout) && // not in the window + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pFanout)) && // but fanins are + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pFanout)) ) // in the window + { + // add fanout to the window and to the levelized structure + Gia_ObjSetTravIdCurrent( p, pFanout ); + Vec_WecPush( vLevels, Gia_ObjLevel(p, pFanout), Gia_ObjId(p, pFanout) ); + // count the number of nodes in the structure + Count++; + } + } + // iterate through the nodes in the levelized structure + Vec_WecForEachLevel( vLevels, vLevel, k ) + { + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + if ( vNodes == NULL ) // it was a test run - unmark the node + Gia_ObjSetTravIdPrevious( p, pObj ); + else // it was a real run - permanently add to the node to the window + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + // clean the levelized structure + Vec_IntClear( vLevel ); + } + // return the number of nodes to be added + return Count; +} +// find the first PI to add based on the fanout count +int Gia_WinAddCiWithMaxFanouts( Gia_Man_t * p ) +{ + int i, Id, nMaxFan = -1, iMaxFan = -1; + Gia_ManForEachCiId( p, Id, i ) + if ( nMaxFan < Gia_ObjFanoutNumId(p, Id) ) + { + nMaxFan = Gia_ObjFanoutNumId(p, Id); + iMaxFan = Id; + } + assert( iMaxFan >= 0 ); + return iMaxFan; +} +// find the next PI to add based on how many nodes will be added to the window +int Gia_WinAddCiWithMaxDivisors( Gia_Man_t * p, Vec_Wec_t * vLevels ) +{ + int i, Id, nCurFan, nMaxFan = -1, iMaxFan = -1; + Gia_ManForEachCiId( p, Id, i ) + { + if ( Gia_ObjIsTravIdCurrentId( p, Id ) ) + continue; + nCurFan = Gia_WinTryAddingNode( p, Id, -1, vLevels, NULL ); + if ( nMaxFan < nCurFan ) + { + nMaxFan = nCurFan; + iMaxFan = Id; + } + } + assert( iMaxFan >= 0 ); + return iMaxFan; +} +// check if the node has unmarked fanouts +int Gia_WinNodeHasUnmarkedFanouts( Gia_Man_t * p, int iPivot ) +{ + int f, iFan; + Gia_ObjForEachFanoutStaticId( p, iPivot, iFan, f ) + if ( !Gia_ObjIsTravIdCurrentId(p, iFan) ) + return 1; + return 0; +} +// this is a translation procedure, which converts the array of node IDs (vObjs) +// into the internal represnetation for the resub engine, which is returned +// (this procedure is not needed when we simply construct a window) +Vec_Int_t * Gia_RsbCiTranslate( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Int_t * vMap ) +{ + int i, iObj, Lit0, Lit1, Fan0, Fan1; + Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); + assert( Vec_IntSize(vMap) == Gia_ManObjNum(p) ); + Vec_IntPushTwo( vNodes, 0, 0 ); // const0 node + Vec_IntForEachEntry( vObjs, iObj, i ) + { + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + assert( Gia_ObjIsTravIdCurrentId(p, iObj) ); + Fan0 = Gia_ObjIsCi(pObj) ? 0 : Vec_IntEntry(vMap, Gia_ObjFaninId0(pObj, iObj)); + Fan1 = Gia_ObjIsCi(pObj) ? 0 : Vec_IntEntry(vMap, Gia_ObjFaninId1(pObj, iObj)); + Lit0 = Gia_ObjIsCi(pObj) ? 0 : Abc_LitNotCond( Fan0, Gia_ObjFaninC0(pObj) ); + Lit1 = Gia_ObjIsCi(pObj) ? 0 : Abc_LitNotCond( Fan1, Gia_ObjFaninC1(pObj) ); + Vec_IntWriteEntry( vMap, iObj, Vec_IntSize(vNodes) ); + Vec_IntPushTwo( vNodes, Lit0, Lit1 ); + } + Vec_IntForEachEntry( vObjs, iObj, i ) + if ( Gia_WinNodeHasUnmarkedFanouts( p, iObj ) ) + Vec_IntPushTwo( vNodes, Vec_IntEntry(vMap, iObj), Vec_IntEntry(vMap, iObj) ); + return vNodes; +} +// construct a high-volume window support by the given number (nPis) of primary inputs +Vec_Int_t * Gia_RsbCiWindow( Gia_Man_t * p, int nPis ) +{ + Vec_Int_t * vRes; int i, iMaxFan; + Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_Wec_t * vLevels = Vec_WecStart( Gia_ManLevelNum(p)+1 ); + Gia_ManStaticFanoutStart( p ); + Gia_ManIncrementTravId(p); + // add the first one + iMaxFan = Gia_WinAddCiWithMaxFanouts( p ); + Gia_ObjSetTravIdCurrentId( p, iMaxFan ); + Vec_IntPush( vNodes, iMaxFan ); + // add remaining ones + for ( i = 1; i < nPis; i++ ) + { + iMaxFan = Gia_WinAddCiWithMaxDivisors( p, vLevels ); + Gia_WinTryAddingNode( p, iMaxFan, -1, vLevels, vNodes ); + } + Vec_IntSort( vNodes, 0 ); + vRes = Gia_RsbCiTranslate( p, vNodes, vMap ); + Gia_ManStaticFanoutStop( p ); + Vec_WecFree( vLevels ); + Vec_IntFree( vMap ); +//Vec_IntPrint( vNodes ); + Vec_IntFree( vNodes ); + return vRes; +} +void Gia_RsbCiWindowTest( Gia_Man_t * p ) +{ + Vec_Int_t * vWin = Gia_RsbCiWindow( p, 6 ); + //Vec_IntPrint( vWin ); + Vec_IntFree( vWin ); +} + + + + +/**Function************************************************************* + + Synopsis [Return initial window for the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +//static inline int Gia_ObjFaninId( Gia_Obj_t * pObj, int iObj, int n ) { return n ? Gia_ObjFaninId1(pObj, iObj) : Gia_ObjFaninId0(pObj, iObj); } + +static inline int Gia_ObjTravIsTopTwo( Gia_Man_t * p, int iNodeA ) { return (p->pTravIds[iNodeA] >= p->nTravIds - 1); } +static inline int Gia_ObjTravIsSame( Gia_Man_t * p, int iNodeA, int iNodeB ) { return (p->pTravIds[iNodeA] == p->pTravIds[iNodeB]); } +static inline void Gia_ObjTravSetSame( Gia_Man_t * p, int iNodeA, int iNodeB ) { p->pTravIds[iNodeA] = p->pTravIds[iNodeB]; } + +// collect nodes on the path from the meeting point to the root node, excluding the meeting point +void Gia_RsbWindowGather( Gia_Man_t * p, Vec_Int_t * vPaths, int iNode, Vec_Int_t * vVisited ) +{ + int iPrev; + if ( iNode == 0 ) + return; + Vec_IntPush( vVisited, iNode ); + iPrev = Vec_IntEntry( vPaths, iNode ); + if ( iPrev == 0 ) + return; + assert( Gia_ObjTravIsSame(p, iPrev, iNode) ); + Gia_RsbWindowGather( p, vPaths, iPrev, vVisited ); +} +// explore the frontier of nodes in the breadth-first traversal +int Gia_RsbWindowExplore( Gia_Man_t * p, Vec_Int_t * vVisited, int iStart, Vec_Int_t * vPaths, int * piMeet, int * piNode ) +{ + int i, n, iObj, iLimit = Vec_IntSize( vVisited ); + *piMeet = *piNode = 0; + Vec_IntForEachEntryStartStop( vVisited, iObj, i, iStart, iLimit ) + { + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + if ( !Gia_ObjIsAnd(pObj) ) + continue; + for ( n = 0; n < 2; n++ ) + { + int iFan = Gia_ObjFaninId( pObj, iObj, n ); + // if the node was visited on the paths to both fanins, collect it + if ( Gia_ObjTravIsTopTwo(p, iObj) && Gia_ObjTravIsTopTwo(p, iFan) && !Gia_ObjTravIsSame(p, iObj, iFan) ) + { + *piMeet = iFan; + *piNode = iObj; + return 1; + } + // if the node was visited already on this path, skip it + if ( Gia_ObjTravIsTopTwo(p, iFan) ) + { + assert( Gia_ObjTravIsSame(p, iObj, iFan) ); + continue; + } + // label the node as visited + Gia_ObjTravSetSame( p, iFan, iObj ); + Vec_IntWriteEntry( vPaths, iFan, iObj ); + Vec_IntPush( vVisited, iFan ); + } + } + return 0; +} +Vec_Int_t * Gia_RsbWindowInit( Gia_Man_t * p, Vec_Int_t * vPaths, int iPivot, int nIter ) +{ + Vec_Int_t * vVisited = Vec_IntAlloc( 100 ); + Gia_Obj_t * pPivot = Gia_ManObj( p, iPivot ); + int i, n, iStart = 0; + assert( Gia_ObjIsAnd(pPivot) ); + // start paths for both fanins of the pivot node + for ( n = 0; n < 2; n++ ) + { + int iFan = Gia_ObjFaninId( pPivot, iPivot, n ); + Gia_ManIncrementTravId(p); + Vec_IntPush( vVisited, iFan ); + Vec_IntWriteEntry( vPaths, iFan, 0 ); + Gia_ObjSetTravIdCurrentId( p, iFan ); + } + // perform several iterations of breadth-first search + for ( i = 0; i < nIter; i++ ) + { + int iMeet, iNode, iNext = Vec_IntSize(vVisited); + if ( Gia_RsbWindowExplore( p, vVisited, iStart, vPaths, &iMeet, &iNode ) ) + { + // found the shared path + if ( Gia_ObjIsTravIdCurrentId(p, iMeet) ) + assert( Gia_ObjIsTravIdPreviousId(p, iNode) ); + else if ( Gia_ObjIsTravIdPreviousId(p, iMeet) ) + assert( Gia_ObjIsTravIdCurrentId(p, iNode) ); + else assert( 0 ); + // collect the initial window + Vec_IntClear( vVisited ); + Gia_RsbWindowGather( p, vPaths, Vec_IntEntry(vPaths, iMeet), vVisited ); + Gia_RsbWindowGather( p, vPaths, iNode, vVisited ); + Vec_IntPush( vVisited, iPivot ); + break; + } + iStart = iNext; + } + // if no meeting point is found, make sure to return NULL + if ( i == nIter ) + Vec_IntFreeP( &vVisited ); + return vVisited; +} +Vec_Int_t * Gia_RsbCreateWindowInputs( Gia_Man_t * p, Vec_Int_t * vWin ) +{ + Vec_Int_t * vInputs = Vec_IntAlloc(10); + Gia_Obj_t * pObj; int i, n, iObj; + Gia_ManIncrementTravId(p); + Gia_ManForEachObjVec( vWin, p, pObj, i ) + Gia_ObjSetTravIdCurrent(p, pObj); + Gia_ManForEachObjVec( vWin, p, pObj, i ) + { + assert( Gia_ObjIsAnd(pObj) ); + for ( n = 0; n < 2; n++ ) + { + int iFan = n ? Gia_ObjFaninId1p(p, pObj) : Gia_ObjFaninId0p(p, pObj); + if ( !Gia_ObjIsTravIdCurrentId(p, iFan) ) + Vec_IntPushUnique( vInputs, iFan ); + } + } + Vec_IntForEachEntry( vInputs, iObj, i ) + { + Gia_ObjSetTravIdCurrentId( p, iObj ); + Vec_IntPush( vWin, iObj ); + } + return vInputs; +} + +/**Function************************************************************* + + Synopsis [Grow window for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_RsbAddSideInputs( Gia_Man_t * p, Vec_Wec_t * vLevels, Vec_Int_t * vWin ) +{ + Vec_Int_t * vLevel; + Gia_Obj_t * pObj, * pFanout; + int k, i, f, iObj; + // precondition: the levelized structure is empty + assert( Vec_WecSizeSize(vLevels) == 0 ); + // precondition: window nodes are labeled with the current ID + Vec_IntForEachEntry( vWin, iObj, i ) + { + assert( Gia_ObjIsTravIdCurrentId(p, iObj) ); + Vec_WecPush( vLevels, Gia_ObjLevelId(p, iObj), iObj ); + } + // iterate through all objects and explore their fanouts + Vec_WecForEachLevel( vLevels, vLevel, k ) + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + Gia_ObjForEachFanoutStatic( p, pObj, pFanout, f ) + { + if ( f == 5 ) // explore first 5 fanouts of the node + break; + if ( Gia_ObjIsAnd(pFanout) && // internal node + !Gia_ObjIsTravIdCurrent(p, pFanout) && // not in the window + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pFanout)) && // but fanins are + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pFanout)) ) // in the window + { + // add fanout to the window and to the levelized structure + Gia_ObjSetTravIdCurrent( p, pFanout ); + Vec_WecPush( vLevels, Gia_ObjLevel(p, pFanout), Gia_ObjId(p, pFanout) ); + Vec_IntPush( vWin, Gia_ObjId(p, pFanout) ); + } + } + // iterate through the nodes in the levelized structure + Vec_WecForEachLevel( vLevels, vLevel, k ) + Vec_IntClear( vLevel ); +} +// expland inputs until saturation while adding the side-fanouts +void Gia_RsbExpandInputs( Gia_Man_t * p, Vec_Wec_t * vLevels, Vec_Int_t * vWin, Vec_Int_t * vInputs ) +{ + Gia_Obj_t * pObj; + int i, n, iFans[2], fChange = 1; + while ( fChange ) + { + fChange = 0; + Gia_ManForEachObjVec( vInputs, p, pObj, i ) + { + if ( !Gia_ObjIsAnd(pObj) ) + continue; + iFans[0] = Gia_ObjFaninId0p(p, pObj); + iFans[1] = Gia_ObjFaninId1p(p, pObj); + if ( !Gia_ObjIsTravIdCurrentId(p, iFans[0]) && !Gia_ObjIsTravIdCurrentId(p, iFans[1]) ) + continue; + Vec_IntRemove( vInputs, Gia_ObjId(p, pObj) ); + assert( Vec_IntFind(vWin, Gia_ObjId(p, pObj)) >= 0 ); + for ( n = 0; n < 2; n++ ) + { + if ( Gia_ObjIsTravIdCurrentId(p, iFans[n]) ) + continue; + assert( Vec_IntFind(vInputs, iFans[n]) == -1 ); + Vec_IntPush( vInputs, iFans[n] ); + Gia_WinTryAddingNode( p, iFans[n], -1, vLevels, vWin ); + assert( Gia_ObjIsTravIdCurrentId(p, iFans[n]) ); + } + fChange = 1; + } + } +} +// select the best input to expand, based on its contribution to the window size +int Gia_RsbSelectOneInput( Gia_Man_t * p, Vec_Wec_t * vLevels, Vec_Int_t * vIns ) +{ + int i, iNode = 0, WeightThis, WeightBest = -1; + Gia_Obj_t * pObj; + Gia_ManForEachObjVec( vIns, p, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + { + int iFan0 = Gia_ObjFaninId0p(p, pObj); + int iFan1 = Gia_ObjFaninId1p(p, pObj); + assert( !Gia_ObjIsTravIdCurrentId(p, iFan0) && !Gia_ObjIsTravIdCurrentId(p, iFan1) ); + WeightThis = Gia_WinTryAddingNode( p, iFan0, iFan1, vLevels, NULL ); + if ( WeightBest < WeightThis ) + { + WeightBest = WeightThis; + iNode = Gia_ObjId(p, pObj); + } + } + return iNode; +} +// grow the initial window as long as it fits the input count limit +void Gia_RsbWindowGrow( Gia_Man_t * p, Vec_Wec_t * vLevels, Vec_Int_t * vWin, Vec_Int_t * vIns, int nInputsMax ) +{ + int iNode; + Gia_RsbAddSideInputs( p, vLevels, vWin ); + Gia_RsbExpandInputs( p, vLevels, vWin, vIns ); + while ( Vec_IntSize(vIns) < nInputsMax && (iNode = Gia_RsbSelectOneInput(p, vLevels, vIns)) ) + { + int iFan0 = Gia_ObjFaninId0p(p, Gia_ManObj(p, iNode)); + int iFan1 = Gia_ObjFaninId1p(p, Gia_ManObj(p, iNode)); + assert( !Gia_ObjIsTravIdCurrentId(p, iFan0) && !Gia_ObjIsTravIdCurrentId(p, iFan1) ); + Gia_WinTryAddingNode( p, iFan0, iFan1, vLevels, vWin ); + assert( Gia_ObjIsTravIdCurrentId(p, iFan0) && Gia_ObjIsTravIdCurrentId(p, iFan1) ); + Vec_IntRemove( vIns, iNode ); + Vec_IntPushTwo( vIns, iFan0, iFan1 ); + Gia_RsbExpandInputs( p, vLevels, vWin, vIns ); + } +} + +/**Function************************************************************* + + Synopsis [Grow window for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_WinCreateFromCut_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vWin ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + assert( Gia_ObjIsAnd(pObj) ); + Gia_WinCreateFromCut_rec( p, Gia_ObjFaninId0(pObj, iObj), vWin ); + Gia_WinCreateFromCut_rec( p, Gia_ObjFaninId1(pObj, iObj), vWin ); + Vec_IntPush( vWin, iObj ); +} +// uses levelized structure (vLevels) to collect in array vWin divisors supported by the cut (vIn) +void Gia_WinCreateFromCut( Gia_Man_t * p, int iPivot, Vec_Int_t * vIn, Vec_Wec_t * vLevels, Vec_Int_t * vWin ) +{ + Vec_Int_t * vLevel; + Gia_Obj_t * pObj, * pFanout; + int k, i, f, iObj, Level; + Vec_Int_t * vUsed = Vec_IntAlloc( 100 ); + // precondition: the levelized structure is empty + assert( Vec_WecSizeSize(vLevels) == 0 ); + // clean the resulting array + Vec_IntClear( vWin ); + // collect leaves + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vIn, iObj, i ) + { + Gia_ObjSetTravIdCurrentId( p, iObj ); + Vec_IntPush( vWin, iObj ); + } + // collect internal cone + Gia_WinCreateFromCut_rec( p, iPivot, vWin ); + // add nodes to the levelized structure + Vec_IntForEachEntry( vWin, iObj, i ) + { + Vec_WecPush( vLevels, Gia_ObjLevelId(p, iObj), iObj ); + Vec_IntPushUniqueOrder( vUsed, Gia_ObjLevelId(p, iObj) ); + } + // iterate through all objects and explore their fanouts + //Vec_WecForEachLevel( vLevels, vLevel, k ) + Vec_IntForEachEntry( vUsed, Level, k ) + { + vLevel = Vec_WecEntry( vLevels, Level ); + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + Gia_ObjForEachFanoutStatic( p, pObj, pFanout, f ) + { + if ( f == 5 ) // explore first 5 fanouts of the node + break; + if ( Gia_ObjIsAnd(pFanout) && // internal node + !Gia_ObjIsTravIdCurrent(p, pFanout) && // not in the window + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pFanout)) && // but fanins are + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pFanout)) ) // in the window + { + // add fanout to the window and to the levelized structure + Gia_ObjSetTravIdCurrent( p, pFanout ); + Vec_WecPush( vLevels, Gia_ObjLevel(p, pFanout), Gia_ObjId(p, pFanout) ); + Vec_IntPush( vWin, Gia_ObjId(p, pFanout) ); + Vec_IntPushUniqueOrder( vUsed, Gia_ObjLevel(p, pFanout) ); + } + } + Vec_IntClear( vLevel ); + } + Vec_IntSort( vWin, 0 ); + Vec_IntFree( vUsed ); +} +// update the cut until both fanins of AND nodes are not in the cut +int Gia_RsbExpandCut( Gia_Man_t * p, Vec_Int_t * vIns ) +{ + int fOnlyPis = 0, fChange = 1, nSize = Vec_IntSize(vIns); + while ( fChange ) + { + Gia_Obj_t * pObj; + int i, iFan0, iFan1, fHave0, fHave1; + fOnlyPis = 1; + fChange = 0; + // check if some nodes can be expanded without increasing cut size + Gia_ManForEachObjVec( vIns, p, pObj, i ) + { + assert( Gia_ObjIsTravIdCurrent(p, pObj) ); + if ( !Gia_ObjIsAnd(pObj) ) + continue; + fOnlyPis = 0; + iFan0 = Gia_ObjFaninId0p(p, pObj); + iFan1 = Gia_ObjFaninId1p(p, pObj); + fHave0 = Gia_ObjIsTravIdCurrentId(p, iFan0); + fHave1 = Gia_ObjIsTravIdCurrentId(p, iFan1); + if ( !fHave0 && !fHave1 ) + continue; + // can expand because one of the fanins is already in the cut + // remove current cut node + Vec_IntDrop( vIns, i ); + // add missing fanin + if ( !fHave0 ) + { + Vec_IntPush( vIns, iFan0 ); + Gia_ObjSetTravIdCurrentId( p, iFan0 ); + } + if ( !fHave1 ) + { + Vec_IntPush( vIns, iFan1 ); + Gia_ObjSetTravIdCurrentId( p, iFan1 ); + } + fChange = 1; + break; + } + } + assert( Vec_IntSize(vIns) <= nSize ); + return fOnlyPis; +} +int Gia_RsbFindFaninAdd( int iFan, int pFanins[32], int pFaninCounts[32], int nFanins ) +{ + int i; + for ( i = 0; i < nFanins; i++ ) + if ( pFanins[i] == iFan ) + break; + pFanins[i] = iFan; + pFaninCounts[i]++; + return nFanins + (i == nFanins); +} +int Gia_RsbFindFaninToAddToCut( Gia_Man_t * p, Vec_Int_t * vIns ) +{ + Gia_Obj_t * pObj; + int nFanins = 0, pFanins[64] = {0}, pFaninCounts[64] = {0}; + int i, iFan0, iFan1, iFanMax = -1, CountMax = 0; + Gia_ManForEachObjVec( vIns, p, pObj, i ) + { + if ( !Gia_ObjIsAnd(pObj) ) + continue; + iFan0 = Gia_ObjFaninId0p(p, pObj); + iFan1 = Gia_ObjFaninId1p(p, pObj); + assert( !Gia_ObjIsTravIdCurrentId(p, iFan0) ); + assert( !Gia_ObjIsTravIdCurrentId(p, iFan1) ); + nFanins = Gia_RsbFindFaninAdd( iFan0, pFanins, pFaninCounts, nFanins ); + nFanins = Gia_RsbFindFaninAdd( iFan1, pFanins, pFaninCounts, nFanins ); + assert( nFanins < 64 ); + } + // find fanin with the highest count + if ( p->vFanoutNums != NULL ) + { + for ( i = 0; i < nFanins; i++ ) + if ( CountMax < pFaninCounts[i] || (CountMax == pFaninCounts[i] && (Gia_ObjFanoutNumId(p, iFanMax) < Gia_ObjFanoutNumId(p, pFanins[i]))) ) + { + CountMax = pFaninCounts[i]; + iFanMax = pFanins[i]; + } + } + else + { + for ( i = 0; i < nFanins; i++ ) + if ( CountMax < pFaninCounts[i] || (CountMax == pFaninCounts[i] && (Gia_ObjRefNumId(p, iFanMax) < Gia_ObjRefNumId(p, pFanins[i]))) ) + { + CountMax = pFaninCounts[i]; + iFanMax = pFanins[i]; + } + } + return iFanMax; +} +// precondition: nodes in vWin and in vIns are marked with the current ID +void Gia_RsbWindowGrow2( Gia_Man_t * p, int iObj, Vec_Wec_t * vLevels, Vec_Int_t * vWin, Vec_Int_t * vIns, int nInputsMax ) +{ + // window will be recomputed later + Vec_IntClear( vWin ); + // expand the cut without increasing its cost + if ( !Gia_RsbExpandCut( p, vIns ) ) + { + // save it as the best cut + Vec_Int_t * vBest = Vec_IntSize(vIns) <= nInputsMax ? Vec_IntDup(vIns) : NULL; + int fOnlyPis = 0, Iter = 0; + // iterate expansion until + // (1) the cut cannot be expanded because all leaves are PIs + // (2) the cut size exceeded the limit for 5 consecutive iterations + while ( !fOnlyPis && (Vec_IntSize(vIns) <= nInputsMax || Iter < 5) ) + { + int iFanBest = Gia_RsbFindFaninToAddToCut( p, vIns ); + Vec_IntPush( vIns, iFanBest ); + Gia_ObjSetTravIdCurrentId( p, iFanBest ); + fOnlyPis = Gia_RsbExpandCut( p, vIns ); + if ( Vec_IntSize(vIns) > nInputsMax ) + Iter++; + else + Iter = 0; + if ( Vec_IntSize(vIns) <= nInputsMax && (!vBest || Vec_IntSize(vBest) <= Vec_IntSize(vIns)) ) + { + if ( vBest ) + Vec_IntClear(vBest); + else + vBest = Vec_IntAlloc( 10 ); + Vec_IntAppend( vBest, vIns ); + } + } + if ( vBest ) + { + Vec_IntClear( vIns ); + Vec_IntAppend( vIns, vBest ); + Vec_IntFree( vBest ); + } + else + assert( Vec_IntSize(vIns) > nInputsMax ); + } + if ( vLevels && Vec_IntSize(vIns) <= nInputsMax ) + { + Vec_IntSort( vIns, 0 ); + Gia_WinCreateFromCut( p, iObj, vIns, vLevels, vWin ); + } +} + +/**Function************************************************************* + + Synopsis [Create window for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_RsbWindowCompute( Gia_Man_t * p, int iObj, int nInputsMax, int nLevelsMax, Vec_Wec_t * vLevels, Vec_Int_t * vPaths, Vec_Int_t ** pvWin, Vec_Int_t ** pvIns ) +{ + Vec_Int_t * vWin, * vIns; + *pvWin = *pvIns = NULL; + vWin = Gia_RsbWindowInit( p, vPaths, iObj, nLevelsMax ); + if ( vWin == NULL ) + return 0; + vIns = Gia_RsbCreateWindowInputs( p, vWin ); + // vWin and vIns are labeled with the current trav ID + //Vec_IntPrint( vWin ); + //Vec_IntPrint( vIns ); + if ( Vec_IntSize(vIns) <= nInputsMax + 3 ) // consider windows, which initially has a larger input space + Gia_RsbWindowGrow2( p, iObj, vLevels, vWin, vIns, nInputsMax ); + if ( Vec_IntSize(vIns) <= nInputsMax ) + { + Vec_IntSort( vWin, 0 ); + Vec_IntSort( vIns, 0 ); + *pvWin = vWin; + *pvIns = vIns; + return 1; + } + else + { + Vec_IntFree( vWin ); + Vec_IntFree( vIns ); + return 0; + } +} + +/**Function************************************************************* + + Synopsis [Derive GIA from the window] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_RsbFindOutputs( Gia_Man_t * p, Vec_Int_t * vWin, Vec_Int_t * vIns, Vec_Int_t * vRefs ) +{ + Vec_Int_t * vOuts = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i; + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vIns, p, pObj, i ) + Gia_ObjSetTravIdCurrent( p, pObj ); + Gia_ManForEachObjVec( vWin, p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) && Gia_ObjIsAnd(pObj) ) + { + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId0p(p, pObj), 1 ); + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId1p(p, pObj), 1 ); + } + Gia_ManForEachObjVec( vWin, p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) && Gia_ObjFanoutNum(p, pObj) != Vec_IntEntry(vRefs, Gia_ObjId(p, pObj)) ) + Vec_IntPush( vOuts, Gia_ObjId(p, pObj) ); + Gia_ManForEachObjVec( vWin, p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) && Gia_ObjIsAnd(pObj) ) + { + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId0p(p, pObj), -1 ); + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId1p(p, pObj), -1 ); + } + return vOuts; +} + +Gia_Man_t * Gia_RsbDeriveGiaFromWindows( Gia_Man_t * p, Vec_Int_t * vWin, Vec_Int_t * vIns, Vec_Int_t * vOuts ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObjVec( vIns, p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVec( vWin, p, pObj, i ) + if ( !~pObj->Value ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ManHashStop( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Naive truth-table-based verification.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Gia_LutComputeTruth66_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + word Truth0, Truth1; + if ( Gia_ObjIsCi(pObj) ) + return s_Truths6[Gia_ObjCioId(pObj)]; + if ( Gia_ObjIsConst0(pObj) ) + return 0; + assert( Gia_ObjIsAnd(pObj) ); + Truth0 = Gia_LutComputeTruth66_rec( p, Gia_ObjFanin0(pObj) ); + Truth1 = Gia_LutComputeTruth66_rec( p, Gia_ObjFanin1(pObj) ); + if ( Gia_ObjFaninC0(pObj) ) + Truth0 = ~Truth0; + if ( Gia_ObjFaninC1(pObj) ) + Truth1 = ~Truth1; + return Truth0 & Truth1; +} +int Gia_ManVerifyTwoTruths( Gia_Man_t * p1, Gia_Man_t * p2 ) +{ + int i, fFailed = 0; + assert( Gia_ManCoNum(p1) == Gia_ManCoNum(p2) ); + for ( i = 0; i < Gia_ManCoNum(p1); i++ ) + { + Gia_Obj_t * pPo1 = Gia_ManCo(p1, i); + Gia_Obj_t * pPo2 = Gia_ManCo(p2, i); + word word1 = Gia_LutComputeTruth66_rec( p1, Gia_ObjFanin0(pPo1) ); + word word2 = Gia_LutComputeTruth66_rec( p2, Gia_ObjFanin0(pPo2) ); + if ( Gia_ObjFaninC0(pPo1) ) + word1 = ~word1; + if ( Gia_ObjFaninC0(pPo2) ) + word2 = ~word2; + if ( word1 != word2 ) + { + //Dau_DsdPrintFromTruth( &word1, 6 ); + //Dau_DsdPrintFromTruth( &word2, 6 ); + printf( "Verification failed for output %d (out of %d).\n", i, Gia_ManCoNum(p1) ); + fFailed = 1; + } + } +// if ( !fFailed ) +// printf( "Verification succeeded for %d outputs.\n", Gia_ManCoNum(p1) ); + return !fFailed; +} + + + +/**Function************************************************************* + + Synopsis [Enumerate windows of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_RsbEnumerateWindows( Gia_Man_t * p, int nInputsMax, int nLevelsMax ) +{ + int fVerbose = 0; + int fUseHash = 0; + int i, nWins = 0, nWinSize = 0, nInsSize = 0, nOutSize = 0, nNodeGain = 0; + Vec_Wec_t * vLevels = Vec_WecStart( Gia_ManLevelNum(p)+1 ); + Vec_Int_t * vPaths = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vRefs = Vec_IntStart( Gia_ManObjNum(p) ); + Hsh_VecMan_t * pHash = Hsh_VecManStart( 1000 ); + Gia_Obj_t * pObj; + Gia_Man_t * pIn, * pOut; + abctime clk = Abc_Clock(); + Gia_ManStaticFanoutStart( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + Vec_Int_t * vWin, * vIns, * vOuts; + if ( !Gia_RsbWindowCompute( p, i, nInputsMax, nLevelsMax, vLevels, vPaths, &vWin, &vIns ) ) + continue; + vOuts = Gia_RsbFindOutputs( p, vWin, vIns, vRefs ); + nWins++; + nWinSize += Vec_IntSize(vWin); + nInsSize += Vec_IntSize(vIns); + nOutSize += Vec_IntSize(vOuts); + + + if ( fVerbose ) + { + printf( "\n\nObj %d\n", i ); + Vec_IntPrint( vWin ); + Vec_IntPrint( vIns ); + Vec_IntPrint( vOuts ); + printf( "\n" ); + } + else if ( Vec_IntSize(vWin) > 1000 ) + printf( "Obj %d. Window: Ins = %d. Ands = %d. Outs = %d.\n", + i, Vec_IntSize(vIns), Vec_IntSize(vWin)-Vec_IntSize(vIns), Vec_IntSize(vOuts) ); + + if ( fUseHash ) + { + int nEntries = Hsh_VecSize(pHash); + Hsh_VecManAdd( pHash, vWin ); + if ( nEntries == Hsh_VecSize(pHash) ) + { + Vec_IntFree( vWin ); + Vec_IntFree( vIns ); + Vec_IntFree( vOuts ); + continue; + } + } + + pIn = Gia_RsbDeriveGiaFromWindows( p, vWin, vIns, vOuts ); + pOut = Gia_ManResub2Test( pIn ); + //pOut = Gia_ManDup( pIn ); + if ( !Gia_ManVerifyTwoTruths( pIn, pOut ) ) + { + Gia_ManPrint( pIn ); + Gia_ManPrint( pOut ); + pOut = pOut; + } + + nNodeGain += Gia_ManAndNum(pIn) - Gia_ManAndNum(pOut); + Gia_ManStop( pIn ); + Gia_ManStop( pOut ); + + Vec_IntFree( vWin ); + Vec_IntFree( vIns ); + Vec_IntFree( vOuts ); + } + Gia_ManStaticFanoutStop( p ); + Vec_WecFree( vLevels ); + Vec_IntFree( vPaths ); + Vec_IntFree( vRefs ); + printf( "Computed windows for %d nodes (out of %d). Unique = %d. Ave inputs = %.2f. Ave outputs = %.2f. Ave volume = %.2f. Gain = %d. ", + nWins, Gia_ManAndNum(p), Hsh_VecSize(pHash), 1.0*nInsSize/Abc_MaxInt(1,nWins), + 1.0*nOutSize/Abc_MaxInt(1,nWins), 1.0*nWinSize/Abc_MaxInt(1,nWins), nNodeGain ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Hsh_VecManStop( pHash ); +} + +/**Function************************************************************* + + Synopsis [Apply k-resub to one AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_RsbTryOneWindow( Gia_Man_t * p ) +{ + return Gia_ManResub2Test( p ); +} + +/**Function************************************************************* + + Synopsis [Apply k-resub to one AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_RsbTestArray() +{ + int Array[1000] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 3, 7, 15, 17, 8, 19, + 5, 20, 5, 12, 8, 24, 4, 12, 9, 28, 27, 31, 23, 32, 4, 13, 8, 36, 5, + 13, 18, 40, 9, 18, 5, 44, 19, 36, 9, 48, 47, 51, 10, 18, 40, 54, 8, + 56, 25, 37, 44, 61, 59, 63, 8, 28, 8, 18, 25, 68, 66, 70, 64, 73, 11, + 19, 8, 13, 76, 78, 10, 19, 40, 82, 9, 84, 81, 87, 20, 61, 19, 28, 30, + 92, 91, 95, 88, 96, 74, 98, 9, 40, 49, 103, 27, 104, 10, 107, 8, 40, + 9, 24, 111, 113, 11, 115, 109, 117, 11, 66, 51, 121, 118, 122, 18, 36, + 18, 110, 93, 127, 10, 131, 129, 133, 11, 38, 32, 137, 103, 138, 19, 141, + 134, 143, 28, 76, 9, 146, 11, 110, 19, 150, 149, 153, 87, 95, 9, 19, 10, + 159, 61, 160, 18, 30, 61, 158, 9, 12, 25, 169, 19, 171, 111, 173, 10, 175, + 167, 177, 18, 102, 4, 20, 18, 171, 183, 185, 11, 187, 181, 189, 178, 190, + 24, 44, 11, 194, 8, 54, 4, 198, 197, 201, 45, 49, 10, 39, 9, 126, 73, 209, + 11, 211, 54, 168, 213, 215, 43, 167, 67, 218, 10, 221, 26, 54, 18, 18, 34, + 34, 38, 38, 40, 40, 42, 42, 52, 52, 100, 100, 124, 124, 126, 126, 144, 144, + 148, 148, 154, 154, 156, 156, 162, 162, 164, 164, 192, 192, 70, 70, 202, + 202, 204, 204, 206, 206, 216, 216, 222, 222, 224, 224 + }; + int i, iFan0, iFan1, nResubs; + int * pRes; + // create the internal array + Vec_Int_t * vArray = Vec_IntAlloc( 100 ); + for ( i = 0; i < 50 || Array[i] > 0; i++ ) + Vec_IntPush( vArray, Array[i] ); + Vec_IntPrint( vArray ); + // check the nodes + printf( "Constant0 and primary inputs:\n" ); + Vec_IntForEachEntryDouble( vArray, iFan0, iFan1, i ) + { + if ( iFan0 != iFan1 ) + break; + printf( "%2d = %c%2d & %c%2d;\n", i, + Abc_LitIsCompl(iFan0) ? '!' : ' ', Abc_Lit2Var(iFan0), + Abc_LitIsCompl(iFan1) ? '!' : ' ', Abc_Lit2Var(iFan1) ); + } + printf( "Primary outputs:\n" ); + Vec_IntForEachEntryDoubleStart( vArray, iFan0, iFan1, i, 14 ) + { + if ( iFan0 != iFan1 ) + continue; + printf( "%2d = %c%2d & %c%2d;\n", i, + Abc_LitIsCompl(iFan0) ? '!' : ' ', Abc_Lit2Var(iFan0), + Abc_LitIsCompl(iFan1) ? '!' : ' ', Abc_Lit2Var(iFan1) ); + } + // run the resub + Abc_ResubPrepareManager( 1 ); + Abc_ResubComputeWindow( Vec_IntArray(vArray), Vec_IntSize(vArray)/2, 10, -1, 0, 0, 1, 1, &pRes, &nResubs ); + Abc_ResubPrepareManager( 0 ); + Vec_IntFree( vArray ); +} + +/**Function************************************************************* + + Synopsis [Computing cuts of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManExtractCuts2( Gia_Man_t * p, int nCutSize, int nCuts, int fVerbose ) +{ + int c, nLevelMax = 8; + abctime clk = Abc_Clock(); + Vec_Wec_t * vCuts = Vec_WecStart( nCuts ); + Vec_Int_t * vPaths = Vec_IntStart( Gia_ManObjNum(p) ); + srand( time(NULL) ); + for ( c = 0; c < nCuts; ) + { + Vec_Int_t * vCut, * vWin = NULL; + while ( vWin == NULL ) + { + int iPivot = 1 + Gia_ManCiNum(p) + rand() % Gia_ManAndNum(p); + assert( Gia_ObjIsAnd(Gia_ManObj(p, iPivot)) ); + vWin = Gia_RsbWindowInit( p, vPaths, iPivot, nLevelMax ); + } + vCut = Gia_RsbCreateWindowInputs( p, vWin ); + if ( Vec_IntSize(vCut) >= nCutSize - 2 && Vec_IntSize(vCut) <= nCutSize ) + { + Vec_IntPush( Vec_WecEntry(vCuts, c), Vec_IntSize(vCut) ); + Vec_IntAppend( Vec_WecEntry(vCuts, c++), vCut ); + } + Vec_IntFree( vCut ); + Vec_IntFree( vWin ); + } + Vec_IntFree( vPaths ); + Abc_PrintTime( 0, "Computing cuts ", Abc_Clock() - clk ); + return vCuts; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaResub3.c b/abc/src/aig/gia/giaResub3.c new file mode 100644 index 00000000000..71e182d11c3 --- /dev/null +++ b/abc/src/aig/gia/giaResub3.c @@ -0,0 +1,54 @@ +/**CFile**************************************************************** + + FileName [giaResub3.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Resubstitution computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaResub3.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPerformNewResub( Gia_Man_t * p, int nWinCount, int nCutSize, int nProcs, int fVerbose ) +{ + return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaResub6.c b/abc/src/aig/gia/giaResub6.c new file mode 100644 index 00000000000..3203a6996e1 --- /dev/null +++ b/abc/src/aig/gia/giaResub6.c @@ -0,0 +1,451 @@ +/**CFile**************************************************************** + + FileName [giaResub6.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Resubstitution.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaResub6.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilTruth.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define MAX_NODE 100 + +typedef struct Res6_Man_t_ Res6_Man_t; +struct Res6_Man_t_ +{ + int nIns; // inputs + int nDivs; // divisors + int nDivsA; // divisors alloc + int nOuts; // outputs + int nPats; // patterns + int nWords; // words + Vec_Wrd_t vIns; // input sim data + Vec_Wrd_t vOuts; // input sim data + word ** ppLits; // literal sim info + word ** ppSets; // set sim info + Vec_Int_t vSol; // current solution + Vec_Int_t vSolBest; // best solution + Vec_Int_t vTempBest;// current best solution +}; + +extern void Dau_DsdPrintFromTruth2( word * pTruth, int nVarsInit ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Res6_Man_t * Res6_ManStart( int nIns, int nNodes, int nOuts, int nPats ) +{ + Res6_Man_t * p; int i; + p = ABC_CALLOC( Res6_Man_t, 1 ); + p->nIns = nIns; + p->nDivs = 1 + nIns + nNodes; + p->nDivsA = p->nDivs + MAX_NODE; + p->nOuts = nOuts; + p->nPats = nPats; + p->nWords =(nPats + 63)/64; + Vec_WrdFill( &p->vIns, 2*p->nDivsA*p->nWords, 0 ); + Vec_WrdFill( &p->vOuts, (1 << nOuts)*p->nWords, 0 ); + p->ppLits = ABC_CALLOC( word *, 2*p->nDivsA ); + p->ppSets = ABC_CALLOC( word *, 1 << nOuts ); + for ( i = 0; i < 2*p->nDivsA; i++ ) + p->ppLits[i] = Vec_WrdEntryP( &p->vIns, i*p->nWords ); + for ( i = 0; i < (1 << nOuts); i++ ) + p->ppSets[i] = Vec_WrdEntryP( &p->vOuts, i*p->nWords ); + Abc_TtFill( p->ppLits[1], p->nWords ); + Vec_IntGrow( &p->vSol, 2*MAX_NODE+nOuts ); + Vec_IntGrow( &p->vSolBest, 2*MAX_NODE+nOuts ); + Vec_IntGrow( &p->vTempBest, 2*MAX_NODE+nOuts ); + return p; +} +static inline void Res6_ManStop( Res6_Man_t * p ) +{ + Vec_WrdErase( &p->vIns ); + Vec_WrdErase( &p->vOuts ); + Vec_IntErase( &p->vSol ); + Vec_IntErase( &p->vSolBest ); + Vec_IntErase( &p->vTempBest ); + ABC_FREE( p->ppLits ); + ABC_FREE( p->ppSets ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Res6_Man_t * Res6_ManRead( char * pFileName ) +{ + Res6_Man_t * p = NULL; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + printf( "Cannot open input file \"%s\".\n", pFileName ); + else + { + int i, k, nIns, nNodes, nOuts, nPats; + char Temp[100], Buffer[100]; + char * pLine = fgets( Buffer, 100, pFile ); + if ( pLine == NULL ) + { + printf( "Cannot read the header line of input file \"%s\".\n", pFileName ); + return NULL; + } + if ( 5 != sscanf(pLine, "%s %d %d %d %d", Temp, &nIns, &nNodes, &nOuts, &nPats) ) + { + printf( "Cannot read the parameters from the header of input file \"%s\".\n", pFileName ); + return NULL; + } + p = Res6_ManStart( nIns, nNodes, nOuts, nPats ); + pLine = ABC_ALLOC( char, nPats + 100 ); + for ( i = 1; i < p->nDivs; i++ ) + { + char * pNext = fgets( pLine, nPats + 100, pFile ); + if ( pNext == NULL ) + { + printf( "Cannot read line %d of input file \"%s\".\n", i, pFileName ); + Res6_ManStop( p ); + ABC_FREE( pLine ); + fclose( pFile ); + return NULL; + } + for ( k = 0; k < p->nPats; k++ ) + if ( pNext[k] == '0' ) + Abc_TtSetBit( p->ppLits[2*i+1], k ); + else if ( pNext[k] == '1' ) + Abc_TtSetBit( p->ppLits[2*i], k ); + } + for ( i = 0; i < (1 << p->nOuts); i++ ) + { + char * pNext = fgets( pLine, nPats + 100, pFile ); + if ( pNext == NULL ) + { + printf( "Cannot read line %d of input file \"%s\".\n", i, pFileName ); + Res6_ManStop( p ); + ABC_FREE( pLine ); + fclose( pFile ); + return NULL; + } + for ( k = 0; k < p->nPats; k++ ) + if ( pNext[k] == '1' ) + Abc_TtSetBit( p->ppSets[i], k ); + } + ABC_FREE( pLine ); + fclose( pFile ); + } + return p; +} +void Res6_ManWrite( char * pFileName, Res6_Man_t * p ) +{ + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open output file \"%s\".\n", pFileName ); + else + { + int i, k; + fprintf( pFile, "resyn %d %d %d %d\n", p->nIns, p->nDivs - p->nIns - 1, p->nOuts, p->nPats ); + for ( i = 1; i < p->nDivs; i++, fputc('\n', pFile) ) + for ( k = 0; k < p->nPats; k++ ) + if ( Abc_TtGetBit(p->ppLits[2*i+1], k) ) + fputc( '0', pFile ); + else if ( Abc_TtGetBit(p->ppLits[2*i], k) ) + fputc( '1', pFile ); + else + fputc( '-', pFile ); + for ( i = 0; i < (1 << p->nOuts); i++, fputc('\n', pFile) ) + for ( k = 0; k < p->nPats; k++ ) + fputc( '0' + Abc_TtGetBit(p->ppSets[i], k), pFile ); + fclose( pFile ); + } +} +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 ); + if ( !fVerbose ) + return; + printf( "%02d : %s\n", 0, "const0" ); + printf( "%02d : %s\n", 1, "const1" ); + for ( i = 1; i < p->nDivs; i++ ) + { + if ( nInputs < 6 ) + { + *p->ppLits[2*i+0] = Abc_Tt6Stretch( *p->ppLits[2*i+0], nInputs ); + *p->ppLits[2*i+1] = Abc_Tt6Stretch( *p->ppLits[2*i+1], nInputs ); + } + printf("%02d : ", 2*i+0), Dau_DsdPrintFromTruth2(p->ppLits[2*i+0], nInputs), printf( "\n" ); + printf("%02d : ", 2*i+1), Dau_DsdPrintFromTruth2(p->ppLits[2*i+1], nInputs), printf( "\n" ); + } + for ( i = 0; i < (1 << p->nOuts); i++ ) + { + if ( nInputs < 6 ) + *p->ppSets[i] = Abc_Tt6Stretch( *p->ppSets[i], nInputs ); + printf("%02d : ", i), Dau_DsdPrintFromTruth2(p->ppSets[i], nInputs), printf( "\n" ); + } +} +static inline Vec_Int_t * Res6_ManReadSol( char * pFileName ) +{ + Vec_Int_t * vRes = NULL; int Num; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + printf( "Cannot open input file \"%s\".\n", pFileName ); + else + { + while ( fgetc(pFile) != '\n' ); + vRes = Vec_IntAlloc( 10 ); + while ( fscanf(pFile, "%d", &Num) == 1 ) + Vec_IntPush( vRes, Num ); + fclose ( pFile ); + } + return vRes; +} +static inline void Res6_ManWriteSol( char * pFileName, Vec_Int_t * p ) +{ + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open output file \"%s\".\n", pFileName ); + else + { + int i, iLit; + Vec_IntForEachEntry( p, iLit, i ) + fprintf( pFile, "%d ", iLit ); + fclose ( pFile ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Res6_LitSign( int iLit ) +{ + return Abc_LitIsCompl(iLit) ? '~' : ' '; +} +static inline int Res6_LitChar( int iLit, int nDivs ) +{ + return Abc_Lit2Var(iLit) < nDivs ? (nDivs < 28 ? 'a'+Abc_Lit2Var(iLit)-1 : 'd') : 'x'; +} +static inline void Res6_LitPrint( int iLit, int nDivs ) +{ + if ( iLit < 2 ) + printf( "%d", iLit ); + else + { + printf( "%c%c", Res6_LitSign(iLit), Res6_LitChar(iLit, nDivs) ); + if ( Abc_Lit2Var(iLit) >= nDivs || nDivs >= 28 ) + printf( "%d", Abc_Lit2Var(iLit) ); + } +} +Vec_Int_t * Res6_FindSupport( Vec_Int_t * vSol, int nDivs ) +{ + int i, iLit; + Vec_Int_t * vSupp = Vec_IntAlloc( 10 ); + Vec_IntForEachEntry( vSol, iLit, i ) + if ( iLit >= 2 && iLit < 2*nDivs ) + Vec_IntPushUnique( vSupp, Abc_Lit2Var(iLit) ); + return vSupp; +} +void Res6_PrintSuppSims( Vec_Int_t * vSol, word ** ppLits, int nWords, int nDivs ) +{ + Vec_Int_t * vSupp = Res6_FindSupport( vSol, nDivs ); + int i, k, iObj; + Vec_IntForEachEntry( vSupp, iObj, i ) + { + for ( k = 0; k < 64*nWords; k++ ) + if ( Abc_TtGetBit(ppLits[2*iObj+1], k) ) + printf( "0" ); + else if ( Abc_TtGetBit(ppLits[2*iObj], k) ) + printf( "1" ); + else + printf( "-" ); + printf( "\n" ); + } + for ( k = 0; k < 64*nWords; k++ ) + { + Vec_IntForEachEntry( vSupp, iObj, i ) + if ( Abc_TtGetBit(ppLits[2*iObj+1], k) ) + printf( "0" ); + else if ( Abc_TtGetBit(ppLits[2*iObj+0], k) ) + printf( "1" ); + else + printf( "-" ); + printf( "\n" ); + if ( k == 9 ) + break; + } + Vec_IntFree( vSupp ); +} +int Res6_FindSupportSize( Vec_Int_t * vSol, int nDivs ) +{ + Vec_Int_t * vSupp = Res6_FindSupport( vSol, nDivs ); + int Res = Vec_IntSize(vSupp); + Vec_IntFree( vSupp ); + return Res; +} +void Res6_PrintSolution( Vec_Int_t * vSol, 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", Res6_FindSupportSize(vSol, nDivs), nDivs-1, nNodes, 1 ); + for ( iNode = 0; iNode <= nNodes; iNode++ ) + { + int * pLits = Vec_IntEntryP( vSol, 2*iNode ); + printf( "x%-2d = ", nDivs + iNode ); + Res6_LitPrint( pLits[0], nDivs ); + if ( pLits[0] != pLits[1] ) + { + printf( " %c ", pLits[0] < pLits[1] ? '&' : '^' ); + Res6_LitPrint( pLits[1], nDivs ); + } + printf( "\n" ); + } +} +int Res6_FindGetCost( Res6_Man_t * p, int iDiv ) +{ + int w, Cost = 0; + //printf( "DivLit = %d\n", iDiv ); + //Abc_TtPrintBinary1( stdout, p->ppLits[iDiv], p->nIns ); printf( "\n" ); + //printf( "Set0\n" ); + //Abc_TtPrintBinary1( stdout, p->ppSets[0], p->nIns ); printf( "\n" ); + //printf( "Set1\n" ); + //Abc_TtPrintBinary1( stdout, p->ppSets[1], p->nIns ); printf( "\n" ); + for ( w = 0; w < p->nWords; w++ ) + Cost += Abc_TtCountOnes( (p->ppLits[iDiv][w] & p->ppSets[0][w]) | (p->ppLits[iDiv^1][w] & p->ppSets[1][w]) ); + return Cost; +} +int Res6_FindBestDiv( Res6_Man_t * p, int * pCost ) +{ + int d, dBest = -1, CostBest = ABC_INFINITY; + for ( d = 0; d < 2*p->nDivs; d++ ) + { + int Cost = Res6_FindGetCost( p, d ); + printf( "Div = %d Cost = %d\n", d, Cost ); + if ( CostBest >= Cost ) + CostBest = Cost, dBest = d; + } + if ( pCost ) + *pCost = CostBest; + return dBest; +} +int Res6_FindBestEval( Res6_Man_t * p, Vec_Int_t * vSol, int Start ) +{ + int i, iLit0, iLit1; + assert( Vec_IntSize(vSol) % 2 == 0 ); + Vec_IntForEachEntryDoubleStart( vSol, iLit0, iLit1, i, 2*Start ) + { + if ( iLit0 > iLit1 ) + { + Abc_TtXor( p->ppLits[2*p->nDivs+i+0], p->ppLits[iLit0], p->ppLits[iLit1], p->nWords, 0 ); + Abc_TtXor( p->ppLits[2*p->nDivs+i+1], p->ppLits[iLit0], p->ppLits[iLit1], p->nWords, 1 ); + } + else + { + Abc_TtAnd( p->ppLits[2*p->nDivs+i+0], p->ppLits[iLit0], p->ppLits[iLit1], p->nWords, 0 ); + Abc_TtOr ( p->ppLits[2*p->nDivs+i+1], p->ppLits[iLit0^1], p->ppLits[iLit1^1], p->nWords ); + } + + //printf( "Node %d\n", i/2 ); + //Abc_TtPrintBinary1( stdout, p->ppLits[2*p->nDivs+i+0], 6 ); printf( "\n" ); + //Abc_TtPrintBinary1( stdout, p->ppLits[2*p->nDivs+i+1], 6 ); printf( "\n" ); + } + return Res6_FindGetCost( p, Vec_IntEntryLast(vSol) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res6_ManResubVerify( Res6_Man_t * p, Vec_Int_t * vSol ) +{ + int Cost = Res6_FindBestEval( p, vSol, 0 ); + if ( Cost == 0 ) + printf( "Verification successful.\n" ); + else + printf( "Verification FAILED with %d errors on %d patterns.\n", Cost, p->nPats ); +} +void Res6_ManResubCheck( char * pFileNameRes, char * pFileNameSol, int fVerbose ) +{ + char FileNameSol[1000]; + if ( pFileNameSol ) + strcpy( FileNameSol, pFileNameSol ); + else + { + strcpy( FileNameSol, pFileNameRes ); + strcpy( FileNameSol + strlen(FileNameSol) - strlen(".resub"), ".sol" ); + } + { + Res6_Man_t * p = Res6_ManRead( pFileNameRes ); + Vec_Int_t * vSol = Res6_ManReadSol( FileNameSol ); + if ( p == NULL || vSol == NULL ) + return; + if ( fVerbose ) + Res6_ManPrintProblem( p, 0 ); + if ( fVerbose ) + Res6_PrintSolution( vSol, p->nDivs ); + //if ( fVerbose ) + // Res6_PrintSuppSims( vSol, p->ppLits, p->nWords, p->nDivs ); + Res6_ManResubVerify( p, vSol ); + Vec_IntFree( vSol ); + Res6_ManStop( p ); + } +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaRex.c b/abc/src/aig/gia/giaRex.c index ebfc9401914..7f8d365e82b 100644 --- a/abc/src/aig/gia/giaRex.c +++ b/abc/src/aig/gia/giaRex.c @@ -309,7 +309,7 @@ Gia_Man_t * Gia_ManRex2Gia( char * pStrInit, int fOrder, int fVerbose ) Gia_ManStop( pTemp ); // add initial state - pNew = Gia_ManDupZeroUndc( pTemp = pNew, Vec_StrArray(vInit), 0, 0 ); + pNew = Gia_ManDupZeroUndc( pTemp = pNew, Vec_StrArray(vInit), 0, 0, 0 ); Gia_ManStop( pTemp ); Vec_StrFree( vInit ); /* diff --git a/abc/src/aig/gia/giaSatMap.c b/abc/src/aig/gia/giaSatMap.c index 5c17b74eb8c..a73950fba2c 100644 --- a/abc/src/aig/gia/giaSatMap.c +++ b/abc/src/aig/gia/giaSatMap.c @@ -269,6 +269,118 @@ static inline int sat_solver_add_and2( sat_solver * pSat, int iVar, int iVar0, i return 3; } + +/**Function************************************************************* + + Synopsis [Adds a general cardinality constraint in terms of vVars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Card_AddClause( Vec_Int_t * p, int* begin, int* end ) +{ + Vec_IntPush( p, (int)(end-begin) ); + while ( begin < end ) + Vec_IntPush( p, (int)*begin++ ); + return 1; +} +static inline int Card_AddHalfSorter( Vec_Int_t * p, int iVarA, int iVarB, int iVar0, int iVar1 ) +{ + lit Lits[3]; + int Cid; + + Lits[0] = toLitCond( iVarA, 0 ); + Lits[1] = toLitCond( iVar0, 1 ); + Cid = Card_AddClause( p, Lits, Lits + 2 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarA, 0 ); + Lits[1] = toLitCond( iVar1, 1 ); + Cid = Card_AddClause( p, Lits, Lits + 2 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarB, 0 ); + Lits[1] = toLitCond( iVar0, 1 ); + Lits[2] = toLitCond( iVar1, 1 ); + Cid = Card_AddClause( p, Lits, Lits + 3 ); + assert( Cid ); + return 3; +} +static inline void Card_AddSorter( Vec_Int_t * p, int * pVars, int i, int k, int * pnVars ) +{ + int iVar1 = (*pnVars)++; + int iVar2 = (*pnVars)++; + Card_AddHalfSorter( p, iVar1, iVar2, pVars[i], pVars[k] ); + pVars[i] = iVar1; + pVars[k] = iVar2; +} +static inline void Card_AddCardinConstrMerge( Vec_Int_t * p, int * pVars, int lo, int hi, int r, int * pnVars ) +{ + int i, step = r * 2; + if ( step < hi - lo ) + { + Card_AddCardinConstrMerge( p, pVars, lo, hi-r, step, pnVars ); + Card_AddCardinConstrMerge( p, pVars, lo+r, hi, step, pnVars ); + for ( i = lo+r; i < hi-r; i += step ) + Card_AddSorter( p, pVars, i, i+r, pnVars ); + for ( i = lo+r; i < hi-r-1; i += r ) + { + lit Lits[2] = { Abc_Var2Lit(pVars[i], 0), Abc_Var2Lit(pVars[i+r], 1) }; + int Cid = Card_AddClause( p, Lits, Lits + 2 ); + assert( Cid ); + } + } +} +static inline void Card_AddCardinConstrRange( Vec_Int_t * p, int * pVars, int lo, int hi, int * pnVars ) +{ + if ( hi - lo >= 1 ) + { + int i, mid = lo + (hi - lo) / 2; + for ( i = lo; i <= mid; i++ ) + Card_AddSorter( p, pVars, i, i + (hi - lo + 1) / 2, pnVars ); + Card_AddCardinConstrRange( p, pVars, lo, mid, pnVars ); + Card_AddCardinConstrRange( p, pVars, mid+1, hi, pnVars ); + Card_AddCardinConstrMerge( p, pVars, lo, hi, 1, pnVars ); + } +} +int Card_AddCardinConstrPairWise( Vec_Int_t * p, Vec_Int_t * vVars ) +{ + int nVars = Vec_IntSize(vVars); + Card_AddCardinConstrRange( p, Vec_IntArray(vVars), 0, nVars - 1, &nVars ); + return nVars; +} +int Card_AddCardinSolver( int LogN, Vec_Int_t ** pvVars, Vec_Int_t ** pvRes ) +{ + int nVars = 1 << LogN; + int nVarsAlloc = nVars + 2 * (nVars * LogN * (LogN-1) / 4 + nVars - 1); + Vec_Int_t * vRes = Vec_IntAlloc( 1000 ); + Vec_Int_t * vVars = Vec_IntStartNatural( nVars ); + int nVarsReal = Card_AddCardinConstrPairWise( vRes, vVars ); + assert( nVarsReal == nVarsAlloc ); + Vec_IntPush( vRes, -1 ); + *pvVars = vVars; + *pvRes = vRes; + return nVarsReal; +} +sat_solver * Sbm_AddCardinSolver2( int LogN, Vec_Int_t ** pvVars, Vec_Int_t ** pvRes ) +{ + Vec_Int_t * vVars = NULL; + Vec_Int_t * vRes = NULL; + int nVarsReal = Card_AddCardinSolver( LogN, &vVars, &vRes ), i, size; + sat_solver * pSat = sat_solver_new(); + sat_solver_setnvars( pSat, nVarsReal ); + for ( i = 0, size = Vec_IntEntry(vRes, i++); i < Vec_IntSize(vRes); i += size, size = Vec_IntEntry(vRes, i++) ) + sat_solver_addclause( pSat, Vec_IntEntryP(vRes, i), Vec_IntEntryP(vRes, i+size) ); + if ( pvVars ) *pvVars = vVars; + if ( pvRes ) *pvRes = vRes; + return pSat; +} + + /**Function************************************************************* Synopsis [Adds a general cardinality constraint in terms of vVars.] diff --git a/abc/src/aig/gia/giaSatSyn.c b/abc/src/aig/gia/giaSatSyn.c new file mode 100644 index 00000000000..15829f79b90 --- /dev/null +++ b/abc/src/aig/gia/giaSatSyn.c @@ -0,0 +1,60 @@ +/**CFile**************************************************************** + + FileName [giaSyn.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [High-effort synthesis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSyn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilTruth.h" +#include "sat/glucose/AbcGlucose.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManSyn( Gia_Man_t * p, int nNodes, int nOuts, int nTimeLimit, int fUseXor, int fFancy, int fVerbose ) +{ + Gia_Man_t * pNew = NULL; + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaScript.c b/abc/src/aig/gia/giaScript.c index fcf975117b5..b52288a946e 100644 --- a/abc/src/aig/gia/giaScript.c +++ b/abc/src/aig/gia/giaScript.c @@ -88,7 +88,12 @@ Gia_Man_t * Gia_ManAigSyn2( Gia_Man_t * pInit, int fOldAlgo, int fCoarsen, int f p = Gia_ManDup( pInit ); Gia_ManTransferTiming( p, pInit ); if ( Gia_ManAndNum(p) == 0 ) - return p; + { + pNew = Gia_ManDup(p); + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + return pNew; + } // delay optimization if ( fDelayMin && p->pManTime == NULL ) { @@ -157,7 +162,12 @@ Gia_Man_t * Gia_ManAigSyn3( Gia_Man_t * p, int fVerbose, int fVeryVerbose ) pPars->nRelaxRatio = 40; if ( fVerbose ) Gia_ManPrintStats( p, NULL ); if ( Gia_ManAndNum(p) == 0 ) - return Gia_ManDup(p); + { + pNew = Gia_ManDup(p); + Gia_ManTransferTiming( pNew, p ); + //Gia_ManStop( p ); + return pNew; + } // perform balancing pNew = Gia_ManAreaBalance( p, 0, ABC_INFINITY, fVeryVerbose, 0 ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); @@ -189,7 +199,12 @@ Gia_Man_t * Gia_ManAigSyn4( Gia_Man_t * p, int fVerbose, int fVeryVerbose ) pPars->nRelaxRatio = 40; if ( fVerbose ) Gia_ManPrintStats( p, NULL ); if ( Gia_ManAndNum(p) == 0 ) - return Gia_ManDup(p); + { + pNew = Gia_ManDup(p); + Gia_ManTransferTiming( pNew, p ); + //Gia_ManStop( p ); + return pNew; + } //Gia_ManAigPrintPiLevels( p ); // perform balancing pNew = Gia_ManAreaBalance( p, 0, ABC_INFINITY, fVeryVerbose, 0 ); @@ -609,11 +624,21 @@ void Gia_ManPerformFlow( int fIsMapped, int nAnds, int nLevels, int nLutSize, in ***********************************************************************/ void Gia_ManPerformFlow2( int fIsMapped, int nAnds, int nLevels, int nLutSize, int nCutNum, int fBalance, int fMinAve, int fUseMfs, int fVerbose ) { - char Comm1[100], Comm2[100], Comm3[100], Comm4[100]; - sprintf( Comm1, "&synch2 -K %d -C 500; &if -m%s -K %d -C %d; %s &save", nLutSize, fMinAve?"t":"", nLutSize, nCutNum, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); - sprintf( Comm2, "&dch -C 500; &if -m%s -K %d -C %d; %s &save", fMinAve?"t":"", nLutSize, nCutNum+4, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); - sprintf( Comm3, "&synch2 -K %d -C 500; &lf -m%s -E 5 -K %d -C %d; %s &save", nLutSize, fMinAve?"t":"", nLutSize, nCutNum, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); - sprintf( Comm4, "&dch -C 500; &lf -m%sk -E 5 -K %d -C %d; %s &save", fMinAve?"t":"", nLutSize, nCutNum+4, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + char Comm1[1000], Comm2[1000], Comm3[1000], Comm4[1000]; + if ( nLutSize == 0 ) + { + sprintf( Comm1, "&synch2 -K 6 -C 500; &if -m%s -C %d; %s &save", fMinAve?"t":"", nCutNum, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + sprintf( Comm2, "&dch -C 500; &if -m%s -C %d; %s &save", fMinAve?"t":"", nCutNum+4, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + sprintf( Comm3, "&synch2 -K 6 -C 500; &lf -m%s -E 5 -C %d; %s &save", fMinAve?"t":"", nCutNum, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + sprintf( Comm4, "&dch -C 500; &lf -m%sk -E 5 -C %d; %s &save", fMinAve?"t":"", nCutNum+4, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + } + else + { + sprintf( Comm1, "&synch2 -K %d -C 500; &if -m%s -K %d -C %d; %s &save", nLutSize, fMinAve?"t":"", nLutSize, nCutNum, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + sprintf( Comm2, "&dch -C 500; &if -m%s -K %d -C %d; %s &save", fMinAve?"t":"", nLutSize, nCutNum+4, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + sprintf( Comm3, "&synch2 -K %d -C 500; &lf -m%s -E 5 -K %d -C %d; %s &save", nLutSize, fMinAve?"t":"", nLutSize, nCutNum, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + sprintf( Comm4, "&dch -C 500; &lf -m%sk -E 5 -K %d -C %d; %s &save", fMinAve?"t":"", nLutSize, nCutNum+4, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + } // perform synthesis if ( fVerbose ) diff --git a/abc/src/aig/gia/giaShow.c b/abc/src/aig/gia/giaShow.c index ead794ebaf2..c3a211849d8 100644 --- a/abc/src/aig/gia/giaShow.c +++ b/abc/src/aig/gia/giaShow.c @@ -1125,7 +1125,7 @@ void Gia_ShowProcess( Gia_Man_t * p, char * pFileName, Vec_Int_t * vBold, Vec_In } void Gia_ManShow( Gia_Man_t * pMan, Vec_Int_t * vBold, int fAdders, int fFadds, int fPath ) { - extern void Abc_ShowFile( char * FileNameDot ); + extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); char FileNameDot[200]; FILE * pFile; Vec_Int_t * vXors = NULL, * vAdds = fAdders ? Ree_ManComputeCuts( pMan, &vXors, 0 ) : NULL; @@ -1145,7 +1145,7 @@ void Gia_ManShow( Gia_Man_t * pMan, Vec_Int_t * vBold, int fAdders, int fFadds, else Gia_WriteDotAigSimple( pMan, FileNameDot, vBold ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); Vec_IntFreeP( &vAdds ); Vec_IntFreeP( &vXors ); diff --git a/abc/src/aig/gia/giaSif.c b/abc/src/aig/gia/giaSif.c new file mode 100644 index 00000000000..db7629fb302 --- /dev/null +++ b/abc/src/aig/gia/giaSif.c @@ -0,0 +1,650 @@ +/**CFile**************************************************************** + + FileName [giaSif.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Sequential mapping.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSif.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_ManSifDupNode_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjUpdateTravIdCurrent(p, pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManSifDupNode_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManSifDupNode_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManAppendAnd2( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +void Gia_ManSifDupNode( Gia_Man_t * pNew, Gia_Man_t * p, int iObj, Vec_Int_t * vCopy ) +{ + int k, iFan; + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + Gia_ManIncrementTravId( p ); + Gia_LutForEachFanin( p, iObj, iFan, k ) + { + assert( Vec_IntEntry(vCopy, iFan) >= 0 ); + Gia_ManObj(p, iFan)->Value = Vec_IntEntry(vCopy, iFan); + Gia_ObjUpdateTravIdCurrentId(p, iFan); + } + Gia_ManSifDupNode_rec( pNew, p, pObj ); + Vec_IntWriteEntry( vCopy, iObj, pObj->Value ); +} +Vec_Int_t * Gia_ManSifInitNeg( Gia_Man_t * p, Vec_Int_t * vMoves, Vec_Int_t * vRegs ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( Vec_IntSize(vRegs) ); + Gia_Obj_t * pObj; int i, iObj; + Gia_Man_t * pNew = Gia_ManStart( 1000 ), * pTemp; + Vec_Int_t * vCopy = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_IntWriteEntry( vCopy, 0, 0 ); + Gia_ManForEachRo( p, pObj, i ) + Vec_IntWriteEntry( vCopy, Gia_ObjId(p, pObj), Gia_ManAppendCi(pNew) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Vec_IntForEachEntry( vMoves, iObj, i ) + Gia_ManSifDupNode( pNew, p, iObj, vCopy ); + Vec_IntForEachEntry( vRegs, iObj, i ) + { + int iLit = Vec_IntEntry( vCopy, iObj ); + assert( iLit >= 0 ); + Gia_ManAppendCo( pNew, iLit ); + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Gia_ManSetPhase( pNew ); + Gia_ManForEachPo( pNew, pObj, i ) + Vec_IntPush( vRes, pObj->fPhase ); + Gia_ManStop( pNew ); + Vec_IntFree( vCopy ); + assert( Vec_IntSize(vRes) == Vec_IntSize(vRegs) ); + return vRes; +} +Vec_Int_t * Gia_ManSifInitPos( Gia_Man_t * p, Vec_Int_t * vMoves, Vec_Int_t * vRegs ) +{ + extern int * Abc_NtkSolveGiaMiter( Gia_Man_t * p ); + int i, iObj, iLitAnd = 1, * pResult = NULL; + Gia_Obj_t * pObj; Vec_Int_t * vRes = NULL; + Gia_Man_t * pNew = Gia_ManStart( 1000 ), * pTemp; + Vec_Int_t * vCopy = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_IntWriteEntry( vCopy, 0, 0 ); + Vec_IntForEachEntry( vRegs, iObj, i ) + Vec_IntWriteEntry( vCopy, iObj, Gia_ManAppendCi(pNew) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Vec_IntForEachEntry( vMoves, iObj, i ) + Gia_ManSifDupNode( pNew, p, iObj, vCopy ); + Gia_ManForEachRi( p, pObj, i ) + { + int iFan = Gia_ObjFaninId0p(p, pObj); + int iLit = Vec_IntEntry(vCopy, iFan); + if ( iLit == -1 ) + continue; + iLit = Abc_LitNotCond( iLit, Gia_ObjFaninC0(pObj) ); + iLitAnd = Gia_ManAppendAnd2( pNew, iLitAnd, Abc_LitNot(iLit) ); + } + Gia_ManAppendCo( pNew, iLitAnd ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + pResult = Abc_NtkSolveGiaMiter( pNew ); + if ( pResult ) + { + vRes = Vec_IntAllocArray( pResult, Vec_IntSize(vRegs) ); + Gia_ManSetPhasePattern( pNew, vRes ); + assert( Gia_ManPo(pNew, 0)->fPhase == 1 ); + } + else + { + vRes = Vec_IntStart( Vec_IntSize(vRegs) ); + printf( "***!!!*** The SAT problem has no solution. Using all-0 initial state. ***!!!***\n" ); + } + Gia_ManStop( pNew ); + Vec_IntFree( vCopy ); + assert( Vec_IntSize(vRes) == Vec_IntSize(vRegs) ); + return vRes; +} +Gia_Man_t * Gia_ManSifDerive( Gia_Man_t * p, Vec_Int_t * vCounts, int fVerbose ) +{ + Gia_Man_t * pNew = NULL; Gia_Obj_t * pObj; + Vec_Int_t * vCopy = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_Int_t * vCopy2 = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_Int_t * vLuts[3], * vRos[3], * vRegs[2], * vInits[2], * vTemp; + int i, k, Id, iFan; + for ( i = 0; i < 3; i++ ) + { + vLuts[i] = Vec_IntAlloc(100); + vRos[i] = Vec_IntAlloc(100); + if ( i == 2 ) break; + vRegs[i] = Vec_IntAlloc(100); + } + Gia_ManForEachLut( p, i ) + if ( Vec_IntEntry(vCounts, i) == 1 ) + Vec_IntPush( vLuts[0], i ); + else if ( Vec_IntEntry(vCounts, i) == -1 ) + Vec_IntPush( vLuts[1], i ); + else if ( Vec_IntEntry(vCounts, i) == 0 ) + Vec_IntPush( vLuts[2], i ); + else assert( 0 ); + assert( Vec_IntSize(vLuts[0]) || Vec_IntSize(vLuts[1]) ); + if ( Vec_IntSize(vLuts[0]) ) + { + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLuts[0], Id, i ) + Gia_ObjSetTravIdCurrentId(p, Id); + Gia_ManForEachRo( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(Gia_ObjRoToRi(p, pObj))) ) + Vec_IntPush( vRos[0], Gia_ObjId(p, pObj) ); + assert( !Vec_IntSize(vLuts[0]) == !Vec_IntSize(vRos[0]) ); + } + if ( Vec_IntSize(vLuts[1]) ) + { + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLuts[1], Id, i ) + Gia_LutForEachFanin( p, Id, iFan, k ) + Gia_ObjSetTravIdCurrentId(p, iFan); + Gia_ManForEachRo( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + Vec_IntPush( vRos[1], Gia_ObjId(p, pObj) ); + assert( !Vec_IntSize(vLuts[1]) == !Vec_IntSize(vRos[1]) ); + } + Gia_ManIncrementTravId( p ); + for ( k = 0; k < 2; k++ ) + Vec_IntForEachEntry( vRos[k], Id, i ) + Gia_ObjSetTravIdCurrentId(p, Id); + Gia_ManForEachRo( p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) + Vec_IntPush( vRos[2], Gia_ObjId(p, pObj) ); + + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLuts[0], Id, i ) + Gia_ObjSetTravIdCurrentId(p, Id); + Vec_IntForEachEntry( vLuts[0], Id, i ) + Gia_LutForEachFanin( p, Id, iFan, k ) + if ( !Gia_ObjUpdateTravIdCurrentId(p, iFan) ) + Vec_IntPush( vRegs[0], iFan ); + Vec_IntSort( vRegs[0], 0 ); + assert( Vec_IntCountDuplicates(vRegs[1]) == 0 ); + assert( !Vec_IntSize(vLuts[0]) == !Vec_IntSize(vRegs[0]) ); + + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLuts[0], Id, i ) + Gia_LutForEachFanin( p, Id, iFan, k ) + Gia_ObjSetTravIdCurrentId(p, iFan); + Vec_IntForEachEntry( vLuts[2], Id, i ) + Gia_LutForEachFanin( p, Id, iFan, k ) + Gia_ObjSetTravIdCurrentId(p, iFan); + Gia_ManForEachCo( p, pObj, i ) + Gia_ObjSetTravIdCurrentId(p, Gia_ObjFaninId0p(p, pObj)); + Vec_IntForEachEntry( vRos[1], Id, i ) + if ( Gia_ObjIsTravIdCurrentId(p, Id) ) + Vec_IntPush( vRegs[1], Id ); + Vec_IntForEachEntry( vLuts[1], Id, i ) + if ( Gia_ObjIsTravIdCurrentId(p, Id) ) + Vec_IntPush( vRegs[1], Id ); + Vec_IntSort( vRegs[1], 0 ); + assert( Vec_IntCountDuplicates(vRegs[1]) == 0 ); + assert( !Vec_IntSize(vLuts[1]) == !Vec_IntSize(vRegs[1]) ); + + vInits[0] = Vec_IntSize(vLuts[0]) ? Gia_ManSifInitPos( p, vLuts[0], vRegs[0] ) : Vec_IntAlloc(0); + vInits[1] = Vec_IntSize(vLuts[1]) ? Gia_ManSifInitNeg( p, vLuts[1], vRegs[1] ) : Vec_IntAlloc(0); + + if ( fVerbose ) + { + printf( "Flops : %5d %5d %5d\n", Vec_IntSize(vRos[0]), Vec_IntSize(vRos[1]), Vec_IntSize(vRos[2]) ); + printf( "LUTs : %5d %5d %5d\n", Vec_IntSize(vLuts[0]), Vec_IntSize(vLuts[1]), Vec_IntSize(vLuts[2]) ); + printf( "Spots : %5d %5d %5d\n", Vec_IntSize(vRegs[0]), Vec_IntSize(vRegs[1]), 0 ); + } + + pNew = Gia_ManStart( Gia_ManObjNum(p) + Vec_IntSize(vRegs[0]) + Vec_IntSize(vRegs[1]) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + + Vec_IntWriteEntry( vCopy, 0, 0 ); + Gia_ManForEachPi( p, pObj, i ) + Vec_IntWriteEntry( vCopy, Gia_ObjId(p, pObj), Gia_ManAppendCi(pNew) ); + Vec_IntForEachEntry( vRos[2], Id, i ) + Vec_IntWriteEntry( vCopy, Id, Gia_ManAppendCi(pNew) ); + Vec_IntForEachEntry( vRegs[1], Id, i ) + Vec_IntWriteEntry( vCopy, Id, Abc_LitNotCond(Gia_ManAppendCi(pNew), Vec_IntEntry(vInits[1], i)) ); + + vTemp = Vec_IntAlloc(100); + Vec_IntForEachEntry( vRegs[0], Id, i ) + Vec_IntPush( vTemp, Vec_IntEntry(vCopy, Id) ); + Vec_IntForEachEntry( vRegs[0], Id, i ) + Vec_IntWriteEntry( vCopy, Id, Abc_LitNotCond(Gia_ManAppendCi(pNew), Vec_IntEntry(vInits[0], i)) ); + Vec_IntForEachEntry( vLuts[0], Id, i ) + Gia_ManSifDupNode( pNew, p, Id, vCopy ); + Vec_IntForEachEntry( vRegs[0], Id, i ) + Vec_IntWriteEntry( vCopy, Id, Vec_IntEntry(vTemp, i) ); + Vec_IntFree( vTemp ); + + Gia_ManForEachRoToRiVec( vRos[0], p, pObj, i ) + Vec_IntWriteEntry( vCopy, Vec_IntEntry(vRos[0], i), Abc_LitNotCond(Vec_IntEntry(vCopy, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj)) ); + Vec_IntForEachEntry( vLuts[2], Id, i ) + Gia_ManSifDupNode( pNew, p, Id, vCopy ); + + Gia_ManForEachRoToRiVec( vRos[1], p, pObj, i ) + Vec_IntWriteEntry( vCopy2, Vec_IntEntry(vRos[1], i), Abc_LitNotCond(Vec_IntEntry(vCopy, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj)) ); + Vec_IntForEachEntry( vLuts[1], Id, i ) + Gia_ManSifDupNode( pNew, p, Id, vCopy2 ); + + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(Vec_IntEntry(vCopy, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj)) ); + Gia_ManForEachRoToRiVec( vRos[2], p, pObj, i ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(Vec_IntEntry(vCopy, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj)) ); + Vec_IntForEachEntry( vRegs[1], Id, i ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(Vec_IntEntry(vCopy2, Id), Vec_IntEntry(vInits[1], i)) ); + Vec_IntForEachEntry( vRegs[0], Id, i ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(Vec_IntEntry(vCopy, Id), Vec_IntEntry(vInits[0], i)) ); + + Gia_ManSetRegNum( pNew, Vec_IntSize(vRos[2]) + Vec_IntSize(vRegs[0]) + Vec_IntSize(vRegs[1]) ); + + for ( i = 0; i < 3; i++ ) + { + Vec_IntFreeP( &vLuts[i] ); + Vec_IntFreeP( &vRos[i] ); + if ( i == 2 ) break; + Vec_IntFreeP( &vRegs[i] ); + Vec_IntFreeP( &vInits[i] ); + } + Vec_IntFree( vCopy ); + Vec_IntFree( vCopy2 ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSifArea_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vCuts, int nSize ) +{ + int i, * pCut, Area = 1; + if ( Gia_ObjUpdateTravIdCurrent(p, pObj) ) + return 0; + if ( !Gia_ObjIsAnd(pObj) ) + return 0; + pCut = Vec_IntEntryP( vCuts, Gia_ObjId(p, pObj)*nSize ); + for ( i = 1; i <= pCut[0]; i++ ) + Area += Gia_ManSifArea_rec( p, Gia_ManObj(p, pCut[i] >> 8), vCuts, nSize ); + return Area; +} +int Gia_ManSifArea( Gia_Man_t * p, Vec_Int_t * vCuts, int nSize ) +{ + Gia_Obj_t * pObj; int i, nArea = 0; + Gia_ManIncrementTravId( p ); + Gia_ManForEachCo( p, pObj, i ) + nArea += Gia_ManSifArea_rec( p, Gia_ObjFanin0(pObj), vCuts, nSize ); + return nArea; +} +int Gia_ManSifDelay_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nSize ) +{ + int i, * pCut, Delay, nFails = 0; + if ( Gia_ObjUpdateTravIdCurrent(p, pObj) ) + return 0; + if ( !Gia_ObjIsAnd(pObj) ) + return 0; + pCut = Vec_IntEntryP( vCuts, Gia_ObjId(p, pObj)*nSize ); + Delay = -ABC_INFINITY-10000; + for ( i = 1; i <= pCut[0]; i++ ) + { + nFails += Gia_ManSifDelay_rec( p, Gia_ManObj(p, pCut[i] >> 8), vCuts, vTimes, nSize ); + Delay = Abc_MaxInt( Delay, Vec_IntEntry(vTimes, pCut[i] >> 8) ); + } + Delay += 1; + return nFails + (int)(Delay > Vec_IntEntry(vTimes, Gia_ObjId(p, pObj))); +} +int Gia_ManSifDelay( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nSize ) +{ + Gia_Obj_t * pObj; int i, nFails = 0; + Gia_ManIncrementTravId( p ); + Gia_ManForEachCo( p, pObj, i ) + nFails += Gia_ManSifDelay_rec( p, Gia_ObjFanin0(pObj), vCuts, vTimes, nSize ); + return nFails; +} +static inline int Gia_ManSifTimeToCount( int Value, int Period ) +{ + return (Period*0xFFFF + Value)/Period + ((Period*0xFFFF + Value)%Period != 0) - 0x10000; +} +Vec_Int_t * Gia_ManSifTimesToCounts( Gia_Man_t * p, Vec_Int_t * vTimes, int Period ) +{ + int i, Times; + Vec_Int_t * vCounts = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_IntFillExtra( vTimes, Gia_ManObjNum(p), 0 ); + Vec_IntForEachEntry( vTimes, Times, i ) + if ( Gia_ObjIsLut(p, i) ) + Vec_IntWriteEntry( vCounts, i, Gia_ManSifTimeToCount(Times, Period) ); + return vCounts; +} +Gia_Man_t * Gia_ManSifTransform( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period, int fVerbose ) +{ + Gia_Man_t * pNew = NULL; Vec_Int_t * vCounts = NULL; + if ( fVerbose ) + printf( "Current area = %d. Period = %d. ", Gia_ManSifArea(p, vCuts, nLutSize+1), Period ); + if ( fVerbose ) + printf( "Delay checking failed for %d cuts.\n", Gia_ManSifDelay( p, vCuts, vTimes, nLutSize+1 ) ); + vCounts = Gia_ManSifTimesToCounts( p, vTimes, Period ); + pNew = Gia_ManSifDerive( p, vCounts, fVerbose ); + Vec_IntFreeP( &vCounts ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSifCutMerge( int * pCut, int * pCut1, int * pCut2, int nSize ) +{ + int * pBeg = pCut+1; + int * pBeg1 = pCut1+1; + int * pBeg2 = pCut2+1; + int * pEnd1 = pBeg1 + pCut1[0]; + int * pEnd2 = pBeg2 + pCut2[0]; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( pBeg == pCut+nSize ) + { + pCut[0] = -1; + return; + } + if ( *pBeg1 == *pBeg2 ) + *pBeg++ = *pBeg1++, pBeg2++; + else if ( *pBeg1 < *pBeg2 ) + *pBeg++ = *pBeg1++; + else + *pBeg++ = *pBeg2++; + } + while ( pBeg1 < pEnd1 ) + { + if ( pBeg == pCut+nSize ) + { + pCut[0] = -1; + return; + } + *pBeg++ = *pBeg1++; + } + while ( pBeg2 < pEnd2 ) + { + if ( pBeg == pCut+nSize ) + { + pCut[0] = -1; + return; + } + *pBeg++ = *pBeg2++; + } + pCut[0] = pBeg-(pCut+1); + assert( pCut[0] < nSize ); +} +static inline int Gia_ManSifCutChoice( Gia_Man_t * p, int Level, int iObj, int iSibl, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nSize ) +{ + int * pCut = Vec_IntEntryP( vCuts, iObj*nSize ); + int * pCut2 = Vec_IntEntryP( vCuts, iSibl*nSize ); + int Level2 = Vec_IntEntry( vTimes, iSibl ); int i; + assert( iObj > iSibl ); + if ( Level < Level2 || (Level == Level2 && pCut[0] <= pCut2[0]) ) + return Level; + for ( i = 0; i <= pCut2[0]; i++ ) + pCut[i] = pCut2[i]; + return Level2; +} +static inline int Gia_ManSifCutOne( Gia_Man_t * p, int iObj, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nSize ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + int iFan0 = Gia_ObjFaninId0(pObj, iObj); + int iFan1 = Gia_ObjFaninId1(pObj, iObj); + int Cut0[2] = { 1, iFan0 << 8 }; + int Cut1[2] = { 1, iFan1 << 8 }; + int * pCut = Vec_IntEntryP( vCuts, iObj*nSize ); + int * pCut0 = Vec_IntEntryP( vCuts, iFan0*nSize ); + int * pCut1 = Vec_IntEntryP( vCuts, iFan1*nSize ); + int Level_ = Vec_IntEntry( vTimes, iObj ); + int Level0 = Vec_IntEntry( vTimes, iFan0 ); + int Level1 = Vec_IntEntry( vTimes, iFan1 ); + int Level = -ABC_INFINITY, i; + assert( pCut0[0] > 0 && pCut1[0] > 0 ); + if ( Level0 == Level1 ) + Gia_ManSifCutMerge( pCut, pCut0, pCut1, nSize ); + else if ( Level0 > Level1 ) + Gia_ManSifCutMerge( pCut, pCut0, Cut1, nSize ); + else //if ( Level0 < Level1 ) + Gia_ManSifCutMerge( pCut, pCut1, Cut0, nSize ); + if ( pCut[0] == -1 ) + { + pCut[0] = 2; + pCut[1] = iFan0 << 8; + pCut[2] = iFan1 << 8; + } + for ( i = 1; i <= pCut[0]; i++ ) + Level = Abc_MaxInt( Level, Vec_IntEntry(vTimes, pCut[i] >> 8) ); + Level++; + if ( Gia_ObjSibl(p, iObj) ) + Level = Gia_ManSifCutChoice( p, Level, iObj, Gia_ObjSibl(p, iObj), vCuts, vTimes, nSize ); + assert( pCut[0] > 0 && pCut[0] < nSize ); + Vec_IntUpdateEntry( vTimes, iObj, Level ); + return Level > Level_; +} +int Gia_ManSifCheckIter( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period ) +{ + int i, fChange = 0, nSize = nLutSize+1; + Gia_Obj_t * pObj, * pObjRi, * pObjRo; + Gia_ManForEachAnd( p, pObj, i ) + fChange |= Gia_ManSifCutOne( p, i, vCuts, vTimes, nSize ); + Gia_ManForEachCo( p, pObj, i ) + Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), Vec_IntEntry(vTimes, Gia_ObjFaninId0p(p, pObj)) ); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) + { + int TimeNew = Vec_IntEntry(vTimes, Gia_ObjId(p, pObjRi)) - Period; + TimeNew = Abc_MaxInt( TimeNew, Vec_IntEntry(vTimes, Gia_ObjId(p, pObjRo)) ); + Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObjRo), TimeNew ); + } + return fChange; +} +int Gia_ManSifCheckPeriod( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period, int * pIters ) +{ + Gia_Obj_t * pObj; int i, Id, nSize = nLutSize+1; + assert( Gia_ManRegNum(p) > 0 ); + Gia_ManForEachCiId( p, Id, i ) + Vec_IntWriteEntry( vCuts, Id*nSize, 1 ); + Gia_ManForEachCiId( p, Id, i ) + Vec_IntWriteEntry( vCuts, Id*nSize+1, Id << 8 ); + Vec_IntFill( vTimes, Gia_ManObjNum(p), -Period ); + Vec_IntWriteEntry( vTimes, 0, 0 ); + Gia_ManForEachPi( p, pObj, i ) + Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), 0 ); + for ( *pIters = 0; *pIters < 100; (*pIters)++ ) + { + if ( !Gia_ManSifCheckIter(p, vCuts, vTimes, nLutSize, Period) ) + return 1; + Gia_ManForEachPo( p, pObj, i ) + if ( Vec_IntEntry(vTimes, Gia_ObjId(p, pObj)) > Period ) + return 0; + Gia_ManForEachObj( p, pObj, i ) + if ( Vec_IntEntry(vTimes, Gia_ObjId(p, pObj)) > 2*Period ) + return 0; + } + return 0; +} +int Gia_ManSifMapComb( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize ) +{ + Gia_Obj_t * pObj; int i, Id, Res = 0, nSize = nLutSize+1; + Vec_IntFill( vTimes, Gia_ManObjNum(p), 0 ); + Gia_ManForEachCiId( p, Id, i ) + Vec_IntWriteEntry( vCuts, Id*nSize, 1 ); + Gia_ManForEachCiId( p, Id, i ) + Vec_IntWriteEntry( vCuts, Id*nSize+1, Id << 8 ); + Gia_ManForEachAnd( p, pObj, i ) + Gia_ManSifCutOne( p, i, vCuts, vTimes, nSize ); + Gia_ManForEachCo( p, pObj, i ) + Res = Abc_MaxInt( Res, Vec_IntEntry(vTimes, Gia_ObjFaninId0p(p, pObj)) ); + return Res; +} +void Gia_ManSifPrintTimes( Gia_Man_t * p, Vec_Int_t * vTimes, int Period ) +{ + int i, Value, Pos[256] = {0}, Neg[256] = {0}; + Gia_ManForEachLut( p, i ) + { + Value = Gia_ManSifTimeToCount( Vec_IntEntry(vTimes, i), Period ); + Value = Abc_MinInt( Value, 255 ); + Value = Abc_MaxInt( Value, -255 ); + if ( Value >= 0 ) + Pos[Value]++; + else + Neg[-Value]++; + } + printf( "Statistics: " ); + for ( i = 255; i > 0; i-- ) + if ( Neg[i] ) + printf( " -%d=%d", i, Neg[i] ); + for ( i = 0; i < 256; i++ ) + if ( Pos[i] ) + printf( " %d=%d", i, Pos[i] ); + printf( "\n" ); +} +int Gia_ManSifDeriveMapping_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vCuts, int nSize ) +{ + int i, * pCut, Area = 1; + if ( !Gia_ObjIsAnd(pObj) ) + return 0; + if ( Gia_ObjUpdateTravIdCurrent(p, pObj) ) + return 0; + pCut = Vec_IntEntryP( vCuts, Gia_ObjId(p, pObj)*nSize ); + for ( i = 1; i <= pCut[0]; i++ ) + Area += Gia_ManSifDeriveMapping_rec( p, Gia_ManObj(p, pCut[i] >> 8), vCuts, nSize ); + Vec_IntWriteEntry( p->vMapping, Gia_ObjId(p, pObj), Vec_IntSize(p->vMapping) ); + Vec_IntPush( p->vMapping, pCut[0] ); + for ( i = 1; i <= pCut[0]; i++ ) + { + Gia_Obj_t * pObj = Gia_ManObj(p, pCut[i] >> 8); + assert( !Gia_ObjIsAnd(pObj) || Gia_ObjIsLut(p, pCut[i] >> 8) ); + Vec_IntPush( p->vMapping, pCut[i] >> 8 ); + } + Vec_IntPush( p->vMapping, -1 ); + return Area; +} +int Gia_ManSifDeriveMapping( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period, int fVerbose ) +{ + Gia_Obj_t * pObj; int i, nArea = 0; + if ( p->vMapping != NULL ) + { + printf( "Removing available combinational mapping.\n" ); + Vec_IntFreeP( &p->vMapping ); + } + assert( p->vMapping == NULL ); + p->vMapping = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachCo( p, pObj, i ) + nArea += Gia_ManSifDeriveMapping_rec( p, Gia_ObjFanin0(pObj), vCuts, nLutSize+1 ); + return nArea; +} +Gia_Man_t * Gia_ManSifPerform( Gia_Man_t * p, int nLutSize, int fEvalOnly, int fVerbose ) +{ + Gia_Man_t * pNew = NULL; + int nIters, Status, nSize = nLutSize+1; // (2+1+nSize)*4=40 bytes/node + abctime clk = Abc_Clock(); + Vec_Int_t * vCuts = Vec_IntStart( Gia_ManObjNum(p) * nSize ); + Vec_Int_t * vTimes = Vec_IntAlloc( Gia_ManObjNum(p) ); + int Lower = 0; + int Upper = Gia_ManSifMapComb( p, vCuts, vTimes, nLutSize ); + int CombD = Upper; + if ( fVerbose && Gia_ManRegNum(p) ) + printf( "Clock period %2d is %s\n", Lower, 0 ? "Yes" : "No " ); + if ( fVerbose && Gia_ManRegNum(p) ) + printf( "Clock period %2d is %s\n", Upper, 1 ? "Yes" : "No " ); + while ( Gia_ManRegNum(p) > 0 && Upper - Lower > 1 ) + { + int Middle = (Upper + Lower) / 2; + int Status = Gia_ManSifCheckPeriod( p, vCuts, vTimes, nLutSize, Middle, &nIters ); + if ( Status ) + Upper = Middle; + else + Lower = Middle; + if ( fVerbose ) + printf( "Clock period %2d is %s after %d iterations\n", Middle, Status ? "Yes" : "No ", nIters ); + } + if ( fVerbose ) + printf( "Best period = <<%d>> (%.2f %%) ", Upper, (float)(100.0*(CombD-Upper)/CombD) ); + if ( fVerbose ) + printf( "LUT size = %d ", nLutSize ); + if ( fVerbose ) + printf( "Memory usage = %.2f MB ", 4.0*(2+1+nSize)*Gia_ManObjNum(p)/(1 << 20) ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( Upper == CombD ) + { + Vec_IntFree( vCuts ); + Vec_IntFree( vTimes ); + printf( "Combinational delay (%d) cannot be improved.\n", CombD ); + return Gia_ManDup( p ); + } + Status = Gia_ManSifCheckPeriod( p, vCuts, vTimes, nLutSize, Upper, &nIters ); + assert( Status ); + Status = Gia_ManSifDeriveMapping( p, vCuts, vTimes, nLutSize, Upper, fVerbose ); + if ( fEvalOnly ) + { + printf( "Optimized level %2d (%6.2f %% less than comb level %2d). LUT size = %d. Area estimate = %d.\n", + Upper, (float)(100.0*(CombD-Upper)/CombD), CombD, nLutSize, Gia_ManSifArea(p, vCuts, nLutSize+1) ); + printf( "The command is invoked in the evaluation mode. Retiming is not performed.\n" ); + } + else + pNew = Gia_ManSifTransform( p, vCuts, vTimes, nLutSize, Upper, fVerbose ); + Vec_IntFree( vCuts ); + Vec_IntFree( vTimes ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaSim.c b/abc/src/aig/gia/giaSim.c index 88e94156ec7..ecad182f76e 100644 --- a/abc/src/aig/gia/giaSim.c +++ b/abc/src/aig/gia/giaSim.c @@ -1222,6 +1222,173 @@ int Gia_ManIncrSimCheckEqual( Gia_Man_t * p, int iLit0, int iLit1 ) } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimOneBit( Gia_Man_t * p, Vec_Int_t * vValues ) +{ + Gia_Obj_t * pObj; int k; + assert( Vec_IntSize(vValues) == Gia_ManCiNum(p) ); + + Gia_ManConst0(p)->fMark0 = 0; + Gia_ManForEachCi( p, pObj, k ) + pObj->fMark0 = Vec_IntEntry(vValues, k); + Gia_ManForEachAnd( p, pObj, k ) + pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); + Gia_ManForEachCo( p, pObj, k ) + pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); + + Gia_ManForEachCi( p, pObj, k ) + printf( "%d", k % 10 ); + printf( "\n" ); + Gia_ManForEachCi( p, pObj, k ) + printf( "%d", Vec_IntEntry(vValues, k) ); + printf( "\n" ); + + Gia_ManForEachCo( p, pObj, k ) + printf( "%d", k % 10 ); + printf( "\n" ); + Gia_ManForEachCo( p, pObj, k ) + printf( "%d", pObj->fMark0 ); + printf( "\n" ); + printf( "\n" ); +} +void Gia_ManSimOneBitTest2( Gia_Man_t * p ) +{ + Vec_Int_t * vValues = Vec_IntStart( Gia_ManCiNum(p) ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Vec_IntWriteEntry( vValues, 1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2+2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Vec_IntWriteEntry( vValues, 1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntFill( vValues, Vec_IntSize(vValues)/2, 1 ); + Vec_IntFillExtra( vValues, Gia_ManCiNum(p), 0 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Gia_ManCiNum(p), 0 ); + + Vec_IntFill( vValues, Gia_ManCiNum(p), 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Gia_ManCiNum(p), 0 ); + + Vec_IntFill( vValues, Gia_ManCiNum(p), 1 ); + Vec_IntWriteEntry( vValues, 127, 1 ); + Vec_IntWriteEntry( vValues, 255, 0 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Gia_ManCiNum(p), 0 ); + + Vec_IntFill( vValues, Gia_ManCiNum(p), 1 ); + Vec_IntWriteEntry( vValues, 127, 0 ); + Vec_IntWriteEntry( vValues, 255, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Gia_ManCiNum(p), 0 ); + + Vec_IntFill( vValues, Gia_ManCiNum(p), 1 ); + Vec_IntWriteEntry( vValues, 127, 0 ); + Vec_IntWriteEntry( vValues, 255, 0 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Gia_ManCiNum(p), 0 ); + + Vec_IntFree( vValues ); +} +void Gia_ManSimOneBitTest3( Gia_Man_t * p ) +{ + Vec_Int_t * vValues = Vec_IntStart( Gia_ManCiNum(p) ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Vec_IntWriteEntry( vValues, 1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2+2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -1, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-3, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -3, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-3, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -3, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntFill( vValues, Vec_IntSize(vValues), 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntFree( vValues ); +} + + +void Gia_ManSimOneBitTest( Gia_Man_t * p ) +{ + Vec_Int_t * vValues = Vec_IntStart( Gia_ManCiNum(p) ); + int i, k; + for ( i = 0; i < 10; i++ ) + { + for ( k = 0; k < Vec_IntSize(vValues); k++ ) + Vec_IntWriteEntry( vValues, k, Vec_IntEntry(vValues, k) ^ (rand()&1) ); + + printf( "Values = %d ", Vec_IntSum(vValues) ); + Gia_ManSimOneBit( p, vValues ); + } +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/abc/src/aig/gia/giaSimBase.c b/abc/src/aig/gia/giaSimBase.c new file mode 100644 index 00000000000..97335d37833 --- /dev/null +++ b/abc/src/aig/gia/giaSimBase.c @@ -0,0 +1,3750 @@ +/**CFile**************************************************************** + + FileName [giaSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Fast sequential simulator.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" +//#include +#include "aig/miniaig/miniaig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +typedef struct Gia_SimRsbMan_t_ Gia_SimRsbMan_t; +struct Gia_SimRsbMan_t_ +{ + Gia_Man_t * pGia; + Vec_Int_t * vTfo; + Vec_Int_t * vCands; + Vec_Int_t * vFanins; + Vec_Int_t * vFanins2; + Vec_Wrd_t * vSimsObj; + Vec_Wrd_t * vSimsObj2; + int nWords; + word * pFunc[3]; +}; + + +typedef struct Gia_SimAbsMan_t_ Gia_SimAbsMan_t; +struct Gia_SimAbsMan_t_ +{ + // problem formulation + Gia_Man_t * pGia; // AIG manager + word * pSet[2]; // offset/onset truth tables + int nCands; // candidate count + int nWords; // word count + Vec_Wrd_t * vSims; // candidate simulation info + Vec_Int_t * vResub; // the result + int fVerbose; // verbose + // intermediate result + Vec_Int_t * vValues; // function values in each pattern + Vec_Int_t * vPatPairs; // used minterms + int nWordsTable; // words of table data + word * pTableTemp; // temporary table pattern + Vec_Wrd_t * vCoverTable; // columns = minterms; rows = classes + Vec_Int_t * vTtMints; // truth table minterms +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimPatAssignInputs( Gia_Man_t * p, int nWords, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsIn ) +{ + int i, Id; + assert( Vec_WrdSize(vSims) == nWords * Gia_ManObjNum(p) ); + assert( Vec_WrdSize(vSimsIn) == nWords * Gia_ManCiNum(p) ); + Gia_ManForEachCiId( p, Id, i ) + memcpy( Vec_WrdEntryP(vSims, Id*nWords), Vec_WrdEntryP(vSimsIn, i*nWords), sizeof(word)*nWords ); +} +static inline void Gia_ManSimPatSimAnd( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims ) +{ + word pComps[2] = { 0, ~(word)0 }; + word Diff0 = pComps[Gia_ObjFaninC0(pObj)]; + word Diff1 = pComps[Gia_ObjFaninC1(pObj)]; + word * pSims = Vec_WrdArray(vSims); + word * pSims0 = pSims + nWords*Gia_ObjFaninId0(pObj, i); + word * pSims1 = pSims + nWords*Gia_ObjFaninId1(pObj, i); + word * pSims2 = pSims + nWords*i; int w; + if ( Gia_ObjIsXor(pObj) ) + for ( w = 0; w < nWords; w++ ) + pSims2[w] = (pSims0[w] ^ Diff0) ^ (pSims1[w] ^ Diff1); + else + for ( w = 0; w < nWords; w++ ) + pSims2[w] = (pSims0[w] ^ Diff0) & (pSims1[w] ^ Diff1); +} +static inline void Gia_ManSimPatSimPo( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims ) +{ + word pComps[2] = { 0, ~(word)0 }; + word Diff0 = pComps[Gia_ObjFaninC0(pObj)]; + word * pSims = Vec_WrdArray(vSims); + word * pSims0 = pSims + nWords*Gia_ObjFaninId0(pObj, i); + word * pSims2 = pSims + nWords*i; int w; + for ( w = 0; w < nWords; w++ ) + pSims2[w] = (pSims0[w] ^ Diff0); +} +static inline void Gia_ManSimPatSimNot( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims ) +{ + word * pSims = Vec_WrdArray(vSims) + nWords*i; int w; + for ( w = 0; w < nWords; w++ ) + pSims[w] = ~pSims[w]; +} +Vec_Wrd_t * Gia_ManSimPatSim( Gia_Man_t * pGia ) +{ + Gia_Obj_t * pObj; + int i, nWords = Vec_WrdSize(pGia->vSimsPi) / Gia_ManCiNum(pGia); + Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(pGia) * nWords ); + assert( Vec_WrdSize(pGia->vSimsPi) % Gia_ManCiNum(pGia) == 0 ); + Gia_ManSimPatAssignInputs( pGia, nWords, vSims, pGia->vSimsPi ); + Gia_ManForEachAnd( pGia, pObj, i ) + Gia_ManSimPatSimAnd( pGia, i, pObj, nWords, vSims ); + Gia_ManForEachCo( pGia, pObj, i ) + Gia_ManSimPatSimPo( pGia, Gia_ObjId(pGia, pObj), pObj, nWords, vSims ); + return vSims; +} +Vec_Wrd_t * Gia_ManSimPatSimOut( Gia_Man_t * pGia, Vec_Wrd_t * vSimsPi, int fOuts ) +{ + Gia_Obj_t * pObj; + int i, nWords = Vec_WrdSize(vSimsPi) / Gia_ManCiNum(pGia); + Vec_Wrd_t * vSimsCo = fOuts ? Vec_WrdStart( Gia_ManCoNum(pGia) * nWords ) : NULL; + Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(pGia) * nWords ); + assert( Vec_WrdSize(vSimsPi) % Gia_ManCiNum(pGia) == 0 ); + Gia_ManSimPatAssignInputs( pGia, nWords, vSims, vSimsPi ); + Gia_ManForEachAnd( pGia, pObj, i ) + Gia_ManSimPatSimAnd( pGia, i, pObj, nWords, vSims ); + Gia_ManForEachCo( pGia, pObj, i ) + Gia_ManSimPatSimPo( pGia, Gia_ObjId(pGia, pObj), pObj, nWords, vSims ); + if ( !fOuts ) + return vSims; + Gia_ManForEachCo( pGia, pObj, i ) + memcpy( Vec_WrdEntryP(vSimsCo, i*nWords), Vec_WrdEntryP(vSims, Gia_ObjId(pGia, pObj)*nWords), sizeof(word)*nWords ); + Vec_WrdFree( vSims ); + return vSimsCo; +} +static inline void Gia_ManSimPatSimAnd3( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsC ) +{ + word pComps[2] = { ~(word)0, 0 }; + word Diff0 = pComps[Gia_ObjFaninC0(pObj)]; + word Diff1 = pComps[Gia_ObjFaninC1(pObj)]; + word * pSims0 = Vec_WrdArray(vSims) + nWords*Gia_ObjFaninId0(pObj, i); + word * pSims1 = Vec_WrdArray(vSims) + nWords*Gia_ObjFaninId1(pObj, i); + word * pSims2 = Vec_WrdArray(vSims) + nWords*i; + word * pSimsC0 = Vec_WrdArray(vSimsC) + nWords*Gia_ObjFaninId0(pObj, i); + word * pSimsC1 = Vec_WrdArray(vSimsC) + nWords*Gia_ObjFaninId1(pObj, i); + word * pSimsC2 = Vec_WrdArray(vSimsC) + nWords*i; int w; + if ( Gia_ObjIsXor(pObj) ) + for ( w = 0; w < nWords; w++ ) + { + pSimsC0[w] |= pSimsC2[w]; + pSimsC1[w] |= pSimsC2[w]; + } + else + for ( w = 0; w < nWords; w++ ) + { + pSimsC0[w] |= (pSims2[w] | (pSims0[w] ^ Diff0)) & pSimsC2[w]; + pSimsC1[w] |= (pSims2[w] | (pSims1[w] ^ Diff1)) & pSimsC2[w]; + } +} +Vec_Wrd_t * Gia_ManSimPatSimIn( Gia_Man_t * pGia, Vec_Wrd_t * vSims, int fIns, Vec_Int_t * vAnds ) +{ + Gia_Obj_t * pObj; + int i, Id, nWords = Vec_WrdSize(vSims) / Gia_ManObjNum(pGia); + Vec_Wrd_t * vSimsCi = fIns ? Vec_WrdStart( Gia_ManCiNum(pGia) * nWords ) : NULL; + Vec_Wrd_t * vSimsC = Vec_WrdStart( Vec_WrdSize(vSims) ); + assert( Vec_WrdSize(vSims) % Gia_ManObjNum(pGia) == 0 ); + if ( vAnds ) + Vec_IntForEachEntry( vAnds, Id, i ) + memset( Vec_WrdEntryP(vSimsC, Id*nWords), 0xFF, sizeof(word)*nWords ); + else + Gia_ManForEachCoDriverId( pGia, Id, i ) + memset( Vec_WrdEntryP(vSimsC, Id*nWords), 0xFF, sizeof(word)*nWords ); + Gia_ManForEachAndReverse( pGia, pObj, i ) + Gia_ManSimPatSimAnd3( pGia, i, pObj, nWords, vSims, vSimsC ); + if ( !fIns ) + return vSimsC; + Gia_ManForEachCi( pGia, pObj, i ) + memcpy( Vec_WrdEntryP(vSimsCi, i*nWords), Vec_WrdEntryP(vSimsC, Gia_ObjId(pGia, pObj)*nWords), sizeof(word)*nWords ); + Vec_WrdFree( vSimsC ); + return vSimsCi; +} +void Gia_ManSimPatSimInTest( Gia_Man_t * pGia ) +{ + int nWords = 10; + Vec_Wrd_t * vSimsCi = Vec_WrdStartRandom( Gia_ManCiNum(pGia) * nWords ); + Vec_Wrd_t * vSims = Gia_ManSimPatSimOut( pGia, vSimsCi, 0 ); + Vec_Wrd_t * vSims2 = Gia_ManSimPatSimIn( pGia, vSims, 0, NULL ); + int nOnes = Abc_TtCountOnesVec( Vec_WrdArray(vSims2), Vec_WrdSize(vSims2) ); + int nTotal = 64*nWords*Gia_ManCandNum(pGia); + printf( "Ratio = %6.2f %%\n", 100.0*nOnes/nTotal ); + Vec_WrdFree( vSims ); + Vec_WrdFree( vSims2 ); + Vec_WrdFree( vSimsCi ); +} +static inline void Gia_ManSimPatSimAnd4( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsC ) +{ + word pComps[2] = { ~(word)0, 0 }; + word Diff0 = pComps[Gia_ObjFaninC0(pObj)]; + word Diff1 = pComps[Gia_ObjFaninC1(pObj)]; + word * pSims0 = Vec_WrdArray(vSims) + nWords*Gia_ObjFaninId0(pObj, i); + word * pSims1 = Vec_WrdArray(vSims) + nWords*Gia_ObjFaninId1(pObj, i); + word * pSimsC0 = Vec_WrdArray(vSimsC) + nWords*Gia_ObjFaninId0(pObj, i); + word * pSimsC1 = Vec_WrdArray(vSimsC) + nWords*Gia_ObjFaninId1(pObj, i); + word * pSimsC2 = Vec_WrdArray(vSimsC) + nWords*i; int w; + if ( Gia_ObjIsXor(pObj) ) + for ( w = 0; w < nWords; w++ ) + pSimsC2[w] = pSimsC0[w] & pSimsC1[w]; + else + for ( w = 0; w < nWords; w++ ) + pSimsC2[w] = (pSimsC0[w] & pSimsC1[w]) | ((pSims0[w] ^ Diff0) & pSimsC0[w]) | ((pSims1[w] ^ Diff1) & pSimsC1[w]); +} +Vec_Wrd_t * Gia_ManSimPatSimC( Gia_Man_t * pGia, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsCiC ) +{ + Gia_Obj_t * pObj; + int i, Id, nWords = Vec_WrdSize(vSims) / Gia_ManObjNum(pGia); + Vec_Wrd_t * vSimsC = Vec_WrdStart( Vec_WrdSize(vSims) ); + assert( Vec_WrdSize(vSims) % Gia_ManObjNum(pGia) == 0 ); + memset( Vec_WrdEntryP(vSimsC, 0), 0xFF, sizeof(word)*nWords ); + Gia_ManForEachCiId( pGia, Id, i ) + memmove( Vec_WrdEntryP(vSimsC, Id*nWords), Vec_WrdEntryP(vSimsCiC, i*nWords), sizeof(word)*nWords ); + Gia_ManForEachAnd( pGia, pObj, i ) + Gia_ManSimPatSimAnd4( pGia, i, pObj, nWords, vSims, vSimsC ); + return vSimsC; +} +void Gia_ManSimPatSimCTest( Gia_Man_t * pGia ) +{ + int nWords = 10; + Vec_Wrd_t * vSimsCi = Vec_WrdStartRandom( Gia_ManCiNum(pGia) * nWords ); + Vec_Wrd_t * vSims = Gia_ManSimPatSimOut( pGia, vSimsCi, 0 ); + Vec_Wrd_t * vSims2 = Gia_ManSimPatSimIn( pGia, vSims, 0, NULL ); + Vec_Wrd_t * vSimsCi2 = Gia_ManSimPatSimIn( pGia, vSims, 1, NULL ); + Vec_Wrd_t * vSims3 = Gia_ManSimPatSimC( pGia, vSims, vSimsCi2 ); + int nOnes2 = Abc_TtCountOnesVec( Vec_WrdArray(vSims2), Vec_WrdSize(vSims2) ); + int nOnes3 = Abc_TtCountOnesVec( Vec_WrdArray(vSims3), Vec_WrdSize(vSims3) ); + int nTotal = 64*nWords*Gia_ManCandNum(pGia); + printf( "Ratio = %6.2f %% Ratio = %6.2f %%\n", 100.0*nOnes2/nTotal, 100.0*nOnes3/nTotal ); + Vec_WrdFree( vSims ); + Vec_WrdFree( vSims2 ); + Vec_WrdFree( vSims3 ); + Vec_WrdFree( vSimsCi ); + Vec_WrdFree( vSimsCi2 ); +} +void Gia_ManSimPatResim( Gia_Man_t * pGia, Vec_Int_t * vObjs, int nWords, Vec_Wrd_t * vSims ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManForEachObjVec( vObjs, pGia, pObj, i ) + if ( i == 0 ) + Gia_ManSimPatSimNot( pGia, Gia_ObjId(pGia, pObj), pObj, nWords, vSims ); + else if ( Gia_ObjIsAnd(pObj) ) + Gia_ManSimPatSimAnd( pGia, Gia_ObjId(pGia, pObj), pObj, nWords, vSims ); + else if ( !Gia_ObjIsCo(pObj) ) assert(0); +} +void Gia_ManSimPatWrite( char * pFileName, Vec_Wrd_t * vSimsIn, int nWords ) +{ + Vec_WrdDumpHex( pFileName, vSimsIn, nWords, 0 ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word * Gia_ManDeriveFuncs( Gia_Man_t * p ) +{ + int nVars2 = (Gia_ManCiNum(p) + 6)/2; + int nVars3 = Gia_ManCiNum(p) - nVars2; + int nWords = Abc_Truth6WordNum( Gia_ManCiNum(p) ); + int nWords2 = Abc_Truth6WordNum( nVars2 ); + word * pRes = ABC_ALLOC( word, Gia_ManCoNum(p) * nWords ); + Vec_Wrd_t * vSims = Vec_WrdStart( nWords2 * Gia_ManObjNum(p) ); + Vec_Ptr_t * vTruths = Vec_PtrAllocTruthTables( nVars2 ); + Gia_Obj_t * pObj; int i, v, m; + Gia_ManForEachCi( p, pObj, i ) + assert( Gia_ObjId(p, pObj) == i+1 ); + for ( i = 0; i < nVars2; i++ ) + Abc_TtCopy( Vec_WrdEntryP(vSims, nWords2*(i+1)), (word *)Vec_PtrEntry(vTruths, i), nWords2, 0 ); + Vec_PtrFree( vTruths ); + for ( m = 0; m < (1 << nVars3); m++ ) + { + for ( v = 0; v < nVars3; v++ ) + Abc_TtConst( Vec_WrdEntryP(vSims, nWords2*(nVars2+v+1)), nWords2, (m >> v) & 1 ); + Gia_ManForEachAnd( p, pObj, i ) + Gia_ManSimPatSimAnd( p, i, pObj, nWords2, vSims ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManSimPatSimPo( p, Gia_ObjId(p, pObj), pObj, nWords2, vSims ); + Gia_ManForEachCo( p, pObj, i ) + Abc_TtCopy( pRes + i*nWords + m*nWords2, Vec_WrdEntryP(vSims, nWords2*Gia_ObjId(p, pObj)), nWords2, 0 ); + } + Vec_WrdFree( vSims ); + return pRes; +} +Gia_Man_t * Gia_ManPerformMuxDec( Gia_Man_t * p ) +{ + extern int Gia_ManFindMuxTree_rec( Gia_Man_t * pNew, int * pCtrl, int nCtrl, Vec_Int_t * vData, int Shift ); + extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); + int nWords = Abc_Truth6WordNum( Gia_ManCiNum(p) ); + int nCofs = 1 << (Gia_ManCiNum(p) - 6); + word * pRes = Gia_ManDeriveFuncs( p ); + Vec_Int_t * vMemory = Vec_IntAlloc( 1 << 16 ); + Vec_Int_t * vLeaves = Vec_IntAlloc( 6 ); + Vec_Int_t * vCtrls = Vec_IntAlloc( nCofs ); + Vec_Int_t * vDatas = Vec_IntAlloc( Gia_ManCoNum(p) ); + Gia_Man_t * pNew, * pTemp; int i, o; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + Vec_IntPush( i < 6 ? vLeaves : vCtrls, Gia_ManAppendCi(pNew) ); + Gia_ManHashAlloc( pNew ); + for ( o = 0; o < Gia_ManCoNum(p); o++ ) + { + Vec_IntClear( vDatas ); + for ( i = 0; i < nWords; i++ ) + Vec_IntPush( vDatas, Kit_TruthToGia(pNew, (unsigned *)(pRes+o*nWords+i), 6, vMemory, vLeaves, 1) ); + Gia_ManAppendCo( pNew, Gia_ManFindMuxTree_rec(pNew, Vec_IntArray(vCtrls), Vec_IntSize(vCtrls), vDatas, 0) ); + } + Gia_ManHashStop( pNew ); + ABC_FREE( pRes ); + Vec_IntFree( vMemory ); + Vec_IntFree( vLeaves ); + Vec_IntFree( vCtrls ); + Vec_IntFree( vDatas ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Gia_ManTransferTiming( pNew, p ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManComputeTfos_rec( Gia_Man_t * p, int iObj, int iRoot, Vec_Int_t * vNode ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdPreviousId(p, iObj) ) + return 1; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return 0; + pObj = Gia_ManObj( p, iObj ); + if ( !Gia_ObjIsAnd(pObj) ) + return 0; + if ( Gia_ManComputeTfos_rec( p, Gia_ObjFaninId0(pObj, iObj), iRoot, vNode ) | + Gia_ManComputeTfos_rec( p, Gia_ObjFaninId1(pObj, iObj), iRoot, vNode ) ) + { + Gia_ObjSetTravIdPreviousId(p, iObj); + Vec_IntPush( vNode, iObj ); + return 1; + } + Gia_ObjSetTravIdCurrentId(p, iObj); + return 0; +} +Vec_Wec_t * Gia_ManComputeTfos( Gia_Man_t * p ) +{ + Vec_Wec_t * vNodes = Vec_WecStart( Gia_ManCiNum(p) ); + Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); + int i, o, IdCi, IdCo; + Gia_ManForEachCiId( p, IdCi, i ) + { + Vec_Int_t * vNode = Vec_WecEntry( vNodes, i ); + Gia_ManIncrementTravId( p ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdPreviousId(p, IdCi); + Vec_IntPush( vNode, IdCi ); + Vec_IntClear( vTemp ); + Gia_ManForEachCoId( p, IdCo, o ) + if ( Gia_ManComputeTfos_rec( p, Gia_ObjFaninId0(Gia_ManObj(p, IdCo), IdCo), IdCi, vNode ) ) + Vec_IntPush( vTemp, Gia_ManObjNum(p) + (o >> 1) ); + Vec_IntUniqify( vTemp ); + Vec_IntAppend( vNode, vTemp ); + } + Vec_IntFree( vTemp ); + Vec_WecSort( vNodes, 1 ); + //Vec_WecPrint( vNodes, 0 ); + //Gia_AigerWrite( p, "dump.aig", 0, 0, 0 ); + return vNodes; +} +int Gia_ManFindDividerVar( Gia_Man_t * p, int fVerbose ) +{ + int iVar, Target = 1 << 28; + for ( iVar = 6; iVar < Gia_ManCiNum(p); iVar++ ) + if ( (1 << (iVar-3)) * Gia_ManObjNum(p) > Target ) + break; + if ( iVar == Gia_ManCiNum(p) ) + iVar = Gia_ManCiNum(p) - 1; + if ( fVerbose ) + printf( "Split var = %d. Rounds = %d. Bytes per node = %d. Total = %.2f MB.\n", iVar, 1 << (Gia_ManCiNum(p) - iVar), 1 << (iVar-3), 1.0*(1 << (iVar-3)) * Gia_ManObjNum(p)/(1<<20) ); + return iVar; +} +int Gia_ManComparePair( Gia_Man_t * p, Vec_Wrd_t * vSims, int iOut, int nWords2 ) +{ + Gia_Obj_t * pObj0 = Gia_ManCo( p, 2*iOut+0 ); + Gia_Obj_t * pObj1 = Gia_ManCo( p, 2*iOut+1 ); + word * pSim0 = Vec_WrdEntryP( vSims, nWords2*Gia_ObjId(p, pObj0) ); + word * pSim1 = Vec_WrdEntryP( vSims, nWords2*Gia_ObjId(p, pObj1) ); + Gia_ManSimPatSimPo( p, Gia_ObjId(p, pObj0), pObj0, nWords2, vSims ); + Gia_ManSimPatSimPo( p, Gia_ObjId(p, pObj1), pObj1, nWords2, vSims ); + return Abc_TtEqual( pSim0, pSim1, nWords2 ); +} +int Gia_ManCheckSimEquiv( Gia_Man_t * p, int fVerbose ) +{ + abctime clk = Abc_Clock(); int fWarning = 0; + //int nVars2 = (Gia_ManCiNum(p) + 6)/2; + int nVars2 = Gia_ManFindDividerVar( p, fVerbose ); + int nVars3 = Gia_ManCiNum(p) - nVars2; + int nWords2 = Abc_Truth6WordNum( nVars2 ); + Vec_Wrd_t * vSims = Vec_WrdStart( nWords2 * Gia_ManObjNum(p) ); + Vec_Wec_t * vNodes = Gia_ManComputeTfos( p ); + Vec_Ptr_t * vTruths = Vec_PtrAllocTruthTables( nVars2 ); + Gia_Obj_t * pObj; Vec_Int_t * vNode; int i, m, iObj; + Vec_WecForEachLevelStop( vNodes, vNode, i, nVars2 ) + Abc_TtCopy( Vec_WrdEntryP(vSims, nWords2*Vec_IntEntry(vNode,0)), (word *)Vec_PtrEntry(vTruths, i), nWords2, 0 ); + Vec_PtrFree( vTruths ); + Gia_ManForEachAnd( p, pObj, i ) + Gia_ManSimPatSimAnd( p, i, pObj, nWords2, vSims ); + for ( i = 0; i < Gia_ManCoNum(p)/2; i++ ) + { + if ( !Gia_ManComparePair( p, vSims, i, nWords2 ) ) + { + printf( "Miter is asserted for output %d.\n", i ); + Vec_WecFree( vNodes ); + Vec_WrdFree( vSims ); + return 0; + } + } + for ( m = 0; m < (1 << nVars3); m++ ) + { + int iVar = m ? Abc_TtSuppFindFirst( m ^ (m >> 1) ^ (m-1) ^ ((m-1) >> 1) ) : 0; + vNode = Vec_WecEntry( vNodes, nVars2+iVar ); + Abc_TtNot( Vec_WrdEntryP(vSims, nWords2*Vec_IntEntry(vNode,0)), nWords2 ); + Vec_IntForEachEntryStart( vNode, iObj, i, 1 ) + { + if ( iObj < Gia_ManObjNum(p) ) + { + pObj = Gia_ManObj( p, iObj ); + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManSimPatSimAnd( p, iObj, pObj, nWords2, vSims ); + } + else if ( !Gia_ManComparePair( p, vSims, iObj - Gia_ManObjNum(p), nWords2 ) ) + { + printf( "Miter is asserted for output %d.\n", iObj - Gia_ManObjNum(p) ); + Vec_WecFree( vNodes ); + Vec_WrdFree( vSims ); + return 0; + } + } + //for ( i = 0; i < Gia_ManObjNum(p); i++ ) + // printf( "%3d : ", i), Extra_PrintHex2( stdout, (unsigned *)Vec_WrdEntryP(vSims, i), 6 ), printf( "\n" ); + if ( !fWarning && Abc_Clock() > clk + 5*CLOCKS_PER_SEC ) + printf( "The computation is expected to take about %.2f sec.\n", 5.0*(1 << nVars3)/m ), fWarning = 1; + //if ( (m & 0x3F) == 0x3F ) + if ( fVerbose && (m & 0xFF) == 0xFF ) + printf( "Finished %6d (out of %6d)...\n", m, 1 << nVars3 ); + } + Vec_WecFree( vNodes ); + Vec_WrdFree( vSims ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimPatAssignInputs2( Gia_Man_t * p, int nWords, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsIn ) +{ + int i, Id; + assert( Vec_WrdSize(vSims) == 2 * nWords * Gia_ManObjNum(p) ); + assert( Vec_WrdSize(vSimsIn) == nWords * Gia_ManCiNum(p) ); + Gia_ManForEachCiId( p, Id, i ) + { + Abc_TtCopy( Vec_WrdEntryP(vSims, 2*Id*nWords+0), Vec_WrdEntryP(vSimsIn, i*nWords), nWords, 0 ); + Abc_TtCopy( Vec_WrdEntryP(vSims, 2*Id*nWords+1), Vec_WrdEntryP(vSimsIn, i*nWords), nWords, 1 ); + } +} +static inline void Gia_ManSimPatSimAnd2( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims ) +{ + word * pSims = Vec_WrdArray(vSims); + word * pSims0 = pSims + nWords*Gia_ObjFaninLit0(pObj, i); + word * pSims1 = pSims + nWords*Gia_ObjFaninLit1(pObj, i); + word * pSims2 = pSims + nWords*(2*i+0); + word * pSims3 = pSims + nWords*(2*i+1); int w; + assert( !Gia_ObjIsXor(pObj) ); +// if ( Gia_ObjIsXor(pObj) ) +// for ( w = 0; w < nWords; w++ ) +// pSims2[w] = pSims0[w] ^ pSims1[w]; +// else + for ( w = 0; w < nWords; w++ ) + { + pSims2[w] = pSims0[w] & pSims1[w]; + pSims3[w] = ~pSims2[w]; + } + //_mm256_storeu_ps( (float *)pSims2, _mm256_and_ps(_mm256_loadu_ps((float *)pSims0), _mm256_loadu_ps((float *)pSims1)) ); +} +static inline void Gia_ManSimPatSimPo2( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims ) +{ + word * pSims = Vec_WrdArray(vSims); + word * pSims0 = pSims + nWords*Gia_ObjFaninLit0(pObj, i); + word * pSims2 = pSims + nWords*i; int w; + for ( w = 0; w < nWords; w++ ) + pSims2[w] = pSims0[w]; +} +Vec_Wrd_t * Gia_ManSimPatSim2( Gia_Man_t * pGia ) +{ + Gia_Obj_t * pObj; + int i, nWords = Vec_WrdSize(pGia->vSimsPi) / Gia_ManCiNum(pGia); + Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(pGia) * nWords * 2 ); + assert( Vec_WrdSize(pGia->vSimsPi) % Gia_ManCiNum(pGia) == 0 ); + Gia_ManSimPatAssignInputs2( pGia, nWords, vSims, pGia->vSimsPi ); + Gia_ManForEachAnd( pGia, pObj, i ) + Gia_ManSimPatSimAnd2( pGia, i, pObj, nWords, vSims ); + Gia_ManForEachCo( pGia, pObj, i ) + Gia_ManSimPatSimPo2( pGia, Gia_ObjId(pGia, pObj), pObj, nWords, vSims ); + return vSims; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimPatValuesDerive( Gia_Man_t * p, int nWords, Vec_Wrd_t * vSims, Vec_Wrd_t * vValues ) +{ + int i, Id; + assert( Vec_WrdSize(vSims) == nWords * Gia_ManObjNum(p) ); + assert( Vec_WrdSize(vValues) == nWords * Gia_ManCoNum(p) ); + Gia_ManForEachCoId( p, Id, i ) + memcpy( Vec_WrdEntryP(vValues, nWords * i), Vec_WrdEntryP(vSims, nWords * Id), sizeof(word)* nWords ); +} +Vec_Wrd_t * Gia_ManSimPatValues( Gia_Man_t * p ) +{ + int i, Id, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + Vec_Wrd_t * vSims = Gia_ManSimPatSim( p ); + Vec_Wrd_t * vValues = Vec_WrdStart( Gia_ManCoNum(p) * nWords ); + assert( Vec_WrdSize(p->vSimsPi) == nWords * Gia_ManCiNum(p) ); + assert( Vec_WrdSize(vValues) == nWords * Gia_ManCoNum(p) ); + assert( Vec_WrdSize(vSims) == nWords * Gia_ManObjNum(p) ); + Gia_ManForEachCoId( p, Id, i ) + memcpy( Vec_WrdEntryP(vValues, nWords * i), Vec_WrdEntryP(vSims, nWords * Id), sizeof(word)* nWords ); + Vec_WrdFree( vSims ); + return vValues; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Gia_ManSimCombine( int nInputs, Vec_Wrd_t * vBase, Vec_Wrd_t * vAddOn, int nWordsUse ) +{ + int nWordsBase = Vec_WrdSize(vBase) / nInputs; + int nWordsAddOn = Vec_WrdSize(vAddOn) / nInputs; int i, w; + Vec_Wrd_t * vSimsIn = Vec_WrdAlloc( nInputs * (nWordsBase + nWordsUse) ); + assert( Vec_WrdSize(vBase) % nInputs == 0 ); + assert( Vec_WrdSize(vAddOn) % nInputs == 0 ); + assert( nWordsUse <= nWordsAddOn ); + for ( i = 0; i < nInputs; i++ ) + { + word * pSimsB = nWordsBase ? Vec_WrdEntryP( vBase, i * nWordsBase ) : NULL; + word * pSimsA = nWordsAddOn ? Vec_WrdEntryP( vAddOn, i * nWordsAddOn ) : NULL; + for ( w = 0; w < nWordsBase; w++ ) + Vec_WrdPush( vSimsIn, pSimsB[w] ); + for ( w = 0; w < nWordsUse; w++ ) + Vec_WrdPush( vSimsIn, pSimsA[w] ); + } + assert( Vec_WrdSize(vSimsIn) == Vec_WrdCap(vSimsIn) || Vec_WrdSize(vSimsIn) < 16 ); + return vSimsIn; +} +int Gia_ManSimBitPackOne( int nWords, Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsCare, int iPat, int * pLits, int nLits ) +{ + word * pSimsI, * pSimsC; int i, k; + for ( i = 0; i < iPat; i++ ) + { + for ( k = 0; k < nLits; k++ ) + { + int iVar = Abc_Lit2Var( pLits[k] ); + pSimsI = Vec_WrdEntryP( vSimsIn, nWords * iVar ); + pSimsC = Vec_WrdEntryP( vSimsCare, nWords * iVar ); + if ( Abc_TtGetBit(pSimsC, i) && (Abc_TtGetBit(pSimsI, i) == Abc_LitIsCompl(pLits[k])) ) + break; + } + if ( k == nLits ) + break; + } + for ( k = 0; k < nLits; k++ ) + { + int iVar = Abc_Lit2Var( pLits[k] ); + pSimsI = Vec_WrdEntryP( vSimsIn, nWords * iVar ); + pSimsC = Vec_WrdEntryP( vSimsCare, nWords * iVar ); + if ( !Abc_TtGetBit(pSimsC, i) && Abc_TtGetBit(pSimsI, i) == Abc_LitIsCompl(pLits[k]) ) + Abc_TtXorBit( pSimsI, i ); + Abc_TtSetBit( pSimsC, i ); + assert( Abc_TtGetBit(pSimsC, i) && (Abc_TtGetBit(pSimsI, i) != Abc_LitIsCompl(pLits[k])) ); + } + return (int)(i == iPat); +} +Vec_Wrd_t * Gia_ManSimBitPacking( Gia_Man_t * p, Vec_Int_t * vCexStore, int nCexes, int nUnDecs ) +{ + int c, iCur = 0, iPat = 0; + int nWordsMax = Abc_Bit6WordNum( nCexes ); + Vec_Wrd_t * vSimsIn = Vec_WrdStartRandom( Gia_ManCiNum(p) * nWordsMax ); + Vec_Wrd_t * vSimsCare = Vec_WrdStart( Gia_ManCiNum(p) * nWordsMax ); + Vec_Wrd_t * vSimsRes = NULL; + for ( c = 0; c < nCexes + nUnDecs; c++ ) + { + int Out = Vec_IntEntry( vCexStore, iCur++ ); + int Size = Vec_IntEntry( vCexStore, iCur++ ); + if ( Size == -1 ) + continue; + iPat += Gia_ManSimBitPackOne( nWordsMax, vSimsIn, vSimsCare, iPat, Vec_IntEntryP(vCexStore, iCur), Size ); + iCur += Size; + assert( iPat <= nCexes + nUnDecs ); + Out = 0; + } + assert( iCur == Vec_IntSize(vCexStore) ); + vSimsRes = Gia_ManSimCombine( Gia_ManCiNum(p), p->vSimsPi, vSimsIn, Abc_Bit6WordNum(iPat+1) ); + printf( "Compressed %d CEXes into %d patterns and added %d words to available %d words.\n", + nCexes, iPat, Abc_Bit6WordNum(iPat+1), Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p) ); + Vec_WrdFree( vSimsIn ); + Vec_WrdFree( vSimsCare ); + return vSimsRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSimPatHashPatterns( Gia_Man_t * p, int nWords, Vec_Wrd_t * vSims, int * pnC0, int * pnC1 ) +{ + Gia_Obj_t * pObj; + int i, nUnique; + Vec_Mem_t * vStore; + vStore = Vec_MemAlloc( nWords, 12 ); // 2^12 N-word entries per page + Vec_MemHashAlloc( vStore, 1 << 12 ); + Gia_ManForEachCand( p, pObj, i ) + { + word * pSim = Vec_WrdEntryP(vSims, i*nWords); + if ( pnC0 && Abc_TtIsConst0(pSim, nWords) ) + (*pnC0)++; + if ( pnC1 && Abc_TtIsConst1(pSim, nWords) ) + (*pnC1)++; + Vec_MemHashInsert( vStore, pSim ); + } + nUnique = Vec_MemEntryNum( vStore ); + Vec_MemHashFree( vStore ); + Vec_MemFree( vStore ); + return nUnique; +} +Gia_Man_t * Gia_ManSimPatGenMiter( Gia_Man_t * p, Vec_Wrd_t * vSims ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, nWords = Vec_WrdSize(vSims) / Gia_ManObjNum(p); + pNew = Gia_ManStart( Gia_ManObjNum(p) + Gia_ManCoNum(p) ); + Gia_ManHashStart( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachAnd( p, pObj, i ) + { + word * pSim = Vec_WrdEntryP(vSims, i*nWords); + if ( Abc_TtIsConst0(pSim, nWords) ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(pObj->Value, 0) ); + if ( Abc_TtIsConst1(pSim, nWords) ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(pObj->Value, 1) ); + } + Gia_ManHashStop( pNew ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimProfile( Gia_Man_t * pGia ) +{ + Vec_Wrd_t * vSims = Gia_ManSimPatSim( pGia ); + int nWords = Vec_WrdSize(vSims) / Gia_ManObjNum(pGia); + int nC0s = 0, nC1s = 0, nUnique = Gia_ManSimPatHashPatterns( pGia, nWords, vSims, &nC0s, &nC1s ); + printf( "Simulating %d patterns leads to %d unique objects (%.2f %% out of %d). Const0 = %d. Const1 = %d.\n", + 64*nWords, nUnique, 100.0*nUnique/Gia_ManCandNum(pGia), Gia_ManCandNum(pGia), nC0s, nC1s ); + Vec_WrdFree( vSims ); +} +void Gia_ManPatSatImprove( Gia_Man_t * p, int nWords0, int fVerbose ) +{ + extern Vec_Int_t * Cbs2_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ); + int i, Status, Counts[3] = {0}; + Gia_Man_t * pGia; + Vec_Wrd_t * vSimsIn = NULL; + Vec_Str_t * vStatus = NULL; + Vec_Int_t * vCexStore = NULL; + Vec_Wrd_t * vSims = Gia_ManSimPatSim( p ); + //Gia_ManSimProfile( p ); + pGia = Gia_ManSimPatGenMiter( p, vSims ); + vCexStore = Cbs2_ManSolveMiterNc( pGia, 1000, &vStatus, 0 ); + Gia_ManStop( pGia ); + Vec_StrForEachEntry( vStatus, Status, i ) + { + assert( Status >= -1 && Status <= 1 ); + Counts[Status+1]++; + } + if ( fVerbose ) + printf( "Total = %d : SAT = %d. UNSAT = %d. UNDEC = %d.\n", Counts[1]+Counts[2]+Counts[0], Counts[1], Counts[2], Counts[0] ); + if ( Counts[1] == 0 ) + printf( "There are no counter-examples. No need for more simulation.\n" ); + else + { + vSimsIn = Gia_ManSimBitPacking( p, vCexStore, Counts[1], Counts[0] ); + Vec_WrdFreeP( &p->vSimsPi ); + p->vSimsPi = vSimsIn; + //Gia_ManSimProfile( p ); + } + Vec_StrFree( vStatus ); + Vec_IntFree( vCexStore ); + Vec_WrdFree( vSims ); +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_SimRsbMan_t * Gia_SimRsbAlloc( Gia_Man_t * pGia ) +{ + Gia_SimRsbMan_t * p = ABC_CALLOC( Gia_SimRsbMan_t, 1 ); + p->pGia = pGia; + p->nWords = Vec_WrdSize(pGia->vSimsPi) / Gia_ManCiNum(pGia); assert( Vec_WrdSize(pGia->vSimsPi) % Gia_ManCiNum(pGia) == 0 ); + p->pFunc[0] = ABC_CALLOC( word, p->nWords ); + p->pFunc[1] = ABC_CALLOC( word, p->nWords ); + p->pFunc[2] = ABC_CALLOC( word, p->nWords ); + p->vTfo = Vec_IntAlloc( 1000 ); + p->vCands = Vec_IntAlloc( 1000 ); + p->vFanins = Vec_IntAlloc( 10 ); + p->vFanins2 = Vec_IntAlloc( 10 ); + p->vSimsObj = Gia_ManSimPatSim( pGia ); + p->vSimsObj2 = Vec_WrdStart( Vec_WrdSize(p->vSimsObj) ); + assert( p->nWords == Vec_WrdSize(p->vSimsObj) / Gia_ManObjNum(pGia) ); + Gia_ManStaticFanoutStart( pGia ); + return p; +} +void Gia_SimRsbFree( Gia_SimRsbMan_t * p ) +{ + Gia_ManStaticFanoutStop( p->pGia ); + Vec_IntFree( p->vTfo ); + Vec_IntFree( p->vCands ); + Vec_IntFree( p->vFanins ); + Vec_IntFree( p->vFanins2 ); + Vec_WrdFree( p->vSimsObj ); + Vec_WrdFree( p->vSimsObj2 ); + ABC_FREE( p->pFunc[0] ); + ABC_FREE( p->pFunc[1] ); + ABC_FREE( p->pFunc[2] ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_SimRsbTfo_rec( Gia_Man_t * p, int iObj, int iFanout, Vec_Int_t * vTfo ) +{ + int i, iFan; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + Gia_ObjForEachFanoutStaticId( p, iObj, iFan, i ) + if ( iFanout == -1 || iFan == iFanout ) + Gia_SimRsbTfo_rec( p, iFan, -1, vTfo ); + Vec_IntPush( vTfo, iObj ); +} +Vec_Int_t * Gia_SimRsbTfo( Gia_SimRsbMan_t * p, int iObj, int iFanout ) +{ + assert( iObj > 0 ); + Vec_IntClear( p->vTfo ); + Gia_ManIncrementTravId( p->pGia ); + Gia_SimRsbTfo_rec( p->pGia, iObj, iFanout, p->vTfo ); + assert( Vec_IntEntryLast(p->vTfo) == iObj ); + Vec_IntPop( p->vTfo ); + Vec_IntReverseOrder( p->vTfo ); + Vec_IntSort( p->vTfo, 0 ); + return p->vTfo; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word * Gia_SimRsbFunc( Gia_SimRsbMan_t * p, int iObj, Vec_Int_t * vFanins, int fOnSet ) +{ + int nTruthWords = Abc_Truth6WordNum( Vec_IntSize(vFanins) ); + word * pTruth = ABC_CALLOC( word, nTruthWords ); + word * pFunc = Vec_WrdEntryP( p->vSimsObj, p->nWords*iObj ); + word * pFanins[16] = {NULL}; int s, b, iMint, i, iFanin; + assert( Vec_IntSize(vFanins) <= 16 ); + Vec_IntForEachEntry( vFanins, iFanin, i ) + pFanins[i] = Vec_WrdEntryP( p->vSimsObj, p->nWords*iFanin ); + for ( s = 0; s < 64*p->nWords; s++ ) + { + if ( !Abc_TtGetBit(p->pFunc[2], s) || Abc_TtGetBit(pFunc, s) != fOnSet ) + continue; + iMint = 0; + for ( b = 0; b < Vec_IntSize(vFanins); b++ ) + if ( Abc_TtGetBit(pFanins[b], s) ) + iMint |= 1 << b; + Abc_TtSetBit( pTruth, iMint ); + } + return pTruth; +} +int Gia_SimRsbResubVerify( Gia_SimRsbMan_t * p, int iObj, Vec_Int_t * vFanins ) +{ + word * pTruth0 = Gia_SimRsbFunc( p, iObj, p->vFanins, 0 ); + word * pTruth1 = Gia_SimRsbFunc( p, iObj, p->vFanins, 1 ); + int Res = !Abc_TtIntersect( pTruth0, pTruth1, p->nWords, 0 ); + ABC_FREE( pTruth0 ); + ABC_FREE( pTruth1 ); + return Res; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_SimRsbSimAndCareSet( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims, Vec_Wrd_t * vSims2 ) +{ + word pComps[2] = { 0, ~(word)0 }; + word Diff0 = pComps[Gia_ObjFaninC0(pObj)]; + word Diff1 = pComps[Gia_ObjFaninC1(pObj)]; + Vec_Wrd_t * vSims0 = Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)) ? vSims2 : vSims; + Vec_Wrd_t * vSims1 = Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)) ? vSims2 : vSims; + word * pSims0 = Vec_WrdEntryP( vSims0, nWords*Gia_ObjFaninId0(pObj, i) ); + word * pSims1 = Vec_WrdEntryP( vSims1, nWords*Gia_ObjFaninId1(pObj, i) ); + word * pSims2 = Vec_WrdEntryP( vSims2, nWords*i ); int w; + if ( Gia_ObjIsXor(pObj) ) + for ( w = 0; w < nWords; w++ ) + pSims2[w] = (pSims0[w] ^ Diff0) ^ (pSims1[w] ^ Diff1); + else + for ( w = 0; w < nWords; w++ ) + pSims2[w] = (pSims0[w] ^ Diff0) & (pSims1[w] ^ Diff1); +} +word * Gia_SimRsbCareSet( Gia_SimRsbMan_t * p, int iObj, Vec_Int_t * vTfo ) +{ + word * pSims = Vec_WrdEntryP( p->vSimsObj, p->nWords*iObj ); + word * pSims2 = Vec_WrdEntryP( p->vSimsObj2, p->nWords*iObj ); int iNode, i; + Abc_TtCopy( pSims2, pSims, p->nWords, 1 ); + Abc_TtClear( p->pFunc[2], p->nWords ); + Vec_IntForEachEntry( vTfo, iNode, i ) + { + Gia_Obj_t * pNode = Gia_ManObj(p->pGia, iNode); + if ( Gia_ObjIsAnd(pNode) ) + Gia_SimRsbSimAndCareSet( p->pGia, iNode, pNode, p->nWords, p->vSimsObj, p->vSimsObj2 ); + else if ( Gia_ObjIsCo(pNode) ) + { + word * pSimsA = Vec_WrdEntryP( p->vSimsObj, p->nWords*Gia_ObjFaninId0p(p->pGia, pNode) ); + word * pSimsB = Vec_WrdEntryP( p->vSimsObj2, p->nWords*Gia_ObjFaninId0p(p->pGia, pNode) ); + Abc_TtOrXor( p->pFunc[2], pSimsA, pSimsB, p->nWords ); + } + else assert( 0 ); + } + return p->pFunc[2]; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjSimCollect( Gia_SimRsbMan_t * p ) +{ + int i, k, iTemp, iFanout; + Vec_IntClear( p->vFanins2 ); + assert( Vec_IntSize(p->vFanins) > 0 ); + Vec_IntForEachEntry( p->vFanins, iTemp, i ) + { + Gia_Obj_t * pObj = Gia_ManObj( p->pGia, iTemp ); + if ( Gia_ObjIsAnd(pObj) && !Gia_ObjIsTravIdCurrentId( p->pGia, Gia_ObjFaninId0(pObj, iTemp) ) ) + Vec_IntPush( p->vFanins2, Gia_ObjFaninId0(pObj, iTemp) ); + if ( Gia_ObjIsAnd(pObj) && !Gia_ObjIsTravIdCurrentId( p->pGia, Gia_ObjFaninId1(pObj, iTemp) ) ) + Vec_IntPush( p->vFanins2, Gia_ObjFaninId1(pObj, iTemp) ); + Gia_ObjForEachFanoutStaticId( p->pGia, iTemp, iFanout, k ) + if ( Gia_ObjIsAnd(Gia_ManObj(p->pGia, iFanout)) && !Gia_ObjIsTravIdCurrentId( p->pGia, iFanout ) ) + Vec_IntPush( p->vFanins2, iFanout ); + } +} +Vec_Int_t * Gia_ObjSimCands( Gia_SimRsbMan_t * p, int iObj, int nCands ) +{ + assert( iObj > 0 ); + assert( Gia_ObjIsAnd(Gia_ManObj(p->pGia, iObj)) ); + Vec_IntClear( p->vCands ); + Vec_IntFill( p->vFanins, 1, iObj ); + while ( Vec_IntSize(p->vFanins) > 0 && Vec_IntSize(p->vCands) < nCands ) + { + int i, iTemp; + Vec_IntForEachEntry( p->vFanins, iTemp, i ) + Gia_ObjSetTravIdCurrentId( p->pGia, iTemp ); + Gia_ObjSimCollect( p ); // p->vFanins -> p->vFanins2 + Vec_IntAppend( p->vCands, p->vFanins2 ); + ABC_SWAP( Vec_Int_t *, p->vFanins, p->vFanins2 ); + } + assert( Vec_IntSize(p->vFanins) == 0 || Vec_IntSize(p->vCands) >= nCands ); + if ( Vec_IntSize(p->vCands) > nCands ) + Vec_IntShrink( p->vCands, nCands ); + return p->vCands; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjSimRsb( Gia_SimRsbMan_t * p, int iObj, int nCands, int fVerbose, int * pnBufs, int * pnInvs ) +{ + int i, iCand, RetValue = 0; + Vec_Int_t * vTfo = Gia_SimRsbTfo( p, iObj, -1 ); + word * pCareSet = Gia_SimRsbCareSet( p, iObj, vTfo ); + word * pFunc = Vec_WrdEntryP( p->vSimsObj, p->nWords*iObj ); + Vec_Int_t * vCands = Gia_ObjSimCands( p, iObj, nCands ); + Abc_TtAndSharp( p->pFunc[0], pCareSet, pFunc, p->nWords, 1 ); + Abc_TtAndSharp( p->pFunc[1], pCareSet, pFunc, p->nWords, 0 ); + +/* +printf( "Considering node %d with %d candidates:\n", iObj, Vec_IntSize(vCands) ); +Vec_IntPrint( vTfo ); +Vec_IntPrint( vCands ); +Extra_PrintBinary( stdout, (unsigned *)pCareSet, 64 ); printf( "\n" ); +Extra_PrintBinary( stdout, (unsigned *)pFunc, 64 ); printf( "\n" ); +Extra_PrintBinary( stdout, (unsigned *)p->pFunc[0], 64 ); printf( "\n" ); +Extra_PrintBinary( stdout, (unsigned *)p->pFunc[1], 64 ); printf( "\n" ); +*/ + Vec_IntForEachEntry( vCands, iCand, i ) + { + word * pDiv = Vec_WrdEntryP( p->vSimsObj, p->nWords*iCand ); + if ( !Abc_TtIntersect(pDiv, p->pFunc[0], p->nWords, 0) && + !Abc_TtIntersect(pDiv, p->pFunc[1], p->nWords, 1) ) + { (*pnBufs)++; if ( fVerbose ) printf( "Level %3d : %d = buf(%d)\n", Gia_ObjLevelId(p->pGia, iObj), iObj, iCand ); RetValue = 1; } + if ( !Abc_TtIntersect(pDiv, p->pFunc[0], p->nWords, 1) && + !Abc_TtIntersect(pDiv, p->pFunc[1], p->nWords, 0) ) + { (*pnInvs)++; if ( fVerbose ) printf( "Level %3d : %d = inv(%d)\n", Gia_ObjLevelId(p->pGia, iObj), iObj, iCand ); RetValue = 1; } + } + return RetValue; +} + +int Gia_ManSimRsb( Gia_Man_t * pGia, int nCands, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Obj_t * pObj; int iObj, nCount = 0, nBufs = 0, nInvs = 0; + Gia_SimRsbMan_t * p = Gia_SimRsbAlloc( pGia ); + assert( pGia->vSimsPi != NULL ); + Gia_ManLevelNum( pGia ); + Gia_ManForEachAnd( pGia, pObj, iObj ) + //if ( iObj == 6 ) + nCount += Gia_ObjSimRsb( p, iObj, nCands, fVerbose, &nBufs, &nInvs ); + printf( "Can resubstitute %d nodes (%.2f %% out of %d) (Bufs = %d Invs = %d) ", + nCount, 100.0*nCount/Gia_ManAndNum(pGia), Gia_ManAndNum(pGia), nBufs, nInvs ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Gia_SimRsbFree( p ); + return nCount; +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimRelAssignInputs( Gia_Man_t * p, int nWords, Vec_Wrd_t * vSims, int nWordsIn, Vec_Wrd_t * vSimsIn ) +{ + int i, m, Id, nMints = nWords / nWordsIn; + assert( Vec_WrdSize(vSims) == nWords * Gia_ManObjNum(p) ); + assert( Vec_WrdSize(vSimsIn) == nWordsIn * Gia_ManCiNum(p) ); + Gia_ManForEachCiId( p, Id, i ) + for ( m = 0; m < nMints; m++ ) + memcpy( Vec_WrdEntryP(vSims, Id * nWords + nWordsIn * m), + Vec_WrdEntryP(vSimsIn, i * nWordsIn), sizeof(word) * nWordsIn ); +} +int Gia_ManSimRelCompare( Gia_Man_t * p, int nWords, Vec_Wrd_t * vSims, int nWordsOut, Vec_Wrd_t * vSimsOut, int iPat, int iMint ) +{ + int i, Id; + Gia_ManForEachCoId( p, Id, i ) + { + word * pSim = Vec_WrdEntryP( vSims, nWords * Id + iMint * nWordsOut ); + word * pSimOut = Vec_WrdEntryP( vSimsOut, nWordsOut * i ); +/* + int k; + for ( k = 0; k < 64*nWordsOut; k++ ) + printf( "%d", Abc_TtGetBit( pSim, k ) ); + printf( "\n" ); + for ( k = 0; k < 64*nWordsOut; k++ ) + printf( "%d", Abc_TtGetBit( pSimOut, k ) ); + printf( "\n\n" ); +*/ + if ( Abc_TtGetBit(pSim, iPat) != Abc_TtGetBit(pSimOut, iPat) ) + return 0; + } + return 1; +} +int Gia_ManSimRelCollectOutputs( Gia_Man_t * p, int nWords, Vec_Wrd_t * vSims, int nWordsOut, Vec_Wrd_t * vSimsOut, Vec_Wrd_t * vRel ) +{ + int i, m, nMints = nWords / nWordsOut, Count = 0; + assert( Vec_WrdSize(vSims) == nWords * Gia_ManObjNum(p) ); + assert( Vec_WrdSize(vSimsOut) == nWordsOut * Gia_ManCoNum(p) ); + assert( Vec_WrdSize(vRel) == nWordsOut * nMints ); + for ( i = 0; i < 64 * nWordsOut; i++ ) + { + int CountMints = 0; + for ( m = 0; m < nMints; m++ ) + if ( Gia_ManSimRelCompare(p, nWords, vSims, nWordsOut, vSimsOut, i, m) ) + Abc_TtSetBit( Vec_WrdArray(vRel), i*nMints+m ), CountMints++; + Count += CountMints == 0; + } + if ( Count ) + printf( "The relation is not well-defined for %d (out of %d) patterns.\n", Count, 64 * nWordsOut ); + return Count; +} +Vec_Wrd_t * Gia_ManSimRel( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wrd_t * vVals ) +{ + int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + int nMints = 1 << Vec_IntSize(vObjs), i, m, iObj; + Gia_Obj_t * pObj; + Vec_Wrd_t * vRel = Vec_WrdStart( nWords * nMints ); + Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(p) * nWords * nMints ); + Gia_ManSimRelAssignInputs( p, nWords * nMints, vSims, nWords, p->vSimsPi ); + Vec_IntForEachEntry( vObjs, iObj, i ) + for ( m = 0; m < nMints; m++ ) + if ( (m >> i) & 1 ) + memset( Vec_WrdEntryP(vSims, iObj*nMints*nWords + nWords*m), 0xFF, sizeof(word)*nWords ); + else + memset( Vec_WrdEntryP(vSims, iObj*nMints*nWords + nWords*m), 0x00, sizeof(word)*nWords ); + Gia_ManCleanPhase( p ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->fPhase = 1; + Gia_ManForEachAnd( p, pObj, i ) + if ( !pObj->fPhase ) + Gia_ManSimPatSimAnd( p, i, pObj, nWords * nMints, vSims ); + Gia_ManForEachCo( p, pObj, i ) + if ( !pObj->fPhase ) + Gia_ManSimPatSimPo( p, Gia_ObjId(p, pObj), pObj, nWords * nMints, vSims ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->fPhase = 0; + if ( Gia_ManSimRelCollectOutputs( p, nWords * nMints, vSims, nWords, vVals, vRel ) ) + Vec_WrdFreeP( &vRel ); + Vec_WrdFree( vSims ); + return vRel; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimRelCheckFuncs( Gia_Man_t * p, Vec_Wrd_t * vRel, int nOuts, Vec_Wrd_t * vFuncs ) +{ + int i, k, m, Values[32], nErrors = 0, nMints = 1 << nOuts, nWords = Vec_WrdSize(vRel) / nMints; + assert( Vec_WrdSize(vFuncs) == 2 * nOuts * nWords ); + assert( nOuts <= 32 ); + for ( i = 0; i < 64 * nWords; i++ ) + { + for ( k = 0; k < nOuts; k++ ) + { + int Value0 = Abc_TtGetBit( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), i ); + int Value1 = Abc_TtGetBit( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), i ); + if ( Value0 && !Value1 ) + Values[k] = 1; + else if ( !Value0 && Value1 ) + Values[k] = 2; + else if ( !Value0 && !Value1 ) + Values[k] = 3; + else assert( 0 ); + } + for ( m = 0; m < nMints; m++ ) + { + for ( k = 0; k < nOuts; k++ ) + if ( ((Values[k] >> ((m >> k) & 1)) & 1) == 0 ) + break; + if ( k < nOuts ) + continue; + if ( Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ) ) + continue; + if ( nErrors++ == 0 ) + printf( "For pattern %d, minterm %d produced by function is not in the relation.\n", i, m ); + } + } + if ( nErrors ) + printf( "Total number of similar errors = %d.\n", nErrors ); + else + printf( "The function agrees with the relation.\n" ); +} +Vec_Wrd_t * Gia_ManSimRelDeriveFuncs( Gia_Man_t * p, Vec_Wrd_t * vRel, int nOuts ) +{ + int i, k, m, Count = 0, nMints = 1 << nOuts, nWords = Vec_WrdSize(vRel) / nMints; + Vec_Wrd_t * vFuncs = Vec_WrdStart( 2 * nOuts * nWords ); + assert( Vec_WrdSize(vRel) % nMints == 0 ); + for ( i = 0; i < 64 * nWords; i++ ) + { + for ( m = 0; m < nMints; m++ ) + if ( Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ) ) + break; + Count += m == nMints; + for ( k = 0; k < nOuts; k++ ) + if ( (m >> k) & 1 ) + Abc_TtSetBit( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), i ); + else + Abc_TtSetBit( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), i ); + } + if ( Count ) + printf( "The relation is not well-defined for %d (out of %d) patterns.\n", Count, 64 * nWords ); + else + printf( "The relation was successfully determized without don't-cares for %d patterns.\n", 64 * nWords ); + Gia_ManSimRelCheckFuncs( p, vRel, nOuts, vFuncs ); + return vFuncs; +} +Vec_Wrd_t * Gia_ManSimRelDeriveFuncs2( Gia_Man_t * p, Vec_Wrd_t * vRel, int nOuts ) +{ + int i, k, m, nDCs[32] = {0}, Count = 0, nMints = 1 << nOuts, nWords = Vec_WrdSize(vRel) / nMints; + Vec_Wrd_t * vFuncs = Vec_WrdStart( 2 * nOuts * nWords ); + assert( Vec_WrdSize(vRel) % nMints == 0 ); + assert( nOuts <= 32 ); + for ( i = 0; i < 64 * nWords; i++ ) + { + for ( m = 0; m < nMints; m++ ) + if ( Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ) ) + break; + Count += m == nMints; + for ( k = 0; k < nOuts; k++ ) + { + if ( Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+(m^(1<> k) & 1 ) + Abc_TtSetBit( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), i ); + else + Abc_TtSetBit( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), i ); + } + if ( 0 ) + { + for ( m = 0; m < nMints; m++ ) + printf( "%d", Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ) ); + printf( " " ); + for ( k = 0; k < nOuts; k++ ) + { + if ( Abc_TtGetBit( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), i ) ) + printf( "0" ); + else if ( Abc_TtGetBit( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), i ) ) + printf( "1" ); + else + printf( "-" ); + } + printf( "\n" ); + } + } + if ( Count ) + printf( "The relation is not well-defined for %d (out of %d) patterns.\n", Count, 64 * nWords ); + else + { + printf( "The relation was successfully determized with don't-cares for %d patterns.\n", 64 * nWords ); + for ( k = 0; k < nOuts; k++ ) + { + int nOffs = Abc_TtCountOnesVec( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), nWords ); + int nOns = Abc_TtCountOnesVec( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), nWords ); + printf( "%4d : Off = %6d On = %6d Dc = %6d (%6.2f %%)\n", k, nOffs, nOns, nDCs[k], 100.0*nDCs[k]/(64*nWords) ); + } + printf( "\n" ); + } + Gia_ManSimRelCheckFuncs( p, vRel, nOuts, vFuncs ); + return vFuncs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimRelPrint( Gia_Man_t * p, Vec_Wrd_t * vRel, Vec_Int_t * vOutMints ) +{ + int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + int nMints = Vec_WrdSize(vRel) / nWords; + int i, m, Count; +/* + for ( i = 0; i < 64 * nWords; i++ ) + { + int k; + for ( k = 0; k < Gia_ManCiNum(p); k++ ) + printf( "%d", Abc_TtGetBit( Vec_WrdEntryP(p->vSimsPi, k), i ) ); + printf( " " ); + Count = 0; + for ( m = 0; m < nMints; m++ ) + { + printf( "%d", Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ) ); + Count += Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ); + } + printf( " Count = %2d ", Count ); + if ( vOutMints ) + { + printf( " %3d ", Vec_IntEntry(vOutMints, i) ); + if ( Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+Vec_IntEntry(vOutMints, i) ) ) + printf( "yes" ); + else + printf( "no" ); + } + printf( "\n" ); + } +*/ +/* + for ( i = 0; i < 64 * nWords; i++ ) + { + Count = 0; + for ( m = 0; m < nMints; m++ ) + Count += Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ); + printf( "%d ", Count ); + } + printf( "\n" ); +*/ + for ( i = 0; i < 64 * nWords; i++ ) + { + Count = 0; + for ( m = 0; m < nMints; m++ ) + { + printf( "%d", Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ) ); + Count += Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ); + } + printf( " Count = %2d \n", Count ); + } +} +Vec_Int_t * Gia_ManSimPatStart( int nItems ) +{ + Vec_Int_t * vValues = Vec_IntAlloc( nItems ); + Vec_IntPush( vValues, 17 ); + Vec_IntPush( vValues, 39 ); + Vec_IntPush( vValues, 56 ); + Vec_IntPush( vValues, 221 ); + return vValues; +} +void Gia_ManSimRelTest( Gia_Man_t * p ) +{ + //int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + Vec_Int_t * vObjs = Gia_ManSimPatStart( 4 ); // can be CI/AND/CO + Vec_Wrd_t * vVals = Gia_ManSimPatValues( p ); + Vec_Wrd_t * vRel = Gia_ManSimRel( p, vObjs, vVals ); + assert( p->vSimsPi != NULL ); + Gia_ManSimRelPrint( p, vRel, NULL ); + Vec_IntFree( vObjs ); + Vec_WrdFree( vVals ); + Vec_WrdFree( vRel ); +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_Sim5CollectValues( word * pOffSet, word * pOnSet, int nWords ) +{ + Vec_Int_t * vBits = Vec_IntAlloc( 64*nWords ); int i, Count[2] = {0}; + for ( i = 0; i < 64*nWords; i++ ) + if ( Abc_TtGetBit( pOffSet, i ) ) + Vec_IntPush( vBits, 0 ), Count[0]++; + else if ( Abc_TtGetBit( pOnSet, i ) ) + Vec_IntPush( vBits, 1 ), Count[1]++; + else + Vec_IntPush( vBits, -1 ); + //printf( "Offset = %d. Onset = %d. Dcset = %d.\n", Count[0], Count[1], 64*nWords - Count[0] - Count[1] ); + return vBits; +} +Gia_SimAbsMan_t * Gia_SimAbsAlloc( Gia_Man_t * pGia, word * pOffSet, word * pOnSet, Vec_Wrd_t * vSims, int nWords, Vec_Int_t * vResub, int fVerbose ) +{ + Gia_SimAbsMan_t * p = ABC_CALLOC( Gia_SimAbsMan_t, 1 ); + p->pGia = pGia; + p->pSet[0] = pOffSet; + p->pSet[1] = pOnSet; + p->nCands = Vec_WrdSize(vSims)/nWords; + p->nWords = nWords; + p->vSims = vSims; + p->vResub = vResub; + p->fVerbose = fVerbose; + p->vValues = Gia_Sim5CollectValues( pOffSet, pOnSet, nWords ); + p->vPatPairs = Vec_IntAlloc( 100 ); + p->vCoverTable = Vec_WrdAlloc( 10000 ); + p->vTtMints = Vec_IntAlloc( 100 ); + assert( Vec_WrdSize(vSims) % nWords == 0 ); + return p; +} +void Gia_SimAbsFree( Gia_SimAbsMan_t * p ) +{ + Vec_IntFree( p->vValues ); + Vec_IntFree( p->vPatPairs ); + Vec_WrdFree( p->vCoverTable ); + Vec_IntFree( p->vTtMints ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_SimAbsCheckSolution( Gia_SimAbsMan_t * p ) +{ + int x, y, z, w, fFound = 0; + assert( Vec_WrdSize(p->vCoverTable) == p->nWordsTable * (p->nCands+1) ); + + Abc_TtClear( p->pTableTemp, p->nWordsTable ); + for ( x = 0; x < Vec_IntSize(p->vPatPairs)/2; x++ ) + Abc_TtXorBit( p->pTableTemp, x ); + + for ( x = 0; x < p->nCands; x++ ) + { + word * pSimTableX = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * x ); + for ( w = 0; w < p->nWordsTable; w++ ) + if ( p->pTableTemp[w] != pSimTableX[w] ) + break; + if ( w == p->nWordsTable ) + { + printf( "Found solution { %d }\n", x ); + fFound = 1; + } + } + if ( fFound ) + return; + + for ( x = 0; x < p->nCands; x++ ) + for ( y = 0; y < x; y++ ) + { + word * pSimTableX = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * x ); + word * pSimTableY = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * y ); + for ( w = 0; w < p->nWordsTable; w++ ) + if ( p->pTableTemp[w] != (pSimTableX[w] | pSimTableY[w]) ) + break; + if ( w == p->nWordsTable ) + { + printf( "Found solution { %d %d }\n", y, x ); + fFound = 1; + } + } + if ( fFound ) + return; + + for ( x = 0; x < p->nCands; x++ ) + for ( y = 0; y < x; y++ ) + for ( z = 0; z < y; z++ ) + { + word * pSimTableX = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * x ); + word * pSimTableY = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * y ); + word * pSimTableZ = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * z ); + for ( w = 0; w < p->nWordsTable; w++ ) + if ( p->pTableTemp[w] != (pSimTableX[w] | pSimTableY[w] | pSimTableZ[w]) ) + break; + if ( w == p->nWordsTable ) + printf( "Found solution { %d %d %d }\n", z, y, x ); + } +} + +void Gia_SimAbsSolve( Gia_SimAbsMan_t * p ) +{ + abctime clk = Abc_Clock(); + int i, k, iPat, iPat2; +/* + Vec_Int_t * vSimPats = Vec_IntDup( p->vPatPairs ); + Vec_IntUniqify( vSimPats ); + printf( "Selected %d pattern pairs contain %d unique patterns.\n", Vec_IntSize(p->vPatPairs)/2, Vec_IntSize(vSimPats) ); + Vec_IntFree( vSimPats ); +*/ + // set up the covering problem + p->nWordsTable = Abc_Bit6WordNum( Vec_IntSize(p->vPatPairs)/2 ); + Vec_WrdFill( p->vCoverTable, p->nWordsTable * (p->nCands + 1), 0 ); + p->pTableTemp = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * p->nCands ); + for ( i = 0; i < p->nCands; i++ ) + { + word * pSimCand = Vec_WrdEntryP( p->vSims, p->nWords * i ); + word * pSimTable = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * i ); + //printf( "%4d : ", i ); + //Extra_PrintBinary( stdout, (word *)pSimCand, p->nCands ); printf( "\n" ); + Vec_IntForEachEntryDouble( p->vPatPairs, iPat, iPat2, k ) + { + assert( Vec_IntEntry(p->vValues, iPat) == 0 ); + assert( Vec_IntEntry(p->vValues, iPat2) == 1 ); + if ( Abc_TtGetBit(pSimCand, iPat) != Abc_TtGetBit(pSimCand, iPat2) ) + Abc_TtXorBit(pSimTable, k/2); + } + assert( k == Vec_IntSize(p->vPatPairs) ); + } + + if ( 0 ) + { + printf( " " ); + for ( i = 0; i < p->nCands; i++ ) + printf( "%d", i % 10 ); + printf( "\n" ); + + Vec_IntForEachEntryDouble( p->vPatPairs, iPat, iPat2, i ) + { + printf( "%4d ", i/2 ); + printf( "%4d ", iPat ); + printf( "%4d ", iPat2 ); + for ( k = 0; k < p->nCands; k++ ) + { + word * pSimTable = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * k ); + printf( "%c", Abc_TtGetBit(pSimTable, i/2) ? '*' : ' ' ); + } + printf( "\n" ); + } + } + + //Gia_SimAbsCheckSolution(p); + + Vec_IntClear( p->vResub ); + Abc_TtClear( p->pTableTemp, p->nWordsTable ); + for ( i = 0; i < Vec_IntSize(p->vPatPairs)/2; i++ ) + Abc_TtXorBit( p->pTableTemp, i ); + + while ( !Abc_TtIsConst0(p->pTableTemp, p->nWordsTable) ) + { + word * pSimTable; + int iArgMax = -1, CostThis, CostMax = -1; + // compute the cost of each column + for ( i = 0; i < p->nCands; i++ ) + { + pSimTable = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * i ); + CostThis = Abc_TtCountOnesVecMask( pSimTable, p->pTableTemp, p->nWordsTable, 0 ); + if ( CostMax >= CostThis ) + continue; + CostMax = CostThis; + iArgMax = i; + } + // find the best column + Vec_IntPush( p->vResub, iArgMax ); + // delete values of this column + pSimTable = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * iArgMax ); + Abc_TtSharp( p->pTableTemp, p->pTableTemp, pSimTable, p->nWordsTable ); + } + if ( p->fVerbose ) + { + printf( "Solution %2d for covering problem [%5d x %5d]: ", Vec_IntSize(p->vResub), Vec_IntSize(p->vPatPairs)/2, p->nCands ); + Vec_IntForEachEntry( p->vResub, iPat, i ) + printf( "%6d ", iPat ); + for ( ; i < 12; i++ ) + printf( " " ); + printf( " " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } +} +int Gia_SimAbsRefine( Gia_SimAbsMan_t * p ) +{ + int i, b, Value, iPat, iMint, iObj, Count = 0; + word ** pFanins = ABC_ALLOC( word *, Vec_IntSize(p->vResub) ); + assert( Vec_IntSize(p->vResub) > 0 ); + Vec_IntForEachEntry( p->vResub, iObj, b ) + pFanins[b] = Vec_WrdEntryP( p->vSims, p->nWords * iObj ); + Vec_IntFill( p->vTtMints, 1 << Vec_IntSize(p->vResub), -1 ); + Vec_IntForEachEntry( p->vValues, Value, i ) + { + if ( Value == -1 ) + continue; + iMint = 0; + for ( b = 0; b < Vec_IntSize(p->vResub); b++ ) + if ( Abc_TtGetBit(pFanins[b], i) ) + iMint |= 1 << b; + iPat = Vec_IntEntry( p->vTtMints, iMint ); + if ( iPat == -1 ) + { + Vec_IntWriteEntry( p->vTtMints, iMint, i ); + continue; + } + assert( Abc_TtGetBit(p->pSet[Value], i) ); + if ( Abc_TtGetBit(p->pSet[Value], iPat) ) + continue; + assert( Abc_TtGetBit(p->pSet[!Value], iPat) ); + Vec_IntPushTwo( p->vPatPairs, Value ? iPat : i, Value ? i : iPat ); + //printf( "iPat1 = %d iPat2 = %d Mint = %d\n", Value ? iPat : i, Value ? i : iPat, iMint ); + Count++; + if ( Count == 64 ) + { + ABC_FREE( pFanins ); + return 1; + } + } + //printf( "Refinement added %d minterm pairs.\n", Count ); + ABC_FREE( pFanins ); + return Count != 0; +} +Vec_Int_t * Gia_SimAbsFind( Vec_Int_t * vValues, int Value ) +{ + Vec_Int_t * vSubset = Vec_IntAlloc( 100 ); int i, Entry; + Vec_IntForEachEntry( vValues, Entry, i ) + if ( Entry == Value ) + Vec_IntPush( vSubset, i ); + return vSubset; +} +void Gia_SimAbsInit( Gia_SimAbsMan_t * p ) +{ + int n, nPairsInit = 64; + Vec_Int_t * vValue0 = Gia_SimAbsFind( p->vValues, 0 ); + Vec_Int_t * vValue1 = Gia_SimAbsFind( p->vValues, 1 ); + Vec_IntClear( p->vPatPairs ); + printf( "There are %d offset and %d onset minterms (%d pairs) and %d divisors.\n", + Vec_IntSize(vValue0), Vec_IntSize(vValue1), Vec_IntSize(vValue0)*Vec_IntSize(vValue1), p->nCands ); + Abc_Random( 1 ); + assert( Vec_IntSize(vValue0) > 0 ); + assert( Vec_IntSize(vValue1) > 0 ); + for ( n = 0; n < nPairsInit; n++ ) + Vec_IntPushTwo( p->vPatPairs, + Vec_IntEntry(vValue0, Abc_Random(0) % Vec_IntSize(vValue0)), + Vec_IntEntry(vValue1, Abc_Random(0) % Vec_IntSize(vValue1)) ); + Vec_IntFree( vValue0 ); + Vec_IntFree( vValue1 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_SimAbsPerformOne( Gia_Man_t * pGia, word * pOffSet, word * pOnSet, Vec_Wrd_t * vSimsCands, int nWords, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Vec_Int_t * vResub = Vec_IntAlloc( 10 ); + Gia_SimAbsMan_t * p = Gia_SimAbsAlloc( pGia, pOffSet, pOnSet, vSimsCands, nWords, vResub, fVerbose ); + Gia_SimAbsInit( p ); + while ( 1 ) + { + Gia_SimAbsSolve( p ); + if ( !Gia_SimAbsRefine( p ) ) + break; + } + Gia_SimAbsFree( p ); + Abc_PrintTime( 1, "Resubstitution time", Abc_Clock() - clk ); + return vResub; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +typedef struct Gia_RsbMan_t_ Gia_RsbMan_t; +struct Gia_RsbMan_t_ +{ + Gia_Man_t * pGia; + word * pOffSet; + word * pOnSet; + int nWords; + int nWordsT; + Vec_Wrd_t * vSims; + Vec_Wrd_t * vSimsT; + Vec_Int_t * vCands; + Vec_Int_t * vObjs; + Vec_Int_t * vObjs2; + Vec_Wec_t * vSets[2]; + word * pSet[3]; + Vec_Int_t * vActive; +}; +Gia_RsbMan_t * Gia_RsbAlloc( Gia_Man_t * pGia, word * pOffSet, word * pOnSet, Vec_Wrd_t * vSims, int nWords, Vec_Wrd_t * vSimsT, int nWordsT, Vec_Int_t * vCands ) +{ + int i, iObj; + Gia_RsbMan_t * p = ABC_CALLOC( Gia_RsbMan_t, 1 ); + assert( nWords <= 1024 ); + assert( Vec_WrdSize(vSims) == 64 * nWords * nWordsT ); + assert( Vec_WrdSize(vSims) == Vec_WrdSize(vSimsT) ); + p->pGia = pGia; + p->pOffSet = pOffSet; + p->pOnSet = pOnSet; + p->nWords = nWords; + p->nWordsT = nWordsT; + p->vSims = vSims; + p->vSimsT = vSimsT; + p->vCands = vCands; + p->vObjs = Vec_IntAlloc( 100 ); + p->vObjs2 = Vec_IntAlloc( 100 ); + p->vSets[0] = Vec_WecAlloc( 1024 ); + p->vSets[1] = Vec_WecAlloc( 1024 ); + p->pSet[0] = ABC_CALLOC( word, nWordsT ); + p->pSet[1] = ABC_CALLOC( word, nWordsT ); + p->pSet[2] = ABC_CALLOC( word, nWordsT ); + p->vActive = Vec_IntAlloc( 100 ); + Vec_IntForEachEntry( vCands, iObj, i ) + { + assert( iObj < nWordsT * 64 ); + Abc_TtSetBit( p->pSet[0], iObj ); + } + Vec_WecPushLevel( p->vSets[0] ); + Vec_WecPushLevel( p->vSets[1] ); + for ( i = 0; i < 64*nWords; i++ ) + { + int Value0 = Abc_TtGetBit( pOffSet, i ); + int Value1 = Abc_TtGetBit( pOnSet, i ); + if ( Value0 && !Value1 ) + Vec_WecPush( p->vSets[0], 0, i ); + else if ( !Value0 && Value1 ) + Vec_WecPush( p->vSets[1], 0, i ); + else assert( !Value0 || !Value1 ); + } + assert( Vec_WecSize(p->vSets[0]) == 1 ); + assert( Vec_WecSize(p->vSets[1]) == 1 ); + Abc_Random( 1 ); + //Extra_PrintBinary2( stdout, (unsigned*)pOffSet, 64*nWords ); printf( "\n" ); + //Extra_PrintBinary2( stdout, (unsigned*)pOnSet, 64*nWords ); printf( "\n" ); + return p; +} +void Gia_RsbFree( Gia_RsbMan_t * p ) +{ + Vec_IntFree( p->vActive ); + Vec_IntFree( p->vObjs ); + Vec_IntFree( p->vObjs2 ); + Vec_WecFree( p->vSets[0] ); + Vec_WecFree( p->vSets[1] ); + ABC_FREE( p->pSet[0] ); + ABC_FREE( p->pSet[1] ); + ABC_FREE( p->pSet[2] ); + ABC_FREE( p ); +} + + +int Gia_RsbCost( Gia_RsbMan_t * p ) +{ + Vec_Int_t * vLevel[2]; int i, Cost = 0; + Vec_WecForEachLevelTwo( p->vSets[0], p->vSets[1], vLevel[0], vLevel[1], i ) + Cost += Vec_IntSize(vLevel[0]) * Vec_IntSize(vLevel[1]); + return Cost; +} +void Gia_RsbPrint( Gia_RsbMan_t * p ) +{ + Vec_Int_t * vLevel[2]; + int n, i, nLeaves = 1 << Vec_IntSize(p->vObjs); + assert( Vec_WecSize(p->vSets[0]) == nLeaves ); + assert( Vec_WecSize(p->vSets[1]) == nLeaves ); + printf( "Database for %d objects and cost %d:\n", Vec_IntSize(p->vObjs), Gia_RsbCost(p) ); + Vec_WecForEachLevelTwo( p->vSets[0], p->vSets[1], vLevel[0], vLevel[1], i ) + { + for ( n = 0; n < 2; n++ ) + { + printf( "%5d : ", i ); + Extra_PrintBinary2( stdout, (unsigned*)&i, Vec_IntSize(p->vObjs) ); printf( " %d ", n ); + Vec_IntPrint( vLevel[n] ); + } + } +} +void Gia_RsbUpdateAdd( Gia_RsbMan_t * p, int iObj ) +{ + int n, i, nLeaves = 1 << Vec_IntSize(p->vObjs); + assert( Vec_WecSize(p->vSets[0]) == nLeaves ); + assert( Vec_WecSize(p->vSets[1]) == nLeaves ); + for ( i = 0; i < nLeaves; i++ ) + { + for ( n = 0; n < 2; n++ ) + { + Vec_Int_t * vLevelN = Vec_WecPushLevel(p->vSets[n]); + Vec_Int_t * vLevel = Vec_WecEntry(p->vSets[n], i); + int iMint, j, k = 0; + Vec_IntForEachEntry( vLevel, iMint, j ) + { + if ( Abc_TtGetBit(Vec_WrdEntryP(p->vSims, p->nWords*iObj), iMint) ) + Vec_IntPush( vLevelN, iMint ); + else + Vec_IntWriteEntry( vLevel, k++, iMint ); + } + Vec_IntShrink( vLevel, k ); + } + } + Vec_IntPush( p->vObjs, iObj ); + assert( Vec_WecSize(p->vSets[0]) == 2*nLeaves ); + assert( Vec_WecSize(p->vSets[1]) == 2*nLeaves ); +} +void Gia_RsbUpdateRemove( Gia_RsbMan_t * p, int Index ) +{ + Vec_Int_t * vLevel[2], * vTemp[2][2]; + int k = 0, m, m2, nLeaves = 1 << Vec_IntSize(p->vObjs); + assert( Index < Vec_IntSize(p->vObjs) ); + assert( Vec_WecSize(p->vSets[0]) == nLeaves ); + assert( Vec_WecSize(p->vSets[1]) == nLeaves ); + for ( m = 0; m < nLeaves; m++ ) + { + if ( m & (1 << Index) ) + continue; + m2 = m ^ (1 << Index); + vTemp[0][0] = Vec_WecEntry(p->vSets[0], m); + vTemp[0][1] = Vec_WecEntry(p->vSets[1], m); + vTemp[1][0] = Vec_WecEntry(p->vSets[0], m2); + vTemp[1][1] = Vec_WecEntry(p->vSets[1], m2); + Vec_IntAppend( vTemp[0][0], vTemp[1][0] ); + Vec_IntAppend( vTemp[0][1], vTemp[1][1] ); + Vec_IntClear( vTemp[1][0] ); + Vec_IntClear( vTemp[1][1] ); + } + Vec_IntDrop( p->vObjs, Index ); + Vec_WecForEachLevelTwo( p->vSets[0], p->vSets[1], vLevel[0], vLevel[1], m ) + { + if ( m & (1 << Index) ) + continue; + ABC_SWAP( Vec_Int_t, Vec_WecArray(p->vSets[0])[k], Vec_WecArray(p->vSets[0])[m] ); + ABC_SWAP( Vec_Int_t, Vec_WecArray(p->vSets[1])[k], Vec_WecArray(p->vSets[1])[m] ); + k++; + } + assert( k == nLeaves/2 ); + Vec_WecShrink( p->vSets[0], k ); + Vec_WecShrink( p->vSets[1], k ); +} +int Gia_RsbRemovalCost( Gia_RsbMan_t * p, int Index ) +{ + Vec_Int_t * vTemp[2][2]; + //unsigned Mask = Abc_InfoMask( Index ); + int m, m2, Cost = 0, nLeaves = 1 << Vec_IntSize(p->vObjs); + assert( Vec_WecSize(p->vSets[0]) == (1 << Vec_IntSize(p->vObjs)) ); + assert( Vec_WecSize(p->vSets[1]) == (1 << Vec_IntSize(p->vObjs)) ); + for ( m = 0; m < nLeaves; m++ ) + { + if ( m & (1 << Index) ) + continue; + m2 = m ^ (1 << Index); + vTemp[0][0] = Vec_WecEntry(p->vSets[0], m); + vTemp[0][1] = Vec_WecEntry(p->vSets[1], m); + vTemp[1][0] = Vec_WecEntry(p->vSets[0], m2); + vTemp[1][1] = Vec_WecEntry(p->vSets[1], m2); + Cost += (Vec_IntSize(vTemp[0][0]) + Vec_IntSize(vTemp[1][0])) * (Vec_IntSize(vTemp[0][1]) + Vec_IntSize(vTemp[1][1])); + } + return Cost; +} +int Gia_RsbFindNodeToRemove( Gia_RsbMan_t * p, int * pMinCost ) +{ + int i, iObj, iMin = -1, CostMin = ABC_INFINITY; + Vec_IntForEachEntry( p->vObjs, iObj, i ) + { + int Cost = Gia_RsbRemovalCost( p, i ); + if ( CostMin > Cost ) + { + CostMin = Cost; + iMin = i; + } + } + if ( pMinCost ) + *pMinCost = CostMin; + return iMin; +} + +void Gia_RsbFindMints( Gia_RsbMan_t * p, int * pMint0, int * pMint1 ) +{ + int iSetI = Abc_Random(0) % Vec_IntSize(p->vActive); + int iSet = Vec_IntEntry( p->vActive, iSetI ); + Vec_Int_t * vArray0 = Vec_WecEntry(p->vSets[0], iSet); + Vec_Int_t * vArray1 = Vec_WecEntry(p->vSets[1], iSet); + int iMint0i = Abc_Random(0) % Vec_IntSize(vArray0); + int iMint1i = Abc_Random(0) % Vec_IntSize(vArray1); + int iMint0 = Vec_IntEntry( vArray0, iMint0i ); + int iMint1 = Vec_IntEntry( vArray1, iMint1i ); + *pMint0 = iMint0; + *pMint1 = iMint1; +} +int Gia_RsbFindNode( Gia_RsbMan_t * p ) +{ + int i, iObj, nNodes, nNodesNew = -1, nNodesOld = -1, Mint0, Mint1, Shift; + Abc_TtCopy( p->pSet[1], p->pSet[0], p->nWordsT, 0 ); + Vec_IntForEachEntry( p->vObjs, iObj, i ) + { + assert( Abc_TtGetBit(p->pSet[1], iObj) ); + Abc_TtXorBit(p->pSet[1], iObj); + } + Abc_TtCopy( p->pSet[2], p->pSet[1], p->nWordsT, 0 ); + Gia_RsbFindMints( p, &Mint0, &Mint1 ); + nNodes = Abc_TtAndXorSum( p->pSet[1], Vec_WrdEntryP(p->vSimsT, p->nWordsT*Mint0), Vec_WrdEntryP(p->vSimsT, p->nWordsT*Mint1), p->nWordsT ); + for ( i = 0; i < 5 && nNodes > 1; i++ ) + { + nNodesOld = nNodes; + Abc_TtCopy( p->pSet[2], p->pSet[1], p->nWordsT, 0 ); + Gia_RsbFindMints( p, &Mint0, &Mint1 ); + nNodesNew = Abc_TtAndXorSum( p->pSet[1], Vec_WrdEntryP(p->vSimsT, p->nWordsT*Mint0), Vec_WrdEntryP(p->vSimsT, p->nWordsT*Mint1), p->nWordsT ); + assert( nNodesNew <= nNodes ); + if ( nNodesNew < nNodes ) + i = 0; + nNodes = nNodesNew; + } + Shift = Abc_Random(0) % (64*p->nWordsT); + for ( i = 0; i < 64*p->nWordsT; i++ ) + { + int Index = (i+Shift) % (64*p->nWordsT); + if ( Abc_TtGetBit( p->pSet[2], Index ) ) + return Index; + } + assert( 0 ); + return -1; +} +int Gia_RsbCollectValid( Gia_RsbMan_t * p ) +{ + Vec_Int_t * vLevel[2]; int i; + Vec_IntClear( p->vActive ); + assert( Vec_WecSize(p->vSets[0]) == Vec_WecSize(p->vSets[1]) ); + Vec_WecForEachLevelTwo( p->vSets[0], p->vSets[1], vLevel[0], vLevel[1], i ) + if ( Vec_IntSize(vLevel[0]) && Vec_IntSize(vLevel[1]) ) + Vec_IntPush( p->vActive, i ); + if ( Vec_IntSize(p->vActive) == 0 ) + return 0; + return 1; +} +Vec_Int_t * Gia_RsbSolve( Gia_RsbMan_t * p ) +{ + int i, iMin; + Vec_IntClear( p->vObjs ); + while ( Gia_RsbCollectValid(p) ) + Gia_RsbUpdateAdd( p, Gia_RsbFindNode(p) ); + for ( i = 0; i < 100; i++ ) + { + int k, nUndo = 1 + Abc_Random(0) % Vec_IntSize(p->vObjs); + for ( k = 0; k < nUndo; k++ ) + { + iMin = Gia_RsbFindNodeToRemove( p, NULL );// &MinCost ); + Gia_RsbUpdateRemove( p, iMin ); + } + while ( Gia_RsbCollectValid(p) ) + Gia_RsbUpdateAdd( p, Gia_RsbFindNode(p) ); + if ( Vec_IntSize(p->vObjs2) == 0 || Vec_IntSize(p->vObjs2) > Vec_IntSize(p->vObjs) ) + { + Vec_IntClear( p->vObjs2 ); + Vec_IntAppend( p->vObjs2, p->vObjs ); + } + } + //Gia_RsbPrint( p ); + return Vec_IntDup( p->vObjs2 ); +} +Vec_Int_t * Gia_RsbSetFind( word * pOffSet, word * pOnSet, Vec_Wrd_t * vSims, int nWords, Vec_Wrd_t * vSimsT, int nWordsT, Vec_Int_t * vCands ) +{ + Gia_RsbMan_t * p = Gia_RsbAlloc( NULL, pOffSet, pOnSet, vSims, nWords, vSimsT, nWordsT, vCands ); + Vec_Int_t * vObjs = Gia_RsbSolve( p ); + Gia_RsbFree( p ); + Vec_IntSort( vObjs, 0 ); + return vObjs; +} + +/**Function************************************************************* + + Synopsis [Improving quality of simulation patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_SimQualityOne( Gia_Man_t * p, Vec_Int_t * vPat, int fPoOnly ) +{ + int i, Id, Value, nWords = Abc_Bit6WordNum( 1+Gia_ManCiNum(p) ); + Vec_Wrd_t * vTemp, * vSims, * vSimsPi = Vec_WrdStart( Gia_ManCiNum(p) * nWords ); + Vec_Int_t * vRes; + assert( Vec_IntSize(vPat) == Gia_ManCiNum(p) ); + Vec_IntForEachEntry( vPat, Value, i ) + { + word * pSim = Vec_WrdEntryP( vSimsPi, i*nWords ); + if ( Value ) + Abc_TtFill( pSim, nWords ); + Abc_TtXorBit( pSim, i+1 ); + } + vTemp = p->vSimsPi; + p->vSimsPi = vSimsPi; + vSims = Gia_ManSimPatSim( p ); + p->vSimsPi = vTemp; + if ( fPoOnly ) + { + vRes = Vec_IntStart( Gia_ManCoNum(p) ); + Gia_ManForEachCoId( p, Id, i ) + { + word * pSim = Vec_WrdEntryP( vSims, Id*nWords ); + if ( pSim[0] & 1 ) + Abc_TtNot( pSim, nWords ); + Vec_IntWriteEntry( vRes, i, Abc_TtCountOnesVec(pSim, nWords) ); + } + assert( Vec_IntSize(vRes) == Gia_ManCoNum(p) ); + } + else + { + vRes = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManForEachAndId( p, Id ) + { + word * pSim = Vec_WrdEntryP( vSims, Id*nWords ); + if ( pSim[0] & 1 ) + Abc_TtNot( pSim, nWords ); + Vec_IntWriteEntry( vRes, Id, Abc_TtCountOnesVec(pSim, nWords) ); + } + assert( Vec_IntSize(vRes) == Gia_ManObjNum(p) ); + } + Vec_WrdFree( vSims ); + Vec_WrdFree( vSimsPi ); + return vRes; +} +void Gia_SimQualityTest( Gia_Man_t * p ) +{ + Vec_Int_t * vPat, * vRes; + int k, m, nMints = (1 << Gia_ManCiNum(p)); + assert( Gia_ManCiNum(p) <= 10 ); + for ( m = 0; m < nMints; m++ ) + { + printf( "%d : ", m ); + Extra_PrintBinary( stdout, (unsigned*)&m, Gia_ManCiNum(p) ); + printf( " " ); + vPat = Vec_IntAlloc( Gia_ManCiNum(p) ); + for ( k = 0; k < Gia_ManCiNum(p); k++ ) + Vec_IntPush( vPat, (m >> k) & 1 ); + vRes = Gia_SimQualityOne( p, vPat, 1 ); + printf( "%d ", Vec_IntSum(vRes) ); + Vec_IntFree( vRes ); + Vec_IntFree( vPat ); + printf( "\n" ); + } +} +Vec_Int_t * Gia_SimGenerateStats( Gia_Man_t * p ) +{ + Vec_Int_t * vTotal = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vRes, * vPat; + int i, k, Value; + Abc_Random(1); + for ( i = 0; i < 1000; i++ ) + { + vPat = Vec_IntAlloc( Gia_ManCiNum(p) ); + for ( k = 0; k < Gia_ManCiNum(p); k++ ) + Vec_IntPush( vPat, Abc_Random(0) & 1 ); + vRes = Gia_SimQualityOne( p, vPat, 0 ); + assert( Vec_IntSize(vRes) == Gia_ManObjNum(p) ); + Vec_IntForEachEntry( vRes, Value, k ) + Vec_IntAddToEntry( vTotal, k, Value ); + Vec_IntFree( vRes ); + Vec_IntFree( vPat ); + } + //Vec_IntPrint( vTotal ); + return vTotal; +} +double Gia_SimComputeScore( Gia_Man_t * p, Vec_Int_t * vTotal, Vec_Int_t * vThis ) +{ + double TotalScore = 0; + int i, Total, This; + assert( Vec_IntSize(vTotal) == Vec_IntSize(vThis) ); + Vec_IntForEachEntryTwo( vTotal, vThis, Total, This, i ) + { + if ( Total == 0 ) + Total = 1; + TotalScore += 1000.0*This/Total; + } + return TotalScore == 0 ? 1.0 : TotalScore/Gia_ManAndNum(p); +} +int Gia_SimQualityPatternsMax( Gia_Man_t * p, Vec_Int_t * vPat, int Iter, int fVerbose, Vec_Int_t * vStats ) +{ + int k, MaxIn = -1; + Vec_Int_t * vTries = Vec_IntAlloc( 100 ); + Vec_Int_t * vRes = Gia_SimQualityOne( p, vPat, 0 ); + double Value, InitValue, MaxValue = InitValue = Gia_SimComputeScore( p, vStats, vRes ); + Vec_IntFree( vRes ); + + if ( fVerbose ) + printf( "Iter %5d : Init = %6.3f ", Iter, InitValue ); + + for ( k = 0; k < Gia_ManCiNum(p); k++ ) + { + Vec_IntArray(vPat)[k] ^= 1; + //Vec_IntPrint( vPat ); + + vRes = Gia_SimQualityOne( p, vPat, 0 ); + Value = Gia_SimComputeScore( p, vStats, vRes ); + if ( MaxValue <= Value ) + { + if ( MaxValue < Value ) + Vec_IntClear( vTries ); + Vec_IntPush( vTries, k ); + MaxValue = Value; + MaxIn = k; + } + Vec_IntFree( vRes ); + + Vec_IntArray(vPat)[k] ^= 1; + } + MaxIn = Vec_IntSize(vTries) ? Vec_IntEntry( vTries, rand()%Vec_IntSize(vTries) ) : -1; + if ( fVerbose ) + { + printf( "Final = %6.3f Ratio = %4.2f Tries = %5d ", MaxValue, MaxValue/InitValue, Vec_IntSize(vTries) ); + printf( "Choosing %5d\r", MaxIn ); + } + Vec_IntFree( vTries ); + return MaxIn; +} +Vec_Int_t * Gia_ManPatCollectOne( Gia_Man_t * p, Vec_Wrd_t * vPatterns, int n, int nWords ) +{ + Vec_Int_t * vPat = Vec_IntAlloc( Gia_ManCiNum(p) ); int k; + for ( k = 0; k < Gia_ManCiNum(p); k++ ) + Vec_IntPush( vPat, Abc_TtGetBit( Vec_WrdEntryP(vPatterns, k*nWords), n ) ); + return vPat; +} +void Gia_ManPatUpdateOne( Gia_Man_t * p, Vec_Wrd_t * vPatterns, int n, int nWords, Vec_Int_t * vPat ) +{ + int k, Value; + Vec_IntForEachEntry( vPat, Value, k ) + { + word * pSim = Vec_WrdEntryP( vPatterns, k*nWords ); + if ( Abc_TtGetBit(pSim, n) != Value ) + Abc_TtXorBit( pSim, n ); + } +} +void Gia_ManPatDistImprove( Gia_Man_t * p, int fVerbose ) +{ + int n, k, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + double InitValue, InitTotal = 0, FinalValue, FinalTotal = 0; + Vec_Int_t * vPat, * vRes, * vStats = Gia_SimGenerateStats( p ); + Vec_Wrd_t * vPatterns = p->vSimsPi; p->vSimsPi = NULL; + Abc_Random(1); + for ( n = 0; n < 64*nWords; n++ ) + { + abctime clk = Abc_Clock(); +// if ( n == 32 ) +// break; + + vPat = Gia_ManPatCollectOne( p, vPatterns, n, nWords ); + vRes = Gia_SimQualityOne( p, vPat, 0 ); + InitValue = Gia_SimComputeScore(p, vStats, vRes); + InitTotal += InitValue; + Vec_IntFree( vRes ); + + for ( k = 0; k < 100; k++ ) + { + int MaxIn = Gia_SimQualityPatternsMax( p, vPat, k, fVerbose, vStats ); + if ( MaxIn == -1 ) + break; + assert( MaxIn >= 0 && MaxIn < Gia_ManCiNum(p) ); + Vec_IntArray(vPat)[MaxIn] ^= 1; + } + //Vec_IntPrint( vPat ); + + vRes = Gia_SimQualityOne( p, vPat, 0 ); + FinalValue = Gia_SimComputeScore(p, vStats, vRes); + FinalTotal += FinalValue; + Vec_IntFree( vRes ); + + if ( fVerbose ) + { + printf( "Pat %5d : Tries = %5d InitValue = %6.3f FinalValue = %6.3f Ratio = %4.2f ", + n, k, InitValue, FinalValue, FinalValue/InitValue ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + + Gia_ManPatUpdateOne( p, vPatterns, n, nWords, vPat ); + Vec_IntFree( vPat ); + } + Vec_IntFree( vStats ); + if ( fVerbose ) + printf( "\n" ); + printf( "Improved %d patterns with average init value %.2f and average final value %.2f.\n", + 64*nWords, 1.0*InitTotal/(64*nWords), 1.0*FinalTotal/(64*nWords) ); + p->vSimsPi = vPatterns; +} + +/**Function************************************************************* + + Synopsis [Improving quality of simulation patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_SimCollectRare( Gia_Man_t * p, Vec_Wrd_t * vPatterns, int RareLimit ) +{ + Vec_Int_t * vRareCounts = Vec_IntAlloc( 100 ); // (node, rare_count) pairs + int Id, nWords = Vec_WrdSize(vPatterns) / Gia_ManCiNum(p), TotalBits = 64*nWords; + Vec_Wrd_t * vSims, * vTemp = p->vSimsPi; + assert( Vec_WrdSize(vPatterns) % Gia_ManCiNum(p) == 0 ); + p->vSimsPi = vPatterns; + vSims = Gia_ManSimPatSim( p ); + p->vSimsPi = vTemp; + Gia_ManForEachAndId( p, Id ) + { + word * pSim = Vec_WrdEntryP( vSims, Id*nWords ); + int Count = Abc_TtCountOnesVec( pSim, nWords ); + int fRareOne = Count < TotalBits/2; // fRareOne is 1 if rare value is 1 + int CountRare = fRareOne ? Count : TotalBits - Count; + assert( CountRare <= TotalBits/2 ); + if ( CountRare <= RareLimit ) + Vec_IntPushTwo( vRareCounts, Abc_Var2Lit(Id, fRareOne), CountRare ); + } + Vec_WrdFree( vSims ); + return vRareCounts; +} +Vec_Flt_t * Gia_SimQualityImpact( Gia_Man_t * p, Vec_Int_t * vPat, Vec_Int_t * vRareCounts ) +{ + Vec_Flt_t * vQuoIncs = Vec_FltStart( Gia_ManCiNum(p) ); + int nWordsNew = Abc_Bit6WordNum( 1+Gia_ManCiNum(p) ); + Vec_Wrd_t * vSimsPiNew = Vec_WrdStart( Gia_ManCiNum(p) * nWordsNew ); + Vec_Wrd_t * vTemp, * vSims; + int i, k, Value, RareLit, RareCount; + assert( Vec_IntSize(vPat) == Gia_ManCiNum(p) ); + Vec_IntForEachEntry( vPat, Value, i ) + { + word * pSim = Vec_WrdEntryP( vSimsPiNew, i*nWordsNew ); + if ( Value ) + Abc_TtFill( pSim, nWordsNew ); + Abc_TtXorBit( pSim, i+1 ); + } + vTemp = p->vSimsPi; + p->vSimsPi = vSimsPiNew; + vSims = Gia_ManSimPatSim( p ); + p->vSimsPi = vTemp; + Vec_IntForEachEntryDouble( vRareCounts, RareLit, RareCount, i ) + { + float Incrm = (float)1.0/(RareCount+1); + int RareObj = Abc_Lit2Var(RareLit); + int RareVal = Abc_LitIsCompl(RareLit); + word * pSim = Vec_WrdEntryP( vSims, RareObj*nWordsNew ); + int OrigVal = pSim[0] & 1; + if ( OrigVal ) + Abc_TtNot( pSim, nWordsNew ); + for ( k = 0; k < Gia_ManCiNum(p); k++ ) + if ( Abc_TtGetBit(pSim, k+1) ) // value changed + Vec_FltAddToEntry( vQuoIncs, k, OrigVal != RareVal ? Incrm : -Incrm ); + } + Vec_WrdFree( vSims ); + Vec_WrdFree( vSimsPiNew ); + return vQuoIncs; +} +Vec_Int_t * Gia_SimCollectBest( Vec_Flt_t * vQuo ) +{ + Vec_Int_t * vRes; int i; + float Value, ValueMax = Vec_FltFindMax( vQuo ); + if ( ValueMax <= 0 ) + return NULL; + vRes = Vec_IntAlloc( 100 ); // variables with max quo + Vec_FltForEachEntry( vQuo, Value, i ) + if ( Value == ValueMax ) + Vec_IntPush( vRes, i ); + return vRes; +} +float Gia_ManPatGetQuo( Gia_Man_t * p, Vec_Int_t * vRareCounts, Vec_Wrd_t * vSims, int n, int nWords ) +{ + float Quality = 0; + int RareLit, RareCount, i; + assert( Vec_WrdSize(vSims) == Gia_ManObjNum(p) ); + Vec_IntForEachEntryDouble( vRareCounts, RareLit, RareCount, i ) + { + float Incrm = (float)1.0/(RareCount+1); + int RareObj = Abc_Lit2Var(RareLit); + int RareVal = Abc_LitIsCompl(RareLit); + word * pSim = Vec_WrdEntryP( vSims, RareObj*nWords ); + if ( Abc_TtGetBit(pSim, n) == RareVal ) + Quality += Incrm; + } + return Quality; +} +float Gia_ManPatGetTotalQuo( Gia_Man_t * p, int RareLimit, Vec_Wrd_t * vPatterns, int nWords ) +{ + float Total = 0; int n; + Vec_Int_t * vRareCounts = Gia_SimCollectRare( p, vPatterns, RareLimit ); + Vec_Wrd_t * vSims, * vTemp = p->vSimsPi; + p->vSimsPi = vPatterns; + vSims = Gia_ManSimPatSim( p ); + p->vSimsPi = vTemp; + for ( n = 0; n < 64*nWords; n++ ) + Total += Gia_ManPatGetQuo( p, vRareCounts, vSims, n, nWords ); + Vec_IntFree( vRareCounts ); + Vec_WrdFree( vSims ); + return Total; +} +float Gia_ManPatGetOneQuo( Gia_Man_t * p, int RareLimit, Vec_Wrd_t * vPatterns, int nWords, int n ) +{ + float Total = 0; + Vec_Int_t * vRareCounts = Gia_SimCollectRare( p, vPatterns, RareLimit ); + Vec_Wrd_t * vSims, * vTemp = p->vSimsPi; + p->vSimsPi = vPatterns; + vSims = Gia_ManSimPatSim( p ); + p->vSimsPi = vTemp; + Total += Gia_ManPatGetQuo( p, vRareCounts, vSims, n, nWords ); + Vec_IntFree( vRareCounts ); + Vec_WrdFree( vSims ); + return Total; +} +void Gia_ManPatRareImprove( Gia_Man_t * p, int RareLimit, int fVerbose ) +{ + abctime clk = Abc_Clock(); + float FinalTotal, InitTotal; + int n, nRares = 0, nChanges = 0, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + Vec_Wrd_t * vPatterns = p->vSimsPi; p->vSimsPi = NULL; + InitTotal = Gia_ManPatGetTotalQuo( p, RareLimit, vPatterns, nWords ); + for ( n = 0; n < 64*nWords; n++ ) + { + abctime clk = Abc_Clock(); + Vec_Int_t * vRareCounts = Gia_SimCollectRare( p, vPatterns, RareLimit ); + Vec_Int_t * vPat = Gia_ManPatCollectOne( p, vPatterns, n, nWords ); + Vec_Flt_t * vQuoIncs = Gia_SimQualityImpact( p, vPat, vRareCounts ); + Vec_Int_t * vBest = Gia_SimCollectBest( vQuoIncs ); + if ( fVerbose ) + { + float PatQuo = Gia_ManPatGetOneQuo( p, RareLimit, vPatterns, nWords, n ); + printf( "Pat %5d : Rare = %4d Cands = %3d Value = %8.3f Change = %8.3f ", + n, Vec_IntSize(vRareCounts)/2, vBest ? Vec_IntSize(vBest) : 0, + PatQuo, vBest ? Vec_FltEntry(vQuoIncs, Vec_IntEntry(vBest,0)) : 0 ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + if ( vBest != NULL ) + { + int VarBest = Vec_IntEntry( vBest, rand()%Vec_IntSize(vBest) ); + Abc_TtXorBit( Vec_WrdEntryP(vPatterns, VarBest*nWords), n ); + nChanges++; + } + nRares = Vec_IntSize(vRareCounts)/2; + Vec_IntFree( vRareCounts ); + Vec_IntFree( vPat ); + Vec_FltFree( vQuoIncs ); + Vec_IntFreeP( &vBest ); + } + if ( fVerbose ) + printf( "\n" ); + FinalTotal = Gia_ManPatGetTotalQuo( p, RareLimit, vPatterns, nWords ); + p->vSimsPi = vPatterns; + + printf( "Improved %d out of %d patterns using %d rare nodes: %.2f -> %.2f. ", + nChanges, 64*nWords, nRares, InitTotal, FinalTotal ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Trying vectorized simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimTest( Gia_Man_t * pGia ) +{ + int n, nWords = 4; + Vec_Wrd_t * vSim1, * vSim2; + Vec_Wrd_t * vSim0 = Vec_WrdStartRandom( Gia_ManCiNum(pGia) * nWords ); + abctime clk = Abc_Clock(); + + pGia->vSimsPi = vSim0; + for ( n = 0; n < 20; n++ ) + { + vSim1 = Gia_ManSimPatSim( pGia ); + Vec_WrdFree( vSim1 ); + } + Abc_PrintTime( 1, "Time1", Abc_Clock() - clk ); + + clk = Abc_Clock(); + for ( n = 0; n < 20; n++ ) + { + vSim2 = Gia_ManSimPatSim2( pGia ); + Vec_WrdFree( vSim2 ); + } + Abc_PrintTime( 1, "Time2", Abc_Clock() - clk ); + + pGia->vSimsPi = NULL; + Vec_WrdFree( vSim0 ); +} + +/**Function************************************************************* + + Synopsis [Trying compiled simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimGen( Gia_Man_t * pGia ) +{ + int nWords = 4; + Gia_Obj_t * pObj; + Vec_Wrd_t * vSim0 = Vec_WrdStartRandom( Gia_ManCiNum(pGia) * nWords ); + FILE * pFile = fopen( "comp_sim.c", "wb" ); + int i, k, Id; + fprintf( pFile, "#include \n" ); + fprintf( pFile, "#include \n" ); + fprintf( pFile, "#include \n" ); + fprintf( pFile, "int main()\n" ); + fprintf( pFile, "{\n" ); + fprintf( pFile, " clock_t clkThis = clock();\n" ); + fprintf( pFile, " unsigned long Res = 0;\n" ); + fprintf( pFile, " int i;\n" ); + fprintf( pFile, " srand(time(NULL));\n" ); + fprintf( pFile, " for ( i = 0; i < 2000; i++ )\n" ); + fprintf( pFile, " {\n" ); + for ( k = 0; k < nWords; k++ ) + fprintf( pFile, " unsigned long s%07d_%d = 0x%08x%08x;\n", 0, k, 0, 0 ); + Gia_ManForEachCiId( pGia, Id, i ) + { + //word * pSim = Vec_WrdEntryP(vSim0, i*nWords); + //unsigned * pSimU = (unsigned *)pSim; + for ( k = 0; k < nWords; k++ ) + fprintf( pFile, " unsigned long s%07d_%d = ((unsigned long)rand() << 48) | ((unsigned long)rand() << 32) | ((unsigned long)rand() << 16) | (unsigned long)rand();\n", Id, k ); + } + Gia_ManForEachAnd( pGia, pObj, Id ) + { + for ( k = 0; k < nWords; k++ ) + fprintf( pFile, " unsigned long s%07d_%d = %cs%07d_%d & %cs%07d_%d;\n", Id, k, + Gia_ObjFaninC0(pObj) ? '~' : ' ', Gia_ObjFaninId0(pObj, Id), k, + Gia_ObjFaninC1(pObj) ? ' ' : '~', Gia_ObjFaninId1(pObj, Id), k ); + } + Gia_ManForEachCoId( pGia, Id, i ) + { + pObj = Gia_ManObj(pGia, Id); + for ( k = 0; k < nWords; k++ ) + fprintf( pFile, " Res ^= %cs%07d_%d;\n", Gia_ObjFaninC0(pObj) ? '~' : ' ', Gia_ObjFaninId0(pObj, Id), k ); + } + Vec_WrdFree( vSim0 ); + fprintf( pFile, " }\n" ); + fprintf( pFile, " printf( \"Res = 0x%%08x \", (unsigned)Res );\n" ); + fprintf( pFile, " printf( \"Time = %%6.2f sec\\n\", (float)(clock() - clkThis)/CLOCKS_PER_SEC );\n" ); + fprintf( pFile, " return 1;\n" ); + fprintf( pFile, "}\n" ); + fclose( pFile ); +} + + +/**Function************************************************************* + + Synopsis [Trying vectorized simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSimTwo( Gia_Man_t * p0, Gia_Man_t * p1, int nWords, int nRounds, int TimeLimit, int fVerbose ) +{ + Vec_Wrd_t * vSim0, * vSim1, * vSim2; + abctime clk = Abc_Clock(); + int n, i, RetValue = 1; + int TimeStop = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + Abc_Clock() : 0; // in CPU ticks + printf( "Simulating %d round with %d machine words.\n", nRounds, nWords ); + Abc_RandomW(0); + for ( n = 0; RetValue && n < nRounds; n++ ) + { + if ( TimeStop && Abc_Clock() > TimeStop ) + { + printf( "Computation timed out after %d seconds and %d rounds.\n", TimeLimit, n ); + break; + } + vSim0 = Vec_WrdStartRandom( Gia_ManCiNum(p0) * nWords ); + p0->vSimsPi = vSim0; + p1->vSimsPi = vSim0; + vSim1 = Gia_ManSimPatSim( p0 ); + vSim2 = Gia_ManSimPatSim( p1 ); + for ( i = 0; i < Gia_ManCoNum(p0); i++ ) + { + word * pSim1 = Vec_WrdEntryP(vSim1, Gia_ObjId(p0, Gia_ManCo(p0, i))*nWords); + word * pSim2 = Vec_WrdEntryP(vSim2, Gia_ObjId(p1, Gia_ManCo(p1, i))*nWords); + if ( memcmp(pSim1, pSim2, sizeof(word)*nWords) ) + { + printf( "Output %d failed simulation at round %d. ", i, n ); + RetValue = 0; + break; + } + } + Vec_WrdFree( vSim1 ); + Vec_WrdFree( vSim2 ); + Vec_WrdFree( vSim0 ); + p0->vSimsPi = NULL; + p1->vSimsPi = NULL; + } + if ( RetValue == 1 ) + printf( "Simulation did not detect a bug. " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Serialization.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSim2ArrayOne( Vec_Wrd_t * vSimsPi, Vec_Int_t * vRes ) +{ + word * pInfo = Vec_WrdArray(vSimsPi); int w, i; + word * pCare = pInfo + Vec_WrdSize(vSimsPi); + Vec_IntClear( vRes ); + for ( w = 0; w < Vec_WrdSize(vSimsPi); w++ ) + if ( pCare[w] ) + for ( i = 0; i < 64; i++ ) + if ( Abc_TtGetBit(pCare, w*64+i) ) + Vec_IntPush( vRes, Abc_Var2Lit(w*64+i, Abc_TtGetBit(pInfo, w*64+i)) ); + Vec_IntPush( vRes, Vec_WrdSize(vSimsPi) ); +} +Vec_Wec_t * Gia_ManSim2Array( Vec_Ptr_t * vSims ) +{ + Vec_Wec_t * vRes = Vec_WecStart( Vec_PtrSize(vSims) ); + Vec_Int_t * vLevel; int i; + Vec_WecForEachLevel( vRes, vLevel, i ) + Gia_ManSim2ArrayOne( (Vec_Wrd_t *)Vec_PtrEntry(vSims, i), vLevel ); + return vRes; +} + +Vec_Wrd_t * Gia_ManArray2SimOne( Vec_Int_t * vRes ) +{ + int i, iLit, nWords = Vec_IntEntryLast(vRes); + Vec_Wrd_t * vSimsPi = Vec_WrdStart( 2*nWords ); + word * pInfo = Vec_WrdArray(vSimsPi); + word * pCare = pInfo + nWords; + Vec_IntPop( vRes ); + Vec_IntForEachEntry( vRes, iLit, i ) + { + Abc_TtXorBit( pCare, Abc_Lit2Var(iLit) ); + if ( Abc_LitIsCompl(iLit) ) + Abc_TtXorBit( pInfo, Abc_Lit2Var(iLit) ); + } + Vec_IntPush( vRes, nWords ); + Vec_WrdShrink( vSimsPi, Vec_WrdSize(vSimsPi)/2 ); + return vSimsPi; +} +Vec_Ptr_t * Gia_ManArray2Sim( Vec_Wec_t * vRes ) +{ + Vec_Ptr_t * vSims = Vec_PtrAlloc( Vec_WecSize(vRes) ); + Vec_Int_t * vLevel; int i; + Vec_WecForEachLevel( vRes, vLevel, i ) + Vec_PtrPush( vSims, Gia_ManArray2SimOne(vLevel) ); + return vSims; +} + +void Gia_ManSimArrayTest( Vec_Wrd_t * vSimsPi ) +{ + Vec_Ptr_t * vTemp = Vec_PtrAlloc( 2 ); + Vec_PtrPushTwo( vTemp, vSimsPi, vSimsPi ); + { + Vec_Wec_t * vRes = Gia_ManSim2Array( vTemp ); + Vec_WecDumpBin( "temp.sims", vRes, 1 ); + { + Vec_Wec_t * vRes = Vec_WecReadBin( "temp.sims", 1 ); + Vec_Ptr_t * vTemp2 = Gia_ManArray2Sim( vRes ); + Vec_Wrd_t * vSimsPi2 = (Vec_Wrd_t *)Vec_PtrEntry( vTemp2, 0 ); + Vec_Wrd_t * vSimsPi3 = (Vec_Wrd_t *)Vec_PtrEntry( vTemp2, 1 ); + + Abc_TtAnd( Vec_WrdArray(vSimsPi), Vec_WrdArray(vSimsPi), Vec_WrdArray(vSimsPi)+Vec_WrdSize(vSimsPi), Vec_WrdSize(vSimsPi), 0 ); + + vSimsPi->nSize *= 2; + vSimsPi2->nSize *= 2; + vSimsPi3->nSize *= 2; + Vec_WrdDumpHex( "test1.hex", vSimsPi, 1, 1 ); + Vec_WrdDumpHex( "test2.hex", vSimsPi2, 1, 1 ); + Vec_WrdDumpHex( "test3.hex", vSimsPi3, 1, 1 ); + vSimsPi->nSize /= 2; + vSimsPi2->nSize /= 2; + vSimsPi3->nSize /= 2; + + if ( Vec_WrdEqual( vSimsPi, vSimsPi2 ) ) + printf( "Success.\n" ); + else + printf( "Failure.\n" ); + if ( Vec_WrdEqual( vSimsPi, vSimsPi3 ) ) + printf( "Success.\n" ); + else + printf( "Failure.\n" ); + Vec_WrdFree( vSimsPi2 ); + Vec_WrdFree( vSimsPi3 ); + Vec_PtrFree( vTemp2 ); + Vec_WecFree( vRes ); + } + Vec_WecFree( vRes ); + } + Vec_PtrFree( vTemp ); +} + + +/**Function************************************************************* + + Synopsis [Serialization.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPtrWrdDumpBin( char * pFileName, Vec_Ptr_t * p, int fVerbose ) +{ + Vec_Wrd_t * vLevel; + int i, nSize, RetValue; + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + nSize = Vec_PtrSize(p); + RetValue = fwrite( &nSize, 1, sizeof(int), pFile ); + Vec_PtrForEachEntry( Vec_Wrd_t *, p, vLevel, i ) + { + nSize = Vec_WrdSize(vLevel); + RetValue += fwrite( &nSize, 1, sizeof(int), pFile ); + RetValue += fwrite( Vec_WrdArray(vLevel), 1, sizeof(word)*nSize, pFile ); + } + fclose( pFile ); + if ( fVerbose ) + printf( "Written %d arrays into file \"%s\".\n", Vec_PtrSize(p), pFileName ); +} +Vec_Ptr_t * Gia_ManPtrWrdReadBin( char * pFileName, int fVerbose ) +{ + Vec_Ptr_t * p = NULL; Vec_Wrd_t * vLevel; int i, nSize, RetValue; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + fseek( pFile, 0, SEEK_END ); + nSize = ftell( pFile ); + if ( nSize == 0 ) + { + printf( "The input file is empty.\n" ); + fclose( pFile ); + return NULL; + } + if ( nSize % (int)sizeof(int) > 0 ) + { + printf( "Cannot read file with integers because it is not aligned at 4 bytes (remainder = %d).\n", nSize % (int)sizeof(int) ); + fclose( pFile ); + return NULL; + } + rewind( pFile ); + RetValue = fread( &nSize, 1, sizeof(int), pFile ); + assert( RetValue == 4 ); + p = Vec_PtrAlloc( nSize ); + for ( i = 0; i < nSize; i++ ) + Vec_PtrPush( p, Vec_WrdAlloc(100) ); + Vec_PtrForEachEntry( Vec_Wrd_t *, p, vLevel, i ) + { + RetValue = fread( &nSize, 1, sizeof(int), pFile ); + assert( RetValue == 4 ); + Vec_WrdFill( vLevel, nSize, 0 ); + RetValue = fread( Vec_WrdArray(vLevel), 1, sizeof(word)*nSize, pFile ); + assert( RetValue == 8*nSize ); + } + fclose( pFile ); + if ( fVerbose ) + printf( "Read %d arrays from file \"%s\".\n", Vec_PtrSize(p), pFileName ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManProcessBuffs( Gia_Man_t * pHie, Vec_Wrd_t * vSimsH, int nWords, Vec_Mem_t * vStore, Vec_Int_t * vLabels ) +{ + Vec_Int_t * vPoSigs = Vec_IntAlloc( Gia_ManBufNum(pHie) ); + Vec_Int_t * vMap; + Vec_Wec_t * vNodes = Vec_WecStart( Gia_ManBufNum(pHie) ); + Gia_Obj_t * pObj; int i, Sig, Value; + Gia_ManForEachBuf( pHie, pObj, i ) + { + word * pSim = Vec_WrdEntryP(vSimsH, Gia_ObjId(pHie, pObj)*nWords); + int fCompl = pSim[0] & 1; + if ( fCompl ) + Abc_TtNot( pSim, nWords ); + Vec_IntPush( vPoSigs, Vec_MemHashInsert(vStore, pSim) ); + if ( fCompl ) + Abc_TtNot( pSim, nWords ); + } + Vec_IntPrint( vPoSigs ); + vMap = Vec_IntStartFull( Vec_MemEntryNum(vStore) ); + Vec_IntForEachEntry( vPoSigs, Sig, i ) + { + assert( Vec_IntEntry(vMap, Sig) == -1 ); + Vec_IntWriteEntry( vMap, Sig, i ); + } + Vec_IntForEachEntry( vLabels, Sig, i ) + { + if ( Sig < 0 ) + continue; + Value = Vec_IntEntry(vMap, Sig); + if ( Value == -1 ) + continue; + assert( Value >= 0 && Value < Gia_ManBufNum(pHie) ); + Vec_WecPush( vNodes, Value, i ); + } + Vec_WecPrint( vNodes, 0 ); + Vec_WecFree( vNodes ); + Vec_IntFree( vMap ); + Vec_IntFree( vPoSigs ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManUpdateCoPhase( Gia_Man_t * pNew, Gia_Man_t * pOld ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManSetPhase( pNew ); + Gia_ManSetPhase( pOld ); + Gia_ManForEachCo( pNew, pObj, i ) + if ( pObj->fPhase ^ Gia_ManCo(pOld, i)->fPhase ) + { + printf( "Updating out %d.\n", i ); + Gia_ObjFlipFaninC0( pObj ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCompareSims( Gia_Man_t * pHie, Gia_Man_t * pFlat, int nWords, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Vec_Wrd_t * vSims = pFlat->vSimsPi = pHie->vSimsPi = Vec_WrdStartRandom( Gia_ManCiNum(pFlat) * nWords ); + Vec_Wrd_t * vSims0 = Gia_ManSimPatSim( pFlat ); + Vec_Wrd_t * vSims1 = Gia_ManSimPatSim( pHie ); + Vec_Int_t * vLabels = Vec_IntStartFull( Gia_ManObjNum(pFlat) ); + Gia_Obj_t * pObj; int fCompl, Value, * pSpot, * pSpot2, i, nC0s = 0, nC1s = 0, nUnique = 0, nFound[3] = {0}, nBoundary = 0, nMatched = 0; + Vec_Mem_t * vStore = Vec_MemAlloc( nWords, 12 ); // 2^12 N-word entries per page + pFlat->vSimsPi = NULL; + pHie->vSimsPi = NULL; + Vec_WrdFree( vSims ); + + printf( "Comparing two AIGs using %d simulation words.\n", nWords ); + printf( "Hierarchical: " ); Gia_ManPrintStats( pHie, NULL ); + printf( "Flat: " ); Gia_ManPrintStats( pFlat, NULL ); + + Vec_MemHashAlloc( vStore, 1 << 12 ); + Gia_ManForEachCand( pFlat, pObj, i ) + { + word * pSim = Vec_WrdEntryP(vSims0, i*nWords); + nC0s += Abc_TtIsConst0(pSim, nWords); + nC1s += Abc_TtIsConst1(pSim, nWords); + fCompl = pSim[0] & 1; + if ( fCompl ) + Abc_TtNot( pSim, nWords ); + Value = Vec_MemHashInsert( vStore, pSim ); + if ( fCompl ) + Abc_TtNot( pSim, nWords ); + Vec_IntWriteEntry( vLabels, i, Value ); + } + nUnique = Vec_MemEntryNum( vStore ); + printf( "Simulating %d patterns through the second (flat) AIG leads to %d unique objects (%.2f %% out of %d). Const0 = %d. Const1 = %d.\n", + 64*nWords, nUnique, 100.0*nUnique/Gia_ManCandNum(pFlat), Gia_ManCandNum(pFlat), nC0s, nC1s ); + + assert( Gia_ManCiNum(pFlat) == Gia_ManCiNum(pHie) ); + Gia_ManForEachCand( pHie, pObj, i ) + { + word * pSim = Vec_WrdEntryP(vSims1, i*nWords); + pSpot = Vec_MemHashLookup( vStore, pSim ); + Abc_TtNot( pSim, nWords ); + pSpot2 = Vec_MemHashLookup( vStore, pSim ); + Abc_TtNot( pSim, nWords ); + nBoundary += Gia_ObjIsBuf(pObj); + if ( *pSpot != -1 || *pSpot2 != -1 ) + { + nMatched++; + continue; + } + //Extra_PrintBinary( stdout, (unsigned *)pSim, 64*nWords ); printf("\n"); + nFound[1] += Gia_ObjIsBuf(pObj); + nFound[2]++; + //if ( Gia_ObjIsBuf(pObj) ) + // printf( "%d(%d) ", i, nBoundary-1 ); + } + Gia_ManProcessBuffs( pHie, vSims1, nWords, vStore, vLabels ); + Vec_MemHashFree( vStore ); + Vec_MemFree( vStore ); + Vec_WrdFree( vSims0 ); + Vec_WrdFree( vSims1 ); + Vec_IntFree( vLabels ); + + printf( "The first (hierarchical) AIG has %d (%.2f %%) matches, %d (%.2f %%) mismatches, including %d (%.2f %%) on the boundary. ", + nMatched, 100.0*nMatched /Abc_MaxInt(1, Gia_ManCandNum(pHie)), + nFound[2], 100.0*nFound[2]/Abc_MaxInt(1, Gia_ManCandNum(pHie)), + nFound[1], 100.0*nFound[1]/Abc_MaxInt(1, nBoundary) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManRelTfos( Gia_Man_t * p, Vec_Int_t * vObjs ) +{ + Gia_Obj_t * pObj; + Vec_Wec_t * vNodes = Vec_WecStart( Vec_IntSize(vObjs)+1 ); + Vec_Int_t * vSigns = Vec_IntStart( Gia_ManObjNum(p) ); + int n, k, i, iObj, * pSigns = Vec_IntArray(vSigns); + assert( Vec_IntSize(vObjs) < 32 ); + Vec_IntForEachEntry( vObjs, iObj, i ) + pSigns[iObj] |= 1 << i; + Gia_ManForEachAnd( p, pObj, i ) + { + if ( pSigns[i] == 0 ) + for ( n = 0; n < 2; n++ ) + pSigns[i] |= pSigns[Gia_ObjFaninId(pObj, i, n)]; + if ( pSigns[i] == 0 ) + continue; + Vec_WecPush( vNodes, Vec_IntSize(vObjs), i ); + for ( k = 0; k < Vec_IntSize(vObjs); k++ ) + if ( (pSigns[i] >> k) & 1 ) + Vec_WecPush( vNodes, k, i ); + } + Vec_IntFree( vSigns ); + return vNodes; +} +Vec_Wrd_t * Gia_ManRelDerive( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wrd_t * vSims ) +{ + int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); Gia_Obj_t * pObj; + int i, m, iVar, iMint = 0, nMints = 1 << Vec_IntSize(vObjs); + Vec_Wrd_t * vCopy = Vec_WrdDup(vSims); Vec_Int_t * vLevel; + Vec_Wrd_t * vRel = Vec_WrdStart( Gia_ManCoNum(p) * nWords * nMints ); + Vec_Wec_t * vNodes = Gia_ManRelTfos( p, vObjs ); + Vec_WecPrint( vNodes, 0 ); + Gia_ManForEachAnd( p, pObj, i ) + assert( pObj->fPhase == 0 ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->fPhase = 1; + vLevel = Vec_WecEntry( vNodes, Vec_IntSize(vObjs) ); + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + if ( pObj->fPhase ) + Abc_TtClear( Vec_WrdEntryP(vCopy, Gia_ObjId(p, pObj)*nWords), nWords ); + else + Gia_ManSimPatSimAnd( p, Gia_ObjId(p, pObj), pObj, nWords, vCopy ); + for ( m = 0; m < nMints; m++ ) + { + Gia_ManForEachCo( p, pObj, i ) + { + word * pSimO = Vec_WrdEntryP(vCopy, Gia_ObjId(p, pObj)*nWords); + word * pSimF = Vec_WrdEntryP(vCopy, Gia_ObjFaninId0p(p, pObj)*nWords); + word * pSimR = Vec_WrdEntryP(vRel, (iMint*Gia_ManCoNum(p) + i)*nWords); + Abc_TtXor( pSimR, pSimF, pSimO, nWords, Gia_ObjFaninC0(pObj) ); + } + if ( m == nMints-1 ) + break; + iVar = Abc_TtSuppFindFirst( (m+1) ^ ((m+1) >> 1) ^ (m) ^ ((m) >> 1) ); + vLevel = Vec_WecEntry( vNodes, iVar ); + assert( Vec_IntEntry(vLevel, 0) == Vec_IntEntry(vObjs, iVar) ); + Abc_TtNot( Vec_WrdEntryP(vCopy, Vec_IntEntry(vObjs, iVar)*nWords), nWords ); + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + if ( !pObj->fPhase ) + Gia_ManSimPatSimAnd( p, Gia_ObjId(p, pObj), pObj, nWords, vCopy ); + iMint ^= 1 << iVar; + } + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->fPhase = 0; + Vec_WrdFree( vCopy ); + Vec_WecFree( vNodes ); + return vRel; +} +Vec_Wrd_t * Gia_ManRelDerive2( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wrd_t * vSims ) +{ + int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); Gia_Obj_t * pObj; + int i, Id, m, Index, nMints = 1 << Vec_IntSize(vObjs); + Vec_Wrd_t * vPos, * vRel = Vec_WrdStart( Gia_ManCoNum(p) * nWords * nMints ); + for ( m = 0; m < nMints; m++ ) + { + Gia_Man_t * pNew = Gia_ManDup( p ); + Gia_ManForEachAnd( pNew, pObj, i ) + { + if ( (Index = Vec_IntFind(vObjs, Gia_ObjFaninId0(pObj, i))) >= 0 ) + pObj->iDiff0 = i, pObj->fCompl0 ^= (m >> Index) & 1; + if ( (Index = Vec_IntFind(vObjs, Gia_ObjFaninId1(pObj, i))) >= 0 ) + pObj->iDiff1 = i, pObj->fCompl1 ^= (m >> Index) & 1; + } + vPos = Gia_ManSimPatSimOut( pNew, p->vSimsPi, 1 ); + Gia_ManForEachCoId( p, Id, i ) + Abc_TtXor( Vec_WrdEntryP(vRel, (m*Gia_ManCoNum(p) + i)*nWords), Vec_WrdEntryP(vPos, i*nWords), Vec_WrdEntryP(vSims, Id*nWords), nWords, 0 ); + Vec_WrdFree( vPos ); + Gia_ManStop( pNew ); + } + return vRel; +} +void Gia_ManRelPrint( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wrd_t * vSims, Vec_Wrd_t * vRel ) +{ + int w, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + int i, Id, m, nMints = 1 << Vec_IntSize(vObjs); + printf( "Relation has %d inputs and %d outputs:\n", Gia_ManCiNum(p), Vec_IntSize(vObjs) ); + for ( w = 0; w < 64*nWords; w++ ) + { + Gia_ManForEachCiId( p, Id, i ) + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) ); + printf( " " ); + Vec_IntForEachEntry( vObjs, Id, i ) + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) ); + printf( " " ); + Gia_ManForEachCoId( p, Id, i ) + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) ); + printf( " " ); + for ( m = 0; m < nMints; m++ ) + { + printf( " " ); + for ( i = 0; i < Vec_IntSize(vObjs); i++ ) + printf( "%d", (m >> i) & 1 ); + printf( "=" ); + Gia_ManForEachCoId( p, Id, i ) + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vRel, (m*Gia_ManCoNum(p)+i)*nWords), w) ); + } + printf( "\n" ); + } +} +void Gia_ManRelPrint2( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wrd_t * vSims, Vec_Wrd_t * vRel ) +{ + int w, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + int i, Id, m, nMints = 1 << Vec_IntSize(vObjs); + int nWordsM = Abc_Truth6WordNum(Vec_IntSize(vObjs)); + Vec_Wrd_t * vRes = Vec_WrdStart( 64*nWords * nWordsM ); + printf( "Relation has %d inputs and %d outputs:\n", Gia_ManCiNum(p), Vec_IntSize(vObjs) ); + for ( w = 0; w < 64*nWords; w++ ) + { + int iMint = 0; + int nValid = 0; + Gia_ManForEachCiId( p, Id, i ) + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) ); + printf( " " ); + Vec_IntForEachEntry( vObjs, Id, i ) + { + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) ); + if ( Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) ) + iMint |= 1 << i; + } + printf( " " ); + Gia_ManForEachCoId( p, Id, i ) + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) ); + printf( " " ); + for ( m = 0; m < nMints; m++ ) + { + int Count = 0; + Gia_ManForEachCoId( p, Id, i ) + Count += Abc_TtGetBit(Vec_WrdEntryP(vRel, (m*Gia_ManCoNum(p)+i)*nWords), w); + printf( "%d", Count == 0 ); + nValid += Count > 0; + if ( Count == 0 ) + Abc_TtSetBit( Vec_WrdEntryP(vRes, w*nWordsM), m ); + } + printf( " " ); + for ( m = 0; m < nMints; m++ ) + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vRes, w*nWordsM), m) ); + printf( " " ); + assert( Abc_TtGetBit(Vec_WrdEntryP(vRes, w*nWordsM), iMint) ); + for ( i = 0; i < Vec_IntSize(vObjs); i++ ) + if ( Abc_TtGetBit(Vec_WrdEntryP(vRes, w*nWordsM), iMint ^ (1 << i)) ) + printf( "-" ); + else + printf( "%d", (iMint >> i) & 1 ); + printf( " %d", nMints-nValid ); + printf( "\n" ); + } + Vec_WrdFree( vRes ); +} +Vec_Int_t * Gia_ManRelInitObjs() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + /* + Vec_IntPush( vRes, 33 ); + Vec_IntPush( vRes, 52 ); + Vec_IntPush( vRes, 53 ); + Vec_IntPush( vRes, 65 ); + Vec_IntPush( vRes, 79 ); + Vec_IntPush( vRes, 81 ); + */ + /* + Vec_IntPush( vRes, 60 ); + Vec_IntPush( vRes, 61 ); + Vec_IntPush( vRes, 71 ); + Vec_IntPush( vRes, 72 ); + */ + /* + Vec_IntPush( vRes, 65 ); + Vec_IntPush( vRes, 79 ); + Vec_IntPush( vRes, 81 ); + */ + Vec_IntPush( vRes, 52 ); + Vec_IntPush( vRes, 54 ); + Vec_IntPrint( vRes ); + return vRes; +} +void Gia_ManRelDeriveTest2( Gia_Man_t * p ) +{ + Vec_Int_t * vObjs = Gia_ManRelInitObjs(); + Vec_Wrd_t * vSims, * vRel, * vRel2; int nWords; + Vec_WrdFreeP( &p->vSimsPi ); + p->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + vSims = Gia_ManSimPatSim( p ); + vRel = Gia_ManRelDerive( p, vObjs, vSims ); + vRel2 = Gia_ManRelDerive2( p, vObjs, vSims ); + //assert( !memcmp(vRel2->pArray, vRel->pArray, sizeof(word)*Vec_WrdSize(vRel)) ); + Gia_ManRelPrint2( p, vObjs, vSims, vRel ); + Vec_WrdFree( vRel2 ); + Vec_WrdFree( vRel ); + Vec_WrdFree( vSims ); + Vec_IntFree( vObjs ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManRelInitIns() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 12 ); + Vec_IntPush( vRes, 18 ); + Vec_IntPush( vRes, 21 ); + Vec_IntPush( vRes, 34 ); + Vec_IntPush( vRes, 45 ); + Vec_IntPush( vRes, 59 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitOuts() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 65 ); + Vec_IntPush( vRes, 66 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitMffc( Gia_Man_t * p, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + Vec_IntSort( vOuts, 0 ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + Gia_ObjSetTravIdCurrent( p, pObj ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachCo( p, pObj, i ) + if ( !Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin0(pObj)) ) + Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachAndReverse( p, pObj, i ) + if ( Gia_ObjIsTravIdPrevious(p, pObj) ) + continue; + else if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + { + if ( !Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin0(pObj)) ) + Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) ); + if ( !Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin1(pObj)) ) + Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin1(pObj) ); + } + Gia_ManForEachAnd( p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) + Vec_IntPush( vRes, i ); + printf( "MFFC: " ); + Vec_IntPrint( vRes ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitDivs( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vMffc = Gia_ManRelInitMffc( p, vOuts ); + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + Vec_IntSort( vIns, 0 ); + + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vMffc, p, pObj, i ) + Gia_ObjSetTravIdCurrent( p, pObj ); + Vec_IntFree( vMffc ); + + Vec_IntPush( vRes, 0 ); + Vec_IntAppend( vRes, vIns ); + + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vIns, p, pObj, i ) + Gia_ObjSetTravIdCurrent( p, pObj ); + + Gia_ManForEachAnd( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + continue; + else if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) && Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) + { + if ( !Gia_ObjIsTravIdPrevious(p, pObj) ) + Vec_IntPush( vRes, i ); + Gia_ObjSetTravIdCurrent( p, pObj ); + } + printf( "Divisors: " ); + Vec_IntPrint( vRes ); + return vRes; +} + +Vec_Int_t * Gia_ManRelDeriveSimple( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Int_t * vIns, Vec_Int_t * vOuts ) +{ + Vec_Int_t * vRes = Vec_IntStartFull( 1 << Vec_IntSize(vIns) ); + int w, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + for ( w = 0; w < 64*nWords; w++ ) + { + int i, iObj, iMint = 0, iMint2 = 0; + Vec_IntForEachEntry( vIns, iObj, i ) + if ( Abc_TtGetBit(Vec_WrdEntryP(vSims, iObj*nWords), w) ) + iMint |= 1 << i; + if ( Vec_IntEntry(vRes, iMint) >= 0 ) + continue; + Vec_IntForEachEntry( vOuts, iObj, i ) + if ( Abc_TtGetBit(Vec_WrdEntryP(vSims, iObj*nWords), w) ) + iMint2 |= 1 << i; + Vec_IntWriteEntry( vRes, iMint, iMint2 ); + } + return vRes; +} + +void Gia_ManRelSolve( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Int_t * vIns, Vec_Int_t * vOuts, Vec_Int_t * vRel, Vec_Int_t * vDivs ) +{ + extern Mini_Aig_t * Exa4_ManGenTest( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, int TimeOut, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans, int fVerbose ); + + int i, m, iObj, Entry, iMint = 0, nMints = Vec_IntSize(vRel) - Vec_IntCountEntry(vRel, -1); + Vec_Wrd_t * vSimsIn = Vec_WrdStart( nMints ); + Vec_Wrd_t * vSimsOut = Vec_WrdStart( nMints ); + int Entry0 = Vec_IntEntry( vRel, 0 ); + + word Value, Phase = 0; + int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + Vec_IntForEachEntry( vDivs, iObj, i ) + if ( Vec_WrdEntry(vSims, iObj*nWords) & 1 ) + Phase |= 1 << i; + + assert( Entry0 >= 0 ); + printf( "Entry0 = %d\n", Entry0 ); + Entry0 ^= 1; +// for ( m = 0; m < nMints; m++ ) + Vec_IntForEachEntry( vRel, Entry, m ) + { + if ( Entry == -1 ) + continue; + Abc_TtSetBit( Vec_WrdEntryP(vSimsOut, iMint), Entry0 ^ Entry ); + + Value = 0; + Vec_IntForEachEntry( vDivs, iObj, i ) + if ( Abc_TtGetBit(Vec_WrdEntryP(vSims, iObj*nWords), m) ) + Abc_TtSetBit( &Value, i ); + Vec_WrdEntryP(vSimsOut, iMint)[0] = Value ^ Phase; + + iMint++; + } + assert( iMint == nMints ); + printf( "Created %d minterms.\n", iMint ); + Exa4_ManGenTest( vSimsIn, vSimsOut, Vec_IntSize(vIns), Vec_IntSize(vDivs), Vec_IntSize(vOuts), 10, 0, 0, 0, 0, 0, 1 ); + Vec_WrdFree( vSimsIn ); + Vec_WrdFree( vSimsOut ); +} +void Gia_ManRelDeriveTest( Gia_Man_t * p ) +{ + Vec_Int_t * vIns = Gia_ManRelInitIns(); + Vec_Int_t * vOuts = Gia_ManRelInitOuts(); + Vec_Wrd_t * vSims; Vec_Int_t * vRel, * vDivs; int nWords; + Vec_WrdFreeP( &p->vSimsPi ); + p->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + vSims = Gia_ManSimPatSim( p ); + vRel = Gia_ManRelDeriveSimple( p, vSims, vIns, vOuts ); + vDivs = Gia_ManRelInitDivs( p, vIns, vOuts ); + //printf( "Neg = %d\n", Vec_IntCountEntry(vRel, -1) ); + + Gia_ManRelSolve( p, vSims, vIns, vOuts, vRel, vDivs ); + + Vec_IntFree( vDivs ); + Vec_IntPrint( vRel ); + Vec_IntFree( vRel ); + Vec_WrdFree( vSims ); + Vec_IntFree( vIns ); + Vec_IntFree( vOuts ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManRelOutsTfo_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vTfo ) +{ + if ( Gia_ObjIsTravIdPrevious(p, pObj) ) + return 1; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; + if ( pObj->fPhase ) + { + Gia_ObjSetTravIdPrevious(p, pObj); + return 1; + } + if ( Gia_ObjIsAnd(pObj) ) + { + int Val0 = Gia_ManRelOutsTfo_rec( p, Gia_ObjFanin0(pObj), vTfo ); + int Val1 = Gia_ManRelOutsTfo_rec( p, Gia_ObjFanin1(pObj), vTfo ); + if ( Val0 || Val1 ) + { + Gia_ObjSetTravIdPrevious(p, pObj); + Vec_IntPush( vTfo, Gia_ObjId(p, pObj) ); + return 1; + } + } + Gia_ObjSetTravIdCurrent(p, pObj); + return 0; +} +Vec_Int_t * Gia_ManRelOutsTfo( Gia_Man_t * p, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vTfo = Vec_IntAlloc( 100 ); + Gia_ManIncrementTravId( p ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrentId( p, 0 ); + Gia_ManCleanPhase( p ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + pObj->fPhase = 1; + Gia_ManForEachCo( p, pObj, i ) + if ( Gia_ManRelOutsTfo_rec( p, Gia_ObjFanin0(pObj), vTfo ) ) + Vec_IntPush( vTfo, Gia_ObjId(p, pObj) ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + pObj->fPhase = 0; + //Vec_IntPrint( vTfo ); + return vTfo; +} +void Gia_ManSimPatSimTfo( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Int_t * vTfo ) +{ + Gia_Obj_t * pObj; + int i, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + Gia_ManForEachObjVec( vTfo, p, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + Gia_ManSimPatSimAnd( p, Gia_ObjId(p, pObj), pObj, nWords, vSims ); + else + Gia_ManSimPatSimPo( p, Gia_ObjId(p, pObj), pObj, nWords, vSims ); +} +void Gia_ManSimPatSimMiter( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vSims2, word * pSims, int nWords ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManForEachCo( p, pObj, i ) + Abc_TtOrXor( pSims, Vec_WrdEntryP(vSims, Gia_ObjId(p, pObj)*nWords), Vec_WrdEntryP(vSims2, Gia_ObjId(p, pObj)*nWords), nWords ); + Abc_TtNot( pSims, nWords ); +} +Vec_Wrd_t * Gia_ManRelDeriveRel( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts, Vec_Wrd_t * vSims ) +{ + extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + int i, o, iObj, nMintsO = 1 << Vec_IntSize(vOuts); + int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + Vec_Wrd_t * vSims2 = Vec_WrdDup( vSims ); + Vec_Wrd_t * vRel = Vec_WrdStart( nWords * 64 ); + Vec_Wrd_t * vRel2 = Vec_WrdStart( nWords * 64 ); + Vec_Int_t * vTfo = Gia_ManRelOutsTfo( p, vOuts ); + assert( 1 + Vec_IntSize(vIns) + Vec_IntSize(vDivs) + nMintsO <= 64 ); + assert( Vec_WrdSize(p->vSimsPi) % Gia_ManCiNum(p) == 0 ); + Vec_IntForEachEntry( vIns, iObj, o ) + memcpy( Vec_WrdEntryP(vRel, nWords*o), Vec_WrdEntryP(vSims, iObj*nWords), sizeof(word)*nWords ); + Vec_IntForEachEntry( vDivs, iObj, o ) + memcpy( Vec_WrdEntryP(vRel, nWords*(Vec_IntSize(vIns)+o)), Vec_WrdEntryP(vSims, iObj*nWords), sizeof(word)*nWords ); + for ( o = 0; o < nMintsO; o++ ) + { + word * pRes = Vec_WrdEntryP(vRel, nWords*(Vec_IntSize(vIns)+Vec_IntSize(vDivs)+o)); + Vec_IntForEachEntry( vOuts, iObj, i ) + memset( Vec_WrdEntryP(vSims2, iObj*nWords), ((o >> i) & 1) ? 0xFF : 0x00, sizeof(word)*nWords ); + Gia_ManSimPatSimTfo( p, vSims2, vTfo ); + Gia_ManSimPatSimMiter( p, vSims, vSims2, pRes, nWords ); + } + Extra_BitMatrixTransposeP( vRel, nWords, vRel2, 1 ); + Vec_IntFree( vTfo ); + Vec_WrdFree( vSims2 ); + Vec_WrdFree( vRel ); + return vRel2; +} +void Gia_ManRelDeriveSims( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts, Vec_Wrd_t * vSims, Vec_Wrd_t * vRel, Vec_Wrd_t ** pvSimsIn, Vec_Wrd_t ** pvSimsOut ) +{ + Vec_Wrd_t * vVals = Vec_WrdStartFull( 1 << Vec_IntSize(vIns) ); + Vec_Wrd_t * vSets = Vec_WrdStartFull( 1 << Vec_IntSize(vIns) ); + int m, nMints = 1 << Gia_ManCiNum(p), nCares = 0; + int nMintsI = 1 << Vec_IntSize(vIns); + int nShift = Vec_IntSize(vIns) + Vec_IntSize(vDivs); + int MaskI = Abc_Tt6Mask( Vec_IntSize(vIns) ); + int MaskD = Abc_Tt6Mask( nShift ); + for ( m = 0; m < nMints; m++ ) + { + word Sign = Vec_WrdEntry( vRel, m ); + *Vec_WrdEntryP( vVals, (int)Sign & MaskI ) = (int)Sign & MaskD; + *Vec_WrdEntryP( vSets, (int)Sign & MaskI ) &= Sign >> nShift; + } + for ( m = 0; m < nMintsI; m++ ) + if ( ~Vec_WrdEntry(vSets, m) ) + nCares++; + assert( *pvSimsIn == NULL ); + assert( *pvSimsOut == NULL ); + *pvSimsIn = Vec_WrdAlloc( nCares ); + *pvSimsOut = Vec_WrdAlloc( nCares ); + for ( m = 0; m < nMintsI; m++ ) + if ( ~Vec_WrdEntry(vSets, m) ) + { + Vec_WrdPush( *pvSimsIn, Vec_WrdEntry(vVals, m) << 1 ); + Vec_WrdPush( *pvSimsOut, Vec_WrdEntry(vSets, m) ); + } + assert( Vec_WrdSize(*pvSimsIn) == nCares ); + Vec_WrdFree( vSets ); + Vec_WrdFree( vVals ); +} + +int Gia_ManRelCheck_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsTravIdPrevious(p, pObj) ) + return 1; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; + if ( pObj->fPhase ) + { + Gia_ObjSetTravIdPrevious(p, pObj); + return 1; + } + if ( Gia_ObjIsAnd(pObj) ) + { + int Val0 = Gia_ManRelCheck_rec( p, Gia_ObjFanin0(pObj) ); + int Val1 = Gia_ManRelCheck_rec( p, Gia_ObjFanin1(pObj) ); + if ( Val0 && Val1 ) + { + Gia_ObjSetTravIdPrevious(p, pObj); + return 1; + } + } + Gia_ObjSetTravIdCurrent(p, pObj); + return 0; +} +int Gia_ManRelCheck( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i, Res = 1; + Gia_ManIncrementTravId( p ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrentId( p, 0 ); + Gia_ManCleanPhase( p ); + Gia_ManForEachObjVec( vIns, p, pObj, i ) + pObj->fPhase = 1; + Gia_ManForEachObjVec( vDivs, p, pObj, i ) + if ( !Gia_ManRelCheck_rec( p, pObj ) ) + Res = 0; + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + if ( !Gia_ManRelCheck_rec( p, pObj ) ) + Res = 0; + Gia_ManForEachObjVec( vIns, p, pObj, i ) + pObj->fPhase = 0; + return Res; +} +void Gia_ManRelCompute( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts, Vec_Wrd_t ** pvSimsIn, Vec_Wrd_t ** pvSimsOut ) +{ + Vec_Wrd_t * vSims, * vRel; + //Vec_Wrd_t * vSimsDiv = NULL, * vSimsOut = NULL; + + Vec_WrdFreeP( &p->vSimsPi ); + p->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + + if ( !Gia_ManRelCheck( p, vIns, vDivs, vOuts ) ) + printf( "Window is NOT consistent.\n" ); + else + printf( "Window is consistent.\n" ); + + vSims = Gia_ManSimPatSim( p ); + vRel = Gia_ManRelDeriveRel( p, vIns, vDivs, vOuts, vSims ); + + Gia_ManRelDeriveSims( p, vIns, vDivs, vOuts, vSims, vRel, pvSimsIn, pvSimsOut ); + + Vec_WrdFree( vRel ); + Vec_WrdFree( vSims ); + Vec_WrdFreeP( &p->vSimsPi ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +Vec_Int_t * Gia_ManRelInitIns1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 22 ); + Vec_IntPush( vRes, 41 ); + Vec_IntPush( vRes, 45 ); + Vec_IntPush( vRes, 59 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitDivs1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 46 ); + Vec_IntPush( vRes, 47 ); + Vec_IntPush( vRes, 48 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitOuts1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 65 ); + Vec_IntPush( vRes, 66 ); + return vRes; +} +*/ + +Vec_Int_t * Gia_ManRelInitIns1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 22 ); + Vec_IntPush( vRes, 25 ); + Vec_IntPush( vRes, 42 ); + Vec_IntPush( vRes, 59 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitDivs1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 43 ); + Vec_IntPush( vRes, 44 ); + Vec_IntPush( vRes, 45 ); + Vec_IntPush( vRes, 46 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitOuts1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 60 ); + Vec_IntPush( vRes, 61 ); + return vRes; +} + +/* +Vec_Int_t * Gia_ManRelInitIns1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 22 ); + Vec_IntPush( vRes, 25 ); + Vec_IntPush( vRes, 42 ); + Vec_IntPush( vRes, 50 ); + Vec_IntPush( vRes, 67 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitDivs1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 43 ); + Vec_IntPush( vRes, 44 ); + Vec_IntPush( vRes, 45 ); + Vec_IntPush( vRes, 46 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitOuts1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 73 ); + Vec_IntPush( vRes, 74 ); + return vRes; +} +*/ + +/* +Vec_Int_t * Gia_ManRelInitIns1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 43 ); + Vec_IntPush( vRes, 46 ); + //Vec_IntPush( vRes, 49 ); + Vec_IntPush( vRes, 50 ); + Vec_IntPush( vRes, 67 ); + Vec_IntPush( vRes, 75 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitDivs1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitOuts1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 73 ); + Vec_IntPush( vRes, 86 ); + Vec_IntPush( vRes, 88 ); + return vRes; +} +*/ + +void Gia_ManRelDeriveTest1( Gia_Man_t * p ) +{ + extern void Exa6_WriteFile2( char * pFileName, int nVars, int nDivs, int nOuts, Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut ); + + word Entry; int i; + Vec_Int_t * vIns = Gia_ManRelInitIns1(); + Vec_Int_t * vDivs = Gia_ManRelInitDivs1(); + Vec_Int_t * vOuts = Gia_ManRelInitOuts1(); + + Vec_Wrd_t * vSimsDiv = NULL, * vSimsOut = NULL; + Gia_ManRelCompute( p, vIns, vDivs, vOuts, &vSimsDiv, &vSimsOut ); + + printf( "Inputs:\n" ); + Vec_WrdForEachEntry( vSimsDiv, Entry, i ) + Abc_TtPrintBits( &Entry, 1 + Vec_IntSize(vIns) + Vec_IntSize(vDivs) ); + printf( "Outputs:\n" ); + Vec_WrdForEachEntry( vSimsOut, Entry, i ) + Abc_TtPrintBits( &Entry, 1 << Vec_IntSize(vOuts) ); + printf( "\n" ); + + Exa6_WriteFile2( "mul44_i5_n0_t3_s11.rel", Vec_IntSize(vIns), Vec_IntSize(vDivs), Vec_IntSize(vOuts), vSimsDiv, vSimsOut ); + + Vec_WrdFree( vSimsDiv ); + Vec_WrdFree( vSimsOut ); + + Vec_IntFree( vIns ); + Vec_IntFree( vDivs ); + Vec_IntFree( vOuts ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +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 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; + Mini_Aig_t * pMini = NULL; + Vec_Int_t * vIns = Gia_ManRelInitIns1(); + Vec_Int_t * vDivs = Gia_ManRelInitDivs1(); + Vec_Int_t * vOuts = Gia_ManRelInitOuts1(); + int nNodes = 4; + + Vec_Wrd_t * vSimsDiv = NULL, * vSimsOut = NULL; + 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 ); + if ( pMini ) + { + pNew = Gia_ManDupMini( p, vIns, vDivs, vOuts, pMini ); + Mini_AigStop( pMini ); + } + Vec_WrdFree( vSimsDiv ); + Vec_WrdFree( vSimsOut ); + + Vec_IntFree( vIns ); + Vec_IntFree( vDivs ); + Vec_IntFree( vOuts ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Gia_ManComputeRange( Gia_Man_t * p ) +{ + Vec_Wrd_t * vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + Vec_Wrd_t * vSims = Gia_ManSimPatSimOut( p, vSimsPi, 1 ); + int n, nWords = Vec_WrdSize(vSimsPi) / Gia_ManCiNum(p); + int i, nLimit = Gia_ManCiNum(p) < 6 ? 1 << Gia_ManCiNum(p) : 64*nWords; + Vec_Str_t * vOut = Vec_StrAlloc( nLimit*(Gia_ManCoNum(p) + 3)+1 ); + assert( Vec_WrdSize(vSims) == nWords * Gia_ManCoNum(p) ); + for ( n = 0; n < nLimit; n++ ) + { + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + Vec_StrPush( vOut, (char)('0' + Abc_TtGetBit(Vec_WrdEntryP(vSims, i*nWords), n)) ); + Vec_StrPush( vOut, ' ' ); + Vec_StrPush( vOut, '1' ); + Vec_StrPush( vOut, '\n' ); + } + Vec_StrPush( vOut, '\0' ); + Vec_WrdFree( vSims ); + Vec_WrdFree( vSimsPi ); + return vOut; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManComparePrint( Gia_Man_t * p, Gia_Man_t * q ) +{ + Vec_Wrd_t * vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + Vec_Wrd_t * vSimsP = Gia_ManSimPatSimOut( p, vSimsPi, 0 ); + Vec_Wrd_t * vSimsQ = Gia_ManSimPatSimOut( q, vSimsPi, 0 ); + int i, k, nWords = Vec_WrdSize(vSimsPi) / Gia_ManCiNum(p), Count = 0; + Gia_Obj_t * pObjP, * pObjQ; + Gia_ManSetPhase( p ); + Gia_ManSetPhase( q ); + Gia_ManForEachObj( p, pObjP, i ) { + word * pSim = Vec_WrdEntryP( vSimsP, i * nWords ); + if ( pSim[0] & 1 ) Abc_TtNot( pSim, nWords ); + } + Gia_ManForEachObj( q, pObjQ, i ) { + word * pSim = Vec_WrdEntryP( vSimsQ, i * nWords ); + if ( pSim[0] & 1 ) Abc_TtNot( pSim, nWords ); + } + Gia_ManForEachAnd( q, pObjQ, i ) { + word * pSimQ = Vec_WrdEntryP( vSimsQ, i * nWords ); + int fFirst = 1; + Gia_ManForEachObj( p, pObjP, k ) { + word * pSimP = Vec_WrdEntryP( vSimsP, k * nWords ); + if ( !Abc_TtEqual(pSimQ, pSimP, nWords) ) + continue; + if ( fFirst ) { + printf( "%5d :", i ); + fFirst = 0; + Count++; + } + printf( " %5d(%d)", k, pObjQ->fPhase ^ pObjP->fPhase ); + } + if ( !fFirst ) + printf( "\n"); + } + printf( "Found %d equivalent nodes.\n", Count ); + Vec_WrdFree( vSimsP ); + Vec_WrdFree( vSimsQ ); + Vec_WrdFree( vSimsPi ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaSort.c b/abc/src/aig/gia/giaSort.c index 7586be65cab..d64a80c52a9 100644 --- a/abc/src/aig/gia/giaSort.c +++ b/abc/src/aig/gia/giaSort.c @@ -165,7 +165,7 @@ void Gia_SortTest() printf( "Sorting %d integers\n", nSize ); pArray = Gia_SortGetTest( nSize ); clk = Abc_Clock(); - qsort( pArray, nSize, 4, (int (*)(const void *, const void *)) num_cmp1 ); + qsort( pArray, (size_t)nSize, 4, (int (*)(const void *, const void *)) num_cmp1 ); ABC_PRT( "qsort ", Abc_Clock() - clk ); Gia_SortVerifySorted( pArray, nSize ); ABC_FREE( pArray ); diff --git a/abc/src/aig/gia/giaSpeedup.c b/abc/src/aig/gia/giaSpeedup.c index 0d593993583..b9f4f03716b 100644 --- a/abc/src/aig/gia/giaSpeedup.c +++ b/abc/src/aig/gia/giaSpeedup.c @@ -246,6 +246,7 @@ float Gia_ManDelayTraceLut( Gia_Man_t * p ) // initialize the arrival times Gia_ManTimeStart( p ); + Gia_ManLevelNum( p ); // propagate arrival times if ( p->pManTime ) diff --git a/abc/src/aig/gia/giaStg.c b/abc/src/aig/gia/giaStg.c index 9588d51c2ea..9b6d49b600e 100644 --- a/abc/src/aig/gia/giaStg.c +++ b/abc/src/aig/gia/giaStg.c @@ -53,7 +53,7 @@ void Gia_ManPrintStateEncoding( Vec_Vec_t * vCodes, int nBits ) Vec_VecForEachLevelInt( vCodes, vVec, i ) { printf( "%6d : ", i+1 ); - memset( pBuffer, '-', nBits ); + memset( pBuffer, '-', (size_t)nBits ); Vec_IntForEachEntry( vVec, Bit, k ) { assert( Bit < nBits ); diff --git a/abc/src/aig/gia/giaStoch.c b/abc/src/aig/gia/giaStoch.c new file mode 100644 index 00000000000..78fe2cb6771 --- /dev/null +++ b/abc/src/aig/gia/giaStoch.c @@ -0,0 +1,629 @@ +/**CFile**************************************************************** + + FileName [giaDeep.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Experiments with synthesis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaDeep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "base/main/main.h" +#include "base/cmd/cmd.h" + +#ifdef _MSC_VER +#define unlink _unlink +#else +#include +#endif + +#ifdef ABC_USE_PTHREADS + +#ifdef _WIN32 +#include "../lib/pthread.h" +#else +#include +#endif + +#endif + + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Processing on a single core.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_StochProcessOne( Gia_Man_t * p, char * pScript, int Rand, int TimeSecs ) +{ + Gia_Man_t * pNew; + char FileName[100], Command[1000]; + 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 ( system( (char *)Command ) ) + { + fprintf( stderr, "The following command has returned non-zero exit status:\n" ); + fprintf( stderr, "\"%s\"\n", (char *)Command ); + fprintf( stderr, "Sorry for the inconvenience.\n" ); + fflush( stdout ); + unlink( FileName ); + return Gia_ManDup(p); + } + pNew = Gia_AigerRead( FileName, 0, 0, 0 ); + unlink( FileName ); + if ( pNew && Gia_ManAndNum(pNew) < Gia_ManAndNum(p) ) + return pNew; + Gia_ManStopP( &pNew ); + return Gia_ManDup(p); +} +void Gia_StochProcessArray( Vec_Ptr_t * vGias, char * pScript, int TimeSecs, int fVerbose ) +{ + Gia_Man_t * pGia, * pNew; int i; + Vec_Int_t * vRands = Vec_IntAlloc( Vec_PtrSize(vGias) ); + Abc_Random(1); + for ( i = 0; i < Vec_PtrSize(vGias); i++ ) + Vec_IntPush( vRands, Abc_Random(0) % 0x1000000 ); + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) + { + pNew = Gia_StochProcessOne( pGia, pScript, Vec_IntEntry(vRands, i), TimeSecs ); + Gia_ManStop( pGia ); + Vec_PtrWriteEntry( vGias, i, pNew ); + } + Vec_IntFree( vRands ); +} + +/**Function************************************************************* + + Synopsis [Processing on a many cores.] + + Description [] + + SideEffects [] + + 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; + +void * Gia_StochWorkerThread( void * pArg ) +{ + 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; +} + +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 ); + } + // look at the threads + for ( k = 0; k < Vec_PtrSize(vGias); k++ ) + { + for ( i = 0; i < nProcs; i++ ) + { + if ( ThData[i].fWorking ) + continue; + ThData[i].Index = k; + ThData[i].fWorking = 1; + break; + } + if ( i == nProcs ) + k--; + } + // wait till threads finish + for ( i = 0; i < nProcs; i++ ) + if ( ThData[i].fWorking ) + i = -1; + // stop threads + for ( i = 0; i < nProcs; i++ ) + { + assert( !ThData[i].fWorking ); + // stop + ThData[i].Index = -1; + ThData[i].fWorking = 1; + } +} + +#endif // pthreads are used + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupMapping( Gia_Man_t * pNew, Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pFanin; int i, k; + Vec_Int_t * vMapping = p->vMapping ? Vec_IntAlloc( Vec_IntSize(p->vMapping) ) : NULL; + if ( p->vMapping == NULL ) + return; + Vec_IntFill( vMapping, Gia_ManObjNum(p), 0 ); + Gia_ManForEachLut( p, i ) + { + pObj = Gia_ManObj( p, i ); + Vec_IntWriteEntry( vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Gia_ObjLutSize(p, i) ); + Gia_LutForEachFaninObj( p, i, pFanin, k ) + Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->Value) ); + Vec_IntPush( vMapping, Abc_Lit2Var(pObj->Value) ); + } + pNew->vMapping = vMapping; +} +Gia_Man_t * Gia_ManDupWithMapping( Gia_Man_t * pGia ) +{ + Gia_Man_t * pCopy = Gia_ManDup(pGia); + Gia_ManDupMapping( pCopy, pGia ); + return pCopy; +} +void Gia_ManStochSynthesis( Vec_Ptr_t * vAigs, char * pScript ) +{ + Gia_Man_t * pGia, * pNew; int i; + Vec_PtrForEachEntry( Gia_Man_t *, vAigs, pGia, i ) + { + Gia_Man_t * pCopy = Gia_ManDupWithMapping(pGia); + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pGia ); + if ( Abc_FrameIsBatchMode() ) + { + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + return; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + Abc_FrameSetBatchMode( 0 ); + return; + } + Abc_FrameSetBatchMode( 0 ); + } + pNew = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + if ( Gia_ManHasMapping(pNew) && Gia_ManHasMapping(pCopy) ) + { + if ( Gia_ManLutNum(pNew) < Gia_ManLutNum(pCopy) ) + { + Gia_ManStop( pCopy ); + pCopy = Gia_ManDupWithMapping( pNew ); + } + } + else + { + if ( Gia_ManAndNum(pNew) < Gia_ManAndNum(pCopy) ) + { + Gia_ManStop( pCopy ); + pCopy = Gia_ManDup( pNew ); + } + } + Vec_PtrWriteEntry( vAigs, i, pCopy ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectNodes_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vAnds ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjUpdateTravIdCurrentId( p, iObj ) ) + return; + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) || iObj == 0 ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManCollectNodes_rec( p, Gia_ObjFaninId0(pObj, iObj), vAnds ); + Gia_ManCollectNodes_rec( p, Gia_ObjFaninId1(pObj, iObj), vAnds ); + Vec_IntPush( vAnds, iObj ); +} +void Gia_ManCollectNodes( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos ) +{ + int i, iObj; + if ( !Gia_ManHasMapping(p) ) + return; + Vec_IntClear( vAnds ); + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vCis, iObj, i ) + Gia_ObjSetTravIdCurrentId( p, iObj ); + Vec_IntForEachEntry( vCos, iObj, i ) + Gia_ManCollectNodes_rec( p, iObj, vAnds ); +} +Gia_Man_t * Gia_ManDupDivideOne( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos ) +{ + Vec_Int_t * vMapping; int i; + Gia_Man_t * pNew; Gia_Obj_t * pObj; + pNew = Gia_ManStart( 1+Vec_IntSize(vCis)+Vec_IntSize(vAnds)+Vec_IntSize(vCos) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObjVec( vCis, p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vCos, p, pObj, i ) + Gia_ManAppendCo( pNew, pObj->Value ); + assert( Gia_ManCiNum(pNew) > 0 && Gia_ManCoNum(pNew) > 0 ); + if ( !Gia_ManHasMapping(p) ) + return pNew; + vMapping = Vec_IntAlloc( 4*Gia_ManObjNum(pNew) ); + Vec_IntFill( vMapping, Gia_ManObjNum(pNew), 0 ); + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + { + Gia_Obj_t * pFanin; int k; + int iObj = Gia_ObjId(p, pObj); + if ( !Gia_ObjIsLut(p, iObj) ) + continue; + Vec_IntWriteEntry( vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Gia_ObjLutSize(p, iObj) ); + Gia_LutForEachFaninObj( p, iObj, pFanin, k ) + Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->Value) ); + Vec_IntPush( vMapping, Abc_Lit2Var(pObj->Value) ); + } + pNew->vMapping = vMapping; + return pNew; +} +Vec_Ptr_t * Gia_ManDupDivide( Gia_Man_t * p, Vec_Wec_t * vCis, Vec_Wec_t * vAnds, Vec_Wec_t * vCos, char * pScript, int nProcs, int TimeOut ) +{ + Vec_Ptr_t * vAigs = Vec_PtrAlloc( Vec_WecSize(vCis) ); int i; + for ( i = 0; i < Vec_WecSize(vCis); i++ ) + { + Gia_ManCollectNodes( p, Vec_WecEntry(vCis, i), Vec_WecEntry(vAnds, i), Vec_WecEntry(vCos, i) ); + Vec_PtrPush( vAigs, Gia_ManDupDivideOne(p, Vec_WecEntry(vCis, i), Vec_WecEntry(vAnds, i), Vec_WecEntry(vCos, i)) ); + } + //Gia_ManStochSynthesis( vAigs, pScript ); + Gia_StochProcess( vAigs, pScript, nProcs, TimeOut, 0 ); + return vAigs; +} +Gia_Man_t * Gia_ManDupStitch( Gia_Man_t * p, Vec_Wec_t * vCis, Vec_Wec_t * vAnds, Vec_Wec_t * vCos, Vec_Ptr_t * vAigs, int fHash ) +{ + Gia_Man_t * pGia, * pNew; + Gia_Obj_t * pObj; int i, k; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManCleanValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + if ( fHash ) + Gia_ManHashAlloc( pNew ); + Vec_PtrForEachEntry( Gia_Man_t *, vAigs, pGia, i ) + { + Vec_Int_t * vCi = Vec_WecEntry( vCis, i ); + Vec_Int_t * vCo = Vec_WecEntry( vCos, i ); + Gia_ManCleanValue( pGia ); + Gia_ManConst0(pGia)->Value = 0; + Gia_ManForEachObjVec( vCi, p, pObj, k ) + Gia_ManCi(pGia, k)->Value = pObj->Value; + if ( fHash ) + Gia_ManForEachAnd( pGia, pObj, k ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + Gia_ManForEachAnd( pGia, pObj, k ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vCo, p, pObj, k ) + pObj->Value = Gia_ObjFanin0Copy(Gia_ManCo(pGia, k)); + } + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + if ( fHash ) + { + pNew = Gia_ManCleanup( pGia = pNew ); + Gia_ManStop( pGia ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManDupStitchMap( Gia_Man_t * p, Vec_Wec_t * vCis, Vec_Wec_t * vAnds, Vec_Wec_t * vCos, Vec_Ptr_t * vAigs ) +{ + Vec_Int_t * vMapping; int n; + Gia_Man_t * pGia, * pNew = Gia_ManDupStitch( p, vCis, vAnds, vCos, vAigs, !Gia_ManHasMapping(p) ); + if ( !Gia_ManHasMapping(p) ) + return pNew; + vMapping = Vec_IntAlloc( Vec_IntSize(p->vMapping) ); + Vec_IntFill( vMapping, Gia_ManObjNum(pNew), 0 ); + Vec_PtrForEachEntry( Gia_Man_t *, vAigs, pGia, n ) + { + Gia_Obj_t * pFanin; int iObj, k; + //printf( "Gia %d has %d Luts\n", n, Gia_ManLutNum(pGia) ); + + Gia_ManForEachLut( pGia, iObj ) + { + Gia_Obj_t * pObj = Gia_ManObj( pGia, iObj ); + Vec_IntWriteEntry( vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Gia_ObjLutSize(pGia, iObj) ); + Gia_LutForEachFaninObj( pGia, iObj, pFanin, k ) + Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->Value) ); + Vec_IntPush( vMapping, Abc_Lit2Var(pObj->Value) ); + } + } + pNew->vMapping = vMapping; + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManStochNodes( Gia_Man_t * p, int nMaxSize, int Seed ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 100 ); + Vec_Int_t * vPart = Vec_WecPushLevel( vRes ); + int i, iStart = Seed % Gia_ManCoNum(p); + //Gia_ManLevelNum( p ); + Gia_ManIncrementTravId( p ); + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + { + Gia_Obj_t * pObj = Gia_ManCo( p, (iStart+i) % Gia_ManCoNum(p) ); + if ( Vec_IntSize(vPart) > nMaxSize ) + vPart = Vec_WecPushLevel( vRes ); + Gia_ManCollectNodes_rec( p, Gia_ObjFaninId0p(p, pObj), vPart ); + } + if ( Vec_IntSize(vPart) == 0 ) + Vec_WecShrink( vRes, Vec_WecSize(vRes)-1 ); + //Vec_WecPrint( vRes, 0 ); + return vRes; +} +Vec_Wec_t * Gia_ManStochInputs( Gia_Man_t * p, Vec_Wec_t * vAnds ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 100 ); + Vec_Int_t * vLevel; Gia_Obj_t * pObj; int i, k, iObj, iFan, f; + Vec_WecForEachLevel( vAnds, vLevel, i ) + { + Vec_Int_t * vVec = Vec_WecPushLevel( vRes ); + assert( Vec_IntSize(vVec) == 0 ); + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLevel, iObj, k ) + Gia_ObjSetTravIdCurrentId( p, iObj ); + if ( Gia_ManHasMapping(p) ) + { + Vec_IntForEachEntry( vLevel, iObj, k ) + if ( Gia_ObjIsLut(p, iObj) ) + Gia_LutForEachFanin( p, iObj, iFan, f ) + if ( !Gia_ObjUpdateTravIdCurrentId(p, iFan) ) + Vec_IntPush( vVec, iFan ); + } + else + { + Gia_ManForEachObjVec( vLevel, p, pObj, k ) + { + iObj = Gia_ObjFaninId0p(p, pObj); + if ( !Gia_ObjUpdateTravIdCurrentId(p, iObj) ) + Vec_IntPush( vVec, iObj ); + iObj = Gia_ObjFaninId1p(p, pObj); + if ( !Gia_ObjUpdateTravIdCurrentId(p, iObj) ) + Vec_IntPush( vVec, iObj ); + } + } + assert( Vec_IntSize(vVec) > 0 ); + } + return vRes; +} +Vec_Wec_t * Gia_ManStochOutputs( Gia_Man_t * p, Vec_Wec_t * vAnds ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 100 ); + Vec_Int_t * vLevel; Gia_Obj_t * pObj; int i, k, iObj, iFan, f; + if ( Gia_ManHasMapping(p) ) + { + Gia_ManSetLutRefs( p ); + Vec_WecForEachLevel( vAnds, vLevel, i ) + { + Vec_Int_t * vVec = Vec_WecPushLevel( vRes ); + assert( Vec_IntSize(vVec) == 0 ); + Vec_IntForEachEntry( vLevel, iObj, k ) + if ( Gia_ObjIsLut(p, iObj) ) + Gia_LutForEachFanin( p, iObj, iFan, f ) + Gia_ObjLutRefDecId( p, iFan ); + Vec_IntForEachEntry( vLevel, iObj, k ) + if ( Gia_ObjIsLut(p, iObj) ) + if ( Gia_ObjLutRefNumId(p, iObj) ) + Vec_IntPush( vVec, iObj ); + Vec_IntForEachEntry( vLevel, iObj, k ) + if ( Gia_ObjIsLut(p, iObj) ) + Gia_LutForEachFanin( p, iObj, iFan, f ) + Gia_ObjLutRefIncId( p, iFan ); + assert( Vec_IntSize(vVec) > 0 ); + } + } + else + { + Gia_ManCreateRefs( p ); + Vec_WecForEachLevel( vAnds, vLevel, i ) + { + Vec_Int_t * vVec = Vec_WecPushLevel( vRes ); + Gia_ManForEachObjVec( vLevel, p, pObj, k ) + { + Gia_ObjRefDecId( p, Gia_ObjFaninId0p(p, pObj) ); + Gia_ObjRefDecId( p, Gia_ObjFaninId1p(p, pObj) ); + } + Gia_ManForEachObjVec( vLevel, p, pObj, k ) + if ( Gia_ObjRefNum(p, pObj) ) + Vec_IntPush( vVec, Gia_ObjId(p, pObj) ); + Gia_ManForEachObjVec( vLevel, p, pObj, k ) + { + Gia_ObjRefIncId( p, Gia_ObjFaninId0p(p, pObj) ); + Gia_ObjRefIncId( p, Gia_ObjFaninId1p(p, pObj) ); + } + } + } + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManStochSyn( int nMaxSize, int nIters, int TimeOut, int Seed, int fVerbose, char * pScript, int nProcs ) +{ + abctime nTimeToStop = TimeOut ? Abc_Clock() + TimeOut * CLOCKS_PER_SEC : 0; + abctime clkStart = Abc_Clock(); + int fMapped = Gia_ManHasMapping(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())); + int nLutEnd, nLutBeg = fMapped ? Gia_ManLutNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())) : 0; + int i, nEnd, nBeg = Gia_ManAndNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())); + Abc_Random(1); + for ( i = 0; i < 10+Seed; i++ ) + Abc_Random(0); + if ( fVerbose ) + printf( "Running %d iterations of script \"%s\".\n", nIters, pScript ); + for ( i = 0; i < nIters; i++ ) + { + abctime clk = Abc_Clock(); + Gia_Man_t * pGia = Gia_ManDupWithMapping( Abc_FrameReadGia(Abc_FrameGetGlobalFrame()) ); + Vec_Wec_t * vAnds = Gia_ManStochNodes( pGia, nMaxSize, Abc_Random(0) & 0x7FFFFFFF ); + Vec_Wec_t * vIns = Gia_ManStochInputs( pGia, vAnds ); + Vec_Wec_t * vOuts = Gia_ManStochOutputs( pGia, vAnds ); + Vec_Ptr_t * vAigs = Gia_ManDupDivide( pGia, vIns, vAnds, vOuts, pScript, nProcs, TimeOut ); + Gia_Man_t * pNew = Gia_ManDupStitchMap( pGia, vIns, vAnds, vOuts, vAigs ); + int fMapped = Gia_ManHasMapping(pGia) && Gia_ManHasMapping(pNew); + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew ); + if ( fVerbose ) + printf( "Iteration %3d : Using %3d partitions. Reducing %6d to %6d %s. ", + i, Vec_PtrSize(vAigs), fMapped ? Gia_ManLutNum(pGia) : Gia_ManAndNum(pGia), + fMapped ? Gia_ManLutNum(pNew) : Gia_ManAndNum(pNew), + fMapped ? "LUTs" : "ANDs" ); + if ( fVerbose ) + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + Gia_ManStop( pGia ); + Vec_PtrFreeFunc( vAigs, (void (*)(void *)) Gia_ManStop ); + Vec_WecFree( vAnds ); + Vec_WecFree( vIns ); + Vec_WecFree( vOuts ); + if ( nTimeToStop && Abc_Clock() > nTimeToStop ) + { + printf( "Runtime limit (%d sec) is reached after %d iterations.\n", TimeOut, i ); + break; + } + } + fMapped &= Gia_ManHasMapping(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())); + nLutEnd = fMapped ? Gia_ManLutNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())) : 0; + nEnd = Gia_ManAndNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())); + if ( fVerbose ) + printf( "Cumulatively reduced %d %s after %d iterations. ", + fMapped ? nLutBeg - nLutEnd : nBeg - nEnd, fMapped ? "LUTs" : "ANDs", nIters ); + if ( fVerbose ) + Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaStr.c b/abc/src/aig/gia/giaStr.c index 68d478b82c7..a87662a8586 100644 --- a/abc/src/aig/gia/giaStr.c +++ b/abc/src/aig/gia/giaStr.c @@ -736,7 +736,7 @@ Str_Ntk_t * Str_ManNormalizeInt( Gia_Man_t * p, Vec_Wec_t * vGroups, Vec_Int_t * if ( p->vStore == NULL ) p->vStore = Vec_IntAlloc( STR_SUPER ); Gia_ManFillValue( p ); - pNtk = Str_NtkCreate( Gia_ManObjNum(p), 1 + Gia_ManCoNum(p) + 2 * Gia_ManAndNum(p) + Gia_ManMuxNum(p) ); + pNtk = Str_NtkCreate( Gia_ManObjNum(p) + 10000, 1 + Gia_ManCoNum(p) + 2 * Gia_ManAndNum(p) + Gia_ManMuxNum(p) + 10000 ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObj1( p, pObj, i ) { @@ -749,7 +749,7 @@ Str_Ntk_t * Str_ManNormalizeInt( Gia_Man_t * p, Vec_Wec_t * vGroups, Vec_Int_t * pObj->Value = Str_ObjCreate( pNtk, STR_PO, 1, &iFanin ); } } - assert( pNtk->nObjs <= Gia_ManObjNum(p) ); + //assert( pNtk->nObjs <= Gia_ManObjNum(p) ); return pNtk; } Str_Ntk_t * Str_ManNormalize( Gia_Man_t * p ) @@ -859,21 +859,23 @@ static inline void transpose64( word A[64] ) static inline int Str_ManNum( Gia_Man_t * p, int iObj ) { return Vec_IntEntry(&p->vCopies, iObj); } static inline void Str_ManSetNum( Gia_Man_t * p, int iObj, int Num ) { Vec_IntWriteEntry(&p->vCopies, iObj, Num); } -int Str_ManVectorAffinity( Gia_Man_t * p, Vec_Int_t * vSuper, Vec_Int_t * vDelay, word Matrix[256], int nLimit ) +int Str_ManVectorAffinity( Gia_Man_t * p, Vec_Int_t * vSuper, Vec_Int_t * vDelay, word * Matrix, int nLimit ) { int fVerbose = 0; - int Levels[256]; + int * Levels = NULL; int nSize = Vec_IntSize(vSuper); int Prev = nSize, nLevels = 1; int i, k, iLit, iFanin, nSizeNew; word Mask; assert( nSize > 2 ); + assert( nSize <= nLimit ); if ( nSize > 64 ) { for ( i = 0; i < 64; i++ ) Matrix[i] = 0; return 0; } + Levels = ABC_ALLOC( int, nLimit+256 ); // mark current nodes Gia_ManIncrementTravId( p ); Vec_IntForEachEntry( vSuper, iLit, i ) @@ -948,6 +950,7 @@ int Str_ManVectorAffinity( Gia_Man_t * p, Vec_Int_t * vSuper, Vec_Int_t * vDelay if ( nSizeNew == 0 ) { Vec_IntShrink( vSuper, nSize ); + ABC_FREE( Levels ); return 0; } /* @@ -979,6 +982,7 @@ int Str_ManVectorAffinity( Gia_Man_t * p, Vec_Int_t * vSuper, Vec_Int_t * vDelay } i = 0; } + ABC_FREE( Levels ); Vec_IntShrink( vSuper, nSize ); return nSizeNew; } @@ -1088,15 +1092,14 @@ int Str_NtkBalanceTwo( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, int i, void Str_NtkBalanceMulti( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec_Int_t * vDelay, int nLutSize ) { - word pMatrix[256]; - int Limit = 256; + word * pMatrix = ABC_ALLOC( word, pObj->nFanins+256 ); Vec_Int_t * vSuper = pNew->vSuper; Vec_Int_t * vCosts = pNew->vStore; int * pSuper = Vec_IntArray(vSuper); int * pCost = Vec_IntArray(vCosts); int k, iLit, MatrixSize = 0; - assert( Limit <= Vec_IntCap(vSuper) ); - assert( Limit <= Vec_IntCap(vCosts) ); + assert( (int)pObj->nFanins <= Vec_IntCap(vSuper) ); + assert( (int)pObj->nFanins <= Vec_IntCap(vCosts) ); // collect nodes Vec_IntClear( vSuper ); @@ -1111,11 +1114,13 @@ void Str_NtkBalanceMulti( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec if ( Vec_IntSize(vSuper) == 1 ) { pObj->iCopy = Vec_IntEntry(vSuper, 0); + ABC_FREE( pMatrix ); return; } if ( Vec_IntSize(vSuper) == 2 ) { pObj->iCopy = Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, 2, nLutSize, -1 ); + ABC_FREE( pMatrix ); return; } @@ -1127,7 +1132,7 @@ void Str_NtkBalanceMulti( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec // compute affinity if ( Vec_IntSize(vSuper) < 64 ) - MatrixSize = Str_ManVectorAffinity( pNew, vSuper, vCosts, pMatrix, Limit ); + MatrixSize = Str_ManVectorAffinity( pNew, vSuper, vCosts, pMatrix, pObj->nFanins ); // start the new product while ( Vec_IntSize(vSuper) > 2 ) @@ -1147,7 +1152,7 @@ void Str_NtkBalanceMulti( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec // compute affinity if ( Vec_IntSize(vSuper) == 64 ) - MatrixSize = Str_ManVectorAffinity( pNew, vSuper, vCosts, pMatrix, Limit ); + MatrixSize = Str_ManVectorAffinity( pNew, vSuper, vCosts, pMatrix, pObj->nFanins ); assert( Vec_IntSize(vSuper) <= 64 ); // Str_PrintState( pCost, pSuper, pMatrix, Vec_IntSize(vSuper) ); @@ -1236,6 +1241,7 @@ void Str_NtkBalanceMulti( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec continue; } pObj->iCopy = Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, 2, nLutSize, -1 ); + ABC_FREE( pMatrix ); /* // simple @@ -1357,7 +1363,7 @@ Gia_Man_t * Str_NtkBalance( Gia_Man_t * pGia, Str_Ntk_t * p, int nLutSize, int f ABC_FREE( pNew->vCopies.pArray ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); - pNew = Gia_ManDupNoMuxes( pTemp = pNew ); + pNew = Gia_ManDupNoMuxes( pTemp = pNew, 0 ); Gia_ManStop( pTemp ); // if ( pGia->pManTime != NULL ) // pNew->pManTime = Tim_ManDup( (Tim_Man_t *)pGia->pManTime, 0 ); diff --git a/abc/src/aig/gia/giaSupps.c b/abc/src/aig/gia/giaSupps.c new file mode 100644 index 00000000000..96721d66b96 --- /dev/null +++ b/abc/src/aig/gia/giaSupps.c @@ -0,0 +1,957 @@ +/**CFile**************************************************************** + + FileName [giaSupp.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Support computation manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSupp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig/gia/gia.h" +#include "base/main/mainInt.h" +#include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" +#include "misc/vec/vecHsh.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Supp_Man_t_ Supp_Man_t; +struct Supp_Man_t_ +{ + // user data + int nIters; // optimization rounds + int nRounds; // optimization rounds + int nWords; // the number of simulation words + int nDivWords; // the number of divisor words + Vec_Wrd_t * vIsfs; // functions to synthesize + Vec_Int_t * vCands; // candidate divisors + Vec_Int_t * vWeights; // divisor weights (optional) + Vec_Wrd_t * vSims; // simulation values + Vec_Wrd_t * vSimsC; // simulation values + Gia_Man_t * pGia; // used for object names + // computed data + Vec_Wrd_t * vDivs[2]; // simulation values + Vec_Wrd_t * vDivsC[2]; // simulation values + Vec_Wrd_t * vPats[2]; // simulation values + Vec_Ptr_t * vMatrix; // simulation values + Vec_Wrd_t * vMask; // simulation values + Vec_Wrd_t * vRowTemp; // simulation values + Vec_Int_t * vCosts; // candidate costs + Hsh_VecMan_t * pHash; // subsets considered + Vec_Wrd_t * vSFuncs; // ISF storage + Vec_Int_t * vSStarts; // subset function starts + Vec_Int_t * vSCount; // subset function count + Vec_Int_t * vSPairs; // subset pair count + Vec_Int_t * vTemp; // temporary + Vec_Int_t * vTempSets; // temporary + Vec_Int_t * vTempPairs; // temporary + Vec_Wec_t * vSolutions; // solutions for each node count +}; + +extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Supp_ManFuncInit( Vec_Wrd_t * vFuncs, int nWords ) +{ + int i, k = 0, nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc0 = Vec_WrdEntryP(vFuncs, (2*i+0)*nWords); + word * pFunc1 = Vec_WrdEntryP(vFuncs, (2*i+1)*nWords); + if ( Abc_TtIsConst0(pFunc0, nWords) || Abc_TtIsConst0(pFunc1, nWords) ) + continue; + if ( k < i ) Abc_TtCopy( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), pFunc0, nWords, 0 ); + if ( k < i ) Abc_TtCopy( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), pFunc1, nWords, 0 ); + k++; + } + Vec_WrdShrink( vFuncs, 2*k*nWords ); + return k; +} +int Supp_ManCostInit( Vec_Wrd_t * vFuncs, int nWords ) +{ + int Res = 0, i, nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc0 = Vec_WrdEntryP(vFuncs, (2*i+0)*nWords); + word * pFunc1 = Vec_WrdEntryP(vFuncs, (2*i+1)*nWords); + Res += Abc_TtCountOnesVec(pFunc0, nWords) * Abc_TtCountOnesVec(pFunc1, nWords); + } + assert( nFuncs < 128 ); + assert( Res < (1 << 24) ); + return (nFuncs << 24) | Res; +} +void Supp_ManInit( Supp_Man_t * p ) +{ + int Value, nFuncs, iSet = Hsh_VecManAdd( p->pHash, p->vTemp ); // empty set + assert( iSet == 0 ); + Vec_IntPush( p->vSStarts, Vec_WrdSize(p->vSFuncs) ); + Vec_WrdAppend( p->vSFuncs, p->vIsfs ); + nFuncs = Supp_ManFuncInit( p->vSFuncs, p->nWords ); + assert( Vec_WrdSize(p->vSFuncs) == 2 * nFuncs * p->nWords ); + Value = Supp_ManCostInit(p->vSFuncs, p->nWords); + Vec_IntPush( p->vSCount, Value >> 24 ); + Vec_IntPush( p->vSPairs, Value & 0xFFFFFF ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Supp_DeriveLines( Supp_Man_t * p ) +{ + int n, i, iObj, nWords = p->nWords; + int nDivWords = Abc_Bit6WordNum( Vec_IntSize(p->vCands) ); + //Vec_IntPrint( p->vCands ); + for ( n = 0; n < 2; n++ ) + { + p->vDivs[n] = Vec_WrdStart( 64*nWords*nDivWords ); + p->vPats[n] = Vec_WrdStart( 64*nWords*nDivWords ); + //p->vDivsC[n] = Vec_WrdStart( 64*nWords*nDivWords ); + if ( p->vSimsC ) + Vec_IntForEachEntry( p->vCands, iObj, i ) + Abc_TtAndSharp( Vec_WrdEntryP(p->vDivsC[n], i*nWords), Vec_WrdEntryP(p->vSimsC, iObj*nWords), Vec_WrdEntryP(p->vSims, iObj*nWords), nWords, !n ); + else + Vec_IntForEachEntry( p->vCands, iObj, i ) + Abc_TtCopy( Vec_WrdEntryP(p->vDivs[n], i*nWords), Vec_WrdEntryP(p->vSims, iObj*nWords), nWords, !n ); + Extra_BitMatrixTransposeP( p->vDivs[n], nWords, p->vPats[n], nDivWords ); + } + return nDivWords; +} +Supp_Man_t * Supp_ManCreate( Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vWeights, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsC, int nWords, Gia_Man_t * pGia, int nIters, int nRounds ) +{ + Supp_Man_t * p = ABC_CALLOC( Supp_Man_t, 1 ); + p->nIters = nIters; + p->nRounds = nRounds; + p->nWords = nWords; + p->vIsfs = vIsfs; + p->vCands = vCands; + p->vWeights = vWeights; + p->vSims = vSims; + p->vSimsC = vSimsC; + p->pGia = pGia; + // computed data + p->nDivWords = Supp_DeriveLines( p ); + p->vMatrix = Vec_PtrAlloc( 100 ); + p->vMask = Vec_WrdAlloc( 100 ); + p->vRowTemp = Vec_WrdStart( 64*p->nDivWords ); + p->vCosts = Vec_IntStart( Vec_IntSize(p->vCands) ); + p->pHash = Hsh_VecManStart( 1000 ); + p->vSFuncs = Vec_WrdAlloc( 1000 ); + p->vSStarts = Vec_IntAlloc( 1000 ); + p->vSCount = Vec_IntAlloc( 1000 ); + p->vSPairs = Vec_IntAlloc( 1000 ); + p->vSolutions = Vec_WecStart( 16 ); + p->vTemp = Vec_IntAlloc( 10 ); + p->vTempSets = Vec_IntAlloc( 10 ); + p->vTempPairs = Vec_IntAlloc( 10 ); + Supp_ManInit( p ); + return p; +} +void Supp_ManCleanMatrix( Supp_Man_t * p ) +{ + Vec_Wrd_t * vTemp; int i; + Vec_PtrForEachEntry( Vec_Wrd_t *, p->vMatrix, vTemp, i ) + Vec_WrdFreeP( &vTemp ); + Vec_PtrClear( p->vMatrix ); +} +void Supp_ManDelete( Supp_Man_t * p ) +{ + Supp_ManCleanMatrix( p ); + Vec_WrdFreeP( &p->vDivs[0] ); + Vec_WrdFreeP( &p->vDivs[1] ); + Vec_WrdFreeP( &p->vDivsC[0] ); + Vec_WrdFreeP( &p->vDivsC[1] ); + Vec_WrdFreeP( &p->vPats[0] ); + Vec_WrdFreeP( &p->vPats[1] ); + Vec_PtrFreeP( &p->vMatrix ); + Vec_WrdFreeP( &p->vMask ); + Vec_WrdFreeP( &p->vRowTemp ); + Vec_IntFreeP( &p->vCosts ); + Hsh_VecManStop( p->pHash ); + Vec_WrdFreeP( &p->vSFuncs ); + Vec_IntFreeP( &p->vSStarts ); + Vec_IntFreeP( &p->vSCount ); + Vec_IntFreeP( &p->vSPairs ); + Vec_WecFreeP( &p->vSolutions ); + Vec_IntFreeP( &p->vTemp ); + Vec_IntFreeP( &p->vTempSets ); + Vec_IntFreeP( &p->vTempPairs ); + ABC_FREE( p ); +} +int Supp_ManMemory( Supp_Man_t * p ) +{ + int nMem = sizeof(Supp_Man_t); + nMem += 2*(int)Vec_WrdMemory( p->vDivs[0] ); + nMem += 2*(int)Vec_WrdMemory( p->vPats[0] ); + nMem += (Vec_PtrSize(p->vMatrix)+1)*(int)Vec_WrdMemory( p->vRowTemp ); + nMem += (int)Vec_WrdMemory( p->vMask ); + nMem += (int)Vec_IntMemory( p->vCosts ); + nMem += (int)Hsh_VecManMemory( p->pHash ); + nMem += (int)Vec_WrdMemory( p->vSFuncs ); + nMem += (int)Vec_IntMemory( p->vSStarts ); + nMem += (int)Vec_IntMemory( p->vSCount ); + nMem += (int)Vec_IntMemory( p->vSPairs ); + nMem += (int)Vec_WecMemory( p->vSolutions ); + nMem += (int)Vec_IntMemory( p->vTemp ); + nMem += (int)Vec_IntMemory( p->vTempSets ); + nMem += (int)Vec_IntMemory( p->vTempPairs ); + return nMem; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Supp_ArrayWeight( Vec_Int_t * vRes, Vec_Int_t * vWeights ) +{ + int i, iObj, Cost = 0; + if ( !vWeights ) + return Vec_IntSize(vRes); + Vec_IntForEachEntry( vRes, iObj, i ) + Cost += Vec_IntEntry(vWeights, iObj); + return Cost; +} +int Supp_SetWeight( Supp_Man_t * p, int iSet ) +{ + return Supp_ArrayWeight( Hsh_VecReadEntry(p->pHash, iSet), p->vWeights ); +} +int Supp_SetSize( Supp_Man_t * p, int iSet ) +{ + return Vec_IntSize( Hsh_VecReadEntry(p->pHash, iSet) ); +} +int Supp_SetFuncNum( Supp_Man_t * p, int iSet ) +{ + return Vec_IntEntry(p->vSCount, iSet); +} +int Supp_SetPairNum( Supp_Man_t * p, int iSet ) +{ + return Vec_IntEntry(p->vSPairs, iSet); +} +void Supp_SetConvert( Vec_Int_t * vSet, Vec_Int_t * vCands ) +{ + int i, iObj; + Vec_IntForEachEntry( vSet, iObj, i ) + Vec_IntWriteEntry( vSet, i, Vec_IntEntry(vCands, iObj) ); +} +void Supp_PrintNodes( Gia_Man_t * pGia, Vec_Int_t * vObjs, int Skip, int Limit ) +{ + int i, iObj; + //printf( "Considering %d targets: ", Vec_IntSize(vObjs) ); + Vec_IntForEachEntryStart( vObjs, iObj, i, Skip ) + { + if ( iObj < 0 ) + continue; + printf( "(%d)", iObj ); + if ( pGia && pGia->vWeights && Vec_IntEntry(pGia->vWeights, iObj) > 0 ) + printf( "(%d)", Vec_IntEntry(pGia->vWeights, iObj) ); + if ( pGia ) + printf( " %s ", Gia_ObjName(pGia, iObj)+2 ); + else + printf( " n%d ", iObj ); + if ( i >= Limit ) + { + printf( "... " ); + break; + } + } + printf( "Cost = %d", Supp_ArrayWeight(vObjs, pGia ? pGia->vWeights : NULL) ); + printf( "\n" ); +} +void Supp_PrintOne( Supp_Man_t * p, int iSet ) +{ + Vec_Int_t * vSet = Hsh_VecReadEntry(p->pHash, iSet); + printf( "Set %5d : ", iSet ); + printf( "Funcs %2d ", Supp_SetFuncNum(p, iSet) ); + printf( "Pairs %4d ", Supp_SetPairNum(p, iSet) ); + printf( "Start %8d ", Vec_IntEntry(p->vSStarts, iSet) ); + printf( "Weight %4d ", Supp_ArrayWeight(vSet, p->vWeights) ); + Vec_IntClearAppend( p->vTemp, vSet ); + Supp_SetConvert( p->vTemp, p->vCands ); + Supp_PrintNodes( p->pGia, p->vTemp, 0, 6 ); +} +int Supp_ManRefine1( Supp_Man_t * p, int iSet, int iObj ) +{ + word * pSet = Vec_WrdEntryP( p->vSims, Vec_IntEntry(p->vCands, iObj)*p->nWords ); + word * pIsf; int nFuncs = Vec_IntEntry(p->vSCount, iSet); + int i, n, f, w, nFuncsNew = 0, Mark = Vec_WrdSize(p->vSFuncs), Res = 0; + if ( Vec_WrdSize(p->vSFuncs) + 4*nFuncs*p->nWords > Vec_WrdCap(p->vSFuncs) ) + Vec_WrdGrow( p->vSFuncs, 2*Vec_WrdCap(p->vSFuncs) ); + pIsf = Vec_WrdEntryP( p->vSFuncs, Vec_IntEntry(p->vSStarts, iSet) ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc[2] = { pIsf + (2*i+0)*p->nWords, pIsf + (2*i+1)*p->nWords }; + for ( f = 0; f < 2; f++ ) + { + int nOnes[2], Start = Vec_WrdSize(p->vSFuncs); + for ( n = 0; n < 2; n++ ) + { + word * pLimit = Vec_WrdLimit(p->vSFuncs); + if ( f ) + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[n][w] & pSet[w] ); + else + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[n][w] & ~pSet[w] ); + nOnes[n] = Abc_TtCountOnesVec( pLimit, p->nWords ); + } + if ( nOnes[0] && nOnes[1] ) + Res += nOnes[0] * nOnes[1]; + else + Vec_WrdShrink( p->vSFuncs, Start ); + } + } + assert( Res < (1 << 24) ); + nFuncsNew = (Vec_WrdSize(p->vSFuncs) - Mark)/2/p->nWords; + assert( nFuncsNew < 128 ); + assert( nFuncsNew >= 0 && nFuncsNew <= 2*nFuncs ); + return (nFuncsNew << 24) | Res; +} +void Supp_ManRefine( Supp_Man_t * p, int iSet, int iObj, int * pnFuncs, int * pnPairs ) +{ + word * pDivs0 = Vec_WrdEntryP( p->vDivs[0], iObj*p->nWords ); + word * pDivs1 = Vec_WrdEntryP( p->vDivs[1], iObj*p->nWords ); + word * pIsf; int nFuncs = Supp_SetFuncNum(p, iSet); + int i, f, w, nFuncsNew = 0, Mark = Vec_WrdSize(p->vSFuncs), Res = 0; + if ( Vec_WrdSize(p->vSFuncs) + 6*nFuncs*p->nWords > Vec_WrdCap(p->vSFuncs) ) + Vec_WrdGrow( p->vSFuncs, 2*Vec_WrdCap(p->vSFuncs) ); + if ( Vec_WrdSize(p->vSFuncs) == Vec_IntEntry(p->vSStarts, iSet) ) + pIsf = Vec_WrdLimit( p->vSFuncs ); + else + pIsf = Vec_WrdEntryP( p->vSFuncs, Vec_IntEntry(p->vSStarts, iSet) ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc[2] = { pIsf + (2*i+0)*p->nWords, pIsf + (2*i+1)*p->nWords }; + for ( f = 0; f < 3; f++ ) + { + int nOnes[2], Start = Vec_WrdSize(p->vSFuncs); + word * pLimit[2] = { Vec_WrdLimit(p->vSFuncs), Vec_WrdLimit(p->vSFuncs) + p->nWords }; + if ( f == 0 ) + { + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[0][w] & pDivs0[w] ); + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[1][w] & ~pDivs1[w] ); + } + else if ( f == 1 ) + { + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[0][w] & pDivs1[w] ); + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[1][w] & ~pDivs0[w] ); + } + else + { + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[0][w] & ~pDivs0[w] & ~pDivs1[w] ); + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[1][w] ); + } + nOnes[0] = Abc_TtCountOnesVec( pLimit[0], p->nWords ); + nOnes[1] = Abc_TtCountOnesVec( pLimit[1], p->nWords ); + if ( nOnes[0] && nOnes[1] ) + Res += nOnes[0] * nOnes[1]; + else + Vec_WrdShrink( p->vSFuncs, Start ); + } + } + assert( Res < (1 << 24) ); + nFuncsNew = (Vec_WrdSize(p->vSFuncs) - Mark)/2/p->nWords; + *pnFuncs = nFuncsNew; + *pnPairs = Res; +} +int Supp_ManSubsetAdd( Supp_Man_t * p, int iSet, int iObj, int fVerbose ) +{ + int iSetNew, nEntries = Hsh_VecSize( p->pHash ); + Vec_Int_t * vSet = Hsh_VecReadEntry( p->pHash, iSet ); + Vec_IntClear( p->vTemp ); + Vec_IntAppend( p->vTemp, vSet ); + Vec_IntPushOrder( p->vTemp, iObj ); + assert( Vec_IntIsOrdered(p->vTemp, 0) ); + iSetNew = Hsh_VecManAdd( p->pHash, p->vTemp ); + if ( iSetNew == nEntries ) // new entry + { + int nFuncs, nPairs; + Vec_IntPush( p->vSStarts, Vec_WrdSize(p->vSFuncs) ); + Supp_ManRefine( p, iSet, iObj, &nFuncs, &nPairs ); + Vec_IntPush( p->vSCount, nFuncs ); + Vec_IntPush( p->vSPairs, nPairs ); + assert( Hsh_VecSize(p->pHash) == Vec_IntSize(p->vSStarts) ); + assert( Hsh_VecSize(p->pHash) == Vec_IntSize(p->vSCount) ); + assert( Hsh_VecSize(p->pHash) == Vec_IntSize(p->vSPairs) ); + if ( Supp_SetFuncNum(p, iSetNew) == 0 && Supp_SetSize(p, iSetNew) < Vec_WecSize(p->vSolutions) ) + Vec_WecPush( p->vSolutions, Supp_SetSize(p, iSetNew), iSetNew ); + if ( fVerbose ) + Supp_PrintOne( p, iSetNew ); + } + return iSetNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Supp_ComputePair1( Supp_Man_t * p, int iSet ) +{ + int Random = 0xFFFFFF & Abc_Random(0); + int nFuncs = Vec_IntEntry(p->vSCount, iSet); + int iFunc = Random % nFuncs; + word * pIsf = Vec_WrdEntryP( p->vSFuncs, Vec_IntEntry(p->vSStarts, iSet) ); + word * pFunc[2] = { pIsf + (2*iFunc+0)*p->nWords, pIsf + (2*iFunc+1)*p->nWords }; + int iBit0 = ((Random >> 16) & 1) ? Abc_TtFindFirstBit2(pFunc[0], p->nWords) : Abc_TtFindLastBit2(pFunc[0], p->nWords); + int iBit1 = ((Random >> 17) & 1) ? Abc_TtFindFirstBit2(pFunc[1], p->nWords) : Abc_TtFindLastBit2(pFunc[1], p->nWords); + if ( 1 ) + { + Vec_Int_t * vSet = Hsh_VecReadEntry( p->pHash, iSet ); int i, iObj; + Vec_IntForEachEntry( vSet, iObj, i ) + { + word * pSet = Vec_WrdEntryP( p->vSims, Vec_IntEntry(p->vCands, iObj)*p->nWords ); + assert( Abc_TtGetBit(pSet, iBit0) == Abc_TtGetBit(pSet, iBit1) ); + } + } + return (iBit0 << 16) | iBit1; +} +int Supp_ComputePair( Supp_Man_t * p, int iSet ) +{ + int Random = 0xFFFFFF & Abc_Random(0); + int nFuncs = Vec_IntEntry(p->vSCount, iSet); + int iFunc = Random % nFuncs; + word * pIsf = Vec_WrdEntryP( p->vSFuncs, Vec_IntEntry(p->vSStarts, iSet) ); + word * pFunc[2] = { pIsf + (2*iFunc+0)*p->nWords, pIsf + (2*iFunc+1)*p->nWords }; + int iBit0 = ((Random >> 16) & 1) ? Abc_TtFindFirstBit2(pFunc[0], p->nWords) : Abc_TtFindLastBit2(pFunc[0], p->nWords); + int iBit1 = ((Random >> 17) & 1) ? Abc_TtFindFirstBit2(pFunc[1], p->nWords) : Abc_TtFindLastBit2(pFunc[1], p->nWords); + if ( 1 ) + { + Vec_Int_t * vSet = Hsh_VecReadEntry( p->pHash, iSet ); int i, iObj; + Vec_IntForEachEntry( vSet, iObj, i ) + { + word * pSet0 = Vec_WrdEntryP( p->vDivs[0], iObj*p->nWords ); + word * pSet1 = Vec_WrdEntryP( p->vDivs[1], iObj*p->nWords ); + int Value00 = Abc_TtGetBit(pSet0, iBit0); + int Value01 = Abc_TtGetBit(pSet0, iBit1); + int Value10 = Abc_TtGetBit(pSet1, iBit0); + int Value11 = Abc_TtGetBit(pSet1, iBit1); + assert( !Value00 || !Value11 ); + assert( !Value01 || !Value10 ); + } + } + return (iBit0 << 16) | iBit1; +} +Vec_Int_t * Supp_Compute64Pairs( Supp_Man_t * p, Vec_Int_t * vSets ) +{ + int i; + Vec_IntClear( p->vTempPairs ); + for ( i = 0; i < 64; i++ ) + { + int Rand = 0xFFFFFF & Abc_Random(0); + int iSet = Vec_IntEntry( vSets, Rand % Vec_IntSize(vSets) ); + Vec_IntPush( p->vTempPairs, Supp_ComputePair(p, iSet) ); + } + return p->vTempPairs; +} +void Supp_ManFillBlock( Supp_Man_t * p, Vec_Int_t * vPairs, Vec_Wrd_t * vRes ) +{ + int i, Pair; + assert( Vec_IntSize(vPairs) == 64 ); + Vec_IntForEachEntry( vPairs, Pair, i ) + { + int iBit0 = Pair >> 16, iBit1 = Pair & 0xFFFF; + word * pPat00 = Vec_WrdEntryP(p->vPats[0], iBit0*p->nDivWords); + word * pPat01 = Vec_WrdEntryP(p->vPats[0], iBit1*p->nDivWords); + word * pPat10 = Vec_WrdEntryP(p->vPats[1], iBit0*p->nDivWords); + word * pPat11 = Vec_WrdEntryP(p->vPats[1], iBit1*p->nDivWords); + word * pPat = Vec_WrdEntryP(p->vRowTemp, i*p->nDivWords); + Abc_TtAnd( pPat, pPat00, pPat11, p->nDivWords, 0 ); + Abc_TtOrAnd( pPat, pPat01, pPat10, p->nDivWords ); + } + Extra_BitMatrixTransposeP( p->vRowTemp, p->nDivWords, vRes, 1 ); +} +void Supp_ManAddPatterns( Supp_Man_t * p, Vec_Int_t * vSets ) +{ + Vec_Int_t * vPairs = Supp_Compute64Pairs( p, vSets ); + Vec_Wrd_t * vRow = Vec_WrdStart( 64*p->nDivWords ); + Supp_ManFillBlock( p, vPairs, vRow ); + Vec_PtrPush( p->vMatrix, vRow ); +} +Vec_Int_t * Supp_ManCollectOnes( word * pSim, int nWords ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); int i; + for ( i = 0; i < 64*nWords; i++ ) + if ( Abc_TtGetBit(pSim, i) ) + Vec_IntPush( vRes, i ); + return vRes; +} +Vec_Int_t * Supp_Compute64PairsFunc( Supp_Man_t * p, Vec_Int_t * vBits0, Vec_Int_t * vBits1 ) +{ + int i; + Vec_IntClear( p->vTempPairs ); + for ( i = 0; i < 64; i++ ) + { + int Random = 0xFFFFFF & Abc_Random(0); + int iBit0 = Vec_IntEntry( vBits0, (Random & 0xFFF) % Vec_IntSize(vBits0) ); + int iBit1 = Vec_IntEntry( vBits1, (Random >> 12) % Vec_IntSize(vBits1) ); + Vec_IntPush( p->vTempPairs, (iBit0 << 16) | iBit1 ); + } + return p->vTempPairs; +} +void Supp_ManAddPatternsFunc( Supp_Man_t * p, int nBatches ) +{ + int b; + Vec_Int_t * vBits0 = Supp_ManCollectOnes( Vec_WrdEntryP(p->vSFuncs, 0*p->nWords), p->nWords ); + Vec_Int_t * vBits1 = Supp_ManCollectOnes( Vec_WrdEntryP(p->vSFuncs, 1*p->nWords), p->nWords ); + for ( b = 0; b < nBatches; b++ ) + { + Vec_Int_t * vPairs = Supp_Compute64PairsFunc( p, vBits0, vBits1 ); + Vec_Wrd_t * vRow = Vec_WrdStart( 64*p->nDivWords ); + Supp_ManFillBlock( p, vPairs, vRow ); + Vec_PtrPush( p->vMatrix, vRow ); + } + Vec_IntFree( vBits0 ); + Vec_IntFree( vBits1 ); +} +int Supp_FindNextDiv( Supp_Man_t * p, int Pair ) +{ + int iDiv, iBit0 = Pair >> 16, iBit1 = Pair & 0xFFFF; + word * pPat00 = Vec_WrdEntryP(p->vPats[0], iBit0*p->nDivWords); + word * pPat01 = Vec_WrdEntryP(p->vPats[0], iBit1*p->nDivWords); + word * pPat10 = Vec_WrdEntryP(p->vPats[1], iBit0*p->nDivWords); + word * pPat11 = Vec_WrdEntryP(p->vPats[1], iBit1*p->nDivWords); + int iDiv1 = Abc_TtFindFirstAndBit2( pPat00, pPat11, p->nDivWords ); + int iDiv2 = Abc_TtFindFirstAndBit2( pPat01, pPat10, p->nDivWords ); + iDiv1 = iDiv1 == -1 ? ABC_INFINITY : iDiv1; + iDiv2 = iDiv2 == -1 ? ABC_INFINITY : iDiv2; + iDiv = Abc_MinInt( iDiv1, iDiv2 ); + assert( iDiv >= 0 && iDiv < Vec_IntSize(p->vCands) ); + return iDiv; +} +int Supp_ManRandomSolution( Supp_Man_t * p, int iSet, int fVerbose ) +{ + Vec_IntClear( p->vTempSets ); + while ( Supp_SetFuncNum(p, iSet) > 0 ) + { + int Pair = Supp_ComputePair( p, iSet ); + int iDiv = Supp_FindNextDiv( p, Pair ); + iSet = Supp_ManSubsetAdd( p, iSet, iDiv, fVerbose ); + if ( Supp_SetFuncNum(p, iSet) > 0 ) + Vec_IntPush( p->vTempSets, iSet ); + } + if ( Vec_IntSize(p->vTempSets) < 2 ) + return iSet; + Supp_ManAddPatterns( p, p->vTempSets ); + return iSet; +} +int Supp_ManSubsetRemove( Supp_Man_t * p, int iSet, int iPos ) +{ + int i, iSetNew = 0, nSize = Supp_SetSize(p, iSet); + for ( i = 0; i < nSize; i++ ) + if ( i != iPos && Supp_SetFuncNum(p, iSetNew) > 0 ) + iSetNew = Supp_ManSubsetAdd( p, iSetNew, Vec_IntEntry(Hsh_VecReadEntry(p->pHash, iSet), i), 0 ); + return iSetNew; +} +int Supp_ManMinimize( Supp_Man_t * p, int iSet0, int r, int fVerbose ) +{ + int i, nSize = Supp_SetSize(p, iSet0); + Vec_Int_t * vPerm = Vec_IntStartNatural( Supp_SetSize(p, iSet0) ); + Vec_IntRandomizeOrder( vPerm ); + Vec_IntClear( p->vTempSets ); + if ( fVerbose ) + printf( "Removing items from %d:\n", iSet0 ); + // make sure we first try to remove items with higher weight + for ( i = 0; i < nSize; i++ ) + { + int Index = Vec_IntEntry( vPerm, i ); + int iSet = Supp_ManSubsetRemove( p, iSet0, Index ); + if ( fVerbose ) + printf( "Item %2d : ", Index ); + if ( fVerbose ) + Supp_PrintOne( p, iSet ); + if ( Supp_SetFuncNum(p, iSet) == 0 ) + { + Vec_IntFree( vPerm ); + return Supp_ManMinimize( p, iSet, r, fVerbose ); + } + Vec_IntPush( p->vTempSets, iSet ); + } + Supp_ManAddPatterns( p, p->vTempSets ); + Vec_IntFree( vPerm ); + return iSet0; +} +int Supp_ManFindNextObj( Supp_Man_t * p, int fVerbose ) +{ + Vec_Wrd_t * vTemp; int r, k, iDiv; + word Sim, * pMask = Vec_WrdArray(p->vMask); + assert( Vec_WrdSize(p->vMask) == Vec_PtrSize(p->vMatrix) ); + Vec_IntFill( p->vCosts, Vec_IntSize(p->vCosts), 0 ); + Vec_PtrForEachEntry( Vec_Wrd_t *, p->vMatrix, vTemp, r ) + Vec_WrdForEachEntryStop( vTemp, Sim, k, Vec_IntSize(p->vCosts) ) + Vec_IntAddToEntry( p->vCosts, k, Abc_TtCountOnes(Sim & pMask[r]) ); + iDiv = Vec_IntArgMax( p->vCosts ); + if ( fVerbose ) + printf( "Choosing divisor %d with weight %d.\n", iDiv, Vec_IntEntry(p->vCosts, iDiv) ); + Vec_PtrForEachEntry( Vec_Wrd_t *, p->vMatrix, vTemp, r ) + pMask[r] &= ~Vec_WrdEntry( vTemp, iDiv ); + return iDiv; +} +int Supp_ManReconstruct( Supp_Man_t * p, int fVerbose ) +{ + int iSet = 0; + Vec_WrdFill( p->vMask, Vec_PtrSize(p->vMatrix), ~(word)0 ); + if ( fVerbose ) + printf( "\nBuilding a new set:\n" ); + while ( Supp_SetPairNum(p, iSet) ) + { + int iDiv = Supp_ManFindNextObj( p, fVerbose ); + iSet = Supp_ManSubsetAdd( p, iSet, iDiv, fVerbose ); + if ( Abc_TtIsConst0(Vec_WrdArray(p->vMask), Vec_WrdSize(p->vMask)) ) + break; + } + if ( fVerbose ) + printf( "Adding random part:\n" ); + return Supp_ManRandomSolution( p, iSet, fVerbose ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int s_Counter = 0; + +void Supp_DeriveDumpSims( FILE * pFile, Vec_Wrd_t * vDivs, int nWords ) +{ + int i, k, nDivs = Vec_WrdSize(vDivs)/nWords; + for ( i = 0; i < nDivs; i++ ) + { + word * pSim = Vec_WrdEntryP(vDivs, i*nWords); + for ( k = 0; k < 64*nWords; k++ ) + fprintf( pFile, "%c", '0'+Abc_TtGetBit(pSim, k) ); + fprintf( pFile, "\n" ); + } +} +void Supp_DeriveDumpSimsC( FILE * pFile, Vec_Wrd_t * vDivs[2], int nWords ) +{ + int i, k, nDivs = Vec_WrdSize(vDivs[0])/nWords; + for ( i = 0; i < nDivs; i++ ) + { + word * pSim0 = Vec_WrdEntryP(vDivs[0], i*nWords); + word * pSim1 = Vec_WrdEntryP(vDivs[1], i*nWords); + for ( k = 0; k < 64*nWords; k++ ) + if ( Abc_TtGetBit(pSim0, k) ) + fprintf( pFile, "0" ); + else if ( Abc_TtGetBit(pSim1, k) ) + fprintf( pFile, "1" ); + else + fprintf( pFile, "-" ); + fprintf( pFile, "\n" ); + } +} +void Supp_DeriveDumpProb( Vec_Wrd_t * vIsfs, Vec_Wrd_t * vDivs, int nWords ) +{ + char Buffer[100]; int nDivs = Vec_WrdSize(vDivs)/nWords; + int RetValue = sprintf( Buffer, "%02d.resub", 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, "%d %d %d %d\n", 0, nDivs, 1, 64*nWords ); + Supp_DeriveDumpSims( pFile, vDivs, nWords ); + Supp_DeriveDumpSims( pFile, vIsfs, nWords ); + fclose ( pFile ); + RetValue = 0; +} +void Supp_DeriveDumpProbC( Vec_Wrd_t * vIsfs, Vec_Wrd_t * vDivs[2], int nWords ) +{ + char Buffer[100]; int nDivs = Vec_WrdSize(vDivs[0])/nWords; + int RetValue = sprintf( Buffer, "%02d.resub", 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, "%d %d %d %d\n", 0, nDivs, 1, 64*nWords ); + Supp_DeriveDumpSimsC( pFile, vDivs, nWords ); + Supp_DeriveDumpSims( pFile, vIsfs, nWords ); + fclose ( pFile ); + RetValue = 0; +} +void Supp_DeriveDumpSol( Vec_Int_t * vSet, Vec_Int_t * vRes, int nDivs ) +{ + char Buffer[100]; + int RetValue = sprintf( Buffer, "%02d.sol", s_Counter ); + int i, iLit, iLitRes = -1, nSupp = Vec_IntSize(vSet); + FILE * pFile = fopen( Buffer, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open output file.\n" ); + fprintf( pFile, "sol name aig %d\n", Vec_IntSize(vRes)/2 ); + //Vec_IntPrint( vSet ); + //Vec_IntPrint( vRes ); + Vec_IntForEachEntry( vRes, iLit, i ) + { + assert( iLit != 2 && iLit != 3 ); + if ( iLit < 2 ) + iLitRes = iLit; + else if ( iLit-4 < 2*nSupp ) + { + int iDiv = Vec_IntEntry(vSet, Abc_Lit2Var(iLit-4)); + assert( iDiv >= 0 && iDiv < nDivs ); + iLitRes = Abc_Var2Lit(1+iDiv, Abc_LitIsCompl(iLit)); + } + else + iLitRes = iLit + 2*((nDivs+1)-(nSupp+2)); + fprintf( pFile, "%d ", iLitRes ); + } + if ( Vec_IntSize(vRes) & 1 ) + fprintf( pFile, "%d ", iLitRes ); + fprintf( pFile, "\n" ); + fclose( pFile ); + RetValue = 0; + printf( "Dumped solution info file \"%s\".\n", Buffer ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Supp_ManFindBestSolution( Supp_Man_t * p, Vec_Wec_t * vSols, int fVerbose, Vec_Int_t ** pvDivs ) +{ + Vec_Int_t * vLevel, * vRes = NULL; + int i, k, iSet, nFuncs = 0, Count = 0; + int iSolBest = -1, Cost, CostBest = ABC_INFINITY; + Vec_WecForEachLevel( vSols, vLevel, i ) + { + Count += Vec_IntSize(vLevel) > 0; + Vec_IntForEachEntry( vLevel, iSet, k ) + { + if ( fVerbose ) + printf( "%3d : ", nFuncs++ ); + Cost = Gia_ManEvalSolutionOne( p->pGia, p->vSims, p->vIsfs, p->vCands, Hsh_VecReadEntry(p->pHash, iSet), p->nWords, fVerbose ); + if ( Cost == -1 ) + continue; + if ( CostBest > Cost ) + { + CostBest = Cost; + iSolBest = iSet; + } + if ( nFuncs > 5 ) + break; + } + if ( Count == 2 || k < Vec_IntSize(vLevel) ) + break; + } + if ( iSolBest > 0 && (CostBest >> 2) < 50 ) + { + Vec_Int_t * vSet = Hsh_VecReadEntry( p->pHash, iSolBest ); int i, iObj; + vRes = Gia_ManDeriveSolutionOne( p->pGia, p->vSims, p->vIsfs, p->vCands, vSet, p->nWords, CostBest & 3 ); + assert( !vRes || Vec_IntSize(vRes) == 2*(CostBest >> 2)+1 ); + if ( vRes && pvDivs ) + { + Vec_IntClear( *pvDivs ); + Vec_IntPushTwo( *pvDivs, -1, -1 ); + Vec_IntForEachEntry( vSet, iObj, i ) + Vec_IntPush( *pvDivs, Vec_IntEntry(p->vCands, iObj) ); + } + //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++; + } + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Supp_FindGivenOne( Supp_Man_t * p ) +{ + int i, iObj, iSet = 0; + Vec_Int_t * vSet = Vec_IntStart( 2 ); + //extern void Patch_GenerateSet11( Gia_Man_t * p, Vec_Int_t * vDivs, Vec_Int_t * vCands ); + //Patch_GenerateSet11( p->pGia, vSet, p->vCands ); + Vec_IntDrop( vSet, 0 ); + Vec_IntDrop( vSet, 0 ); + Vec_IntForEachEntry( vSet, iObj, i ) + iSet = Supp_ManSubsetAdd( p, iSet, iObj, 1 ); + Vec_IntFree( vSet ); + return iSet; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Supp_ManCompute( Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vWeights, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsC, int nWords, Gia_Man_t * pGia, Vec_Int_t ** pvDivs, int nIters, int nRounds, int fVerbose ) +{ + int fVeryVerbose = 0; + int i, r, iSet, iBest = -1; + abctime clk = Abc_Clock(); + Vec_Int_t * vRes = NULL; + Supp_Man_t * p = Supp_ManCreate( vIsfs, vCands, vWeights, vSims, vSimsC, nWords, pGia, nIters, nRounds ); + if ( Supp_SetFuncNum(p, 0) == 0 ) + { + Supp_ManDelete( p ); + Vec_IntClear( *pvDivs ); + Vec_IntPushTwo( *pvDivs, -1, -1 ); + vRes = Vec_IntAlloc( 1 ); + Vec_IntPush( vRes, Abc_TtIsConst0(Vec_WrdArray(vIsfs), nWords) ); + return vRes; + } + if ( fVerbose ) + printf( "\nUsing %d divisors with %d words. Problem has %d functions and %d minterm pairs.\n", + Vec_IntSize(p->vCands), p->nWords, Supp_SetFuncNum(p, 0), Supp_SetPairNum(p, 0) ); + //iBest = Supp_FindGivenOne( p ); + if ( iBest == -1 ) + for ( i = 0; i < p->nIters; i++ ) + { + Supp_ManAddPatternsFunc( p, i ); + iSet = Supp_ManRandomSolution( p, 0, fVeryVerbose ); + for ( r = 0; r < p->nRounds; r++ ) + { + if ( fVeryVerbose ) + printf( "\n\nITER %d ROUND %d\n", i, r ); + iSet = Supp_ManMinimize( p, iSet, r, fVeryVerbose ); + if ( iBest == -1 || Supp_SetWeight(p, iBest) > Supp_SetWeight(p, iSet) ) + //if ( Supp_SetSize(p, iBest) > Supp_SetSize(p, iSet) ) + { + if ( fVeryVerbose ) + printf( "\nThe best solution found:\n" ); + if ( fVeryVerbose ) + Supp_PrintOne( p, iSet ); + iBest = iSet; + } + iSet = Supp_ManReconstruct( p, fVeryVerbose ); + } + if ( fVeryVerbose ) + printf( "Matrix size %d.\n", Vec_PtrSize(p->vMatrix) ); + Supp_ManCleanMatrix( p ); + } + if ( fVerbose ) + { + printf( "Explored %d divisor sets. Found %d solutions. Memory usage %.2f MB. ", + Hsh_VecSize(p->pHash), Vec_WecSizeSize(p->vSolutions), 1.0*Supp_ManMemory(p)/(1<<20) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + printf( "The best solution: " ); + if ( iBest == -1 ) + printf( "No solution.\n" ); + else + Supp_PrintOne( p, iBest ); + } + vRes = Supp_ManFindBestSolution( p, p->vSolutions, fVerbose, pvDivs ); + //Vec_IntPrint( vRes ); + Supp_ManDelete( p ); +// if ( vRes && Vec_IntSize(vRes) == 0 ) +// Vec_IntFreeP( &vRes ); + return vRes; +} +void Supp_ManComputeTest( Gia_Man_t * p ) +{ + Vec_Wrd_t * vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + Vec_Wrd_t * vSims = Gia_ManSimPatSimOut( p, vSimsPi, 0 ); + int i, iPoId, nWords = Vec_WrdSize(vSimsPi) / Gia_ManCiNum(p); + Vec_Wrd_t * vIsfs = Vec_WrdStart( 2*nWords ); + Vec_Int_t * vCands = Vec_IntAlloc( 4 ); + Vec_Int_t * vRes; + +// for ( i = 0; i < Gia_ManCiNum(p)+5; i++ ) + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + Vec_IntPush( vCands, 1+i ); + + iPoId = Gia_ObjId(p, Gia_ManPo(p, 0)); + Abc_TtCopy( Vec_WrdEntryP(vIsfs, 0*nWords), Vec_WrdEntryP(vSims, iPoId*nWords), nWords, 1 ); + Abc_TtCopy( Vec_WrdEntryP(vIsfs, 1*nWords), Vec_WrdEntryP(vSims, iPoId*nWords), nWords, 0 ); + + vRes = Supp_ManCompute( vIsfs, vCands, NULL, vSims, NULL, nWords, p, NULL, 1, 1, 0 ); + Vec_IntPrint( vRes ); + + Vec_WrdFree( vSimsPi ); + Vec_WrdFree( vSims ); + Vec_WrdFree( vIsfs ); + Vec_IntFree( vCands ); + Vec_IntFree( vRes ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaSweep.c b/abc/src/aig/gia/giaSweep.c index 2d8e705b2c4..8a7fcbd074a 100644 --- a/abc/src/aig/gia/giaSweep.c +++ b/abc/src/aig/gia/giaSweep.c @@ -203,6 +203,7 @@ Gia_Man_t * Gia_ManDupWithBoxes( Gia_Man_t * p, int fSeq ) pNew->pAigExtra = Gia_ManUpdateExtraAig2( p->pManTime, p->pAigExtra, vBoxesLeft ); assert( Gia_ManCiNum(pNew) == Tim_ManPiNum((Tim_Man_t*)pNew->pManTime) + Gia_ManCoNum(pNew->pAigExtra) ); Vec_IntFree( vBoxesLeft ); + pNew->nAnd2Delay = p->nAnd2Delay; return pNew; } @@ -387,6 +388,14 @@ Vec_Int_t * Gia_ManComputeCarryOuts( Gia_Man_t * p ) Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; int i, iLast, iBox, nBoxes = Tim_ManBoxNum( pManTime ); Vec_Int_t * vCarryOuts = Vec_IntAlloc( nBoxes ); + + // Create and populate reference count (and free later) only if not already + // done. + int createRefs = (p->pRefs == NULL); + if (createRefs) { + Gia_ManCreateRefs( p ); + } + for ( i = 0; i < nBoxes; i++ ) { iLast = Tim_ManBoxInputLast( pManTime, i ); @@ -397,9 +406,24 @@ Vec_Int_t * Gia_ManComputeCarryOuts( Gia_Man_t * p ) if ( iBox == -1 ) continue; assert( Gia_ObjIsCi(pObj) ); - if ( Gia_ObjCioId(pObj) == Tim_ManBoxOutputLast(pManTime, iBox) ) + if ( Gia_ObjCioId(pObj) == Tim_ManBoxOutputLast(pManTime, iBox) ) { Vec_IntPush( vCarryOuts, Gia_ObjId(p, pObj) ); + + // We have identified a carry connection. Check if the carry out + // of the destination box is unconnected. If so then add it to + // the carry list as well. + iLast = Tim_ManBoxOutputLast(pManTime, i); + pObj = Gia_ManCi(p, iLast); + if ( Gia_ObjRefNum(p, pObj) == 0 ) { + Vec_IntPush( vCarryOuts, Gia_ObjId(p, pObj) ); + } + } + } + + if (createRefs) { + ABC_FREE( p->pRefs ); } + return vCarryOuts; } diff --git a/abc/src/aig/gia/giaSweeper.c b/abc/src/aig/gia/giaSweeper.c index c1ce596d816..de3f4049524 100644 --- a/abc/src/aig/gia/giaSweeper.c +++ b/abc/src/aig/gia/giaSweeper.c @@ -439,7 +439,7 @@ void Gia_SweeperLogicDump( Gia_Man_t * p, Vec_Int_t * vProbeIds, int fDumpConds, Gia_ManStop( pGiaCond ); printf( " and conditions" ); } - Gia_AigerWrite( pGiaOuts, pFileName, 0, 0 ); + Gia_AigerWrite( pGiaOuts, pFileName, 0, 0, 0 ); Gia_ManStop( pGiaOuts ); printf( " into file \"%s\".\n", pFileName ); } diff --git a/abc/src/aig/gia/giaSwitch.c b/abc/src/aig/gia/giaSwitch.c index b1c5eb8236e..4722ef0f59f 100644 --- a/abc/src/aig/gia/giaSwitch.c +++ b/abc/src/aig/gia/giaSwitch.c @@ -795,6 +795,14 @@ float Gia_ManComputeSwitching( Gia_Man_t * p, int nFrames, int nPref, int fProbO Gia_ManForEachAnd( p, pObj, i ) SwiTotal += pSwi[Gia_ObjFaninId0(pObj, i)] + pSwi[Gia_ObjFaninId1(pObj, i)]; } + if ( 0 ) + { + Gia_ManForEachObj( p, pObj, i ) + { + printf( "Switch %6.2f ", pSwi[i] ); + Gia_ObjPrint( p, pObj ); + } + } Vec_IntFree( vSwitching ); return SwiTotal; } diff --git a/abc/src/aig/gia/giaTim.c b/abc/src/aig/gia/giaTim.c index 22212793679..fc40835cba7 100644 --- a/abc/src/aig/gia/giaTim.c +++ b/abc/src/aig/gia/giaTim.c @@ -730,6 +730,49 @@ Gia_Man_t * Gia_ManUpdateExtraAig2( void * pTime, Gia_Man_t * p, Vec_Int_t * vBo return pNew; } +/**Function************************************************************* + + Synopsis [Duplicates AIG while moving the last CIs to be after PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupMoveLast( Gia_Man_t * p, int iInsert, int nItems ) +{ + 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_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + if ( i < iInsert ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachCi( p, pObj, i ) + if ( i >= Gia_ManCiNum(p) - nItems ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachCi( p, pObj, i ) + if ( i >= iInsert && i < Gia_ManCiNum(p) - nItems ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + continue; + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else assert( 0 ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + /**Function************************************************************* Synopsis [Computes AIG with boxes.] @@ -762,7 +805,7 @@ Gia_Man_t * Gia_ManDupCollapse( Gia_Man_t * p, Gia_Man_t * pBoxes, Vec_Int_t * v Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObjBox; - int i, k, curCi, curCo, nBBins = 0, nBBouts = 0; + int i, k, curCi, curCo, nBBins = 0, nBBouts = 0, nNewPis = 0; assert( !fSeq || p->vRegClasses ); //assert( Gia_ManRegNum(p) == 0 ); assert( Gia_ManCiNum(p) == Tim_ManPiNum(pManTime) + Gia_ManCoNum(pBoxes) ); @@ -810,6 +853,7 @@ Gia_Man_t * Gia_ManDupCollapse( Gia_Man_t * p, Gia_Man_t * pBoxes, Vec_Int_t * v pObj->Value = fSkip ? 0 : Gia_ManAppendCi(pNew); Gia_ObjSetTravIdCurrent( p, pObj ); nBBins++; + nNewPis += !fSkip; } } else @@ -855,8 +899,23 @@ Gia_Man_t * Gia_ManDupCollapse( Gia_Man_t * p, Gia_Man_t * pBoxes, Vec_Int_t * v pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManCleanupRemap( p, pTemp ); Gia_ManStop( pTemp ); - assert( Tim_ManPoNum(pManTime) == Gia_ManCoNum(pNew) - nBBouts ); - assert( Tim_ManPiNum(pManTime) == Gia_ManCiNum(pNew) - nBBins ); + if ( nNewPis ) + { + pNew = Gia_ManDupMoveLast( pTemp = pNew, Tim_ManPiNum(pManTime)-Gia_ManRegNum(pNew), nNewPis ); + Gia_ManCleanupRemap( p, pTemp ); + Gia_ManStop( pTemp ); + } +/* + printf( "%d = %d - %d Diff = %d\n", + Tim_ManPoNum(pManTime), Gia_ManCoNum(pNew), nBBouts, + Tim_ManPoNum(pManTime) - (Gia_ManCoNum(pNew) - nBBouts) ); + + printf( "%d = %d - %d Diff = %d\n\n", + Tim_ManPiNum(pManTime), Gia_ManCiNum(pNew), nBBins, + Tim_ManPiNum(pManTime) - (Gia_ManCiNum(pNew) - nBBins) ); +*/ + assert( vBoxPres != NULL || Tim_ManPoNum(pManTime) == Gia_ManCoNum(pNew) - nBBouts ); + assert( vBoxPres != NULL || Tim_ManPiNum(pManTime) == Gia_ManCiNum(pNew) - nBBins ); // implement initial state if given if ( fSeq && p->vRegInits && Vec_IntSum(p->vRegInits) ) { @@ -874,7 +933,7 @@ Gia_Man_t * Gia_ManDupCollapse( Gia_Man_t * p, Gia_Man_t * pBoxes, Vec_Int_t * v pInit[i] = 'X'; } pInit[i] = 0; - pNew = Gia_ManDupZeroUndc( pTemp = pNew, pInit, 0, 1 ); + pNew = Gia_ManDupZeroUndc( pTemp = pNew, pInit, 0, 0, 1 ); pNew->nConstrs = pTemp->nConstrs; pTemp->nConstrs = 0; Gia_ManStop( pTemp ); ABC_FREE( pInit ); @@ -962,8 +1021,8 @@ int Gia_ManVerifyWithBoxes( Gia_Man_t * pGia, int nBTLimit, int nTimeLim, int fS char * pNameGeneric = Extra_FileNameGeneric( pFileSpec ? pFileSpec : pGia->pSpec ); sprintf( pFileName0, "%s_spec.aig", pNameGeneric ); sprintf( pFileName1, "%s_impl.aig", pNameGeneric ); - Gia_AigerWrite( pGia0, pFileName0, 0, 0 ); - Gia_AigerWrite( pGia1, pFileName1, 0, 0 ); + Gia_AigerWrite( pGia0, pFileName0, 0, 0, 0 ); + Gia_AigerWrite( pGia1, pFileName1, 0, 0, 0 ); ABC_FREE( pNameGeneric ); printf( "Dumped two parts of the miter into files \"%s\" and \"%s\".\n", pFileName0, pFileName1 ); } diff --git a/abc/src/aig/gia/giaTranStoch.c b/abc/src/aig/gia/giaTranStoch.c new file mode 100644 index 00000000000..aa600c0c0d2 --- /dev/null +++ b/abc/src/aig/gia/giaTranStoch.c @@ -0,0 +1,429 @@ +/**CFile**************************************************************** + + FileName [giaTranStoch.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of transduction method.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 2023.] + + Revision [$Id: giaTranStoch.c,v 1.00 2023/05/10 00:00:00 Exp $] + +***********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#define unlink _unlink +#else +#include +#endif + +#ifdef ABC_USE_PTHREADS + +#ifdef _WIN32 +#include "../lib/pthread.h" +#else +#include +#endif + +#endif + +ABC_NAMESPACE_IMPL_START + +extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); +extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); +extern int Abc_NtkPerformMfs( Abc_Ntk_t * pNtk, Sfm_Par_t * pPars ); +extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); +extern int Abc_NtkFxPerform( Abc_Ntk_t * pNtk, int nNewNodesMax, int nLitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose ); + +Abc_Ntk_t * Gia_ManTranStochPut( Gia_Man_t * pGia ) { + Abc_Ntk_t * pNtk; + Aig_Man_t * pMan = Gia_ManToAig( pGia, 0 ); + pNtk = Abc_NtkFromAigPhase( pMan ); + Aig_ManStop( pMan ); + return pNtk; +} +Abc_Ntk_t * Gia_ManTranStochIf( Abc_Ntk_t * pNtk ) { + If_Par_t Pars, * pPars = &Pars; + If_ManSetDefaultPars( pPars ); + pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); + pPars->nLutSize = pPars->pLutLib->LutMax; + return Abc_NtkIf( pNtk, pPars ); +} +void Gia_ManTranStochMfs2( Abc_Ntk_t * pNtk ) { + Sfm_Par_t Pars, * pPars = &Pars; + Sfm_ParSetDefault( pPars ); + Abc_NtkPerformMfs( pNtk, pPars ); +} +Gia_Man_t * Gia_ManTranStochGet( Abc_Ntk_t * pNtk ) { + Gia_Man_t * pGia; + Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 ); + pGia = Gia_ManFromAig( pAig ); + Aig_ManStop( pAig ); + return pGia; +} +void Gia_ManTranStochFx( Abc_Ntk_t * pNtk ) { + Fxu_Data_t Params, * p = &Params; + Abc_NtkSetDefaultFxParams( p ); + Abc_NtkFxPerform( pNtk, p->nNodesExt, p->LitCountMax, p->fCanonDivs, p->fVerbose, p->fVeryVerbose ); + Abc_NtkFxuFreeInfo( p ); +} +Gia_Man_t * Gia_ManTranStochRefactor( Gia_Man_t * pGia ) { + Gia_Man_t * pNew; + Aig_Man_t * pAig, * pTemp; + Dar_RefPar_t Pars, * pPars = &Pars; + Dar_ManDefaultRefParams( pPars ); + pPars->fUseZeros = 1; + pAig = Gia_ManToAig( pGia, 0 ); + Dar_ManRefactor( pAig, pPars ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + pNew = Gia_ManFromAig( pAig ); + Aig_ManStop( pAig ); + return pNew; +} + +struct Gia_ManTranStochParam { + Gia_Man_t * pStart; + int nSeed; + int nHops; + int nRestarts; + int nSeedBase; + int fMspf; + int fMerge; + int fResetHop; + int fZeroCostHop; + int fRefactor; + int fTruth; + int fNewLine; + Gia_Man_t * pExdc; + int nVerbose; + +#ifdef ABC_USE_PTHREADS + int nSp; + int nIte; + Gia_Man_t * pRes; + int fWorking; + pthread_mutex_t * mutex; +#endif +}; + +typedef struct Gia_ManTranStochParam Gia_ManTranStochParam; + +void Gia_ManTranStochLock( Gia_ManTranStochParam * p ) { +#ifdef ABC_USE_PTHREADS + if ( p->fWorking ) + pthread_mutex_lock( p->mutex ); +#endif +} +void Gia_ManTranStochUnlock( Gia_ManTranStochParam * p ) { +#ifdef ABC_USE_PTHREADS + if ( p->fWorking ) + pthread_mutex_unlock( p->mutex ); +#endif +} + +Gia_Man_t * Gia_ManTranStochOpt1( Gia_ManTranStochParam * p, Gia_Man_t * pOld ) { + Gia_Man_t * pGia, * pNew; + int i = 0, n; + pGia = Gia_ManDup( pOld ); + do { + n = Gia_ManAndNum( pGia ); + if ( p->fTruth ) + pNew = Gia_ManTransductionTt( pGia, (p->fMerge? 8: 7), p->fMspf, p->nSeed++, 0, 0, 0, 0, p->pExdc, p->fNewLine, p->nVerbose > 0? p->nVerbose - 1: 0 ); + else + pNew = Gia_ManTransductionBdd( pGia, (p->fMerge? 8: 7), p->fMspf, p->nSeed++, 0, 0, 0, 0, p->pExdc, p->fNewLine, p->nVerbose > 0? p->nVerbose - 1: 0 ); + Gia_ManStop( pGia ); + pGia = pNew; + if ( p->fRefactor ) { + pNew = Gia_ManTranStochRefactor( pGia ); + Gia_ManStop( pGia ); + pGia = pNew; + } else { + Gia_ManTranStochLock( p ); + pNew = Gia_ManCompress2( pGia, 1, 0 ); + Gia_ManTranStochUnlock( p ); + Gia_ManStop( pGia ); + pGia = pNew; + } + if ( p->nVerbose ) + printf( "* ite %d : #nodes = %5d\n", i, Gia_ManAndNum( pGia ) ); + i++; + } while ( n > Gia_ManAndNum( pGia ) ); + return pGia; +} + +Gia_Man_t * Gia_ManTranStochOpt2( Gia_ManTranStochParam * p ) { + int i, n = Gia_ManAndNum( p->pStart ); + Gia_Man_t * pGia, * pBest, * pNew; + Abc_Ntk_t * pNtk, * pNtkRes; + pGia = Gia_ManDup( p->pStart ); + pBest = Gia_ManDup( pGia ); + for ( i = 0; 1; i++ ) { + pNew = Gia_ManTranStochOpt1( p, pGia ); + Gia_ManStop( pGia ); + pGia = pNew; + if ( n > Gia_ManAndNum( pGia ) ) { + n = Gia_ManAndNum( pGia ); + Gia_ManStop( pBest ); + pBest = Gia_ManDup( pGia ); + if ( p->fResetHop ) + i = 0; + } + if ( i == p->nHops ) + break; + if ( p->fZeroCostHop ) { + pNew = Gia_ManTranStochRefactor( pGia ); + Gia_ManStop( pGia ); + pGia = pNew; + } else { + Gia_ManTranStochLock( p ); + pNtk = Gia_ManTranStochPut( pGia ); + Gia_ManTranStochUnlock( p ); + Gia_ManStop( pGia ); + pNtkRes = Gia_ManTranStochIf( pNtk ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + Gia_ManTranStochMfs2( pNtk ); + Gia_ManTranStochLock( p ); + pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Gia_ManTranStochUnlock( p ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + pGia = Gia_ManTranStochGet( pNtk ); + Abc_NtkDelete( pNtk ); + } + if ( p->nVerbose ) + printf( "* hop %d : #nodes = %5d\n", i, Gia_ManAndNum( pGia ) ); + } + Gia_ManStop( pGia ); + return pBest; +} + +Gia_Man_t * Gia_ManTranStochOpt3( Gia_ManTranStochParam * p ) { + int i, n = Gia_ManAndNum( p->pStart ); + Gia_Man_t * pBest, * pNew; + pBest = Gia_ManDup( p->pStart ); + for ( i = 0; i <= p->nRestarts; i++ ) { + p->nSeed = 1234 * (i + p->nSeedBase); + pNew = Gia_ManTranStochOpt2( p ); + if ( p->nRestarts && p->nVerbose ) + printf( "* res %2d : #nodes = %5d\n", i, Gia_ManAndNum( pNew ) ); + if ( n > Gia_ManAndNum( pNew ) ) { + n = Gia_ManAndNum( pNew ); + Gia_ManStop( pBest ); + pBest = pNew; + } else { + Gia_ManStop( pNew ); + } + } + return pBest; +} + +#ifdef ABC_USE_PTHREADS +void * Gia_ManTranStochWorkerThread( void * pArg ) { + Gia_ManTranStochParam * p = (Gia_ManTranStochParam *)pArg; + volatile int * pPlace = &p->fWorking; + while ( 1 ) { + while ( *pPlace == 0 ); + assert( p->fWorking ); + if ( p->pStart == NULL ) { + pthread_exit( NULL ); + assert( 0 ); + return NULL; + } + p->nSeed = 1234 * (p->nIte + p->nSeedBase); + p->pRes = Gia_ManTranStochOpt2( p ); + p->fWorking = 0; + } + assert( 0 ); + return NULL; +} +#endif + +Gia_Man_t * Gia_ManTranStoch( Gia_Man_t * pGia, int nRestarts, int nHops, int nSeedBase, int fMspf, int fMerge, int fResetHop, int fZeroCostHop, int fRefactor, int fTruth, int fSingle, int fOriginalOnly, int fNewLine, Gia_Man_t * pExdc, int nThreads, int nVerbose ) { + int i, j = 0; + Gia_Man_t * pNew, * pBest, * pStart; + Abc_Ntk_t * pNtk, * pNtkRes; Vec_Ptr_t * vpStarts; + Gia_ManTranStochParam Par, *p = &Par; + p->nRestarts = nRestarts; + p->nHops = nHops; + p->nSeedBase = nSeedBase; + p->fMspf = fMspf; + p->fMerge = fMerge; + p->fResetHop = fResetHop; + p->fZeroCostHop = fZeroCostHop; + p->fRefactor = fRefactor; + p->fTruth = fTruth; + p->fNewLine = fNewLine; + p->pExdc = pExdc; + p->nVerbose = nVerbose; +#ifdef ABC_USE_PTHREADS + p->fWorking = 0; +#endif + // setup start points + vpStarts = Vec_PtrAlloc( 4 ); + Vec_PtrPush( vpStarts, Gia_ManDup( pGia ) ); + if ( !fOriginalOnly ) { + { // &put; collapse; st; &get; + pNtk = Gia_ManTranStochPut( pGia ); + pNtkRes = Abc_NtkCollapse( pNtk, ABC_INFINITY, 0, 1, 0, 0, 0 ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + pNew = Gia_ManTranStochGet( pNtk ); + Abc_NtkDelete( pNtk ); + Vec_PtrPush( vpStarts, pNew ); + } + { // &ttopt; + pNew = Gia_ManTtopt( pGia, Gia_ManCiNum( pGia ), Gia_ManCoNum( pGia ), 100 ); + Vec_PtrPush( vpStarts, pNew ); + } + { // &put; collapse; sop; fx; + pNtk = Gia_ManTranStochPut( pGia ); + pNtkRes = Abc_NtkCollapse( pNtk, ABC_INFINITY, 0, 1, 0, 0, 0 ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); + Gia_ManTranStochFx( pNtk ); + pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + pNew = Gia_ManTranStochGet( pNtk ); + Abc_NtkDelete( pNtk ); + Vec_PtrPush( vpStarts, pNew ); + } + } + if ( fSingle ) { + pBest = (Gia_Man_t *)Vec_PtrEntry( vpStarts, 0 ); + for ( i = 1; i < Vec_PtrSize( vpStarts ); i++ ) { + pStart = (Gia_Man_t *)Vec_PtrEntry( vpStarts, i ); + if ( Gia_ManAndNum( pStart ) < Gia_ManAndNum( pBest ) ) { + Gia_ManStop( pBest ); + pBest = pStart; + j = i; + } else { + Gia_ManStop( pStart ); + } + } + Vec_PtrClear( vpStarts ); + Vec_PtrPush( vpStarts, pBest ); + } + // optimize + pBest = Gia_ManDup( pGia ); + if ( nThreads == 1 ) { + Vec_PtrForEachEntry( Gia_Man_t *, vpStarts, pStart, i ) { + if ( p->nVerbose ) + printf( "*begin starting point %d: #nodes = %5d\n", i + j, Gia_ManAndNum( pStart ) ); + p->pStart = pStart; + pNew = Gia_ManTranStochOpt3( p ); + if ( p->nVerbose ) + printf( "*end starting point %d: #nodes = %5d\n", i + j, Gia_ManAndNum( pNew ) ); + if ( Gia_ManAndNum( pBest ) > Gia_ManAndNum( pNew ) ) { + Gia_ManStop( pBest ); + pBest = pNew; + } else { + Gia_ManStop( pNew ); + } + Gia_ManStop( pStart ); + } + } else { +#ifdef ABC_USE_PTHREADS + static pthread_mutex_t mutex; + int k, status, nIte, fAssigned, fWorking; + Gia_ManTranStochParam ThData[100]; + pthread_t WorkerThread[100]; + p->pRes = NULL; + p->mutex = &mutex; + if ( p->nVerbose ) + p->nVerbose--; + for ( i = 0; i < nThreads; i++ ) { + ThData[i] = *p; + status = pthread_create( WorkerThread + i, NULL, Gia_ManTranStochWorkerThread, (void *)(ThData + i) ); + assert( status == 0 ); + } + Vec_PtrForEachEntry( Gia_Man_t *, vpStarts, pStart, k ) { + for ( nIte = 0; nIte <= p->nRestarts; nIte++ ) { + fAssigned = 0; + while ( !fAssigned ) { + for ( i = 0; i < nThreads; i++ ) { + if ( ThData[i].fWorking ) + continue; + if ( ThData[i].pRes != NULL ) { + if( nVerbose ) + printf( "*sp %d res %4d : #nodes = %5d\n", ThData[i].nSp, ThData[i].nIte, Gia_ManAndNum( ThData[i].pRes ) ); + if ( Gia_ManAndNum( pBest ) > Gia_ManAndNum( ThData[i].pRes ) ) { + Gia_ManStop( pBest ); + pBest = ThData[i].pRes; + } else { + Gia_ManStop( ThData[i].pRes ); + } + ThData[i].pRes = NULL; + } + ThData[i].nSp = j + k; + ThData[i].nIte = nIte; + ThData[i].pStart = pStart; + ThData[i].fWorking = 1; + fAssigned = 1; + break; + } + } + } + } + fWorking = 1; + while ( fWorking ) { + fWorking = 0; + for ( i = 0; i < nThreads; i++ ) { + if( ThData[i].fWorking ) { + fWorking = 1; + continue; + } + if ( ThData[i].pRes != NULL ) { + if( nVerbose ) + printf( "*sp %d res %4d : #nodes = %5d\n", ThData[i].nSp, ThData[i].nIte, Gia_ManAndNum( ThData[i].pRes ) ); + if ( Gia_ManAndNum( pBest ) > Gia_ManAndNum( ThData[i].pRes ) ) { + Gia_ManStop( pBest ); + pBest = ThData[i].pRes; + } else { + Gia_ManStop( ThData[i].pRes ); + } + ThData[i].pRes = NULL; + } + } + } + for ( i = 0; i < nThreads; i++ ) { + ThData[i].pStart = NULL; + ThData[i].fWorking = 1; + } +#else + printf( "ERROR: pthread is off" ); +#endif + Vec_PtrForEachEntry( Gia_Man_t *, vpStarts, pStart, i ) + Gia_ManStop( pStart ); + } + if ( nVerbose ) + printf( "best: %d\n", Gia_ManAndNum( pBest ) ); + Vec_PtrFree( vpStarts ); + return pBest; +} + +ABC_NAMESPACE_IMPL_END diff --git a/abc/src/aig/gia/giaTransduction.cpp b/abc/src/aig/gia/giaTransduction.cpp new file mode 100644 index 00000000000..f9220210f28 --- /dev/null +++ b/abc/src/aig/gia/giaTransduction.cpp @@ -0,0 +1,166 @@ +/**CFile**************************************************************** + + FileName [giaTransduction.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of transduction method.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 2023.] + + Revision [$Id: giaTransduction.c,v 1.00 2023/05/10 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef _WIN32 + +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma warning(disable : 4786) // warning C4786: identifier was truncated to '255' characters in the browser information +#endif +#endif + +#include "giaTransduction.h" +#include "giaNewBdd.h" +#include "giaNewTt.h" + +ABC_NAMESPACE_IMPL_START + +Gia_Man_t *Gia_ManTransductionBdd(Gia_Man_t *pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t *pExdc, int fNewLine, int nVerbose) { + if(nRandom) { + srand(nRandom); + nSortType = rand() % 4; + nPiShuffle = rand(); + nParameter = rand() % 16; + } + NewBdd::Param p; + Transduction::Transduction t(pGia, nVerbose, fNewLine, nSortType, nPiShuffle, fLevel, pExdc, p); + int count = t.CountWires(); + switch(nType) { + case 0: + count -= fMspf? t.Mspf(): t.Cspf(); + break; + case 1: + count -= t.Resub(fMspf); + break; + case 2: + count -= t.ResubMono(fMspf); + break; + case 3: + count -= t.ResubShared(fMspf); + break; + case 4: + count -= t.RepeatResub(false, fMspf); + break; + case 5: + count -= t.RepeatResub(true, fMspf); + break; + case 6: { + bool fInner = (nParameter / 4) % 2; + count -= t.RepeatInner(fMspf, fInner); + break; + } + case 7: { + bool fInner = (nParameter / 4) % 2; + bool fOuter = (nParameter / 8) % 2; + count -= t.RepeatOuter(fMspf, fInner, fOuter); + break; + } + case 8: { + bool fFirstMerge = nParameter % 2; + bool fMspfMerge = fMspf? (nParameter / 2) % 2: false; + bool fInner = (nParameter / 4) % 2; + bool fOuter = (nParameter / 8) % 2; + count -= t.RepeatAll(fFirstMerge, fMspfMerge, fMspf, fInner, fOuter); + break; + } + default: + std::cout << "Unknown transduction type " << nType << std::endl; + } + assert(t.Verify()); + assert(count == t.CountWires()); + return t.GenerateAig(); +} + +Gia_Man_t *Gia_ManTransductionTt(Gia_Man_t *pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t *pExdc, int fNewLine, int nVerbose) { + if(nRandom) { + srand(nRandom); + nSortType = rand() % 4; + nPiShuffle = rand(); + nParameter = rand() % 16; + } + NewTt::Param p; + Transduction::Transduction t(pGia, nVerbose, fNewLine, nSortType, nPiShuffle, fLevel, pExdc, p); + int count = t.CountWires(); + switch(nType) { + case 0: + count -= fMspf? t.Mspf(): t.Cspf(); + break; + case 1: + count -= t.Resub(fMspf); + break; + case 2: + count -= t.ResubMono(fMspf); + break; + case 3: + count -= t.ResubShared(fMspf); + break; + case 4: + count -= t.RepeatResub(false, fMspf); + break; + case 5: + count -= t.RepeatResub(true, fMspf); + break; + case 6: { + bool fInner = (nParameter / 4) % 2; + count -= t.RepeatInner(fMspf, fInner); + break; + } + case 7: { + bool fInner = (nParameter / 4) % 2; + bool fOuter = (nParameter / 8) % 2; + count -= t.RepeatOuter(fMspf, fInner, fOuter); + break; + } + case 8: { + bool fFirstMerge = nParameter % 2; + bool fMspfMerge = fMspf? (nParameter / 2) % 2: false; + bool fInner = (nParameter / 4) % 2; + bool fOuter = (nParameter / 8) % 2; + count -= t.RepeatAll(fFirstMerge, fMspfMerge, fMspf, fInner, fOuter); + break; + } + default: + std::cout << "Unknown transduction type " << nType << std::endl; + } + assert(t.Verify()); + assert(count == t.CountWires()); + return t.GenerateAig(); +} + +ABC_NAMESPACE_IMPL_END + +#else + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + +Gia_Man_t * Gia_ManTransductionBdd(Gia_Man_t *pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t *pExdc, int fNewLine, int nVerbose) +{ + return NULL; +} +Gia_Man_t * Gia_ManTransductionTt(Gia_Man_t *pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t *pExdc, int fNewLine, int nVerbose) +{ + return NULL; +} + +ABC_NAMESPACE_IMPL_END + +#endif diff --git a/abc/src/aig/gia/giaTransduction.h b/abc/src/aig/gia/giaTransduction.h new file mode 100644 index 00000000000..6dd081e15dc --- /dev/null +++ b/abc/src/aig/gia/giaTransduction.h @@ -0,0 +1,1768 @@ +/**CFile**************************************************************** + + FileName [giaTransduction.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of transduction method.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 2023.] + + Revision [$Id: giaTransduction.h,v 1.00 2023/05/10 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__gia__giaTransduction_h +#define ABC__aig__gia__giaTransduction_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gia.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Transduction { + +enum PfState {none, cspf, mspf}; + +template +class ManUtil { +protected: + Man *man; + inline void IncRef(lit x) const { + if(x != LitMax) + man->IncRef(x); + } + inline void DecRef(lit x) const { + if(x != LitMax) + man->DecRef(x); + } + inline void Update(lit &x, lit y) const { + DecRef(x); + x = y; + IncRef(x); + } + inline void DelVec(std::vector &v) const { + for(unsigned i = 0; i < v.size(); i++) + DecRef(v[i]); + v.clear(); + } + inline void DelVec(std::vector > &v) const { + for(unsigned i = 0; i < v.size(); i++) + DelVec(v[i]); + v.clear(); + } + inline void CopyVec(std::vector &v, std::vector const &u) const { + DelVec(v); + v = u; + for(unsigned i = 0; i < v.size(); i++) + IncRef(v[i]); + } + inline void CopyVec(std::vector > &v, std::vector > const &u) const { + for(unsigned i = u.size(); i < v.size(); i++) + DelVec(v[i]); + v.resize(u.size()); + for(unsigned i = 0; i < v.size(); i++) + CopyVec(v[i], u[i]); + } + inline bool LitVecIsEq(std::vector const &v, std::vector const &u) const { + if(v.size() != u.size()) + return false; + for(unsigned i = 0; i < v.size(); i++) + if(!man->LitIsEq(v[i], u[i])) + return false; + return true; + } + inline bool LitVecIsEq(std::vector > const &v, std::vector > const &u) const { + if(v.size() != u.size()) + return false; + for(unsigned i = 0; i < v.size(); i++) + if(!LitVecIsEq(v[i], u[i])) + return false; + return true; + } + inline lit Xor(lit x, lit y) const { + lit f = man->And(x, man->LitNot(y)); + man->IncRef(f); + lit g = man->And(man->LitNot(x), y); + man->IncRef(g); + lit r = man->Or(f, g); + man->DecRef(f); + man->DecRef(g); + return r; + } +}; + +template +class TransductionBackup: ManUtil { +private: + int nObjsAlloc; + PfState state; + std::list vObjs; + std::vector > vvFis; + std::vector > vvFos; + std::vector vLevels; + std::vector vSlacks; + std::vector > vvFiSlacks; + std::vector vFs; + std::vector vGs; + std::vector > vvCs; + std::vector vUpdates; + std::vector vPfUpdates; + std::vector vFoConeShared; + template + friend class Transduction; + +public: + ~TransductionBackup() { + if(this->man) { + this->DelVec(vFs); + this->DelVec(vGs); + this->DelVec(vvCs); + } + } +}; + +template +class Transduction: ManUtil { +private: + int nVerbose; + int nSortType; + bool fLevel; + int nObjsAlloc; + int nMaxLevels; + PfState state; + std::vector vPis; + std::vector vPos; + std::list vObjs; + std::vector > vvFis; + std::vector > vvFos; + std::vector vLevels; + std::vector vSlacks; + std::vector > vvFiSlacks; + std::vector vFs; + std::vector vGs; + std::vector > vvCs; + std::vector vUpdates; + std::vector vPfUpdates; + std::vector vFoConeShared; + std::vector vPoFs; + + bool fNewLine; + abctime startclk; + +private: // Helper functions + inline bool AllFalse(std::vector const &v) const { + for(std::list::const_iterator it = vObjs.begin(); it != vObjs.end(); it++) + if(v[*it]) + return false; + return true; + } + +public: // Counting + inline int CountGates() const { + return vObjs.size(); + } + inline int CountWires() const { + int count = 0; + for(std::list::const_iterator it = vObjs.begin(); it != vObjs.end(); it++) + count += vvFis[*it].size(); + return count; + } + inline int CountNodes() const { + return CountWires() - CountGates(); + } + inline int CountLevels() const { + int count = 0; + for(unsigned i = 0; i < vPos.size(); i++) + count = std::max(count, vLevels[vvFis[vPos[i]][0] >> 1]); + return count; + } + inline void Print(std::string str, bool nl) const { + if(!fNewLine) + std::cout << "\33[2K\r"; + std::cout << str; + if(fNewLine || nl) + std::cout << std::endl; + else + std::cout << std::flush; + } + inline void PrintStats(std::string prefix, bool nl, int prefix_size = 0) const { + if(!prefix_size) + prefix_size = prefix.size(); + std::stringstream ss; + ss << std::left << std::setw(prefix_size) << prefix << ": " << std::right; + ss << "#nodes = " << std::setw(5) << CountNodes(); + if(fLevel) + ss << ", #level = " << std::setw(5) << CountLevels(); + ss << ", elapsed = " << std::setprecision(2) << std::fixed << std::setw(8) << 1.0 * (Abc_Clock() - startclk) / CLOCKS_PER_SEC << "s"; + Print(ss.str(), nl); + } + inline void PrintPfHeader(std::string prefix, int block, int block_i0) { + std::stringstream ss; + ss << "\t\t" << prefix; + if(block_i0 != -1) + ss << " (blocking Wire " << block_i0 << " -> " << block << ")"; + else if(block != -1) + ss << " (blocking Gate " << block << ")"; + Print(ss.str(), true); + } + +private: // MIAIG + void SortObjs_rec(std::list::iterator const &it) { + for(unsigned j = 0; j < vvFis[*it].size(); j++) { + int i0 = vvFis[*it][j] >> 1; + if(!vvFis[i0].empty()) { + std::list::iterator it_i0 = std::find(it, vObjs.end(), i0); + if(it_i0 != vObjs.end()) { + // if(nVerbose > 6) + // std::cout << "\t\t\t\t\t\tMove " << i0 << " before " << *it << std::endl; + vObjs.erase(it_i0); + it_i0 = vObjs.insert(it, i0); + SortObjs_rec(it_i0); + } + } + } + } + inline void Connect(int i, int f, bool fSort = false, bool fUpdate = true, lit c = LitMax) { + int i0 = f >> 1; + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\t\tadd Wire " << std::setw(5) << i0 << "(" << (f & 1) << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + assert(std::find(vvFis[i].begin(), vvFis[i].end(), f) == vvFis[i].end()); + vvFis[i].push_back(f); + vvFos[i0].push_back(i); + if(fUpdate) + vUpdates[i] = true; + this->IncRef(c); + vvCs[i].push_back(c); + if(fSort && !vvFos[i].empty() && !vvFis[i0].empty()) { + std::list::iterator it = find(vObjs.begin(), vObjs.end(), i); + std::list::iterator it_i0 = find(it, vObjs.end(), i0); + if(it_i0 != vObjs.end()) { + // if(nVerbose > 6) + // std::cout << "\t\t\t\t\t\tMove " << i0 << " before " << *it << std::endl; + vObjs.erase(it_i0); + it_i0 = vObjs.insert(it, i0); + SortObjs_rec(it_i0); + } + } + } + inline void Disconnect(int i, int i0, unsigned j, bool fUpdate = true, bool fPfUpdate = true) { + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\t\tremove Wire " << std::setw(5) << i0 << "(" << (vvFis[i][j] & 1) << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + vvFos[i0].erase(std::find(vvFos[i0].begin(), vvFos[i0].end(), i)); + vvFis[i].erase(vvFis[i].begin() + j); + this->DecRef(vvCs[i][j]); + vvCs[i].erase(vvCs[i].begin() + j); + if(fUpdate) + vUpdates[i] = true; + if(fPfUpdate) + vPfUpdates[i0] = true; + } + inline int Remove(int i, bool fPfUpdate = true) { + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\t\tremove Gate " << std::setw(5) << i; + Print(ss.str(), true); + } + assert(vvFos[i].empty()); + for(unsigned j = 0; j < vvFis[i].size(); j++) { + int i0 = vvFis[i][j] >> 1; + vvFos[i0].erase(std::find(vvFos[i0].begin(), vvFos[i0].end(), i)); + if(fPfUpdate) + vPfUpdates[i0] = true; + } + int count = vvFis[i].size(); + vvFis[i].clear(); + this->DecRef(vFs[i]); + this->DecRef(vGs[i]); + vFs[i] = vGs[i] = LitMax; + this->DelVec(vvCs[i]); + vUpdates[i] = vPfUpdates[i] = false; + return count; + } + inline int FindFi(int i, int i0) const { + for(unsigned j = 0; j < vvFis[i].size(); j++) + if((vvFis[i][j] >> 1) == i0) + return j; + return -1; + } + inline int Replace(int i, int f, bool fUpdate = true) { + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\t\t\treplace Gate " << std::setw(5) << i + << " by Node " << std::setw(5) << (f >> 1) << "(" << (f & 1) << ")"; + Print(ss.str(), true); + } + assert(i != (f >> 1)); + int count = 0; + for(unsigned j = 0; j < vvFos[i].size(); j++) { + int k = vvFos[i][j]; + int l = FindFi(k, i); + assert(l >= 0); + int fc = f ^ (vvFis[k][l] & 1); + if(find(vvFis[k].begin(), vvFis[k].end(), fc) != vvFis[k].end()) { + this->DecRef(vvCs[k][l]); + vvCs[k].erase(vvCs[k].begin() + l); + vvFis[k].erase(vvFis[k].begin() + l); + count++; + } else { + vvFis[k][l] = f ^ (vvFis[k][l] & 1); + vvFos[f >> 1].push_back(k); + } + if(fUpdate) + vUpdates[k] = true; + } + vvFos[i].clear(); + vPfUpdates[f >> 1] = true; + return count + Remove(i); + } + int ReplaceByConst(int i, bool c) { + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\t\t\treplace Gate " << std::setw(5) << i << " by Const " << c; + Print(ss.str(), true); + } + int count = 0; + for(unsigned j = 0; j < vvFos[i].size(); j++) { + int k = vvFos[i][j]; + int l = FindFi(k, i); + assert(l >= 0); + bool fc = c ^ (vvFis[k][l] & 1); + this->DecRef(vvCs[k][l]); + vvCs[k].erase(vvCs[k].begin() + l); + vvFis[k].erase(vvFis[k].begin() + l); + if(fc) { + if(vvFis[k].size() == 1) + count += Replace(k, vvFis[k][0]); + else + vUpdates[k] = true; + } else + count += ReplaceByConst(k, 0); + } + count += vvFos[i].size(); + vvFos[i].clear(); + return count + Remove(i); + } + inline void NewGate(int &pos) { + while(pos != nObjsAlloc && (!vvFis[pos].empty() || !vvFos[pos].empty())) + pos++; + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\t\tcreate Gate " << std::setw(5) << pos; + Print(ss.str(), true); + } + if(pos == nObjsAlloc) { + nObjsAlloc++; + vvFis.resize(nObjsAlloc); + vvFos.resize(nObjsAlloc); + if(fLevel) { + vLevels.resize(nObjsAlloc); + vSlacks.resize(nObjsAlloc); + vvFiSlacks.resize(nObjsAlloc); + } + vFs.resize(nObjsAlloc, LitMax); + vGs.resize(nObjsAlloc, LitMax); + vvCs.resize(nObjsAlloc); + vUpdates.resize(nObjsAlloc); + vPfUpdates.resize(nObjsAlloc); + } + } + void MarkFiCone_rec(std::vector &vMarks, int i) const { + if(vMarks[i]) + return; + vMarks[i] = true; + for(unsigned j = 0; j < vvFis[i].size(); j++) + MarkFiCone_rec(vMarks, vvFis[i][j] >> 1); + } + void MarkFoCone_rec(std::vector &vMarks, int i) const { + if(vMarks[i]) + return; + vMarks[i] = true; + for(unsigned j = 0; j < vvFos[i].size(); j++) + MarkFoCone_rec(vMarks, vvFos[i][j]); + } + bool IsFoConeShared_rec(std::vector &vVisits, int i, int visitor) const { + if(vVisits[i] == visitor) + return false; + if(vVisits[i]) + return true; + vVisits[i] = visitor; + for(unsigned j = 0; j < vvFos[i].size(); j++) + if(IsFoConeShared_rec(vVisits, vvFos[i][j], visitor)) + return true; + return false; + } + inline bool IsFoConeShared(int i) const { + std::vector vVisits(nObjsAlloc); + for(unsigned j = 0; j < vvFos[i].size(); j++) + if(IsFoConeShared_rec(vVisits, vvFos[i][j], j + 1)) + return true; + return false; + } + +private: // Level calculation + inline void add(std::vector &a, unsigned i) { + if(a.size() <= i) { + a.resize(i + 1); + a[i] = true; + return; + } + for(; i < a.size() && a[i]; i++) + a[i] = false; + if(i == a.size()) + a.resize(i + 1); + a[i] = true; + } + inline bool balanced(std::vector const &a) { + for(unsigned i = 0; i < a.size() - 1; i++) + if(a[i]) + return false; + return true; + } + inline bool noexcess(std::vector const &a, unsigned i) { + if(a.size() <= i) + return false; + for(unsigned j = i; j < a.size(); j++) + if(!a[j]) + return true; + for(unsigned j = 0; j < i; j++) + if(a[j]) + return false; + return true; + } + inline void ComputeLevel() { + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) { + if(vvFis[*it].size() == 2) + vLevels[*it] = std::max(vLevels[vvFis[*it][0] >> 1], vLevels[vvFis[*it][1] >> 1]) + 1; + else { + std::vector lev; + for(unsigned j = 0; j < vvFis[*it].size(); j++) + add(lev, vLevels[vvFis[*it][j] >> 1]); + if(balanced(lev)) + vLevels[*it] = (int)lev.size() - 1; + else + vLevels[*it] = (int)lev.size(); + } + } + if(nMaxLevels == -1) + nMaxLevels = CountLevels(); + for(unsigned i = 0; i < vPos.size(); i++) { + vvFiSlacks[vPos[i]].resize(1); + vvFiSlacks[vPos[i]][0] = nMaxLevels - vLevels[vvFis[vPos[i]][0] >> 1]; + } + for(std::list::reverse_iterator it = vObjs.rbegin(); it != vObjs.rend(); it++) { + vSlacks[*it] = nMaxLevels; + for(unsigned j = 0; j < vvFos[*it].size(); j++) { + int k = vvFos[*it][j]; + int l = FindFi(k, *it); + assert(l >= 0); + vSlacks[*it] = std::min(vSlacks[*it], vvFiSlacks[k][l]); + } + vvFiSlacks[*it].resize(vvFis[*it].size()); + for(unsigned j = 0; j < vvFis[*it].size(); j++) + vvFiSlacks[*it][j] = vSlacks[*it] + vLevels[*it] - 1 - vLevels[vvFis[*it][j] >> 1]; + } + } + +private: // Cost function + inline void ShufflePis(int seed) { + srand(seed); + for(int i = (int)vPis.size() - 1; i > 0; i--) + std::swap(vPis[i], vPis[rand() % (i + 1)]); + } + inline bool CostCompare(int a, int b) const { // return (cost(a) > cost(b)) + int a0 = a >> 1; + int b0 = b >> 1; + if(vvFis[a0].empty() && vvFis[b0].empty()) + return std::find(find(vPis.begin(), vPis.end(), a0), vPis.end(), b0) != vPis.end(); + if(vvFis[a0].empty() && !vvFis[b0].empty()) + return false; + if(!vvFis[a0].empty() && vvFis[b0].empty()) + return true; + if(vvFos[a0].size() > vvFos[b0].size()) + return false; + if(vvFos[a0].size() < vvFos[b0].size()) + return true; + bool ac = a & 1; + bool bc = b & 1; + switch(nSortType) { + case 0: + return std::find(find(vObjs.begin(), vObjs.end(), a0), vObjs.end(), b0) == vObjs.end(); + case 1: + return this->man->OneCount(this->man->LitNotCond(vFs[a0], ac)) < this->man->OneCount(this->man->LitNotCond(vFs[b0], bc)); + case 2: + return this->man->OneCount(vFs[a0]) < this->man->OneCount(vFs[b0]); + case 3: + return this->man->OneCount(this->man->LitNot(vFs[a0])) < this->man->OneCount(vFs[b0]); // pseudo random + default: + return false; // no sorting + } + } + inline bool SortFis(int i) { + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\tsort FIs Gate " << std::setw(5) << i; + Print(ss.str(), true); + } + bool fSort = false; + for(int p = 1; p < (int)vvFis[i].size(); p++) { + int f = vvFis[i][p]; + lit c = vvCs[i][p]; + int q = p - 1; + for(; q >= 0 && CostCompare(f, vvFis[i][q]); q--) { + vvFis[i][q + 1] = vvFis[i][q]; + vvCs[i][q + 1] = vvCs[i][q]; + } + if(q + 1 != p) { + fSort = true; + vvFis[i][q + 1] = f; + vvCs[i][q + 1] = c; + } + } + if(nVerbose > 5) + for(unsigned j = 0; j < vvFis[i].size(); j++) { + std::stringstream ss; + ss << "\t\t\t\t\tFI " << j << " = " + << std::setw(5) << (vvFis[i][j] >> 1) << "(" << (vvFis[i][j] & 1) << ")"; + Print(ss.str(), true); + } + return fSort; + } + +private: // Symbolic simulation + inline lit LitFi(int i, int j) const { + int i0 = vvFis[i][j] >> 1; + bool c0 = vvFis[i][j] & 1; + return this->man->LitNotCond(vFs[i0], c0); + } + inline lit LitFi(int i, int j, std::vector const &vFs_) const { + int i0 = vvFis[i][j] >> 1; + bool c0 = vvFis[i][j] & 1; + return this->man->LitNotCond(vFs_[i0], c0); + } + inline void Build(int i, std::vector &vFs_) const { + if(nVerbose > 6) { + std::stringstream ss; + ss << "\t\t\t\tbuilding Gate" << std::setw(5) << i; + Print(ss.str(), nVerbose > 7); + } + this->Update(vFs_[i], this->man->Const1()); + for(unsigned j = 0; j < vvFis[i].size(); j++) + this->Update(vFs_[i], this->man->And(vFs_[i], LitFi(i, j, vFs_))); + } + inline void Build(bool fPfUpdate = true) { + if(nVerbose > 6) + Print("\t\t\tBuild", true); + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + if(vUpdates[*it]) { + lit x = vFs[*it]; + this->IncRef(x); + Build(*it, vFs); + this->DecRef(x); + if(!this->man->LitIsEq(x, vFs[*it])) + for(unsigned j = 0; j < vvFos[*it].size(); j++) + vUpdates[vvFos[*it][j]] = true; + } + if(fPfUpdate) + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + vPfUpdates[*it] = vPfUpdates[*it] || vUpdates[*it]; + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + vUpdates[*it] = false; + assert(AllFalse(vUpdates)); + } + void BuildFoConeCompl(int i, std::vector &vPoFsCompl) const { + if(nVerbose > 6) { + std::stringstream ss; + ss << "\t\t\tBuild with complemented Gate " << std::setw(5) << i; + Print(ss.str(), true); + } + std::vector vFsCompl; + this->CopyVec(vFsCompl, vFs); + vFsCompl[i] = this->man->LitNot(vFs[i]); + std::vector vUpdatesCompl(nObjsAlloc); + for(unsigned j = 0; j < vvFos[i].size(); j++) + vUpdatesCompl[vvFos[i][j]] = true; + for(std::list::const_iterator it = vObjs.begin(); it != vObjs.end(); it++) + if(vUpdatesCompl[*it]) { + Build(*it, vFsCompl); + if(!this->man->LitIsEq(vFsCompl[*it], vFs[*it])) + for(unsigned j = 0; j < vvFos[*it].size(); j++) + vUpdatesCompl[vvFos[*it][j]] = true; + } + for(unsigned j = 0; j < vPos.size(); j++) + this->Update(vPoFsCompl[j], LitFi(vPos[j], 0, vFsCompl)); + this->DelVec(vFsCompl); + } + +private: // CSPF + inline int RemoveRedundantFis(int i, int block_i0 = -1, unsigned j = 0) { + int count = 0; + for(; j < vvFis[i].size(); j++) { + if(block_i0 == (vvFis[i][j] >> 1)) + continue; + lit x = this->man->Const1(); + this->IncRef(x); + for(unsigned jj = 0; jj < vvFis[i].size(); jj++) + if(j != jj) + this->Update(x, this->man->And(x, LitFi(i, jj))); + this->Update(x, this->man->Or(this->man->LitNot(x), vGs[i])); + this->Update(x, this->man->Or(x, LitFi(i, j))); + this->DecRef(x); + if(this->man->IsConst1(x)) { + int i0 = vvFis[i][j] >> 1; + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\t\t\t[Rrfi] remove Wire " << std::setw(5) << i0 << "(" << (vvFis[i][j] & 1) << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + Disconnect(i, i0, j--); + count++; + } + } + return count; + } + inline void CalcG(int i) { + this->Update(vGs[i], this->man->Const1()); + for(unsigned j = 0; j < vvFos[i].size(); j++) { + int k = vvFos[i][j]; + int l = FindFi(k, i); + assert(l >= 0); + this->Update(vGs[i], this->man->And(vGs[i], vvCs[k][l])); + } + } + inline int CalcC(int i) { + int count = 0; + for(unsigned j = 0; j < vvFis[i].size(); j++) { + lit x = this->man->Const1(); + this->IncRef(x); + for(unsigned jj = j + 1; jj < vvFis[i].size(); jj++) + this->Update(x, this->man->And(x, LitFi(i, jj))); + this->Update(x, this->man->Or(this->man->LitNot(x), vGs[i])); + int i0 = vvFis[i][j] >> 1; + if(this->man->IsConst1(this->man->Or(x, LitFi(i, j)))) { + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\t\t\t[Cspf] remove Wire " << std::setw(5) << i0 << "(" << (vvFis[i][j] & 1) << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + Disconnect(i, i0, j--); + count++; + } else if(!this->man->LitIsEq(vvCs[i][j], x)) { + this->Update(vvCs[i][j], x); + vPfUpdates[i0] = true; + } + this->DecRef(x); + } + return count; + } + int Cspf(bool fSortRemove, int block = -1, int block_i0 = -1) { + if(nVerbose > 3) + PrintPfHeader("Cspf", block, block_i0); + if(state != cspf) + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + vPfUpdates[*it] = true; + state = cspf; + int count = 0; + for(std::list::reverse_iterator it = vObjs.rbegin(); it != vObjs.rend();) { + if(vvFos[*it].empty()) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t\tremove unused Gate " << std::setw(5) << *it; + Print(ss.str(), nVerbose > 4); + } + count += Remove(*it); + it = std::list::reverse_iterator(vObjs.erase(--(it.base()))); + continue; + } + if(!vPfUpdates[*it]) { + it++; + continue; + } + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t\tprocessing Gate " << std::setw(5) << *it + << " (" << std::setw(5) << std::distance(vObjs.rbegin(), it) + 1 + << "/" << std::setw(5) << vObjs.size() << ")"; + Print(ss.str(), nVerbose > 4); + } + CalcG(*it); + if(fSortRemove) { + if(*it != block) + SortFis(*it), count += RemoveRedundantFis(*it); + else if(block_i0 != -1) + count += RemoveRedundantFis(*it, block_i0); + } + count += CalcC(*it); + vPfUpdates[*it] = false; + assert(!vvFis[*it].empty()); + if(vvFis[*it].size() == 1) { + count += Replace(*it, vvFis[*it][0]); + it = std::list::reverse_iterator(vObjs.erase(--(it.base()))); + continue; + } + it++; + } + Build(false); + assert(AllFalse(vPfUpdates)); + if(fLevel) + ComputeLevel(); + return count; + } + +private: // MSPF + inline bool MspfCalcG(int i) { + lit g = vGs[i]; + this->IncRef(g); + std::vector vPoFsCompl(vPos.size(), LitMax); + BuildFoConeCompl(i, vPoFsCompl); + this->Update(vGs[i], this->man->Const1()); + for(unsigned j = 0; j < vPos.size(); j++) { + lit x = this->man->LitNot(this->Xor(vPoFs[j], vPoFsCompl[j])); + this->IncRef(x); + this->Update(x, this->man->Or(x, vvCs[vPos[j]][0])); + this->Update(vGs[i], this->man->And(vGs[i], x)); + this->DecRef(x); + } + this->DelVec(vPoFsCompl); + this->DecRef(g); + return !this->man->LitIsEq(vGs[i], g); + } + inline int MspfCalcC(int i, int block_i0 = -1) { + for(unsigned j = 0; j < vvFis[i].size(); j++) { + lit x = this->man->Const1(); + this->IncRef(x); + for(unsigned jj = 0; jj < vvFis[i].size(); jj++) + if(j != jj) + this->Update(x, this->man->And(x, LitFi(i, jj))); + this->Update(x, this->man->Or(this->man->LitNot(x), vGs[i])); + int i0 = vvFis[i][j] >> 1; + if(i0 != block_i0 && this->man->IsConst1(this->man->Or(x, LitFi(i, j)))) { + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\t\t\t[Mspf] remove Wire " << std::setw(5) << i0 << "(" << (vvFis[i][j] & 1) << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + Disconnect(i, i0, j); + this->DecRef(x); + return RemoveRedundantFis(i, block_i0, j) + 1; + } else if(!this->man->LitIsEq(vvCs[i][j], x)) { + this->Update(vvCs[i][j], x); + vPfUpdates[i0] = true; + } + this->DecRef(x); + } + return 0; + } + int Mspf(bool fSort, int block = -1, int block_i0 = -1) { + if(nVerbose > 3) + PrintPfHeader("Mspf", block, block_i0); + assert(AllFalse(vUpdates)); + vFoConeShared.resize(nObjsAlloc); + if(state != mspf) + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + vPfUpdates[*it] = true; + state = mspf; + int count = 0; + int restarts = 0; + for(std::list::reverse_iterator it = vObjs.rbegin(); it != vObjs.rend();) { + if(vvFos[*it].empty()) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t\tremove unused Gate " << std::setw(5) << *it; + Print(ss.str(), nVerbose > 4); + } + count += Remove(*it); + it = std::list::reverse_iterator(vObjs.erase(--(it.base()))); + continue; + } + if(!vFoConeShared[*it] && !vPfUpdates[*it] && (vvFos[*it].size() == 1 || !IsFoConeShared(*it))) { + it++; + continue; + } + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t\tprocessing Gate " << std::setw(5) << *it + << " (" << std::setw(5) << std::distance(vObjs.rbegin(), it) + 1 + << "/" << std::setw(5) << vObjs.size() << ")" + << ", #restarts = " << std::setw(3) << restarts; + Print(ss.str(), nVerbose > 4); + } + if(vvFos[*it].size() == 1 || !IsFoConeShared(*it)) { + if(vFoConeShared[*it]) { + vFoConeShared[*it] = false; + lit g = vGs[*it]; + this->IncRef(g); + CalcG(*it); + this->DecRef(g); + if(g == vGs[*it] && !vPfUpdates[*it]) { + it++; + continue; + } + } else + CalcG(*it); + } else { + vFoConeShared[*it] = true; + if(!MspfCalcG(*it) && !vPfUpdates[*it]) { + it++; + continue; + } + bool IsConst1 = this->man->IsConst1(this->man->Or(vGs[*it], vFs[*it])); + bool IsConst0 = IsConst1? false: this->man->IsConst1(this->man->Or(vGs[*it], this->man->LitNot(vFs[*it]))); + if(IsConst1 || IsConst0) { + count += ReplaceByConst(*it, (int)IsConst1); + vObjs.erase(--(it.base())); + Build(); + it = vObjs.rbegin(); + restarts++; + continue; + } + } + if(fSort && block != *it) + SortFis(*it); + if(int diff = (block == *it)? MspfCalcC(*it, block_i0): MspfCalcC(*it)) { + count += diff; + assert(!vvFis[*it].empty()); + if(vvFis[*it].size() == 1) { + count += Replace(*it, vvFis[*it][0]); + vObjs.erase(--(it.base())); + } + Build(); + it = vObjs.rbegin(); + restarts++; + continue; + } + vPfUpdates[*it] = false; + it++; + } + assert(AllFalse(vUpdates)); + assert(AllFalse(vPfUpdates)); + if(fLevel) + ComputeLevel(); + return count; + } + +private: // Merge/decompose one + inline int TrivialMergeOne(int i) { + int count = 0; + std::vector vFisOld = vvFis[i]; + std::vector vCsOld = vvCs[i]; + vvFis[i].clear(); + vvCs[i].clear(); + for(unsigned j = 0; j < vFisOld.size(); j++) { + int i0 = vFisOld[j] >> 1; + int c0 = vFisOld[j] & 1; + if(vvFis[i0].empty() || vvFos[i0].size() > 1 || c0) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t[TrivialMerge] adding Wire " << std::setw(5) << i0 << "(" << c0 << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + vvFis[i].push_back(vFisOld[j]); + vvCs[i].push_back(vCsOld[j]); + continue; + } + vPfUpdates[i] = vPfUpdates[i] | vPfUpdates[i0]; + vvFos[i0].erase(find(vvFos[i0].begin(), vvFos[i0].end(), i)); + count++; + typename std::vector::iterator itfi = vFisOld.begin() + j; + typename std::vector::iterator itc = vCsOld.begin() + j; + for(unsigned jj = 0; jj < vvFis[i0].size(); jj++) { + int f = vvFis[i0][jj]; + std::vector::iterator it = find(vvFis[i].begin(), vvFis[i].end(), f); + if(it == vvFis[i].end()) { + vvFos[f >> 1].push_back(i); + itfi = vFisOld.insert(itfi, f); + itc = vCsOld.insert(itc, vvCs[i0][jj]); + this->IncRef(*itc); + itfi++; + itc++; + count--; + } else { + assert(state == none); + } + } + count += Remove(i0, false); + vObjs.erase(find(vObjs.begin(), vObjs.end(), i0)); + vFisOld.erase(itfi); + this->DecRef(*itc); + vCsOld.erase(itc); + j--; + } + return count; + } + inline int TrivialDecomposeOne(std::list::iterator const &it, int &pos) { + if(nVerbose > 2) { + std::stringstream ss; + ss << "\tTrivialDecompose Gate " << std::setw(5) << *it; + Print(ss.str() , nVerbose > 3); + } + assert(vvFis[*it].size() > 2); + int count = 2 - vvFis[*it].size(); + while(vvFis[*it].size() > 2) { + int f0 = vvFis[*it].back(); + lit c0 = vvCs[*it].back(); + Disconnect(*it, f0 >> 1, vvFis[*it].size() - 1, false, false); + int f1 = vvFis[*it].back(); + lit c1 = vvCs[*it].back(); + Disconnect(*it, f1 >> 1, vvFis[*it].size() - 1, false, false); + NewGate(pos); + Connect(pos, f1, false, false, c1); + Connect(pos, f0, false, false, c0); + if(!vPfUpdates[*it]) { + if(state == cspf) + this->Update(vGs[pos], vGs[*it]); + else if(state == mspf) { + lit x = this->man->Const1(); + this->IncRef(x); + for(unsigned j = 0; j < vvFis[*it].size(); j++) + this->Update(x, this->man->And(x, LitFi(*it, j))); + this->Update(vGs[pos], this->man->Or(this->man->LitNot(x), vGs[*it])); + this->DecRef(x); + } + } + Connect(*it, pos << 1, false, false, vGs[pos]); + vObjs.insert(it, pos); + Build(pos, vFs); + } + return count; + } + inline int BalancedDecomposeOne(std::list::iterator const &it, int &pos) { + if(nVerbose > 2) { + std::stringstream ss; + ss << "\tBalancedDecompose Gate " << std::setw(5) << *it; + Print(ss.str(), nVerbose > 3); + } + assert(fLevel); + assert(vvFis[*it].size() > 2); + for(int p = 1; p < (int)vvFis[*it].size(); p++) { + int f = vvFis[*it][p]; + lit c = vvCs[*it][p]; + int q = p - 1; + for(; q >= 0 && vLevels[f >> 1] > vLevels[vvFis[*it][q] >> 1]; q--) { + vvFis[*it][q + 1] = vvFis[*it][q]; + vvCs[*it][q + 1] = vvCs[*it][q]; + } + if(q + 1 != p) { + vvFis[*it][q + 1] = f; + vvCs[*it][q + 1] = c; + } + } + int count = 2 - vvFis[*it].size(); + while(vvFis[*it].size() > 2) { + int f0 = vvFis[*it].back(); + lit c0 = vvCs[*it].back(); + Disconnect(*it, f0 >> 1, vvFis[*it].size() - 1, false, false); + int f1 = vvFis[*it].back(); + lit c1 = vvCs[*it].back(); + Disconnect(*it, f1 >> 1, vvFis[*it].size() - 1, false, false); + NewGate(pos); + Connect(pos, f1, false, false, c1); + Connect(pos, f0, false, false, c0); + Connect(*it, pos << 1, false, false); + Build(pos, vFs); + vLevels[pos] = std::max(vLevels[f0 >> 1], vLevels[f1 >> 1]) + 1; + vObjs.insert(it, pos); + int f = vvFis[*it].back(); + lit c = vvCs[*it].back(); + int q = (int)vvFis[*it].size() - 2; + for(; q >= 0 && vLevels[f >> 1] > vLevels[vvFis[*it][q] >> 1]; q--) { + vvFis[*it][q + 1] = vvFis[*it][q]; + vvCs[*it][q + 1] = vvCs[*it][q]; + } + if(q + 1 != (int)vvFis[*it].size() - 1) { + vvFis[*it][q + 1] = f; + vvCs[*it][q + 1] = c; + } + } + vPfUpdates[*it] = true; + return count; + } + +public: // Merge/decompose + int TrivialMerge() { + int count = 0; + for(std::list::reverse_iterator it = vObjs.rbegin(); it != vObjs.rend();) { + count += TrivialMergeOne(*it); + it++; + } + return count; + } + int TrivialDecompose() { + int count = 0; + int pos = vPis.size() + 1; + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + if(vvFis[*it].size() > 2) + count += TrivialDecomposeOne(it, pos); + return count; + } + int Decompose() { + int count = 0; + int pos = vPis.size() + 1; + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) { + std::set s1(vvFis[*it].begin(), vvFis[*it].end()); + assert(s1.size() == vvFis[*it].size()); + std::list::iterator it2 = it; + for(it2++; it2 != vObjs.end(); it2++) { + std::set s2(vvFis[*it2].begin(), vvFis[*it2].end()); + std::set s; + std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), std::inserter(s, s.begin())); + if(s.size() > 1) { + if(s == s1) { + if(s == s2) { + if(nVerbose > 2) { + std::stringstream ss; + ss << "\treplace Gate " << std::setw(5) << *it2 + << " by Gate " << std::setw(5) << *it; + Print(ss.str() , nVerbose > 3); + } + count += Replace(*it2, *it << 1, false); + it2 = vObjs.erase(it2); + it2--; + } else { + if(nVerbose > 2) { + std::stringstream ss; + ss << "\tdecompose Gate " << std::setw(5) << *it2 + << " by Gate " << std::setw(5) << *it; + Print(ss.str() , nVerbose > 3); + } + for(std::set::iterator it3 = s.begin(); it3 != s.end(); it3++) { + unsigned j = find(vvFis[*it2].begin(), vvFis[*it2].end(), *it3) - vvFis[*it2].begin(); + Disconnect(*it2, *it3 >> 1, j, false); + } + count += s.size(); + if(std::find(vvFis[*it2].begin(), vvFis[*it2].end(), *it << 1) == vvFis[*it2].end()) { + Connect(*it2, *it << 1, false, false); + count--; + } + vPfUpdates[*it2] = true; + } + continue; + } + if(s == s2) { + it = vObjs.insert(it, *it2); + vObjs.erase(it2); + } else { + NewGate(pos); + if(nVerbose > 2) { + std::stringstream ss; + ss << "\tdecompose Gate " << std::setw(5) << *it + << " and " << std::setw(5) << *it2 + << " by a new Gate " << std::setw(5) << pos; + Print(ss.str() , nVerbose > 3); + } + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\tIntersection:"; + for(std::set::iterator it3 = s.begin(); it3 != s.end(); it3++) + ss << " " << (*it3 >> 1) << "(" << (*it3 & 1) << ")"; + Print(ss.str(), true); + } + for(std::set::iterator it3 = s.begin(); it3 != s.end(); it3++) + Connect(pos, *it3, false, false); + count -= s.size(); + it = vObjs.insert(it, pos); + Build(pos, vFs); + vPfUpdates[*it] = true; + } + s1 = s; + it2 = it; + } + } + if(vvFis[*it].size() > 2) + count += TrivialDecomposeOne(it, pos); + } + return count; + } + +private: // Save/load + inline void Save(TransductionBackup &b) const { + b.man = this->man; + b.nObjsAlloc = nObjsAlloc; + b.state = state; + b.vObjs = vObjs; + b.vvFis = vvFis; + b.vvFos = vvFos; + b.vLevels = vLevels; + b.vSlacks = vSlacks; + b.vvFiSlacks = vvFiSlacks; + this->CopyVec(b.vFs, vFs); + this->CopyVec(b.vGs, vGs); + this->CopyVec(b.vvCs, vvCs); + b.vUpdates = vUpdates; + b.vPfUpdates = vPfUpdates; + b.vFoConeShared = vFoConeShared; + } + inline void Load(TransductionBackup const &b) { + nObjsAlloc = b.nObjsAlloc; + state = b.state; + vObjs = b.vObjs; + vvFis = b.vvFis; + vvFos = b.vvFos; + vLevels = b.vLevels; + vSlacks = b.vSlacks; + vvFiSlacks = b.vvFiSlacks; + this->CopyVec(vFs, b.vFs); + this->CopyVec(vGs, b.vGs); + this->CopyVec(vvCs, b.vvCs); + vUpdates = b.vUpdates; + vPfUpdates = b.vPfUpdates; + vFoConeShared = b.vFoConeShared; + } + +private: // Connectable condition + inline bool TryConnect(int i, int i0, bool c0) { + int f = (i0 << 1) ^ (int)c0; + if(find(vvFis[i].begin(), vvFis[i].end(), f) == vvFis[i].end()) { + lit x = this->man->Or(this->man->LitNot(vFs[i]), vGs[i]); + this->IncRef(x); + if(this->man->IsConst1(this->man->Or(x, this->man->LitNotCond(vFs[i0], c0)))) { + this->DecRef(x); + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t[TryConnect] adding Wire " << std::setw(5) << i0 << "(" << c0 << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + Connect(i, f, true); + return true; + } + this->DecRef(x); + } + return false; + } + +public: // Resubs + int Resub(bool fMspf) { + int count = fMspf? Mspf(true): Cspf(true); + int nodes = CountNodes(); + TransductionBackup b; + Save(b); + int count_ = count; + std::list targets = vObjs; + for(std::list::reverse_iterator it = targets.rbegin(); it != targets.rend(); it++) { + if(nVerbose > 1) { + std::stringstream ss; + ss << "[Resub] processing Gate " << std::setw(5) << *it + << " (" << std::setw(5) << std::distance(targets.rbegin(), it) + 1 + << "/" << std::setw(5) << targets.size() << ")"; + PrintStats(ss.str(), nVerbose > 2); + } + if(vvFos[*it].empty()) + continue; + count += TrivialMergeOne(*it); + std::vector lev; + if(fLevel) { + for(unsigned j = 0; j < vvFis[*it].size(); j++) + add(lev, vLevels[vvFis[*it][j] >> 1]); + if((int)lev.size() > vLevels[*it] + vSlacks[*it]) { + Load(b); + count = count_; + continue; + } + lev.resize(vLevels[*it] + vSlacks[*it]); + } + bool fConnect = false; + std::vector vMarks(nObjsAlloc); + MarkFoCone_rec(vMarks, *it); + std::list targets2 = vObjs; + for(std::list::iterator it2 = targets2.begin(); it2 != targets2.end(); it2++) { + if(fLevel && (int)lev.size() > vLevels[*it] + vSlacks[*it]) + break; + if(!vMarks[*it2] && !vvFos[*it2].empty()) + if(!fLevel || noexcess(lev, vLevels[*it2])) + if(TryConnect(*it, *it2, false) || TryConnect(*it, *it2, true)) { + fConnect = true; + count--; + if(fLevel) + add(lev, vLevels[*it2]); + } + } + if(fConnect) { + if(fMspf) { + Build(); + count += Mspf(true, *it); + } else { + vPfUpdates[*it] = true; + count += Cspf(true, *it); + } + if(!vvFos[*it].empty()) { + vPfUpdates[*it] = true; + count += fMspf? Mspf(true): Cspf(true); + } + } + if(nodes < CountNodes()) { + Load(b); + count = count_; + continue; + } + if(!vvFos[*it].empty() && vvFis[*it].size() > 2) { + std::list::iterator it2 = find(vObjs.begin(), vObjs.end(), *it); + int pos = nObjsAlloc; + if(fLevel) + count += BalancedDecomposeOne(it2, pos) + (fMspf? Mspf(true): Cspf(true)); + else + count += TrivialDecomposeOne(it2, pos); + } + nodes = CountNodes(); + Save(b); + count_ = count; + } + if(nVerbose) + PrintStats("Resub", true, 11); + return count; + } + int ResubMono(bool fMspf) { + int count = fMspf? Mspf(true): Cspf(true); + std::list targets = vObjs; + for(std::list::reverse_iterator it = targets.rbegin(); it != targets.rend(); it++) { + if(nVerbose > 1) { + std::stringstream ss; + ss << "[ResubMono] processing Gate " << std::setw(5) << *it + << " (" << std::setw(5) << std::distance(targets.rbegin(), it) + 1 + << "/" << std::setw(5) << targets.size() << ")"; + PrintStats(ss.str(), nVerbose > 2); + } + if(vvFos[*it].empty()) + continue; + count += TrivialMergeOne(*it); + TransductionBackup b; + Save(b); + int count_ = count; + for(unsigned i = 0; i < vPis.size(); i++) { + if(vvFos[*it].empty()) + break; + if(nVerbose > 2) { + std::stringstream ss; + ss << "\ttrying a new fanin PI " << std::setw(2) << i; + PrintStats(ss.str(), nVerbose > 3); + } + if(TryConnect(*it, vPis[i], false) || TryConnect(*it, vPis[i], true)) { + count--; + int diff; + if(fMspf) { + Build(); + diff = Mspf(true, *it, vPis[i]); + } else { + vPfUpdates[*it] = true; + diff = Cspf(true, *it, vPis[i]); + } + if(diff) { + count += diff; + if(!vvFos[*it].empty()) { + vPfUpdates[*it] = true; + count += fMspf? Mspf(true): Cspf(true); + } + if(fLevel && CountLevels() > nMaxLevels) { + Load(b); + count = count_; + } else { + Save(b); + count_ = count; + } + } else { + Load(b); + count = count_; + } + } + } + if(vvFos[*it].empty()) + continue; + std::vector vMarks(nObjsAlloc); + MarkFoCone_rec(vMarks, *it); + std::list targets2 = vObjs; + for(std::list::iterator it2 = targets2.begin(); it2 != targets2.end(); it2++) { + if(vvFos[*it].empty()) + break; + if(nVerbose > 2) { + std::stringstream ss; + ss << "\ttrying a new fanin Gate " << std::setw(5) << *it2 + << " (" << std::setw(5) << std::distance(targets2.begin(), it2) + 1 + << "/" << std::setw(5) << targets2.size() << ")"; + PrintStats(ss.str(), nVerbose > 3); + } + if(!vMarks[*it2] && !vvFos[*it2].empty()) + if(TryConnect(*it, *it2, false) || TryConnect(*it, *it2, true)) { + count--; + int diff; + if(fMspf) { + Build(); + diff = Mspf(true, *it, *it2); + } else { + vPfUpdates[*it] = true; + diff = Cspf(true, *it, *it2); + } + if(diff) { + count += diff; + if(!vvFos[*it].empty()) { + vPfUpdates[*it] = true; + count += fMspf? Mspf(true): Cspf(true); + } + if(fLevel && CountLevels() > nMaxLevels) { + Load(b); + count = count_; + } else { + Save(b); + count_ = count; + } + } else { + Load(b); + count = count_; + } + } + } + if(vvFos[*it].empty()) + continue; + if(vvFis[*it].size() > 2) { + std::list::iterator it2 = find(vObjs.begin(), vObjs.end(), *it); + int pos = nObjsAlloc; + if(fLevel) + count += BalancedDecomposeOne(it2, pos) + (fMspf? Mspf(true): Cspf(true)); + else + count += TrivialDecomposeOne(it2, pos); + } + } + if(nVerbose) + PrintStats("ResubMono", true, 11); + return count; + } + int ResubShared(bool fMspf) { + int count = fMspf? Mspf(true): Cspf(true); + std::list targets = vObjs; + for(std::list::reverse_iterator it = targets.rbegin(); it != targets.rend(); it++) { + if(nVerbose > 1) { + std::stringstream ss; + ss << "[ResubShared] processing Gate " << std::setw(5) << *it + << " (" << std::setw(5) << std::distance(targets.rbegin(), it) + 1 + << "/" << std::setw(5) << targets.size() << ")"; + PrintStats(ss.str(), nVerbose > 2); + } + if(vvFos[*it].empty()) + continue; + count += TrivialMergeOne(*it); + bool fConnect = false; + for(unsigned i = 0; i < vPis.size(); i++) + if(TryConnect(*it, vPis[i], false) || TryConnect(*it, vPis[i], true)) { + fConnect |= true; + count--; + } + std::vector vMarks(nObjsAlloc); + MarkFoCone_rec(vMarks, *it); + for(std::list::iterator it2 = targets.begin(); it2 != targets.end(); it2++) + if(!vMarks[*it2] && !vvFos[*it2].empty()) + if(TryConnect(*it, *it2, false) || TryConnect(*it, *it2, true)) { + fConnect |= true; + count--; + } + if(fConnect) { + if(fMspf) { + Build(); + count += Mspf(true, *it); + } else { + vPfUpdates[*it] = true; + count += Cspf(true, *it); + } + if(!vvFos[*it].empty()) { + vPfUpdates[*it] = true; + count += fMspf? Mspf(true): Cspf(true); + } + } + } + count += Decompose(); + if(nVerbose) + PrintStats("ResubShared", true, 11); + return count; + } + +public: // Optimization scripts + int RepeatResub(bool fMono, bool fMspf) { + int count = 0; + while(int diff = fMono? ResubMono(fMspf): Resub(fMspf)) + count += diff; + return count; + } + int RepeatInner(bool fMspf, bool fInner) { + int count = 0; + while(int diff = RepeatResub(true, fMspf) + RepeatResub(false, fMspf)) { + count += diff; + if(!fInner) + break; + } + return count; + } + int RepeatOuter(bool fMspf, bool fInner, bool fOuter) { + int count = 0; + while(int diff = fMspf? RepeatInner(false, fInner) + RepeatInner(true, fInner): RepeatInner(false, fInner)) { + count += diff; + if(!fOuter) + break; + } + return count; + } + int RepeatAll(bool fFirstMerge, bool fMspfMerge, bool fMspfResub, bool fInner, bool fOuter) { + TransductionBackup b; + Save(b); + int count = 0; + int diff = 0; + if(fFirstMerge) + diff = ResubShared(fMspfMerge); + diff += RepeatOuter(fMspfResub, fInner, fOuter); + if(diff > 0) { + count = diff; + Save(b); + diff = 0; + } + while(true) { + diff += ResubShared(fMspfMerge) + RepeatOuter(fMspfResub, fInner, fOuter); + if(diff > 0) { + count += diff; + Save(b); + diff = 0; + } else { + Load(b); + break; + } + } + return count; + } + +public: // Cspf/mspf + int Cspf() { + return Cspf(true); + } + int Mspf() { + return Mspf(true); + } + +private: // Setup + void ImportAig(Gia_Man_t *pGia) { + int i; + Gia_Obj_t *pObj; + nObjsAlloc = Gia_ManObjNum(pGia); + vvFis.resize(nObjsAlloc); + vvFos.resize(nObjsAlloc); + if(fLevel) { + vLevels.resize(nObjsAlloc); + vSlacks.resize(nObjsAlloc); + vvFiSlacks.resize(nObjsAlloc); + } + vFs.resize(nObjsAlloc, LitMax); + vGs.resize(nObjsAlloc, LitMax); + vvCs.resize(nObjsAlloc); + vUpdates.resize(nObjsAlloc); + vPfUpdates.resize(nObjsAlloc); + std::vector v(Gia_ManObjNum(pGia), -1); + int nObjs = 0; + v[Gia_ObjId(pGia, Gia_ManConst0(pGia))] = nObjs << 1; + nObjs++; + Gia_ManForEachCi(pGia, pObj, i) { + v[Gia_ObjId(pGia, pObj)] = nObjs << 1; + vPis.push_back(nObjs); + nObjs++; + } + Gia_ManForEachAnd(pGia, pObj, i) { + int id = Gia_ObjId(pGia, pObj); + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\timport Gate " << std::setw(5) << id; + Print(ss.str(), true); + } + int i0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); + int i1 = Gia_ObjId(pGia, Gia_ObjFanin1(pObj)); + int c0 = Gia_ObjFaninC0(pObj); + int c1 = Gia_ObjFaninC1(pObj); + if(i0 == i1) { + if(c0 == c1) + v[id] = v[i0] ^ c0; + else + v[id] = 0; + } else { + Connect(nObjs , v[i0] ^ c0); + Connect(nObjs, v[i1] ^ c1); + v[id] = nObjs << 1; + vObjs.push_back(nObjs); + nObjs++; + } + } + Gia_ManForEachCo(pGia, pObj, i) { + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\timport PO " << std::setw(2) << i; + Print(ss.str(), true); + } + int i0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); + int c0 = Gia_ObjFaninC0(pObj); + Connect(nObjs, v[i0] ^ c0); + vPos.push_back(nObjs); + nObjs++; + } + } + void Aig2Bdd(Gia_Man_t *pGia, std::vector &vNodes) { + if(nVerbose > 6) + Print("\t\t\tBuild Exdc", true); + int i; + Gia_Obj_t *pObj; + std::vector vCounts(pGia->nObjs); + Gia_ManStaticFanoutStart(pGia); + Gia_ManForEachAnd(pGia, pObj, i) + vCounts[Gia_ObjId(pGia, pObj)] = Gia_ObjFanoutNum(pGia, pObj); + Gia_ManStaticFanoutStop(pGia); + std::vector nodes(pGia->nObjs); + nodes[Gia_ObjId(pGia, Gia_ManConst0(pGia))] = this->man->Const0(); + Gia_ManForEachCi(pGia, pObj, i) + nodes[Gia_ObjId(pGia, pObj)] = this->man->IthVar(i); + Gia_ManForEachAnd(pGia, pObj, i) { + int id = Gia_ObjId(pGia, pObj); + if(nVerbose > 6) { + std::stringstream ss; + ss << "\t\t\t\tbuilding Exdc (" << i << " / " << Gia_ManAndNum(pGia) << ")"; + Print(ss.str(), nVerbose > 7); + } + int i0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); + int i1 = Gia_ObjId(pGia, Gia_ObjFanin1(pObj)); + bool c0 = Gia_ObjFaninC0(pObj); + bool c1 = Gia_ObjFaninC1(pObj); + nodes[id] = this->man->And(this->man->LitNotCond(nodes[i0], c0), this->man->LitNotCond(nodes[i1], c1)); + this->IncRef(nodes[id]); + vCounts[i0]--; + if(!vCounts[i0]) + this->DecRef(nodes[i0]); + vCounts[i1]--; + if(!vCounts[i1]) + this->DecRef(nodes[i1]); + } + Gia_ManForEachCo(pGia, pObj, i) { + int i0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); + bool c0 = Gia_ObjFaninC0(pObj); + vNodes.push_back(this->man->LitNotCond(nodes[i0], c0)); + } + } + void RemoveConstOutputs() { + bool fRemoved = false; + for(unsigned i = 0; i < vPos.size(); i++) { + int i0 = vvFis[vPos[i]][0] >> 1; + lit c = vvCs[vPos[i]][0]; + if(i0) { + if(this->man->IsConst1(this->man->Or(LitFi(vPos[i], 0), c))) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\tPO " << std::setw(2) << i << " is Const 1"; + Print(ss.str(), true); + } + Disconnect(vPos[i], i0, 0, false, false); + Connect(vPos[i], 1, false, false, c); + fRemoved |= vvFos[i0].empty(); + } else if(this->man->IsConst1(this->man->Or(this->man->LitNot(LitFi(vPos[i], 0)), c))) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\tPO " << std::setw(2) << i << " is Const 0"; + Print(ss.str(), true); + } + Disconnect(vPos[i], i0, 0, false, false); + Connect(vPos[i], 0, false, false, c); + fRemoved |= vvFos[i0].empty(); + } + } + } + if(fRemoved) { + for(std::list::reverse_iterator it = vObjs.rbegin(); it != vObjs.rend();) { + if(vvFos[*it].empty()) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\tremove unused Gate " << std::setw(5) << *it; + Print(ss.str(), true); + } + Remove(*it, false); + it = std::list::reverse_iterator(vObjs.erase(--(it.base()))); + continue; + } + it++; + } + } + } + +public: // Constructor + Transduction(Gia_Man_t *pGia, int nVerbose, bool fNewLine, int nSortType, int nPiShuffle, bool fLevel, Gia_Man_t *pExdc, Param &p): nVerbose(nVerbose), nSortType(nSortType), fLevel(fLevel), fNewLine(fNewLine) { + startclk = Abc_Clock(); + p.nGbc = 1; + p.nReo = 4000; + if(nSortType && nSortType < 4) + p.fCountOnes = true; + this->man = new Man(Gia_ManCiNum(pGia), p); + ImportAig(pGia); + this->Update(vFs[0], this->man->Const0()); + for(unsigned i = 0; i < vPis.size(); i++) + this->Update(vFs[i + 1], this->man->IthVar(i)); + nMaxLevels = -1; + Build(false); + this->man->Reorder(); + this->man->TurnOffReo(); + if(pExdc) { + std::vector vExdc; + Aig2Bdd(pExdc, vExdc); + for(unsigned i = 0; i < vPos.size(); i++) + vvCs[vPos[i]][0] = vExdc.size() == 1? vExdc[0]: vExdc[i]; + } else + for(unsigned i = 0; i < vPos.size(); i++) + this->Update(vvCs[vPos[i]][0], this->man->Const0()); + RemoveConstOutputs(); + vPoFs.resize(vPos.size(), LitMax); + for(unsigned i = 0; i < vPos.size(); i++) + this->Update(vPoFs[i], LitFi(vPos[i], 0)); + state = none; + if(nPiShuffle) + ShufflePis(nPiShuffle); + if(fLevel) + ComputeLevel(); + if(nVerbose) + PrintStats("Init", true, 11); + } + ~Transduction() { + if(nVerbose) + PrintStats("End", true, 11); + this->DelVec(vFs); + this->DelVec(vGs); + this->DelVec(vvCs); + this->DelVec(vPoFs); + //assert(this->man->CountNodes() == (int)vPis.size() + 1); + //assert(!this->man->Ref(this->man->Const0())); + delete this->man; + } + +public: // Output + Gia_Man_t *GenerateAig() const { + Gia_Man_t * pGia, *pTemp; + pGia = Gia_ManStart(1 + vPis.size() + CountNodes() + vPos.size()); + Gia_ManHashAlloc(pGia); + std::vector values(nObjsAlloc); + values[0] = Gia_ManConst0Lit(); + for(unsigned i = 0; i < vPis.size(); i++) + values[i + 1] = Gia_ManAppendCi(pGia); + for(std::list::const_iterator it = vObjs.begin(); it != vObjs.end(); it++) { + assert(vvFis[*it].size() > 1); + int i0 = vvFis[*it][0] >> 1; + int i1 = vvFis[*it][1] >> 1; + int c0 = vvFis[*it][0] & 1; + int c1 = vvFis[*it][1] & 1; + int r = Gia_ManHashAnd(pGia, Abc_LitNotCond(values[i0], c0), Abc_LitNotCond(values[i1], c1)); + for(unsigned i = 2; i < vvFis[*it].size(); i++) { + int ii = vvFis[*it][i] >> 1; + int ci = vvFis[*it][i] & 1; + r = Gia_ManHashAnd(pGia, r, Abc_LitNotCond(values[ii], ci)); + } + values[*it] = r; + } + for(unsigned i = 0; i < vPos.size(); i++) { + int i0 = vvFis[vPos[i]][0] >> 1; + int c0 = vvFis[vPos[i]][0] & 1; + Gia_ManAppendCo(pGia, Abc_LitNotCond(values[i0], c0)); + } + pGia = Gia_ManCleanup(pTemp = pGia); + Gia_ManStop(pTemp); + return pGia; + } + +public: // Debug and print + PfState State() const { + return state; + } + bool BuildDebug() { + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + vUpdates[*it] = true; + std::vector vFsOld; + CopyVec(vFsOld, vFs); + Build(false); + bool r = LitVecIsEq(vFsOld, vFs); + DelVec(vFsOld); + return r; + } + bool CspfDebug() { + std::vector vGsOld; + this->CopyVec(vGsOld, vGs); + std::vector > vvCsOld; + this->CopyVec(vvCsOld, vvCs); + state = none; + Cspf(false); + bool r = this->LitVecIsEq(vGsOld, vGs) && this->LitVecIsEq(vvCsOld, vvCs); + this->DelVec(vGsOld); + this->DelVec(vvCsOld); + return r; + } + bool MspfDebug() { + std::vector vGsOld; + this->CopyVec(vGsOld, vGs); + std::vector > vvCsOld; + this->CopyVec(vvCsOld, vvCs); + state = none; + Mspf(false); + bool r = this->LitVecIsEq(vGsOld, vGs) && this->LitVecIsEq(vvCsOld, vvCs); + this->DelVec(vGsOld); + this->DelVec(vvCsOld); + return r; + } + bool Verify() const { + for(unsigned j = 0; j < vPos.size(); j++) { + lit x = this->Xor(LitFi(vPos[j], 0), vPoFs[j]); + this->IncRef(x); + this->Update(x, this->man->And(x, this->man->LitNot(vvCs[vPos[j]][0]))); + this->DecRef(x); + if(!this->man->IsConst0(x)) + return false; + } + return true; + } + void PrintObjs() const { + for(std::list::const_iterator it = vObjs.begin(); it != vObjs.end(); it++) { + std::cout << "Gate " << *it << ":"; + if(fLevel) + std::cout << " Level = " << vLevels[*it] << ", Slack = " << vSlacks[*it]; + std::cout << std::endl; + std::string delim = ""; + std::cout << "\tFis: "; + for(unsigned j = 0; j < vvFis[*it].size(); j++) { + std::cout << delim << (vvFis[*it][j] >> 1) << "(" << (vvFis[*it][j] & 1) << ")"; + delim = ", "; + } + std::cout << std::endl; + delim = ""; + std::cout << "\tFos: "; + for(unsigned j = 0; j < vvFos[*it].size(); j++) { + std::cout << delim << vvFos[*it][j]; + delim = ", "; + } + std::cout << std::endl; + } + } +}; + +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/abc/src/aig/gia/giaTruth.c b/abc/src/aig/gia/giaTruth.c index 86f17594dc2..c24748ede00 100644 --- a/abc/src/aig/gia/giaTruth.c +++ b/abc/src/aig/gia/giaTruth.c @@ -52,6 +52,171 @@ static inline word * Gla_ObjTruthDup( Gia_Man_t * p, word * pDst, word * pSrc, i /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// +/**Function************************************************************* + + Synopsis [Compute truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Gia_LutComputeTruth6Simple_rec( Gia_Man_t * p, int iObj ) +{ + word Truth0, Truth1, Truth; + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + if ( Gia_ObjIsConst0(pObj) ) + return 0; + if ( Gia_ObjIsCi(pObj) ) + return s_Truths6[Gia_ObjCioId(pObj)]; + Truth0 = Gia_LutComputeTruth6Simple_rec( p, Gia_ObjFaninId0(pObj, iObj) ); + Truth1 = Gia_LutComputeTruth6Simple_rec( p, Gia_ObjFaninId1(pObj, iObj) ); + Truth0 = Gia_ObjFaninC0(pObj) ? ~Truth0 : Truth0; + Truth1 = Gia_ObjFaninC1(pObj) ? ~Truth1 : Truth1; + Truth = Gia_ObjIsXor(pObj) ? Truth0 ^ Truth1 : Truth0 & Truth1; + return Truth; +} +word Gia_LutComputeTruth6Simple( Gia_Man_t * p, int iPo ) +{ + Gia_Obj_t * pObj = Gia_ManPo( p, iPo ); + word Truth = Gia_LutComputeTruth6Simple_rec( p, Gia_ObjFaninId0p(p, pObj) ); + return Gia_ObjFaninC0(pObj) ? ~Truth : Truth; +} + +word Gia_LutComputeTruth6Map_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vMap ) +{ + word Truth0, Truth1, Truth; + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + if ( Gia_ObjIsConst0(pObj) ) + return 0; + if ( Gia_ObjIsCi(pObj) ) + return s_Truths6[Vec_IntEntry(vMap, Gia_ObjCioId(pObj))]; + Truth0 = Gia_LutComputeTruth6Map_rec( p, Gia_ObjFaninId0(pObj, iObj), vMap ); + Truth1 = Gia_LutComputeTruth6Map_rec( p, Gia_ObjFaninId1(pObj, iObj), vMap ); + Truth0 = Gia_ObjFaninC0(pObj) ? ~Truth0 : Truth0; + Truth1 = Gia_ObjFaninC1(pObj) ? ~Truth1 : Truth1; + Truth = Gia_ObjIsXor(pObj) ? Truth0 ^ Truth1 : Truth0 & Truth1; + return Truth; +} +word Gia_LutComputeTruth6Map( Gia_Man_t * p, int iPo, Vec_Int_t * vMap ) +{ + Gia_Obj_t * pObj = Gia_ManPo( p, iPo ); + word Truth = Gia_LutComputeTruth6Map_rec( p, Gia_ObjFaninId0p(p, pObj), vMap ); + return Gia_ObjFaninC0(pObj) ? ~Truth : Truth; +} + +/**Function************************************************************* + + Synopsis [Generate MUX tree of the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Truth5ToGia( Gia_Man_t * p, int * pVarLits, int nVars, unsigned Truth, int fHash ) +{ + int Var, Lit0, Lit1; + if ( Truth == 0 ) + return 0; + if ( ~Truth == 0 ) + return 1; + assert( nVars > 0 ); + // find the topmost var + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt5HasVar( Truth, Var ) ) + break; + assert( Var >= 0 ); + // cofactor + Lit0 = Gia_Truth5ToGia( p, pVarLits, Var, Abc_Tt5Cofactor0(Truth, Var), fHash ); + Lit1 = Gia_Truth5ToGia( p, pVarLits, Var, Abc_Tt5Cofactor1(Truth, Var), fHash ); + if ( fHash ) + return Gia_ManHashMux( p, pVarLits[Var], Lit1, Lit0 ); + else + return Gia_ManAppendMux( p, pVarLits[Var], Lit1, Lit0 ); +} + +/**Function************************************************************* + + Synopsis [Generate MUX tree of the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Truth6ToGia( Gia_Man_t * p, int * pVarLits, int nVars, word Truth, int fHash ) +{ + int Var, Lit0, Lit1; + if ( Truth == 0 ) + return 0; + if ( ~Truth == 0 ) + return 1; + assert( nVars > 0 ); + // find the topmost var + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt6HasVar( Truth, Var ) ) + break; + assert( Var >= 0 ); + // cofactor + Lit0 = Gia_Truth6ToGia( p, pVarLits, Var, Abc_Tt6Cofactor0(Truth, Var), fHash ); + Lit1 = Gia_Truth6ToGia( p, pVarLits, Var, Abc_Tt6Cofactor1(Truth, Var), fHash ); + if ( fHash ) + return Gia_ManHashMux( p, pVarLits[Var], Lit1, Lit0 ); + else + return Gia_ManAppendMux( p, pVarLits[Var], Lit1, Lit0 ); +} +void Gia_Truth6ToGiaTest( Gia_Man_t * p ) +{ + int Size = 5; + word Truth, TruthNew; + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManCiNum(p) ); + Vec_Int_t * vSupp = Vec_IntStart( 100 ); + int nCos = Gia_ManCoNum(p), Count = 0; + int i, k, Id, ObjId, iLitNew; + Gia_ManHashAlloc( p ); + Gia_ManForEachCoId( p, Id, i ) + { + Gia_ManCollectCis( p, &Id, 1, vSupp ); // ObjIds + if ( Vec_IntSize(vSupp) <= Size && i < nCos ) + { + int pVarLits[6]; + Vec_IntForEachEntry( vSupp, ObjId, k ) + { + int CioId = Gia_ObjCioId(Gia_ManObj(p, ObjId)); + Vec_IntWriteEntry( vMap, CioId, k ); + pVarLits[k] = Abc_Var2Lit( ObjId, 0 ); + } + Truth = Gia_LutComputeTruth6Map( p, i, vMap ); + if ( Size == 5 ) + iLitNew = Gia_Truth5ToGia( p, pVarLits, Vec_IntSize(vSupp), (unsigned)Truth, 1 ); + else + iLitNew = Gia_Truth6ToGia( p, pVarLits, Vec_IntSize(vSupp), Truth, 1 ); + Gia_ManAppendCo( p, iLitNew ); + TruthNew = Gia_LutComputeTruth6Map( p, Gia_ManCoNum(p)-1, vMap ); + Vec_IntForEachEntry( vSupp, ObjId, k ) + { + int CioId = Gia_ObjCioId(Gia_ManObj(p, ObjId)); + Vec_IntWriteEntry( vMap, CioId, -1 ); + } + if ( Truth != TruthNew ) + printf( "Error for output %d.\n", i ); + Count++; + //Dau_DsdPrintFromTruth( &Truth, Vec_IntSize(vSupp) ); + } + } + Gia_ManHashStop( p ); + printf( "Finished processing %d outputs.\n", Count ); + Vec_IntFree( vSupp ); + Vec_IntFree( vMap ); +} + /**Function************************************************************* Synopsis [Compute truth table.] @@ -459,9 +624,18 @@ word * Gia_ObjComputeTruthTableCut( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t { Gia_Obj_t * pTemp; word * pTruth, * pTruthL, * pTruth0, * pTruth1; - int i, iObj, Id0, Id1; + int i, iObj, Id0, Id1, Index = Vec_IntFind(vLeaves, Gia_ObjId(p, pRoot)); assert( p->vTtMemory != NULL ); assert( Vec_IntSize(vLeaves) <= p->nTtVars ); + if ( Index >= 0 ) + return Gla_ObjTruthElem( p, Index ); + if ( Gia_ObjIsConst0(pRoot) ) + { + if ( Vec_WrdSize(p->vTtMemory) < p->nTtWords ) + Vec_WrdFillExtra( p->vTtMemory, p->nTtWords, 0 ); + return Gla_ObjTruthConst0( p, Gla_ObjTruthFree1(p) ); + } + assert( Gia_ObjIsAnd(pRoot) ); // extend ID numbers if ( Vec_IntSize(p->vTtNums) < Gia_ManObjNum(p) ) Vec_IntFillExtra( p->vTtNums, Gia_ManObjNum(p), -ABC_INFINITY ); diff --git a/abc/src/aig/gia/giaTtopt.cpp b/abc/src/aig/gia/giaTtopt.cpp new file mode 100644 index 00000000000..a765633f8c5 --- /dev/null +++ b/abc/src/aig/gia/giaTtopt.cpp @@ -0,0 +1,1213 @@ +/**CFile**************************************************************** + + FileName [giaTtopt.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Truth-table-based logic synthesis.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaTtopt.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma warning(disable : 4786) // warning C4786: identifier was truncated to '255' characters in the browser information +#endif +#endif + +#include +#include +#include +#include + +#include "gia.h" +#include "misc/vec/vecHash.h" + +ABC_NAMESPACE_IMPL_START + +namespace Ttopt { + +class TruthTable { +public: + static const int ww; // word width + static const int lww; // log word width + typedef std::bitset<64> bsw; + + int nInputs; + int nSize; + int nTotalSize; + int nOutputs; + std::vector t; + + std::vector > vvIndices; + std::vector > vvRedundantIndices; + std::vector vLevels; + + std::vector > savedt; + std::vector > > vvIndicesSaved; + std::vector > > vvRedundantIndicesSaved; + std::vector > vLevelsSaved; + + static const word ones[]; + static const word swapmask[]; + + TruthTable(int nInputs, int nOutputs): nInputs(nInputs), nOutputs(nOutputs) { + srand(0xABC); + if(nInputs >= lww) { + nSize = 1 << (nInputs - lww); + nTotalSize = nSize * nOutputs; + t.resize(nTotalSize); + } else { + nSize = 0; + nTotalSize = ((1 << nInputs) * nOutputs + ww - 1) / ww; + t.resize(nTotalSize); + } + vLevels.resize(nInputs); + for(int i = 0; i < nInputs; i++) { + vLevels[i] = i; + } + } + + virtual void Save(unsigned i) { + if(savedt.size() < i + 1) { + savedt.resize(i + 1); + vLevelsSaved.resize(i + 1); + } + savedt[i] = t; + vLevelsSaved[i] = vLevels; + } + + virtual void Load(unsigned i) { + assert(i < savedt.size()); + t = savedt[i]; + vLevels = vLevelsSaved[i]; + } + + virtual void SaveIndices(unsigned i) { + if(vvIndicesSaved.size() < i + 1) { + vvIndicesSaved.resize(i + 1); + vvRedundantIndicesSaved.resize(i + 1); + } + vvIndicesSaved[i] = vvIndices; + vvRedundantIndicesSaved[i] = vvRedundantIndices; + } + + virtual void LoadIndices(unsigned i) { + vvIndices = vvIndicesSaved[i]; + vvRedundantIndices = vvRedundantIndicesSaved[i]; + } + + word GetValue(int index_lev, int lev) { + assert(index_lev >= 0); + assert(nInputs - lev <= lww); + int logwidth = nInputs - lev; + int index = index_lev >> (lww - logwidth); + int pos = (index_lev % (1 << (lww - logwidth))) << logwidth; + return (t[index] >> pos) & ones[logwidth]; + } + + int IsEq(int index1, int index2, int lev, bool fCompl = false) { + assert(index1 >= 0); + assert(index2 >= 0); + int logwidth = nInputs - lev; + bool fEq = true; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + for(int i = 0; i < nScopeSize && (fEq || fCompl); i++) { + fEq &= (t[nScopeSize * index1 + i] == t[nScopeSize * index2 + i]); + fCompl &= (t[nScopeSize * index1 + i] == ~t[nScopeSize * index2 + i]); + } + } else { + word value = GetValue(index1, lev) ^ GetValue(index2, lev); + fEq &= !value; + fCompl &= !(value ^ ones[logwidth]); + } + return 2 * fCompl + fEq; + } + + bool Imply(int index1, int index2, int lev) { + assert(index1 >= 0); + assert(index2 >= 0); + int logwidth = nInputs - lev; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + for(int i = 0; i < nScopeSize; i++) { + if(t[nScopeSize * index1 + i] & ~t[nScopeSize * index2 + i]) { + return false; + } + } + return true; + } + return !(GetValue(index1, lev) & (GetValue(index2, lev) ^ ones[logwidth])); + } + + int BDDNodeCountLevel(int lev) { + return vvIndices[lev].size() - vvRedundantIndices[lev].size(); + } + + int BDDNodeCount() { + int count = 1; // const node + for(int i = 0; i < nInputs; i++) { + count += BDDNodeCountLevel(i); + } + return count; + } + + int BDDFind(int index, int lev) { + int logwidth = nInputs - lev; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + bool fZero = true; + bool fOne = true; + for(int i = 0; i < nScopeSize && (fZero || fOne); i++) { + word value = t[nScopeSize * index + i]; + fZero &= !value; + fOne &= !(~value); + } + if(fZero || fOne) { + return -2 ^ (int)fOne; + } + for(unsigned j = 0; j < vvIndices[lev].size(); j++) { + int index2 = vvIndices[lev][j]; + bool fEq = true; + bool fCompl = true; + for(int i = 0; i < nScopeSize && (fEq || fCompl); i++) { + fEq &= (t[nScopeSize * index + i] == t[nScopeSize * index2 + i]); + fCompl &= (t[nScopeSize * index + i] == ~t[nScopeSize * index2 + i]); + } + if(fEq || fCompl) { + return (j << 1) ^ (int)fCompl; + } + } + } else { + word value = GetValue(index, lev); + if(!value) { + return -2; + } + if(!(value ^ ones[logwidth])) { + return -1; + } + for(unsigned j = 0; j < vvIndices[lev].size(); j++) { + int index2 = vvIndices[lev][j]; + word value2 = value ^ GetValue(index2, lev); + if(!(value2)) { + return j << 1; + } + if(!(value2 ^ ones[logwidth])) { + return (j << 1) ^ 1; + } + } + } + return -3; + } + + virtual int BDDBuildOne(int index, int lev) { + int r = BDDFind(index, lev); + if(r >= -2) { + return r; + } + vvIndices[lev].push_back(index); + return (vvIndices[lev].size() - 1) << 1; + } + + virtual void BDDBuildStartup() { + vvIndices.clear(); + vvIndices.resize(nInputs); + vvRedundantIndices.clear(); + vvRedundantIndices.resize(nInputs); + for(int i = 0; i < nOutputs; i++) { + BDDBuildOne(i, 0); + } + } + + virtual void BDDBuildLevel(int lev) { + for(unsigned i = 0; i < vvIndices[lev-1].size(); i++) { + int index = vvIndices[lev-1][i]; + int cof0 = BDDBuildOne(index << 1, lev); + int cof1 = BDDBuildOne((index << 1) ^ 1, lev); + if(cof0 == cof1) { + vvRedundantIndices[lev-1].push_back(index); + } + } + } + + virtual int BDDBuild() { + BDDBuildStartup(); + for(int i = 1; i < nInputs; i++) { + BDDBuildLevel(i); + } + return BDDNodeCount(); + } + + virtual int BDDRebuild(int lev) { + vvIndices[lev].clear(); + vvIndices[lev+1].clear(); + for(int i = lev; i < lev + 2; i++) { + if(!i) { + for(int j = 0; j < nOutputs; j++) { + BDDBuildOne(j, 0); + } + } else { + vvRedundantIndices[i-1].clear(); + BDDBuildLevel(i); + } + } + if(lev < nInputs - 2) { + vvRedundantIndices[lev+1].clear(); + for(unsigned i = 0; i < vvIndices[lev+1].size(); i++) { + int index = vvIndices[lev+1][i]; + if(IsEq(index << 1, (index << 1) ^ 1, lev + 2)) { + vvRedundantIndices[lev+1].push_back(index); + } + } + } + return BDDNodeCount(); + } + + virtual void Swap(int lev) { + assert(lev < nInputs - 1); + std::vector::iterator it0 = std::find(vLevels.begin(), vLevels.end(), lev); + std::vector::iterator it1 = std::find(vLevels.begin(), vLevels.end(), lev + 1); + std::swap(*it0, *it1); + if(nInputs - lev - 1 > lww) { + int nScopeSize = 1 << (nInputs - lev - 2 - lww); + for(int i = nScopeSize; i < nTotalSize; i += (nScopeSize << 2)) { + for(int j = 0; j < nScopeSize; j++) { + std::swap(t[i + j], t[i + nScopeSize + j]); + } + } + } else if(nInputs - lev - 1 == lww) { + for(int i = 0; i < nTotalSize; i += 2) { + t[i+1] ^= t[i] >> (ww / 2); + t[i] ^= t[i+1] << (ww / 2); + t[i+1] ^= t[i] >> (ww / 2); + } + } else { + for(int i = 0; i < nTotalSize; i++) { + int d = nInputs - lev - 2; + int shamt = 1 << d; + t[i] ^= (t[i] >> shamt) & swapmask[d]; + t[i] ^= (t[i] & swapmask[d]) << shamt; + t[i] ^= (t[i] >> shamt) & swapmask[d]; + } + } + } + + void SwapIndex(int &index, int d) { + if((index >> d) % 4 == 1) { + index += 1 << d; + } else if((index >> d) % 4 == 2) { + index -= 1 << d; + } + } + + virtual int BDDSwap(int lev) { + Swap(lev); + for(int i = lev + 2; i < nInputs; i++) { + for(unsigned j = 0; j < vvIndices[i].size(); j++) { + SwapIndex(vvIndices[i][j], i - (lev + 2)); + } + } + // swapping vvRedundantIndices is unnecessary for node counting + return BDDRebuild(lev); + } + + int SiftReo() { + int best = BDDBuild(); + Save(0); + SaveIndices(0); + std::vector vars(nInputs); + int i; + for(i = 0; i < nInputs; i++) { + vars[i] = i; + } + std::vector vCounts(nInputs); + for(i = 0; i < nInputs; i++) { + vCounts[i] = BDDNodeCountLevel(vLevels[i]); + } + for(i = 1; i < nInputs; i++) { + int j = i; + while(j > 0 && vCounts[vars[j-1]] < vCounts[vars[j]]) { + std::swap(vars[j], vars[j-1]); + j--; + } + } + bool turn = true; + unsigned j; + for(j = 0; j < vars.size(); j++) { + int var = vars[j]; + bool updated = false; + int lev = vLevels[var]; + for(int i = lev; i < nInputs - 1; i++) { + int count = BDDSwap(i); + if(best > count) { + best = count; + updated = true; + Save(turn); + SaveIndices(turn); + } + } + if(lev) { + Load(!turn); + LoadIndices(!turn); + for(int i = lev - 1; i >= 0; i--) { + int count = BDDSwap(i); + if(best > count) { + best = count; + updated = true; + Save(turn); + SaveIndices(turn); + } + } + } + turn ^= updated; + Load(!turn); + LoadIndices(!turn); + } + return best; + } + + void Reo(std::vector vLevelsNew) { + for(int i = 0; i < nInputs; i++) { + int var = std::find(vLevelsNew.begin(), vLevelsNew.end(), i) - vLevelsNew.begin(); + int lev = vLevels[var]; + if(lev < i) { + for(int j = lev; j < i; j++) { + Swap(j); + } + } else if(lev > i) { + for(int j = lev - 1; j >= i; j--) { + Swap(j); + } + } + } + assert(vLevels == vLevelsNew); + } + + int RandomSiftReo(int nRound) { + int best = SiftReo(); + Save(2); + for(int i = 0; i < nRound; i++) { + std::vector vLevelsNew(nInputs); + int j; + for(j = 0; j < nInputs; j++) { + vLevelsNew[j] = j; + } + for(j = nInputs - 1; j > 0; j--) { + int d = rand() % j; + std::swap(vLevelsNew[j], vLevelsNew[d]); + } + Reo(vLevelsNew); + int r = SiftReo(); + if(best > r) { + best = r; + Save(2); + } + } + Load(2); + return best; + } + + int BDDGenerateAigRec(Gia_Man_t *pNew, std::vector const &vInputs, std::vector > &vvNodes, int index, int lev) { + int r = BDDFind(index, lev); + if(r >= 0) { + return vvNodes[lev][r >> 1] ^ (r & 1); + } + if(r >= -2) { + return r + 2; + } + int cof0 = BDDGenerateAigRec(pNew, vInputs, vvNodes, index << 1, lev + 1); + int cof1 = BDDGenerateAigRec(pNew, vInputs, vvNodes, (index << 1) ^ 1, lev + 1); + if(cof0 == cof1) { + return cof0; + } + int node; + if(Imply(index << 1, (index << 1) ^ 1, lev + 1)) { + node = Gia_ManHashOr(pNew, Gia_ManHashAnd(pNew, vInputs[lev], cof1), cof0); + } else if(Imply((index << 1) ^ 1, index << 1, lev + 1)) { + node = Gia_ManHashOr(pNew, Gia_ManHashAnd(pNew, vInputs[lev] ^ 1, cof0), cof1); + } else { + node = Gia_ManHashMux(pNew, vInputs[lev], cof1, cof0); + } + vvIndices[lev].push_back(index); + vvNodes[lev].push_back(node); + return node; + } + + virtual void BDDGenerateAig(Gia_Man_t *pNew, Vec_Int_t *vSupp) { + vvIndices.clear(); + vvIndices.resize(nInputs); + std::vector > vvNodes(nInputs); + std::vector vInputs(nInputs); + int i; + for(i = 0; i < nInputs; i++) { + vInputs[vLevels[i]] = Vec_IntEntry(vSupp, nInputs - i - 1) << 1; + } + for(i = 0; i < nOutputs; i++) { + int node = BDDGenerateAigRec(pNew, vInputs, vvNodes, i, 0); + Gia_ManAppendCo(pNew, node); + } + } +}; + +const int TruthTable::ww = 64; +const int TruthTable::lww = 6; + +const word TruthTable::ones[7] = {ABC_CONST(0x0000000000000001), + ABC_CONST(0x0000000000000003), + ABC_CONST(0x000000000000000f), + ABC_CONST(0x00000000000000ff), + ABC_CONST(0x000000000000ffff), + ABC_CONST(0x00000000ffffffff), + ABC_CONST(0xffffffffffffffff)}; + +const word TruthTable::swapmask[5] = {ABC_CONST(0x2222222222222222), + ABC_CONST(0x0c0c0c0c0c0c0c0c), + ABC_CONST(0x00f000f000f000f0), + ABC_CONST(0x0000ff000000ff00), + ABC_CONST(0x00000000ffff0000)}; + +class TruthTableReo : public TruthTable { +public: + bool fBuilt; + std::vector > vvChildren; + std::vector > > vvChildrenSaved; + + TruthTableReo(int nInputs, int nOutputs): TruthTable(nInputs, nOutputs) { + fBuilt = false; + } + + void Save(unsigned i) { + if(vLevelsSaved.size() < i + 1) { + vLevelsSaved.resize(i + 1); + } + vLevelsSaved[i] = vLevels; + } + + void Load(unsigned i) { + assert(i < vLevelsSaved.size()); + vLevels = vLevelsSaved[i]; + } + + void SaveIndices(unsigned i) { + TruthTable::SaveIndices(i); + if(vvChildrenSaved.size() < i + 1) { + vvChildrenSaved.resize(i + 1); + } + vvChildrenSaved[i] = vvChildren; + } + + void LoadIndices(unsigned i) { + TruthTable::LoadIndices(i); + vvChildren = vvChildrenSaved[i]; + } + + void BDDBuildStartup() { + vvChildren.clear(); + vvChildren.resize(nInputs); + TruthTable::BDDBuildStartup(); + } + + void BDDBuildLevel(int lev) { + for(unsigned i = 0; i < vvIndices[lev-1].size(); i++) { + int index = vvIndices[lev-1][i]; + int cof0 = BDDBuildOne(index << 1, lev); + int cof1 = BDDBuildOne((index << 1) ^ 1, lev); + vvChildren[lev-1].push_back(cof0); + vvChildren[lev-1].push_back(cof1); + if(cof0 == cof1) { + vvRedundantIndices[lev-1].push_back(index); + } + } + } + + int BDDBuild() { + if(fBuilt) { + return BDDNodeCount(); + } + fBuilt = true; + BDDBuildStartup(); + for(int i = 1; i < nInputs + 1; i++) { + BDDBuildLevel(i); + } + return BDDNodeCount(); + } + + int BDDRebuildOne(int index, int cof0, int cof1, int lev, Hash_IntMan_t *unique, std::vector &vChildrenLow) { + if(cof0 < 0 && cof0 == cof1) { + return cof0; + } + bool fCompl = cof0 & 1; + if(fCompl) { + cof0 ^= 1; + cof1 ^= 1; + } + int *place = Hash_Int2ManLookup(unique, cof0, cof1); + if(*place) { + return (Hash_IntObjData2(unique, *place) << 1) ^ (int)fCompl; + } + vvIndices[lev].push_back(index); + Hash_Int2ManInsert(unique, cof0, cof1, vvIndices[lev].size() - 1); + vChildrenLow.push_back(cof0); + vChildrenLow.push_back(cof1); + if(cof0 == cof1) { + vvRedundantIndices[lev].push_back(index); + } + return ((vvIndices[lev].size() - 1) << 1) ^ (int)fCompl; + } + + int BDDRebuild(int lev) { + vvRedundantIndices[lev].clear(); + vvRedundantIndices[lev+1].clear(); + std::vector vChildrenHigh; + std::vector vChildrenLow; + Hash_IntMan_t *unique = Hash_IntManStart(2 * vvIndices[lev+1].size()); + vvIndices[lev+1].clear(); + for(unsigned i = 0; i < vvIndices[lev].size(); i++) { + int index = vvIndices[lev][i]; + int cof0index = vvChildren[lev][i+i] >> 1; + int cof1index = vvChildren[lev][i+i+1] >> 1; + bool cof0c = vvChildren[lev][i+i] & 1; + bool cof1c = vvChildren[lev][i+i+1] & 1; + int cof00, cof01, cof10, cof11; + if(cof0index < 0) { + cof00 = -2 ^ (int)cof0c; + cof01 = -2 ^ (int)cof0c; + } else { + cof00 = vvChildren[lev+1][cof0index+cof0index] ^ (int)cof0c; + cof01 = vvChildren[lev+1][cof0index+cof0index+1] ^ (int)cof0c; + } + if(cof1index < 0) { + cof10 = -2 ^ (int)cof1c; + cof11 = -2 ^ (int)cof1c; + } else { + cof10 = vvChildren[lev+1][cof1index+cof1index] ^ (int)cof1c; + cof11 = vvChildren[lev+1][cof1index+cof1index+1] ^ (int)cof1c; + } + int newcof0 = BDDRebuildOne(index << 1, cof00, cof10, lev + 1, unique, vChildrenLow); + int newcof1 = BDDRebuildOne((index << 1) ^ 1, cof01, cof11, lev + 1, unique, vChildrenLow); + vChildrenHigh.push_back(newcof0); + vChildrenHigh.push_back(newcof1); + if(newcof0 == newcof1) { + vvRedundantIndices[lev].push_back(index); + } + } + Hash_IntManStop(unique); + vvChildren[lev] = vChildrenHigh; + vvChildren[lev+1] = vChildrenLow; + return BDDNodeCount(); + } + + void Swap(int lev) { + assert(lev < nInputs - 1); + std::vector::iterator it0 = std::find(vLevels.begin(), vLevels.end(), lev); + std::vector::iterator it1 = std::find(vLevels.begin(), vLevels.end(), lev + 1); + std::swap(*it0, *it1); + BDDRebuild(lev); + } + + int BDDSwap(int lev) { + Swap(lev); + return BDDNodeCount(); + } + + virtual void BDDGenerateAig(Gia_Man_t *pNew, Vec_Int_t *vSupp) { + abort(); + } +}; + +class TruthTableRewrite : public TruthTable { +public: + TruthTableRewrite(int nInputs, int nOutputs): TruthTable(nInputs, nOutputs) {} + + void SetValue(int index_lev, int lev, word value) { + assert(index_lev >= 0); + assert(nInputs - lev <= lww); + int logwidth = nInputs - lev; + int index = index_lev >> (lww - logwidth); + int pos = (index_lev % (1 << (lww - logwidth))) << logwidth; + t[index] &= ~(ones[logwidth] << pos); + t[index] ^= value << pos; + } + + void CopyFunc(int index1, int index2, int lev, bool fCompl) { + assert(index1 >= 0); + int logwidth = nInputs - lev; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + if(!fCompl) { + if(index2 < 0) { + for(int i = 0; i < nScopeSize; i++) { + t[nScopeSize * index1 + i] = 0; + } + } else { + for(int i = 0; i < nScopeSize; i++) { + t[nScopeSize * index1 + i] = t[nScopeSize * index2 + i]; + } + } + } else { + if(index2 < 0) { + for(int i = 0; i < nScopeSize; i++) { + t[nScopeSize * index1 + i] = ones[lww]; + } + } else { + for(int i = 0; i < nScopeSize; i++) { + t[nScopeSize * index1 + i] = ~t[nScopeSize * index2 + i]; + } + } + } + } else { + word value = 0; + if(index2 >= 0) { + value = GetValue(index2, lev); + } + if(fCompl) { + value ^= ones[logwidth]; + } + SetValue(index1, lev, value); + } + } + + void ShiftToMajority(int index, int lev) { + assert(index >= 0); + int logwidth = nInputs - lev; + int count = 0; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + for(int i = 0; i < nScopeSize; i++) { + count += bsw(t[nScopeSize * index + i]).count(); + } + } else { + count = bsw(GetValue(index, lev)).count(); + } + bool majority = count > (1 << (logwidth - 1)); + CopyFunc(index, -1, lev, majority); + } +}; + +class TruthTableCare : public TruthTableRewrite { +public: + std::vector originalt; + std::vector caret; + std::vector care; + + std::vector > > vvMergedIndices; + + std::vector > savedcare; + std::vector > > > vvMergedIndicesSaved; + + TruthTableCare(int nInputs, int nOutputs): TruthTableRewrite(nInputs, nOutputs) { + if(nSize) { + care.resize(nSize); + } else { + care.resize(1); + } + } + + void Save(unsigned i) { + TruthTable::Save(i); + if(savedcare.size() < i + 1) { + savedcare.resize(i + 1); + } + savedcare[i] = care; + } + + void Load(unsigned i) { + TruthTable::Load(i); + care = savedcare[i]; + } + + void SaveIndices(unsigned i) { + TruthTable::SaveIndices(i); + if(vvMergedIndicesSaved.size() < i + 1) { + vvMergedIndicesSaved.resize(i + 1); + } + vvMergedIndicesSaved[i] = vvMergedIndices; + } + + void LoadIndices(unsigned i) { + TruthTable::LoadIndices(i); + vvMergedIndices = vvMergedIndicesSaved[i]; + } + + void Swap(int lev) { + TruthTable::Swap(lev); + if(nInputs - lev - 1 > lww) { + int nScopeSize = 1 << (nInputs - lev - 2 - lww); + for(int i = nScopeSize; i < nSize; i += (nScopeSize << 2)) { + for(int j = 0; j < nScopeSize; j++) { + std::swap(care[i + j], care[i + nScopeSize + j]); + } + } + } else if(nInputs - lev - 1 == lww) { + for(int i = 0; i < nSize; i += 2) { + care[i+1] ^= care[i] >> (ww / 2); + care[i] ^= care[i+1] << (ww / 2); + care[i+1] ^= care[i] >> (ww / 2); + } + } else { + for(int i = 0; i < nSize || (i == 0 && !nSize); i++) { + int d = nInputs - lev - 2; + int shamt = 1 << d; + care[i] ^= (care[i] >> shamt) & swapmask[d]; + care[i] ^= (care[i] & swapmask[d]) << shamt; + care[i] ^= (care[i] >> shamt) & swapmask[d]; + } + } + } + + void RestoreCare() { + caret.clear(); + if(nSize) { + for(int i = 0; i < nOutputs; i++) { + caret.insert(caret.end(), care.begin(), care.end()); + } + } else { + caret.resize(nTotalSize); + for(int i = 0; i < nOutputs; i++) { + int padding = i * (1 << nInputs); + caret[padding / ww] |= care[0] << (padding % ww); + } + } + } + + word GetCare(int index_lev, int lev) { + assert(index_lev >= 0); + assert(nInputs - lev <= lww); + int logwidth = nInputs - lev; + int index = index_lev >> (lww - logwidth); + int pos = (index_lev % (1 << (lww - logwidth))) << logwidth; + return (caret[index] >> pos) & ones[logwidth]; + } + + void CopyFuncMasked(int index1, int index2, int lev, bool fCompl) { + assert(index1 >= 0); + assert(index2 >= 0); + int logwidth = nInputs - lev; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + for(int i = 0; i < nScopeSize; i++) { + word value = t[nScopeSize * index2 + i]; + if(fCompl) { + value = ~value; + } + word cvalue = caret[nScopeSize * index2 + i]; + t[nScopeSize * index1 + i] &= ~cvalue; + t[nScopeSize * index1 + i] |= cvalue & value; + } + } else { + word one = ones[logwidth]; + word value1 = GetValue(index1, lev); + word value2 = GetValue(index2, lev); + if(fCompl) { + value2 ^= one; + } + word cvalue = GetCare(index2, lev); + value1 &= cvalue ^ one; + value1 |= cvalue & value2; + SetValue(index1, lev, value1); + } + } + + bool IsDC(int index, int lev) { + if(nInputs - lev > lww) { + int nScopeSize = 1 << (nInputs - lev - lww); + for(int i = 0; i < nScopeSize; i++) { + if(caret[nScopeSize * index + i]) { + return false; + } + } + } else if(GetCare(index, lev)) { + return false; + } + return true; + } + + int Include(int index1, int index2, int lev, bool fCompl) { + assert(index1 >= 0); + assert(index2 >= 0); + int logwidth = nInputs - lev; + bool fEq = true; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + for(int i = 0; i < nScopeSize && (fEq || fCompl); i++) { + word cvalue = caret[nScopeSize * index2 + i]; + if(~caret[nScopeSize * index1 + i] & cvalue) { + return 0; + } + word value = t[nScopeSize * index1 + i] ^ t[nScopeSize * index2 + i]; + fEq &= !(value & cvalue); + fCompl &= !(~value & cvalue); + } + } else { + word cvalue = GetCare(index2, lev); + if((GetCare(index1, lev) ^ ones[logwidth]) & cvalue) { + return 0; + } + word value = GetValue(index1, lev) ^ GetValue(index2, lev); + fEq &= !(value & cvalue); + fCompl &= !((value ^ ones[logwidth]) & cvalue); + } + return 2 * fCompl + fEq; + } + + int Intersect(int index1, int index2, int lev, bool fCompl, bool fEq = true) { + assert(index1 >= 0); + assert(index2 >= 0); + int logwidth = nInputs - lev; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + for(int i = 0; i < nScopeSize && (fEq || fCompl); i++) { + word value = t[nScopeSize * index1 + i] ^ t[nScopeSize * index2 + i]; + word cvalue = caret[nScopeSize * index1 + i] & caret[nScopeSize * index2 + i]; + fEq &= !(value & cvalue); + fCompl &= !(~value & cvalue); + } + } else { + word value = GetValue(index1, lev) ^ GetValue(index2, lev); + word cvalue = GetCare(index1, lev) & GetCare(index2, lev); + fEq &= !(value & cvalue); + fCompl &= !((value ^ ones[logwidth]) & cvalue); + } + return 2 * fCompl + fEq; + } + + void MergeCare(int index1, int index2, int lev) { + assert(index1 >= 0); + assert(index2 >= 0); + int logwidth = nInputs - lev; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + for(int i = 0; i < nScopeSize; i++) { + caret[nScopeSize * index1 + i] |= caret[nScopeSize * index2 + i]; + } + } else { + word value = GetCare(index2, lev); + int index = index1 >> (lww - logwidth); + int pos = (index1 % (1 << (lww - logwidth))) << logwidth; + caret[index] |= value << pos; + } + } + + void Merge(int index1, int index2, int lev, bool fCompl) { + MergeCare(index1, index2, lev); + vvMergedIndices[lev].push_back(std::make_pair((index1 << 1) ^ (int)fCompl, index2)); + } + + int BDDBuildOne(int index, int lev) { + int r = BDDFind(index, lev); + if(r >= -2) { + if(r >= 0) { + Merge(vvIndices[lev][r >> 1], index, lev, r & 1); + } + return r; + } + vvIndices[lev].push_back(index); + return (vvIndices[lev].size() - 1) << 1; + } + + void CompleteMerge() { + for(int i = nInputs - 1; i >= 0; i--) { + for(std::vector >::reverse_iterator it = vvMergedIndices[i].rbegin(); it != vvMergedIndices[i].rend(); it++) { + CopyFunc((*it).second, (*it).first >> 1, i, (*it).first & 1); + } + } + } + + void BDDBuildStartup() { + RestoreCare(); + vvIndices.clear(); + vvIndices.resize(nInputs); + vvRedundantIndices.clear(); + vvRedundantIndices.resize(nInputs); + vvMergedIndices.clear(); + vvMergedIndices.resize(nInputs); + for(int i = 0; i < nOutputs; i++) { + if(!IsDC(i, 0)) { + BDDBuildOne(i, 0); + } + } + } + + virtual void BDDRebuildByMerge(int lev) { + for(unsigned i = 0; i < vvMergedIndices[lev].size(); i++) { + std::pair &p = vvMergedIndices[lev][i]; + MergeCare(p.first >> 1, p.second, lev); + } + } + + int BDDRebuild(int lev) { + RestoreCare(); + int i; + for(i = lev; i < nInputs; i++) { + vvIndices[i].clear(); + vvMergedIndices[i].clear(); + if(i) { + vvRedundantIndices[i-1].clear(); + } + } + for(i = 0; i < lev; i++) { + BDDRebuildByMerge(i); + } + for(i = lev; i < nInputs; i++) { + if(!i) { + for(int j = 0; j < nOutputs; j++) { + if(!IsDC(j, 0)) { + BDDBuildOne(j, 0); + } + } + } else { + BDDBuildLevel(i); + } + } + return BDDNodeCount(); + } + + int BDDSwap(int lev) { + Swap(lev); + return BDDRebuild(lev); + } + + void OptimizationStartup() { + originalt = t; + RestoreCare(); + vvIndices.clear(); + vvIndices.resize(nInputs); + vvMergedIndices.clear(); + vvMergedIndices.resize(nInputs); + for(int i = 0; i < nOutputs; i++) { + if(!IsDC(i, 0)) { + BDDBuildOne(i, 0); + } else { + ShiftToMajority(i, 0); + } + } + } + + virtual void Optimize() { + OptimizationStartup(); + for(int i = 1; i < nInputs; i++) { + for(unsigned j = 0; j < vvIndices[i-1].size(); j++) { + int index = vvIndices[i-1][j]; + BDDBuildOne(index << 1, i); + BDDBuildOne((index << 1) ^ 1, i); + } + } + CompleteMerge(); + } +}; + +class TruthTableLevelTSM : public TruthTableCare { +public: + TruthTableLevelTSM(int nInputs, int nOutputs): TruthTableCare(nInputs, nOutputs) {} + + int BDDFindTSM(int index, int lev) { + int logwidth = nInputs - lev; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + bool fZero = true; + bool fOne = true; + for(int i = 0; i < nScopeSize && (fZero || fOne); i++) { + word value = t[nScopeSize * index + i]; + word cvalue = caret[nScopeSize * index + i]; + fZero &= !(value & cvalue); + fOne &= !(~value & cvalue); + } + if(fZero || fOne) { + return -2 ^ (int)fOne; + } + for(unsigned j = 0; j < vvIndices[lev].size(); j++) { + int index2 = vvIndices[lev][j]; + bool fEq = true; + bool fCompl = true; + for(int i = 0; i < nScopeSize && (fEq || fCompl); i++) { + word value = t[nScopeSize * index + i] ^ t[nScopeSize * index2 + i]; + word cvalue = caret[nScopeSize * index + i] & caret[nScopeSize * index2 + i]; + fEq &= !(value & cvalue); + fCompl &= !(~value & cvalue); + } + if(fEq || fCompl) { + return (index2 << 1) ^ (int)!fEq; + } + } + } else { + word one = ones[logwidth]; + word value = GetValue(index, lev); + word cvalue = GetCare(index, lev); + if(!(value & cvalue)) { + return -2; + } + if(!((value ^ one) & cvalue)) { + return -1; + } + for(unsigned j = 0; j < vvIndices[lev].size(); j++) { + int index2 = vvIndices[lev][j]; + word value2 = value ^ GetValue(index2, lev); + word cvalue2 = cvalue & GetCare(index2, lev); + if(!(value2 & cvalue2)) { + return index2 << 1; + } + if(!((value2 ^ one) & cvalue2)) { + return (index2 << 1) ^ 1; + } + } + } + return -3; + } + + int BDDBuildOne(int index, int lev) { + int r = BDDFindTSM(index, lev); + if(r >= -2) { + if(r >= 0) { + CopyFuncMasked(r >> 1, index, lev, r & 1); + Merge(r >> 1, index, lev, r & 1); + } else { + vvMergedIndices[lev].push_back(std::make_pair(r, index)); + } + return r; + } + vvIndices[lev].push_back(index); + return index << 1; + } + + int BDDBuild() { + TruthTable::Save(3); + int r = TruthTable::BDDBuild(); + TruthTable::Load(3); + return r; + } + + void BDDRebuildByMerge(int lev) { + for(unsigned i = 0; i < vvMergedIndices[lev].size(); i++) { + std::pair &p = vvMergedIndices[lev][i]; + if(p.first >= 0) { + CopyFuncMasked(p.first >> 1, p.second, lev, p.first & 1); + MergeCare(p.first >> 1, p.second, lev); + } + } + } + + int BDDRebuild(int lev) { + TruthTable::Save(3); + int r = TruthTableCare::BDDRebuild(lev); + TruthTable::Load(3); + return r; + } +}; + +} + +Gia_Man_t * Gia_ManTtopt( Gia_Man_t * p, int nIns, int nOuts, int nRounds ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vSupp; + word v; + word * pTruth; + int i, g, k, nInputs; + Gia_ManLevelNum( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManForEachCi( p, pObj, k ) + Gia_ManAppendCi( pNew ); + Gia_ObjComputeTruthTableStart( p, nIns ); + Gia_ManHashStart( pNew ); + for ( g = 0; g < Gia_ManCoNum(p); g += nOuts ) + { + vSupp = Gia_ManCollectSuppNew( p, g, nOuts ); + nInputs = Vec_IntSize( vSupp ); + Ttopt::TruthTableReo tt( nInputs, nOuts ); + for ( k = 0; k < nOuts; k++ ) + { + pObj = Gia_ManCo( p, g+k ); + pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); + if ( nInputs >= 6 ) + for ( i = 0; i < tt.nSize; i++ ) + tt.t[i + tt.nSize * k] = Gia_ObjFaninC0(pObj)? ~pTruth[i]: pTruth[i]; + else + { + i = k * (1 << nInputs); + v = (Gia_ObjFaninC0(pObj)? ~pTruth[0]: pTruth[0]) & tt.ones[nInputs]; + tt.t[i / tt.ww] |= v << (i % tt.ww); + } + } + tt.RandomSiftReo( nRounds ); + Ttopt::TruthTable tt2( nInputs, nOuts ); + tt2.t = tt.t; + tt2.Reo( tt.vLevels ); + tt2.BDDGenerateAig( pNew, vSupp ); + Vec_IntFree( vSupp ); + } + Gia_ObjComputeTruthTableStop( p ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +Gia_Man_t * Gia_ManTtoptCare( Gia_Man_t * p, int nIns, int nOuts, int nRounds, char * pFileName, int nRarity ) +{ + int fVerbose = 0; + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vSupp; + word v; + word * pTruth, * pCare; + int i, g, k, nInputs; + Vec_Wrd_t * vSimI = Vec_WrdReadBin( pFileName, fVerbose ); + Gia_ManLevelNum( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManForEachCi( p, pObj, k ) + Gia_ManAppendCi( pNew ); + Gia_ObjComputeTruthTableStart( p, nIns ); + Gia_ManHashStart( pNew ); + for ( g = 0; g < Gia_ManCoNum(p); g += nOuts ) + { + vSupp = Gia_ManCollectSuppNew( p, g, nOuts ); + nInputs = Vec_IntSize( vSupp ); + Ttopt::TruthTableLevelTSM tt( nInputs, nOuts ); + for ( k = 0; k < nOuts; k++ ) + { + pObj = Gia_ManCo( p, g+k ); + pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); + if ( nInputs >= 6 ) + for ( i = 0; i < tt.nSize; i++ ) + tt.t[i + tt.nSize * k] = Gia_ObjFaninC0(pObj)? ~pTruth[i]: pTruth[i]; + else + { + i = k * (1 << nInputs); + v = (Gia_ObjFaninC0(pObj)? ~pTruth[0]: pTruth[0]) & tt.ones[nInputs]; + tt.t[i / tt.ww] |= v << (i % tt.ww); + } + } + i = 1 << Vec_IntSize( vSupp ); + pCare = Gia_ManCountFraction( p, vSimI, vSupp, nRarity, fVerbose, &i ); + tt.care[0] = pCare[0]; + for ( i = 1; i < tt.nSize; i++ ) + tt.care[i] = pCare[i]; + ABC_FREE( pCare ); + tt.RandomSiftReo( nRounds ); + tt.Optimize(); + tt.BDDGenerateAig( pNew, vSupp ); + Vec_IntFree( vSupp ); + } + Gia_ObjComputeTruthTableStop( p ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Vec_WrdFreeP( &vSimI ); + return pNew; +} + +ABC_NAMESPACE_IMPL_END + diff --git a/abc/src/aig/gia/giaUnate.c b/abc/src/aig/gia/giaUnate.c index b627641ed8b..cf8d9104dfa 100644 --- a/abc/src/aig/gia/giaUnate.c +++ b/abc/src/aig/gia/giaUnate.c @@ -178,7 +178,7 @@ void Gia_ManCheckUnateVecTest( Gia_Man_t * p, int fVerbose ) for ( o = 0; o < Gia_ManCoNum(p); o++ ) { Vec_Int_t * vUnate = Vec_WecEntry( vUnates, o ); - memset( pBuffer, ' ', nVars ); + memset( pBuffer, ' ', (size_t)nVars ); Vec_IntForEachEntry( vUnate, Var, i ) if ( i+1 < Vec_IntSize(vUnate) && Abc_Lit2Var(Var) == Abc_Lit2Var(Vec_IntEntry(vUnate, i+1)) ) // both lits are present pBuffer[Abc_Lit2Var(Var)] = '.', i++, nNonUnate++; // does not depend on this var diff --git a/abc/src/aig/gia/giaUtil.c b/abc/src/aig/gia/giaUtil.c index 204d303340f..dfddc693180 100644 --- a/abc/src/aig/gia/giaUtil.c +++ b/abc/src/aig/gia/giaUtil.c @@ -522,6 +522,28 @@ int Gia_ManLevelNum( Gia_Man_t * p ) } return p->nLevels; } +int Gia_ManLevelRNum( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); + p->nLevels = 0; + Gia_ManForEachObjReverse( p, pObj, i ) + { + if ( !p->fGiaSimple && Gia_ObjIsBuf(pObj) ) + Gia_ObjUpdateLevelId( p, Gia_ObjFaninId0(pObj, i), Gia_ObjLevel(p, pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjUpdateLevelId( p, Gia_ObjFaninId0(pObj, i), 1+Gia_ObjLevel(p, pObj) ); + Gia_ObjUpdateLevelId( p, Gia_ObjFaninId1(pObj, i), 1+Gia_ObjLevel(p, pObj) ); + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ObjUpdateLevelId( p, Gia_ObjFaninId0(pObj, i), 1 ); + else + p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) ); + } + return p->nLevels; +} float Gia_ManLevelAve( Gia_Man_t * p ) { Gia_Obj_t * pObj; @@ -694,7 +716,8 @@ void Gia_ManCreateValueRefs( Gia_Man_t * p ) if ( Gia_ObjIsAnd(pObj) ) { Gia_ObjFanin0(pObj)->Value++; - Gia_ObjFanin1(pObj)->Value++; + if ( !Gia_ObjIsBuf(pObj) ) + Gia_ObjFanin1(pObj)->Value++; } else if ( Gia_ObjIsCo(pObj) ) Gia_ObjFanin0(pObj)->Value++; @@ -723,7 +746,8 @@ void Gia_ManCreateRefs( Gia_Man_t * p ) if ( Gia_ObjIsAnd(pObj) ) { Gia_ObjRefFanin0Inc( p, pObj ); - Gia_ObjRefFanin1Inc( p, pObj ); + if ( !Gia_ObjIsBuf(pObj) ) + Gia_ObjRefFanin1Inc( p, pObj ); if ( Gia_ObjIsMuxId(p, i) ) Gia_ObjRefFanin2Inc( p, pObj ); } @@ -771,6 +795,20 @@ int * Gia_ManCreateMuxRefs( Gia_Man_t * p ) SeeAlso [] ***********************************************************************/ +Vec_Int_t * Gia_ManBfsForCrossCut( Gia_Man_t * p ) +{ + Vec_Int_t * vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_Vec_t * vLevels = Gia_ManLevelize( p ); + Vec_Ptr_t * vObjs; + Gia_Obj_t * pObj; + int i, k; + Vec_VecForEachLevel( vLevels, vObjs, i ) + Vec_PtrForEachEntry( Gia_Obj_t *, vObjs, pObj, k ) + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + Vec_VecFree( vLevels ); + return vNodes; +} + void Gia_ManDfsForCrossCut_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) @@ -823,6 +861,7 @@ int Gia_ManCrossCut( Gia_Man_t * p, int fReverse ) Gia_Obj_t * pObj; int i, nCutCur = 0, nCutMax = 0; vNodes = Gia_ManDfsForCrossCut( p, fReverse ); + //vNodes = Gia_ManBfsForCrossCut( p ); Gia_ManForEachObjVec( vNodes, p, pObj, i ) { if ( pObj->Value ) @@ -1084,19 +1123,20 @@ int Gia_NodeDeref_rec( Gia_Man_t * p, Gia_Obj_t * pNode ) SeeAlso [] ***********************************************************************/ -int Gia_NodeRef_rec( Gia_Man_t * p, Gia_Obj_t * pNode ) +int Gia_NodeRef_rec( Gia_Man_t * p, Gia_Obj_t * pNode, int fMark ) { Gia_Obj_t * pFanin; int Counter = 0; if ( Gia_ObjIsCi(pNode) ) return 0; assert( Gia_ObjIsAnd(pNode) ); + if ( fMark ) Gia_ObjSetTravIdCurrent(p, pNode); pFanin = Gia_ObjFanin0(pNode); if ( Gia_ObjRefInc(p, pFanin) == 0 ) - Counter += Gia_NodeRef_rec( p, pFanin ); + Counter += Gia_NodeRef_rec( p, pFanin, fMark ); pFanin = Gia_ObjFanin1(pNode); if ( Gia_ObjRefInc(p, pFanin) == 0 ) - Counter += Gia_NodeRef_rec( p, pFanin ); + Counter += Gia_NodeRef_rec( p, pFanin, fMark ); return Counter + 1; } @@ -1135,7 +1175,19 @@ int Gia_NodeMffcSize( Gia_Man_t * p, Gia_Obj_t * pNode ) assert( !Gia_IsComplement(pNode) ); assert( Gia_ObjIsCand(pNode) ); ConeSize1 = Gia_NodeDeref_rec( p, pNode ); - ConeSize2 = Gia_NodeRef_rec( p, pNode ); + ConeSize2 = Gia_NodeRef_rec( p, pNode, 0 ); + assert( ConeSize1 == ConeSize2 ); + assert( ConeSize1 >= 0 ); + return ConeSize1; +} +int Gia_NodeMffcSizeMark( Gia_Man_t * p, Gia_Obj_t * pNode ) +{ + int ConeSize1, ConeSize2; + assert( !Gia_IsComplement(pNode) ); + assert( Gia_ObjIsCand(pNode) ); + ConeSize1 = Gia_NodeDeref_rec( p, pNode ); + Gia_ManIncrementTravId( p ); + ConeSize2 = Gia_NodeRef_rec( p, pNode, 1 ); assert( ConeSize1 == ConeSize2 ); assert( ConeSize1 >= 0 ); return ConeSize1; @@ -1176,12 +1228,59 @@ int Gia_NodeMffcSizeSupp( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp ) ConeSize1 = Gia_NodeDeref_rec( p, pNode ); Gia_NodeCollect_rec( p, Gia_ObjFanin0(pNode), vSupp ); Gia_NodeCollect_rec( p, Gia_ObjFanin1(pNode), vSupp ); - ConeSize2 = Gia_NodeRef_rec( p, pNode ); + ConeSize2 = Gia_NodeRef_rec( p, pNode, 0 ); assert( ConeSize1 == ConeSize2 ); assert( ConeSize1 >= 0 ); return ConeSize1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_NodeMffcMapping_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vMapping, Vec_Int_t * vSupp ) +{ + Gia_Obj_t * pObj; int i, iNode, Count = 1; + if ( !iObj || Vec_IntEntry(vMapping, iObj) ) + return 0; + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return 0; + Gia_NodeMffcSizeSupp( p, pObj, vSupp ); + Vec_IntSort( vSupp, 0 ); + Vec_IntWriteEntry( vMapping, iObj, Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Vec_IntSize(vSupp) ); + Vec_IntAppend( vMapping, vSupp ); + Vec_IntPush( vMapping, iObj ); + Vec_IntForEachEntry( vSupp, iNode, i ) + Count += Gia_NodeMffcMapping_rec( p, iNode, vMapping, vSupp ); + return Count; +} +int Gia_NodeMffcMapping( Gia_Man_t * p ) +{ + int i, Id, Count = 0; + int * pRefsOld; + Vec_Int_t * vMapping, * vSupp = Vec_IntAlloc( 100 ); + vMapping = Vec_IntAlloc( 2 * Gia_ManObjNum(p) ); + Vec_IntFill( vMapping, Gia_ManObjNum(p), 0 ); + pRefsOld = p->pRefs; p->pRefs = NULL; + Gia_ManCreateRefs( p ); + Gia_ManForEachCoDriverId( p, Id, i ) + Count += Gia_NodeMffcMapping_rec( p, Id, vMapping, vSupp ); + p->pRefs = pRefsOld; + Vec_IntFree( vSupp ); + p->vMapping = vMapping; + //printf( "Mapping is %.2fx larger than AIG manager.\n", 1.0*Vec_IntSize(vMapping)/Gia_ManObjNum(p) ); + return Count; +} + /**Function************************************************************* Synopsis [Returns 1 if AIG has dangling nodes.] @@ -2010,11 +2109,13 @@ void Gia_AigerWriteLut( Gia_Man_t * p, char * pFileName ) Gia_ManForEachObj( p, pObj, i ) if ( i && Gia_ObjIsLut(p, i) ) { + word truth; pLuts[iLut].Type = 3; Gia_LutForEachFanin( p, i, iFan, k ) pLuts[iLut].pFans[k] = Gia_ManObj(p, iFan)->Value; pLuts[iLut].nFans = k; - *(word *)pLuts[iLut].pTruth = Gia_LutComputeTruth6(p, i, vTruths); + truth = Gia_LutComputeTruth6(p, i, vTruths); + memcpy( pLuts[iLut].pTruth, &truth, sizeof(word) ); pObj->Value = pLuts[iLut].Out = Abc_Var2Lit( iLut, 0 ); iLut++; } @@ -2127,6 +2228,939 @@ int Gia_ManCheckSuppOverlap( Gia_Man_t * p, int iNode1, int iNode2 ) return Result; } + +/**Function************************************************************* + + Synopsis [Count PIs with fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCountPisWithFanout( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, Count = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->fMark0 = 0; + Gia_ManForEachAnd( p, pObj, i ) + { + Gia_ObjFanin0(pObj)->fMark0 = 1; + Gia_ObjFanin1(pObj)->fMark0 = 1; + } + Gia_ManForEachCo( p, pObj, i ) + Gia_ObjFanin0(pObj)->fMark0 = 1; + Gia_ManForEachCi( p, pObj, i ) + Count += pObj->fMark0; + Gia_ManForEachObj( p, pObj, i ) + pObj->fMark0 = 0; + return Count; +} + +/**Function************************************************************* + + Synopsis [Count POs driven by non-zero driver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCountPosWithNonZeroDrivers( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, Count = 0; + Gia_ManForEachCo( p, pObj, i ) + Count += Gia_ObjFaninLit0(pObj, Gia_ObjId(p, pObj)) != 0; + return Count; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManUpdateCopy( Vec_Int_t * vCopy, Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, iLit; + Vec_IntForEachEntry( vCopy, iLit, i ) + { + if ( iLit == -1 ) + continue; + pObj = Gia_ManObj( p, Abc_Lit2Var(iLit) ); + if ( !~pObj->Value ) + Vec_IntWriteEntry( vCopy, i, -1 ); + else + Vec_IntWriteEntry( vCopy, i, Abc_LitNotCond(pObj->Value, Abc_LitIsCompl(iLit)) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupWithMuxPos( Gia_Man_t * p ) +{ + Vec_Int_t * vPoints = Vec_IntAlloc( 1000 ); + Vec_Int_t * vQuads = Vec_IntAlloc( 1000 ); + Vec_Bit_t * vHeads = Vec_BitStart( Gia_ManObjNum(p) ); + Vec_Bit_t * vDatas = Vec_BitStart( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj, * pCtrl, * pData0, * pData1; + Gia_Man_t * pNew = Gia_ManDup( p ); int i, iObj; + assert( Gia_ManRegNum(pNew) == 0 ); + Gia_ManForEachAnd( pNew, pObj, i ) + { + if ( !Gia_ObjIsMuxType(pObj) ) + continue; + pCtrl = Gia_ObjRecognizeMux( pObj, &pData1, &pData0 ); + pCtrl = Gia_Regular(pCtrl); + pData0 = Gia_Regular(pData0); + pData1 = Gia_Regular(pData1); + Vec_IntPushTwo( vQuads, Gia_ObjId(pNew, pObj), Gia_ObjId(pNew, pCtrl) ); + Vec_IntPushTwo( vQuads, Gia_ObjId(pNew, pData0), Gia_ObjId(pNew, pData1) ); + Vec_BitWriteEntry( vHeads, Gia_ObjId(pNew, pObj), 1 ); + Vec_BitWriteEntry( vDatas, Gia_ObjId(pNew, pData0), 1 ); + Vec_BitWriteEntry( vDatas, Gia_ObjId(pNew, pData1), 1 ); + } + Gia_ManForEachCo( pNew, pObj, i ) + Gia_ObjFanin0(pObj)->fMark0 = 1; + for ( i = 0; i < Vec_IntSize(vQuads)/4; i++ ) + { + int iObj = Vec_IntEntry( vQuads, 4*i+0 ); + int iCtrl = Vec_IntEntry( vQuads, 4*i+1 ); + int iData0 = Vec_IntEntry( vQuads, 4*i+2 ); + int iData1 = Vec_IntEntry( vQuads, 4*i+3 ); + if ( (Vec_BitEntry(vHeads, iObj) && Vec_BitEntry(vDatas, iObj)) || + (Vec_BitEntry(vHeads, iData0) && Vec_BitEntry(vDatas, iData0)) || + (Vec_BitEntry(vHeads, iData1) && Vec_BitEntry(vDatas, iData1)) ) + { + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + Gia_Obj_t * pCtrl = Gia_ManObj( p, iCtrl ); + Gia_Obj_t * pData0 = Gia_ManObj( p, iData0 ); + Gia_Obj_t * pData1 = Gia_ManObj( p, iData1 ); + if ( Gia_ObjIsAnd(pObj) && !pObj->fMark0 ) Vec_IntPush( vPoints, iObj ); + if ( Gia_ObjIsAnd(pCtrl) && !pCtrl->fMark0 ) Vec_IntPush( vPoints, iCtrl ); + if ( Gia_ObjIsAnd(pData0) && !pData0->fMark0 ) Vec_IntPush( vPoints, iData0 ); + if ( Gia_ObjIsAnd(pData1) && !pData1->fMark0 ) Vec_IntPush( vPoints, iData1 ); + } + } + Gia_ManCleanMark0( pNew ); + Vec_IntUniqify( vPoints ); + Vec_IntForEachEntry( vPoints, iObj, i ) + Gia_ManAppendCo( pNew, Abc_Var2Lit(iObj, 0) ); + Vec_IntFree( vPoints ); + Vec_IntFree( vQuads ); + Vec_BitFree( vHeads ); + Vec_BitFree( vDatas ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Collect distance info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManRingAdd( Gia_Man_t * p, int iObj, Vec_Int_t * vRes, Vec_Int_t * vDists, int Dist ) +{ + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + Vec_IntWriteEntry( vDists, iObj, Dist ); + Vec_IntPush( vRes, iObj ); +} +void Gia_ManCollectRing( Gia_Man_t * p, Vec_Int_t * vStart, Vec_Int_t * vRes, Vec_Int_t * vDists ) +{ + int i, k, iObj, iFan; + Vec_IntForEachEntry( vStart, iObj, i ) + { + int Weight = Vec_IntEntry( vDists, iObj ); + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + assert( Weight > 0 ); + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManRingAdd( p, Gia_ObjFaninId0(pObj, iObj), vRes, vDists, Weight + 1*!Gia_ObjIsBuf(Gia_ObjFanin0(pObj)) ); + Gia_ManRingAdd( p, Gia_ObjFaninId1(pObj, iObj), vRes, vDists, Weight + 1*!Gia_ObjIsBuf(Gia_ObjFanin1(pObj)) ); + } + Gia_ObjForEachFanoutStaticId( p, iObj, iFan, k ) + Gia_ManRingAdd( p, iFan, vRes, vDists, Weight + 1*!Gia_ObjIsBuf(Gia_ManObj(p, iFan)) ); + } +} +Vec_Int_t * Gia_ManComputeDistanceInt( Gia_Man_t * p, int iTarg, Vec_Int_t * vObjs, int fVerbose ) +{ + int i, iObj; + Vec_Int_t * vDists, * vStart, * vNexts; + vStart = Vec_IntAlloc( 100 ); + vNexts = Vec_IntAlloc( 100 ); + vDists = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManIncrementTravId( p ); + if ( vObjs ) + { + Vec_IntForEachEntry( vObjs, iObj, i ) + { + Gia_ObjSetTravIdCurrentId(p, iObj); + Vec_IntWriteEntry( vDists, iObj, 1 ); + Vec_IntPush( vStart, iObj ); + } + } + else + { + Gia_ObjSetTravIdCurrentId(p, iTarg); + Vec_IntWriteEntry( vDists, iTarg, 1 ); + Vec_IntPush( vStart, iTarg ); + } + for ( i = 0; ; i++ ) + { + if ( fVerbose ) + printf( "Ring %2d : %6d\n", i, Vec_IntSize(vDists)-Vec_IntCountZero(vDists) ); + Gia_ManCollectRing( p, vStart, vNexts, vDists ); + if ( Vec_IntSize(vNexts) == 0 ) + break; + Vec_IntClear( vStart ); + ABC_SWAP( Vec_Int_t, *vStart, *vNexts ); + } + Vec_IntFree( vStart ); + Vec_IntFree( vNexts ); + return vDists; +} +Vec_Int_t * Gia_ManComputeDistance( Gia_Man_t * p, int iObj, Vec_Int_t * vObjs, int fVerbose ) +{ + Vec_Int_t * vDists; + if ( p->vFanoutNums ) + vDists = Gia_ManComputeDistanceInt( p, iObj, vObjs, fVerbose ); + else + { + Gia_ManStaticFanoutStart( p ); + vDists = Gia_ManComputeDistanceInt( p, iObj, vObjs, fVerbose ); + Gia_ManStaticFanoutStop( p ); + } + return vDists; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ComputeTest() +{ + char * pStart, Line [1000]; float Total = 0; + char * pFileName = "data.txt"; + FILE * pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { printf( "Input file \"%s\" cannot be opened.\n", pFileName ); return; } + while ( fgets( Line, 1000, pFile ) != NULL ) + { + if ( !strstr(Line, "xxx") ) + continue; + if ( !strstr(Line, "yyy") ) + continue; + //printf( "%s", Line ); + pStart = strstr(Line, "zzz"); + if ( pStart == NULL ) + continue; + //printf( "%s", pStart + 4 ); + Total += -atof( pStart + 4 ); + } + printf( "Total = %.2f\n", Total ); + fclose( pFile ); +} + + +/**Function************************************************************* + + Synopsis [Computes sum total of support size of primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSumTotalOfSupportSizes( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + Vec_Wec_t * vSupps = Vec_WecStart( Gia_ManObjNum(p) ); + int i, nResult = 0; + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + Vec_IntPush( Vec_WecEntry(vSupps, 1+i), i ); + Gia_ManForEachAnd( p, pObj, i ) + Vec_IntTwoMerge2( Vec_WecEntry(vSupps, Gia_ObjFaninId0(pObj, i)), Vec_WecEntry(vSupps, Gia_ObjFaninId1(pObj, i)), Vec_WecEntry(vSupps, i) ); + Gia_ManForEachCo( p, pObj, i ) + nResult += Vec_IntSize( Vec_WecEntry(vSupps, Gia_ObjFaninId0p(p, pObj)) ); + Vec_WecFree( vSupps ); + return nResult; +} + +/**Function************************************************************* + + Synopsis [Computes sum total of support size of primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSumTotalOfSupportSizes2( Gia_Man_t * p ) +{ + Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(p) ); + int r, nResult = 0, nRounds = (Gia_ManCiNum(p) + 63)/64; + for ( r = 0; r < nRounds; r++ ) + { + Gia_Obj_t * pObj; + int i, Limit = r == nRounds-1 ? Gia_ManCiNum(p) % 64 : 64; + for ( i = 0; i < Limit; i++ ) + Vec_WrdWriteEntry( vSims, 1+64*r+i, (word)1 << i ); + Gia_ManForEachAnd( p, pObj, i ) + Vec_WrdWriteEntry( vSims, i, Vec_WrdEntry(vSims, Gia_ObjFaninId0(pObj, i)) | Vec_WrdEntry(vSims, Gia_ObjFaninId1(pObj, i)) ); + Gia_ManForEachCo( p, pObj, i ) + nResult += Abc_TtCountOnes( Vec_WrdEntry(vSims, Gia_ObjFaninId0p(p, pObj)) ); + for ( i = 0; i < Limit; i++ ) + Vec_WrdWriteEntry( vSims, 1+64*r+i, 0 ); + } + Vec_WrdFree( vSims ); + return nResult; +} + +/**Function************************************************************* + + Synopsis [Compute dependency.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManComputeCofs( Gia_Man_t * p, int nVars ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; int i, m; + Gia_Obj_t * pSink = Gia_ManCo(p, 0); + Vec_Int_t * vRoots = Vec_IntAlloc( 1 ); + Vec_Int_t * vNodes = Vec_IntAlloc( 1000 ); + Vec_IntPush( vRoots, Gia_ObjFaninId0p(p, pSink) ); + Gia_ManCollectTfi( p, vRoots, vNodes ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + for ( m = 0; m < (1 << nVars); m++ ) + { + for ( i = 0; i < nVars; i++ ) + Gia_ManCi(p, Gia_ManCiNum(p)-nVars+i)->Value = (m >> i) & 1; + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pSink) ); + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vRoots ); + Vec_IntFree( vNodes ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Compute dependency.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManComputeCofs2( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pSink; int i, o, m; + Vec_Int_t * vSupp = Vec_IntAlloc( 1000 ); + Vec_Int_t * vAnds = Vec_IntAlloc( 1000 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManForEachCi( p, pObj, i ) + { + pObj->Value = Gia_ManAppendCi(pNew); + assert( (int)pObj->Value == Abc_Var2Lit( 1 + Gia_ObjCioId(pObj), 0 ) ); + } + Gia_ManHashAlloc( pNew ); + Gia_ManForEachRi( p, pSink, o ) + { + int Fanin = Gia_ObjFaninId0p( p, pSink ); + Vec_Int_t * vNodes = Gia_ManCollectNodesCis( p, &Fanin, 1 ); + Vec_IntClear( vSupp ); + Vec_IntClear( vAnds ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + Vec_IntPush( Gia_ObjIsAnd(pObj) ? vAnds : vSupp, Gia_ObjId(p, pObj) ); + Vec_IntFree( vNodes ); + Vec_IntSort( vSupp, 0 ); + for ( m = 0; m < 5; m++ ) + { + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + if ( i >= Vec_IntSize(vSupp)-5 ) + pObj->Value = (i == Vec_IntSize(vSupp)-5+m) ? 1 : 0; + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + //if ( m == 4 ) + // Gia_ManAppendCo( pNew, 0 ); + //else + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pSink) ); + Gia_ManAppendCo( pNew, Abc_Var2Lit( Vec_IntEntry(vSupp, Vec_IntSize(vSupp)-5+m), 0 ) ); + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + if ( i >= Vec_IntSize(vSupp)-5 ) + pObj->Value = Abc_Var2Lit( 1 + Gia_ObjCioId(pObj), 0 ); + } + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vSupp ); + Vec_IntFree( vAnds ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Compute dependency.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManComputeDepAig( Gia_Man_t * p, int iIn, int iOut ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; int i, n, iLits[2]; + Gia_Obj_t * pPivot = Gia_ManCi(p, iIn); + Gia_Obj_t * pSink = Gia_ManCo(p, iOut); + Vec_Int_t * vRoots = Vec_IntAlloc( 1 ); + Vec_Int_t * vNodes = Vec_IntAlloc( 1000 ); + Vec_IntPush( vRoots, Gia_ObjFaninId0p(p, pSink) ); + Gia_ManCollectTfi( p, vRoots, vNodes ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + for ( n = 0; n < 2; n++ ) + { + pPivot->Value = n; + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + iLits[n] = Gia_ObjFanin0Copy(pSink); + } + Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, iLits[1], Abc_LitNot(iLits[0])) ); + Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, iLits[0], Abc_LitNot(iLits[1])) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vRoots ); + Vec_IntFree( vNodes ); + return pNew; +} +int Gia_ManComputeDep( Gia_Man_t * p, int iIn, int iOut ) +{ + extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pNew = Gia_ManComputeDepAig( p, iIn, iOut ); + Gia_Man_t * pSwp = Cec4_ManSimulateTest3( pNew, 100000, 0 ); + int iLit[2] = { Gia_ObjFaninId0p( pSwp, Gia_ManCo(pSwp, 0) ), Gia_ObjFaninId0p( pSwp, Gia_ManCo(pSwp, 1) ) }; + Gia_ManStop( pNew ); + Gia_ManStop( pSwp ); + if ( iLit[0] == 0 && iLit[1] == 0 ) + return 2; + if ( iLit[1] == 0 ) + return 1; + if ( iLit[0] == 0 ) + return 0; + return -1; +} +Gia_Man_t * Gia_ManComputeDepTest( Gia_Man_t * p ) +{ + abctime clk = Abc_Clock(); + int i; + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + printf( "%3d : %3d\n", i, Gia_ManComputeDep(p, i, 0) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return Gia_ManDup(p); +} + +/**Function************************************************************* + + Synopsis [Compute support diffs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManComputeSupports( Gia_Man_t * p ) +{ + Vec_Wec_t * vRes = Vec_WecStart( Gia_ManCoNum(p) ); + Vec_Wec_t * vSupps = Vec_WecStart( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; int i; + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + Vec_IntPush( Vec_WecEntry(vSupps, 1+i), i ); + Gia_ManForEachAnd( p, pObj, i ) + Vec_IntTwoMerge2( Vec_WecEntry(vSupps, Gia_ObjFaninId0(pObj, i)), Vec_WecEntry(vSupps, Gia_ObjFaninId1(pObj, i)), Vec_WecEntry(vSupps, i) ); + Gia_ManForEachCo( p, pObj, i ) + Vec_IntAppend( Vec_WecEntry(vRes, i), Vec_WecEntry(vSupps, Gia_ObjFaninId0p(p, pObj)) ); + Vec_WecFree( vSupps ); + return vRes; +} +Vec_Wec_t * Gia_ManComputeSharing( Vec_Wec_t * vSupps ) +{ + Vec_Wec_t * vDiffs = Vec_WecStart( Vec_WecSize(vSupps) ); + Vec_Int_t * vNew, * vOld; int i; + Vec_WecForEachLevelTwo( vDiffs, vSupps, vNew, vOld, i ) if ( i ) + Vec_IntTwoFindCommon( Vec_WecEntry(vSupps, i-1), vOld, vNew ); + return vDiffs; +} +Vec_Str_t * Gia_ManConvertDump( Gia_Man_t * p, Vec_Wec_t * vSupps ) +{ + int fPrintDep = 1; + int nSize = Gia_ManCoNum(p) * (Gia_ManCiNum(p) + 1) + 1; + Vec_Str_t * vRes = Vec_StrAlloc( nSize ); + Vec_Int_t * vLevel; int i, k, Obj; + assert( Gia_ManCoNum(p) == Vec_WecSize(vSupps) ); + Vec_StrFill( vRes, nSize-1, '_' ); + Vec_StrPush( vRes, '\0' ); + Vec_WecForEachLevel( vSupps, vLevel, i ) + { + Vec_IntForEachEntry( vLevel, Obj, k ) + { + if ( !fPrintDep ) + Vec_StrWriteEntry( vRes, i * (Gia_ManCiNum(p) + 1) + Obj, '*' ); + else + { + int Value = Gia_ManComputeDep( p, Obj, i ); + if ( Value == -1 ) + Vec_StrWriteEntry( vRes, i * (Gia_ManCiNum(p) + 1) + Obj, '*' ); + else + Vec_StrWriteEntry( vRes, i * (Gia_ManCiNum(p) + 1) + Obj, (char)('0'+Value) ); + } + } + Vec_StrWriteEntry( vRes, i * (Gia_ManCiNum(p) + 1) + Gia_ManCiNum(p), '\n' ); + //printf( "Output %d\n", i ); + } + return vRes; +} +void Gia_ManDumpSuppFile( Vec_Str_t * p, char * pFileName ) +{ + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + else + { + int nOuts = Vec_StrCountEntry(p, '\n'); + int nIns = Vec_StrSize(p)/Vec_StrCountEntry(p, '\n') - 1; + int nSize1 = Vec_StrSize(p) - 1; + int nSize2 = fwrite( Vec_StrArray(p), 1, nSize1, pFile ); + assert( nSize1 == nSize2 ); + printf( "Successfully dumped file \"%s\" with support data for %d outputs and %d inputs.\n", pFileName, nOuts, nIns ); + } + fclose( pFile ); +} +void Gia_ManDumpSuppFileTest3( Gia_Man_t * p, char * pFileName ) +{ + Vec_Wec_t * vSupps = Gia_ManComputeSupports( p ); + Vec_Wec_t * vDiffs = Gia_ManComputeSharing( vSupps ); + Vec_Wec_t * vDiffs2 = Gia_ManComputeSharing( vDiffs ); + Vec_Str_t * vRes = Gia_ManConvertDump( p, vDiffs2 ); + Gia_ManDumpSuppFile( vRes, pFileName ); + Vec_WecFree( vDiffs2 ); + Vec_WecFree( vDiffs ); + Vec_WecFree( vSupps ); + Vec_StrFree( vRes ); +} +void Gia_ManDumpSuppFileTest( Gia_Man_t * p, char * pFileName ) +{ + Vec_Wec_t * vSupps = Gia_ManComputeSupports( p ); + Vec_Str_t * vRes = Gia_ManConvertDump( p, vSupps ); + Gia_ManDumpSuppFile( vRes, pFileName ); + Vec_WecFree( vSupps ); + Vec_StrFree( vRes ); +} + + +/**Function************************************************************* + + Synopsis [Compute support diffs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManConvertSupp_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( !Gia_ObjIsAnd(pObj) ) + return; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + Gia_ManConvertSupp_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManConvertSupp_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManConvertSupp( Gia_Man_t * p ) +{ + int fOnly1 = 0; + int fVerbose = 1; + abctime clk = Abc_Clock(); + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObjPi, * pObjRi, * pObjRo; + Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); + Vec_Int_t * vAnds = Vec_IntAlloc( 100 ); + int i, n, iLits[2]; + assert( Gia_ManRegNum(p) && Gia_ManRegNum(p) % 8 == 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObjPi, i ) + pObjPi->Value = Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachRi( p, pObjRi, i ) + { + pObjRo = Gia_ObjRiToRo(p, pObjRi); + if ( (i - Gia_ManPoNum(p)) % 8 != 0 ) + continue; + if ( fOnly1 ) + { + assert( pObjRo->Value == ~0 ); + for ( n = 0; n < 2; n++ ) + { + pObjRo->Value = n; + Gia_ManIncrementTravId( p ); + Gia_ManConvertSupp_rec( pNew, p, Gia_ObjFanin0(pObjRi) ); + iLits[n] = Gia_ObjFanin0Copy(pObjRi); + } + pObjRo->Value = ~0; + Gia_ManAppendCo( pNew, Abc_LitNot(Gia_ManHashAnd( pNew, iLits[1], Abc_LitNot(iLits[0]) )) ); + } + else + { + int Fanin = Gia_ObjFaninId0p( p, pObjRi ); + Vec_Int_t * vNodes = Gia_ManCollectNodesCis( p, &Fanin, 1 ); + Gia_Obj_t * pObj; int i, m; + Vec_IntClear( vSupp ); + Vec_IntClear( vAnds ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + Vec_IntPush( Gia_ObjIsAnd(pObj) ? vAnds : vSupp, Gia_ObjId(p, pObj) ); + Vec_IntFree( vNodes ); + Vec_IntSort( vSupp, 0 ); + for ( m = 0; m < 4; m++ ) + { + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + if ( i >= Vec_IntSize(vSupp)-5 ) + pObj->Value = (i == Vec_IntSize(vSupp)-5+m) ? 1 : 0; + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + //if ( m == 4 ) + // Gia_ManAppendCo( pNew, 0 ); + //else + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObjRi) ); + //Gia_ManAppendCo( pNew, Abc_Var2Lit( Vec_IntEntry(vSupp, Vec_IntSize(vSupp)-5+m), 0 ) ); + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + if ( i >= Vec_IntSize(vSupp)-5 ) + pObj->Value = Abc_Var2Lit( 1 + Gia_ObjCioId(pObj), 0 ); + } + } + } + Vec_IntFree( vSupp ); + Vec_IntFree( vAnds ); + Gia_ManHashStop( pNew ); + //Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + if ( fVerbose ) + printf( "Transformed %d outputs, ", Gia_ManPoNum(pNew) ); + if ( fVerbose ) + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Transform flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManTransformCond2( Gia_Man_t * p ) +{ + int fVerbose = 1; + abctime clk = Abc_Clock(); + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObjPi, * pObjRi, * pObjRo; + int i, n, iTempLit, iLits[2]; + assert( Gia_ManRegNum(p) > 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObjPi, i ) + pObjPi->Value = Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachRi( p, pObjRi, i ) + { + //if ( (i - Gia_ManPoNum(p)) % 8 != 0 ) + // continue; + pObjRo = Gia_ObjRiToRo(p, pObjRi); + iTempLit = pObjRo->Value; + for ( n = 0; n < 2; n++ ) + { + pObjRo->Value = n; + Gia_ManIncrementTravId( p ); + Gia_ManConvertSupp_rec( pNew, p, Gia_ObjFanin0(pObjRi) ); + iLits[n] = Gia_ObjFanin0Copy(pObjRi); + } + pObjRo->Value = iTempLit; + Gia_ManAppendCo( pNew, Abc_LitNot(Gia_ManHashAnd( pNew, iLits[1], Abc_LitNot(iLits[0]) )) ); + Gia_ManAppendCo( pNew, Abc_LitNot(Gia_ManHashAnd( pNew, iLits[0], Abc_LitNot(iLits[1]) )) ); + } + Gia_ManHashStop( pNew ); + //Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + if ( fVerbose ) + printf( "Created %d outputs. ", Gia_ManPoNum(pNew) ); + if ( fVerbose ) + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Transform flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Gia_ManDetectSims( Gia_Man_t * p, int iCo, int nWords ) +{ + extern int Cec4_ManGeneratePatterns_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int Value, Vec_Int_t * vPat, Vec_Int_t * vVisit ); + Vec_Wrd_t * vSim = Vec_WrdStart( nWords * Gia_ManCiNum(p) ); + Vec_Int_t * vPat = Vec_IntAlloc( Gia_ManCiNum(p) ); + Vec_Int_t * vVis = Vec_IntAlloc( Gia_ManAndNum(p) ); + Gia_Obj_t * pObj = Gia_ManCo( p, iCo ), * pTemp; int iLit, i, k, nTries = 0; + if ( Gia_ObjFanin0(pObj) == Gia_ManConst0(p) ) + return NULL; + Gia_ManForEachObj( p, pTemp, k ) + assert( !pTemp->fMark0 && !pTemp->fMark1 ); + for ( i = 0; i < 64*nWords; ) + { + int Res = Cec4_ManGeneratePatterns_rec( p, Gia_ObjFanin0(pObj), !Gia_ObjFaninC0(pObj), vPat, vVis ); + if ( Res ) + { + Vec_IntForEachEntry( vPat, iLit, k ) + { + if ( Abc_LitIsCompl(iLit) ) + continue; + pTemp = Gia_ManObj( p, Abc_Lit2Var(iLit) ); + assert( Gia_ObjIsCi(pTemp) ); + Abc_InfoSetBit( (unsigned *)Vec_WrdEntryP(vSim, nWords*Gia_ObjCioId(pTemp)), i ); + } + i++; + } + Gia_ManForEachObjVec( vVis, p, pTemp, k ) + pTemp->fMark0 = pTemp->fMark1 = 0; + nTries++; + } + //printf( "%d ", nTries ); + Vec_IntFree( vPat ); + Vec_IntFree( vVis ); + return vSim; +} +Vec_Wrd_t * Vec_WrdInterleave( Vec_Wrd_t * p1, Vec_Wrd_t * p2, int nWords, int nIns ) +{ + Vec_Wrd_t * p = Vec_WrdAlloc( Vec_WrdSize(p1)+Vec_WrdSize(p2) ); + int i, k; + assert( Vec_WrdSize(p1) == nWords*nIns ); + assert( Vec_WrdSize(p2) == nWords*nIns ); + for ( i = 0; i < nIns; i++ ) + { + for ( k = 0; k < nWords; k++ ) + Vec_WrdPush( p, Vec_WrdEntry(p1, i*nWords+k) ); + for ( k = 0; k < nWords; k++ ) + Vec_WrdPush( p, Vec_WrdEntry(p2, i*nWords+k) ); + } + return p; +} +Gia_Man_t * Gia_ManTransformCond( Gia_Man_t * p ) +{ + extern void Gia_ManResubPair( Vec_Wrd_t * vOn, Vec_Wrd_t * vOff, int nWords, int nIns ); + abctime clk = Abc_Clock(); + Vec_Wrd_t * vSims; + Vec_Wrd_t * vSim[4]; + Vec_Wrd_t * vInt[6]; + int i; + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + { + vSims = Gia_ManDetectSims( p, i, 1 ); + if ( i >= Gia_ManCoNum(p)-4 ) + vSim[i-(Gia_ManCoNum(p)-4)] = vSims; + else + Vec_WrdFreeP( &vSims ); + //Vec_PtrPush( vAll, vSims ); + } + vInt[0] = Vec_WrdInterleave( vSim[0], vSim[1], 1, Gia_ManCiNum(p) ); + vInt[1] = Vec_WrdInterleave( vSim[0], vSim[2], 1, Gia_ManCiNum(p) ); + vInt[2] = Vec_WrdInterleave( vSim[0], vSim[3], 1, Gia_ManCiNum(p) ); + vInt[3] = Vec_WrdInterleave( vSim[1], vSim[2], 1, Gia_ManCiNum(p) ); + vInt[4] = Vec_WrdInterleave( vSim[1], vSim[3], 1, Gia_ManCiNum(p) ); + vInt[5] = Vec_WrdInterleave( vSim[2], vSim[3], 1, Gia_ManCiNum(p) ); + + Gia_ManResubPair( vInt[0], vInt[5], 2, Gia_ManCiNum(p) ); + Gia_ManResubPair( vInt[1], vInt[4], 2, Gia_ManCiNum(p) ); + Gia_ManResubPair( vInt[2], vInt[3], 2, Gia_ManCiNum(p) ); + + Gia_ManResubPair( vInt[5], vInt[0], 2, Gia_ManCiNum(p) ); + Gia_ManResubPair( vInt[4], vInt[1], 2, Gia_ManCiNum(p) ); + Gia_ManResubPair( vInt[3], vInt[2], 2, Gia_ManCiNum(p) ); + +/* + for ( i = 0; i < 4; i++ ) + for ( k = i+1; k < 4; k++ ) + Gia_ManResubPair( vSim[i], vSim[k], 1, Gia_ManCiNum(p) ); +*/ + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + return NULL; +} +void Gia_ManWriteSol( Gia_Man_t * p, char * pFileName ) +{ + char * pBasicName = Extra_FileNameGeneric( pFileName ); + char * pFileName2 = Abc_UtilStrsavTwo( pBasicName, ".sol" ); + FILE * pFile = fopen( pFileName2, "wb" ); + ABC_FREE( pBasicName ); + if ( pFile == NULL ) + printf( "Cannot open output file \"%s\".\n", pFileName2 ); + else + { + Gia_Obj_t * pObj; int i; + Gia_ManForEachAnd( p, pObj, i ) + fprintf( pFile, "%d %d ", Gia_ObjFaninLit0(pObj, i), Gia_ObjFaninLit1(pObj, i) ); + Gia_ManForEachCo( p, pObj, i ) + fprintf( pFile, "%d %d ", Gia_ObjFaninLit0p(p, pObj), Gia_ObjFaninLit0p(p, pObj) ); + fclose( pFile ); + printf( "Finished writing solution file \"%s\".\n", pFileName2 ); + } + ABC_FREE( pFileName2 ); +} +void Gia_ManWriteResub( Gia_Man_t * p, char * pFileName ) +{ + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open output file \"%s\".\n", pFileName ); + else + { + Vec_Wrd_t * vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + Vec_Wrd_t * vSimsPo = Gia_ManSimPatSimOut( p, vSimsPi, 1 ); + int i, k, nWords = Vec_WrdSize(vSimsPi) / Gia_ManCiNum(p); + word * pTemp = ABC_ALLOC( word, nWords ); + fprintf( pFile, "%d %d %d %d\n", Gia_ManCiNum(p), 0, Gia_ManCoNum(p), 1 << Gia_ManCiNum(p) ); + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + Abc_TtPrintBinary1( pFile, Vec_WrdEntryP(vSimsPi, i*nWords), Gia_ManCiNum(p) ), fprintf(pFile, "\n"); + for ( i = 0; i < (1 << Gia_ManCoNum(p)); i++ ) + { + Abc_TtFill( pTemp, nWords ); + for ( k = 0; k < Gia_ManCoNum(p); k++ ) + Abc_TtAndCompl( pTemp, pTemp, 0, Vec_WrdEntryP(vSimsPo, k*nWords), !((i>>k)&1), nWords ); + Abc_TtPrintBinary1( pFile, pTemp, Gia_ManCiNum(p) ), fprintf(pFile, "\n"); + } + ABC_FREE( pTemp ); + fclose( pFile ); + Vec_WrdFree( vSimsPi ); + Vec_WrdFree( vSimsPo ); + printf( "Finished writing resub file \"%s\".\n", pFileName ); + Gia_ManWriteSol( p, pFileName ); + } +} + + +/**Function************************************************************* + + Synopsis [Transform flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintArray( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int i, nSize = Gia_ManObjNum(p); + printf( "static int s_ArraySize = %d;\n", nSize ); + printf( "static int s_ArrayData[%d] = {\n", 2*nSize ); + printf( " 0, 0," ); + printf( "\n " ); + Gia_ManForEachCi( p, pObj, i ) + printf( "0, 0, " ); + printf( "\n " ); + Gia_ManForEachAnd( p, pObj, i ) + printf( "%d, %d, ", Gia_ObjFaninLit0p(p, pObj), Gia_ObjFaninLit1p(p, pObj) ); + printf( "\n " ); + Gia_ManForEachCo( p, pObj, i ) + printf( "%d, %d, ", Gia_ObjFaninLit0p(p, pObj), Gia_ObjFaninLit0p(p, pObj) ); + printf( "\n" ); + printf( "};\n" ); + +} //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/abc/src/aig/gia/module.make b/abc/src/aig/gia/module.make index 3fc411083d0..236d43b3261 100644 --- a/abc/src/aig/gia/module.make +++ b/abc/src/aig/gia/module.make @@ -14,8 +14,12 @@ SRC += src/aig/gia/giaAig.c \ src/aig/gia/giaCSatOld.c \ src/aig/gia/giaCSat.c \ src/aig/gia/giaCSat2.c \ + src/aig/gia/giaCSat3.c \ + src/aig/gia/giaCSatP.c \ src/aig/gia/giaCTas.c \ src/aig/gia/giaCut.c \ + src/aig/gia/giaDecs.c \ + src/aig/gia/giaDeep.c \ src/aig/gia/giaDfs.c \ src/aig/gia/giaDup.c \ src/aig/gia/giaEdge.c \ @@ -32,6 +36,7 @@ SRC += src/aig/gia/giaAig.c \ src/aig/gia/giaFrames.c \ src/aig/gia/giaFront.c \ src/aig/gia/giaFx.c \ + src/aig/gia/giaGen.c \ src/aig/gia/giaGig.c \ src/aig/gia/giaGlitch.c \ src/aig/gia/giaHash.c \ @@ -49,14 +54,22 @@ SRC += src/aig/gia/giaAig.c \ src/aig/gia/giaMem.c \ src/aig/gia/giaMfs.c \ src/aig/gia/giaMini.c \ + src/aig/gia/giaMinLut.c \ + src/aig/gia/giaMinLut2.c \ src/aig/gia/giaMuxes.c \ src/aig/gia/giaNf.c \ src/aig/gia/giaOf.c \ src/aig/gia/giaPack.c \ src/aig/gia/giaPat.c \ + src/aig/gia/giaPat2.c \ src/aig/gia/giaPf.c \ src/aig/gia/giaQbf.c \ + src/aig/gia/giaReshape1.c \ + src/aig/gia/giaReshape2.c \ src/aig/gia/giaResub.c \ + src/aig/gia/giaResub2.c \ + src/aig/gia/giaResub3.c \ + src/aig/gia/giaResub6.c \ src/aig/gia/giaRetime.c \ src/aig/gia/giaRex.c \ src/aig/gia/giaSatEdge.c \ @@ -64,6 +77,7 @@ SRC += src/aig/gia/giaAig.c \ src/aig/gia/giaSatLut.c \ src/aig/gia/giaSatMap.c \ src/aig/gia/giaSatoko.c \ + src/aig/gia/giaSatSyn.c \ src/aig/gia/giaSat3.c \ src/aig/gia/giaScl.c \ src/aig/gia/giaScript.c \ @@ -71,21 +85,28 @@ SRC += src/aig/gia/giaAig.c \ src/aig/gia/giaShrink.c \ src/aig/gia/giaShrink6.c \ src/aig/gia/giaShrink7.c \ + src/aig/gia/giaSif.c \ src/aig/gia/giaSim.c \ src/aig/gia/giaSim2.c \ + src/aig/gia/giaSimBase.c \ src/aig/gia/giaSort.c \ src/aig/gia/giaSpeedup.c \ src/aig/gia/giaSplit.c \ src/aig/gia/giaStg.c \ + src/aig/gia/giaStoch.c \ src/aig/gia/giaStr.c \ src/aig/gia/giaSupMin.c \ src/aig/gia/giaSupp.c \ + src/aig/gia/giaSupps.c \ src/aig/gia/giaSweep.c \ src/aig/gia/giaSweeper.c \ src/aig/gia/giaSwitch.c \ src/aig/gia/giaTim.c \ src/aig/gia/giaTis.c \ + src/aig/gia/giaTransduction.cpp \ + src/aig/gia/giaTranStoch.c \ src/aig/gia/giaTruth.c \ src/aig/gia/giaTsim.c \ + src/aig/gia/giaTtopt.cpp \ src/aig/gia/giaUnate.c \ src/aig/gia/giaUtil.c diff --git a/abc/src/aig/hop/hopBalance.c b/abc/src/aig/hop/hopBalance.c index e9aa4d4d5b6..a3ce1c868c4 100644 --- a/abc/src/aig/hop/hopBalance.c +++ b/abc/src/aig/hop/hopBalance.c @@ -246,7 +246,7 @@ Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Ty int LeftBound; assert( vSuper->nSize > 1 ); // sort the new nodes by level in the decreasing order - Vec_PtrSort( vSuper, (int (*)(void))Hop_NodeCompareLevelsDecrease ); + Vec_PtrSort( vSuper, (int (*)(const void *, const void *))Hop_NodeCompareLevelsDecrease ); // balance the nodes while ( vSuper->nSize > 1 ) { diff --git a/abc/src/aig/ioa/ioaReadAig.c b/abc/src/aig/ioa/ioaReadAig.c index 1d1dcbe2a59..c1eceef01bc 100644 --- a/abc/src/aig/ioa/ioaReadAig.c +++ b/abc/src/aig/ioa/ioaReadAig.c @@ -438,7 +438,7 @@ Aig_Man_t * Ioa_ReadAiger( char * pFileName, int fCheck ) // read the file into the buffer nFileSize = Ioa_FileSize( pFileName ); pFile = fopen( pFileName, "rb" ); - pContents = ABC_ALLOC( char, nFileSize ); + pContents = ABC_CALLOC( char, nFileSize+1 ); RetValue = fread( pContents, nFileSize, 1, pFile ); fclose( pFile ); diff --git a/abc/src/aig/ivy/ivyBalance.c b/abc/src/aig/ivy/ivyBalance.c index 6eba318c112..2bcc69eed27 100644 --- a/abc/src/aig/ivy/ivyBalance.c +++ b/abc/src/aig/ivy/ivyBalance.c @@ -178,7 +178,7 @@ Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Ty int LeftBound; assert( vSuper->nSize > 1 ); // sort the new nodes by level in the decreasing order - Vec_PtrSort( vSuper, (int (*)(void))Ivy_NodeCompareLevelsDecrease ); + Vec_PtrSort( vSuper, (int (*)(const void *, const void *))Ivy_NodeCompareLevelsDecrease ); // balance the nodes while ( vSuper->nSize > 1 ) { diff --git a/abc/src/aig/ivy/ivyCheck.c b/abc/src/aig/ivy/ivyCheck.c index c924e2d0cd6..d8ebb198fef 100644 --- a/abc/src/aig/ivy/ivyCheck.c +++ b/abc/src/aig/ivy/ivyCheck.c @@ -97,7 +97,7 @@ int Ivy_ManCheck( Ivy_Man_t * p ) pObj2 = Ivy_TableLookup( p, pObj ); if ( pObj2 != pObj ) printf( "Ivy_ManCheck: Latch with ID \"%d\" is not in the structural hashing table.\n", pObj->Id ); - continue; + continue; } // consider the AND node if ( !Ivy_ObjFanin0(pObj) || !Ivy_ObjFanin1(pObj) ) diff --git a/abc/src/aig/ivy/ivyCutTrav.c b/abc/src/aig/ivy/ivyCutTrav.c index 75acd260544..b1cdb4566b3 100644 --- a/abc/src/aig/ivy/ivyCutTrav.c +++ b/abc/src/aig/ivy/ivyCutTrav.c @@ -142,7 +142,7 @@ unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ) { unsigned * pBitCut; pBitCut = Vec_IntFetch( vStore, nWords ); - memset( pBitCut, 0, 4 * nWords ); + memset( pBitCut, 0, (size_t)(4 * nWords) ); Extra_TruthSetBit( pBitCut, NodeId ); return pBitCut; } @@ -329,7 +329,7 @@ void Ivy_NodeComputeVolume2( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNode } while ( Vec_PtrSize(vNodes) < nNodeLimit ); // sort nodes by level - Vec_PtrSort( vNodes, (int (*)(void))Ivy_CompareNodesByLevel ); + Vec_PtrSort( vNodes, (int (*)(const void *, const void *))Ivy_CompareNodesByLevel ); // make sure the nodes are ordered in the increasing number of levels pFanin = (Ivy_Obj_t *)Vec_PtrEntry( vNodes, 0 ); pPivot = (Ivy_Obj_t *)Vec_PtrEntryLast( vNodes ); diff --git a/abc/src/aig/ivy/ivyFraig.c b/abc/src/aig/ivy/ivyFraig.c index d9887d74058..0bf05ee8863 100644 --- a/abc/src/aig/ivy/ivyFraig.c +++ b/abc/src/aig/ivy/ivyFraig.c @@ -572,7 +572,7 @@ Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParam // p->pSimWords = ABC_ALLOC( unsigned, Ivy_ManObjNum(pManAig) * p->nSimWords ); EntrySize = sizeof(Ivy_FraigSim_t) + sizeof(unsigned) * p->nSimWords; p->pSimWords = (char *)ABC_ALLOC( char, Ivy_ManObjNum(pManAig) * EntrySize ); - memset( p->pSimWords, 0, EntrySize ); + memset( p->pSimWords, 0, (size_t)EntrySize ); k = 0; Ivy_ManForEachObj( pManAig, pObj, i ) { @@ -1354,7 +1354,7 @@ int Ivy_FraigCheckOutputSims( Ivy_FraigMan_t * p ) // pObj = Ivy_ManPo( p->pManAig, 0 ); Ivy_ManForEachPo( p->pManAig, pObj, i ) { - assert( Ivy_ObjFanin0(pObj)->fPhase == (unsigned)Ivy_ObjFaninC0(pObj) ); // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) == 0 + //assert( Ivy_ObjFanin0(pObj)->fPhase == (unsigned)Ivy_ObjFaninC0(pObj) ); // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) == 0 // complement simulation info // if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) ) // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) // Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) ); diff --git a/abc/src/aig/ivy/ivyRwrAlg.c b/abc/src/aig/ivy/ivyRwrAlg.c index ce60500307f..53fe58177d2 100644 --- a/abc/src/aig/ivy/ivyRwrAlg.c +++ b/abc/src/aig/ivy/ivyRwrAlg.c @@ -371,7 +371,7 @@ int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeave if ( Vec_PtrSize(vFront) <= 2 ) return 1; // sort the entries in increasing order - Vec_PtrSort( vFront, (int (*)(void))Ivy_ManFindAlgCutCompare ); + Vec_PtrSort( vFront, (int (*)(const void *, const void *))Ivy_ManFindAlgCutCompare ); // remove duplicates from vFront and save the nodes in vLeaves pPrev = Vec_PtrEntry(vFront, 0); Vec_PtrPush( vLeaves, pPrev ); diff --git a/abc/src/aig/ivy/ivyShow.c b/abc/src/aig/ivy/ivyShow.c index 3aa1e041ab6..3b8c7cc0a74 100644 --- a/abc/src/aig/ivy/ivyShow.c +++ b/abc/src/aig/ivy/ivyShow.c @@ -46,7 +46,7 @@ static void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_ ***********************************************************************/ void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) { - extern void Abc_ShowFile( char * FileNameDot ); + extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); static int Counter = 0; char FileNameDot[200]; FILE * pFile; @@ -63,7 +63,7 @@ void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) // generate the file Ivy_WriteDotAig( pMan, FileNameDot, fHaig, vBold ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); } /**Function************************************************************* diff --git a/abc/src/aig/miniaig/abcOper.h b/abc/src/aig/miniaig/abcOper.h index 51b9d3822c0..cbe2a0f3a72 100644 --- a/abc/src/aig/miniaig/abcOper.h +++ b/abc/src/aig/miniaig/abcOper.h @@ -29,7 +29,9 @@ /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// +#ifndef _YOSYS_ ABC_NAMESPACE_HEADER_START +#endif //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// @@ -60,7 +62,7 @@ typedef enum { ABC_OPER_BIT_NXOR, // 18 ABC_OPER_BIT_SHARP, // 19 ABC_OPER_BIT_SHARPL, // 20 - ABC_OPER_BIT_MUX, // 21 + ABC_OPER_BIT_MUX, // 21 fanins are: {Ctrl, Data1, Data0} ABC_OPER_BIT_MAJ, // 22 ABC_OPER_ABC, // 23 @@ -86,7 +88,7 @@ typedef enum { ABC_OPER_LOGIC_XOR, // 41 ABC_OPER_LOGIC_XNOR, // 42 - ABC_OPER_SEL_NMUX, // 43 + ABC_OPER_SEL_NMUX, // 43 fanins are: {Ctrl, Data0, Data1, Data2, ...} ABC_OPER_SEL_SEL, // 44 ABC_OPER_SEL_PSEL, // 45 ABC_OPER_SEL_ENC, // 46 @@ -138,8 +140,8 @@ typedef enum { ABC_OPER_LATCH, // 86 ABC_OPER_LATCHRS, // 87 ABC_OPER_DFF, // 88 - ABC_OPER_DFFCPL, // 89 - ABC_OPER_DFFRS, // 90 + ABC_OPER_DFFRSE, // 89 + ABC_OPER_DFFLAST, // 90 ABC_OPER_SLICE, // 91 ABC_OPER_CONCAT, // 92 @@ -150,12 +152,14 @@ typedef enum { ABC_OPER_ARI_SQUARE, // 96 ABC_OPER_CONST, // 97 - ABC_OPER_LAST // 98 + ABC_OPER_ARI_ADDSUB, // 98 + + ABC_OPER_LAST // 99 } Acb_ObjType_t; // printing operator types -static inline char * Abc_OperName( int Type ) +static inline const char * Abc_OperName( int Type ) { if ( Type == ABC_OPER_NONE ) return NULL; if ( Type == ABC_OPER_PI ) return "pi"; @@ -192,6 +196,7 @@ static inline char * Abc_OperName( int Type ) if ( Type == ABC_OPER_ARI_ADD ) return "+"; if ( Type == ABC_OPER_ARI_SUB ) return "-"; if ( Type == ABC_OPER_ARI_MUL ) return "*"; + if ( Type == ABC_OPER_ARI_SMUL ) return "*"; if ( Type == ABC_OPER_ARI_DIV ) return "/"; if ( Type == ABC_OPER_ARI_REM ) return "%"; if ( Type == ABC_OPER_ARI_MOD ) return "mod"; @@ -214,17 +219,45 @@ static inline char * Abc_OperName( int Type ) if ( Type == ABC_OPER_SHIFT_ROTL ) return "rotL"; if ( Type == ABC_OPER_SHIFT_ROTR ) return "rotR"; + if ( Type == ABC_OPER_DFFRSE ) return "DFFRSE"; + if ( Type == ABC_OPER_SLICE ) return "[:]"; if ( Type == ABC_OPER_CONCAT ) return "{}"; if ( Type == ABC_OPER_ZEROPAD ) return "zPad"; if ( Type == ABC_OPER_SIGNEXT ) return "sExt"; + if ( Type == ABC_OPER_BIT_MUX ) return "mux"; + if ( Type == ABC_OPER_SEL_NMUX ) return "nmux"; + if ( Type == ABC_OPER_SEL_SEL ) return "pmux"; + + if ( Type == ABC_OPER_CONST ) return "const"; if ( Type == ABC_OPER_TABLE ) return "table"; + if ( Type == ABC_OPER_LUT ) return "lut"; if ( Type == ABC_OPER_LAST ) return NULL; assert( 0 ); return NULL; } +// printing operator types +static inline const char * Abc_OperNameSimple( int Type ) +{ + if ( Type == ABC_OPER_NONE ) return NULL; + if ( Type == ABC_OPER_CONST_F ) return "buf"; + if ( Type == ABC_OPER_CONST_T ) return "buf"; + if ( Type == ABC_OPER_CONST_X ) return "buf"; + if ( Type == ABC_OPER_CONST_Z ) return "buf"; + if ( Type == ABC_OPER_BIT_BUF ) return "buf"; + if ( Type == ABC_OPER_BIT_INV ) return "not"; + if ( Type == ABC_OPER_BIT_AND ) return "and"; + if ( Type == ABC_OPER_BIT_OR ) return "or"; + if ( Type == ABC_OPER_BIT_XOR ) return "xor"; + if ( Type == ABC_OPER_BIT_NAND ) return "nand"; + if ( Type == ABC_OPER_BIT_NOR ) return "nor"; + if ( Type == ABC_OPER_BIT_NXOR ) return "xnor"; + assert( 0 ); + return NULL; +} + //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -237,9 +270,9 @@ static inline char * Abc_OperName( int Type ) /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// - +#ifndef _YOSYS_ ABC_NAMESPACE_HEADER_END - +#endif #endif diff --git a/abc/src/aig/miniaig/miniaig.h b/abc/src/aig/miniaig/miniaig.h index 06769830227..c7ce14e96b2 100644 --- a/abc/src/aig/miniaig/miniaig.h +++ b/abc/src/aig/miniaig/miniaig.h @@ -30,7 +30,9 @@ #include #include +#ifndef _VERIFIC_DATABASE_H_ ABC_NAMESPACE_HEADER_START +#endif //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// @@ -92,15 +94,21 @@ static void Mini_AigPush( Mini_Aig_t * p, int Lit0, int Lit1 ) static int Mini_AigNodeFanin0( Mini_Aig_t * p, int Id ) { assert( Id >= 0 && 2*Id < p->nSize ); - assert( p->pArray[2*Id] == 0x7FFFFFFF || p->pArray[2*Id] < 2*Id ); + assert( p->pArray[2*Id] == MINI_AIG_NULL || p->pArray[2*Id] < 2*Id ); return p->pArray[2*Id]; } static int Mini_AigNodeFanin1( Mini_Aig_t * p, int Id ) { assert( Id >= 0 && 2*Id < p->nSize ); - assert( p->pArray[2*Id+1] == 0x7FFFFFFF || p->pArray[2*Id+1] < 2*Id ); + assert( p->pArray[2*Id+1] == MINI_AIG_NULL || p->pArray[2*Id+1] < 2*Id ); return p->pArray[2*Id+1]; } +static void Mini_AigFlipLastPo( Mini_Aig_t * p ) +{ + assert( p->pArray[p->nSize-1] == MINI_AIG_NULL ); + assert( p->pArray[p->nSize-2] != MINI_AIG_NULL ); + p->pArray[p->nSize-2] ^= 1; +} // working with variables and literals static int Mini_AigVar2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } @@ -142,6 +150,46 @@ static Mini_Aig_t * Mini_AigStart() Mini_AigPush( p, MINI_AIG_NULL, MINI_AIG_NULL ); return p; } +static Mini_Aig_t * Mini_AigStartSupport( int nIns, int nObjsAlloc ) +{ + Mini_Aig_t * p; int i; + assert( 1+nIns < nObjsAlloc ); + p = MINI_AIG_CALLOC( Mini_Aig_t, 1 ); + p->nCap = 2*nObjsAlloc; + p->nSize = 2*(1+nIns); + p->pArray = MINI_AIG_ALLOC( int, p->nCap ); + for ( i = 0; i < p->nSize; i++ ) + p->pArray[i] = MINI_AIG_NULL; + return p; +} +static Mini_Aig_t * Mini_AigStartArray( int nIns, int n0InAnds, int * p0InAnds, int nOuts, int * pOuts ) +{ + Mini_Aig_t * p; int i; + assert( 1+nIns <= n0InAnds ); + p = MINI_AIG_CALLOC( Mini_Aig_t, 1 ); + p->nCap = 2*(n0InAnds + nOuts); + p->nSize = 2*(n0InAnds + nOuts); + p->pArray = MINI_AIG_ALLOC( int, p->nCap ); + for ( i = 0; i < 2*(1 + nIns); i++ ) + p->pArray[i] = MINI_AIG_NULL; + memcpy( p->pArray + 2*(1 + nIns), p0InAnds + 2*(1 + nIns), 2*(n0InAnds - 1 - nIns)*sizeof(int) ); + for ( i = 0; i < nOuts; i++ ) + { + p->pArray[2*(n0InAnds + i)+0] = pOuts[i]; + p->pArray[2*(n0InAnds + i)+1] = MINI_AIG_NULL; + } + return p; +} +static Mini_Aig_t * Mini_AigDup( Mini_Aig_t * p ) +{ + Mini_Aig_t * pNew; + pNew = MINI_AIG_CALLOC( Mini_Aig_t, 1 ); + pNew->nCap = p->nCap; + pNew->nSize = p->nSize; + pNew->pArray = MINI_AIG_ALLOC( int, p->nSize ); + memcpy( pNew->pArray, p->pArray, p->nSize * sizeof(int) ); + return pNew; +} static void Mini_AigStop( Mini_Aig_t * p ) { MINI_AIG_FREE( p->pArray ); @@ -168,9 +216,34 @@ static int Mini_AigAndNum( Mini_Aig_t * p ) nNodes++; return nNodes; } +static int Mini_AigXorNum( Mini_Aig_t * p ) +{ + int i, nNodes = 0; + Mini_AigForEachAnd( p, i ) + nNodes += p->pArray[2*i] > p->pArray[2*i+1]; + return nNodes; +} +static int Mini_AigLevelNum( Mini_Aig_t * p ) +{ + int i, Level = 0; + int * pLevels = MINI_AIG_CALLOC( int, Mini_AigNodeNum(p) ); + Mini_AigForEachAnd( p, i ) + { + int Lel0 = pLevels[Mini_AigLit2Var(Mini_AigNodeFanin0(p, i))]; + int Lel1 = pLevels[Mini_AigLit2Var(Mini_AigNodeFanin1(p, i))]; + pLevels[i] = 1 + (Lel0 > Lel1 ? Lel0 : Lel1); + } + Mini_AigForEachPo( p, i ) + { + int Lel0 = pLevels[Mini_AigLit2Var(Mini_AigNodeFanin0(p, i))]; + Level = Level > Lel0 ? Level : Lel0; + } + MINI_AIG_FREE( pLevels ); + return Level; +} static void Mini_AigPrintStats( Mini_Aig_t * p ) { - printf( "PI = %d. PO = %d. Node = %d.\n", Mini_AigPiNum(p), Mini_AigPoNum(p), Mini_AigAndNum(p) ); + printf( "MiniAIG stats: PI = %d PO = %d FF = %d AND = %d\n", Mini_AigPiNum(p), Mini_AigPoNum(p), Mini_AigRegNum(p), Mini_AigAndNum(p) ); } // serialization @@ -233,7 +306,10 @@ static int Mini_AigAnd( Mini_Aig_t * p, int Lit0, int Lit1 ) int Lit = p->nSize; assert( Lit0 >= 0 && Lit0 < Lit ); assert( Lit1 >= 0 && Lit1 < Lit ); - Mini_AigPush( p, Lit0, Lit1 ); + if ( Lit0 < Lit1 ) + Mini_AigPush( p, Lit0, Lit1 ); + else + Mini_AigPush( p, Lit1, Lit0 ); return Lit; } static int Mini_AigOr( Mini_Aig_t * p, int Lit0, int Lit1 ) @@ -250,6 +326,159 @@ static int Mini_AigXor( Mini_Aig_t * p, int Lit0, int Lit1 ) { return Mini_AigMux( p, Lit0, Mini_AigLitNot(Lit1), Lit1 ); } +static int Mini_AigXorSpecial( Mini_Aig_t * p, int Lit0, int Lit1 ) +{ + int Lit = p->nSize; + assert( Lit0 >= 0 && Lit0 < Lit ); + assert( Lit1 >= 0 && Lit1 < Lit ); + if ( Lit0 > Lit1 ) + Mini_AigPush( p, Lit0, Lit1 ); + else + Mini_AigPush( p, Lit1, Lit0 ); + return Lit; +} +static int Mini_AigAndMulti( Mini_Aig_t * p, int * pLits, int nLits ) +{ + int i; + assert( nLits > 0 ); + while ( nLits > 1 ) + { + for ( i = 0; i < nLits/2; i++ ) + pLits[i] = Mini_AigAnd(p, pLits[2*i], pLits[2*i+1]); + if ( nLits & 1 ) + pLits[i++] = pLits[nLits-1]; + nLits = i; + } + return pLits[0]; +} +static int Mini_AigMuxMulti( Mini_Aig_t * p, int * pCtrl, int nCtrl, int * pData, int nData ) +{ + int i, c; + assert( nData > 0 ); + if ( nCtrl == 0 ) + return pData[0]; + assert( nData <= (1 << nCtrl) ); + for ( c = 0; c < nCtrl; c++ ) + { + for ( i = 0; i < nData/2; i++ ) + pData[i] = Mini_AigMux( p, pCtrl[c], pData[2*i+1], pData[2*i] ); + if ( nData & 1 ) + pData[i++] = Mini_AigMux( p, pCtrl[c], 0, pData[nData-1] ); + nData = i; + } + assert( nData == 1 ); + return pData[0]; +} +static int Mini_AigMuxMulti_rec( Mini_Aig_t * p, int * pCtrl, int * pData, int nData ) +{ + int Res0, Res1; + assert( nData > 0 ); + if ( nData == 1 ) + return pData[0]; + assert( nData % 2 == 0 ); + Res0 = Mini_AigMuxMulti_rec( p, pCtrl+1, pData, nData/2 ); + Res1 = Mini_AigMuxMulti_rec( p, pCtrl+1, pData+nData/2, nData/2 ); + return Mini_AigMux( p, pCtrl[0], Res1, Res0 ); +} +static Mini_Aig_t * Mini_AigTransformXor( Mini_Aig_t * p ) +{ + Mini_Aig_t * pNew = Mini_AigStart(); + int i, * pCopy = MINI_AIG_ALLOC( int, Mini_AigNodeNum(p) ); + Mini_AigForEachPi( p, i ) + pCopy[i] = Mini_AigCreatePi(pNew); + Mini_AigForEachAnd( p, i ) + { + int iLit0 = Mini_AigNodeFanin0(p, i); + int iLit1 = Mini_AigNodeFanin1(p, i); + iLit0 = Mini_AigLitNotCond( pCopy[Mini_AigLit2Var(iLit0)], Mini_AigLitIsCompl(iLit0) ); + iLit1 = Mini_AigLitNotCond( pCopy[Mini_AigLit2Var(iLit1)], Mini_AigLitIsCompl(iLit1) ); + if ( iLit0 <= iLit1 ) + pCopy[i] = Mini_AigAnd( pNew, iLit0, iLit1 ); + else + pCopy[i] = Mini_AigXor( pNew, iLit0, iLit1 ); + } + Mini_AigForEachPo( p, i ) + { + int iLit0 = Mini_AigNodeFanin0( p, i ); + iLit0 = Mini_AigLitNotCond( pCopy[Mini_AigLit2Var(iLit0)], Mini_AigLitIsCompl(iLit0) ); + pCopy[i] = Mini_AigCreatePo( pNew, iLit0 ); + } + MINI_AIG_FREE( pCopy ); + return pNew; +} + + +static unsigned s_MiniTruths5[5] = { + 0xAAAAAAAA, + 0xCCCCCCCC, + 0xF0F0F0F0, + 0xFF00FF00, + 0xFFFF0000, +}; +static inline int Mini_AigTt5HasVar( unsigned t, int iVar ) +{ + return ((t << (1<= 0 && iVar < 6 ); + return (t & ~s_MiniTruths5[iVar]) | ((t & ~s_MiniTruths5[iVar]) << (1<= 0 && iVar < 6 ); + return (t & s_MiniTruths5[iVar]) | ((t & s_MiniTruths5[iVar]) >> (1< 0 ); + // find the topmost var + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Mini_AigTt5HasVar( Truth, Var ) ) + break; + assert( Var >= 0 ); + // cofactor + Lit0 = Mini_AigTruth( p, pVarLits, Var, Mini_AigTt5Cofactor0(Truth, Var) ); + Lit1 = Mini_AigTruth( p, pVarLits, Var, Mini_AigTt5Cofactor1(Truth, Var) ); + return Mini_AigMuxProp( p, pVarLits[Var], Lit1, Lit0 ); +} +static char * Mini_AigPhase( Mini_Aig_t * p ) +{ + char * pRes = MINI_AIG_CALLOC( char, Mini_AigNodeNum(p) ); + int i; + Mini_AigForEachAnd( p, i ) + { + int iFaninLit0 = Mini_AigNodeFanin0( p, i ); + int iFaninLit1 = Mini_AigNodeFanin1( p, i ); + int Phase0 = pRes[Mini_AigLit2Var(iFaninLit0)] ^ Mini_AigLitIsCompl(iFaninLit0); + int Phase1 = pRes[Mini_AigLit2Var(iFaninLit1)] ^ Mini_AigLitIsCompl(iFaninLit1); + pRes[i] = Phase0 & Phase1; + } + return pRes; +} // procedure to check the topological order during AIG construction static int Mini_AigCheck( Mini_Aig_t * p ) @@ -282,11 +511,11 @@ static int Mini_AigCheck( Mini_Aig_t * p ) static void Mini_AigDumpVerilog( char * pFileName, char * pModuleName, Mini_Aig_t * p ) { int i, k, iFaninLit0, iFaninLit1, Length = strlen(pModuleName), nPos = Mini_AigPoNum(p); - Vec_Bit_t * vObjIsPi = Vec_BitStart( Mini_AigNodeNum(p) ); + char * pObjIsPi = MINI_AIG_CALLOC( char, Mini_AigNodeNum(p) ); FILE * pFile = fopen( pFileName, "wb" ); - if ( pFile == NULL ) { printf( "Cannot open output file %s\n", pFileName ); return; } + if ( pFile == NULL ) { printf( "Cannot open output file %s\n", pFileName ); MINI_AIG_FREE( pObjIsPi ); return; } // write interface - fprintf( pFile, "// This MiniAIG dump was produced by ABC on %s\n\n", Extra_TimeStamp() ); + //fprintf( pFile, "// This MiniAIG dump was produced by ABC on %s\n\n", Extra_TimeStamp() ); fprintf( pFile, "module %s (\n", pModuleName ); if ( Mini_AigPiNum(p) > 0 ) { @@ -296,7 +525,7 @@ static void Mini_AigDumpVerilog( char * pFileName, char * pModuleName, Mini_Aig_ { if ( k++ % 12 == 0 ) fprintf( pFile, "\n%*s", Length+10, "" ); fprintf( pFile, "i%d, ", i ); - Vec_BitWriteEntry( vObjIsPi, i, 1 ); + pObjIsPi[i] = 1; } } fprintf( pFile, "\n%*soutput wire", Length+10, "" ); @@ -313,9 +542,9 @@ static void Mini_AigDumpVerilog( char * pFileName, char * pModuleName, Mini_Aig_ iFaninLit0 = Mini_AigNodeFanin0( p, i ); iFaninLit1 = Mini_AigNodeFanin1( p, i ); fprintf( pFile, " assign n%d = ", i ); - fprintf( pFile, "%s%c%d", (iFaninLit0 & 1) ? "~":"", Vec_BitEntry(vObjIsPi, iFaninLit0 >> 1) ? 'i':'n', iFaninLit0 >> 1 ); + fprintf( pFile, "%s%c%d", (iFaninLit0 & 1) ? "~":"", pObjIsPi[iFaninLit0 >> 1] ? 'i':'n', iFaninLit0 >> 1 ); fprintf( pFile, " & " ); - fprintf( pFile, "%s%c%d", (iFaninLit1 & 1) ? "~":"", Vec_BitEntry(vObjIsPi, iFaninLit1 >> 1) ? 'i':'n', iFaninLit1 >> 1 ); + fprintf( pFile, "%s%c%d", (iFaninLit1 & 1) ? "~":"", pObjIsPi[iFaninLit1 >> 1] ? 'i':'n', iFaninLit1 >> 1 ); fprintf( pFile, ";\n" ); } // write assigns @@ -324,19 +553,294 @@ static void Mini_AigDumpVerilog( char * pFileName, char * pModuleName, Mini_Aig_ { iFaninLit0 = Mini_AigNodeFanin0( p, i ); fprintf( pFile, " assign o%d = ", i ); - fprintf( pFile, "%s%c%d", (iFaninLit0 & 1) ? "~":"", Vec_BitEntry(vObjIsPi, iFaninLit0 >> 1) ? 'i':'n', iFaninLit0 >> 1 ); + fprintf( pFile, "%s%c%d", (iFaninLit0 & 1) ? "~":"", pObjIsPi[iFaninLit0 >> 1] ? 'i':'n', iFaninLit0 >> 1 ); fprintf( pFile, ";\n" ); } fprintf( pFile, "\nendmodule // %s \n\n\n", pModuleName ); - Vec_BitFree( vObjIsPi ); + MINI_AIG_FREE( pObjIsPi ); fclose( pFile ); } +// procedure to dump MiniAIG into a BLIF file +static void Mini_AigDumpBlif( char * pFileName, char * pModuleName, Mini_Aig_t * p, int fVerbose ) +{ + int i, k, iFaninLit0, iFaninLit1; + char * pObjIsPi = MINI_AIG_FALLOC( char, Mini_AigNodeNum(p) ); + FILE * pFile = fopen( pFileName, "wb" ); + assert( Mini_AigPiNum(p) <= 26 ); + if ( pFile == NULL ) { printf( "Cannot open output file %s\n", pFileName ); MINI_AIG_FREE( pObjIsPi ); return; } + // write interface + //fprintf( pFile, "// This MiniAIG dump was produced by ABC on %s\n\n", Extra_TimeStamp() ); + fprintf( pFile, ".model %s\n", pModuleName ); + if ( Mini_AigPiNum(p) ) + { + k = 0; + fprintf( pFile, ".inputs" ); + Mini_AigForEachPi( p, i ) + { + pObjIsPi[i] = k; + fprintf( pFile, " %c", (char)('a'+k++) ); + } + } + k = 0; + fprintf( pFile, "\n.outputs" ); + Mini_AigForEachPo( p, i ) + fprintf( pFile, " o%d", k++ ); + fprintf( pFile, "\n\n" ); + // write LUTs + Mini_AigForEachAnd( p, i ) + { + iFaninLit0 = Mini_AigNodeFanin0( p, i ); + iFaninLit1 = Mini_AigNodeFanin1( p, i ); + fprintf( pFile, ".names" ); + if ( pObjIsPi[iFaninLit0 >> 1] >= 0 ) + fprintf( pFile, " %c", (char)('a'+pObjIsPi[iFaninLit0 >> 1]) ); + else + fprintf( pFile, " n%d", iFaninLit0 >> 1 ); + if ( pObjIsPi[iFaninLit1 >> 1] >= 0 ) + fprintf( pFile, " %c", (char)('a'+pObjIsPi[iFaninLit1 >> 1]) ); + else + fprintf( pFile, " n%d", iFaninLit1 >> 1 ); + fprintf( pFile, " n%d\n", i ); + if ( iFaninLit0 < iFaninLit1 ) + fprintf( pFile, "%d%d 1\n", !(iFaninLit0 & 1), !(iFaninLit1 & 1) ); + else if ( !(iFaninLit0 & 1) == !(iFaninLit1 & 1) ) + fprintf( pFile, "10 1\n01 1\n" ); + else + fprintf( pFile, "00 1\n11 1\n" ); + } + // write assigns + fprintf( pFile, "\n" ); + k = 0; + Mini_AigForEachPo( p, i ) + { + iFaninLit0 = Mini_AigNodeFanin0( p, i ); + fprintf( pFile, ".names" ); + if ( pObjIsPi[iFaninLit0 >> 1] >= 0 ) + fprintf( pFile, " %c", (char)('a'+pObjIsPi[iFaninLit0 >> 1]) ); + else + fprintf( pFile, " n%d", iFaninLit0 >> 1 ); + fprintf( pFile, " o%d\n", k++ ); + fprintf( pFile, "%d 1\n", !(iFaninLit0 & 1) ); + } + fprintf( pFile, ".end\n\n" ); + MINI_AIG_FREE( pObjIsPi ); + fclose( pFile ); + if ( fVerbose ) + printf( "Written MiniAIG into the BLIF file \"%s\".\n", pFileName ); +} + + +// checks if MiniAIG is normalized (first inputs, then internal nodes, then outputs) +static int Mini_AigIsNormalized( Mini_Aig_t * p ) +{ + int nCiNum = Mini_AigPiNum(p); + int nCoNum = Mini_AigPoNum(p); + int i, nOffset = 1; + for ( i = 0; i < nCiNum; i++ ) + if ( !Mini_AigNodeIsPi( p, nOffset+i ) ) + return 0; + nOffset = Mini_AigNodeNum(p) - nCoNum; + for ( i = 0; i < nCoNum; i++ ) + if ( !Mini_AigNodeIsPo( p, nOffset+i ) ) + return 0; + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// MiniAIG reading from / write into AIGER /// +//////////////////////////////////////////////////////////////////////// + +static unsigned Mini_AigerReadUnsigned( FILE * pFile ) +{ + unsigned x = 0, i = 0; + unsigned char ch; + while ((ch = fgetc(pFile)) & 0x80) + x |= (ch & 0x7f) << (7 * i++); + return x | (ch << (7 * i)); +} +static void Mini_AigerWriteUnsigned( FILE * pFile, unsigned x ) +{ + unsigned char ch; + while (x & ~0x7f) + { + ch = (x & 0x7f) | 0x80; + fputc( ch, pFile ); + x >>= 7; + } + ch = x; + fputc( ch, pFile ); +} +static int * Mini_AigerReadInt( char * pFileName, int * pnObjs, int * pnIns, int * pnLatches, int * pnOuts, int * pnAnds ) +{ + int i, Temp, nTotal, nObjs, nIns, nLatches, nOuts, nAnds, * pObjs; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Mini_AigerRead(): Cannot open the output file \"%s\".\n", pFileName ); + return NULL; + } + if ( fgetc(pFile) != 'a' || fgetc(pFile) != 'i' || fgetc(pFile) != 'g' ) + { + fprintf( stdout, "Mini_AigerRead(): Can only read binary AIGER.\n" ); + fclose( pFile ); + return NULL; + } + if ( fscanf(pFile, "%d %d %d %d %d", &nTotal, &nIns, &nLatches, &nOuts, &nAnds) != 5 ) + { + fprintf( stdout, "Mini_AigerRead(): Cannot read the header line.\n" ); + fclose( pFile ); + return NULL; + } + if ( nTotal != nIns + nLatches + nAnds ) + { + fprintf( stdout, "The number of objects does not match.\n" ); + fclose( pFile ); + return NULL; + } + nObjs = 1 + nIns + 2*nLatches + nOuts + nAnds; + pObjs = MINI_AIG_CALLOC( int, nObjs * 2 ); + for ( i = 0; i <= nIns + nLatches; i++ ) + pObjs[2*i] = pObjs[2*i+1] = MINI_AIG_NULL; + // read flop input literals + for ( i = 0; i < nLatches; i++ ) + { + while ( fgetc(pFile) != '\n' ); + fscanf( pFile, "%d", &Temp ); + pObjs[2*(nObjs-nLatches+i)+0] = Temp; + pObjs[2*(nObjs-nLatches+i)+1] = MINI_AIG_NULL; + } + // read output literals + for ( i = 0; i < nOuts; i++ ) + { + while ( fgetc(pFile) != '\n' ); + fscanf( pFile, "%d", &Temp ); + pObjs[2*(nObjs-nOuts-nLatches+i)+0] = Temp; + pObjs[2*(nObjs-nOuts-nLatches+i)+1] = MINI_AIG_NULL; + } + // read the binary part + while ( fgetc(pFile) != '\n' ); + for ( i = 0; i < nAnds; i++ ) + { + int uLit = 2*(1+nIns+nLatches+i); + int uLit1 = uLit - Mini_AigerReadUnsigned( pFile ); + int uLit0 = uLit1 - Mini_AigerReadUnsigned( pFile ); + pObjs[uLit+0] = uLit0; + pObjs[uLit+1] = uLit1; + } + fclose( pFile ); + if ( pnObjs ) *pnObjs = nObjs; + if ( pnIns ) *pnIns = nIns; + if ( pnLatches ) *pnLatches = nLatches; + if ( pnOuts ) *pnOuts = nOuts; + if ( pnAnds ) *pnAnds = nAnds; + return pObjs; +} +static Mini_Aig_t * Mini_AigerRead( char * pFileName, int fVerbose ) +{ + Mini_Aig_t * p; + int nObjs, nIns, nLatches, nOuts, nAnds, * pObjs = Mini_AigerReadInt( pFileName, &nObjs, &nIns, &nLatches, &nOuts, &nAnds ); + if ( pObjs == NULL ) + return NULL; + p = MINI_AIG_CALLOC( Mini_Aig_t, 1 ); + p->nCap = 2*nObjs; + p->nSize = 2*nObjs; + p->nRegs = nLatches; + p->pArray = pObjs; + if ( fVerbose ) + printf( "Loaded MiniAIG from the AIGER file \"%s\".\n", pFileName ); + return p; +} + +static void Mini_AigerWriteInt( char * pFileName, int * pObjs, int nObjs, int nIns, int nLatches, int nOuts, int nAnds ) +{ + FILE * pFile = fopen( pFileName, "wb" ); int i; + if ( pFile == NULL ) + { + fprintf( stdout, "Mini_AigerWrite(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "aig %d %d %d %d %d\n", nIns + nLatches + nAnds, nIns, nLatches, nOuts, nAnds ); + for ( i = 0; i < nLatches; i++ ) + fprintf( pFile, "%d\n", pObjs[2*(nObjs-nLatches+i)+0] ); + for ( i = 0; i < nOuts; i++ ) + fprintf( pFile, "%d\n", pObjs[2*(nObjs-nOuts-nLatches+i)+0] ); + for ( i = 0; i < nAnds; i++ ) + { + int uLit = 2*(1+nIns+nLatches+i); + int uLit0 = pObjs[uLit+0]; + int uLit1 = pObjs[uLit+1]; + Mini_AigerWriteUnsigned( pFile, uLit - uLit1 ); + Mini_AigerWriteUnsigned( pFile, uLit1 - uLit0 ); + } + fprintf( pFile, "c\n" ); + fclose( pFile ); +} +static void Mini_AigerWrite( char * pFileName, Mini_Aig_t * p, int fVerbose ) +{ + int i, nIns = 0, nOuts = 0, nAnds = 0; + assert( Mini_AigIsNormalized(p) ); + for ( i = 1; i < Mini_AigNodeNum(p); i++ ) + { + if ( Mini_AigNodeIsPi(p, i) ) + nIns++; + else if ( Mini_AigNodeIsPo(p, i) ) + nOuts++; + else + nAnds++; + } + Mini_AigerWriteInt( pFileName, p->pArray, p->nSize/2, nIns - p->nRegs, p->nRegs, nOuts - p->nRegs, nAnds ); + if ( fVerbose ) + printf( "Written MiniAIG into the AIGER file \"%s\".\n", pFileName ); +} +static void Mini_AigerTest( char * pFileNameIn, char * pFileNameOut ) +{ + Mini_Aig_t * p = Mini_AigerRead( pFileNameIn, 1 ); + if ( p == NULL ) + return; + printf( "Finished reading input file \"%s\".\n", pFileNameIn ); + Mini_AigerWrite( pFileNameOut, p, 1 ); + printf( "Finished writing output file \"%s\".\n", pFileNameOut ); + Mini_AigStop( p ); +} + +/* +int main( int argc, char ** argv ) +{ + if ( argc != 3 ) + return 0; + Mini_AigerTest( argv[1], argv[2] ); + return 1; +} +*/ + +/* +#include "aig/miniaig/miniaig.h" + +// this procedure creates a MiniAIG for function F = a*b + ~c and writes it into a file "test.aig" +void Mini_AigTest() +{ + Mini_Aig_t * p = Mini_AigStart(); // create empty AIG manager (contains only const0 node) + int litApos = Mini_AigCreatePi( p ); // create input A (returns pos lit of A) + int litBpos = Mini_AigCreatePi( p ); // create input B (returns pos lit of B) + int litCpos = Mini_AigCreatePi( p ); // create input C (returns pos lit of C) + int litCneg = Mini_AigLitNot( litCpos ); // neg lit of C + int litAnd = Mini_AigAnd( p, litApos, litBpos ); // lit for a*b + int litOr = Mini_AigOr( p, litAnd, litCneg ); // lit for a*b + ~c + Mini_AigCreatePo( p, litOr ); // create primary output + Mini_AigerWrite( "test.aig", p, 1 ); // write the result into a file + Mini_AigStop( p ); // deallocate MiniAIG +} +*/ + //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// +#ifndef _VERIFIC_DATABASE_H_ ABC_NAMESPACE_HEADER_END +#endif #endif diff --git a/abc/src/aig/miniaig/minilut.h b/abc/src/aig/miniaig/minilut.h index fb5c6f06fcd..2a27ccadbe6 100644 --- a/abc/src/aig/miniaig/minilut.h +++ b/abc/src/aig/miniaig/minilut.h @@ -96,6 +96,8 @@ static void Mini_LutPush( Mini_Lut_t * p, int nVars, int * pVars, unsigned * pTr else Mini_LutGrow( p, 2 * p->nCap ); } + for ( i = 0; i < nVars; i++ ) + assert( pVars[i] >= 0 && pVars[i] < p->nSize ); for ( i = 0; i < nVars; i++ ) p->pArray[p->LutSize * p->nSize + i] = pVars[i]; for ( ; i < p->LutSize; i++ ) @@ -177,7 +179,37 @@ static void Mini_LutPrintStats( Mini_Lut_t * p ) nNodes = 0; Mini_LutForEachNode( p, i ) nNodes++; - printf( "PI = %d. PO = %d. LUT = %d.\n", nPis, nPos, nNodes ); + printf( "PI = %d. PO = %d. LUT = %d. FF = %d.\n", nPis, nPos, nNodes, p->nRegs ); +} +static void Mini_LutPrint( Mini_Lut_t * p ) +{ + int i, k, Fan; + printf( "MiniLUT statistics: " ); + Mini_LutPrintStats( p ); + printf( "Printout of nodes:\n" ); + for ( i = 0; i < p->nSize; i++ ) + { + printf( "%6d : ", i ); + if ( Mini_LutNodeIsConst(p, i) ) + printf( "Const%d", i ); + else if ( Mini_LutNodeIsPi(p, i) ) + printf( "PI" ); + else if ( Mini_LutNodeIsPo(p, i) ) + printf( "PO" ); + else if ( Mini_LutNodeIsNode(p, i) ) + { + printf( "LUT%d Fanins:", p->LutSize ); + Mini_LutForEachFanin( p, i, Fan, k ) + printf( " %6d", Fan ); + while ( k++ < p->LutSize ) + printf( " " ); + printf( " Function: " ); + for ( k = 31; k >= 0; k-- ) + printf( "%c", '0' + ((p->pTruths[i] >> k) & 1) ); + } + printf( "\n" ); + } + printf( "End of printout.\n" ); } // serialization diff --git a/abc/src/aig/miniaig/ndr.h b/abc/src/aig/miniaig/ndr.h index 286c3811adb..1937306368e 100644 --- a/abc/src/aig/miniaig/ndr.h +++ b/abc/src/aig/miniaig/ndr.h @@ -33,7 +33,9 @@ #include "abcOper.h" +#ifndef _YOSYS_ ABC_NAMESPACE_HEADER_START +#endif #ifdef _WIN32 #define inline __inline @@ -42,61 +44,50 @@ ABC_NAMESPACE_HEADER_START /* For the lack of a better name, this format is called New Data Representation (NDR). - NDR is based on the following principles: - - complex data is composed of individual records - - a record has one of several known types (module, name, range, fanins, etc) - - a record can be atomic, for example, a name or an operator type - - a record can be composed of other records (for example, a module is composed of objects, etc) - - the stored data should be easy to write into and read from a file, or pass around as a memory buffer - - the format should be simple, easy to use, low-memory, and extensible - - new record types can be added by the user as needed - - The implementation is based on the following ideas: - - a record is composed of two parts (the header followed by the body) - - the header contains two items (the record type and the body size, measured in terms of 4-byte integers) - - the body contains as many entries as stated in the record size - - if a record is composed of other records, its body contains these records - - As an example, consider a name. It can be a module name, an object name, or a net name. - A record storing one name has a header {NDR_NAME, 1} containing record type (NDR_NAME) and size (1), - The body of the record is composed of one unsigned integer representing the name (say, 357). - So the complete record looks as follows: {
, } = { {NDR_NAME, 1}, {357} }. - - As another example, consider a two-input AND-gate. In this case, the recent is composed - of a header {NDR_OBJECT, 4} containing record type (NDR_OBJECT) and the body size (4), followed - by an array of records creating the AND-gate: (a) name, (b) operation type, (c) fanins. - The complete record looks as follows: { {NDR_OBJECT, 5}, {{{NDR_NAME, 1}, 357}, {{NDR_OPERTYPE, 1}, ABC_OPER_LOGIC_AND}, - {{NDR_INPUT, 2}, {, }}} }. Please note that only body entries are counted towards size. - In the case of one name, there is only one body entry. In the case of the AND-gate, there are 4 body entries - (name ID, gate type, first fanin, second fanin). - - Headers and bodies of all objects are stored differently. Headers are stored in an array of unsigned chars, - while bodies are stored in the array of 4-byte unsigned integers. This is important for memory efficiency. - However, the user does not see these details. - - To estimate memory usage, we can assume that each header takes 1 byte and each body entry contains 4 bytes. - A name takes 5 bytes, and an AND-gate takes 1 * NumHeaders + 4 * NumBodyEntries = 1 * 4 + 4 * 4 = 20 bytes. - Not bad. The same as memory usage in a well-designed AIG package with structural hashing. - - Comments: - - it is assumed that all port names, net names, and instance names are hashed into 1-based integer numbers called name IDs - - nets are not explicitly represented but their name ID are used to establish connectivity between the objects - - primary input and primary output objects have to be explicitly created (as shown in the example below) - - object inputs are name IDs of the driving nets; object outputs are name IDs of the driven nets - - objects can be added to a module in any order - - if the ordering of inputs/outputs/flops of a module is not provided as a separate record, - their ordering is determined by the order of their appearance of their records in the body of the module - - if range limits and signedness are all 0, it is assumed that it is a Boolean object - - if left limit and right limit of a range are equal, it is assumed that the range contains one bit - - instances of known operators can have types defined by Wlc_ObjType_t below - - instances of user modules have type equal to the name ID of the module plus 1000 - - initial states of the flops are given as char-strings containing 0, 1, and 'x' - (for example, "4'b10XX" is an init state of a 4-bit flop with bit-level init states const1, const0, unknown, unknown) - - word-level constants are represented as char-strings given in the same way as they would appear in a Verilog file - (for example, the 16-bit constant 10 is represented as a string "4'b1010". This string contains 8 bytes, - including the char '\0' to denote the end of the string. It will take 2 unsigned ints, therefore - its record will look as follows { {NDR_FUNCTION, 2}, {"4'b1010"} }, but the user does not see these details. - The user only gives "4'b1010" as an argument (char * pFunction) to the above procedure Ndr_AddObject(). + NDR is designed as an interchange format to pass hierarchical word-level designs between the tools. + It is relatively simple, uses little memory, and can be easily converted into other ABC data-structures. + + This tutorial discusses how to construct the NDR representation of a hierarchical word-level design. + + First, all names used in the design (including the design name, module names, port names, net names, + instance names, etc) are hashed into 1-based integers called "name IDs". Nets are not explicitly represented. + The connectivity of a design object is established by specifying name IDs of the nets connected to the object. + Object inputs are name IDs of the driving nets; object outputs are name IDs of the driven nets. + + The design is initialized using procedure Ndr_Create(), which takes the design name as an argument. + A module in the design is initialized using procedure Ndr_AddModule(), which takes the design and + the module name as arguments. Objects are added to a module in any order using procedure Ndr_AddObject(). + + Primary input and primary output objects should be explicitly created, as shown in the examples below. + + Instances of known operators listed in file "abcOper.h" are assumed to have one output. The only known + issue due to this restriction concerns the adder, which produces the sum and the carry-out. To make sure the + adder instance has only one output, the carry-out has to be concatenated with the sum before the adder + instance is created in the NDR format. + + Instances of hierarchical modules defined by the user can have multiple outputs. + + Bit-slice and concatenation operators should be represented as separate objects. + + If the ordering of inputs/outputs/flops of a module is not provided as a separate record in NDR format, + their ordering is determined by the order of their appearance in the NDR description of the module. + + If left limit and right limit of a bit-range are equal, it is assumed that the range contains one bit + + Word-level constants are represented as char-strings given in the same way as they would appear in a Verilog + file. For example, the 16-bit constant 10 is represented as a string "4'b1010" and is given as an argument + (char * pFunction) to the procedure Ndr_AddObject(). + + Currently two types of flops are supported: a simple flop with implicit clock and two fanins (data and init) + and a complex flop with 8 fanins (clock, data, reset, set, enable, async, sre, init), as shown in the examples below. + + The initial value of a flop is represented by input "init", which can be driven by a constant or by a primary + input of the module. If it is a primary input, is it assumed that the flop is not initialized. If the input + "init" is not driven, it is assumed that the flop is initialized to 0. + + Memory read and write ports are supported, as shown in the example below. + + (to be continued) */ //////////////////////////////////////////////////////////////////////// @@ -142,6 +133,8 @@ static inline int Ndr_DataEnd( Ndr_Data_t * p, int i ) static inline void Ndr_DataAddTo( Ndr_Data_t * p, int i, int Add ) { assert(Ndr_DataType(p, i) <= NDR_OBJECT); p->pBody[i] += Add; } static inline void Ndr_DataPush( Ndr_Data_t * p, int Type, int Entry ) { p->pHead[p->nSize] = Type; p->pBody[p->nSize++] = Entry; } +#define NDR_ALLOC(type, num) ((type *) malloc(sizeof(type) * (size_t)(num))) + //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// @@ -183,7 +176,7 @@ static inline void Ndr_DataResize( Ndr_Data_t * p, int Add ) { if ( p->nSize + Add <= p->nCap ) return; - p->nCap = Abc_MaxInt( 2 * p->nCap, p->nSize + Add ); + p->nCap = 2 * p->nCap > p->nSize + Add ? 2 * p->nCap : p->nSize + Add; p->pHead = (unsigned char*)realloc( p->pHead, p->nCap ); p->pBody = (unsigned int *)realloc( p->pBody, 4*p->nCap ); } @@ -212,15 +205,30 @@ static inline void Ndr_DataPushArray( Ndr_Data_t * p, int Type, int nArray, int return; assert( nArray > 0 ); Ndr_DataResize( p, nArray ); - memset( p->pHead + p->nSize, Type, nArray ); - memcpy( p->pBody + p->nSize, pArray, 4*nArray ); + memset( p->pHead + p->nSize, Type, (size_t)nArray ); + memcpy( p->pBody + p->nSize, pArray, (size_t)4*nArray ); p->nSize += nArray; } -static inline void Ndr_DataPushString( Ndr_Data_t * p, int Type, char * pFunc ) +static inline void Ndr_DataPushString( Ndr_Data_t * p, int ObjType, int Type, char * pFunc ) { + int nBuffInts; + int * pBuff; if ( !pFunc ) return; - Ndr_DataPushArray( p, Type, ((int)strlen(pFunc) + 4) / 4, (int *)pFunc ); + if ( ObjType == ABC_OPER_LUT ) + { + //word Truth = (word)pFunc; + //Ndr_DataPushArray( p, Type, 2, (int *)&Truth ); + Ndr_DataPushArray( p, Type, 2, (int *)&pFunc ); + } + else + { + nBuffInts = ((int)strlen(pFunc) + 4) / 4; + pBuff = (int *)calloc( 1, 4*nBuffInts ); + memcpy( pBuff, pFunc, strlen(pFunc) ); + Ndr_DataPushArray( p, Type, nBuffInts, pBuff ); + free( pBuff ); + } } //////////////////////////////////////////////////////////////////////// @@ -329,10 +337,11 @@ static inline int Ndr_DataObjNum( Ndr_Data_t * p, int Mod ) } // to write signal names, this procedure takes a mapping of name IDs into actual char-strings (pNames) -static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod, char ** pNames ) +static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod, char ** pNames, int fSimple ) { Ndr_Data_t * p = (Ndr_Data_t *)pDesign; - int Obj, nArray, * pArray, fFirst = 1; + int * pOuts = NDR_ALLOC( int, Ndr_DataCoNum(p, Mod) ); + int i, k, Obj, nArray, * pArray, fFirst = 1; fprintf( pFile, "\nmodule %s (\n ", pNames[Ndr_ObjReadEntry(p, Mod, NDR_NAME)] ); @@ -353,21 +362,31 @@ static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod fprintf( pFile, " %s;\n", Ndr_ObjReadOutName(p, Obj, pNames) ); } + i = 0; Ndr_ModForEachPo( p, Mod, Obj ) { fprintf( pFile, " output " ); Ndr_ObjWriteRange( p, Obj, pFile, 1 ); fprintf( pFile, " %s;\n", Ndr_ObjReadInName(p, Obj, pNames) ); + pOuts[i++] = Ndr_ObjReadBody(p, Obj, NDR_INPUT); } fprintf( pFile, "\n" ); Ndr_ModForEachNode( p, Mod, Obj ) { + for ( k = 0; k < i; k++ ) + if ( pOuts[k] == Ndr_ObjReadBody(p, Obj, NDR_OUTPUT) ) + break; + if ( k < i ) + continue; + if ( Ndr_ObjReadOutName(p, Obj, pNames)[0] == '1' ) + continue; fprintf( pFile, " wire " ); Ndr_ObjWriteRange( p, Obj, pFile, 1 ); fprintf( pFile, " %s;\n", Ndr_ObjReadOutName(p, Obj, pNames) ); } + free( pOuts ); fprintf( pFile, "\n" ); @@ -377,7 +396,7 @@ static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod if ( Type >= 256 ) { fprintf( pFile, " %s ", pNames[Ndr_ObjReadEntry(p, Type-256, NDR_NAME)] ); - if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) ) + if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 ) fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] ); fprintf( pFile, "( " ); nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); @@ -386,6 +405,83 @@ static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod fprintf( pFile, ");\n" ); continue; } + if ( Type == ABC_OPER_DFF ) + { + fprintf( pFile, " %s ", "ABC_DFF" ); + if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 ) + fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] ); + fprintf( pFile, "( " ); + nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + fprintf( pFile, ".q(%s), ", Ndr_ObjReadOutName(p, Obj, pNames) ); + fprintf( pFile, ".d(%s), ", pNames[pArray[0]] ); + fprintf( pFile, ".init(%s) ", pNames[pArray[1]] ); + fprintf( pFile, ");\n" ); + continue; + } + if ( Type == ABC_OPER_DFFRSE ) + { + fprintf( pFile, " %s ", "ABC_DFFRSE" ); + if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 ) + fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] ); + fprintf( pFile, "( " ); + nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + fprintf( pFile, ".q(%s), ", Ndr_ObjReadOutName(p, Obj, pNames) ); + fprintf( pFile, ".d(%s), ", pNames[pArray[0]] ); + fprintf( pFile, ".clk(%s), ", pNames[pArray[1]] ); + fprintf( pFile, ".reset(%s), ", pNames[pArray[2]] ); + fprintf( pFile, ".set(%s), ", pNames[pArray[3]] ); + fprintf( pFile, ".enable(%s), ", pNames[pArray[4]] ); + fprintf( pFile, ".async(%s), ", pNames[pArray[5]] ); + fprintf( pFile, ".sre(%s), ", pNames[pArray[6]] ); + fprintf( pFile, ".init(%s) ", pNames[pArray[7]] ); + fprintf( pFile, ");\n" ); + continue; + } + if ( Type == ABC_OPER_RAMR ) + { + fprintf( pFile, " %s ", "ABC_READ" ); + if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 ) + fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] ); + fprintf( pFile, "( " ); + nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + fprintf( pFile, ".data(%s), ", Ndr_ObjReadOutName(p, Obj, pNames) ); + fprintf( pFile, ".mem_in(%s), ", pNames[pArray[0]] ); + fprintf( pFile, ".addr(%s) ", pNames[pArray[1]] ); + fprintf( pFile, ");\n" ); + continue; + } + if ( Type == ABC_OPER_RAMW ) + { + fprintf( pFile, " %s ", "ABC_WRITE" ); + if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 ) + fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] ); + fprintf( pFile, "( " ); + nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + fprintf( pFile, ".mem_out(%s), ", Ndr_ObjReadOutName(p, Obj, pNames) ); + fprintf( pFile, ".mem_in(%s), ", pNames[pArray[0]] ); + fprintf( pFile, ".addr(%s), ", pNames[pArray[1]] ); + fprintf( pFile, ".data(%s) ", pNames[pArray[2]] ); + fprintf( pFile, ");\n" ); + continue; + } + if ( fSimple ) + { + if ( Ndr_ObjReadOutName(p, Obj, pNames)[0] == '1' ) + continue; + nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + fprintf( pFile, " %s ( %s", Abc_OperNameSimple(Type), Ndr_ObjReadOutName(p, Obj, pNames) ); + if ( nArray == 0 ) + fprintf( pFile, ", %s );\n", (char *)Ndr_ObjReadBodyP(p, Obj, NDR_FUNCTION) ); + else if ( nArray == 1 && Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE) == ABC_OPER_BIT_BUF ) + fprintf( pFile, ", %s );\n", pNames[pArray[0]] ); + else + { + for ( i = 0; i < nArray; i++ ) + fprintf( pFile, ", %s", pNames[pArray[i]] ); + fprintf( pFile, " );\n" ); + } + continue; + } fprintf( pFile, " assign %s = ", Ndr_ObjReadOutName(p, Obj, pNames) ); nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); if ( nArray == 0 ) @@ -410,7 +506,7 @@ static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod else if ( nArray == 3 && Type == ABC_OPER_ARI_ADD ) fprintf( pFile, "%s + %s + %s;\n", pNames[pArray[0]], pNames[pArray[1]], pNames[pArray[2]] ); else if ( Type == ABC_OPER_BIT_MUX ) - fprintf( pFile, "%s ? %s : %s;\n", pNames[pArray[0]], pNames[pArray[1]], pNames[pArray[2]] ); + fprintf( pFile, "%s ? %s : %s;\n", pNames[pArray[0]], pNames[pArray[2]], pNames[pArray[1]] ); else fprintf( pFile, ";\n", Abc_OperName(Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE)) ); } @@ -419,15 +515,15 @@ static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod } // to write signal names, this procedure takes a mapping of name IDs into actual char-strings (pNames) -static inline void Ndr_WriteVerilog( char * pFileName, void * pDesign, char ** pNames ) +static inline void Ndr_WriteVerilog( char * pFileName, void * pDesign, char ** pNames, int fSimple ) { Ndr_Data_t * p = (Ndr_Data_t *)pDesign; int Mod; FILE * pFile = pFileName ? fopen( pFileName, "wb" ) : stdout; - if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; } + if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ? pFileName : "stdout" ); return; } Ndr_DesForEachMod( p, Mod ) - Ndr_WriteVerilogModule( pFile, p, Mod, pNames ); + Ndr_WriteVerilogModule( pFile, p, Mod, pNames, fSimple ); if ( pFileName ) fclose( pFile ); } @@ -440,11 +536,11 @@ static inline void Ndr_WriteVerilog( char * pFileName, void * pDesign, char ** p // creating a new module (returns pointer to the memory buffer storing the module info) static inline void * Ndr_Create( int Name ) { - Ndr_Data_t * p = ABC_ALLOC( Ndr_Data_t, 1 ); + Ndr_Data_t * p = NDR_ALLOC( Ndr_Data_t, 1 ); p->nSize = 0; p->nCap = 16; - p->pHead = ABC_ALLOC( unsigned char, p->nCap ); - p->pBody = ABC_ALLOC( unsigned int, p->nCap * 4 ); + p->pHead = NDR_ALLOC( unsigned char, p->nCap ); + p->pBody = NDR_ALLOC( unsigned int, p->nCap * 4 ); Ndr_DataPush( p, NDR_DESIGN, 0 ); Ndr_DataPush( p, NDR_NAME, Name ); Ndr_DataAddTo( p, 0, p->nSize ); @@ -489,7 +585,7 @@ static inline void Ndr_AddObject( void * pDesign, int ModuleId, Ndr_DataPush( p, NDR_NAME, InstName ); Ndr_DataPushArray( p, NDR_INPUT, nInputs, pInputs ); Ndr_DataPushArray( p, NDR_OUTPUT, nOutputs, pOutputs ); - Ndr_DataPushString( p, NDR_FUNCTION, pFunction ); + Ndr_DataPushString( p, ObjType, NDR_FUNCTION, pFunction ); Ndr_DataAddTo( p, Obj, p->nSize - Obj ); Ndr_DataAddTo( p, Mod, p->nSize - Obj ); Ndr_DataAddTo( p, 0, p->nSize - Obj ); @@ -520,13 +616,15 @@ static inline void * Ndr_Read( char * pFileName ) // check file size fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); + if ( nFileSize % 5 != 0 ) + return NULL; assert( nFileSize % 5 == 0 ); rewind( pFile ); // create structure - p = ABC_ALLOC( Ndr_Data_t, 1 ); + p = NDR_ALLOC( Ndr_Data_t, 1 ); p->nSize = p->nCap = nFileSize / 5; - p->pHead = ABC_ALLOC( unsigned char, p->nCap ); - p->pBody = ABC_ALLOC( unsigned int, p->nCap * 4 ); + p->pHead = NDR_ALLOC( unsigned char, p->nCap ); + p->pBody = NDR_ALLOC( unsigned int, p->nCap * 4 ); RetValue = (int)fread( p->pBody, 4, p->nCap, pFile ); RetValue = (int)fread( p->pHead, 1, p->nCap, pFile ); assert( p->nSize == (int)p->pBody[0] ); @@ -538,7 +636,7 @@ static inline void Ndr_Write( char * pFileName, void * pDesign ) { Ndr_Data_t * p = (Ndr_Data_t *)pDesign; int RetValue; FILE * pFile = fopen( pFileName, "wb" ); - if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; } + if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ? pFileName : "stdout" ); return; } RetValue = (int)fwrite( p->pBody, 4, p->pBody[0], pFile ); RetValue = (int)fwrite( p->pHead, 1, p->pBody[0], pFile ); fclose( pFile ); @@ -551,7 +649,7 @@ static inline void Ndr_Write( char * pFileName, void * pDesign ) //////////////////////////////////////////////////////////////////////// // This testing procedure creates and writes into a Verilog file -// for the following design composed of one module +// the following design composed of one module // module add10 ( input [3:0] a, output [3:0] s ); // wire [3:0] const10 = 4'b1010; @@ -567,7 +665,7 @@ static inline void Ndr_ModuleTest() // array of fanins of node s int Fanins[2] = { NameIdA, NameIdC }; // map name IDs into char strings - char * ppNames[5] = { NULL, "add10", "a", "s", "const10" }; + //char * ppNames[5] = { NULL, "add10", "a", "s", "const10" }; // create a new module void * pDesign = Ndr_Create( 1 ); @@ -576,20 +674,20 @@ static inline void Ndr_ModuleTest() // add objects to the modele Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &NameIdA, NULL ); // no fanins - Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CONST, 0, 3, 0, 0, 0, NULL, 1, &NameIdC, "4'b1010" ); // no fanins + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CONST, 0, 3, 0, 0, 0, NULL, 1, &NameIdC, (char*)"4'b1010" ); // no fanins Ndr_AddObject( pDesign, ModuleID, ABC_OPER_ARI_ADD, 0, 3, 0, 0, 2, Fanins, 1, &NameIdS, NULL ); // fanins are a and const10 Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 3, 0, 0, 1, &NameIdS, 0, NULL, NULL ); // fanin is a // write Verilog for verification - Ndr_WriteVerilog( NULL, pDesign, ppNames ); - Ndr_Write( "add4.ndr", pDesign ); + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"add4.ndr", pDesign ); Ndr_Delete( pDesign ); } // This testing procedure creates and writes into a Verilog file -// for the following design composed of one adder divided into two +// the following design composed of one adder divided into two // module add8 ( input [7:0] a, input [7:0] b, output [7:0] s, output co ); // wire [3:0] a0 = a[3:0]; @@ -611,6 +709,7 @@ static inline void Ndr_ModuleTest() static inline void Ndr_ModuleTestAdder() { +/* // map name IDs into char strings char * ppNames[20] = { NULL, "a", "b", "s", "co", // 1, 2, 3, 4 @@ -618,6 +717,7 @@ static inline void Ndr_ModuleTestAdder() "r0", "s0", "rco", // 9, 10, 11 "r1", "s1", "add8" // 12, 13, 14 }; +*/ // fanins int FaninA = 1; int FaninB = 2; @@ -669,14 +769,14 @@ static inline void Ndr_ModuleTestAdder() Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 0, 0, 0, 1, &FaninCO, 0, NULL, NULL ); // write Verilog for verification - Ndr_WriteVerilog( NULL, pDesign, ppNames ); - Ndr_Write( "add8.ndr", pDesign ); + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"add8.ndr", pDesign ); Ndr_Delete( pDesign ); } // This testing procedure creates and writes into a Verilog file -// for the following hierarchical design composed of three modules +// the following hierarchical design composed of two modules // module mux21w ( input sel, input [3:0] d1, input [3:0] d0, output [3:0] out ); // assign out = sel ? d1 : d0; @@ -697,6 +797,7 @@ static inline void Ndr_ModuleTestAdder() static inline void Ndr_ModuleTestHierarchy() { +/* // map name IDs into char strings char * ppNames[20] = { NULL, "mux21w", "mux41w", // 1, 2 @@ -706,6 +807,7 @@ static inline void Ndr_ModuleTestHierarchy() "t0", "t1", // 12, 13 "i0", "i1", "i2" // 14, 15, 16 }; +*/ // fanins int FaninSel = 3; int FaninSel0 = 10; @@ -755,13 +857,308 @@ static inline void Ndr_ModuleTestHierarchy() Ndr_AddObject( pDesign, Module41, ABC_OPER_CO, 0, 3, 0, 0, 1, &FaninOut, 0, NULL, NULL ); // write Verilog for verification - Ndr_WriteVerilog( NULL, pDesign, ppNames ); - Ndr_Write( "mux41w.ndr", pDesign ); + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"mux41w.ndr", pDesign ); + Ndr_Delete( pDesign ); +} + + +// This testing procedure creates and writes into a Verilog file +// the following design with read/write memory ports + +// module test ( input clk, input [8:0] raddr, input [8:0] waddr, input [31:0] data, input [16383:0] mem_init, output out ); +// +// wire [31:0] read1, read2; +// +// wire [16383:0] mem_fo1, mem_fo2, mem_fi1, mem_fi2; +// +// ABC_FF i_reg1 ( .q(mem_fo1), .d(mem_fi1), .init(mem_init) ); +// ABC_FF i_reg2 ( .q(mem_fo2), .d(mem_fi2), .init(mem_init) ); +// +// ABC_WRITE i_write1 ( .mem_out(mem_fi1), .mem_in(mem_fo1), .addr(waddr), .data(data) ); +// ABC_WRITE i_write2 ( .mem_out(mem_fi2), .mem_in(mem_fo2), .addr(waddr), .data(data) ); +// +// ABC_READ i_read1 ( .data(read1), .mem_in(mem_fi1), .addr(raddr) ); +// ABC_READ i_read2 ( .data(read2), .mem_in(mem_fi2), .addr(raddr) ); +// +// assign out = read1 != read2; +//endmodule + +static inline void Ndr_ModuleTestMemory() +{ +/* + // map name IDs into char strings + char * ppNames[20] = { NULL, + "clk", "raddr", "waddr", "data", "mem_init", "out", // 1, 2, 3, 4, 5, 6 + "read1", "read2", // 7. 8 + "mem_fo1", "mem_fo2", "mem_fi1", "mem_fi2", // 9, 10, 11, 12 + "i_reg1", "i_reg2", // 13, 14 + "i_read1", "i_read2", // 15, 16 + "i_write1", "i_write2", "memtest" // 17, 18, 19 + }; +*/ + // inputs + int NameIdClk = 1; + int NameIdRaddr = 2; + int NameIdWaddr = 3; + int NameIdData = 4; + int NameIdMemInit = 5; + // flops + int NameIdFF1 = 9; + int NameIdFF2 = 10; + int FaninsFF1[2] = { 11, 5 }; + int FaninsFF2[2] = { 12, 5 }; + // writes + int NameIdWrite1 = 11; + int NameIdWrite2 = 12; + int FaninsWrite1[3] = { 9, 3, 4 }; + int FaninsWrite2[3] = { 10, 3, 4 }; + // reads + int NameIdRead1 = 7; + int NameIdRead2 = 8; + int FaninsRead1[2] = { 11, 2 }; + int FaninsRead2[2] = { 12, 2 }; + // compare + int NameIdComp = 6; + int FaninsComp[2] = { 7, 8 }; + + // create a new module + void * pDesign = Ndr_Create( 19 ); // create design named "memtest" + + int ModuleID = Ndr_AddModule( pDesign, 19 ); // create module named "memtest" + + // add objects to the module + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdClk, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 8, 0, 0, 0, NULL, 1, &NameIdRaddr, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 8, 0, 0, 0, NULL, 1, &NameIdWaddr, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 31, 0, 0, 0, NULL, 1, &NameIdData, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 16383, 0, 0, 0, NULL, 1, &NameIdMemInit, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 0, 0, 0, 1, &NameIdComp, 0, NULL, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_DFF, 13, 16383, 0, 0, 2, FaninsFF1, 1, &NameIdFF1, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_DFF, 14, 16383, 0, 0, 2, FaninsFF2, 1, &NameIdFF2, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMW, 17, 16383, 0, 0, 3, FaninsWrite1, 1, &NameIdWrite1, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMW, 18, 16383, 0, 0, 3, FaninsWrite2, 1, &NameIdWrite2, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMR, 15, 31, 0, 0, 2, FaninsRead1, 1, &NameIdRead1, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMR, 16, 31, 0, 0, 2, FaninsRead2, 1, &NameIdRead2, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_COMP_NOTEQU, 0, 0, 0, 0, 2, FaninsComp, 1, &NameIdComp, NULL ); + + // write Verilog for verification + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"memtest.ndr", pDesign ); Ndr_Delete( pDesign ); } +// This testing procedure creates and writes into a Verilog file +// the following design composed of one word-level flop + +// module flop ( input [3:0] data, input clk, input reset, input set, input enable, input async, input sre, input [3:0] init, output [3:0] q ); +// ABC_DFFRSE reg1 ( .d(data), .clk(clk), .reset(reset), .set(set), .enable(enable), .async(async), .sre(sre), .init(init), .q(q) ) ; +// endmodule + +static inline void Ndr_ModuleTestFlop() +{ + // map name IDs into char strings + //char * ppNames[12] = { NULL, "flop", "data", "clk", "reset", "set", "enable", "async", "sre", "init", "q" }; + // name IDs + int NameIdData = 2; + int NameIdClk = 3; + int NameIdReset = 4; + int NameIdSet = 5; + int NameIdEnable = 6; + int NameIdAsync = 7; + int NameIdSre = 8; + int NameIdInit = 9; + int NameIdQ = 10; + // array of fanins of node s + int Fanins[8] = { NameIdData, NameIdClk, NameIdReset, NameIdSet, NameIdEnable, NameIdAsync, NameIdSre, NameIdInit }; + + // create a new module + void * pDesign = Ndr_Create( 1 ); + + int ModuleID = Ndr_AddModule( pDesign, 1 ); + // add objects to the modele + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &NameIdData, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdClk, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdReset, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdSet, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdEnable, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdAsync, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdSre, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &NameIdInit, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_DFFRSE, 0, 3, 0, 0, 8, Fanins, 1, &NameIdQ, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 3, 0, 0, 1, &NameIdQ, 0, NULL, NULL ); + + // write Verilog for verification + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"flop.ndr", pDesign ); + Ndr_Delete( pDesign ); +} + + +// This testing procedure creates and writes into a Verilog file +// the following design composed of one selector + +// module sel ( input [3:0] c, input [2:0] d0, input [2:0] d1, input [2:0] d2, input [2:0] d3, input [2:0] out ); +// wire [2:0] s7 ; +// always @( c or d0 or d1 or d2 or d3 ) +// begin +// case ( c ) +// 4'b0001 : s7 = d0 ; +// 4'b0010 : s7 = d1 ; +// 4'b0100 : s7 = d2 ; +// 4'b1000 : s7 = d3 ; +// endcase +// end +// assign out = s7 ; +// endmodule + +static inline void Ndr_ModuleTestSelSel() +{ + // map name IDs into char strings + //char * ppNames[12] = { NULL, "sel", "c", "d0", "d1", "d2", "d3", "out" }; + // name IDs + int NameIdC = 2; + int NameIdD0 = 3; + int NameIdD1 = 4; + int NameIdD2 = 5; + int NameIdD3 = 6; + int NameIdOut = 7; + // array of fanins of node s + int Fanins[8] = { NameIdC, NameIdD0, NameIdD1, NameIdD2, NameIdD3 }; + + // create a new module + void * pDesign = Ndr_Create( 1 ); + + int ModuleID = Ndr_AddModule( pDesign, 1 ); + + // add objects to the modele + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &NameIdC, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 2, 0, 0, 0, NULL, 1, &NameIdD0, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 2, 0, 0, 0, NULL, 1, &NameIdD1, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 2, 0, 0, 0, NULL, 1, &NameIdD2, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 2, 0, 0, 0, NULL, 1, &NameIdD3, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SEL_SEL, 0, 2, 0, 0, 5, Fanins, 1, &NameIdOut, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 2, 0, 0, 1, &NameIdOut,0, NULL, NULL ); + + // write Verilog for verification + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"sel.ndr", pDesign ); + Ndr_Delete( pDesign ); +} + +// This testing procedure creates and writes into a Verilog file +// the following design composed of one decoder + +// module dec ( input [1:0] in, output [3:0] out ); +// wire out0 = ~in[1] & ~in[0] ; +// wire out1 = ~in[1] & in[0] ; +// wire out2 = in[1] & ~in[0] ; +// wire out3 = in[1] & in[0] ; +// assign out = { out3, out2, out1, out0 } ; +// endmodule + +static inline void Ndr_ModuleTestDec() +{ + // map name IDs into char strings + //char * ppNames[12] = { NULL, "dec", "in", "out" }; + // name IDs + int NameIdIn = 2; + int NameIdOut = 3; + + // create a new module + void * pDesign = Ndr_Create( 1 ); + + int ModuleID = Ndr_AddModule( pDesign, 1 ); + + // add objects to the modele + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 1, 0, 0, 0, NULL, 1, &NameIdIn, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SEL_DEC, 0, 3, 0, 0, 1, &NameIdIn, 1, &NameIdOut, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 3, 0, 0, 1, &NameIdOut, 0, NULL, NULL ); + + Ndr_Write( (char*)"dec.ndr", pDesign ); + Ndr_Delete( pDesign ); +} + +// This testing procedure creates and writes into a Verilog file +// the following design composed of one adder/subtractor + +// module addsub ( input mode, input cin, input [2:0] a, input [2:0] b, output [3:0] out ); +// assign out = mode ? a+b+cin : a-b-cin ; +// endmodule + +static inline void Ndr_ModuleTestAddSub() +{ + // map name IDs into char strings + //char * ppNames[12] = { NULL, "addsub", "mode", "cin", "a", "b", "out" }; + // name IDs + int NameIdInMode = 2; + int NameIdInCin = 3; + int NameIdInA = 4; + int NameIdInB = 5; + int NameIdOut = 6; + int Fanins[8] = { 2, 3, 4, 5 }; + + // create a new module + void * pDesign = Ndr_Create( 1 ); + + int ModuleID = Ndr_AddModule( pDesign, 1 ); + + // add objects to the modele + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdInMode, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdInCin, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 2, 0, 0, 0, NULL, 1, &NameIdInA, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 2, 0, 0, 0, NULL, 1, &NameIdInB, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_ARI_ADDSUB, 0, 3, 0, 0, 4, Fanins, 1, &NameIdOut, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 3, 0, 0, 1, &NameIdOut, 0, NULL, NULL ); + + Ndr_Write( (char*)"addsub.ndr", pDesign ); + Ndr_Delete( pDesign ); +} + +// This testing procedure creates and writes into a Verilog file +// the following design composed of one lookup table with function of AND2 + +// module lut_test ( input [1:0] in, output out ); +// assign out = LUT #(TT=4'h8) lut_inst { in[0], in[1], out } ; +// endmodule + +static inline void Ndr_ModuleTestLut() +{ + // map name IDs into char strings + //char * ppNames[12] = { NULL, "lut_test", "in", "out" }; + // name IDs + int NameIdIn = 2; + int NameIdOut = 3; + + // create a new module + void * pDesign = Ndr_Create( 1 ); + + int ModuleID = Ndr_AddModule( pDesign, 1 ); + + unsigned pTruth[2] = { 0x88888888, 0x88888888 }; + + // add objects to the modele + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 1, 0, 0, 0, NULL, 1, &NameIdIn, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_LUT, 0, 0, 0, 0, 1, &NameIdIn, 1, &NameIdOut, (char *)pTruth ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 0, 0, 0, 1, &NameIdOut, 0, NULL, NULL ); + + Ndr_Write( (char*)"lut_test.ndr", pDesign ); + Ndr_Delete( pDesign ); +} + +#ifndef _YOSYS_ ABC_NAMESPACE_HEADER_END +#endif #endif diff --git a/abc/src/aig/saig/saigConstr.c b/abc/src/aig/saig/saigConstr.c index ac58839b4d9..90e828166d2 100644 --- a/abc/src/aig/saig/saigConstr.c +++ b/abc/src/aig/saig/saigConstr.c @@ -300,8 +300,8 @@ Aig_Man_t * Saig_ManDupUnfoldConstrs( Aig_Man_t * pAig ) Vec_VecFree( (Vec_Vec_t *)vConsAll ); return Aig_ManDupDfs( pAig ); } - Vec_PtrSort( vOuts, (int (*)(void))Saig_ManDupCompare ); - Vec_PtrSort( vCons, (int (*)(void))Saig_ManDupCompare ); + Vec_PtrSort( vOuts, (int (*)(const void *, const void *))Saig_ManDupCompare ); + Vec_PtrSort( vCons, (int (*)(const void *, const void *))Saig_ManDupCompare ); Vec_PtrPush( vOutsAll, vOuts ); Vec_PtrPush( vConsAll, vCons ); } diff --git a/abc/src/aig/saig/saigInd.c b/abc/src/aig/saig/saigInd.c index f437dba057f..d3665c85615 100644 --- a/abc/src/aig/saig/saigInd.c +++ b/abc/src/aig/saig/saigInd.c @@ -383,9 +383,9 @@ int Saig_ManInduction( Aig_Man_t * p, int nTimeOut, int nFramesMax, int nConfMax else if ( status == l_Undef ) printf( "Conflict limit (%d) was reached during iteration %d.\n", nConfMax, f+1 ); else if ( fUnique || fUniqueAll ) - printf( "Completed %d interations and added %d uniqueness constraints.\n", f+1, nConstrs ); + printf( "Completed %d iterations and added %d uniqueness constraints.\n", f+1, nConstrs ); else - printf( "Completed %d interations.\n", f+1 ); + printf( "Completed %d iterations.\n", f+1 ); } // cleanup sat_solver_delete( pSat ); diff --git a/abc/src/aig/saig/saigIoa.c b/abc/src/aig/saig/saigIoa.c index 35d7b7b279b..c235c186e8c 100644 --- a/abc/src/aig/saig/saigIoa.c +++ b/abc/src/aig/saig/saigIoa.c @@ -45,17 +45,17 @@ ABC_NAMESPACE_IMPL_START ***********************************************************************/ char * Saig_ObjName( Aig_Man_t * p, Aig_Obj_t * pObj ) { - static char Buffer[16]; + static char Buffer[1000]; if ( Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) ) - sprintf( Buffer, "n%0*d", Abc_Base10Log(Aig_ManObjNumMax(p)), Aig_ObjId(pObj) ); + sprintf( Buffer, "n%0*d", (unsigned char)Abc_Base10Log(Aig_ManObjNumMax(p)), Aig_ObjId(pObj) ); else if ( Saig_ObjIsPi(p, pObj) ) - sprintf( Buffer, "pi%0*d", Abc_Base10Log(Saig_ManPiNum(p)), Aig_ObjCioId(pObj) ); + sprintf( Buffer, "pi%0*d", (unsigned char)Abc_Base10Log(Saig_ManPiNum(p)), Aig_ObjCioId(pObj) ); else if ( Saig_ObjIsPo(p, pObj) ) - sprintf( Buffer, "po%0*d", Abc_Base10Log(Saig_ManPoNum(p)), Aig_ObjCioId(pObj) ); + sprintf( Buffer, "po%0*d", (unsigned char)Abc_Base10Log(Saig_ManPoNum(p)), Aig_ObjCioId(pObj) ); else if ( Saig_ObjIsLo(p, pObj) ) - sprintf( Buffer, "lo%0*d", Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjCioId(pObj) - Saig_ManPiNum(p) ); + sprintf( Buffer, "lo%0*d", (unsigned char)Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjCioId(pObj) - Saig_ManPiNum(p) ); else if ( Saig_ObjIsLi(p, pObj) ) - sprintf( Buffer, "li%0*d", Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjCioId(pObj) - Saig_ManPoNum(p) ); + sprintf( Buffer, "li%0*d", (unsigned char)Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjCioId(pObj) - Saig_ManPoNum(p) ); else assert( 0 ); return Buffer; diff --git a/abc/src/aig/saig/saigIso.c b/abc/src/aig/saig/saigIso.c index 40500361850..7ab8486e403 100644 --- a/abc/src/aig/saig/saigIso.c +++ b/abc/src/aig/saig/saigIso.c @@ -63,7 +63,7 @@ Vec_Int_t * Saig_ManFindIsoPermCos( Aig_Man_t * pAig, Vec_Int_t * vPermCis ) pObj->iData = Abc_Var2Lit( pFanin->iData, Aig_ObjFaninC0(pObj) ); Vec_PtrPush( vRoots, pObj ); } - Vec_PtrSort( vRoots, (int (*)(void))Iso_ObjCompareByData ); + Vec_PtrSort( vRoots, (int (*)(const void *, const void *))Iso_ObjCompareByData ); Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i ) Vec_IntPush( vPermCos, Aig_ObjCioId(pObj) ); Vec_PtrFree( vRoots ); @@ -467,7 +467,7 @@ Aig_Man_t * Iso_ManFilterPos( Aig_Man_t * pAig, Vec_Ptr_t ** pvPosEquivs, int fV // sort the infos clk = Abc_Clock(); - Vec_PtrSort( vBuffers, (int (*)(void))Iso_StoCompareVecStr ); + Vec_PtrSort( vBuffers, (int (*)(const void *, const void *))Iso_StoCompareVecStr ); // create classes clk = Abc_Clock(); @@ -493,7 +493,7 @@ Aig_Man_t * Iso_ManFilterPos( Aig_Man_t * pAig, Vec_Ptr_t ** pvPosEquivs, int fV // report the results // Vec_VecPrintInt( (Vec_Vec_t *)vClasses ); -// printf( "Devided %d outputs into %d cand equiv classes.\n", Saig_ManPoNum(pAig), Vec_PtrSize(vClasses) ); +// printf( "Divided %d outputs into %d cand equiv classes.\n", Saig_ManPoNum(pAig), Vec_PtrSize(vClasses) ); /* if ( fVerbose ) { diff --git a/abc/src/aig/saig/saigIsoFast.c b/abc/src/aig/saig/saigIsoFast.c index 6378e4db0f5..90a04df37b8 100644 --- a/abc/src/aig/saig/saigIsoFast.c +++ b/abc/src/aig/saig/saigIsoFast.c @@ -236,7 +236,7 @@ Vec_Int_t * Iso_StoCollectInfo( Iso_Sto_t * p, Aig_Obj_t * pPo ) if ( fVerboseShow ) Vec_IntForEachEntry( vInfo, Entry, i ) { - Iso_Dat2_t Data = { Entry & 0xFFFF }; + Iso_Dat2_t Data = { (unsigned)Entry & 0xFFFF }; Iso_Dat_t * pData = (Iso_Dat_t *)&Data; printf( "%6d : ", i ); @@ -303,7 +303,7 @@ Vec_Vec_t * Saig_IsoDetectFast( Aig_Man_t * pAig ) // sort the infos clk = Abc_Clock(); - Vec_PtrSort( vInfos, (int (*)(void))Iso_StoCompareVecInt ); + Vec_PtrSort( vInfos, (int (*)(const void *, const void *))Iso_StoCompareVecInt ); // create classes clk = Abc_Clock(); @@ -328,7 +328,7 @@ Vec_Vec_t * Saig_IsoDetectFast( Aig_Man_t * pAig ) // report the results // Vec_VecPrintInt( (Vec_Vec_t *)vClasses ); - printf( "Devided %d outputs into %d cand equiv classes.\n", Saig_ManPoNum(pAig), Vec_PtrSize(vClasses) ); + printf( "Divided %d outputs into %d cand equiv classes.\n", Saig_ManPoNum(pAig), Vec_PtrSize(vClasses) ); Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i ) if ( Vec_IntSize(vLevel) > 1 ) diff --git a/abc/src/aig/saig/saigIsoSlow.c b/abc/src/aig/saig/saigIsoSlow.c index a0e2d1d06b0..4784d98ac3d 100644 --- a/abc/src/aig/saig/saigIsoSlow.c +++ b/abc/src/aig/saig/saigIsoSlow.c @@ -572,8 +572,8 @@ void Iso_ManCollectClasses( Iso_Man_t * p ) } } clk = Abc_Clock(); - Vec_PtrSort( p->vSingles, (int (*)(void))Iso_ObjCompare ); - Vec_PtrSort( p->vClasses, (int (*)(void))Iso_ObjCompare ); + Vec_PtrSort( p->vSingles, (int (*)(const void *, const void *))Iso_ObjCompare ); + Vec_PtrSort( p->vClasses, (int (*)(const void *, const void *))Iso_ObjCompare ); p->timeSort += Abc_Clock() - clk; assert( Vec_PtrSize(p->vSingles) == p->nSingles ); assert( Vec_PtrSize(p->vClasses) == p->nClasses ); @@ -1115,8 +1115,8 @@ Vec_Int_t * Iso_ManFinalize( Iso_Man_t * p ) Vec_PtrPush( p->vTemp1, pObj ); } // sort CIs by their IDs - Vec_PtrSort( p->vTemp1, (int (*)(void))Iso_ObjCompareByData ); - Vec_PtrSort( p->vTemp2, (int (*)(void))Iso_ObjCompareByData ); + Vec_PtrSort( p->vTemp1, (int (*)(const void *, const void *))Iso_ObjCompareByData ); + Vec_PtrSort( p->vTemp2, (int (*)(const void *, const void *))Iso_ObjCompareByData ); // create the result vRes = Vec_IntAlloc( Aig_ManCiNum(p->pAig) ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vTemp1, pObj, i ) diff --git a/abc/src/aig/saig/saigMiter.c b/abc/src/aig/saig/saigMiter.c index 598103de917..5b15f932931 100644 --- a/abc/src/aig/saig/saigMiter.c +++ b/abc/src/aig/saig/saigMiter.c @@ -946,7 +946,7 @@ int Saig_ManDemiter( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ) if ( (pFlop0->fMarkA && pFlop0->fMarkB) || (pFlop1->fMarkA && pFlop1->fMarkB) || (pFlop0->fMarkA && pFlop1->fMarkA) || (pFlop0->fMarkB && pFlop1->fMarkB) ) - printf( "Ouput pair %4d: Difficult case...\n", i/2 ); + printf( "Output pair %4d: Difficult case...\n", i/2 ); if ( pFlop0->fMarkB ) { diff --git a/abc/src/aig/saig/saigSimMv.c b/abc/src/aig/saig/saigSimMv.c index 3621cdd3b3b..18df5007960 100644 --- a/abc/src/aig/saig/saigSimMv.c +++ b/abc/src/aig/saig/saigSimMv.c @@ -903,14 +903,14 @@ ABC_PRT( "Constructing the problem", Abc_Clock() - clk ); if ( f == nFramesSatur ) { if ( fVerbose ) - printf( "Begining to saturate simulation after %d frames\n", f ); + printf( "Beginning to saturate simulation after %d frames\n", f ); // find all flops that have at least one X value in the past and set them to X forever p->vXFlops = Saig_MvManFindXFlops( p ); } if ( f == 2 * nFramesSatur ) { if ( fVerbose ) - printf( "Agressively saturating simulation after %d frames\n", f ); + printf( "Aggressively saturating simulation after %d frames\n", f ); Vec_IntFree( p->vXFlops ); p->vXFlops = Saig_MvManCreateNextSkip( p ); } diff --git a/abc/src/aig/saig/saigTrans.c b/abc/src/aig/saig/saigTrans.c index 217d3269228..6d6a2f22667 100644 --- a/abc/src/aig/saig/saigTrans.c +++ b/abc/src/aig/saig/saigTrans.c @@ -6,7 +6,7 @@ PackageName [Sequential AIG package.] - Synopsis [Dynamic simplication of the transition relation.] + Synopsis [Dynamic simplification of the transition relation.] Author [Alan Mishchenko] diff --git a/abc/src/aig/saig/saigWnd.c b/abc/src/aig/saig/saigWnd.c index ce70e7b42cb..949a2728ec8 100644 --- a/abc/src/aig/saig/saigWnd.c +++ b/abc/src/aig/saig/saigWnd.c @@ -106,7 +106,7 @@ Vec_Ptr_t * Saig_ManWindowOutline( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist ) vNodes = Vec_PtrAlloc( 1000 ); Aig_ManIncrementTravId( p ); Saig_ManWindowOutline_rec( p, pObj, nDist, vNodes, pDists ); - Vec_PtrSort( vNodes, (int (*)(void))Aig_ObjCompareIdIncrease ); + Vec_PtrSort( vNodes, (int (*)(const void *, const void *))Aig_ObjCompareIdIncrease ); // make sure LI/LO are labeled/unlabeled mutually Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) assert( Aig_ObjIsTravIdCurrent(p, pObjLi) == diff --git a/abc/src/base/abc/abc.h b/abc/src/base/abc/abc.h index 8ac5040d8b3..5cf7a0f593c 100644 --- a/abc/src/base/abc/abc.h +++ b/abc/src/base/abc/abc.h @@ -559,7 +559,7 @@ extern ABC_DLL Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, A extern ABC_DLL Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); extern ABC_DLL Abc_Obj_t * Abc_AigMux( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * p1, Abc_Obj_t * p0 ); extern ABC_DLL Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs, int fImplic ); -extern ABC_DLL void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ); +extern ABC_DLL int Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ); extern ABC_DLL void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld ); extern ABC_DLL void Abc_AigRehash( Abc_Aig_t * pMan ); extern ABC_DLL int Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode ); @@ -600,7 +600,7 @@ extern ABC_DLL int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk ); /*=== abcCollapse.c ==========================================================*/ -extern ABC_DLL Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fReverse, int fDumpOrder, int fVerbose ); extern ABC_DLL Abc_Ntk_t * Abc_NtkCollapseSat( Abc_Ntk_t * pNtk, int nCubeLim, int nBTLimit, int nCostMax, int fCanon, int fReverse, int fCnfShared, int fVerbose ); extern ABC_DLL Gia_Man_t * Abc_NtkClpGia( Abc_Ntk_t * pNtk ); /*=== abcCut.c ==========================================================*/ @@ -657,6 +657,7 @@ extern ABC_DLL void Abc_ObjPatchFanoutFanin( Abc_Obj_t * pObj, int extern ABC_DLL Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type ); extern ABC_DLL void Abc_ObjTransferFanout( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew ); extern ABC_DLL void Abc_ObjReplace( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew ); +extern ABC_DLL void Abc_ObjReplaceByConstant( Abc_Obj_t * pNode, int fConst1 ); extern ABC_DLL int Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin ); /*=== abcFanOrder.c ==========================================================*/ extern ABC_DLL int Abc_NtkMakeLegit( Abc_Ntk_t * pNtk ); @@ -670,7 +671,7 @@ extern ABC_DLL Abc_Ntk_t * Abc_NtkFraigRestore( int nPatsRand, int nPatsD extern ABC_DLL void Abc_NtkFraigStoreClean(); /*=== abcFunc.c ==========================================================*/ extern ABC_DLL int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ); -extern ABC_DLL int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit ); +extern ABC_DLL int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit, int fCubeSort ); extern ABC_DLL void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Mem_Flex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 ); extern ABC_DLL void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ); @@ -751,6 +752,7 @@ extern ABC_DLL void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkShortNames( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkCleanNames( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkStartNameIds( Abc_Ntk_t * p ); extern ABC_DLL void Abc_NtkTransferNameIds( Abc_Ntk_t * p, Abc_Ntk_t * pNew ); extern ABC_DLL void Abc_NtkUpdateNameIds( Abc_Ntk_t * p ); @@ -760,8 +762,8 @@ extern ABC_DLL Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk ); /*=== abcNtbdd.c ==========================================================*/ extern ABC_DLL Abc_Ntk_t * Abc_NtkDeriveFromBdd( void * dd, void * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi ); -extern ABC_DLL Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk ); -extern ABC_DLL void * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDropInternal, int fReorder, int fVerbose ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk, int fGlobal, int Limit, int fUseAdd ); +extern ABC_DLL void * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDropInternal, int fReorder, int fReverse, int fVerbose ); extern ABC_DLL void * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan ); extern ABC_DLL int Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk ); /*=== abcNtk.c ==========================================================*/ @@ -781,14 +783,16 @@ extern ABC_DLL void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_ extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName ); extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ); extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateFromRange( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateWithNodes( Vec_Ptr_t * vSops ); extern ABC_DLL void Abc_NtkDelete( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkMakeComb( Abc_Ntk_t * pNtk, int fRemoveLatches ); extern ABC_DLL void Abc_NtkPermute( Abc_Ntk_t * pNtk, int fInputs, int fOutputs, int fFlops, char * pFlopPermFile ); extern ABC_DLL void Abc_NtkUnpermute( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateFromSops( char * pName, Vec_Ptr_t * vSops ); -extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateFromGias( char * pName, Vec_Ptr_t * vGias ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateFromGias( char * pName, Vec_Ptr_t * vGias, Gia_Man_t * pMulti ); /*=== abcObj.c ==========================================================*/ extern ABC_DLL Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ); extern ABC_DLL void Abc_ObjRecycle( Abc_Obj_t * pObj ); @@ -869,12 +873,12 @@ extern ABC_DLL int Abc_NodeMffcSize( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NodeMffcSizeSupp( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NodeMffcLabelAig( Abc_Obj_t * pNode ); -extern ABC_DLL int Abc_NodeMffcLabel( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_NodeMffcLabel( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); extern ABC_DLL void Abc_NodeMffcConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ); extern ABC_DLL int Abc_NodeDeref_rec( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NodeRef_rec( Abc_Obj_t * pNode ); /*=== abcRefactor.c ==========================================================*/ -extern ABC_DLL int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); +extern ABC_DLL int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nMinSaved, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); /*=== abcRewrite.c ==========================================================*/ extern ABC_DLL int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable ); /*=== abcSat.c ==========================================================*/ @@ -918,6 +922,8 @@ extern ABC_DLL int Abc_SopIsExorType( char * pSop ); extern ABC_DLL int Abc_SopCheck( char * pSop, int nFanins ); extern ABC_DLL char * Abc_SopFromTruthBin( char * pTruth ); extern ABC_DLL char * Abc_SopFromTruthHex( char * pTruth ); +extern ABC_DLL Vec_Ptr_t * Abc_SopFromTruthsBin( char * pTruth ); +extern ABC_DLL Vec_Ptr_t * Abc_SopFromTruthsHex( char * pTruth ); extern ABC_DLL char * Abc_SopEncoderPos( Mem_Flex_t * pMan, int iValue, int nValues ); extern ABC_DLL char * Abc_SopEncoderLog( Mem_Flex_t * pMan, int iBit, int nValues ); extern ABC_DLL char * Abc_SopDecoderPos( Mem_Flex_t * pMan, int nValues ); diff --git a/abc/src/base/abc/abcAig.c b/abc/src/base/abc/abcAig.c index d3347a13669..e3f3ce457be 100644 --- a/abc/src/base/abc/abcAig.c +++ b/abc/src/base/abc/abcAig.c @@ -847,7 +847,7 @@ Abc_Obj_t * Abc_AigMiter2( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs ) SeeAlso [] ***********************************************************************/ -void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ) +int Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ) { assert( Vec_PtrSize(pMan->vStackReplaceOld) == 0 ); assert( Vec_PtrSize(pMan->vStackReplaceNew) == 0 ); @@ -859,6 +859,9 @@ void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int f { pOld = (Abc_Obj_t *)Vec_PtrPop( pMan->vStackReplaceOld ); pNew = (Abc_Obj_t *)Vec_PtrPop( pMan->vStackReplaceNew ); + if ( Abc_ObjFanoutNum(pOld) == 0 ) + //return 0; + continue; Abc_AigReplace_int( pMan, pOld, pNew, fUpdateLevel ); } if ( fUpdateLevel ) @@ -867,6 +870,7 @@ void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int f if ( pMan->pNtkAig->vLevelsR ) Abc_AigUpdateLevelR_int( pMan ); } + return 1; } /**Function************************************************************* @@ -894,7 +898,20 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, i { if ( Abc_ObjIsCo(pFanout) ) { - Abc_ObjPatchFanin( pFanout, pOld, pNew ); + pFanin1 = Abc_ObjRegular( pNew ); + if ( pFanin1->fMarkB ) + Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanin1 ); + if ( fUpdateLevel && pMan->pNtkAig->vLevelsR ) + { + Abc_ObjSetReverseLevel( pFanin1, Abc_ObjReverseLevel(pOld) ); + assert( pFanin1->fMarkB == 0 ); + if ( !Abc_ObjIsCi(pFanin1) ) + { + pFanin1->fMarkB = 1; + Vec_VecPush( pMan->vLevelsR, Abc_ObjReverseLevel(pFanin1), pFanin1 ); + } + } + Abc_ObjPatchFanin( pFanout, pOld, pNew ); continue; } // find the old node as a fanin of this fanout diff --git a/abc/src/base/abc/abcCheck.c b/abc/src/base/abc/abcCheck.c index 3e978bf020f..c492b7093d7 100644 --- a/abc/src/base/abc/abcCheck.c +++ b/abc/src/base/abc/abcCheck.c @@ -177,7 +177,10 @@ int Abc_NtkDoCheck( Abc_Ntk_t * pNtk ) // check the nodes if ( Abc_NtkIsStrash(pNtk) ) - Abc_AigCheck( (Abc_Aig_t *)pNtk->pManFunc ); + { + if ( !Abc_AigCheck( (Abc_Aig_t *)pNtk->pManFunc ) ) + return 0; + } else { Abc_NtkForEachNode( pNtk, pNode, i ) @@ -865,7 +868,7 @@ int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk ) vNames = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) ); Abc_NtkForEachCi( pNtk, pObj, i ) Vec_PtrPush( vNames, Abc_ObjName(pObj) ); - Vec_PtrSort( vNames, (int (*)())Abc_NtkNamesCompare ); + Vec_PtrSort( vNames, (int (*)(const void *, const void *))Abc_NtkNamesCompare ); for ( i = 1; i < Abc_NtkCiNum(pNtk); i++ ) if ( !strcmp( (const char *)Vec_PtrEntry(vNames,i-1), (const char *)Vec_PtrEntry(vNames,i) ) ) { @@ -896,7 +899,7 @@ int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk ) vNames = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) Vec_PtrPush( vNames, Abc_ObjName(pObj) ); - Vec_PtrSort( vNames, (int (*)())Abc_NtkNamesCompare ); + Vec_PtrSort( vNames, (int (*)(const void *, const void *))Abc_NtkNamesCompare ); for ( i = 1; i < Abc_NtkCoNum(pNtk); i++ ) { // printf( "%s\n", Vec_PtrEntry(vNames,i) ); diff --git a/abc/src/base/abc/abcDfs.c b/abc/src/base/abc/abcDfs.c index 731d35f5ea1..a1345db8c4c 100644 --- a/abc/src/base/abc/abcDfs.c +++ b/abc/src/base/abc/abcDfs.c @@ -897,9 +897,9 @@ Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNod vNodes = Vec_PtrAlloc( 100 ); // go through the PO nodes and call for each of them for ( i = 0; i < nNodes; i++ ) - if ( Abc_ObjIsCo(ppNodes[i]) ) + if ( Abc_ObjIsCo(ppNodes[i]) && Abc_ObjFaninNum(Abc_ObjFanin0(ppNodes[i])) != 0 ) Abc_NtkNodeSupport_rec( Abc_ObjFanin0(ppNodes[i]), vNodes ); - else + else if ( !Abc_ObjIsCo(ppNodes[i]) && Abc_ObjFaninNum(ppNodes[i]) != 0 ) Abc_NtkNodeSupport_rec( ppNodes[i], vNodes ); return vNodes; } diff --git a/abc/src/base/abc/abcFanOrder.c b/abc/src/base/abc/abcFanOrder.c index bfd99f388fd..949170aa78b 100644 --- a/abc/src/base/abc/abcFanOrder.c +++ b/abc/src/base/abc/abcFanOrder.c @@ -66,7 +66,7 @@ void Abc_NtkOrderFaninsById( Abc_Ntk_t * pNtk ) Vec_IntSelectSortCost( pOrder, nVars, &pNode->vFanins ); // copy the cover Vec_StrGrow( vStore, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); - memcpy( Vec_StrArray(vStore), pSop, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); + memcpy( Vec_StrArray(vStore), pSop, (size_t)(Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1) ); pSopNew = pCubeNew = pSop; pSop = Vec_StrArray(vStore); // generate permuted one @@ -168,7 +168,7 @@ void Abc_NtkOrderFaninsBySortingColumns( Abc_Ntk_t * pNtk ) pOrder = Vec_IntArray(vOrder); // copy the cover Vec_StrGrow( vStore, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); - memcpy( Vec_StrArray(vStore), pSop, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); + memcpy( Vec_StrArray(vStore), pSop, (size_t)(Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1) ); pSopNew = pCubeNew = pSop; pSop = Vec_StrArray(vStore); // generate permuted one @@ -272,7 +272,7 @@ void Abc_NtkOrderFaninsByLitCount( Abc_Ntk_t * pNtk ) */ // copy the cover Vec_StrGrow( vStore, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); - memcpy( Vec_StrArray(vStore), pSop, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); + memcpy( Vec_StrArray(vStore), pSop, (size_t)(Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1) ); pSopNew = pCubeNew = pSop; pSop = Vec_StrArray(vStore); // generate permuted one @@ -353,7 +353,7 @@ void Abc_NtkOrderFaninsByLitCountAndCubeCount( Abc_Ntk_t * pNtk ) Vec_IntSelectSortCost( pOrder, nVars, vCounts ); // copy the cover Vec_StrGrow( vStore, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); - memcpy( Vec_StrArray(vStore), pSop, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); + memcpy( Vec_StrArray(vStore), pSop, (size_t)(Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1) ); pSopNew = pCubeNew = pSop; pSop = Vec_StrArray(vStore); // generate permuted one @@ -476,19 +476,19 @@ void Abc_NodeSortCubes( Abc_Obj_t * pNode, Vec_Ptr_t * vCubes, Vec_Str_t * vStor Vec_PtrPush( vCubes, pCube ); } if ( fWeight ) - Vec_PtrSort( vCubes, (int (*)())Abc_NodeCompareCubes2 ); + Vec_PtrSort( vCubes, (int (*)(const void *, const void *))Abc_NodeCompareCubes2 ); else - Vec_PtrSort( vCubes, (int (*)())Abc_NodeCompareCubes1 ); + Vec_PtrSort( vCubes, (int (*)(const void *, const void *))Abc_NodeCompareCubes1 ); Vec_StrGrow( vStore, Vec_PtrSize(vCubes) * (nVars + 3) ); pPivot = Vec_StrArray( vStore ); Vec_PtrForEachEntry( char *, vCubes, pCube, i ) { assert( pCube[nVars] == 0 ); pCube[nVars] = ' '; - memcpy( pPivot, pCube, nVars + 3 ); + memcpy( pPivot, pCube, (size_t)(nVars + 3) ); pPivot += nVars + 3; } - memcpy( pSop, Vec_StrArray(vStore), Vec_PtrSize(vCubes) * (nVars + 3) ); + memcpy( pSop, Vec_StrArray(vStore), (size_t)(Vec_PtrSize(vCubes) * (nVars + 3)) ); } void Abc_NtkSortCubes( Abc_Ntk_t * pNtk, int fWeight ) { @@ -550,7 +550,7 @@ static inline int Abc_CubeContain( char * pCube1, char * pCube2, int nVars ) fCont12 = 0; else return 0; - if ( !fCont21 && !fCont21 ) + if ( !fCont12 && !fCont21 ) return 0; } assert( fCont21 || fCont12 ); @@ -581,7 +581,7 @@ int Abc_NodeMakeSCCFree( Abc_Obj_t * pNode ) { if ( pCube[0] == 'z' ) continue; - memcpy( pSopNew, pCube, nVars + 3 ); + memcpy( pSopNew, pCube, (size_t)(nVars + 3) ); pSopNew += nVars + 3; } *pSopNew = 0; diff --git a/abc/src/base/abc/abcFanio.c b/abc/src/base/abc/abcFanio.c index caa57a4e3d7..519debb1f80 100644 --- a/abc/src/base/abc/abcFanio.c +++ b/abc/src/base/abc/abcFanio.c @@ -335,6 +335,30 @@ void Abc_ObjReplace( Abc_Obj_t * pNodeOld, Abc_Obj_t * pNodeNew ) Abc_NtkDeleteObj_rec( pNodeOld, 1 ); } +/**Function************************************************************* + + Synopsis [Replaces a node by a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjReplaceByConstant( Abc_Obj_t * pNode, int fConst1 ) +{ + Abc_Obj_t * pNodeNew; + assert( Abc_NtkIsLogic(pNode->pNtk) ); + assert( !Abc_ObjIsCo(pNode) ); + pNodeNew = fConst1 ? Abc_NtkCreateNodeConst1(pNode->pNtk) : Abc_NtkCreateNodeConst0(pNode->pNtk); + // transfer the fanouts to the old node + Abc_ObjTransferFanout( pNode, pNodeNew ); + // remove the old node + if ( Abc_ObjIsNode(pNode) ) + Abc_NtkDeleteObj_rec( pNode, 1 ); +} + /**Function************************************************************* Synopsis [Returns the index of the fanin in the fanin list of the fanout.] diff --git a/abc/src/base/abc/abcFunc.c b/abc/src/base/abc/abcFunc.c index 8f68d4be13d..805b91daa44 100644 --- a/abc/src/base/abc/abcFunc.c +++ b/abc/src/base/abc/abcFunc.c @@ -356,7 +356,7 @@ char * Abc_ConvertBddToSop( Mem_Flex_t * pMan, DdManager * dd, DdNode * bFuncOn, SeeAlso [] ***********************************************************************/ -int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit ) +int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit, int fCubeSort ) { Vec_Int_t * vGuide; Vec_Str_t * vCube; @@ -445,6 +445,7 @@ int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit ) Extra_StopManager( dd ); // reorder fanins and cubes to make SOPs more human-readable + if ( fCubeSort ) Abc_NtkSortSops( pNtk ); return 1; } @@ -788,7 +789,7 @@ DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot ) #else int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ) { return 1; } -int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit ) { return 1; } +int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit, int fCubeSort ) { return 1; } void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Mem_Flex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 ) {} void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ) {} int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ) { return 1; } @@ -1178,17 +1179,17 @@ int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit ) return 1; if ( !Abc_NtkSopToBdd(pNtk) ) return 0; - return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit); + return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit, 1); } if ( Abc_NtkHasMapping(pNtk) ) return Abc_NtkMapToSop(pNtk); if ( Abc_NtkHasBdd(pNtk) ) - return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit); + return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit, 1); if ( Abc_NtkHasAig(pNtk) ) { if ( !Abc_NtkAigToBdd(pNtk) ) return 0; - return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit); + return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit, 1); } assert( 0 ); return 0; @@ -1253,7 +1254,7 @@ int Abc_NtkToAig( Abc_Ntk_t * pNtk ) } if ( Abc_NtkHasBdd(pNtk) ) { - if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY) ) + if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 1) ) return 0; return Abc_NtkSopToAig(pNtk); } @@ -1264,6 +1265,42 @@ int Abc_NtkToAig( Abc_Ntk_t * pNtk ) } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjFaninSort( Abc_Obj_t * pObj ) +{ + Vec_Int_t * vFanins = Abc_ObjFaninVec( pObj ); + char * pCube, * pSop = (char*)pObj->pData; + int i, j, nVars = Abc_SopGetVarNum( pSop ); + assert( nVars == Vec_IntSize(vFanins) ); + for ( i = 0; i < Vec_IntSize(vFanins); i++ ) + for ( j = i+1; j < Vec_IntSize(vFanins); j++ ) + { + if ( Vec_IntEntry(vFanins, i) < Vec_IntEntry(vFanins, j) ) + continue; + ABC_SWAP( int, Vec_IntArray(vFanins)[i], Vec_IntArray(vFanins)[j] ); + for ( pCube = pSop; *pCube; pCube += nVars + 3 ) { + ABC_SWAP( char, pCube[i], pCube[j] ); + } + } +} +void Abc_NtkFaninSort( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; int i; + assert( Abc_NtkIsSopLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_ObjFaninSort( pObj ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/abc/src/base/abc/abcHie.c b/abc/src/base/abc/abcHie.c index 8397301fd3f..bd08c35d8d3 100644 --- a/abc/src/base/abc/abcHie.c +++ b/abc/src/base/abc/abcHie.c @@ -442,7 +442,7 @@ void Abc_NtkPrintBoxInfo( Abc_Ntk_t * pNtk ) } // sort models by name vMods = pNtk->pDesign->vModules; - Vec_PtrSort( vMods, (int(*)())Abc_NtkCompareNames ); + Vec_PtrSort( vMods, (int(*)(const void *, const void *))Abc_NtkCompareNames ); // Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) // printf( "%s\n", Abc_NtkName(pModel) ); diff --git a/abc/src/base/abc/abcHieNew.c b/abc/src/base/abc/abcHieNew.c index 0f191707209..54a61609f89 100644 --- a/abc/src/base/abc/abcHieNew.c +++ b/abc/src/base/abc/abcHieNew.c @@ -558,7 +558,7 @@ void Au_ManPrintBoxInfo( Au_Ntk_t * pNtk ) vMods->nSize--; vMods->pArray++; // sort models by name - Vec_PtrSort( vMods, (int(*)())Au_NtkCompareNames ); + Vec_PtrSort( vMods, (int(*)(const void *, const void *))Au_NtkCompareNames ); // swap the first model Num = Vec_PtrFind( vMods, pNtk ); assert( Num >= 0 && Num < Vec_PtrSize(vMods) ); @@ -643,7 +643,7 @@ void Au_ManPrintBoxInfoSorted( Au_Ntk_t * pNtk ) vMods->pArray--; vMods->nSize++; - Vec_PtrSort( vModsNew, (int(*)())Au_NtkCompareSign ); + Vec_PtrSort( vModsNew, (int(*)(const void *, const void *))Au_NtkCompareSign ); Vec_PtrForEachEntryStart( Au_Ntk_t *, vModsNew, pModel, i, 1 ) { printf( "MODULE " ); diff --git a/abc/src/base/abc/abcLatch.c b/abc/src/base/abc/abcLatch.c index fcace105176..653d855fe48 100644 --- a/abc/src/base/abc/abcLatch.c +++ b/abc/src/base/abc/abcLatch.c @@ -148,7 +148,7 @@ int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk ) void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches ) { Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj, * pLatch, * pFanin, * pFanout; + Abc_Obj_t * pObj, * pFanin, * pFanout; int i, k, nTotal, nDigits; if ( nLatches < 1 ) return; @@ -157,18 +157,9 @@ void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches ) vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachPi( pNtk, pObj, i ) { - // remember current fanins of the PI Abc_NodeCollectFanouts( pObj, vNodes ); - // create the latches - for ( pFanin = pObj, k = 0; k < nLatches; k++, pFanin = pLatch ) - { - pLatch = Abc_NtkCreateLatch( pNtk ); - Abc_ObjAddFanin( pLatch, pFanin ); - Abc_LatchSetInitDc( pLatch ); - // create the name of the new latch - Abc_ObjAssignName( pLatch, Abc_ObjNameDummy("LL", i*nLatches + k, nDigits), NULL ); - } - // patch the PI fanouts + for ( pFanin = pObj, k = 0; k < nLatches; k++ ) + pFanin = Abc_NtkAddLatch( pNtk, pFanin, ABC_INIT_ZERO ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pFanout, k ) Abc_ObjPatchFanin( pFanout, pObj, pFanin ); } @@ -435,7 +426,7 @@ Abc_Ntk_t * Abc_NtkConvertOnehot( Abc_Ntk_t * pNtk ) return Abc_NtkDup( pNtk ); if ( nFlops > 16 ) { - printf( "Cannot reencode %d flops because it will lead to 2^%d states.\n", nFlops, nFlops ); + printf( "Cannot re-encode %d flops because it will lead to 2^%d states.\n", nFlops, nFlops ); return NULL; } // check if there are latches with DC values diff --git a/abc/src/base/abc/abcMinBase.c b/abc/src/base/abc/abcMinBase.c index 22d1e285e91..92dbd0c9813 100644 --- a/abc/src/base/abc/abcMinBase.c +++ b/abc/src/base/abc/abcMinBase.c @@ -72,7 +72,7 @@ int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk ) SeeAlso [] ***********************************************************************/ -int Abc_NodeMinimumBase( Abc_Obj_t * pNode ) +int Abc_NodeMinimumBase_buggy( Abc_Obj_t * pNode ) { Vec_Str_t * vSupport; Vec_Ptr_t * vFanins; @@ -107,6 +107,72 @@ int Abc_NodeMinimumBase( Abc_Obj_t * pNode ) return 1; } +int Abc_NodeMinimumBase( Abc_Obj_t * pNode ) +{ + DdManager * dd = (DdManager *)pNode->pNtk->pManFunc; + DdNode * bTemp, ** pbVars; + Vec_Str_t * vSupport; + int i, nVars, j, iFanin, iFanin2, k = 0; + int ddSize, fDupFanins = 0; + + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + + // compute support + vSupport = Vec_StrAlloc( 10 ); + nVars = Abc_NodeSupport( Cudd_Regular(pNode->pData), vSupport, Abc_ObjFaninNum(pNode) ); + if ( nVars == Abc_ObjFaninNum(pNode) ) + { + Vec_StrFree( vSupport ); + return 0; + } + + // remove unused fanins. + + // By default, every BDD variable stays equivalent to itself. + ddSize = Cudd_ReadSize( dd ); + pbVars = ABC_CALLOC( DdNode *, ddSize ); + for (i = 0; i < ddSize; i += 1 ) { + pbVars[i] = Cudd_bddIthVar( dd, i ); + } + Vec_IntForEachEntry( &pNode->vFanins, iFanin, i ) + { + Abc_Obj_t * pFanin = Abc_NtkObj( pNode->pNtk, iFanin ); + if ( !Vec_StrEntry(vSupport, i) ) + { + if ( !Vec_IntRemove( &pFanin->vFanouts, pNode->Id ) ) + printf( "The obj %d is not found among the fanouts of obj %d ...\n", pNode->Id, iFanin ); + continue; + } + Vec_IntForEachEntryStop( &pNode->vFanins, iFanin2, j, k ) + if ( iFanin == iFanin2 ) + break; + fDupFanins |= (int)(j < k); + if ( j == k ) + Vec_IntWriteEntry( &pNode->vFanins, k++, iFanin ); + else if ( !Vec_IntRemove( &pFanin->vFanouts, pNode->Id ) ) + printf( "The obj %d is not found among the fanouts of obj %d ...\n", pNode->Id, iFanin ); + + // i-th variable becomes equivalent to j-th variable (can be itself) + pbVars[i] = Cudd_bddIthVar( dd, j ); + } + Vec_IntShrink( &pNode->vFanins, k ); + + // update the function of the node + if ( ! Cudd_IsConstant((DdNode *) pNode->pData ) ) { + pNode->pData = Cudd_bddVectorCompose( dd, bTemp = (DdNode *)pNode->pData, pbVars ); + Cudd_Ref( (DdNode *)pNode->pData ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Vec_StrFree( vSupport ); + ABC_FREE( pbVars ); + + // try again if node had duplicated fanins + if ( fDupFanins ) + Abc_NodeMinimumBase( pNode ); + return 1; +} + /**Function************************************************************* Synopsis [Makes nodes of the network fanin-dup-free.] @@ -447,7 +513,7 @@ int Abc_NtkEliminate( Abc_Ntk_t * pNtk, int nMaxSize, int fReverse, int fVerbose return 0; } // prepare nodes for sweeping - Abc_NtkRemoveDupFanins( pNtk ); + //Abc_NtkRemoveDupFanins( pNtk ); Abc_NtkMinimumBase( pNtk ); Abc_NtkCleanup( pNtk, 0 ); // get the nodes in the given order @@ -703,7 +769,7 @@ void Abc_ObjSortInReverseOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ) vOrder = Abc_NtkDfsReverse( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pNode, i ) pNode->iTemp = i; - Vec_PtrSort( vNodes, (int (*)())Abc_ObjCompareByNumber ); + Vec_PtrSort( vNodes, (int (*)(const void *, const void *))Abc_ObjCompareByNumber ); Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pNode, i ) pNode->iTemp = 0; Vec_PtrFree( vOrder ); @@ -740,7 +806,7 @@ int Abc_NtkEliminateSpecial( Abc_Ntk_t * pNtk, int nMaxSize, int fVerbose ) } // prepare nodes for sweeping - Abc_NtkRemoveDupFanins( pNtk ); + //Abc_NtkRemoveDupFanins( pNtk ); Abc_NtkMinimumBase( pNtk ); Abc_NtkCleanup( pNtk, 0 ); diff --git a/abc/src/base/abc/abcNames.c b/abc/src/base/abc/abcNames.c index b32093e97a6..dec5f01e0b0 100644 --- a/abc/src/base/abc/abcNames.c +++ b/abc/src/base/abc/abcNames.c @@ -334,13 +334,13 @@ void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb ) Abc_NtkForEachBox( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(Abc_ObjFanout0(pObj)); // order objects alphabetically - qsort( (void *)Vec_PtrArray(pNtk->vPis), Vec_PtrSize(pNtk->vPis), sizeof(Abc_Obj_t *), + qsort( (void *)Vec_PtrArray(pNtk->vPis), (size_t)Vec_PtrSize(pNtk->vPis), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareNames ); - qsort( (void *)Vec_PtrArray(pNtk->vPos), Vec_PtrSize(pNtk->vPos), sizeof(Abc_Obj_t *), + qsort( (void *)Vec_PtrArray(pNtk->vPos), (size_t)Vec_PtrSize(pNtk->vPos), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareNames ); // if the comparison if combinational (latches as PIs/POs), order them too if ( fComb ) - qsort( (void *)Vec_PtrArray(pNtk->vBoxes), Vec_PtrSize(pNtk->vBoxes), sizeof(Abc_Obj_t *), + qsort( (void *)Vec_PtrArray(pNtk->vBoxes), (size_t)Vec_PtrSize(pNtk->vBoxes), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareNames ); // order CIs/COs first PIs/POs(Asserts) then latches Abc_NtkOrderCisCos( pNtk ); @@ -428,14 +428,14 @@ void Abc_NtkTransferOrder( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ) Abc_NamDeref( pStrsCi ); Abc_NamDeref( pStrsCo ); // order PI/PO - qsort( (void *)Vec_PtrArray(pNtkNew->vPis), Vec_PtrSize(pNtkNew->vPis), sizeof(Abc_Obj_t *), + qsort( (void *)Vec_PtrArray(pNtkNew->vPis), (size_t)Vec_PtrSize(pNtkNew->vPis), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareIndexes ); - qsort( (void *)Vec_PtrArray(pNtkNew->vPos), Vec_PtrSize(pNtkNew->vPos), sizeof(Abc_Obj_t *), + qsort( (void *)Vec_PtrArray(pNtkNew->vPos), (size_t)Vec_PtrSize(pNtkNew->vPos), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareIndexes ); // order CI/CO - qsort( (void *)Vec_PtrArray(pNtkNew->vCis), Vec_PtrSize(pNtkNew->vCis), sizeof(Abc_Obj_t *), + qsort( (void *)Vec_PtrArray(pNtkNew->vCis), (size_t)Vec_PtrSize(pNtkNew->vCis), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareIndexes ); - qsort( (void *)Vec_PtrArray(pNtkNew->vCos), Vec_PtrSize(pNtkNew->vCos), sizeof(Abc_Obj_t *), + qsort( (void *)Vec_PtrArray(pNtkNew->vCos), (size_t)Vec_PtrSize(pNtkNew->vCos), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareIndexes ); // order CIs/COs first PIs/POs(Asserts) then latches //Abc_NtkOrderCisCos( pNtk ); @@ -606,6 +606,17 @@ void Abc_NtkShortNames( Abc_Ntk_t * pNtk ) Abc_NtkAddDummyPoNames( pNtk ); Abc_NtkAddDummyBoxNames( pNtk ); } +void Abc_NtkCleanNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; int i; + Nm_Man_t * pManName = Nm_ManCreate( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk) + Abc_NtkBoxNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Nm_ManStoreIdName( pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Nm_ManStoreIdName( pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + Nm_ManFree( pNtk->pManName ); + pNtk->pManName = pManName; +} /**Function************************************************************* diff --git a/abc/src/base/abc/abcNetlist.c b/abc/src/base/abc/abcNetlist.c index 0a5f623bb7b..8a2e9f184ed 100644 --- a/abc/src/base/abc/abcNetlist.c +++ b/abc/src/base/abc/abcNetlist.c @@ -216,10 +216,13 @@ Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ) // create the missing nets Abc_NtkForEachNode( pNtk, pObj, i ) { + char Buffer[1000]; if ( pObj->pCopy->pCopy ) // the net of the new object is already created continue; // create the new net - pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); // here we create ridiculous names net line "n48", where 48 is the ID of the node + sprintf( Buffer, "new_%s", Abc_ObjName(pObj) ); + //pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); // here we create net names such as "n48", where 48 is the ID of the node + pNet = Abc_NtkFindOrCreateNet( pNtkNew, Buffer ); Abc_ObjAddFanin( pNet, pObj->pCopy ); pObj->pCopy->pCopy = pNet; } diff --git a/abc/src/base/abc/abcNtk.c b/abc/src/base/abc/abcNtk.c index a62542b956d..2c8e03b34b3 100644 --- a/abc/src/base/abc/abcNtk.c +++ b/abc/src/base/abc/abcNtk.c @@ -1229,6 +1229,41 @@ Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) return pNtkNew; } +/**Function************************************************************* + + Synopsis [Creates the network composed of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateFromRange( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pNodeNew, * pNodePo; + Gia_Man_t * p = Abc_NtkClpGia( pNtk ); int i; + Vec_Str_t * vStr = Gia_ManComputeRange( p ); + Gia_ManStop( p ); + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + pNtkNew->pName = Extra_UtilStrsav("range"); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pObj), NULL ); + pNodeNew = Abc_NtkCreateObj( pNtkNew, ABC_OBJ_NODE ); + pNodeNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, Vec_StrArray(vStr) ); + Vec_StrFree( vStr ); + Abc_NtkForEachCi( pNtkNew, pObj, i ) + Abc_ObjAddFanin( pNodeNew, pObj ); + pNodePo = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pNodePo, pNodeNew ); + Abc_ObjAssignName( pNodePo, "range", NULL ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateFromNode(): Network check has failed.\n" ); + return pNtkNew; +} + /**Function************************************************************* Synopsis [Creates the network composed of one node with the given SOP.] @@ -1270,6 +1305,52 @@ Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ) return pNtkNew; } +/**Function************************************************************* + + Synopsis [Creates the network composed of one node with the given SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateWithNodes( Vec_Ptr_t * vSop ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pFanin, * pNode, * pNodePo; + Vec_Ptr_t * vNames; + int i, k, nVars; char Buffer[100]; + char * pSop = (char *)Vec_PtrEntry(vSop, 0); + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + pNtkNew->pName = Extra_UtilStrsav("ex"); + // create PIs + Vec_PtrPush( pNtkNew->vObjs, NULL ); + nVars = Abc_SopGetVarNum( pSop ); + vNames = Abc_NodeGetFakeNames( nVars ); + for ( i = 0; i < nVars; i++ ) + Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), (char *)Vec_PtrEntry(vNames, i), NULL ); + Abc_NodeFreeNames( vNames ); + // create the node, add PIs as fanins, set the function + Vec_PtrForEachEntry( char *, vSop, pSop, i ) + { + pNode = Abc_NtkCreateNode( pNtkNew ); + Abc_NtkForEachPi( pNtkNew, pFanin, k ) + Abc_ObjAddFanin( pNode, pFanin ); + pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, pSop ); + // create the only PO + pNodePo = Abc_NtkCreatePo(pNtkNew); + Abc_ObjAddFanin( pNodePo, pNode ); + sprintf( Buffer, "F%d", i ); + Abc_ObjAssignName( pNodePo, Buffer, NULL ); + } + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateWithNode(): Network check has failed.\n" ); + return pNtkNew; +} + /**Function************************************************************* Synopsis [Deletes the Ntk.] @@ -1286,6 +1367,7 @@ void Abc_NtkDelete( Abc_Ntk_t * pNtk ) Abc_Obj_t * pObj; void * pAttrMan; int TotalMemory, i; + int fWarning = 0; // int LargePiece = (4 << ABC_NUM_STEPS); if ( pNtk == NULL ) return; @@ -1310,9 +1392,11 @@ void Abc_NtkDelete( Abc_Ntk_t * pNtk ) // ABC_FREE( pObj->vFanouts.pArray ); // these flags should be always zero // if this is not true, something is wrong somewhere - assert( pObj->fMarkA == 0 ); - assert( pObj->fMarkB == 0 ); - assert( pObj->fMarkC == 0 ); +// assert( pObj->fMarkA == 0 ); +// assert( pObj->fMarkB == 0 ); +// assert( pObj->fMarkC == 0 ); + if ( !fWarning && (pObj->fMarkA || pObj->fMarkB || pObj->fMarkC) ) + { printf( "Flags A, B, or C are not zero.\n" ), fWarning = 1; } } // free the nodes if ( pNtk->pMmStep == NULL ) @@ -2091,7 +2175,7 @@ int Abc_NodeCompareByFanoutCount( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) void Abc_NtkPermutePiUsingFanout( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i; - qsort( (void *)Vec_PtrArray(pNtk->vPis), Vec_PtrSize(pNtk->vPis), sizeof(Abc_Obj_t *), + qsort( (void *)Vec_PtrArray(pNtk->vPis), (size_t)Vec_PtrSize(pNtk->vPis), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareByFanoutCount ); Vec_PtrClear( pNtk->vCis ); Vec_PtrForEachEntry( Abc_Obj_t *, pNtk->vPis, pNode, i ) @@ -2250,15 +2334,43 @@ Abc_Ntk_t * Abc_NtkCreateFromSops( char * pName, Vec_Ptr_t * vSops ) SeeAlso [] ***********************************************************************/ -Abc_Ntk_t * Abc_NtkCreateFromGias( char * pName, Vec_Ptr_t * vGias ) +Abc_Ntk_t * Abc_NtkCreateFromGias( char * pName, Vec_Ptr_t * vGias, Gia_Man_t * pMulti ) { - Gia_Man_t * pGia = (Gia_Man_t *)Vec_PtrEntry(vGias, 0); + Gia_Man_t * pGia = pMulti ? pMulti : (Gia_Man_t *)Vec_PtrEntry(vGias, 0); Abc_Ntk_t * pNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); Abc_Obj_t * pAbcObj, * pAbcObjPo; Gia_Obj_t * pObj; int i, k; pNtk->pName = Extra_UtilStrsav( pName ); for ( k = 0; k < Gia_ManCiNum(pGia); k++ ) Abc_NtkCreatePi( pNtk ); + if ( pMulti ) + { + Gia_ManCleanValue(pGia); + Gia_ManForEachCi( pGia, pObj, k ) + pObj->Value = Abc_ObjId( Abc_NtkCi(pNtk, k) ); + Gia_ManForEachAnd( pGia, pObj, k ) + { + Abc_Obj_t * pAbcObj0 = Abc_NtkObj( pNtk, Gia_ObjFanin0(pObj)->Value ); + Abc_Obj_t * pAbcObj1 = Abc_NtkObj( pNtk, Gia_ObjFanin1(pObj)->Value ); + pAbcObj0 = Abc_ObjNotCond( pAbcObj0, Gia_ObjFaninC0(pObj) ); + pAbcObj1 = Abc_ObjNotCond( pAbcObj1, Gia_ObjFaninC1(pObj) ); + pAbcObj = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pAbcObj0, pAbcObj1 ); + pObj->Value = Abc_ObjId( pAbcObj ); + } + Gia_ManForEachCo( pGia, pObj, k ) + { + //pObj = Gia_ManCo(pGia, 0); + if ( Gia_ObjFaninId0p(pGia, pObj) == 0 ) + pAbcObj = Abc_ObjNot( Abc_AigConst1(pNtk) ); + else + pAbcObj = Abc_NtkObj( pNtk, Gia_ObjFanin0(pObj)->Value ); + pAbcObj = Abc_ObjNotCond( pAbcObj, Gia_ObjFaninC0(pObj) ); + pAbcObjPo = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pAbcObjPo, pAbcObj ); + } + } + else + { Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) { assert( Gia_ManCoNum(pGia) == 1 ); @@ -2283,6 +2395,7 @@ Abc_Ntk_t * Abc_NtkCreateFromGias( char * pName, Vec_Ptr_t * vGias ) pAbcObjPo = Abc_NtkCreatePo( pNtk ); Abc_ObjAddFanin( pAbcObjPo, pAbcObj ); } + } Abc_NtkAddDummyPiNames( pNtk ); Abc_NtkAddDummyPoNames( pNtk ); return pNtk; diff --git a/abc/src/base/abc/abcObj.c b/abc/src/base/abc/abcObj.c index 533f1f735d3..65ea91dc562 100644 --- a/abc/src/base/abc/abcObj.c +++ b/abc/src/base/abc/abcObj.c @@ -393,6 +393,7 @@ Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName } else if ( Abc_ObjIsLatch(pObj) ) // copy the reset value pObjNew->pData = pObj->pData; + pObjNew->fPersist = pObj->fPersist; // transfer HAIG // pObjNew->pEquiv = pObj->pEquiv; // remember the new node in the old node diff --git a/abc/src/base/abc/abcRefs.c b/abc/src/base/abc/abcRefs.c index 26ae55abab8..4c5600c636c 100644 --- a/abc/src/base/abc/abcRefs.c +++ b/abc/src/base/abc/abcRefs.c @@ -405,7 +405,7 @@ Vec_Ptr_t * Abc_NodeMffcInsideCollect( Abc_Obj_t * pNode ) SeeAlso [] ***********************************************************************/ -void Abc_NodeMffcLabel_rec( Abc_Obj_t * pNode, int fTopmost ) +void Abc_NodeMffcLabel_rec( Abc_Obj_t * pNode, int fTopmost, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanin; int i; @@ -418,9 +418,11 @@ void Abc_NodeMffcLabel_rec( Abc_Obj_t * pNode, int fTopmost ) Abc_NodeSetTravIdCurrent(pNode); // recur on the children Abc_ObjForEachFanin( pNode, pFanin, i ) - Abc_NodeMffcLabel_rec( pFanin, 0 ); + Abc_NodeMffcLabel_rec( pFanin, 0, vNodes ); // collect the internal node // printf( "%d ", pNode->Id ); + if ( vNodes ) + Vec_PtrPush( vNodes, pNode ); } /**Function************************************************************* @@ -434,14 +436,14 @@ void Abc_NodeMffcLabel_rec( Abc_Obj_t * pNode, int fTopmost ) SeeAlso [] ***********************************************************************/ -int Abc_NodeMffcLabel( Abc_Obj_t * pNode ) +int Abc_NodeMffcLabel( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { int Count1, Count2; // dereference the node Count1 = Abc_NodeDeref_rec( pNode ); // collect the nodes inside the MFFC Abc_NtkIncrementTravId( pNode->pNtk ); - Abc_NodeMffcLabel_rec( pNode, 1 ); + Abc_NodeMffcLabel_rec( pNode, 1, vNodes ); // reference it back Count2 = Abc_NodeRef_rec( pNode ); assert( Count1 == Count2 ); diff --git a/abc/src/base/abc/abcShow.c b/abc/src/base/abc/abcShow.c index 13dd9346f48..efe10a49c1b 100644 --- a/abc/src/base/abc/abcShow.c +++ b/abc/src/base/abc/abcShow.c @@ -40,7 +40,7 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -extern void Abc_ShowFile( char * FileNameDot ); +extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); static void Abc_ShowGetFileName( char * pName, char * pBuffer ); //////////////////////////////////////////////////////////////////////// @@ -71,7 +71,7 @@ void Abc_NodeShowBddOne( DdManager * dd, DdNode * bFunc ) } Cudd_DumpDot( dd, 1, (DdNode **)&bFunc, NULL, NULL, pFile ); fclose( pFile ); - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); } /**Function************************************************************* @@ -85,12 +85,13 @@ void Abc_NodeShowBddOne( DdManager * dd, DdNode * bFunc ) SeeAlso [] ***********************************************************************/ -void Abc_NodeShowBdd( Abc_Obj_t * pNode ) +void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ) { FILE * pFile; Vec_Ptr_t * vNamesIn; char FileNameDot[200]; char * pNameOut; + DdManager * dd = (DdManager *)pNode->pNtk->pManFunc; assert( Abc_NtkIsBddLogic(pNode->pNtk) ); // create the file name @@ -105,17 +106,87 @@ void Abc_NodeShowBdd( Abc_Obj_t * pNode ) // set the node names vNamesIn = Abc_NodeGetFaninNames( pNode ); pNameOut = Abc_ObjName(pNode); - Cudd_DumpDot( (DdManager *)pNode->pNtk->pManFunc, 1, (DdNode **)&pNode->pData, (char **)vNamesIn->pArray, &pNameOut, pFile ); + if ( fCompl ) + Cudd_DumpDot( dd, 1, (DdNode **)&pNode->pData, (char **)vNamesIn->pArray, &pNameOut, pFile ); + else + { + DdNode * bAdd = Cudd_BddToAdd( dd, (DdNode *)pNode->pData ); Cudd_Ref( bAdd ); + Cudd_DumpDot( dd, 1, (DdNode **)&bAdd, (char **)vNamesIn->pArray, &pNameOut, pFile ); + Cudd_RecursiveDeref( dd, bAdd ); + } Abc_NodeFreeNames( vNamesIn ); Abc_NtkCleanCopy( pNode->pNtk ); fclose( pFile ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); +} +void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl, int fReorder ) +{ + char FileNameDot[200]; + char ** ppNamesIn, ** ppNamesOut; + DdManager * dd; DdNode * bFunc; + Vec_Ptr_t * vFuncsGlob; + Abc_Obj_t * pObj; int i; + FILE * pFile; + + assert( Abc_NtkIsStrash(pNtk) ); + dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, fReorder, 0, 0 ); + if ( dd == NULL ) + { + printf( "Construction of global BDDs has failed.\n" ); + return; + } + //printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + + // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) ); + + // create the file name + Abc_ShowGetFileName( pNtk->pName, FileNameDot ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + + // set the node names + ppNamesIn = Abc_NtkCollectCioNames( pNtk, 0 ); + ppNamesOut = Abc_NtkCollectCioNames( pNtk, 1 ); + if ( fCompl ) + Cudd_DumpDot( dd, Abc_NtkCoNum(pNtk), (DdNode **)Vec_PtrArray(vFuncsGlob), ppNamesIn, ppNamesOut, pFile ); + else + { + DdNode ** pbAdds = ABC_ALLOC( DdNode *, Vec_PtrSize(vFuncsGlob) ); + Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i ) + { pbAdds[i] = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( pbAdds[i] ); } + Cudd_DumpDot( dd, Abc_NtkCoNum(pNtk), pbAdds, ppNamesIn, ppNamesOut, pFile ); + Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i ) + Cudd_RecursiveDeref( dd, pbAdds[i] ); + ABC_FREE( pbAdds ); + } + ABC_FREE( ppNamesIn ); + ABC_FREE( ppNamesOut ); + fclose( pFile ); + + // cleanup + Abc_NtkFreeGlobalBdds( pNtk, 0 ); + Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vFuncsGlob ); + Extra_StopManager( dd ); + Abc_NtkCleanCopy( pNtk ); + + // visualize the file + Abc_ShowFile( FileNameDot, 0 ); } #else -void Abc_NodeShowBdd( Abc_Obj_t * pNode ) {} +void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ) {} +void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl, int fReorder ) {} #endif /**Function************************************************************* @@ -175,7 +246,7 @@ void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) Abc_NtkManCutStop( p ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); } /**Function************************************************************* @@ -189,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 ) +void Abc_NtkShow( Abc_Ntk_t * pNtk0, int fGateNames, int fSeq, int fUseReverse, int fKeepDot ) { FILE * pFile; Abc_Ntk_t * pNtk; @@ -236,7 +307,7 @@ void Abc_NtkShow( Abc_Ntk_t * pNtk0, int fGateNames, int fSeq, int fUseReverse ) Vec_PtrFree( vNodes ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, fKeepDot ); Abc_NtkDelete( pNtk ); } @@ -252,7 +323,7 @@ void Abc_NtkShow( Abc_Ntk_t * pNtk0, int fGateNames, int fSeq, int fUseReverse ) SeeAlso [] ***********************************************************************/ -void Abc_ShowFile( char * FileNameDot ) +void Abc_ShowFile( char * FileNameDot, int fKeepDot ) { FILE * pFile; char * FileGeneric; @@ -315,7 +386,7 @@ void Abc_ShowFile( char * FileNameDot ) // spawn the viewer #ifdef WIN32 - _unlink( FileNameDot ); + if ( !fKeepDot ) _unlink( FileNameDot ); if ( _spawnl( _P_NOWAIT, pGsNameWin, pGsNameWin, FileNamePs, NULL ) == -1 ) if ( _spawnl( _P_NOWAIT, "C:\\Program Files\\Ghostgum\\gsview\\gsview32.exe", "C:\\Program Files\\Ghostgum\\gsview\\gsview32.exe", FileNamePs, NULL ) == -1 ) @@ -328,7 +399,7 @@ void Abc_ShowFile( char * FileNameDot ) #else { char CommandPs[1000]; - unlink( FileNameDot ); + if ( !fKeepDot ) unlink( FileNameDot ); sprintf( CommandPs, "%s %s &", pGsNameUnix, FileNamePs ); if ( system( CommandPs ) == -1 ) { @@ -445,7 +516,7 @@ void Abc_NtkShowFlopDependency( Abc_Ntk_t * pNtk ) // write the DOT file Abc_NtkWriteFlopDependency( pNtk, FileNameDot ); // visualize the file - Abc_ShowFile( FileNameDot ); + Abc_ShowFile( FileNameDot, 0 ); } diff --git a/abc/src/base/abc/abcSop.c b/abc/src/base/abc/abcSop.c index af75897094a..f24c55593c2 100644 --- a/abc/src/base/abc/abcSop.c +++ b/abc/src/base/abc/abcSop.c @@ -81,7 +81,7 @@ char * Abc_SopStart( Mem_Flex_t * pMan, int nCubes, int nVars ) Length = nCubes * (nVars + 3); pSopCover = Mem_FlexEntryFetch( pMan, Length + 1 ); - memset( pSopCover, '-', Length ); + memset( pSopCover, '-', (size_t)Length ); pSopCover[Length] = 0; for ( i = 0; i < nCubes; i++ ) @@ -457,12 +457,21 @@ char * Abc_SopCreateFromIsop( Mem_Flex_t * pMan, int nVars, Vec_Int_t * vCover ) char * Abc_SopCreateFromTruthIsop( Mem_Flex_t * pMan, int nVars, word * pTruth, Vec_Int_t * vCover ) { char * pSop = NULL; - assert( nVars <= 6 ); - if ( pTruth[0] == 0 ) - pSop = Abc_SopRegister( pMan, " 0\n" ); - else if ( ~pTruth[0] == 0 ) - pSop = Abc_SopRegister( pMan, " 1\n" ); - else + int w, nWords = Abc_Truth6WordNum( nVars ); + assert( nVars < 16 ); + + for ( w = 0; w < nWords; w++ ) + if ( pTruth[w] ) + break; + if ( w == nWords ) + return Abc_SopRegister( pMan, " 0\n" ); + + for ( w = 0; w < nWords; w++ ) + if ( ~pTruth[w] ) + break; + if ( w == nWords ) + return Abc_SopRegister( pMan, " 1\n" ); + { int RetValue = Kit_TruthIsop( (unsigned *)pTruth, nVars, vCover, 1 ); assert( nVars > 0 ); @@ -898,6 +907,43 @@ int Abc_SopCheck( char * pSop, int nFanins ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopCheckReadTruth( Vec_Ptr_t * vRes, char * pToken, int fHex ) +{ + char * pBase; int nVars; + int Log2 = Abc_Base2Log( strlen(pToken) ); + if ( fHex && strlen(pToken) == 1 ) + Log2 = 0; + if ( (1 << Log2) != (int)strlen(pToken) ) + { + printf( "The truth table length (%d) is not power-of-2.\n", (int)strlen(pToken) ); + Vec_PtrFreeData( vRes ); + Vec_PtrShrink( vRes, 0 ); + return 0; + } + if ( Vec_PtrSize(vRes) == 0 ) + return 1; + pBase = (char *)Vec_PtrEntry( vRes, 0 ); + nVars = Abc_SopGetVarNum( pBase ); + if ( nVars != Log2+2*fHex ) + { + printf( "Truth table #1 has %d vars while truth table #%d has %d vars.\n", nVars, Vec_PtrSize(vRes)+1, Log2+2*fHex ); + Vec_PtrFreeData( vRes ); + Vec_PtrShrink( vRes, 0 ); + return 0; + } + return 1; +} /**Function************************************************************* @@ -940,33 +986,60 @@ char * Abc_SopFromTruthBin( char * pTruth ) if ( Digit == 1 ) Vec_IntPush( vMints, nTruthSize - 1 - i ); } +/* if ( Vec_IntSize( vMints ) == 0 || Vec_IntSize( vMints ) == nTruthSize ) { Vec_IntFree( vMints ); printf( "Cannot create constant function.\n" ); return NULL; } - - // create the SOP representation of the minterms - Length = Vec_IntSize(vMints) * (nVars + 3); - pSopCover = ABC_ALLOC( char, Length + 1 ); - pSopCover[Length] = 0; - Vec_IntForEachEntry( vMints, Mint, i ) +*/ + if ( Vec_IntSize(vMints) == 0 || Vec_IntSize(vMints) == (1 << nVars) ) { - pCube = pSopCover + i * (nVars + 3); - for ( b = 0; b < nVars; b++ ) - if ( Mint & (1 << (nVars-1-b)) ) -// if ( Mint & (1 << b) ) - pCube[b] = '1'; - else - pCube[b] = '0'; - pCube[nVars + 0] = ' '; - pCube[nVars + 1] = '1'; - pCube[nVars + 2] = '\n'; + pSopCover = ABC_ALLOC( char, 4 ); + pSopCover[0] = ' '; + pSopCover[1] = '0' + (Vec_IntSize(vMints) > 0); + pSopCover[2] = '\n'; + pSopCover[3] = 0; + } + else + { + // create the SOP representation of the minterms + Length = Vec_IntSize(vMints) * (nVars + 3); + pSopCover = ABC_ALLOC( char, Length + 1 ); + pSopCover[Length] = 0; + Vec_IntForEachEntry( vMints, Mint, i ) + { + pCube = pSopCover + i * (nVars + 3); + for ( b = 0; b < nVars; b++ ) + // if ( Mint & (1 << (nVars-1-b)) ) + if ( Mint & (1 << b) ) + pCube[b] = '1'; + else + pCube[b] = '0'; + pCube[nVars + 0] = ' '; + pCube[nVars + 1] = '1'; + pCube[nVars + 2] = '\n'; + } } Vec_IntFree( vMints ); return pSopCover; } +Vec_Ptr_t * Abc_SopFromTruthsBin( char * pTruth ) +{ + Vec_Ptr_t * vRes = Vec_PtrAlloc( 10 ); + char * pCopy = Abc_UtilStrsav(pTruth); + char * pToken = strtok( pCopy, " \r\n\t|" ); + while ( pToken ) + { + if ( !Abc_SopCheckReadTruth( vRes, pToken, 0 ) ) + break; + Vec_PtrPush( vRes, Abc_SopFromTruthBin(pToken) ); + pToken = strtok( NULL, " \r\n\t|" ); + } + ABC_FREE( pCopy ); + return vRes; +} /**Function************************************************************* @@ -1015,40 +1088,52 @@ char * Abc_SopFromTruthHex( char * pTruth ) } // create the SOP representation of the minterms - Length = Vec_IntSize(vMints) * (nVars + 3); - pSopCover = ABC_ALLOC( char, Length + 1 ); - pSopCover[Length] = 0; - Vec_IntForEachEntry( vMints, Mint, i ) + if ( Vec_IntSize(vMints) == 0 || Vec_IntSize(vMints) == (1 << nVars) ) { - pCube = pSopCover + i * (nVars + 3); - for ( b = 0; b < nVars; b++ ) -// if ( Mint & (1 << (nVars-1-b)) ) - if ( Mint & (1 << b) ) - pCube[b] = '1'; - else - pCube[b] = '0'; - pCube[nVars + 0] = ' '; - pCube[nVars + 1] = '1'; - pCube[nVars + 2] = '\n'; + pSopCover = ABC_ALLOC( char, 4 ); + pSopCover[0] = ' '; + pSopCover[1] = '0' + (Vec_IntSize(vMints) > 0); + pSopCover[2] = '\n'; + pSopCover[3] = 0; } -/* - // create TT representation + else { - extern void Bdc_ManDecomposeTest( unsigned uTruth, int nVars ); - unsigned uTruth = 0; - int nVarsAll = 4; - assert( nVarsAll == 4 ); - assert( nVars <= nVarsAll ); + Length = Vec_IntSize(vMints) * (nVars + 3); + pSopCover = ABC_ALLOC( char, Length + 1 ); + pSopCover[Length] = 0; Vec_IntForEachEntry( vMints, Mint, i ) - uTruth |= (1 << Mint); -// uTruth = uTruth | (uTruth << 8) | (uTruth << 16) | (uTruth << 24); - uTruth = uTruth | (uTruth << 16); - Bdc_ManDecomposeTest( uTruth, nVarsAll ); + { + pCube = pSopCover + i * (nVars + 3); + for ( b = 0; b < nVars; b++ ) + // if ( Mint & (1 << (nVars-1-b)) ) + if ( Mint & (1 << b) ) + pCube[b] = '1'; + else + pCube[b] = '0'; + pCube[nVars + 0] = ' '; + pCube[nVars + 1] = '1'; + pCube[nVars + 2] = '\n'; + } } -*/ + Vec_IntFree( vMints ); return pSopCover; } +Vec_Ptr_t * Abc_SopFromTruthsHex( char * pTruth ) +{ + Vec_Ptr_t * vRes = Vec_PtrAlloc( 10 ); + char * pCopy = Abc_UtilStrsav(pTruth); + char * pToken = strtok( pCopy, " \r\n\t|" ); + while ( pToken ) + { + if ( !Abc_SopCheckReadTruth( vRes, pToken, 1 ) ) + break; + Vec_PtrPush( vRes, Abc_SopFromTruthHex(pToken) ); + pToken = strtok( NULL, " \r\n\t|" ); + } + ABC_FREE( pCopy ); + return vRes; +} /**Function************************************************************* diff --git a/abc/src/base/abc/abcUtil.c b/abc/src/base/abc/abcUtil.c index a63abb9e088..88a16e7b629 100644 --- a/abc/src/base/abc/abcUtil.c +++ b/abc/src/base/abc/abcUtil.c @@ -2139,7 +2139,7 @@ void Abc_NtkCompareCones( Abc_Ntk_t * pNtk ) pSupps[i] = Vec_PtrSize(vSupp); Vec_PtrFree( vSupp ); } - qsort( (void *)pPerms, Abc_NtkCoNum(pNtk), sizeof(int), (int (*)(const void *, const void *)) Abc_NtkCompareConesCompare ); + qsort( (void *)pPerms, (size_t)Abc_NtkCoNum(pNtk), sizeof(int), (int (*)(const void *, const void *)) Abc_NtkCompareConesCompare ); // consider COs in this order Iter = 0; @@ -3122,7 +3122,10 @@ Vec_Wec_t * Abc_SopSynthesize( Vec_Ptr_t * vSops ) Abc_Obj_t * pObj, * pFanin; int i, k, iNode = 0; Abc_FrameReplaceCurrentNetwork( Abc_FrameReadGlobalFrame(), pNtk ); - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "fx; strash; balance; dc2; map -a" ); + //Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "fx; strash; balance; dc2; map -a" ); + Abc_FrameSetBatchMode( 1 ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "st; collapse; sop; fx; strash; &get; &ps; &deepsyn -I 4 -J 50 -T 5 -S 111 -t; &ps; &put; map -a" ); + Abc_FrameSetBatchMode( 0 ); pNtkNew = Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ); vRes = Vec_WecStart( Abc_NtkPiNum(pNtkNew) + Abc_NtkNodeNum(pNtkNew) + Abc_NtkPoNum(pNtkNew) ); Abc_NtkForEachPi( pNtkNew, pObj, i ) @@ -3141,15 +3144,17 @@ Vec_Wec_t * Abc_SopSynthesize( Vec_Ptr_t * vSops ) assert( Vec_WecSize(vRes) == iNode ); return vRes; } -Vec_Wec_t * Abc_GiaSynthesize( Vec_Ptr_t * vGias ) +Vec_Wec_t * Abc_GiaSynthesize( Vec_Ptr_t * vGias, Gia_Man_t * pMulti ) { Vec_Wec_t * vRes = NULL; - Abc_Ntk_t * pNtk = Abc_NtkCreateFromGias( "top", vGias ); + Abc_Ntk_t * pNtk = Abc_NtkCreateFromGias( "top", vGias, pMulti ); Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin; int i, k, iNode = 0; Abc_FrameReplaceCurrentNetwork( Abc_FrameReadGlobalFrame(), pNtk ); - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "compress2rs; dch; map -a; strash; compress2rs; dch; map -a; strash; compress2rs; dch; map -a" ); + Abc_FrameSetBatchMode( 1 ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "clp; sop; fx; strash; compress2rs; dch; map -a; strash; compress2rs; dch; map -a" ); + Abc_FrameSetBatchMode( 0 ); pNtkNew = Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ); vRes = Vec_WecStart( Abc_NtkPiNum(pNtkNew) + Abc_NtkNodeNum(pNtkNew) + Abc_NtkPoNum(pNtkNew) ); Abc_NtkForEachPi( pNtkNew, pObj, i ) @@ -3173,7 +3178,7 @@ Gia_Man_t * Abc_GiaSynthesizeInter( Gia_Man_t * p ) Abc_Ntk_t * pNtkNew, * pNtk; Vec_Ptr_t * vGias = Vec_PtrAlloc( 1 ); Vec_PtrPush( vGias, p ); - pNtk = Abc_NtkCreateFromGias( "top", vGias ); + pNtk = Abc_NtkCreateFromGias( "top", vGias, NULL ); Vec_PtrFree( vGias ); Abc_FrameReplaceCurrentNetwork( Abc_FrameReadGlobalFrame(), pNtk ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "balance; collapse; muxes; strash; dc2" ); @@ -3253,13 +3258,100 @@ Gia_Man_t * Abc_SopSynthesizeOne( char * pSop, int fClp ) pNtk = Abc_NtkCreateFromSops( "top", vSops ); Vec_PtrFree( vSops ); Abc_FrameReplaceCurrentNetwork( Abc_FrameReadGlobalFrame(), pNtk ); + Abc_FrameSetBatchMode( 1 ); if ( fClp ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "clp; sop" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "fx; strash; balance; dc2" ); + Abc_FrameSetBatchMode( 0 ); pNtkNew = Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ); return Abc_NtkStrashToGia( pNtkNew ); } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int s_ArraySize = 145; +static int s_ArrayData[290] = { + 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 6, 14, 12, 10, 2, 22, 20, 2, 24, 16, 4, 28, 18, 16, 10, 8, 4, 34, 32, 30, 36, 38, 26, 16, 6, 36, 20, 44, 42, 46, 40, 42, 44, 14, 6, 52, 34, 32, 54, 56, 50, 58, 48, 32, 24, 20, 2, 12, 6, 66, 34, 68, 64, 62, 70, 28, 68, 74, 72, 76, 58, 70, 62, 80, 78, 68, 28, 84, 74, 4, 2, 88, 20, 64, 90, 92, 86, 66, 32, 18, 96, 98, 56, 100, 94, 52, 36, 104, 38, 90, 42, 36, 2, 108, 110, 112, 106, 114, 100, 102, 116, 118, 82, 116, 60, 120, 122, 124, 60, 118, 60, 102, 82, 128, 130, 132, 82, 134, 126, 82, 116, 122, 138, 122, 118, 142, 140, 60, 102, 130, 146, 130, 118, 150, 148, 152, 144, 154, 136, 18, 156, 144, 126, 68, 160, 32, 136, 164, 162, 166, 158, 28, 160, 70, 126, 90, 144, 174, 172, 176, 170, 152, 134, 36, 180, 2, 134, 184, 182, 186, 178, 188, 168, 64, 144, 164, 158, 194, 192, 96, 156, 44, 154, 200, 170, 202, 198, 204, 176, 206, 196, 204, 168, 62, 126, 212, 186, 24, 134, 108, 152, 218, 192, 220, 216, 222, 214, 224, 210, 220, 194, 110, 152, 30, 180, 232, 230, 184, 172, 236, 234, 238, 228, 234, 182, 242, 220, 244, 168, 42, 154, 248, 202, 54, 136, 252, 164, 254, 214, 256, 250, 218, 194, 252, 198, 262, 242, 264, 260, 232, 220, 268, 262, 270, 168, + 191, 191, 209, 209, 226, 226, 240, 240, 246, 246, 259, 259, 267, 267, 272, 272, +}; +int Abc_NtkHasConstNode() +{ + int i; + for ( i = 1; i < s_ArraySize; i++ ) + if ( s_ArrayData[2*i] || s_ArrayData[2*i+1] ) + break; + for ( ; i < s_ArraySize; i++ ) + if ( s_ArrayData[2*i] < 2 && s_ArrayData[2*i+1] < 2 ) + return 1; + return 0; +} +Abc_Ntk_t * Abc_NtkFromArray() +{ + Vec_Ptr_t * vNodes = Vec_PtrAlloc( s_ArraySize ); int i, nPos = 0; + Abc_Ntk_t * pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + Abc_Obj_t * pObjNew = Abc_NtkHasConstNode() ? Abc_NtkCreateNode(pNtkNew) : NULL; + if ( pObjNew ) pObjNew->pData = Abc_SopCreateConst0((Mem_Flex_t *)pNtkNew->pManFunc); + Vec_PtrPush( vNodes, pObjNew ); + for ( i = 1; i < s_ArraySize; i++ ) + if ( !s_ArrayData[2*i] && !s_ArrayData[2*i+1] ) + Vec_PtrPush( vNodes, Abc_NtkCreatePi(pNtkNew) ); + else + break; + for ( ; i < s_ArraySize; i++ ) + { + char * pSop = NULL; + if ( s_ArrayData[2*i] > s_ArrayData[2*i+1] ) + pSop = Abc_SopCreateXor( (Mem_Flex_t *)pNtkNew->pManFunc, 2 ); + else if ( s_ArrayData[2*i] < s_ArrayData[2*i+1] ) + pSop = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, 2, NULL ); + else + break; + pObjNew = Abc_NtkCreateNode( pNtkNew ); + Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Vec_PtrEntry(vNodes, Abc_Lit2Var(s_ArrayData[2*i])) ); + Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Vec_PtrEntry(vNodes, Abc_Lit2Var(s_ArrayData[2*i+1])) ); + if ( Abc_LitIsCompl(s_ArrayData[2*i]) ) Abc_SopComplementVar( pSop, 0 ); + if ( Abc_LitIsCompl(s_ArrayData[2*i+1]) ) Abc_SopComplementVar( pSop, 1 ); + pObjNew->pData = pSop; + Vec_PtrPush( vNodes, pObjNew ); + } + for ( ; i < s_ArraySize; i++ ) + { + char * pSop = NULL; + assert( s_ArrayData[2*i] == s_ArrayData[2*i+1] ); + pObjNew = Abc_NtkCreateNode( pNtkNew ); + Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Vec_PtrEntry(vNodes, Abc_Lit2Var(s_ArrayData[2*i])) ); + if ( Abc_LitIsCompl(s_ArrayData[2*i]) ) + pSop = Abc_SopCreateInv( (Mem_Flex_t *)pNtkNew->pManFunc ); + else + pSop = Abc_SopCreateBuf( (Mem_Flex_t *)pNtkNew->pManFunc ); + pObjNew->pData = pSop; + Vec_PtrPush( vNodes, pObjNew ); + nPos++; + } + for ( i = 0; i < nPos; i++ ) + Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), (Abc_Obj_t *)Vec_PtrEntry(vNodes, s_ArraySize-nPos+i) ); + Vec_PtrFree( vNodes ); + pNtkNew->pName = Extra_UtilStrsav("test"); + Abc_NtkAddDummyPiNames( pNtkNew ); + Abc_NtkAddDummyPoNames( pNtkNew ); + Abc_NtkAddDummyBoxNames( pNtkNew ); + if ( !Abc_NtkCheck( pNtkNew ) ) + Abc_Print( 1, "Abc_NtkFromArray(): Network check has failed.\n" ); + return pNtkNew; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/abc/src/base/abci/abc.c b/abc/src/base/abci/abc.c index 83797ec72f9..e8666788297 100644 --- a/abc/src/base/abci/abc.c +++ b/abc/src/base/abci/abc.c @@ -63,6 +63,7 @@ #include "opt/fret/fretime.h" #include "opt/nwk/nwkMerge.h" #include "base/acb/acbPar.h" +#include "misc/extra/extra.h" #ifndef _WIN32 @@ -86,6 +87,9 @@ static int Abc_CommandPrintMffc ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandPrintFactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintLevel ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintSupport ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#ifdef ABC_USE_CUDD +static int Abc_CommandPrintMint ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#endif static int Abc_CommandPrintSymms ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintUnate ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintAuto ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -134,12 +138,16 @@ static int Abc_CommandMerge ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandTestDec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestNpn ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestRPO ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandTestRun ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTestTruth ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRunEco ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRunGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRunTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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_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_CommandExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -154,10 +162,13 @@ static int Abc_CommandTwoExact ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandLutExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAllExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMajGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandOrchestrate ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandComb ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMiter2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDemiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandOrPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAndPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -184,7 +195,10 @@ static int Abc_CommandExtSeqDcs ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandReach ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCone ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandNode ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRange ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCof ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTopmost ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBottommost ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTopAnd ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTrim ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -311,9 +325,12 @@ static int Abc_CommandSynch ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandClockGate ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExtWin ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandInsWin ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSymFun ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPermute ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandUnpermute ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCubeEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPathEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFunEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -324,6 +341,7 @@ static int Abc_CommandXSat ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandSatoko ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Satoko ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Sat3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Kissat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandIProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -362,8 +380,12 @@ static int Abc_CommandIso ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandTraceStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTraceCheck ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbcSave ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbcLoad ( Abc_Frame_t * pAbc, int argc, char ** argv ); + static int Abc_CommandAbc9Get ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Put ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MoveNames ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Save ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Save2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SaveAig ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -383,6 +405,10 @@ static int Abc_CommandAbc9PFan ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9PSig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Status ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9MuxProfile ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MuxPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MuxStr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MuxDec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9PrintTruth ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Unate ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Rex2Gia ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9RexWalk ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -395,7 +421,16 @@ static int Abc_CommandAbc9Cof ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Trim ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Dfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Sim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Sim2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Sim3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MLGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MLTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Iwls21Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ReadSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9WriteSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9PrintSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SimRsb ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Resim ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SpecI ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Equiv ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -411,8 +446,11 @@ static int Abc_CommandAbc9Dsd ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Bidec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Shrink ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Fx ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Extract ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Balance ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9BalanceLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Resub ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Reshape ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Syn2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Syn3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Syn4 ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -436,6 +474,7 @@ static int Abc_CommandAbc9Reduce ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9EquivMark ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9EquivFilter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Cec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ICec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Verify ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Sweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Force ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -449,6 +488,7 @@ static int Abc_CommandAbc9If ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Iff ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Iiff ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9If2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Sif ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Jf ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Kf ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Lf ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -458,6 +498,16 @@ static int Abc_CommandAbc9Of ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Pack ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Edge ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SatLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9LNetRead ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9LNetSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9LNetEval ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9LNetOpt ( Abc_Frame_t * pAbc, int argc, char ** argv ); +//#ifndef _WIN32 +static int Abc_CommandAbc9Ttopt ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Transduction ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9TranStoch ( Abc_Frame_t * pAbc, int argc, char ** argv ); +//#endif +static int Abc_CommandAbc9LNetMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Unmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Struct ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Trace ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -467,6 +517,7 @@ static int Abc_CommandAbc9Dch ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Rpm ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9BackReach ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Posplit ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Permute ( Abc_Frame_t * pAbc, int argc, char ** argv ); #ifdef ABC_USE_CUDD static int Abc_CommandAbc9ReachM ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9ReachP ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -478,6 +529,9 @@ static int Abc_CommandAbc9Mesh ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Iso ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9IsoNpn ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9IsoSt ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Compare ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9RevEng ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Uif ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9CexInfo ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Cycle ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Cone ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -486,6 +540,7 @@ static int Abc_CommandAbc9PoPart ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9GroupProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9MultiProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SplitProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SplitSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Bmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SBmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9ChainBmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -496,6 +551,7 @@ static int Abc_CommandAbc9FFTest ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Qbf ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9QVar ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenQbf ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9HomoQbf ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SatFx ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SatClp ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Inse ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -513,11 +569,15 @@ static int Abc_CommandAbc9Esop ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Exorcism ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Mfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Mfsd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9DeepSyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SatSyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9StochSyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandAbc9PoPart2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandAbc9CexCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandAbc9CexMerge ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandAbc9CexMin ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9AbsCreate ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9AbsDerive ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9AbsRefine ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GlaDerive ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -530,6 +590,12 @@ static int Abc_CommandAbc9Gla2Vta ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandAbc9Fla2Gla ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Gla2Fla ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Gen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Cfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ProdAdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +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_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); extern int Abc_CommandAbcLivenessToSafety ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -541,6 +607,11 @@ extern int Abc_CommandNChooseK ( Abc_Frame_t * pAbc, int argc, cha extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); +extern Vec_Ptr_t * Abc_NtkCollectCiNames( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkCollectCoNames( Abc_Ntk_t * pNtk ); + +extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -655,6 +726,25 @@ Vec_Int_t * Abc_FrameDeriveStatusArray( Vec_Ptr_t * vCexes ) Vec_IntWriteEntry( vStatuses, i, 0 ); // set this output as SAT return vStatuses; } +Vec_Int_t * Abc_FrameDeriveStatusArray2( Vec_Ptr_t * vCexes ) +{ + Vec_Int_t * vStatuses; + Abc_Cex_t * pCex; + int i; + if ( vCexes == NULL ) + return NULL; + vStatuses = Vec_IntAlloc( Vec_PtrSize(vCexes) ); + Vec_IntFill( vStatuses, Vec_PtrSize(vCexes), -1 ); // assume UNDEC + Vec_PtrForEachEntry( Abc_Cex_t *, vCexes, pCex, i ) + if ( pCex == (Abc_Cex_t *)(ABC_PTRINT_T)1 ) + { + Vec_IntWriteEntry( vStatuses, i, 1 ); // set this output as UNSAT + Vec_PtrWriteEntry( vCexes, i, NULL ); + } + else if ( pCex != NULL ) + Vec_IntWriteEntry( vStatuses, i, 0 ); // set this output as SAT + return vStatuses; +} /**Function************************************************************* @@ -686,7 +776,7 @@ void Abc_FrameUpdateGia( Abc_Frame_t * pAbc, Gia_Man_t * pNew ) { if ( pNew == NULL ) { - Abc_Print( -1, "Abc_FrameUpdateGia(): Tranformation has failed.\n" ); + Abc_Print( -1, "Abc_FrameUpdateGia(): Transformation has failed.\n" ); return; } if ( Gia_ManPoNum(pNew) == 0 ) @@ -704,6 +794,11 @@ void Abc_FrameUpdateGia( Abc_Frame_t * pAbc, Gia_Man_t * pNew ) pNew->vNamesOut = pAbc->pGia->vNamesOut; pAbc->pGia->vNamesOut = NULL; } + if (!pNew->vNamesNode && pAbc->pGia && pAbc->pGia->vNamesNode && Gia_ManObjNum(pNew) == Vec_PtrSize(pAbc->pGia->vNamesNode)) + { + pNew->vNamesNode = pAbc->pGia->vNamesNode; + pAbc->pGia->vNamesNode = NULL; + } // update if ( pAbc->pGia2 ) Gia_ManStop( pAbc->pGia2 ); @@ -756,6 +851,9 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Printing", "print_factor", Abc_CommandPrintFactor, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_level", Abc_CommandPrintLevel, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_supp", Abc_CommandPrintSupport, 0 ); +#ifdef ABC_USE_CUDD + Cmd_CommandAdd( pAbc, "Printing", "print_mint", Abc_CommandPrintMint, 0 ); +#endif Cmd_CommandAdd( pAbc, "Printing", "print_symm", Abc_CommandPrintSymms, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_unate", Abc_CommandPrintUnate, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_auto", Abc_CommandPrintAuto, 0 ); @@ -804,18 +902,23 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "testdec", Abc_CommandTestDec, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "testnpn", Abc_CommandTestNpn, 0 ); Cmd_CommandAdd( pAbc, "LogiCS", "testrpo", Abc_CommandTestRPO, 0 ); - Cmd_CommandAdd( pAbc, "Synthesis", "testrun", Abc_CommandTestRun, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "testtruth", Abc_CommandTestTruth, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "runeco", Abc_CommandRunEco, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "rungen", Abc_CommandRunGen, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "xec", Abc_CommandRunTest, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "rewrite", Abc_CommandRewrite, 1 ); 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_check", Abc_CommandResubCheck, 0 ); // Cmd_CommandAdd( pAbc, "Synthesis", "rr", Abc_CommandRr, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 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 ); Cmd_CommandAdd( pAbc, "Synthesis", "exact", Abc_CommandExact, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "orchestrate", Abc_CommandOrchestrate, 1 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_start", Abc_CommandBmsStart, 0 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_stop", Abc_CommandBmsStop, 0 ); @@ -825,10 +928,12 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Exact synthesis", "lutexact", Abc_CommandLutExact, 0 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "allexact", Abc_CommandAllExact, 0 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "testexact", Abc_CommandTestExact, 0 ); + Cmd_CommandAdd( pAbc, "Exact synthesis", "majgen", Abc_CommandMajGen, 0 ); Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 ); Cmd_CommandAdd( pAbc, "Various", "comb", Abc_CommandComb, 1 ); Cmd_CommandAdd( pAbc, "Various", "miter", Abc_CommandMiter, 1 ); + Cmd_CommandAdd( pAbc, "Various", "miter2", Abc_CommandMiter2, 1 ); Cmd_CommandAdd( pAbc, "Various", "demiter", Abc_CommandDemiter, 1 ); Cmd_CommandAdd( pAbc, "Various", "orpos", Abc_CommandOrPos, 1 ); Cmd_CommandAdd( pAbc, "Various", "andpos", Abc_CommandAndPos, 1 ); @@ -855,8 +960,11 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Various", "reach", Abc_CommandReach, 0 ); Cmd_CommandAdd( pAbc, "Various", "cone", Abc_CommandCone, 1 ); Cmd_CommandAdd( pAbc, "Various", "node", Abc_CommandNode, 1 ); + Cmd_CommandAdd( pAbc, "Various", "range", Abc_CommandRange, 1 ); + Cmd_CommandAdd( pAbc, "Various", "cof", Abc_CommandCof, 1 ); Cmd_CommandAdd( pAbc, "Various", "topmost", Abc_CommandTopmost, 1 ); - Cmd_CommandAdd( pAbc, "Various", "topand", Abc_CommandTopAnd, 1 ); + Cmd_CommandAdd( pAbc, "Various", "bottommost", Abc_CommandBottommost, 1 ); + Cmd_CommandAdd( pAbc, "Various", "topand", Abc_CommandTopAnd, 1 ); Cmd_CommandAdd( pAbc, "Various", "trim", Abc_CommandTrim, 1 ); Cmd_CommandAdd( pAbc, "Various", "short_names", Abc_CommandShortNames, 0 ); Cmd_CommandAdd( pAbc, "Various", "move_names", Abc_CommandMoveNames, 0 ); @@ -955,7 +1063,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Sequential", "zero", Abc_CommandZero, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "undc", Abc_CommandUndc, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "onehot", Abc_CommandOneHot, 1 ); -// Cmd_CommandAdd( pAbc, "Sequential", "pipe", Abc_CommandPipe, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "pipe", Abc_CommandPipe, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "retime", Abc_CommandRetime, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "dretime", Abc_CommandDRetime, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "fretime", Abc_CommandFlowRetime, 1 ); @@ -977,9 +1085,12 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Sequential", "clockgate", Abc_CommandClockGate, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "extwin", Abc_CommandExtWin, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "inswin", Abc_CommandInsWin, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "symfun", Abc_CommandSymFun, 0 ); Cmd_CommandAdd( pAbc, "Sequential", "permute", Abc_CommandPermute, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "unpermute", Abc_CommandUnpermute, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "cubeenum", Abc_CommandCubeEnum, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "pathenum", Abc_CommandPathEnum, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "funenum", Abc_CommandFunEnum, 0 ); Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 ); Cmd_CommandAdd( pAbc, "Verification", "dcec", Abc_CommandDCec, 0 ); @@ -994,6 +1105,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Verification", "satoko", Abc_CommandSatoko, 0 ); Cmd_CommandAdd( pAbc, "Verification", "&satoko", Abc_CommandAbc9Satoko, 0 ); Cmd_CommandAdd( pAbc, "Verification", "&sat3", Abc_CommandAbc9Sat3, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "&kissat", Abc_CommandAbc9Kissat, 0 ); Cmd_CommandAdd( pAbc, "Verification", "psat", Abc_CommandPSat, 0 ); Cmd_CommandAdd( pAbc, "Verification", "prove", Abc_CommandProve, 1 ); Cmd_CommandAdd( pAbc, "Verification", "iprove", Abc_CommandIProve, 1 ); @@ -1029,8 +1141,12 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Verification", "blockpo", Abc_CommandBlockPo, 1 ); Cmd_CommandAdd( pAbc, "Verification", "iso", Abc_CommandIso, 1 ); + Cmd_CommandAdd( pAbc, "Various", "save", Abc_CommandAbcSave, 0 ); + Cmd_CommandAdd( pAbc, "Various", "load", Abc_CommandAbcLoad, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&get", Abc_CommandAbc9Get, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&put", Abc_CommandAbc9Put, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&move_names", Abc_CommandAbc9MoveNames, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&save", Abc_CommandAbc9Save, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&save2", Abc_CommandAbc9Save2, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&saveaig", Abc_CommandAbc9SaveAig, 0 ); @@ -1052,6 +1168,10 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&psig", Abc_CommandAbc9PSig, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&status", Abc_CommandAbc9Status, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&profile", Abc_CommandAbc9MuxProfile, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&muxpos", Abc_CommandAbc9MuxPos, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&muxstr", Abc_CommandAbc9MuxStr, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&muxdec", Abc_CommandAbc9MuxDec, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&print_truth", Abc_CommandAbc9PrintTruth, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&unate", Abc_CommandAbc9Unate, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&rex2gia", Abc_CommandAbc9Rex2Gia, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&rexwalk", Abc_CommandAbc9RexWalk, 0 ); @@ -1064,7 +1184,16 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&trim", Abc_CommandAbc9Trim, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&dfs", Abc_CommandAbc9Dfs, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sim", Abc_CommandAbc9Sim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sim2", Abc_CommandAbc9Sim2, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sim3", Abc_CommandAbc9Sim3, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&mlgen", Abc_CommandAbc9MLGen, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&mltest", Abc_CommandAbc9MLTest, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&iwls21test", Abc_CommandAbc9Iwls21Test, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sim_read", Abc_CommandAbc9ReadSim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sim_write", Abc_CommandAbc9WriteSim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sim_print", Abc_CommandAbc9PrintSim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sim_gen", Abc_CommandAbc9GenSim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&simrsb", Abc_CommandAbc9SimRsb, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&resim", Abc_CommandAbc9Resim, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&speci", Abc_CommandAbc9SpecI, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&equiv", Abc_CommandAbc9Equiv, 0 ); @@ -1080,8 +1209,11 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&bidec", Abc_CommandAbc9Bidec, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&shrink", Abc_CommandAbc9Shrink, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&fx", Abc_CommandAbc9Fx, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&extract", Abc_CommandAbc9Extract, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&b", Abc_CommandAbc9Balance, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&blut", Abc_CommandAbc9BalanceLut, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&resub", Abc_CommandAbc9Resub, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&reshape", Abc_CommandAbc9Reshape, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&syn2", Abc_CommandAbc9Syn2, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&syn3", Abc_CommandAbc9Syn3, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&syn4", Abc_CommandAbc9Syn4, 0 ); @@ -1105,6 +1237,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&equiv_mark", Abc_CommandAbc9EquivMark, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&equiv_filter", Abc_CommandAbc9EquivFilter, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cec", Abc_CommandAbc9Cec, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&icec", Abc_CommandAbc9ICec, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&verify", Abc_CommandAbc9Verify, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sweep", Abc_CommandAbc9Sweep, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&force", Abc_CommandAbc9Force, 0 ); @@ -1118,6 +1251,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&iff", Abc_CommandAbc9Iff, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&iiff", Abc_CommandAbc9Iiff, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&if2", Abc_CommandAbc9If2, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sif", Abc_CommandAbc9Sif, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&jf", Abc_CommandAbc9Jf, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&kf", Abc_CommandAbc9Kf, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&lf", Abc_CommandAbc9Lf, 0 ); @@ -1127,6 +1261,16 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&pack", Abc_CommandAbc9Pack, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&edge", Abc_CommandAbc9Edge, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&satlut", Abc_CommandAbc9SatLut, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&lnetread", Abc_CommandAbc9LNetRead, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&lnetsim", Abc_CommandAbc9LNetSim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&lneteval", Abc_CommandAbc9LNetEval, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&lnetopt", Abc_CommandAbc9LNetOpt, 0 ); +//#ifndef _WIN32 + Cmd_CommandAdd( pAbc, "ABC9", "&ttopt", Abc_CommandAbc9Ttopt, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&transduction", Abc_CommandAbc9Transduction, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&transtoch" , Abc_CommandAbc9TranStoch, 0 ); +//#endif + Cmd_CommandAdd( pAbc, "ABC9", "&lnetmap", Abc_CommandAbc9LNetMap, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&unmap", Abc_CommandAbc9Unmap, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&struct", Abc_CommandAbc9Struct, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&trace", Abc_CommandAbc9Trace, 0 ); @@ -1136,6 +1280,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&rpm", Abc_CommandAbc9Rpm, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&back_reach", Abc_CommandAbc9BackReach, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&posplit", Abc_CommandAbc9Posplit, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&permute", Abc_CommandAbc9Permute, 0 ); #ifdef ABC_USE_CUDD Cmd_CommandAdd( pAbc, "ABC9", "&reachm", Abc_CommandAbc9ReachM, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&reachp", Abc_CommandAbc9ReachP, 0 ); @@ -1147,6 +1292,9 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&iso", Abc_CommandAbc9Iso, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&isonpn", Abc_CommandAbc9IsoNpn, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&isost", Abc_CommandAbc9IsoSt, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&compare", Abc_CommandAbc9Compare, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&reveng", Abc_CommandAbc9RevEng, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&uif", Abc_CommandAbc9Uif, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cexinfo", Abc_CommandAbc9CexInfo, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cycle", Abc_CommandAbc9Cycle, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cone", Abc_CommandAbc9Cone, 0 ); @@ -1155,6 +1303,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&gprove", Abc_CommandAbc9GroupProve, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&mprove", Abc_CommandAbc9MultiProve, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&splitprove", Abc_CommandAbc9SplitProve, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&splitsat", Abc_CommandAbc9SplitSat, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&bmc", Abc_CommandAbc9Bmc, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&bmcs", Abc_CommandAbc9SBmc, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&chainbmc", Abc_CommandAbc9ChainBmc, 0 ); @@ -1165,6 +1314,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&qbf", Abc_CommandAbc9Qbf, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&qvar", Abc_CommandAbc9QVar, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&genqbf", Abc_CommandAbc9GenQbf, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&homoqbf", Abc_CommandAbc9HomoQbf, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&satfx", Abc_CommandAbc9SatFx, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&satclp", Abc_CommandAbc9SatClp, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&inse", Abc_CommandAbc9Inse, 0 ); @@ -1182,11 +1332,15 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "ABC9", "&exorcism", Abc_CommandAbc9Exorcism, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&mfs", Abc_CommandAbc9Mfs, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&mfsd", Abc_CommandAbc9Mfsd, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&deepsyn", Abc_CommandAbc9DeepSyn, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&satsyn", Abc_CommandAbc9SatSyn, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&stochsyn", Abc_CommandAbc9StochSyn, 0 ); // Cmd_CommandAdd( pAbc, "ABC9", "&popart2", Abc_CommandAbc9PoPart2, 0 ); // Cmd_CommandAdd( pAbc, "ABC9", "&cexcut", Abc_CommandAbc9CexCut, 0 ); // Cmd_CommandAdd( pAbc, "ABC9", "&cexmerge", Abc_CommandAbc9CexMerge, 0 ); // Cmd_CommandAdd( pAbc, "ABC9", "&cexmin", Abc_CommandAbc9CexMin, 0 ); + Cmd_CommandAdd( pAbc, "Abstraction", "&abs_create", Abc_CommandAbc9AbsCreate, 0 ); Cmd_CommandAdd( pAbc, "Abstraction", "&abs_derive", Abc_CommandAbc9AbsDerive, 0 ); Cmd_CommandAdd( pAbc, "Abstraction", "&abs_refine", Abc_CommandAbc9AbsRefine, 0 ); Cmd_CommandAdd( pAbc, "Abstraction", "&gla_derive", Abc_CommandAbc9GlaDerive, 0 ); @@ -1205,6 +1359,12 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Liveness", "kcs", Abc_CommandCS_kLiveness, 0 ); Cmd_CommandAdd( pAbc, "Liveness", "nck", Abc_CommandNChooseK, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&gen", Abc_CommandAbc9Gen, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&cfs", Abc_CommandAbc9Cfs, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&prodadd", Abc_CommandAbc9ProdAdd, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&addflop", Abc_CommandAbc9AddFlop, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&bmiter", Abc_CommandAbc9BMiter, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); { // extern Mf_ManTruthCount(); @@ -1745,18 +1905,24 @@ int Abc_CommandPrintMffc( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern void Abc_NodePrintSop( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ); + extern void Abc_NtkPrintSop( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pNode; - int c; + int c, fSop = 0; int fUseRealNames; // set defaults fUseRealNames = 1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "snh" ) ) != EOF ) { switch ( c ) { + case 's': + fSop ^= 1; + break; case 'n': fUseRealNames ^= 1; break; @@ -1793,16 +1959,23 @@ int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } - Abc_NodePrintFactor( stdout, pNode, fUseRealNames ); + if ( fSop ) + Abc_NodePrintSop( stdout, pNode, fUseRealNames ); + else + Abc_NodePrintFactor( stdout, pNode, fUseRealNames ); return 0; } // print the nodes - Abc_NtkPrintFactor( stdout, pNtk, fUseRealNames ); + if ( fSop ) + Abc_NtkPrintSop( stdout, pNtk, fUseRealNames ); + else + Abc_NtkPrintFactor( stdout, pNtk, fUseRealNames ); return 0; usage: - Abc_Print( -2, "usage: print_factor [-nh] \n" ); - Abc_Print( -2, "\t prints the factored forms of nodes\n" ); + Abc_Print( -2, "usage: print_factor [-snh] \n" ); + Abc_Print( -2, "\t prints the factored forms (FFs) of nodes\n" ); + Abc_Print( -2, "\t-s : toggles printing SOP instead of FF [default = %s]\n", fSop? "SOP": "FF" ); Abc_Print( -2, "\t-n : toggles real/dummy fanin names [default = %s]\n", fUseRealNames? "real": "dummy" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tnode : (optional) one node to consider\n"); @@ -1983,6 +2156,71 @@ int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +#ifdef ABC_USE_CUDD +int Abc_CommandPrintMint( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Obj_t * pObj; + int c; + int fVerbose; + + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "svwh" ) ) != EOF ) + { + switch ( c ) + { + 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_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for logic networks (run \"clp\").\n" ); + return 1; + } + if ( !Abc_NtkHasBdd(pNtk) ) + { + Abc_Print( -1, "This command works only for logic networks with local functions represented by BDDs.\n" ); + return 1; + } + + Abc_NtkForEachNode( pNtk, pObj, c ) + printf( "ObjId %3d : SuppSize = %5d MintCount = %32.0f\n", c, Abc_ObjFaninNum(pObj), + Cudd_CountMinterm((DdManager *)pNtk->pManFunc, (DdNode *)pObj->pData, Abc_ObjFaninNum(pObj)) ); + return 0; + +usage: + Abc_Print( -2, "usage: print_mint [-svwh]\n" ); + Abc_Print( -2, "\t prints the number of on-set minterms in the PO functions\n" ); + Abc_Print( -2, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} +#endif + /**Function************************************************************* Synopsis [] @@ -2708,15 +2946,26 @@ int Abc_CommandPrintMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandPrintStatus( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern void Abc_NtkDumpOneCexSpecial( FILE * pFile, Abc_Ntk_t * pNtk, Abc_Cex_t * pCex ); extern void Abc_NtkPrintPoEquivs( Abc_Ntk_t * pNtk ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c, fOutStatus = 0, fShort = 1; + char * pLogFileName = NULL; // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "osh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Losh" ) ) != EOF ) { switch ( c ) { + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" ); + goto usage; + } + pLogFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'o': fOutStatus ^= 1; break; @@ -2739,7 +2988,8 @@ int Abc_CommandPrintStatus( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_NtkPrintPoEquivs( pNtk ); return 0; } - Abc_Print( 1,"Status = %d Frames = %d ", pAbc->Status, pAbc->nFrames ); + if ( !pAbc->vStatuses ) + Abc_Print( 1,"Status = %d Frames = %d ", pAbc->Status, pAbc->nFrames ); if ( pAbc->pCex == NULL && pAbc->vCexVec == NULL ) Abc_Print( 1,"Cex is not defined.\n" ); else @@ -2751,7 +3001,7 @@ int Abc_CommandPrintStatus( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Cex_t * pTemp; int nCexes = 0; int Counter = 0; - printf( "\n" ); + //printf( "\n" ); Vec_PtrForEachEntry( Abc_Cex_t *, pAbc->vCexVec, pTemp, c ) { if ( pTemp == (void *)(ABC_PTRINT_T)1 ) @@ -2765,13 +3015,38 @@ int Abc_CommandPrintStatus( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_CexPrintStats( pTemp ); } } - if ( Counter ) - printf( "In total, %d (out of %d) outputs are \"sat\" but CEXes are not recorded.\n", Counter, Vec_PtrSize(pAbc->vCexVec) ); +// if ( Counter ) +// printf( "In total, %d (out of %d) outputs are \"sat\" but CEXes are not recorded.\n", Counter, Vec_PtrSize(pAbc->vCexVec) ); } } if ( pAbc->vStatuses ) { - if ( fShort ) + if ( pLogFileName ) + { + Abc_Cex_t * pTemp = NULL; + FILE * pFile = fopen( pLogFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for writing.\n", pLogFileName ); + return 0; + } + Vec_PtrForEachEntry( Abc_Cex_t *, pAbc->vCexVec, pTemp, c ) + { + int Status = Vec_IntEntry( pAbc->vStatuses, c ); + if ( Status == -1 ) // undec + fprintf( pFile, "STATUS: ABORTED " ); + else if ( Status == 0 ) + fprintf( pFile, "STATUS: SAT " ); + else if ( Status == 1 ) + fprintf( pFile, "STATUS: UNSAT " ); + fprintf( pFile, "%s\n", Abc_ObjName(Abc_NtkPo(pNtk, c)) ); + if ( Status != 0 ) + continue; + Abc_NtkDumpOneCexSpecial( pFile, pNtk, pTemp ); + } + fclose( pFile ); + } + else if ( fShort ) { printf( "Status array contains %d SAT, %d UNSAT, and %d UNDEC entries (out of %d).", Vec_IntCountEntry(pAbc->vStatuses, 0), Vec_IntCountEntry(pAbc->vStatuses, 1), @@ -2788,11 +3063,12 @@ int Abc_CommandPrintStatus( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: print_status [-osh]\n" ); - Abc_Print( -2, "\t prints verification status\n" ); - Abc_Print( -2, "\t-o : toggle printing output status [default = %s]\n", fOutStatus? "yes": "no" ); - Abc_Print( -2, "\t-s : toggle using short print-out [default = %s]\n", fShort? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "usage: print_status [-L file] [-osh]\n" ); + Abc_Print( -2, "\t prints verification status\n" ); + Abc_Print( -2, "\t-L file : the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); + Abc_Print( -2, "\t-o : toggle printing output status [default = %s]\n", fOutStatus? "yes": "no" ); + Abc_Print( -2, "\t-s : toggle using short print-out [default = %s]\n", fShort? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -2899,7 +3175,8 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) int fGateNames; int fUseReverse; int fFlopDep; - extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse ); + int fKeepDot; + extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse, int fKeepDot ); extern void Abc_NtkShowFlopDependency( Abc_Ntk_t * pNtk ); // set defaults @@ -2907,8 +3184,9 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) fGateNames = 0; fUseReverse = 1; fFlopDep = 0; + fKeepDot = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "rsgfh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "rsgfdh" ) ) != EOF ) { switch ( c ) { @@ -2924,6 +3202,9 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'f': fFlopDep ^= 1; break; + case 'd': + fKeepDot ^= 1; + break; default: goto usage; } @@ -2938,11 +3219,11 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( fFlopDep ) Abc_NtkShowFlopDependency( pNtk ); else - Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse ); + Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse, fKeepDot ); return 0; usage: - Abc_Print( -2, "usage: show [-srgfh]\n" ); + Abc_Print( -2, "usage: show [-srgfdh]\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" ); @@ -2952,6 +3233,7 @@ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-r : toggles ordering nodes in reverse order [default = %s].\n", fUseReverse? "yes": "no" ); 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-h : print the command usage\n"); return 1; } @@ -2971,15 +3253,25 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pNode; - int c; - extern void Abc_NodeShowBdd( Abc_Obj_t * pNode ); + int c, fCompl = 0, fGlobal = 0, fReorder = 1; + extern void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ); + extern void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl, int fReorder ); // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "cgrh" ) ) != EOF ) { switch ( c ) { + case 'c': + fCompl ^= 1; + break; + case 'g': + fGlobal ^= 1; + break; + case 'r': + fReorder ^= 1; + break; case 'h': goto usage; default: @@ -2993,12 +3285,20 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } + if ( fGlobal ) + { + Abc_Ntk_t * pTemp = Abc_NtkIsStrash(pNtk) ? pNtk : Abc_NtkStrash(pNtk, 0, 0, 0); + Abc_NtkShowBdd( pTemp, fCompl, fReorder ); + if ( pTemp != pNtk ) + Abc_NtkDelete( pTemp ); + return 0; + } + if ( !Abc_NtkIsBddLogic(pNtk) ) { 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" ); @@ -3022,17 +3322,21 @@ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } } - Abc_NodeShowBdd( pNode ); + Abc_NodeShowBdd( pNode, fCompl ); return 0; usage: - Abc_Print( -2, "usage: show_bdd [-h] \n" ); - Abc_Print( -2, " visualizes the BDD of a node using DOT and GSVIEW\n" ); + Abc_Print( -2, "usage: show_bdd [-cgrh] \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 Abc_Print( -2, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); Abc_Print( -2, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); #endif - Abc_Print( -2, "\t: the node to consider [default = the driver of the first PO]\n"); + Abc_Print( -2, "\t: (optional) the node to consider [default = the driver of the first PO]\n"); + Abc_Print( -2, "\t-c : toggle visualizing BDD with complemented edges [default = %s].\n", fCompl? "yes": "no" ); + Abc_Print( -2, "\t-g : toggle visualizing the global BDDs of primary outputs [default = %s].\n", fGlobal? "yes": "no" ); + Abc_Print( -2, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -3153,16 +3457,21 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) int fBddSizeMax; int fDualRail; int fReorder; + int fReverse; + int fDumpOrder; int c; + char * pLogFileName = NULL; pNtk = Abc_FrameReadNtk(pAbc); // set defaults fVerbose = 0; fReorder = 1; + fReverse = 0; fDualRail = 0; + fDumpOrder = 0; fBddSizeMax = ABC_INFINITY; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Brdvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "BLrodxvh" ) ) != EOF ) { switch ( c ) { @@ -3177,134 +3486,162 @@ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( fBddSizeMax < 0 ) goto usage; break; - case 'd': - fDualRail ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'r': - fReorder ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - Abc_Print( -1, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) - { - Abc_Print( -1, "Can only collapse a logic network or an AIG.\n" ); - return 1; - } - - // get the new network - if ( Abc_NtkIsStrash(pNtk) ) - pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose ); - else - { - pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose ); - Abc_NtkDelete( pNtk ); - } - if ( pNtkRes == NULL ) - { - Abc_Print( -1, "Collapsing has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - Abc_Print( -2, "usage: collapse [-B ] [-rdvh]\n" ); - Abc_Print( -2, "\t collapses the network by constructing global BDDs\n" ); - Abc_Print( -2, "\t-B : limit on live BDD nodes during collapsing [default = %d]\n", fBddSizeMax ); - Abc_Print( -2, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); - Abc_Print( -2, "\t-d : toggles dual-rail collapsing mode [default = %s]\n", fDualRail? "yes": "no" ); - Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandSatClp( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; - int nCubeLim = 0; - int nBTLimit = 1000000; - int nCostMax = 20000000; - int fCanon = 0; - int fReverse = 0; - int fCnfShared = 0; - int fVerbose = 0; - int c; - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CLZcrsvh" ) ) != EOF ) - { - switch ( c ) - { - case 'C': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nCubeLim = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nCubeLim < 0 ) - goto usage; - break; case 'L': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); - goto usage; - } - nBTLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nBTLimit < 0 ) - goto usage; - break; - case 'Z': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-Z\" should be followed by an integer.\n" ); + Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" ); goto usage; } - nCostMax = atoi(argv[globalUtilOptind]); + pLogFileName = argv[globalUtilOptind]; globalUtilOptind++; - if ( nCostMax < 0 ) - goto usage; - break; - case 'c': - fCanon ^= 1; break; case 'r': + fReorder ^= 1; + break; + case 'o': fReverse ^= 1; break; - case 's': - fCnfShared ^= 1; + case 'd': + fDualRail ^= 1; + break; + case 'x': + fDumpOrder ^= 1; + 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_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Can only collapse a logic network or an AIG.\n" ); + return 1; + } + + // get the new network + if ( Abc_NtkIsStrash(pNtk) ) + pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fReverse, fDumpOrder, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fReverse, fDumpOrder, fVerbose ); + Abc_NtkDelete( pNtk ); + } + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Collapsing has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + if ( pLogFileName ) + { + pAbc->pCex = NULL; + pAbc->nFrames = -1; + if ( Abc_NtkNodeNum(pNtkRes) == 0 ) + pAbc->Status = 1; // UNSAT + else + pAbc->Status = -1; // UNDEC + Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "collapse" ); + } + return 0; + +usage: + Abc_Print( -2, "usage: collapse [-B ] [-L file] [-rodxvh]\n" ); + Abc_Print( -2, "\t collapses the network by constructing global BDDs\n" ); + Abc_Print( -2, "\t-B : limit on live BDD nodes during collapsing [default = %d]\n", fBddSizeMax ); + Abc_Print( -2, "\t-L file : the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); + Abc_Print( -2, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles reverse variable ordering [default = %s]\n", fReverse? "yes": "no" ); + Abc_Print( -2, "\t-d : toggles dual-rail collapsing mode [default = %s]\n", fDualRail? "yes": "no" ); + Abc_Print( -2, "\t-x : toggles dumping file \"order.txt\" with variable order [default = %s]\n", fDumpOrder? "yes": "no" ); + Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSatClp( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; + int nCubeLim = 0; + int nBTLimit = 1000000; + int nCostMax = 20000000; + int fCanon = 0; + int fReverse = 0; + int fCnfShared = 0; + int fVerbose = 0; + int c; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CLZcrsvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCubeLim = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCubeLim < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nBTLimit < 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; + } + nCostMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCostMax < 0 ) + goto usage; + break; + case 'c': + fCanon ^= 1; + break; + case 'r': + fReverse ^= 1; + break; + case 's': + fCnfShared ^= 1; break; case 'v': fVerbose ^= 1; @@ -3952,7 +4289,7 @@ int Abc_CommandCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( Abc_NtkIsStrash(pNtk) ) { - if ( !fCleanupPos && !fCleanupPos ) + if ( !fCleanupPis && !fCleanupPos ) { Abc_Print( -1, "Cleanup for PIs and POs is not enabled.\n" ); pNtkRes = Abc_NtkDup( pNtk ); @@ -4178,8 +4515,8 @@ int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( Abc_NtkNodeNum(pNtk) == 0 || Abc_NtkPiNum(pNtk) == 0 ) { - Abc_Print( -1, "The network does not have internal nodes.\n" ); - return 1; + Abc_Print( 0, "The network does not have internal nodes.\n" ); + return 0; } if ( !Abc_NtkIsLogic(pNtk) ) { @@ -4696,7 +5033,7 @@ int Abc_CommandLutpack( Abc_Frame_t * pAbc, int argc, char ** argv ) } pPars->nLutsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( pPars->nLutsMax < 2 || pPars->nLutsMax > 8 ) + if ( pPars->nLutsMax < 2 || pPars->nLutsMax > 16 ) goto usage; break; case 'Q': @@ -4786,7 +5123,7 @@ int Abc_CommandLutpack( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t performs \"rewriting\" for LUT network;\n" ); Abc_Print( -2, "\t determines LUT size as the max fanin count of a node;\n" ); Abc_Print( -2, "\t if the network is not LUT-mapped, packs it into 6-LUTs\n" ); - Abc_Print( -2, "\t (there is another command for resynthesis after LUT mapping, \"imfs\")\n" ); + Abc_Print( -2, "\t (there is another command for resynthesis after LUT mapping, \"mfs2\")\n" ); Abc_Print( -2, "\t-N : the max number of LUTs in the structure (2 <= num) [default = %d]\n", pPars->nLutsMax ); Abc_Print( -2, "\t-Q : the max number of LUTs not in MFFC (0 <= num) [default = %d]\n", pPars->nLutsOver ); Abc_Print( -2, "\t-S : the max number of LUT inputs shared (0 <= num <= 3) [default = %d]\n", pPars->nVarsShared ); @@ -5191,7 +5528,7 @@ int Abc_CommandMfs2( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Sfm_ParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCZNIdaeijvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCZNIdaeijlvwh" ) ) != EOF ) { switch ( c ) { @@ -5309,6 +5646,9 @@ int Abc_CommandMfs2( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'j': fUseAllFfs ^= 1; break; + case 'l': + pPars->fUseDcs ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -5380,7 +5720,7 @@ int Abc_CommandMfs2( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: mfs2 [-WFDMLCZNI ] [-daeijvwh]\n" ); + Abc_Print( -2, "usage: mfs2 [-WFDMLCZNI ] [-daeijlvwh]\n" ); Abc_Print( -2, "\t performs don't-care-based optimization of logic networks\n" ); Abc_Print( -2, "\t-W : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nTfoLevMax ); Abc_Print( -2, "\t-F : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutMax ); @@ -5396,6 +5736,7 @@ int Abc_CommandMfs2( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-i : toggle using inductive don't-cares [default = %s]\n", fIndDCs? "yes": "no" ); Abc_Print( -2, "\t-j : toggle using all flops when \"-i\" is enabled [default = %s]\n", fUseAllFfs? "yes": "no" ); Abc_Print( -2, "\t-I : the number of additional frames inserted [default = %d]\n", nFramesAdd ); + Abc_Print( -2, "\t-l : toggle deriving don't-cares [default = %s]\n", pPars->fUseDcs? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -6664,7 +7005,7 @@ int Abc_CommandTestNpn( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: Abc_Print( -2, "usage: testnpn [-AN ] [-dbvh] \n" ); Abc_Print( -2, "\t testbench for computing (semi-)canonical forms\n" ); - Abc_Print( -2, "\t of completely-specified Boolean functions up to 16 varibles\n" ); + Abc_Print( -2, "\t of completely-specified Boolean functions up to 16 variables\n" ); Abc_Print( -2, "\t-A : semi-caninical form computation algorithm [default = %d]\n", NpnType ); Abc_Print( -2, "\t 0: uniqifying truth tables\n" ); Abc_Print( -2, "\t 1: exact NPN canonical form by brute-force enumeration\n" ); @@ -6674,7 +7015,11 @@ int Abc_CommandTestNpn( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t 5: new fast hybrid semi-canonical form\n" ); Abc_Print( -2, "\t 6: new phase canonical form\n" ); Abc_Print( -2, "\t 7: new hierarchical matching\n" ); - Abc_Print( -2, "\t 8: hierarchical matching by XueGong Zhou at Fudan University, Shanghai\n" ); + Abc_Print( -2, "\t 8: hierarchical matching by XueGong Zhou at Fudan University, Shanghai\n" ); + Abc_Print( -2, "\t 9: adjustable algorithm (heuristic) by XueGong Zhou at Fudan University, Shanghai\n" ); + Abc_Print( -2, "\t 10: adjustable algorithm (exact) by XueGong Zhou at Fudan University, Shanghai\n" ); + Abc_Print( -2, "\t 11: new cost-aware exact algorithm by XueGong Zhou at Fudan University, Shanghai\n" ); + Abc_Print( -2, "\t 12: new fast hybrid semi-canonical form (permutation only)\n" ); Abc_Print( -2, "\t-N : the number of support variables (binary files only) [default = unused]\n" ); Abc_Print( -2, "\t-d : toggle dumping resulting functions into a file [default = %s]\n", fDumpRes? "yes": "no" ); Abc_Print( -2, "\t-b : toggle dumping in binary format [default = %s]\n", fBinary? "yes": "no" ); @@ -6773,9 +7118,10 @@ int Abc_CommandTestRPO(Abc_Frame_t * pAbc, int argc, char ** argv) { SeeAlso [] ***********************************************************************/ -int Abc_CommandTestRun( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandTestTruth( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Acb_NtkTestRun( char * pFileNames[3], int fVerbose ); + extern int * Kit_TruthTest( char * pFileName ); + int * pResult = NULL; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) @@ -6791,21 +7137,20 @@ int Abc_CommandTestRun( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } -// pArgvNew = argv + globalUtilOptind; -// nArgcNew = argc - globalUtilOptind; - if ( argc - globalUtilOptind != 3 ) + if ( argc != globalUtilOptind + 1 ) { - Abc_Print( 1, "Expecting three file names on the command line.\n" ); - goto usage; + Abc_Print( 1,"Input file is not given.\n" ); + return 0; } - Acb_NtkTestRun( argv + globalUtilOptind, fVerbose ); + pResult = Kit_TruthTest( argv[globalUtilOptind] ); + ABC_FREE( pResult ); return 0; usage: - Abc_Print( -2, "usage: testrun [-vh]\n" ); - Abc_Print( -2, "\t performs testing by running internal procedures\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: testtruth [-vh] \n" ); + Abc_Print( -2, "\t printing truth table stats\n" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -6820,39 +7165,38 @@ int Abc_CommandTestRun( Abc_Frame_t * pAbc, int argc, char ** argv ) SeeAlso [] ***********************************************************************/ -int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandRunEco( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); - int c; - int fUpdateLevel; - int fPrecompute; - int fUseZeros; - int fVerbose; - int fVeryVerbose; - int fPlaceEnable; - // external functions - extern void Rwr_Precompute(); - - // set defaults - fUpdateLevel = 1; - fPrecompute = 0; - fUseZeros = 0; - fVerbose = 0; - fVeryVerbose = 0; - fPlaceEnable = 0; + extern void Acb_NtkRunEco( char * pFileNames[4], int nTimeout, int fCheck, int fRandom, int fInputs, int fUnitW, int fVerbose, int fVeryVerbose ); + char * pFileNames[4] = {NULL}; + int c, nTimeout = 0, fCheck = 0, fRandom = 0, fInputs = 0, fUnitW = 0, fVerbose = 0, fVeryVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "lxzvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Tcriuvwh" ) ) != EOF ) { switch ( c ) { - case 'l': - fUpdateLevel ^= 1; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + nTimeout = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nTimeout < 0 ) + goto usage; break; - case 'x': - fPrecompute ^= 1; + case 'c': + fCheck ^= 1; break; - case 'z': - fUseZeros ^= 1; + case 'r': + fRandom ^= 1; + break; + case 'i': + fInputs ^= 1; + break; + case 'u': + fUnitW ^= 1; break; case 'v': fVerbose ^= 1; @@ -6860,55 +7204,152 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'w': fVeryVerbose ^= 1; break; - case 'p': - fPlaceEnable ^= 1; - break; case 'h': goto usage; default: goto usage; } } - - if ( fPrecompute ) +// pArgvNew = argv + globalUtilOptind; +// nArgcNew = argc - globalUtilOptind; + if ( argc - globalUtilOptind < 2 || argc - globalUtilOptind > 3 ) { - Rwr_Precompute(); - return 0; + Abc_Print( 1, "Expecting three file names on the command line.\n" ); + goto usage; } - - if ( pNtk == NULL ) + for ( c = 0; c < argc - globalUtilOptind; c++ ) { - Abc_Print( -1, "Empty network.\n" ); - return 1; + FILE * pFile = fopen( argv[globalUtilOptind+c], "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open input file \"%s\".\n", argv[globalUtilOptind+c] ); + return 0; + } + else + fclose( pFile ); + pFileNames[c] = argv[globalUtilOptind+c]; } - if ( !Abc_NtkIsStrash(pNtk) ) + Acb_NtkRunEco( pFileNames, nTimeout, fCheck, fRandom, fInputs, fUnitW, fVerbose, fVeryVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: runeco [-T num] [-criuvwh] \n" ); + Abc_Print( -2, "\t performs computation of patch functions during ECO,\n" ); + Abc_Print( -2, "\t as described in the following paper: A. Q. Dao et al\n" ); + Abc_Print( -2, "\t \"Efficient computation of ECO patch functions\", Proc. DAC\'18\n" ); + Abc_Print( -2, "\t https://people.eecs.berkeley.edu/~alanmi/publications/2018/dac18_eco.pdf\n" ); + Abc_Print( -2, "\t (currently only applicable to benchmarks from 2017 ICCAD CAD competition\n" ); + Abc_Print( -2, "\t http://cad-contest-2017.el.cycu.edu.tw/Problem_A/default.html as follows:\n" ); + Abc_Print( -2, "\t \"runeco unit1/F.v unit1/G.v unit1/weight.txt; cec -n out.v unit1/G.v\")\n" ); + Abc_Print( -2, "\t-T num : the timeout in seconds [default = %d]\n", nTimeout ); + Abc_Print( -2, "\t-c : toggle checking that the problem has a solution [default = %s]\n", fCheck? "yes": "no" ); + Abc_Print( -2, "\t-r : toggle using random permutation of support variables [default = %s]\n", fRandom? "yes": "no" ); + Abc_Print( -2, "\t-i : toggle using primary inputs as support variables [default = %s]\n", fInputs? "yes": "no" ); + Abc_Print( -2, "\t-u : toggle using unit weights [default = %s]\n", fUnitW? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing more verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +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; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { - Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" ); - return 1; + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } } - if ( Abc_NtkGetChoiceNum(pNtk) ) + if ( argc - globalUtilOptind != 2 ) { - Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); - return 1; + Abc_Print( 1, "Expecting two file names on the command line.\n" ); + goto usage; } + for ( c = 0; c < 2; c++ ) + pFileNames[c] = argv[globalUtilOptind+c]; + Acb_NtkRunGen( pFileNames, fVerbose ); + return 0; - // modify the current network - if ( !Abc_NtkRewrite( pNtk, fUpdateLevel, fUseZeros, fVerbose, fVeryVerbose, fPlaceEnable ) ) +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"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRunTest( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Acb_NtkRunTest( char * pFileNames[4], int fFancy, int fVerbose ); + char * pFileNames[4] = {NULL}; + int c, fFancy = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "fvh" ) ) != EOF ) { - Abc_Print( -1, "Rewriting has failed.\n" ); - return 1; + switch ( c ) + { + case 'f': + fFancy ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc - globalUtilOptind < 2 || argc - globalUtilOptind > 5 ) + { + Abc_Print( 1, "Expecting two or three file names on the command line.\n" ); + goto usage; } + for ( c = 0; c < argc - globalUtilOptind; c++ ) + pFileNames[c] = argv[globalUtilOptind+c]; + Acb_NtkRunTest( pFileNames, fFancy, fVerbose ); return 0; usage: - Abc_Print( -2, "usage: rewrite [-lzvwh]\n" ); - Abc_Print( -2, "\t performs technology-independent rewriting of the AIG\n" ); - Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); - Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-w : toggle printout subgraph statistics [default = %s]\n", fVeryVerbose? "yes": "no" ); -// Abc_Print( -2, "\t-p : toggle placement-aware rewriting [default = %s]\n", fPlaceEnable? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "usage: xec [-fvh] \n" ); + Abc_Print( -2, "\t combinational equivalence checking with x-values\n" ); + Abc_Print( -2, "\t-f : toggle using experimental feature [default = %s]\n", fFancy? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -6916,83 +7357,130 @@ int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) Synopsis [] - Description [] + Description [Orchestration synthesis] SideEffects [] SeeAlso [] ***********************************************************************/ -int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandOrchestrate( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); - int c; + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pDup; + int c, RetValue; + int nNodeSizeMax; int nConeSizeMax; int fUpdateLevel; - int fUseZeros; + int fUseZeros_rwr; + int fUseZeros_ref; int fUseDcs; - int fVerbose; - extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); + int RS_CUT_MIN = 4;//rs option + int RS_CUT_MAX = 16;//rs option + int nCutsMax; //rs option + int nNodesMax; //rs option + int nLevelsOdc; //rs option + + int fPrecompute; //rewrite option (not enabled) + int fPlaceEnable; //rewrite option (not enabled) + + int fVerbose; //rewrite/rs/rf verbose + int fVeryVerbose; //very verbose option for all + //size_t NtkSize; + extern void Rwr_Precompute(); + //local greedy + extern int Abc_NtkOrchLocal( Abc_Ntk_t * pNtk, int fUseZeros_rwr, int fUseZeros_ref, int fPlaceEnable, int nCutsMax, int nNodesMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose, int nNodeSizeMax, int nConeSizeMax, int fUseDcs ); + //priority orch + extern int Abc_NtkOchestration( Abc_Ntk_t * pNtk, Vec_Int_t **pGain_rwr, Vec_Int_t **pGain_res,Vec_Int_t **pGain_ref, int sOpsOrder, int fUseZeros_rwr, int fUseZeros_ref, int fPlaceEnable, int nCutsMax, int nNodesMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose, int nNodeSizeMax, int nConeSizeMax, int fUseDcs ); // set defaults nNodeSizeMax = 10; nConeSizeMax = 16; fUpdateLevel = 1; - fUseZeros = 0; + fUseZeros_rwr = 1; + fUseZeros_ref = 1; fUseDcs = 0; fVerbose = 0; + fVeryVerbose = 0; + fPlaceEnable = 0; + fPrecompute = 0; + nCutsMax = 8; + nNodesMax = 1; + nLevelsOdc = 0; + Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Nlzvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KNFZzlvwh" ) ) != EOF ) { switch ( c ) { - case 'N': + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutsMax < 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; } - nNodeSizeMax = atoi(argv[globalUtilOptind]); + nNodesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( nNodeSizeMax < 0 ) + if ( nNodesMax < 0 ) goto usage; break; - case 'C': + case 'F': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } - nConeSizeMax = atoi(argv[globalUtilOptind]); + nLevelsOdc = atoi(argv[globalUtilOptind]); globalUtilOptind++; - if ( nConeSizeMax < 0 ) + if ( nLevelsOdc < 0 ) goto usage; break; case 'l': fUpdateLevel ^= 1; break; case 'z': - fUseZeros ^= 1; + fUseZeros_rwr ^= 1; break; - case 'd': - fUseDcs ^= 1; + case 'Z': + fUseZeros_ref ^= 1; break; case 'v': fVerbose ^= 1; break; + case 'w': + fVeryVerbose ^= 1; + break; case 'h': goto usage; - default: - goto usage; + break; } } - + if ( fPrecompute ) + { + Rwr_Precompute(); + return 0; + } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } + if ( nCutsMax < RS_CUT_MIN || nCutsMax > RS_CUT_MAX ) + { + Abc_Print( -1, "Can only compute cuts for %d <= K <= %d.\n", RS_CUT_MIN, RS_CUT_MAX ); + return 1; + } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" ); @@ -7016,17 +7504,303 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) } // modify the current network - if ( !Abc_NtkRefactor( pNtk, nNodeSizeMax, nConeSizeMax, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ) ) + pDup = Abc_NtkDup( pNtk ); + RetValue = Abc_NtkOrchLocal( pNtk, fUseZeros_rwr, fUseZeros_ref, fPlaceEnable, nCutsMax, nNodesMax, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose, nNodeSizeMax, nConeSizeMax, fUseDcs ); + if ( RetValue == -1 ) { - Abc_Print( -1, "Refactoring has failed.\n" ); + Abc_FrameReplaceCurrentNetwork( pAbc, pDup ); + printf( "An error occurred during computation. The original network is restored.\n" ); + } + else + { + Abc_NtkDelete( pDup ); + if ( RetValue == 0 ) + { + Abc_Print( 0, "Ochestration (local greedy) has failed.\n" ); + return 1; + } + } + return 0; + +usage: + Abc_Print( -2, "usage: orchestrate [-KNFZzlvwh]\n" ); + Abc_Print( -2, "\t performs technology-independent AIG synthesis using orchestration method (currently orchestrating rw/rf/rs)\n" ); + Abc_Print( -2, "\t-K : (resub)the max cut size (%d <= num <= %d) [default = %d]\n", RS_CUT_MIN, RS_CUT_MAX, nCutsMax ); + Abc_Print( -2, "\t-N : (resub)the max number of nodes to add (0 <= num <= 3) [default = %d]\n", nNodesMax ); + Abc_Print( -2, "\t-F : (resub)the number of fanout levels for ODC computation [default = %d]\n", nLevelsOdc ); + Abc_Print( -2, "\t-l : (resub/rw/refactor)toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-z : (rw)toggle using zero-cost replacements [default = %s]\n", fUseZeros_rwr? "yes": "no" ); + Abc_Print( -2, "\t-Z : (refactor)toggle using zero-cost replacements [default = %s]\n", fUseZeros_ref? "yes": "no" ); + Abc_Print( -2, "\t-v : (resub/rw/refactor)toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : (resub/rw/refactor)toggle detailed verbose printout [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + + + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pDup; + int c, RetValue; + int fUpdateLevel; + int fPrecompute; + int fUseZeros; + int fVerbose; + int fVeryVerbose; + int fPlaceEnable; + // external functions + extern void Rwr_Precompute(); + + // set defaults + fUpdateLevel = 1; + fPrecompute = 0; + fUseZeros = 0; + fVerbose = 0; + fVeryVerbose = 0; + fPlaceEnable = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lxzvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'x': + fPrecompute ^= 1; + break; + case 'z': + fUseZeros ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'p': + fPlaceEnable ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( fPrecompute ) + { + Rwr_Precompute(); + return 0; + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); return 1; } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + // modify the current network + pDup = Abc_NtkDup( pNtk ); + RetValue = Abc_NtkRewrite( pNtk, fUpdateLevel, fUseZeros, fVerbose, fVeryVerbose, fPlaceEnable ); + if ( RetValue == -1 ) + { + Abc_FrameReplaceCurrentNetwork( pAbc, pDup ); + printf( "An error occurred during computation. The original network is restored.\n" ); + } + else + { + Abc_NtkDelete( pDup ); + if ( RetValue == 0 ) + { + Abc_Print( 0, "Rewriting has failed.\n" ); + return 1; + } + } return 0; usage: - Abc_Print( -2, "usage: refactor [-N ] [-lzvh]\n" ); + Abc_Print( -2, "usage: rewrite [-lzvwh]\n" ); + Abc_Print( -2, "\t performs technology-independent rewriting of the AIG\n" ); + Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printout subgraph statistics [default = %s]\n", fVeryVerbose? "yes": "no" ); +// Abc_Print( -2, "\t-p : toggle placement-aware rewriting [default = %s]\n", fPlaceEnable? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pDup; + int c, RetValue; + int nNodeSizeMax; + int nMinSaved; + int nConeSizeMax; + int fUpdateLevel; + int fUseZeros; + int fUseDcs; + int fVerbose; + extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nMinSaved, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); + + // set defaults + nNodeSizeMax = 10; + nMinSaved = 1; + nConeSizeMax = 16; + fUpdateLevel = 1; + fUseZeros = 0; + fUseDcs = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NMClzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNodeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodeSizeMax < 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; + } + nMinSaved = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMinSaved < 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; + } + nConeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConeSizeMax < 0 ) + goto usage; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeros ^= 1; + break; + case 'd': + fUseDcs ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( fUseZeros ) + nMinSaved = 0; + if ( nMinSaved == 0 ) + fUseZeros = 1; + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + if ( nNodeSizeMax > 15 ) + { + Abc_Print( -1, "The cone size cannot exceed 15.\n" ); + return 1; + } + + if ( fUseDcs && nNodeSizeMax >= nConeSizeMax ) + { + Abc_Print( -1, "For don't-care to work, containing cone should be larger than collapsed node.\n" ); + return 1; + } + + // modify the current network + pDup = Abc_NtkDup( pNtk ); + RetValue = Abc_NtkRefactor( pNtk, nNodeSizeMax, nMinSaved, nConeSizeMax, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ); + if ( RetValue == -1 ) + { + Abc_FrameReplaceCurrentNetwork( pAbc, pDup ); + printf( "An error occurred during computation. The original network is restored.\n" ); + } + else + { + Abc_NtkDelete( pDup ); + if ( RetValue == 0 ) + { + Abc_Print( 0, "Refactoring has failed.\n" ); + return 1; + } + } + return 0; + +usage: + Abc_Print( -2, "usage: refactor [-NM ] [-lzvh]\n" ); Abc_Print( -2, "\t performs technology-independent refactoring of the AIG\n" ); Abc_Print( -2, "\t-N : the max support of the collapsed node [default = %d]\n", nNodeSizeMax ); + Abc_Print( -2, "\t-M : the min number of nodes saved after one step (0 <= num) [default = %d]\n", nMinSaved ); // Abc_Print( -2, "\t-C : the max support of the containing cone [default = %d]\n", nConeSizeMax ); Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); @@ -7154,22 +7928,24 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) int nCutsMax; int nNodesMax; int nLevelsOdc; + int nMinSaved; int fUpdateLevel; int fUseZeros; int fVerbose; int fVeryVerbose; - extern int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutsMax, int nNodesMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose ); + extern int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutsMax, int nNodesMax, int nMinSaved, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose ); // set defaults nCutsMax = 8; nNodesMax = 1; nLevelsOdc = 0; + nMinSaved = 1; fUpdateLevel = 1; fUseZeros = 0; fVerbose = 0; fVeryVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KNFlzvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KNMFlzvwh" ) ) != EOF ) { switch ( c ) { @@ -7195,6 +7971,17 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nNodesMax < 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; + } + nMinSaved = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMinSaved < 0 ) + goto usage; + break; case 'F': if ( globalUtilOptind >= argc ) { @@ -7224,6 +8011,10 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( fUseZeros ) + nMinSaved = 0; + if ( nMinSaved == 0 ) + fUseZeros = 1; if ( pNtk == NULL ) { @@ -7252,7 +8043,7 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) } // modify the current network - if ( !Abc_NtkResubstitute( pNtk, nCutsMax, nNodesMax, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose ) ) + if ( !Abc_NtkResubstitute( pNtk, nCutsMax, nNodesMax, nMinSaved, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose ) ) { Abc_Print( -1, "Refactoring has failed.\n" ); return 1; @@ -7260,10 +8051,11 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: resub [-KN ] [-lzvwh]\n" ); + Abc_Print( -2, "usage: resub [-KNMF ] [-lzvwh]\n" ); Abc_Print( -2, "\t performs technology-independent restructuring of the AIG\n" ); Abc_Print( -2, "\t-K : the max cut size (%d <= num <= %d) [default = %d]\n", RS_CUT_MIN, RS_CUT_MAX, nCutsMax ); Abc_Print( -2, "\t-N : the max number of nodes to add (0 <= num <= 3) [default = %d]\n", nNodesMax ); + Abc_Print( -2, "\t-M : the min number of nodes saved after one step (0 <= num) [default = %d]\n", nMinSaved ); Abc_Print( -2, "\t-F : the number of fanout levels for ODC computation [default = %d]\n", nLevelsOdc ); Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); @@ -7273,6 +8065,64 @@ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandResubCheck( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Res6_ManResubCheck( char * pFileNameRes, char * pFileNameSol, int fVerbose ); + char * pFileR = NULL, * pFileS = NULL; + int fVerbose = 0, c; + 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 ( argc == globalUtilOptind + 2 ) + { + pFileR = argv[globalUtilOptind]; + pFileS = argv[globalUtilOptind+1]; + } + else if ( argc == globalUtilOptind + 1 ) + { + pFileR = argv[globalUtilOptind]; + pFileS = NULL; + } + else + { + Abc_Print( -1, "Incorrect number of command line arguments.\n" ); + return 1; + } + Res6_ManResubCheck( pFileR, pFileS, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: resub_check [-vh] \n" ); + Abc_Print( -2, "\t checks solution to a resub problem\n" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t : resub problem file name\n"); + Abc_Print( -2, "\t : (optional) solution file name\n"); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -7823,7 +8673,7 @@ int Abc_CommandExact( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( argc == globalUtilOptind ) goto usage; - memset( pTruth, 0, 64 ); + memset( pTruth, 0, 64 * sizeof(word) ); while ( globalUtilOptind < argc ) { if ( nFunc == 16 ) @@ -8184,11 +9034,14 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Exa_ManExactSynthesis( Bmc_EsPar_t * pPars ); extern void Exa_ManExactSynthesis2( Bmc_EsPar_t * pPars ); - int c; + extern void Exa_ManExactSynthesis4( Bmc_EsPar_t * pPars ); + extern void Exa_ManExactSynthesis5( Bmc_EsPar_t * pPars ); + extern void Exa_ManExactSynthesis6( Bmc_EsPar_t * pPars, char * pFileName ); + int c, fKissat = 0, fKissat2 = 0; Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "INaogvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "INTadconugklvh" ) ) != EOF ) { switch ( c ) { @@ -8214,15 +9067,44 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nNodes < 0 ) goto usage; break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + pPars->RuntimeLim = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->RuntimeLim < 0 ) + goto usage; + break; case 'a': pPars->fOnlyAnd ^= 1; break; + case 'd': + pPars->fDynConstr ^= 1; + break; + case 'c': + pPars->fDumpCnf ^= 1; + break; case 'o': pPars->fFewerVars ^= 1; break; + case 'n': + pPars->fOrderNodes ^= 1; + break; + case 'u': + pPars->fUniqFans ^= 1; + break; case 'g': pPars->fGlucose ^= 1; break; + case 'k': + fKissat ^= 1; + break; + case 'l': + fKissat2 ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -8233,7 +9115,14 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) } } if ( argc == globalUtilOptind + 1 ) + { + if ( strstr(argv[globalUtilOptind], ".") ) + { + Exa_ManExactSynthesis6( pPars, argv[globalUtilOptind] ); + return 0; + } pPars->pTtStr = argv[globalUtilOptind]; + } if ( pPars->pTtStr == NULL ) { Abc_Print( -1, "Truth table should be given on the command line.\n" ); @@ -8254,20 +9143,31 @@ int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Function should not have more than 10 inputs.\n" ); return 1; } - if ( pPars->fGlucose ) + if ( fKissat ) + Exa_ManExactSynthesis4( pPars ); + else if ( fKissat2 ) + Exa_ManExactSynthesis5( pPars ); + else if ( pPars->fGlucose ) Exa_ManExactSynthesis( pPars ); else Exa_ManExactSynthesis2( pPars ); return 0; usage: - Abc_Print( -2, "usage: twoexact [-IN ] [-aogvh] \n" ); + Abc_Print( -2, "usage: twoexact [-INT ] [-adconugklvh] \n" ); Abc_Print( -2, "\t exact synthesis of multi-input function using two-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 MAJ3 nodes [default = %d]\n", pPars->nNodes ); + Abc_Print( -2, "\t-N : the number of two-input nodes [default = %d]\n", pPars->nNodes ); + Abc_Print( -2, "\t-T : the runtime limit in seconds [default = %d]\n", pPars->RuntimeLim ); Abc_Print( -2, "\t-a : toggle using only AND-gates (without XOR-gates) [default = %s]\n", pPars->fOnlyAnd ? "yes" : "no" ); + Abc_Print( -2, "\t-d : toggle using dynamic constraint addition [default = %s]\n", pPars->fDynConstr ? "yes" : "no" ); + Abc_Print( -2, "\t-c : toggle dumping CNF into a file [default = %s]\n", pPars->fDumpCnf ? "yes" : "no" ); Abc_Print( -2, "\t-o : toggle using additional optimizations [default = %s]\n", pPars->fFewerVars ? "yes" : "no" ); + Abc_Print( -2, "\t-n : toggle ordering internal nodes [default = %s]\n", pPars->fOrderNodes ? "yes" : "no" ); + Abc_Print( -2, "\t-u : toggle using unique fanouts [default = %s]\n", pPars->fUniqFans ? "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-k : toggle using Kissat by Armin Biere [default = %s]\n", fKissat ? "yes" : "no" ); + Abc_Print( -2, "\t-l : toggle using Kissat by Armin Biere [default = %s]\n", fKissat2 ? "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" ); Abc_Print( -2, "\t : truth table in hex notation\n" ); @@ -8300,7 +9200,7 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "INKiaogvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "INKTiaogvh" ) ) != EOF ) { switch ( c ) { @@ -8337,6 +9237,17 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nLutSize < 0 ) goto usage; break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + pPars->RuntimeLim = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->RuntimeLim < 0 ) + goto usage; + break; case 'i': pPars->fUseIncr ^= 1; break; @@ -8392,11 +9303,12 @@ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lutexact [-INK ] [-iaogvh] \n" ); + Abc_Print( -2, "usage: lutexact [-INKT ] [-iaogvh] \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-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" ); @@ -8425,7 +9337,7 @@ int Abc_CommandAllExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "MINKiaoegvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "MINKianegvh" ) ) != EOF ) { switch ( c ) { @@ -8479,7 +9391,7 @@ int Abc_CommandAllExact( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'a': pPars->fOnlyAnd ^= 1; break; - case 'o': + case 'n': pPars->fOrderNodes ^= 1; break; case 'e': @@ -8575,7 +9487,7 @@ int Abc_CommandAllExact( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: allexact [-MIKN ] [-iaoevh] \n" ); + Abc_Print( -2, "usage: allexact [-MIKN ] [-ianevh] \n" ); Abc_Print( -2, "\t exact synthesis of I-input function using N K-input gates\n" ); Abc_Print( -2, "\t-M : the majority support size (overrides -I and -K) [default = %d]\n", pPars->nMajSupp ); Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", pPars->nVars ); @@ -8583,7 +9495,7 @@ int Abc_CommandAllExact( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-N : the number of K-input nodes [default = %d]\n", pPars->nNodes ); 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 node ordering by fanins [default = %s]\n", pPars->fOrderNodes ? "yes" : "no" ); + Abc_Print( -2, "\t-n : toggle using node ordering by fanins [default = %s]\n", pPars->fOrderNodes ? "yes" : "no" ); Abc_Print( -2, "\t-e : toggle enumerating all solutions [default = %s]\n", pPars->fEnumSols ? "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" ); @@ -8641,6 +9553,62 @@ int Abc_CommandTestExact( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMajGen( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Gem_Enumerate( int nVars, int fDump, int fVerbose ); + int c, nVars = 8, fDump = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ndvh" ) ) != EOF ) + { + switch ( c ) + { + 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 'd': + fDump ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + Gem_Enumerate( nVars, fDump, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: majgen [-N ] [-dvh]>\n" ); + Abc_Print( -2, "\t generates networks for majority gates\n" ); + Abc_Print( -2, "\t-N : the maximum number of variables [default = %d]\n", nVars ); + Abc_Print( -2, "\t-d : toggle dumping functions into a file [default = %s]\n", fVerbose ? "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; +} + /**Function************************************************************* Synopsis [] @@ -8928,6 +9896,76 @@ int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMiter2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Vec_Ptr_t * Abc_NtkReadNodeNames( Abc_Ntk_t * pNtk, char * pFileName ); + extern Abc_Ntk_t * Abc_NtkSpecialMiter( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ); + + Abc_Ntk_t * pNtk, * pNtkRes; + Vec_Ptr_t * vNodes; + char * pFileName; + int c, fVerbose = 0; + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + // get the second network + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( -1, "The file with node names is not given.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "The base network should be logic network from BLIF file.\n" ); + return 1; + } + // read the second network + pFileName = argv[globalUtilOptind]; + if ( (vNodes = Abc_NtkReadNodeNames(pNtk, pFileName)) == NULL ) + { + Abc_Print( -1, "Cannot read node names from file \"%s\".\n", pFileName ); + return 1; + } + pNtkRes = Abc_NtkSpecialMiter( pNtk, vNodes ); + Vec_PtrFree( vNodes ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: miter2 [-h] \n" ); + Abc_Print( -2, "\t derives specialized miter\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : file name with node names\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -9660,7 +10698,7 @@ int Abc_CommandPutOnTop( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkPutOnTop( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtk2 ); - Abc_Ntk_t * pNtk, * pNtk2, * pNtkRes; + Abc_Ntk_t * pNtk, * pNtk2, * pNtkRes = NULL; char * FileName; int fComb = 0; int c; @@ -9680,6 +10718,36 @@ int Abc_CommandPutOnTop( Abc_Frame_t * pAbc, int argc, char ** argv ) } } + if ( argc > globalUtilOptind + 1 ) + { + for ( c = 1; c < argc; c++ ) + { + Abc_Ntk_t * pTemp, * pLogic = Io_Read( argv[c], Io_ReadFileType(argv[c]), 1, 0 ); + if ( pLogic == NULL ) + return 1; + if ( Abc_NtkIsStrash(pLogic) ) + { + pLogic = Abc_NtkToLogic( pTemp = pLogic ); + Abc_NtkDelete( pTemp ); + } + if ( pLogic == NULL ) + return 1; + if ( pNtkRes == NULL ) + pNtkRes = pLogic; + else + { + pNtkRes = Abc_NtkPutOnTop( pTemp = pNtkRes, pLogic ); + Abc_NtkDelete( pTemp ); + Abc_NtkDelete( pLogic ); + if ( pNtkRes == NULL ) + return 1; + } + } + assert( Abc_NtkIsLogic(pNtkRes) ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + } + // get the second network if ( argc != globalUtilOptind + 1 ) { @@ -9722,7 +10790,15 @@ int Abc_CommandPutOnTop( Abc_Frame_t * pAbc, int argc, char ** argv ) } // get the new network - pNtkRes = Abc_NtkPutOnTop( pNtk, pNtk2 ); + if ( Abc_NtkIsLogic(pNtk2) ) + pNtkRes = Abc_NtkPutOnTop( pNtk, pNtk2 ); + else if ( Abc_NtkIsStrash(pNtk2) ) + { + Abc_Ntk_t * pLogic = Abc_NtkToLogic( pNtk2 ); + pNtkRes = Abc_NtkPutOnTop( pNtk, pLogic ); + Abc_NtkDelete( pLogic ); + } + else assert( 0 ); Abc_NtkDelete( pNtk2 ); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); @@ -9733,6 +10809,7 @@ int Abc_CommandPutOnTop( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t connects PIs of network in to POs of current network\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : file name with the second network\n"); + Abc_Print( -2, "\t : (given several files, all networks are stacked on top of each other)\n"); return 1; } @@ -9946,12 +11023,13 @@ int Abc_CommandDFrames( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern void Abc_NtkFaninSort( Abc_Ntk_t * pNtk ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); - int c, fMode = -1, nCubeLimit = 1000000; + int c, fCubeSort = 1, fMode = -1, nCubeLimit = 1000000; // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Cdnh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Csdnh" ) ) != EOF ) { switch ( c ) { @@ -9966,6 +11044,9 @@ int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nCubeLimit < 0 ) goto usage; break; + case 's': + fCubeSort ^= 1; + break; case 'd': fMode = 1; break; @@ -9988,17 +11069,25 @@ int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Converting to SOP is possible only for logic networks.\n" ); return 1; } + if ( !fCubeSort && Abc_NtkHasBdd(pNtk) && !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 0) ) + { + Abc_Print( -1, "Converting to SOP has failed.\n" ); + return 0; + } if ( !Abc_NtkToSop(pNtk, fMode, nCubeLimit) ) { Abc_Print( -1, "Converting to SOP has failed.\n" ); return 0; } + if ( !fCubeSort ) + Abc_NtkFaninSort( pNtk ); return 0; usage: - Abc_Print( -2, "usage: sop [-C num] [-dnh]\n" ); + Abc_Print( -2, "usage: sop [-C num] [-sdnh]\n" ); Abc_Print( -2, "\t converts node functions to SOP\n" ); Abc_Print( -2, "\t-C num : the limit on the number of cubes at a node [default = %d]\n", nCubeLimit ); + Abc_Print( -2, "\t-s : toggles cube sort when converting from BDDs [default = %s]\n", fCubeSort ? "yes": "no" ); Abc_Print( -2, "\t-d : toggles using only positive polarity [default = %s]\n", fMode == 1 ? "yes": "no" ); Abc_Print( -2, "\t-n : toggles using only negative polarity [default = %s]\n", fMode == 0 ? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -10343,15 +11432,31 @@ int Abc_CommandOrder( Abc_Frame_t * pAbc, int argc, char ** argv ) int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; - int c; - + int c, fGlobal = 0, fUseAdd = 0, Limit = 1000000; pNtk = Abc_FrameReadNtk(pAbc); // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Bgah" ) ) != EOF ) { switch ( c ) { + case 'B': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); + goto usage; + } + Limit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Limit < 0 ) + goto usage; + break; + case 'g': + fGlobal ^= 1; + break; + case 'a': + fUseAdd ^= 1; + break; case 'h': goto usage; default: @@ -10365,28 +11470,42 @@ int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( !Abc_NtkIsBddLogic(pNtk) ) + if ( fGlobal ) { - Abc_Print( -1, "Only a BDD logic network can be converted to MUXes.\n" ); - return 1; + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "The current network should be an AIG.\n" ); + return 1; + } + } + else + { + if ( !Abc_NtkIsBddLogic(pNtk) ) + { + Abc_Print( -1, "Only a BDD logic network can be converted to MUXes.\n" ); + return 1; + } } // get the new network - pNtkRes = Abc_NtkBddToMuxes( pNtk ); + pNtkRes = Abc_NtkBddToMuxes( pNtk, fGlobal, Limit, fUseAdd ); if ( pNtkRes == NULL ) { - Abc_Print( -1, "Converting to MUXes has failed.\n" ); - return 1; + Abc_Print( 0, "Converting to MUXes has failed.\n" ); + return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: - Abc_Print( -2, "usage: muxes [-h]\n" ); - Abc_Print( -2, "\t converts the current network into a network derived by\n" ); - Abc_Print( -2, "\t replacing all nodes by DAGs isomorphic to the local BDDs\n" ); - Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "usage: muxes [-B num] [-gah]\n" ); + Abc_Print( -2, "\t converts the current network into a network derived by\n" ); + Abc_Print( -2, "\t replacing all nodes by DAGs isomorphic to the local BDDs\n" ); + Abc_Print( -2, "\t-B : limit on live BDD nodes during collapsing [default = %d]\n", Limit ); + Abc_Print( -2, "\t-g : toggle visualizing the global BDDs of primary outputs [default = %s].\n", fGlobal? "yes": "no" ); + Abc_Print( -2, "\t-a : toggle using ADDs instead of BDDs [default = %s].\n", fUseAdd? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -10522,7 +11641,7 @@ int Abc_CommandExpand( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_NtkDelete( pNtk2 ); // convert it into an AIG pGia = Abc_NtkClpGia( pStrash ); - //Gia_AigerWrite( pGia, "aig_dump.aig", 0, 0 ); + //Gia_AigerWrite( pGia, "aig_dump.aig", 0, 0, 0 ); Abc_NtkDelete( pStrash ); // get the new network Abc_NtkExpandCubes( pNtk, pGia, fVerbose ); @@ -10787,6 +11906,11 @@ int Abc_CommandReach( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Reachability analysis works only for AIGs (run \"strash\").\n" ); return 1; } + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } pAbc->Status = Abc_NtkDarReach( pNtk, pPars ); pAbc->nFrames = pPars->iFrame; Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); @@ -11038,6 +12162,134 @@ int Abc_CommandNode( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRange( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + pNtk = Abc_FrameReadNtk(pAbc); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Currently can only be applied to an AIG.\n" ); + return 1; + } + pNtkRes = Abc_NtkCreateFromRange( pNtk ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Deriving the network has failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: range [-h]\n" ); + Abc_Print( -2, "\t computes the range of output values as one node\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCof( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c, Const; + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Currently can only be applied to a logic network.\n" ); + return 1; + } + + if ( argc != globalUtilOptind + 2 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + pNode = Abc_NtkFindCi( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + Const = atoi( argv[globalUtilOptind+1] ); + if ( Const != 0 && Const != 1 ) + { + Abc_Print( -1, "Constant should be 0 or 1.\n", argv[globalUtilOptind+1] ); + return 1; + } + Abc_ObjReplaceByConstant( pNode, Const ); + return 0; + +usage: + Abc_Print( -2, "usage: cof [-h] \n" ); + Abc_Print( -2, "\t replaces one node in a logic network by constant 0 or 1\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the node to replace\n"); + Abc_Print( -2, "\t : the constant to replace the node with\n"); + Abc_Print( -2, "\tname : the node name\n"); + return 1; +} + /**Function************************************************************* @@ -11096,12 +12348,7 @@ int Abc_CommandTopmost( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( Abc_NtkLatchNum(pNtk) > 0 ) { - Abc_Print( -1, "Currently can only works for combinational circuits.\n" ); - return 0; - } - if ( Abc_NtkPoNum(pNtk) != 1 ) - { - Abc_Print( -1, "Currently expects a single-output miter.\n" ); + Abc_Print( -1, "Currently only works for combinational circuits.\n" ); return 0; } @@ -11124,6 +12371,86 @@ int Abc_CommandTopmost( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBottommost( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nLevels; + extern Abc_Ntk_t * Abc_NtkBottommost( Abc_Ntk_t * pNtk, int nLevels ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + nLevels = 10; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevels < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); + return 0; + } + + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + Abc_Print( -1, "Currently only works for combinational circuits.\n" ); + return 0; + } + + pNtkRes = Abc_NtkBottommost( pNtk, nLevels ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "The command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: bottommost [-N num] [-h]\n" ); + Abc_Print( -2, "\t replaces the current network by several of its bottommost levels\n" ); + Abc_Print( -2, "\t-N num : max number of levels [default = %d]\n", nLevels ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\tname : the node name\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -11286,13 +12613,16 @@ int Abc_CommandTrim( Abc_Frame_t * pAbc, int argc, char ** argv ) int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); - int c; + int c, fKeepIo = 0; // set defaults Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "kh" ) ) != EOF ) { switch ( c ) { + case 'k': + fKeepIo ^= 1; + break; case 'h': goto usage; default: @@ -11305,12 +12635,16 @@ int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Empty network.\n" ); return 1; } - Abc_NtkShortNames( pNtk ); + if ( fKeepIo ) + Abc_NtkCleanNames( pNtk ); + else + Abc_NtkShortNames( pNtk ); return 0; usage: - Abc_Print( -2, "usage: short_names [-h]\n" ); + Abc_Print( -2, "usage: short_names [-kh]\n" ); Abc_Print( -2, "\t replaces PI/PO/latch names by short char strings\n" ); + Abc_Print( -2, "\t-k : toggle keeping PI/PO names unchanged [default = %s]\n", fKeepIo? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -12028,15 +13362,19 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) // Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int nVars; // the number of variables + int nArgs; // the number of arguments int nLutSize = -1; // the size of LUTs int nLuts = -1; // the number of LUTs int fAdder; + int fAdderTree; int fSorter; int fMesh; int fMulti; + int fBooth; int fFpga; int fOneHot; int fRandom; + int fGraph; int fVerbose; char * FileName; char Command[1000]; @@ -12044,22 +13382,29 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) extern void Abc_GenSorter( char * pFileName, int nVars ); extern void Abc_GenMesh( char * pFileName, int nVars ); extern void Abc_GenMulti( char * pFileName, int nVars ); + extern void Abc_GenBooth( char * pFileName, int nVars ); extern void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars ); extern void Abc_GenOneHot( char * pFileName, int nVars ); extern void Abc_GenRandom( char * pFileName, int nPis ); + extern void Abc_GenGraph( char * pFileName, int nPis ); + extern void Abc_GenAdderTree( char * pFileName, int nArgs, int nBits ); // set defaults nVars = 8; + nArgs = 8; fAdder = 0; + fAdderTree = 0; fSorter = 0; fMesh = 0; fMulti = 0; + fBooth = 0; fFpga = 0; fOneHot = 0; fRandom = 0; + fGraph = 0; fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NKLasemftrvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "NAKLatsembfnrgvh" ) ) != EOF ) { switch ( c ) { @@ -12074,6 +13419,17 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nVars < 0 ) goto usage; break; + case 'A': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" ); + goto usage; + } + nArgs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nArgs < 0 ) + goto usage; + break; case 'K': if ( globalUtilOptind >= argc ) { @@ -12099,6 +13455,9 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'a': fAdder ^= 1; break; + case 't': + fAdderTree ^= 1; + break; case 's': fSorter ^= 1; break; @@ -12108,15 +13467,21 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'm': fMulti ^= 1; break; + case 'b': + fBooth ^= 1; + break; case 'f': fFpga ^= 1; break; - case 't': + case 'n': fOneHot ^= 1; break; case 'r': fRandom ^= 1; break; + case 'g': + fGraph ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -12146,6 +13511,8 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_GenMesh( FileName, nVars ); else if ( fMulti ) Abc_GenMulti( FileName, nVars ); + else if ( fBooth ) + Abc_GenBooth( FileName, nVars ); else if ( fFpga ) Abc_GenFpga( FileName, nLutSize, nLuts, nVars ); // Abc_GenFpga( FileName, 2, 2, 3 ); @@ -12154,6 +13521,16 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_GenOneHot( FileName, nVars ); else if ( fRandom ) Abc_GenRandom( FileName, nVars ); + else if ( fGraph ) + Abc_GenGraph( FileName, nVars ); + else if ( fAdderTree ) + { + printf( "Generating adder tree with %d arguments and %d bits.\n", nArgs, nVars ); + Abc_GenAdderTree( FileName, nArgs, nVars ); + sprintf( Command, "%%read %s; %%blast; &put", FileName ); + Cmd_CommandExecute( pAbc, Command ); + return 0; + } else { Abc_Print( -1, "Type of circuit is not specified.\n" ); @@ -12165,17 +13542,21 @@ int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: gen [-NKL num] [-asemftrvh] \n" ); + Abc_Print( -2, "usage: gen [-NAKL num] [-atsembfnrgvh] \n" ); Abc_Print( -2, "\t generates simple circuits\n" ); Abc_Print( -2, "\t-N num : the number of variables [default = %d]\n", nVars ); + Abc_Print( -2, "\t-A num : the number of arguments (for adder tree) [default = %d]\n", nArgs ); Abc_Print( -2, "\t-K num : the LUT size (to be used with switch -f) [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-L num : the LUT count (to be used with switch -f) [default = %d]\n", nLuts ); Abc_Print( -2, "\t-a : generate ripple-carry adder [default = %s]\n", fAdder? "yes": "no" ); + Abc_Print( -2, "\t-t : generate an adder tree [default = %s]\n", fAdderTree? "yes": "no" ); Abc_Print( -2, "\t-s : generate a sorter [default = %s]\n", fSorter? "yes": "no" ); Abc_Print( -2, "\t-e : generate a mesh [default = %s]\n", fMesh? "yes": "no" ); Abc_Print( -2, "\t-m : generate a multiplier [default = %s]\n", fMulti? "yes": "no" ); + Abc_Print( -2, "\t-b : generate a signed Booth multiplier [default = %s]\n", fBooth? "yes": "no" ); Abc_Print( -2, "\t-f : generate a LUT FPGA structure [default = %s]\n", fFpga? "yes": "no" ); - Abc_Print( -2, "\t-t : generate one-hotness conditions [default = %s]\n", fOneHot? "yes": "no" ); + Abc_Print( -2, "\t-g : generate a graph structure [default = %s]\n", fGraph? "yes": "no" ); + Abc_Print( -2, "\t-n : generate one-hotness conditions [default = %s]\n", fOneHot? "yes": "no" ); Abc_Print( -2, "\t-r : generate random single-output function [default = %s]\n", fRandom? "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"); @@ -12842,12 +14223,14 @@ int Abc_CommandTestColor( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern void Gia_Gen2CodeTest(); + extern void Dau_NetworkEnumTest(); //Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int nCutMax = 1; int nLeafMax = 4; int nDivMax = 2; - int nDecMax = 70; - int nNumOnes = 4; + int nDecMax = 3; + int nNumOnes = 0; int fNewAlgo = 0; int fNewOrder = 0; int fVerbose = 0; @@ -13000,7 +14383,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) */ { // extern void Abc_EnumerateFuncs( int nDecMax, int nDivMax, int fVerbose ); -// Abc_EnumerateFuncs( nDecMax, nDivMax, fVerbose ); +// Abc_EnumerateFuncs( 4, 7, 0 ); } /* if ( fNewAlgo ) @@ -13051,7 +14434,18 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) // Cba_PrsReadBlifTest(); } // Abc_NtkComputePaths( Abc_FrameReadNtk(pAbc) ); -// Psl_FileTest(); + //Dau_NetworkEnumTest(); + //Extra_SimulationTest( nDivMax, nNumOnes, fNewOrder ); + //Mnist_ExperimentWithScaling( nDecMax ); + //Gyx_ProblemSolveTest(); +/* + { + extern Abc_Ntk_t * Abc_NtkFromArray(); + Abc_Ntk_t * pNtkRes = Abc_NtkFromArray(); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } +*/ + return 0; usage: Abc_Print( -2, "usage: test [-CKDNM] [-aovwh] \n" ); @@ -13654,7 +15048,7 @@ int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Dar_ManDefaultRwrParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CNflzrvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "CNMflzrvwh" ) ) != EOF ) { switch ( c ) { @@ -13680,6 +15074,17 @@ int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nSubgMax < 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; + } + pPars->nMinSaved = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMinSaved < 0 ) + goto usage; + break; case 'f': pPars->fFanout ^= 1; break; @@ -13704,6 +15109,10 @@ int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( pPars->fUseZeros ) + pPars->nMinSaved = 0; + if ( pPars->nMinSaved == 0 ) + pPars->fUseZeros = 1; if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); @@ -13725,10 +15134,11 @@ int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: drw [-C num] [-N num] [-lfzrvwh]\n" ); + Abc_Print( -2, "usage: drw [-C num] [-NM num] [-lfzrvwh]\n" ); Abc_Print( -2, "\t performs combinational AIG rewriting\n" ); Abc_Print( -2, "\t-C num : the max number of cuts at a node [default = %d]\n", pPars->nCutsMax ); Abc_Print( -2, "\t-N num : the max number of subgraphs tried [default = %d]\n", pPars->nSubgMax ); + Abc_Print( -2, "\t-M num : the min number of nodes saved after one step (0 <= num) [default = %d]\n", pPars->nMinSaved ); Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" ); Abc_Print( -2, "\t-f : toggle representing fanouts [default = %s]\n", pPars->fFanout? "yes": "no" ); Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" ); @@ -14071,7 +15481,7 @@ int Abc_CommandDch( Abc_Frame_t * pAbc, int argc, char ** argv ) // set defaults Dch_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptgcfrvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptgcfrxvh" ) ) != EOF ) { switch ( c ) { @@ -14129,6 +15539,9 @@ int Abc_CommandDch( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'r': pPars->fSkipRedSupp ^= 1; break; + case 'x': + pPars->fUseNew ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -14159,7 +15572,7 @@ int Abc_CommandDch( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: dch [-WCS num] [-sptgcfrvh]\n" ); + Abc_Print( -2, "usage: dch [-WCS num] [-sptgcfrxvh]\n" ); Abc_Print( -2, "\t computes structural choices using a new approach\n" ); Abc_Print( -2, "\t-W num : the max number of simulation words [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); @@ -14171,6 +15584,7 @@ int Abc_CommandDch( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-c : toggle using circuit-based SAT vs. MiniSat [default = %s]\n", pPars->fUseCSat? "yes": "no" ); Abc_Print( -2, "\t-f : toggle using faster logic synthesis [default = %s]\n", pPars->fLightSynth? "yes": "no" ); Abc_Print( -2, "\t-r : toggle skipping choices with redundant support [default = %s]\n", pPars->fSkipRedSupp? "yes": "no" ); + Abc_Print( -2, "\t-x : toggle using new choice computation [default = %s]\n", pPars->fUseNew? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -14495,7 +15909,7 @@ int Abc_CommandIFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) nPartSize = 0; nLevelMax = 0; nConfLimit = 100; - fDoSparse = 0; + fDoSparse = 1; fProve = 0; fVerbose = 0; Extra_UtilGetoptReset(); @@ -14803,6 +16217,7 @@ int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv ) Prove_Params_t Params, * pParams = &Params; Abc_Ntk_t * pNtk, * pNtkTemp; int c, RetValue, iOut = -1; + char * pLogFileName = NULL; abctime clk; extern int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ); @@ -14813,7 +16228,7 @@ int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv ) pParams->fUseRewriting = 1; pParams->fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NCFGLIrfbvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "NCFGMILrfbvh" ) ) != EOF ) { switch ( c ) { @@ -14861,10 +16276,10 @@ int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pParams->nFraigingLimitMulti < 0 ) goto usage; break; - case 'L': + case 'M': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } pParams->nMiteringLimitLast = atoi(argv[globalUtilOptind]); @@ -14883,6 +16298,15 @@ int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pParams->nTotalInspectLimit < 0 ) goto usage; break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" ); + goto usage; + } + pLogFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'r': pParams->fUseRewriting ^= 1; break; @@ -14956,17 +16380,20 @@ int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Cex_t * pCex = Abc_CexDeriveFromCombModel( pNtkTemp->pModel, Abc_NtkPiNum(pNtkTemp), 0, iOut ); Abc_FrameReplaceCex( pAbc, &pCex ); } + if ( pLogFileName ) + Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "iprove" ); return 0; usage: - Abc_Print( -2, "usage: iprove [-NCFGLI num] [-rfbvh]\n" ); + Abc_Print( -2, "usage: iprove [-NCFGMI num] [-L file] [-rfbvh]\n" ); Abc_Print( -2, "\t performs CEC using a new method\n" ); Abc_Print( -2, "\t-N num : max number of iterations [default = %d]\n", pParams->nItersMax ); Abc_Print( -2, "\t-C num : max starting number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitStart ); Abc_Print( -2, "\t-F num : max starting number of conflicts in fraiging [default = %d]\n", pParams->nFraigingLimitStart ); Abc_Print( -2, "\t-G num : multiplicative coefficient for fraiging [default = %d]\n", (int)pParams->nFraigingLimitMulti ); - Abc_Print( -2, "\t-L num : max last-gasp number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitLast ); + Abc_Print( -2, "\t-M num : max last-gasp number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitLast ); Abc_Print( -2, "\t-I num : max number of clause inspections in all SAT calls [default = %d]\n", (int)pParams->nTotalInspectLimit ); + Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); Abc_Print( -2, "\t-r : toggle the use of rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" ); Abc_Print( -2, "\t-f : toggle the use of FRAIGing [default = %s]\n", pParams->fUseFraiging? "yes": "no" ); Abc_Print( -2, "\t-b : toggle the use of BDDs [default = %s]\n", pParams->fUseBdds? "yes": "no" ); @@ -16391,7 +17818,7 @@ int Abc_CommandRecPs3( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( !Abc_NtkRecIsRunning3() ) { - Abc_Print( -1, "This command works for AIGs only after calling \"rec_start2\".\n" ); + Abc_Print( -1, "This command works for AIGs only after calling \"rec_start3\".\n" ); return 0; } Abc_NtkRecPs3(fPrintLib); @@ -16443,7 +17870,7 @@ int Abc_CommandRecAdd3( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( !Abc_NtkRecIsRunning3() ) { - Abc_Print( -1, "This command works for AIGs after calling \"rec_start2\".\n" ); + Abc_Print( -1, "This command works for AIGs after calling \"rec_start3\".\n" ); return 0; } Abc_NtkRecAdd3( pNtk, fUseSOPB ); @@ -16528,7 +17955,7 @@ int Abc_CommandRecDump3( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( 0, "No structure in the library.\n" ); return 1; } - Gia_AigerWrite( pGia, FileName, 0, 0 ); + Gia_AigerWrite( pGia, FileName, 0, 0, 0 ); } return 0; @@ -16650,9 +18077,10 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) int fSwitching; int fSkipFanout; int fUseProfile; + 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 fVerbose ); + 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 int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); pNtk = Abc_FrameReadNtk(pAbc); @@ -16666,9 +18094,10 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) fSwitching = 0; fSkipFanout = 0; fUseProfile = 0; + fUseBuffs = 0; fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "DABFSGMarspfuvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "DABFSGMarspfuovh" ) ) != EOF ) { switch ( c ) { @@ -16763,6 +18192,9 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'u': fUseProfile ^= 1; break; + case 'o': + fUseBuffs ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -16799,7 +18231,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, fVerbose ); + pNtkRes = Abc_NtkMap( pNtk, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, fUseBuffs, fVerbose ); if ( pNtkRes == NULL ) { Abc_NtkDelete( pNtk ); @@ -16811,7 +18243,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, fVerbose ); + pNtkRes = Abc_NtkMap( pNtk, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, fUseBuffs, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Mapping has failed.\n" ); @@ -16838,7 +18270,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) sprintf(Buffer, "not used" ); else sprintf(Buffer, "%.3f", DelayTarget ); - Abc_Print( -2, "usage: map [-DABFSG float] [-M num] [-arspfuvh]\n" ); + Abc_Print( -2, "usage: map [-DABFSG float] [-M num] [-arspfuovh]\n" ); Abc_Print( -2, "\t performs standard cell mapping of the current network\n" ); Abc_Print( -2, "\t-D float : sets the global required times [default = %s]\n", Buffer ); Abc_Print( -2, "\t-A float : \"area multiplier\" to bias gate selection [default = %.2f]\n", AreaMulti ); @@ -16853,6 +18285,7 @@ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-p : optimizes power by minimizing switching [default = %s]\n", fSwitching? "yes": "no" ); Abc_Print( -2, "\t-f : do not use large gates to map high-fanout nodes [default = %s]\n", fSkipFanout? "yes": "no" ); Abc_Print( -2, "\t-u : use standard-cell profile [default = %s]\n", fUseProfile? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles using buffers to decouple combinational outputs [default = %s]\n", fUseBuffs? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -18710,7 +20143,7 @@ int Abc_CommandDsdPs( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t prints statistics of the DSD manager\n" ); Abc_Print( -2, "\t-N num : show structures whose ID divides by N [default = %d]\n", Number ); Abc_Print( -2, "\t-S num : show structures whose support size is S [default = %d]\n", Support ); - Abc_Print( -2, "\t-o : toggles printing occurence distribution [default = %s]\n", fOccurs? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles printing occurrence distribution [default = %s]\n", fOccurs? "yes": "no" ); Abc_Print( -2, "\t-t : toggles dumping truth tables [default = %s]\n", fTtDump? "yes": "no" ); Abc_Print( -2, "\t-b : toggles processing second manager [default = %s]\n", fSecond? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); @@ -18732,10 +20165,10 @@ int Abc_CommandDsdPs( Abc_Frame_t * pAbc, int argc, char ** argv ) int Abc_CommandDsdMatch( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * pStruct = NULL; - int c, fVerbose = 0, fFast = 0, fAdd = 0, fSpec = 0, LutSize = 0, nConfls = 10000, nProcs = 1; + int c, fVerbose = 0, fFast = 0, fAdd = 0, fSpec = 0, LutSize = 0, nConfls = 10000, nProcs = 1, nInputs = 0; If_DsdMan_t * pDsdMan = (If_DsdMan_t *)Abc_FrameReadManDsd(); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCPSfasvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCPISfasvh" ) ) != EOF ) { switch ( c ) { @@ -18768,6 +20201,15 @@ int Abc_CommandDsdMatch( Abc_Frame_t * pAbc, int argc, char ** argv ) nProcs = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a floating point number.\n" ); + goto usage; + } + nInputs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; case 'S': if ( globalUtilOptind >= argc ) { @@ -18808,18 +20250,19 @@ int Abc_CommandDsdMatch( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "DSD manager matched with cell %s should be cleaned by \"dsd_filter -m\" before matching with cell %s.\n", pStructCur, pStruct ); return 0; } - Id_DsdManTuneStr( pDsdMan, pStruct, nConfls, nProcs, fVerbose ); + Id_DsdManTuneStr( pDsdMan, pStruct, nConfls, nProcs, nInputs, fVerbose ); } else If_DsdManTune( pDsdMan, LutSize, fFast, fAdd, fSpec, fVerbose ); return 0; usage: - Abc_Print( -2, "usage: dsd_match [-KCP num] [-fasvh] [-S str]\n" ); + Abc_Print( -2, "usage: dsd_match [-KCPI num] [-fasvh] [-S str]\n" ); Abc_Print( -2, "\t matches DSD structures with the given cell\n" ); Abc_Print( -2, "\t-K num : LUT size used for tuning [default = %d]\n", LutSize ); Abc_Print( -2, "\t-C num : the maximum number of conflicts [default = %d]\n", nConfls ); Abc_Print( -2, "\t-P num : the maximum number of processes [default = %d]\n", nProcs ); + Abc_Print( -2, "\t-I num : skip checking if support is less than this [default = %d]\n", nInputs ); Abc_Print( -2, "\t-f : toggles using fast check [default = %s]\n", fFast? "yes": "no" ); Abc_Print( -2, "\t-a : toggles adding tuning to the current one [default = %s]\n", fAdd? "yes": "no" ); Abc_Print( -2, "\t-s : toggles using specialized check [default = %s]\n", fSpec? "yes": "no" ); @@ -19441,9 +20884,15 @@ int Abc_CommandPipe( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - if ( Abc_NtkIsComb(pNtk) ) + if ( !Abc_NtkIsLogic(pNtk) ) { - Abc_Print( 0, "The current network is combinational.\n" ); + Abc_Print( 0, "Abc_CommandPipe(): Expecting a logic network (run command \"logic\").\n" ); + return 0; + } + + if ( !Abc_NtkIsComb(pNtk) ) + { + Abc_Print( 0, "Abc_CommandPipe(): Expecting a combinational network.\n" ); return 0; } @@ -20574,15 +22023,14 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; Ssw_Pars_t Pars, * pPars = &Pars; - int nConstrs = 0; - int c; + int c, nConstrs = 0; extern Abc_Ntk_t * Abc_NtkDarSeqSweep2( Abc_Ntk_t * pNtk, Ssw_Pars_t * pPars ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults Ssw_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLSIVMNcmplkodsefqvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "PQFCLSIVMNXcmplkodsefqvwh" ) ) != EOF ) { switch ( c ) { @@ -20696,6 +22144,17 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nConstrs < 0 ) goto usage; break; + case 'X': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-X\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nLimitMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLimitMax < 0 ) + goto usage; + break; case 'c': pPars->fConstrs ^= 1; break; @@ -20786,10 +22245,18 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->fConstrs ) { + if ( Abc_NtkConstrNum(pNtk) == Abc_NtkPoNum(pNtk) ) + { + Abc_Print( 0, "Command cannot be applied because the network has only constraint outputs (no primary outputs).\n" ); + return 0; + } if ( Abc_NtkConstrNum(pNtk) > 0 ) Abc_Print( 0, "Performing scorr with %d constraints.\n", Abc_NtkConstrNum(pNtk) ); else + { Abc_Print( 0, "Performing constraint-based scorr without constraints.\n" ); + pPars->fConstrs = 0; + } } if ( pPars->fEquivDump && pPars->fEquivDump2 ) { @@ -20809,7 +22276,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: scorr [-PQFCLSIVMN ] [-cmplkodsefqvwh]\n" ); + Abc_Print( -2, "usage: scorr [-PQFCLSIVMNX ] [-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 ); @@ -20822,6 +22289,7 @@ int Abc_CommandSeqSweep2( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-V num : min var num needed to recycle the SAT solver [default = %d]\n", pPars->nSatVarMax2 ); 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-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" ); @@ -21132,10 +22600,11 @@ int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv ) int nFramesP; int nConfMax; int nVarsMax; + int nLimitMax; int fNewAlgor; int fVerbose; extern Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose ); - extern Abc_Ntk_t * Abc_NtkDarLcorrNew( Abc_Ntk_t * pNtk, int nVarsMax, int nConfMax, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkDarLcorrNew( Abc_Ntk_t * pNtk, int nVarsMax, int nConfMax, int nLimitMax, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); @@ -21145,10 +22614,11 @@ int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv ) nFramesP = 0; nConfMax = 1000; nVarsMax = 1000; + nLimitMax = 0; fNewAlgor = 1; fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PCSnvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "PCSXnvh" ) ) != EOF ) { switch ( c ) { @@ -21185,6 +22655,17 @@ int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nVarsMax < 0 ) goto usage; break; + case 'X': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-X\" should be followed by an integer.\n" ); + goto usage; + } + nLimitMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLimitMax < 0 ) + goto usage; + break; case 'n': fNewAlgor ^= 1; break; @@ -21218,7 +22699,7 @@ int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv ) // get the new network if ( fNewAlgor ) - pNtkRes = Abc_NtkDarLcorrNew( pNtk, nVarsMax, nConfMax, fVerbose ); + pNtkRes = Abc_NtkDarLcorrNew( pNtk, nVarsMax, nConfMax, nLimitMax, fVerbose ); else pNtkRes = Abc_NtkDarLcorr( pNtk, nFramesP, nConfMax, fVerbose ); if ( pNtkRes == NULL ) @@ -21231,11 +22712,12 @@ int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: lcorr [-PCS num] [-nvh]\n" ); + Abc_Print( -2, "usage: lcorr [-PCSX num] [-nvh]\n" ); Abc_Print( -2, "\t computes latch correspondence using 1-step induction\n" ); Abc_Print( -2, "\t-P num : number of time frames to use as the prefix [default = %d]\n", nFramesP ); Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfMax ); Abc_Print( -2, "\t-S num : the max number of SAT variables [default = %d]\n", nVarsMax ); + Abc_Print( -2, "\t-X num : the number of iterations of little or no improvement [default = %d]\n", nLimitMax ); Abc_Print( -2, "\t-n : toggle using new algorithm [default = %s]\n", fNewAlgor? "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"); @@ -21563,6 +23045,7 @@ int Abc_CommandSim( Abc_Frame_t * pAbc, int argc, char ** argv ) int fMiter; int fVerbose; char * pFileSim; + char * pLogFileName = NULL; extern int Abc_NtkDarSeqSim( Abc_Ntk_t * pNtk, int nFrames, int nWords, int TimeOut, int fNew, int fMiter, int fVerbose, char * pFileSim ); // set defaults fNew = 0; @@ -21574,7 +23057,7 @@ int Abc_CommandSim( Abc_Frame_t * pAbc, int argc, char ** argv ) fVerbose = 0; pFileSim = NULL; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FWTAnmvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "FWTALnmvh" ) ) != EOF ) { switch ( c ) { @@ -21620,6 +23103,15 @@ int Abc_CommandSim( Abc_Frame_t * pAbc, int argc, char ** argv ) pFileSim = argv[globalUtilOptind]; globalUtilOptind++; break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" ); + goto usage; + } + pLogFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'n': fNew ^= 1; break; @@ -21653,16 +23145,19 @@ int Abc_CommandSim( Abc_Frame_t * pAbc, int argc, char ** argv ) ABC_FREE( pNtk->pSeqModel ); pAbc->Status = Abc_NtkDarSeqSim( pNtk, nFrames, nWords, TimeOut, fNew, fMiter, fVerbose, pFileSim ); Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); + if ( pLogFileName ) + Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "sim" ); return 0; usage: - Abc_Print( -2, "usage: sim [-FWT num] [-A file] [-nmvh]\n" ); + Abc_Print( -2, "usage: sim [-FWT num] [-AL file] [-nmvh]\n" ); Abc_Print( -2, "\t performs random simulation of the sequential miter\n" ); Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", nWords ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", TimeOut ); Abc_Print( -2, "\t-A file : text file name with user's patterns [default = random simulation]\n" ); Abc_Print( -2, "\t (patterns are listed, one per line, as sequences of 0s and 1s)\n" ); + Abc_Print( -2, "\t-L file : the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); Abc_Print( -2, "\t-n : toggle new vs. old implementation [default = %s]\n", fNew? "new": "old" ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", fMiter? "miter": "circuit" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); @@ -21688,10 +23183,11 @@ int Abc_CommandSim3( Abc_Frame_t * pAbc, int argc, char ** argv ) Ssw_RarPars_t Pars, * pPars = &Pars; Abc_Ntk_t * pNtkRes, * pNtk = Abc_FrameReadNtk(pAbc); Vec_Ptr_t * vSeqModelVec; + char * pLogFileName = NULL; int c; Ssw_RarSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FWBRSNTGadivzh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "FWBRSNTGLadivzh" ) ) != EOF ) { switch ( c ) { @@ -21783,6 +23279,15 @@ int Abc_CommandSim3( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->TimeOutGap < 0 ) goto usage; break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" ); + goto usage; + } + pLogFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'a': pPars->fSolveAll ^= 1; break; @@ -21865,10 +23370,12 @@ int Abc_CommandSim3( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_FrameReplaceCexVec( pAbc, &vSeqModelVec ); pAbc->nFrames = -1; } + if ( pLogFileName ) + Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "sim3" ); return 0; usage: - Abc_Print( -2, "usage: sim3 [-FWBRSNTG num] [-advzh]\n" ); + Abc_Print( -2, "usage: sim3 [-FWBRSNTG num] [-L file] [-advzh]\n" ); Abc_Print( -2, "\t performs random simulation of the sequential miter\n" ); Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", pPars->nFrames ); Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", pPars->nWords ); @@ -21878,6 +23385,7 @@ int Abc_CommandSim3( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-N num : random number seed (1 <= num <= 1000) [default = %d]\n", pPars->nRandSeed ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeOut ); Abc_Print( -2, "\t-G num : approximate runtime gap in seconds since the last CEX [default = %d]\n", pPars->TimeOutGap ); + Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); Abc_Print( -2, "\t-a : toggle solving all outputs (do not stop when one is SAT) [default = %s]\n", pPars->fSolveAll? "yes": "no" ); Abc_Print( -2, "\t-d : toggle dropping (replacing by 0) SAT outputs [default = %s]\n", pPars->fDropSatOuts? "yes": "no" ); Abc_Print( -2, "\t-i : toggle changing init state to a last rare state [default = %s]\n", pPars->fVerbose? "yes": "no" ); @@ -21887,7 +23395,6 @@ int Abc_CommandSim3( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } - /**Function************************************************************* Synopsis [] @@ -22523,6 +24030,107 @@ int Abc_CommandInsWin( Abc_Frame_t * pAbc, int argc, char ** argv ) } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSymFun( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Ntk_SymFunGenerate( int nVars, int fVerbose ); + word * pFun = NULL; + char * pStr, * pTruth, * pCommand; + int c, k, nVars = -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 a file name.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + Abc_Print( -2, "Unknown switch.\n"); + goto usage; + } + } + if ( nVars != -1 ) + { + if ( nVars < 1 || nVars > 16 ) + { + printf( "Cannot generate functions for less than 1 and more than %d variables.\n", nVars ); + return 1; + } + Ntk_SymFunGenerate( nVars, fVerbose ); + return 0; + } + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( -1, "Not enough command-line arguments.\n" ); + return 1; + } + // make sure the string is composed of N+1 zeros and ones + pStr = argv[globalUtilOptind]; + nVars = strlen(pStr) - 1; + for ( k = 0; k <= nVars; k++ ) + if ( pStr[k] != '0' && pStr[k] != '1' ) + break; + if ( k <= nVars ) + { + Abc_Print( -1, "The string should be composed of zeros and ones.\n" ); + return 1; + } + // generate and print one function + pFun = Abc_TtSymFunGenerate( pStr, nVars ); + pTruth = ABC_CALLOC( char, nVars > 2 ? (1 << (nVars-2)) + 1 : 2 ); + Extra_PrintHexadecimalString( pTruth, (unsigned *)pFun, nVars ); + ABC_FREE( pFun ); + if ( fVerbose ) + { + if ( nVars > 6 ) + printf( "Generated truth table of the %d-variable function and set it as the current network.\n", nVars ); + else + printf( "Generated truth table of the %d-variable function (%s) and set it as the current network\n", nVars, pTruth ); + } + else if ( nVars <= 8 ) + printf( "%s\n", pTruth ); + // read the truth table to be the current network in ABC + pCommand = ABC_CALLOC( char, strlen(pTruth) + 100 ); + sprintf( pCommand, "read_truth %s", pTruth ); + Cmd_CommandExecute( pAbc, pCommand ); + ABC_FREE( pCommand ); + ABC_FREE( pTruth ); + return 0; + +usage: + Abc_Print( -2, "usage: symfun [-N num] [-vh] \n" ); + Abc_Print( -2, "\t generated a single-output symmetric function\n" ); + Abc_Print( -2, "\t-N : prints truth tables of all N-var symmetric functions [default = not used]\n" ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the string of N+1 zeros and ones, where N is the number of variables\n" ); + Abc_Print( -2, "\t For example, to get 3-input NAND-gate, use \"symfun 1000\".\n" ); + Abc_Print( -2, "\t To get 5-input majority gate, use \"symfun 000111\".\n" ); + + return 1; +} /**Function************************************************************* Synopsis [] @@ -22545,12 +24153,24 @@ int Abc_CommandPermute( Abc_Frame_t * pAbc, int argc, char ** argv ) int fFlops = 1; int fNodes = 1; int fFanout = 0; + int Seed = -1; int c; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Fiofnxh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "SFiofnxh" ) ) != EOF ) { switch ( c ) { + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Seed < 0 ) + goto usage; + break; case 'F': if ( globalUtilOptind >= argc ) { @@ -22582,6 +24202,8 @@ int Abc_CommandPermute( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( Seed >= 0 ) + srand( (unsigned)Seed ); if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); @@ -22616,8 +24238,9 @@ int Abc_CommandPermute( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: permute [-iofnxh] [-F filename]\n" ); + Abc_Print( -2, "usage: permute [-S num] [-iofnxh] [-F filename]\n" ); Abc_Print( -2, "\t performs random permutation of inputs/outputs/flops\n" ); + Abc_Print( -2, "\t-S num : the random seed to generate permutations (0 <= num < INT_MAX) [default = %d]\n", Seed ); Abc_Print( -2, "\t-i : toggle permuting primary inputs [default = %s]\n", fInputs? "yes": "no" ); Abc_Print( -2, "\t-o : toggle permuting primary outputs [default = %s]\n", fOutputs? "yes": "no" ); Abc_Print( -2, "\t-f : toggle permuting flip-flops [default = %s]\n", fFlops? "yes": "no" ); @@ -22727,6 +24350,197 @@ int Abc_CommandCubeEnum( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPathEnum( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_EnumerateFrontierTest( int nSize ); + int c, nSize = 4, fZddAlgo = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSize < 0 ) + goto usage; + break; + case 'z': + fZddAlgo ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + Abc_Print( -2, "Unknown switch.\n"); + goto usage; + } + } + Abc_EnumerateFrontierTest( nSize ); + return 0; + +usage: + Abc_Print( -2, "usage: pathenum [-N num] [-vh]\n" ); + Abc_Print( -2, "\t enumerates self-avoiding paths on the NxN grid\n" ); + Abc_Print( -2, "\t-N num : the size of the grid to consider [default = %d]\n", nSize ); +// Abc_Print( -2, "\t-z : toggle using ZDD-based algorithm [default = %s]\n", fZddAlgo? "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"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFunEnum( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Dtt_EnumerateLf( int nVars, int nNodeMax, int fDelay, int fMulti, int fVerbose, char* pFileName ); + extern void Dau_FunctionEnum( int nInputs, int nVars, int nNodeMax, int fUseTwo, int fReduce, int fVerbose ); + extern Gia_Man_t * Dau_ConstructAigFromFile( char * pFileName ); + int c, nInputs = 4, nVars = 4, nNodeMax = 32, fUseTwo = 0, fReduce = 0, fSimple = 0, fDelay = 0, fMulti = 0, fDump = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "SIMtrldmpvh" ) ) != EOF ) + { + switch ( c ) + { + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + nInputs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nInputs < 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; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 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; + } + nNodeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodeMax < 0 ) + goto usage; + break; + case 't': + fUseTwo ^= 1; + break; + case 'r': + fReduce ^= 1; + break; + case 'l': + fSimple ^= 1; + break; + case 'd': + fDelay ^= 1; + break; + case 'm': + fMulti ^= 1; + break; + case 'p': + fDump ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + Abc_Print( -2, "Unknown switch.\n"); + goto usage; + } + } + if ( fSimple || fDelay ) + { + char Buffer[100]; + if ( nVars < 3 || nVars > 5 ) + { + Abc_Print( -1, "The number of inputs should be 3 <= I <= 5.\n" ); + goto usage; + } + sprintf( Buffer, "Lflib%d.txt", nVars ); + Dtt_EnumerateLf( nVars, nNodeMax, fDelay, fMulti, fVerbose, fDump?Buffer:NULL ); + if ( fDump ) + { + Gia_Man_t * pTemp; + pTemp = Dau_ConstructAigFromFile( Buffer ); + Abc_FrameUpdateGia( pAbc, pTemp ); + Gia_DumpAiger( pTemp, "Lflib", nVars, 1 ); + } + } + else + { + if ( nVars < 2 || nVars > 6 ) + { + Abc_Print( -1, "The number of inputs should be 2 <= I <= 6.\n" ); + goto usage; + } + if ( nInputs < nVars || nInputs > 6 ) + { + Abc_Print( -1, "The intermediate support size should be I <= S <= 6.\n" ); + goto usage; + } + Dau_FunctionEnum( nInputs, nVars, nNodeMax, fUseTwo, fReduce, fVerbose ); + } + return 0; + +usage: + Abc_Print( -2, "usage: funenum [-SIM num] [-trldmvph]\n" ); + Abc_Print( -2, "\t enumerates minimum 2-input-gate implementations\n" ); + Abc_Print( -2, "\t-S num : the maximum intermediate support size [default = %d]\n", nInputs ); + Abc_Print( -2, "\t-I num : the number of inputs of Boolean functions [default = %d]\n", nVars ); + Abc_Print( -2, "\t-M num : the maximum number of 2-input gates [default = %d]\n", nNodeMax ); + Abc_Print( -2, "\t-t : toggle adding combination of two gates [default = %s]\n", fUseTwo? "yes": "no" ); + Abc_Print( -2, "\t-r : toggle reducing the last level [default = %s]\n", fReduce? "yes": "no" ); + Abc_Print( -2, "\t-l : toggle generating L(f) rather than C(f) [default = %s]\n", fSimple? "yes": "no" ); + Abc_Print( -2, "\t-d : toggle generating D(f) rather than C(f) [default = %s]\n", fDelay? "yes": "no" ); + Abc_Print( -2, "\t-m : toggle generating multiplicity statistics [default = %s]\n", fMulti? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-p : toggle dumping result library (formula and AIG) [default = %s]\n",fDump?"yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* @@ -23173,7 +24987,7 @@ int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv ) } // perform verification - Abc_NtkDarSec( pNtk1, pNtk2, pSecPar ); + pAbc->Status = Abc_NtkDarSec( pNtk1, pNtk2, pSecPar ); if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); @@ -23400,12 +25214,16 @@ int Abc_CommandDProve( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Empty network.\n" ); return 1; } - if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for structrally hashed networks. Run \"st\".\n" ); return 0; } + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } // perform verification pAbc->Status = Abc_NtkDarProve( pNtk, pSecPar, nBmcFramesMax, nBmcConfMax ); @@ -24364,7 +26182,7 @@ int Abc_CommandSatoko( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-Q num : Min clause LBD for binary resolution [default = %d]\n", opts.clause_min_lbd_bin_resol ); Abc_Print( -2, "\n\tConstants used for branching (VSIDS heuristic):\n"); Abc_Print( -2, "\t-R num : Clause activity decay factor (when using float clause activity) [default = %f]\n", opts.clause_decay ); - Abc_Print( -2, "\t-S num : Varibale activity decay factor [default = %f]\n", opts.var_decay ); + Abc_Print( -2, "\t-S num : Variable activity decay factor [default = %f]\n", opts.var_decay ); #ifdef SATOKO_ACT_VAR_FIXED Abc_Print( -2, "\t-T num : Variable activity limit valeu [default = 0x%08X]\n", opts.var_act_limit ); Abc_Print( -2, "\t-U num : Variable activity re-scale factor [default = 0x%08X]\n", opts.var_act_rescale ); @@ -24519,6 +26337,117 @@ int Abc_CommandAbc9Sat3( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Kissat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Mf_ManDumpCnf( Gia_Man_t * p, char * pFileName, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); + extern void Gia_ManKissatCall( Abc_Frame_t * pAbc, char * pFileName, char * pArgs, int nConfs, int nTimeLimit, int fSat, int fUnsat, int fPrintCex, int fVerbose ); + int c, nConfs = 0, nTimeLimit = 0, fSat = 0, fUnsat = 0, fPrintCex = 0, fVerbose = 0; + char * pArgs = NULL; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CTAsucvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfs < 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + nTimeLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nTimeLimit < 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; + } + pArgs = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 's': + fSat ^= 1; + break; + case 'u': + fUnsat ^= 1; + break; + case 'c': + fPrintCex ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + + default: + goto usage; + } + } + if ( argc == globalUtilOptind + 1 ) + { + Gia_ManKissatCall( pAbc, argv[globalUtilOptind], pArgs, nConfs, nTimeLimit, fSat, fUnsat, fPrintCex, fVerbose ); + return 0; + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Satoko(): There is no AIG.\n" ); + return 1; + } + else + { + int nLutSize = 8; + int fCnfObjIds = 0; + int fAddOrCla = 1; + char * pFileName = "_temp_.cnf"; + Mf_ManDumpCnf( pAbc->pGia, pFileName, nLutSize, fCnfObjIds, fAddOrCla, fVerbose ); + Gia_ManKissatCall( pAbc, pFileName, pArgs, nConfs, nTimeLimit, fSat, fUnsat, fPrintCex, fVerbose ); + unlink( pFileName ); + } + return 0; + +usage: + Abc_Print( -2, "usage: &kissat [-CT num] [-sucvh] [-A string] \n" ); + Abc_Print( -2, "\t run SAT solver Kissat, by Armin Biere (https://github.com/arminbiere/kissat)\n" ); + Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfs ); + Abc_Print( -2, "\t-T num : runtime limit in seconds [default = %d]\n", nTimeLimit ); + Abc_Print( -2, "\t-s : expect a satisfiable problem [default = %s]\n", fSat ? "yes": "no" ); + Abc_Print( -2, "\t-u : expect an unsatisfiable problem [default = %s]\n", fUnsat ? "yes": "no" ); + Abc_Print( -2, "\t-c : prints satisfying assignment if satisfiable [default = %s]\n", fPrintCex ? "yes": "no" ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose ? "yes": "no" ); + Abc_Print( -2, "\t-A num : string containing additional command-line args for the Kissat binary [default = %s]\n", pArgs ? pArgs : "unused" ); + Abc_Print( -2, "\t (in particular, <&kissat -A \"--help\"> prints all command-line args of Kissat)\n" ); + Abc_Print( -2, "\t : (optional) CNF file to solve\n"); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -25104,6 +27033,11 @@ int Abc_CommandBmc( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Does not work for combinational networks.\n" ); return 0; } + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } pAbc->Status = Abc_NtkDarBmc( pNtk, 0, nFrames, nSizeMax, nNodeDelta, 0, nBTLimit, nBTLimitAll, fRewrite, fNewAlgo, 0, nCofFanLit, fVerbose, &iFrames, fUseSatoko ); pAbc->nFrames = iFrames; Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); @@ -25299,6 +27233,11 @@ int Abc_CommandBmc2( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Does not work for combinational networks.\n" ); return 0; } + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } pAbc->Status = Abc_NtkDarBmc( pNtk, nStart, nFrames, nSizeMax, nNodeDelta, nTimeOut, nBTLimit, nBTLimitAll, fRewrite, fNewAlgo, fOrDecomp, 0, fVerbose, &iFrames, fUseSatoko ); pAbc->nFrames = iFrames; Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); @@ -25553,6 +27492,11 @@ int Abc_CommandBmc3( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Constraints have to be folded (use \"fold\").\n" ); return 0; } + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } pPars->fUseBridge = pAbc->fBridgeMode; pAbc->Status = Abc_NtkDarBmc3( pNtk, pPars, fOrDecomp ); pAbc->nFrames = pNtk->vSeqModelVec ? -1 : pPars->iFrame; @@ -25592,7 +27536,7 @@ int Abc_CommandBmc3( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-S num : the starting time frame [default = %d]\n", pPars->nStart ); Abc_Print( -2, "\t-F num : the max number of time frames (0 = unused) [default = %d]\n", pPars->nFramesMax ); Abc_Print( -2, "\t-T num : runtime limit, in seconds [default = %d]\n", pPars->nTimeOut ); - Abc_Print( -2, "\t-H num : runtime limit per output, in miliseconds (with \"-a\") [default = %d]\n", pPars->nTimeOutOne ); + Abc_Print( -2, "\t-H num : runtime limit per output, in milliseconds (with \"-a\") [default = %d]\n", pPars->nTimeOutOne ); Abc_Print( -2, "\t-G num : runtime gap since the last CEX, in seconds [default = %d]\n", pPars->nTimeOutGap ); Abc_Print( -2, "\t-C num : max conflicts at an output [default = %d]\n", pPars->nConfLimit ); Abc_Print( -2, "\t-D num : max conflicts after jumping (0 = infinity) [default = %d]\n", pPars->nConfLimitJump ); @@ -25759,6 +27703,11 @@ int Abc_CommandBmcInter( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); return 0; } + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } if ( Abc_NtkLatchNum(pNtk) == 0 ) { Abc_Print( -1, "Does not work for combinational networks.\n" ); @@ -26581,6 +28530,7 @@ int Abc_CommandConstr( Abc_Frame_t * pAbc, int argc, char ** argv ) 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" ); + Abc_Print( -2, "\t (constraints fail when any of them becomes 1 in any timeframe)\n" ); Abc_Print( -2, "\t-F num : the max number of timeframes to consider [default = %d]\n", nFrames ); 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 ); @@ -26803,6 +28753,11 @@ int Abc_CommandFold( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( 0, "The network has no constraints.\n" ); return 0; } + if ( Abc_NtkConstrNum(pNtk) == Abc_NtkPoNum(pNtk) ) + { + Abc_Print( 0, "The network has no primary outputs (only constraints).\n" ); + return 0; + } if ( Abc_NtkIsComb(pNtk) ) Abc_Print( 0, "The network is combinational.\n" ); // modify the current network @@ -26818,6 +28773,7 @@ int Abc_CommandFold( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: Abc_Print( -2, "usage: fold [-cvh]\n" ); Abc_Print( -2, "\t folds constraints represented as separate outputs\n" ); + 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-h : print the command usage\n"); @@ -27114,7 +29070,7 @@ int Abc_CommandSaucy( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Obj_t * pNodePo; FILE * hadi = fopen("hadi.txt", "w"); Abc_NtkForEachPo( pNtk, pNodePo, i ) { - printf("Ouput %s\n\n", Abc_ObjName(pNodePo)); + printf("Output %s\n\n", Abc_ObjName(pNodePo)); saucyGateWay( pNtk, pNodePo, gFile, 0, fLookForSwaps, fFixOutputs, fFixInputs, fQuiet, fPrintTree ); printf("----------------------------------------\n"); } @@ -27140,7 +29096,7 @@ int Abc_CommandSaucy( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: Abc_Print( -2, "usage: saucy3 [-O ] [-F ] [-iosqvh]\n\n" ); - Abc_Print( -2, "\t computes functional symmetries of the netowrk\n" ); + Abc_Print( -2, "\t computes functional symmetries of the network\n" ); Abc_Print( -2, "\t prints symmetry generators to the standard output\n" ); Abc_Print( -2, "\t-O : (optional) compute symmetries only for output given by name\n"); Abc_Print( -2, "\t only inputs in the output cone are permuted\n"); @@ -27285,11 +29241,12 @@ int Abc_CommandPdr( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_NtkDarPdr( Abc_Ntk_t * pNtk, Pdr_Par_t * pPars ); Pdr_Par_t Pars, * pPars = &Pars; - Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkUsed, * pNtkFlop = NULL; + char * pLogFileName = NULL; int c; Pdr_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "MFCDQTHGSaxrmuyfqipdegjonctkvwzh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "MFCDQTHGSLIaxrmuyfqipdegjonctkvwzh" ) ) != EOF ) { switch ( c ) { @@ -27392,6 +29349,24 @@ int Abc_CommandPdr( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nRandomSeed < 0 ) goto usage; break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" ); + goto usage; + } + pLogFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a file name.\n" ); + goto usage; + } + pPars->pInvFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'a': pPars->fSolveAll ^= 1; break; @@ -27468,29 +29443,38 @@ int Abc_CommandPdr( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "There is no current network.\n"); return 0; } - if ( Abc_NtkLatchNum(pNtk) == 0 ) - { - Abc_Print( 0, "The current network is combinational.\n"); - return 0; - } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -2, "The current network is not an AIG (run \"strash\").\n"); return 0; } + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + pNtkFlop = Abc_NtkDup( pNtk ); + Abc_NtkAddLatch( pNtkFlop, Abc_AigConst1(pNtkFlop), ABC_INIT_ONE ); + } // run the procedure pPars->fUseBridge = pAbc->fBridgeMode; - pAbc->Status = Abc_NtkDarPdr( pNtk, pPars ); - pAbc->nFrames = pNtk->vSeqModelVec ? -1 : pPars->iFrame; + pNtkUsed = pNtkFlop ? pNtkFlop : pNtk; + pAbc->Status = Abc_NtkDarPdr( pNtkUsed, pPars ); + pAbc->nFrames = pNtkUsed->vSeqModelVec ? -1 : pPars->iFrame; Abc_FrameReplacePoStatuses( pAbc, &pPars->vOutMap ); - if ( pNtk->vSeqModelVec ) - Abc_FrameReplaceCexVec( pAbc, &pNtk->vSeqModelVec ); + if ( pNtkUsed->vSeqModelVec ) + Abc_FrameReplaceCexVec( pAbc, &pNtkUsed->vSeqModelVec ); else - Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); + Abc_FrameReplaceCex( pAbc, &pNtkUsed->pSeqModel ); + if ( pNtkFlop ) Abc_NtkDelete( pNtkFlop ); + if ( pLogFileName ) + Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "pdr" ); return 0; usage: - Abc_Print( -2, "usage: pdr [-MFCDQTHGS ] [-axrmuyfqipdegjonctkvwzh]\n" ); + Abc_Print( -2, "usage: pdr [-MFCDQTHGS ] [-LI ] [-axrmuyfqipdegjonctkvwzh]\n" ); Abc_Print( -2, "\t model checking using property directed reachability (aka IC3)\n" ); Abc_Print( -2, "\t pioneered by Aaron R. Bradley (http://theory.stanford.edu/~arbrad/)\n" ); Abc_Print( -2, "\t with improvements by Niklas Een (http://een.se/niklas/)\n" ); @@ -27500,9 +29484,11 @@ int Abc_CommandPdr( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-D num : limit on conflicts during ind-generalization (0 = no limit) [default = %d]\n",pPars->nConfGenLimit ); Abc_Print( -2, "\t-Q num : limit on proof obligations before a restart (0 = no limit) [default = %d]\n", pPars->nRestLimit ); Abc_Print( -2, "\t-T num : runtime limit, in seconds (0 = no limit) [default = %d]\n", pPars->nTimeOut ); - Abc_Print( -2, "\t-H num : runtime limit per output, in miliseconds (with \"-a\") [default = %d]\n", pPars->nTimeOutOne ); + Abc_Print( -2, "\t-H num : runtime limit per output, in milliseconds (with \"-a\") [default = %d]\n", pPars->nTimeOutOne ); Abc_Print( -2, "\t-G num : runtime gap since the last CEX (0 = no limit) [default = %d]\n", pPars->nTimeOutGap ); Abc_Print( -2, "\t-S num : * value to seed the SAT solver with [default = %d]\n", pPars->nRandomSeed ); + Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); + Abc_Print( -2, "\t-I file: the invariant file name [default = %s]\n", pPars->pInvFileName ? pPars->pInvFileName : "default name" ); Abc_Print( -2, "\t-a : toggle solving all outputs even if one of them is SAT [default = %s]\n", pPars->fSolveAll? "yes": "no" ); Abc_Print( -2, "\t-x : toggle storing CEXes when solving all outputs [default = %s]\n", pPars->fStoreCex? "yes": "no" ); Abc_Print( -2, "\t-r : toggle using more effort in generalization [default = %s]\n", pPars->fTwoRounds? "yes": "no" ); @@ -28454,9 +30440,11 @@ int Abc_CommandTraceCheck( Abc_Frame_t * pAbc, int argc, char ** argv ) } + + /**Function************************************************************* - Synopsis [] + Synopsis [Compares to versions of the design and finds the best.] Description [] @@ -28465,90 +30453,35 @@ int Abc_CommandTraceCheck( Abc_Frame_t * pAbc, int argc, char ** argv ) SeeAlso [] ***********************************************************************/ -int Abc_CommandAbc9Read( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - extern void Abc3_ReadShowHie( char * pFileName, int fFlat ); - Gia_Man_t * pAig = NULL; - FILE * pFile; - char ** pArgvNew; - char * FileName, * pTemp; - int c, nArgcNew; - int fMiniAig = 0; - int fMiniLut = 0; - int fVerbose = 0; - int fGiaSimple = 0; - int fSkipStrash = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "csmlvh" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fGiaSimple ^= 1; - break; - case 's': - fSkipStrash ^= 1; - break; - case 'm': - fMiniAig ^= 1; - break; - case 'l': - fMiniLut ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - default: - goto usage; - } - } - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( nArgcNew != 1 ) - { - Abc_Print( -1, "There is no file name.\n" ); - return 1; - } +static inline int Abc_NtkCompareWithBest( Abc_Ntk_t * pBest, Abc_Ntk_t * p, + float * pnBestNtkArea, float * pnBestNtkDelay, + int * pnBestNtkNodes, int * pnBestNtkLevels, int fArea ) +{ + float nNtkArea = (float)Abc_NtkGetMappedArea(p); + float nNtkDelay = (float)Abc_NtkDelayTrace(p, NULL, NULL, 0); + int nNtkNodes = Abc_NtkNodeNum(p); + int nNtkLevels = Abc_NtkLevel(p); - // get the input file name - FileName = pArgvNew[0]; - // fix the wrong symbol - for ( pTemp = FileName; *pTemp; pTemp++ ) - if ( *pTemp == '>' ) - *pTemp = '\\'; - if ( (pFile = fopen( FileName, "r" )) == NULL ) + if ( pBest == NULL || + Abc_NtkPiNum(pBest) != Abc_NtkPiNum(p) || + Abc_NtkPoNum(pBest) != Abc_NtkPoNum(p) || + Abc_NtkLatchNum(pBest) != Abc_NtkLatchNum(p) || + strcmp(Abc_NtkName(pBest), Abc_NtkName(p)) || +// (!fArea && (*pnBestNtkLevels > nNtkLevels || (*pnBestNtkLevels == nNtkLevels && *pnBestNtkDelay > nNtkDelay ))) || +// ( fArea && (*pnBestNtkNodes > nNtkNodes || (*pnBestNtkNodes == nNtkNodes && *pnBestNtkArea > nNtkArea ))) + (!fArea && (*pnBestNtkDelay > nNtkDelay || (*pnBestNtkDelay == nNtkDelay && *pnBestNtkArea > nNtkArea ))) || + ( fArea && (*pnBestNtkArea > nNtkArea || (*pnBestNtkArea == nNtkArea && *pnBestNtkDelay > nNtkDelay ))) + ) { - Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); - if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", ".blif", ".pla", ".eqn", ".bench" )) ) - Abc_Print( 1, "Did you mean \"%s\"?", FileName ); - Abc_Print( 1, "\n" ); + *pnBestNtkArea = nNtkArea; + *pnBestNtkDelay = nNtkDelay; + *pnBestNtkNodes = nNtkNodes; + *pnBestNtkLevels = nNtkLevels; + printf( "\nUpdating the best network (Area = %10.2f Delay = %10.2f Nodes = %6d Level = %6d).\n\n", + nNtkArea, nNtkDelay, nNtkNodes, nNtkLevels ); return 1; } - fclose( pFile ); - - if ( fMiniAig ) - pAig = Gia_ManReadMiniAig( FileName ); - else if ( fMiniLut ) - pAig = Gia_ManReadMiniLut( FileName ); -// else if ( Extra_FileIsType( FileName, ".v", NULL, NULL ) ) -// Abc3_ReadShowHie( FileName, fSkipStrash ); - else - pAig = Gia_AigerRead( FileName, fGiaSimple, fSkipStrash, 0 ); - if ( pAig ) - Abc_FrameUpdateGia( pAbc, pAig ); return 0; - -usage: - Abc_Print( -2, "usage: &r [-csmlvh] \n" ); - Abc_Print( -2, "\t reads the current AIG from the AIGER file\n" ); - Abc_Print( -2, "\t-c : toggles reading simple AIG [default = %s]\n", fGiaSimple? "yes": "no" ); - Abc_Print( -2, "\t-s : toggles structural hashing while reading [default = %s]\n", !fSkipStrash? "yes": "no" ); - Abc_Print( -2, "\t-m : toggles reading MiniAIG rather than AIGER file [default = %s]\n", fMiniAig? "yes": "no" ); - Abc_Print( -2, "\t-l : toggles reading MiniLUT rather than AIGER file [default = %s]\n", fMiniLut? "yes": "no" ); - Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - Abc_Print( -2, "\t : the file name\n"); - return 1; } /**Function************************************************************* @@ -28562,62 +30495,47 @@ int Abc_CommandAbc9Read( Abc_Frame_t * pAbc, int argc, char ** argv ) SeeAlso [] ***********************************************************************/ -int Abc_CommandAbc9ReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandAbcSave( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t * Abc_NtkHieCecTest( char * pFileName, int fVerbose ); - Gia_Man_t * pAig; - FILE * pFile; - char ** pArgvNew; - char * FileName, * pTemp; - int nArgcNew; - int c, fVerbose = 0; + int c, fArea = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF ) { switch ( c ) { - case 'v': - fVerbose ^= 1; + case 'a': + fArea ^= 1; break; + case 'h': + goto usage; default: goto usage; } } - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( nArgcNew != 1 ) + if ( pAbc->pNtkCur == NULL ) { - Abc_Print( -1, "There is no file name.\n" ); + Abc_Print( -1, "Empty network.\n" ); return 1; } - - // get the input file name - FileName = pArgvNew[0]; - // fix the wrong symbol - for ( pTemp = FileName; *pTemp; pTemp++ ) - if ( *pTemp == '>' ) - *pTemp = '\\'; - if ( (pFile = fopen( FileName, "r" )) == NULL ) + if ( !Abc_NtkHasMapping(pAbc->pNtkCur) ) { - Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); - if ( (FileName = Extra_FileGetSimilarName( FileName, ".blif", NULL, NULL, NULL, NULL )) ) - Abc_Print( 1, "Did you mean \"%s\"?", FileName ); - Abc_Print( 1, "\n" ); + Abc_Print( -1, "Network has no mapping.\n" ); return 1; } - fclose( pFile ); - - pAig = Abc_NtkHieCecTest( FileName, fVerbose ); - Abc_FrameUpdateGia( pAbc, pAig ); + if ( !Abc_NtkCompareWithBest( pAbc->pNtkBest, pAbc->pNtkCur, + &pAbc->nBestNtkArea, &pAbc->nBestNtkDelay, + &pAbc->nBestNtkNodes, &pAbc->nBestNtkLevels, fArea ) ) + return 0; + // save the design as best + if ( pAbc->pNtkBest ) Abc_NtkDelete( pAbc->pNtkBest ); + pAbc->pNtkBest = Abc_NtkDup(pAbc->pNtkCur); return 0; usage: - Abc_Print( -2, "usage: &read_blif [-vh] \n" ); - Abc_Print( -2, "\t a specialized reader for hierarchical BLIF files\n" ); - Abc_Print( -2, "\t (for general-purpose BLIFs, please use \"read_blif\")\n" ); - Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - Abc_Print( -2, "\t : the file name\n"); + Abc_Print( -2, "usage: save [-ah]\n" ); + Abc_Print( -2, "\t compares and possibly saves network with mapping\n" ); + Abc_Print( -2, "\t-a : toggle using area as the primary metric [default = %s]\n", fArea? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -28632,72 +30550,34 @@ int Abc_CommandAbc9ReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) SeeAlso [] ***********************************************************************/ -int Abc_CommandAbc9ReadCBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandAbcLoad( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t * Abc_NtkHieCecTest2( char * pFileName, char * pModelName, int fVerbose ); - Gia_Man_t * pAig; - FILE * pFile; - char ** pArgvNew; - char * FileName, * pTemp; - char * pModelName = NULL; - int nArgcNew; - int c, fVerbose = 0; + int c; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Mvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { - case 'M': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-M\" should be followed by a file name.\n" ); - goto usage; - } - pModelName = argv[globalUtilOptind]; - globalUtilOptind++; - break; - case 'v': - fVerbose ^= 1; - break; + case 'h': + goto usage; default: goto usage; } } - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( nArgcNew != 1 ) - { - Abc_Print( -1, "There is no file name.\n" ); - return 1; - } - - // get the input file name - FileName = pArgvNew[0]; - // fix the wrong symbol - for ( pTemp = FileName; *pTemp; pTemp++ ) - if ( *pTemp == '>' ) - *pTemp = '\\'; - if ( (pFile = fopen( FileName, "r" )) == NULL ) + // restore from best + if ( pAbc->pNtkBest == NULL ) { - Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); - if ( (FileName = Extra_FileGetSimilarName( FileName, ".cblif", NULL, NULL, NULL, NULL )) ) - Abc_Print( 1, "Did you mean \"%s\"?", FileName ); - Abc_Print( 1, "\n" ); + Abc_Print( -1, "Abc_CommandAbcLoad(): There is no best design saved.\n" ); return 1; } - fclose( pFile ); - - pAig = Abc_NtkHieCecTest2( FileName, pModelName, fVerbose ); - Abc_FrameUpdateGia( pAbc, pAig ); + if ( pAbc->pNtkCur ) Abc_NtkDelete( pAbc->pNtkCur ); + pAbc->pNtkCur = Abc_NtkDup(pAbc->pNtkBest); return 0; usage: - Abc_Print( -2, "usage: &read_cblif [-M name] [-vh] \n" ); - Abc_Print( -2, "\t reads CBLIF file and collapse it into an AIG\n" ); - Abc_Print( -2, "\t-M name: module name to collapse [default = ]\n" ); - Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - Abc_Print( -2, "\t : the file name\n"); + Abc_Print( -2, "usage: load [-h]\n" ); + Abc_Print( -2, "\t loads mapped network previously saved by \"save\"\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -28712,29 +30592,50 @@ int Abc_CommandAbc9ReadCBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) SeeAlso [] ***********************************************************************/ -int Abc_CommandAbc9ReadStg( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandAbc9Read( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Gia_Man_t * pAig; + extern void Abc3_ReadShowHie( char * pFileName, int fFlat ); + extern Gia_Man_t * Gia_MiniAigSuperDerive( char * pFileName, int fVerbose ); + extern Gia_Man_t * Gia_FileSimpleRead( char * pFileName, int fNames, char * pFileW ); + extern Gia_Man_t * Gia_ManCreateXors( Gia_Man_t * p ); + Gia_Man_t * pAig = NULL; FILE * pFile; - char * FileName, ** pArgvNew; + char ** pArgvNew; + char * FileName, * pTemp; int c, nArgcNew; - int kHot = 1; + int fMiniAig = 0; + int fMiniAig2 = 0; + int fMiniLut = 0; int fVerbose = 0; + int fGiaSimple = 0; + int fSkipStrash = 0; + int fNewReader = 0; + int fDetectXors = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Kvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "csxmnlpvh" ) ) != EOF ) { switch ( c ) { - case 'K': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); - goto usage; - } - kHot = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( kHot < 1 || kHot > 5 ) - goto usage; + case 'c': + fGiaSimple ^= 1; + break; + case 's': + fSkipStrash ^= 1; + break; + case 'x': + fDetectXors ^= 1; + break; + case 'm': + fMiniAig ^= 1; + break; + case 'n': + fMiniAig2 ^= 1; + break; + case 'l': + fMiniLut ^= 1; + break; + case 'p': + fNewReader ^= 1; break; case 'v': fVerbose ^= 1; @@ -28753,22 +30654,54 @@ int Abc_CommandAbc9ReadStg( Abc_Frame_t * pAbc, int argc, char ** argv ) // get the input file name FileName = pArgvNew[0]; + // fix the wrong symbol + for ( pTemp = FileName; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; if ( (pFile = fopen( FileName, "r" )) == NULL ) { Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", ".blif", ".pla", ".eqn", ".bench" )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); return 1; } fclose( pFile ); - pAig = Gia_ManStgRead( FileName, kHot, fVerbose ); - Abc_FrameUpdateGia( pAbc, pAig ); + if ( fNewReader ) + pAig = Gia_FileSimpleRead( FileName, fGiaSimple, NULL ); + else if ( fMiniAig ) + pAig = Gia_ManReadMiniAig( FileName, fGiaSimple || fSkipStrash ); + else if ( fMiniAig2 ) + pAig = Gia_MiniAigSuperDerive( FileName, fVerbose ); + else if ( fMiniLut ) + pAig = Gia_ManReadMiniLut( FileName ); +// else if ( Extra_FileIsType( FileName, ".v", NULL, NULL ) ) +// Abc3_ReadShowHie( FileName, fSkipStrash ); + else + { + pAig = Gia_AigerRead( FileName, fGiaSimple, fSkipStrash, 0 ); + if ( fDetectXors ) + { + Gia_Man_t * pTemp; + pAig = Gia_ManCreateXors( pTemp = pAig ); + Gia_ManStop( pTemp ); + } + } + if ( pAig ) + Abc_FrameUpdateGia( pAbc, pAig ); return 0; usage: - Abc_Print( -2, "usage: &read_stg [-K ] [-vh] \n" ); - Abc_Print( -2, "\t reads STG file and generates K-hot-encoded AIG\n" ); - Abc_Print( -2, "\t-K num : the K parameter for hotness of the encoding (1 <= K <= 5) [default = %d]\n", kHot ); - Abc_Print( -2, "\t-v : toggles printing state codes [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "usage: &r [-csxmnlvh] \n" ); + Abc_Print( -2, "\t reads the current AIG from the AIGER file\n" ); + Abc_Print( -2, "\t-c : toggles reading simple AIG [default = %s]\n", fGiaSimple? "yes": "no" ); + Abc_Print( -2, "\t-s : toggles structural hashing while reading [default = %s]\n", !fSkipStrash? "yes": "no" ); + Abc_Print( -2, "\t-x : toggles detecting XORs while reading [default = %s]\n", fDetectXors? "yes": "no" ); + Abc_Print( -2, "\t-m : toggles reading MiniAIG rather than AIGER file [default = %s]\n", fMiniAig? "yes": "no" ); + Abc_Print( -2, "\t-n : toggles reading MiniAIG as a set of supergates [default = %s]\n", fMiniAig2? "yes": "no" ); + Abc_Print( -2, "\t-l : toggles reading MiniLUT rather than AIGER file [default = %s]\n", fMiniLut? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : the file name\n"); return 1; @@ -28785,13 +30718,236 @@ int Abc_CommandAbc9ReadStg( Abc_Frame_t * pAbc, int argc, char ** argv ) SeeAlso [] ***********************************************************************/ -int Abc_CommandAbc9ReadVer( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandAbc9ReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) { - Abc_Ntk_t * pNtk; + extern Gia_Man_t * Abc_NtkHieCecTest( char * pFileName, int fVerbose ); Gia_Man_t * pAig; FILE * pFile; char ** pArgvNew; - char * pFileName, * pTemp; + char * FileName, * pTemp; + int nArgcNew; + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + default: + goto usage; + } + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "There is no file name.\n" ); + return 1; + } + + // get the input file name + FileName = pArgvNew[0]; + // fix the wrong symbol + for ( pTemp = FileName; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".blif", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + + pAig = Abc_NtkHieCecTest( FileName, fVerbose ); + Abc_FrameUpdateGia( pAbc, pAig ); + return 0; + +usage: + Abc_Print( -2, "usage: &read_blif [-vh] \n" ); + Abc_Print( -2, "\t a specialized reader for hierarchical BLIF files\n" ); + Abc_Print( -2, "\t (for general-purpose BLIFs, please use \"read_blif\")\n" ); + Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the file name\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9ReadCBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Abc_NtkHieCecTest2( char * pFileName, char * pModelName, int fVerbose ); + Gia_Man_t * pAig; + FILE * pFile; + char ** pArgvNew; + char * FileName, * pTemp; + char * pModelName = NULL; + int nArgcNew; + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Mvh" ) ) != EOF ) + { + switch ( c ) + { + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by a file name.\n" ); + goto usage; + } + pModelName = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + default: + goto usage; + } + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "There is no file name.\n" ); + return 1; + } + + // get the input file name + FileName = pArgvNew[0]; + // fix the wrong symbol + for ( pTemp = FileName; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".cblif", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + + pAig = Abc_NtkHieCecTest2( FileName, pModelName, fVerbose ); + Abc_FrameUpdateGia( pAbc, pAig ); + return 0; + +usage: + Abc_Print( -2, "usage: &read_cblif [-M name] [-vh] \n" ); + Abc_Print( -2, "\t reads CBLIF file and collapse it into an AIG\n" ); + Abc_Print( -2, "\t-M name: module name to collapse [default = ]\n" ); + Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the file name\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9ReadStg( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Gia_Man_t * pAig; + FILE * pFile; + char * FileName, ** pArgvNew; + int c, nArgcNew; + int kHot = 1; + int 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; + } + kHot = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( kHot < 1 || kHot > 5 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + default: + goto usage; + } + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "There is no file name.\n" ); + return 1; + } + + // get the input file name + FileName = pArgvNew[0]; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + return 1; + } + fclose( pFile ); + + pAig = Gia_ManStgRead( FileName, kHot, fVerbose ); + Abc_FrameUpdateGia( pAbc, pAig ); + return 0; + +usage: + Abc_Print( -2, "usage: &read_stg [-K ] [-vh] \n" ); + Abc_Print( -2, "\t reads STG file and generates K-hot-encoded AIG\n" ); + Abc_Print( -2, "\t-K num : the K parameter for hotness of the encoding (1 <= K <= 5) [default = %d]\n", kHot ); + Abc_Print( -2, "\t-v : toggles printing state codes [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the file name\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9ReadVer( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + Gia_Man_t * pAig; + FILE * pFile; + char ** pArgvNew; + char * pFileName, * pTemp; int nArgcNew; int c, fVerbose = 0; Extra_UtilGetoptReset(); @@ -28864,8 +31020,6 @@ int Abc_CommandAbc9ReadVer( Abc_Frame_t * pAbc, int argc, char ** argv ) int Abc_CommandAbc9Get( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Aig_Man_t * Abc_NtkToDarChoices( Abc_Ntk_t * pNtk ); - extern Vec_Ptr_t * Abc_NtkCollectCiNames( Abc_Ntk_t * pNtk ); - extern Vec_Ptr_t * Abc_NtkCollectCoNames( Abc_Ntk_t * pNtk ); Abc_Ntk_t * pStrash; Aig_Man_t * pAig; Gia_Man_t * pGia, * pTemp; @@ -28915,7 +31069,7 @@ int Abc_CommandAbc9Get( Abc_Frame_t * pAbc, int argc, char ** argv ) Aig_ManStop( pAig ); // perform undc/zero pInits = Abc_NtkCollectLatchValuesStr( pAbc->pNtkCur ); - pGia = Gia_ManDupZeroUndc( pTemp = pGia, pInits, 0, fVerbose ); + pGia = Gia_ManDupZeroUndc( pTemp = pGia, pInits, 0, 0, fVerbose ); Gia_ManStop( pTemp ); ABC_FREE( pInits ); } @@ -28945,6 +31099,7 @@ int Abc_CommandAbc9Get( Abc_Frame_t * pAbc, int argc, char ** argv ) pGia->DefOutReqs = Abc_NtkReadDefaultRequiredWorst(pNtk); pGia->vInArrs = Vec_FltAllocArray( Abc_NtkGetCiArrivalFloats(pNtk), Abc_NtkCiNum(pNtk) ); pGia->vOutReqs = Vec_FltAllocArray( Abc_NtkGetCoRequiredFloats(pNtk), Abc_NtkCoNum(pNtk) ); + pGia->And2Delay = pNtk->AndGateDelay; } Abc_FrameUpdateGia( pAbc, pGia ); return 0; @@ -28978,20 +31133,30 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ); extern void Abc_NtkRedirectCiCo( Abc_Ntk_t * pNtk ); + extern Abc_Ntk_t * Abc_NtkFromCellMappedGia( Gia_Man_t * p, int fUseBuffs ); + extern Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p, int fFindEnables, int fUseBuffs ); Aig_Man_t * pMan; Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); - int c, fVerbose = 0; int fStatusClear = 1; + int fFindEnables = 0; + int fUseBuffs = 0; + int c, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "seovh" ) ) != EOF ) { switch ( c ) { case 's': fStatusClear ^= 1; break; + case 'e': + fFindEnables ^= 1; + break; + case 'o': + fUseBuffs ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -29006,16 +31171,12 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Empty network.\n" ); return 1; } - if ( Gia_ManHasCellMapping(pAbc->pGia) ) - { - extern Abc_Ntk_t * Abc_NtkFromCellMappedGia( Gia_Man_t * p ); - pNtk = Abc_NtkFromCellMappedGia( pAbc->pGia ); - } + if ( fFindEnables ) + pNtk = Abc_NtkFromMappedGia( pAbc->pGia, 1, fUseBuffs ); + else if ( Gia_ManHasCellMapping(pAbc->pGia) ) + pNtk = Abc_NtkFromCellMappedGia( pAbc->pGia, fUseBuffs ); else if ( Gia_ManHasMapping(pAbc->pGia) || pAbc->pGia->pMuxes ) - { - extern Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p ); - pNtk = Abc_NtkFromMappedGia( pAbc->pGia ); - } + pNtk = Abc_NtkFromMappedGia( pAbc->pGia, 0, fUseBuffs ); else if ( Gia_ManHasDangling(pAbc->pGia) == 0 ) { pMan = Gia_ManToAig( pAbc->pGia, 0 ); @@ -29026,7 +31187,7 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) else { Abc_Ntk_t * pNtkNoCh; -// Abc_Print( -1, "Transforming AIG with %d choice nodes.\n", Gia_ManEquivCountClasses(pAbc->pGia) ); + Abc_Print( -1, "Transforming AIG with %d choice nodes.\n", Gia_ManEquivCountClasses(pAbc->pGia) ); // create network without choices pMan = Gia_ManToAig( pAbc->pGia, 0 ); pNtkNoCh = Abc_NtkFromAigPhase( pMan ); @@ -29053,15 +31214,25 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) // transfer PO names to pNtk if ( pAbc->pGia->vNamesOut ) { - Abc_Obj_t * pObj; - int i; + char pSuffix[1000]; + Abc_Obj_t * pObj; int i; + unsigned char nDigits = (unsigned char)Abc_Base10Log( Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) { if (i < Vec_PtrSize(pAbc->pGia->vNamesOut)) { Nm_ManDeleteIdName(pNtk->pManName, pObj->Id); - Abc_ObjAssignName( pObj, (char *)Vec_PtrEntry(pAbc->pGia->vNamesOut, i), NULL ); + if ( Abc_ObjIsPo(pObj) ) + Abc_ObjAssignName( pObj, (char *)Vec_PtrEntry(pAbc->pGia->vNamesOut, i), NULL ); + else + { + assert( i >= Abc_NtkPoNum(pNtk) ); + sprintf( pSuffix, "_li%0*d", nDigits, i-Abc_NtkPoNum(pNtk) ); + Abc_ObjAssignName( pObj, (char *)Vec_PtrEntry(pAbc->pGia->vNamesOut, i), pSuffix ); + } } } } + if ( pAbc->pGia->vNamesNode ) + Abc_Print( 0, "Internal nodes names are not transferred.\n" ); // decouple CI/CO with the same name if ( pAbc->pGia->vNamesIn || pAbc->pGia->vNamesOut ) @@ -29089,15 +31260,78 @@ int Abc_CommandAbc9Put( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &put [-svh]\n" ); + Abc_Print( -2, "usage: &put [-seovh]\n" ); Abc_Print( -2, "\t transfer the current network into the old ABC\n" ); Abc_Print( -2, "\t-s : toggle clearning verification status [default = %s]\n", fStatusClear? "yes": "no" ); + Abc_Print( -2, "\t-e : toggle extracting MUXes for flop enables [default = %s]\n", fFindEnables? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles using buffers to decouple combinational outputs [default = %s]\n", fUseBuffs? "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"); return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9MoveNames( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nvh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + default: + goto usage; + } + } + if ( pAbc->pNtkCur == NULL ) + { + Abc_Print( -1, "There is no current network\n" ); + return 1; + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "There is no current AIG.\n" ); + return 1; + } + if ( Gia_ManCiNum(pAbc->pGia) != Abc_NtkCiNum(pAbc->pNtkCur) ) + { + Abc_Print( -1, "The number of CIs does not match.\n" ); + return 1; + } + if ( Gia_ManCoNum(pAbc->pGia) != Abc_NtkCoNum(pAbc->pNtkCur) ) + { + Abc_Print( -1, "The number of COs does not match.\n" ); + return 1; + } + if ( pAbc->pGia->vNamesIn ) Vec_PtrFreeFree( pAbc->pGia->vNamesIn ); + if ( pAbc->pGia->vNamesOut ) Vec_PtrFreeFree( pAbc->pGia->vNamesOut ); + pAbc->pGia->vNamesIn = Abc_NtkCollectCiNames( pAbc->pNtkCur ); + pAbc->pGia->vNamesOut = Abc_NtkCollectCoNames( pAbc->pNtkCur ); + return 0; + +usage: + Abc_Print( -2, "usage: &move_names [-vh]\n" ); + Abc_Print( -2, "\t move CI/CO names\n" ); + Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the file name\n"); + return 1; +} + /**Function************************************************************* Synopsis [Compares to versions of the design and finds the best.] @@ -29250,12 +31484,18 @@ int Abc_CommandAbc9Save2( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandAbc9SaveAig( Abc_Frame_t * pAbc, int argc, char ** argv ) { - int c; + int c, fClear = 0, fArea = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "cah" ) ) != EOF ) { switch ( c ) { + case 'c': + fClear ^= 1; + break; + case 'a': + fArea ^= 1; + break; case 'h': goto usage; default: @@ -29267,14 +31507,25 @@ int Abc_CommandAbc9SaveAig( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Empty network.\n" ); return 1; } + if ( fClear && pAbc->pGiaSaved != NULL ) + { + Gia_ManStopP( &pAbc->pGiaSaved ); + return 0; + } + if ( fArea && pAbc->pGiaSaved != NULL && Gia_ManAndNum(pAbc->pGiaSaved) <= Gia_ManAndNum(pAbc->pGia) ) + return 0; + if ( !fArea && pAbc->pGiaSaved != NULL && !(Gia_ManLevelNum(pAbc->pGiaSaved) > Gia_ManLevelNum(pAbc->pGia) || (Gia_ManLevelNum(pAbc->pGiaSaved) == Gia_ManLevelNum(pAbc->pGia) && Gia_ManAndNum(pAbc->pGiaSaved) > Gia_ManAndNum(pAbc->pGia))) ) + return 0; // save the design as best Gia_ManStopP( &pAbc->pGiaSaved ); pAbc->pGiaSaved = Gia_ManDupWithAttributes( pAbc->pGia ); return 0; usage: - Abc_Print( -2, "usage: &saveaig [-ah]\n" ); + Abc_Print( -2, "usage: &saveaig [-cah]\n" ); Abc_Print( -2, "\t saves the current AIG into the internal storage\n" ); + Abc_Print( -2, "\t-c : toggle clearing the saved AIG [default = %s]\n", fClear? "yes": "no" ); + Abc_Print( -2, "\t-a : toggle saving AIG with the smaller area [default = %s]\n", fArea? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -29316,8 +31567,8 @@ int Abc_CommandAbc9Load( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: Abc_Print( -2, "usage: &load [-h]\n" ); - Abc_Print( -2, "\t loads AIG with mapping previously saved by &save" ); - Abc_Print( -2, "\t (after loading the previously saved AIG can be loaded again)" ); + Abc_Print( -2, "\t loads AIG with mapping previously saved by &save\n" ); + Abc_Print( -2, "\t (after loading the previously saved AIG can be loaded again)\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -29363,8 +31614,8 @@ int Abc_CommandAbc9Load2( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: Abc_Print( -2, "usage: &load2 [-h]\n" ); - Abc_Print( -2, "\t loads AIG with mapping previously saved by &save2" ); - Abc_Print( -2, "\t (after loading the previously saved AIG cannot be loaded again)" ); + Abc_Print( -2, "\t loads AIG with mapping previously saved by &save2\n" ); + Abc_Print( -2, "\t (after loading the previously saved AIG cannot be loaded again)\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -29406,7 +31657,7 @@ int Abc_CommandAbc9LoadAig( Abc_Frame_t * pAbc, int argc, char ** argv ) usage: Abc_Print( -2, "usage: &loadaig [-h]\n" ); - Abc_Print( -2, "\t loads AIG previously saved by &saveaig" ); + Abc_Print( -2, "\t loads AIG previously saved by &saveaig\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -29509,23 +31760,39 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) char ** pArgvNew; int c, nArgcNew; int fUnique = 0; + int fVerilog = 0; + int fInter = 0; + int fVerBufs = 0; int fMiniAig = 0; int fMiniLut = 0; + int fWriteNewLine = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "umlvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "upibmlnvh" ) ) != EOF ) { switch ( c ) { case 'u': fUnique ^= 1; break; + case 'p': + fVerilog ^= 1; + break; + case 'i': + fInter ^= 1; + break; + case 'b': + fVerBufs ^= 1; + break; case 'm': fMiniAig ^= 1; break; case 'l': fMiniLut ^= 1; break; + case 'n': + fWriteNewLine ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -29554,20 +31821,26 @@ int Abc_CommandAbc9Write( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_AigerWriteSimple( pGia, pFileName ); Gia_ManStop( pGia ); } + else if ( fVerilog ) + Gia_ManDumpVerilog( pAbc->pGia, pFileName, NULL, fVerBufs, fInter ); else if ( fMiniAig ) Gia_ManWriteMiniAig( pAbc->pGia, pFileName ); else if ( fMiniLut ) Gia_ManWriteMiniLut( pAbc->pGia, pFileName ); else - Gia_AigerWrite( pAbc->pGia, pFileName, 0, 0 ); + Gia_AigerWrite( pAbc->pGia, pFileName, 0, 0, fWriteNewLine ); return 0; usage: - Abc_Print( -2, "usage: &w [-umlvh] \n" ); + Abc_Print( -2, "usage: &w [-upibmlnvh] \n" ); Abc_Print( -2, "\t writes the current AIG into the AIGER file\n" ); Abc_Print( -2, "\t-u : toggle writing canonical AIG structure [default = %s]\n", fUnique? "yes" : "no" ); + Abc_Print( -2, "\t-p : toggle writing Verilog with 'and' and 'not' [default = %s]\n", fVerilog? "yes" : "no" ); + Abc_Print( -2, "\t-i : toggle writing the interface module in Verilog [default = %s]\n", fInter? "yes" : "no" ); + Abc_Print( -2, "\t-b : toggle writing additional buffers in Verilog [default = %s]\n", fVerBufs? "yes" : "no" ); Abc_Print( -2, "\t-m : toggle writing MiniAIG rather than AIGER [default = %s]\n", fMiniAig? "yes" : "no" ); Abc_Print( -2, "\t-l : toggle writing MiniLUT rather than AIGER [default = %s]\n", fMiniLut? "yes" : "no" ); + Abc_Print( -2, "\t-n : toggle writing \'\\n\' after \'c\' in the AIGER file [default = %s]\n", fWriteNewLine? "yes": "no" ); 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 : the file name\n"); @@ -29653,7 +31926,7 @@ int Abc_CommandAbc9Ps( Abc_Frame_t * pAbc, int argc, char ** argv ) int c, fBest = 0; memset( pPars, 0, sizeof(Gps_Par_t) ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Dtpcnlmaszbh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Dtpcnlmaszxbh" ) ) != EOF ) { switch ( c ) { @@ -29684,6 +31957,9 @@ int Abc_CommandAbc9Ps( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'z': pPars->fSkipMap ^= 1; break; + case 'x': + pPars->fNoColor ^= 1; + break; case 'D': if ( globalUtilOptind >= argc ) { @@ -29723,7 +31999,7 @@ int Abc_CommandAbc9Ps( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &ps [-tpcnlmaszbh] [-D file]\n" ); + Abc_Print( -2, "usage: &ps [-tpcnlmaszxbh] [-D file]\n" ); Abc_Print( -2, "\t prints stats of the current AIG\n" ); Abc_Print( -2, "\t-t : toggle printing BMC tents [default = %s]\n", pPars->fTents? "yes": "no" ); Abc_Print( -2, "\t-p : toggle printing switching activity [default = %s]\n", pPars->fSwitch? "yes": "no" ); @@ -29734,6 +32010,7 @@ int Abc_CommandAbc9Ps( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-a : toggle printing miter statistics [default = %s]\n", pPars->fMiter? "yes": "no" ); Abc_Print( -2, "\t-s : toggle printing slack distribution [default = %s]\n", pPars->fSlacks? "yes": "no" ); Abc_Print( -2, "\t-z : skip mapping statistics even if mapped [default = %s]\n", pPars->fSkipMap? "yes": "no" ); + Abc_Print( -2, "\t-x : toggle using no color in the printout [default = %s]\n", pPars->fNoColor? "yes": "no" ); Abc_Print( -2, "\t-b : toggle printing saved AIG statistics [default = %s]\n", fBest? "yes": "no" ); Abc_Print( -2, "\t-D file : file name to dump statistics [default = none]\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -29969,6 +32246,240 @@ int Abc_CommandAbc9MuxProfile( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9MuxPos( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDupWithMuxPos( Gia_Man_t * p ); + Gia_Man_t * pGia; + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9MuxPos(): There is no AIG.\n" ); + return 1; + } + pGia = Gia_ManDupWithMuxPos( pAbc->pGia ); + Abc_FrameUpdateGia( pAbc, pGia ); + return 0; + +usage: + Abc_Print( -2, "usage: &muxpos [-vh]\n" ); + Abc_Print( -2, "\t create additional POs to preserve MUXes\n" ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9MuxStr( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManCofStructure( Gia_Man_t * p ); + Gia_Man_t * pGia; + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9MuxStr(): There is no AIG.\n" ); + return 1; + } + pGia = Gia_ManCofStructure( pAbc->pGia ); + Abc_FrameUpdateGia( pAbc, pGia ); + return 0; + +usage: + Abc_Print( -2, "usage: &muxstr [-vh]\n" ); + Abc_Print( -2, "\t performs restructuring\n" ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9MuxDec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManPerformMuxDec( Gia_Man_t * p ); + Gia_Man_t * pGia; + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9MuxDec(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManCiNum(pAbc->pGia) <= 6 || Gia_ManCiNum(pAbc->pGia) > 26 ) + { + Abc_Print( -1, "Abc_CommandAbc9MuxDec(): The number of inputs is wrong.\n" ); + return 1; + } + pGia = Gia_ManPerformMuxDec( pAbc->pGia ); + Abc_FrameUpdateGia( pAbc, pGia ); + return 0; + +usage: + Abc_Print( -2, "usage: &muxdec [-vh]\n" ); + Abc_Print( -2, "\t performs restructuring\n" ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9PrintTruth( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern word Gia_LutComputeTruth6Simple( Gia_Man_t * p, int iPo ); + int i, c, iOutNum = 0, nOutRange = -1, fVerbose = 0; word Truth; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ORvh" ) ) != EOF ) + { + switch ( c ) + { + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); + goto usage; + } + iOutNum = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iOutNum < 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; + } + nOutRange = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nOutRange < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9PrintTruth(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManPiNum(pAbc->pGia) > 6 ) + { + Abc_Print( -1, "The number of inputs of the AIG exceeds 6.\n" ); + return 1; + } + if ( iOutNum < 0 || iOutNum + nOutRange > Gia_ManPoNum(pAbc->pGia) ) + { + Abc_Print( -1, "Abc_CommandAbc9PrintTruth(): Range of outputs to extract is incorrect.\n" ); + return 1; + } + if ( nOutRange == -1 ) + nOutRange = Gia_ManCoNum(pAbc->pGia); + for ( i = iOutNum; i < iOutNum + nOutRange; i++ ) + { + Truth = Gia_LutComputeTruth6Simple( pAbc->pGia, i ); + printf( "Output %8d : ", i ); + Extra_PrintHex( stdout, (unsigned *)&Truth, Gia_ManCiNum(pAbc->pGia) ); + printf( "\n" ); + } + return 0; + +usage: + Abc_Print( -2, "usage: &print_truth [-OR num] [-vh]\n" ); + Abc_Print( -2, "\t prints truth tables of outputs in hex notation\n" ); + Abc_Print( -2, "\t-O num : the index of first PO to print [default = %d]\n", iOutNum ); + Abc_Print( -2, "\t-R num : (optional) the number of outputs to extract [default = all]\n" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -30292,14 +32803,18 @@ int Abc_CommandAbc9SetRegNum( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern Gia_Man_t * Gia_ManDupMuxRestructure( Gia_Man_t * p ); Gia_Man_t * pTemp; int c, Limit = 2; + int Multi = 0; + int fAddBuffs = 0; int fAddStrash = 0; - int fCollapse = 0; - int fAddMuxes = 0; + int fCollapse = 0; + int fAddMuxes = 0; + int fStrMuxes = 0; int fRehashMap = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Lacmrh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "LMbacmrsh" ) ) != EOF ) { switch ( c ) { @@ -30314,6 +32829,20 @@ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( Limit < 0 ) goto usage; break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + Multi = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Multi <= 0 ) + goto usage; + break; + case 'b': + fAddBuffs ^= 1; + break; case 'a': fAddStrash ^= 1; break; @@ -30326,6 +32855,9 @@ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'r': fRehashMap ^= 1; break; + case 's': + fStrMuxes ^= 1; + break; case 'h': goto usage; default: @@ -30337,7 +32869,29 @@ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Strash(): There is no AIG.\n" ); return 1; } - if ( Gia_ManHasMapping(pAbc->pGia) && fRehashMap ) + if ( fAddBuffs ) + { + extern Gia_Man_t * Gia_ManDupAddBufs( Gia_Man_t * p ); + pTemp = Gia_ManDupAddBufs( pAbc->pGia ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + } + if ( Multi > 0 ) + { + extern Gia_Man_t * Gia_ManDupAddPis( Gia_Man_t * p, int nMulti ); + pTemp = Gia_ManDupAddPis( pAbc->pGia, Multi ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + } + if ( fStrMuxes ) + { + if ( Gia_ManHasMapping(pAbc->pGia) ) + Abc_Print( 0, "Restructing the current AIG destroys the LUT mapping.\n" ); + Vec_IntFreeP( &pAbc->pGia->vMapping ); + pTemp = Gia_ManDupMuxRestructure( pAbc->pGia ); + Abc_Print( 1, "Finished AIG restructing to enable efficient mapping of 4:1 MUXes into 4-LUTs.\n" ); + } + else if ( Gia_ManHasMapping(pAbc->pGia) && fRehashMap ) { pTemp = Gia_ManDupHashMapping( pAbc->pGia ); Gia_ManTransferPacking( pTemp, pAbc->pGia ); @@ -30376,7 +32930,7 @@ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) } else if ( pAbc->pGia->pMuxes ) { - pTemp = Gia_ManDupNoMuxes( pAbc->pGia ); + pTemp = Gia_ManDupNoMuxes( pAbc->pGia, 0 ); if ( !Abc_FrameReadFlag("silentmode") ) printf( "Generated AIG from AND/XOR/MUX graph.\n" ); } @@ -30396,14 +32950,17 @@ int Abc_CommandAbc9Strash( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &st [-L num] [-acmrh]\n" ); + Abc_Print( -2, "usage: &st [-LM num] [-bacmrsh]\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" ); Abc_Print( -2, "\t-c : toggle collapsing hierarchical AIG [default = %s]\n", fCollapse? "yes": "no" ); Abc_Print( -2, "\t-m : toggle converting to larger gates [default = %s]\n", fAddMuxes? "yes": "no" ); Abc_Print( -2, "\t-L num : create MUX when sum of refs does not exceed this limit [default = %d]\n", Limit ); Abc_Print( -2, "\t (use L = 1 to create AIG with XORs but without MUXes)\n" ); + Abc_Print( -2, "\t-M num : create an AIG with additional primary inputs [default = %d]\n", Multi ); Abc_Print( -2, "\t-r : toggle rehashing AIG while preserving mapping [default = %s]\n", fRehashMap? "yes": "no" ); + Abc_Print( -2, "\t-s : toggle using MUX restructuring [default = %s]\n", fStrMuxes? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -30518,11 +33075,12 @@ int Abc_CommandAbc9Add1Hot( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandAbc9Cof( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern Gia_Man_t * Gia_ManComputeCofs( Gia_Man_t * p, int nVars ); Gia_Man_t * pTemp; int c, fVerbose = 0; - int iVar = 0, nLimFan = 0; + int iVar = 0, nLimFan = 0, nVars = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "VLvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "VLNvh" ) ) != EOF ) { switch ( c ) { @@ -30548,6 +33106,17 @@ int Abc_CommandAbc9Cof( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nLimFan < 0 ) goto usage; break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 0 ) + goto usage; + break; case 'v': fVerbose ^= 1; break; @@ -30562,15 +33131,21 @@ int Abc_CommandAbc9Cof( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Cof(): There is no AIG.\n" ); return 1; } - if ( nLimFan ) + if ( nVars ) + { + Abc_Print( 0, "Cofactoring the last %d inputs.\n", nVars ); + pTemp = Gia_ManComputeCofs( pAbc->pGia, nVars ); + Abc_FrameUpdateGia( pAbc, pTemp ); + } + else if ( nLimFan ) { - Abc_Print( -1, "Cofactoring all variables whose fanout count is higher than %d.\n", nLimFan ); + Abc_Print( 0, "Cofactoring all variables whose fanout count is higher than %d.\n", nLimFan ); pTemp = Gia_ManDupCofAll( pAbc->pGia, nLimFan, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); } else if ( iVar ) { - Abc_Print( -1, "Cofactoring one variable with object ID %d.\n", iVar ); + Abc_Print( 0, "Cofactoring one variable with object ID %d.\n", iVar ); pTemp = Gia_ManDupCof( pAbc->pGia, iVar ); Abc_FrameUpdateGia( pAbc, pTemp ); } @@ -30582,10 +33157,11 @@ int Abc_CommandAbc9Cof( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &cof [-VL num] [-vh]\n" ); + Abc_Print( -2, "usage: &cof [-VLN num] [-vh]\n" ); Abc_Print( -2, "\t performs cofactoring w.r.t. variable(s)\n" ); Abc_Print( -2, "\t-V num : the zero-based ID of one variable to cofactor [default = %d]\n", iVar ); Abc_Print( -2, "\t-L num : cofactor vars with fanout count higher than this [default = %d]\n", nLimFan ); + Abc_Print( -2, "\t-N num : cofactoring the given number of last input variables [default = %d]\n", nVars ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -30611,8 +33187,9 @@ int Abc_CommandAbc9Trim( Abc_Frame_t * pAbc, int argc, char ** argv ) int fTrimCos = 1; int fDualOut = 0; int fPoFedByPi = 0; + int fPoFedByPo = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Viocdh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Viocpdh" ) ) != EOF ) { switch ( c ) { @@ -30636,6 +33213,9 @@ int Abc_CommandAbc9Trim( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'c': fPoFedByPi ^= 1; break; + case 'p': + fPoFedByPo ^= 1; + break; case 'd': fDualOut ^= 1; break; @@ -30657,16 +33237,23 @@ int Abc_CommandAbc9Trim( Abc_Frame_t * pAbc, int argc, char ** argv ) pTemp = Gia_ManDupTrimmed2( pTemp2 = pTemp ); Gia_ManStop( pTemp2 ); } + if ( fPoFedByPo ) + { + extern Gia_Man_t * Gia_ManDupTrimmed3( Gia_Man_t * p ); + pTemp = Gia_ManDupTrimmed3( pTemp2 = pTemp ); + Gia_ManStop( pTemp2 ); + } Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &trim [-V num] [-iocdh]\n" ); + Abc_Print( -2, "usage: &trim [-V num] [-iocpdh]\n" ); Abc_Print( -2, "\t removes PIs without fanout and PO driven by constants\n" ); Abc_Print( -2, "\t-V num : the value (0 or 1) of POs to remove [default = both]\n" ); Abc_Print( -2, "\t-i : toggle removing PIs [default = %s]\n", fTrimCis? "yes": "no" ); Abc_Print( -2, "\t-o : toggle removing POs [default = %s]\n", fTrimCos? "yes": "no" ); Abc_Print( -2, "\t-c : toggle additionally removing POs fed by PIs [default = %s]\n", fPoFedByPi? "yes": "no" ); + Abc_Print( -2, "\t-p : toggle additionally removing duplicated POs [default = %s]\n", fPoFedByPo? "yes": "no" ); Abc_Print( -2, "\t-d : toggle using dual-output miter [default = %s]\n", fDualOut? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -30688,18 +33275,26 @@ int Abc_CommandAbc9Dfs( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_Man_t * pTemp; int c; int fNormal = 0; - int fReverse = 0; + int fRevFans = 0; + int fRevOuts = 0; + int fLeveled = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "nrvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "nfolvh" ) ) != EOF ) { switch ( c ) { case 'n': fNormal ^= 1; break; - case 'r': - fReverse ^= 1; + case 'f': + fRevFans ^= 1; + break; + case 'o': + fRevOuts ^= 1; + break; + case 'l': + fLeveled ^= 1; break; case 'v': fVerbose ^= 1; @@ -30715,33 +33310,23 @@ int Abc_CommandAbc9Dfs( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Dfs(): There is no AIG.\n" ); return 1; } - if ( fNormal ) - { + if ( fLeveled ) + pTemp = Gia_ManDupLevelized( pAbc->pGia ); + else if ( fNormal ) pTemp = Gia_ManDupOrderAiger( pAbc->pGia ); - if ( fVerbose ) - Abc_Print( -1, "AIG objects are reordered as follows: CIs, ANDs, COs.\n" ); - } - else if ( fReverse ) - { - pTemp = Gia_ManDupOrderDfsReverse( pAbc->pGia ); - if ( fVerbose ) - Abc_Print( -1, "AIG objects are reordered in the reserve DFS order.\n" ); - } - else - { - pTemp = Gia_ManDupOrderDfs( pAbc->pGia ); - if ( fVerbose ) - Abc_Print( -1, "AIG objects are reordered in the DFS order.\n" ); - } + else + pTemp = Gia_ManDupOrderDfsReverse( pAbc->pGia, fRevFans, fRevOuts ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &dfs [-nrvh]\n" ); + Abc_Print( -2, "usage: &dfs [-nfolvh]\n" ); Abc_Print( -2, "\t orders objects in the DFS order\n" ); - Abc_Print( -2, "\t-n : toggle using normalized ordering [default = %s]\n", fNormal? "yes": "no" ); - Abc_Print( -2, "\t-r : toggle using reverse DFS ordering [default = %s]\n", fReverse? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-n : toggle using normalized ordering [default = %s]\n", fNormal? "yes": "no" ); + Abc_Print( -2, "\t-f : toggle using reverse fanin traversal order [default = %s]\n", fRevFans? "yes": "no" ); + Abc_Print( -2, "\t-o : toggle using reverse output traversal order [default = %s]\n", fRevOuts? "yes": "no" ); + Abc_Print( -2, "\t-l : toggle using levelized order [default = %s]\n", fLeveled? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -30882,6 +33467,184 @@ int Abc_CommandAbc9Sim( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Sim2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Gia_ManSimTwo( Gia_Man_t * p0, Gia_Man_t * p1, int nWords, int nRounds, int TimeLimit, int fVerbose ); + Gia_Man_t * pGias[2]; FILE * pFile; + char ** pArgvNew; int nArgcNew; + int c, RetValue = 0, fVerbose = 0, nWords = 16, nRounds = 10, RandSeed = 1, TimeLimit = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "WRNTvh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + nWords = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nWords < 0 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nRounds = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nRounds < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + RandSeed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( RandSeed < 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + TimeLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( TimeLimit < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew > 2 ) + { + Abc_Print( -1, "Abc_CommandAbc9Cec(): Wrong number of command-line arguments.\n" ); + return 1; + } + if ( nArgcNew == 2 ) + { + char * pFileNames[2] = { pArgvNew[0], pArgvNew[1] }, * pTemp; + int n; + for ( n = 0; n < 2; n++ ) + { + // fix the wrong symbol + for ( pTemp = pFileNames[n]; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( pFileNames[n], "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", pFileNames[n] ); + if ( (pFileNames[n] = Extra_FileGetSimilarName( pFileNames[n], ".aig", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", pFileNames[n] ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pGias[n] = Gia_AigerRead( pFileNames[n], 0, 0, 0 ); + if ( pGias[n] == NULL ) + { + Abc_Print( -1, "Reading AIGER from file \"%s\" has failed.\n", pFileNames[n] ); + return 0; + } + } + } + else + { + char * FileName, * pTemp; + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Cec(): There is no current AIG.\n" ); + return 1; + } + pGias[0] = pAbc->pGia; + if ( nArgcNew == 1 ) + FileName = pArgvNew[0]; + else + { + assert( nArgcNew == 0 ); + if ( pAbc->pGia->pSpec == NULL ) + { + Abc_Print( -1, "File name is not given on the command line.\n" ); + return 1; + } + FileName = pAbc->pGia->pSpec; + } + // fix the wrong symbol + for ( pTemp = FileName; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pGias[1] = Gia_AigerRead( FileName, 0, 0, 0 ); + if ( pGias[1] == NULL ) + { + Abc_Print( -1, "Reading AIGER has failed.\n" ); + return 0; + } + } + if ( Gia_ManCiNum(pGias[0]) != Gia_ManCiNum(pGias[1]) ) + { + Abc_Print( -1, "The number of CIs does not match.\n" ); + return 1; + } + if ( Gia_ManCoNum(pGias[0]) != Gia_ManCoNum(pGias[1]) ) + { + Abc_Print( -1, "The number of COs does not match.\n" ); + return 1; + } + RetValue = Gia_ManSimTwo( pGias[0], pGias[1], nWords, nRounds, TimeLimit, fVerbose ); + if ( pGias[0] != pAbc->pGia ) + Gia_ManStopP( &pGias[0] ); + Gia_ManStopP( &pGias[1] ); + return 0; + +usage: + Abc_Print( -2, "usage: &sim2 [-WRNT num] [-vh] \n" ); + Abc_Print( -2, "\t performs random of two circuits\n" ); + Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", nWords ); + Abc_Print( -2, "\t-R num : the number of simulation rounds [default = %d]\n", nRounds ); + Abc_Print( -2, "\t-N num : random number seed (1 <= num <= 1000) [default = %d]\n", RandSeed ); + Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", TimeLimit ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -31035,6 +33798,762 @@ int Abc_CommandAbc9Sim3( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9MLGen( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManDumpFiles( Gia_Man_t * p, int nCexesT, int nCexesV, int Seed, char * pFileName ); + extern void Gia_ManDumpPlaFiles( Gia_Man_t * p, int nCexesT, int nCexesV, int Seed, char * pFileName ); + int c, Seed = 0, nWords = 10, fBinData = 0, fVerbose = 0; + char * pFileName = NULL; + char ** pArgvNew; + int nArgcNew; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "WSbvh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + nWords = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nWords < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Seed < 0 ) + goto usage; + break; + case 'b': + fBinData ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9MLGen(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManRegNum(pAbc->pGia) > 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9MLGen(): This command works only for combinational AIGs.\n" ); + return 0; + } + Vec_WrdFreeP( &pAbc->pGia->vSimsPi ); + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew == 0 ) + printf( "Default file names will be used.\n" ); + else + pFileName = pArgvNew[0]; + if ( nArgcNew != 0 && nArgcNew != 1 ) + { + Abc_Print( -1, "File name is not given on the command line.\n" ); + return 1; + } + if ( fBinData ) + Gia_ManDumpFiles( pAbc->pGia, nWords, nWords, Seed, pFileName ); + else + Gia_ManDumpPlaFiles( pAbc->pGia, nWords, nWords, Seed, pFileName ); + return 0; + +usage: + Abc_Print( -2, "usage: &mlgen [-WS num] [-bvh] \n" ); + Abc_Print( -2, "\t generates data files for machine learning\n" ); + Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", nWords ); + Abc_Print( -2, "\t-S num : the random seed for simulation data (num < 10000) [default = %d]\n", Seed ); + Abc_Print( -2, "\t-b : toggle using binary data files [default = %s]\n", fBinData? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : file to store the simulation info\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9MLTest( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManTestOneFile( Gia_Man_t * p, char * pFileName, char * pDumpFile ); + int c, fVerbose = 0; + char * pDumpFile = NULL; + char ** pArgvNew; + int nArgcNew; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Dvh" ) ) != EOF ) + { + switch ( c ) + { + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by a file name.\n" ); + goto usage; + } + pDumpFile = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9MLTest(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManRegNum(pAbc->pGia) > 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9MLTest(): This command works only for combinational AIGs.\n" ); + return 0; + } + Vec_WrdFreeP( &pAbc->pGia->vSimsPi ); + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "Abc_CommandAbc9MLTest(): Expecting data file name on the command line.\n" ); + return 0; + } + Gia_ManTestOneFile( pAbc->pGia, pArgvNew[0], pDumpFile ); + return 0; + +usage: + Abc_Print( -2, "usage: &mltest [-vh] [-D file] \n" ); + Abc_Print( -2, "\t testing command for machine learning data\n" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t-D file : file name to dump statistics [default = none]\n" ); + Abc_Print( -2, "\tfile : file with input simulation info\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Iwls21Test( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManTestWordFile( Gia_Man_t * p, char * pFileName, char * pDumpFile, int fVerbose ); + int c, fVerbose = 0; + char * pDumpFile = NULL; + char ** pArgvNew; + int nArgcNew; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Dvh" ) ) != EOF ) + { + switch ( c ) + { + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by a file name.\n" ); + goto usage; + } + pDumpFile = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew == 2 ) + { + Gia_Man_t * pAig = Gia_AigerRead( pArgvNew[0], 0, 0, 0 ); + if ( pAig == NULL ) + { + Abc_Print( -1, "Reading AIGER from file \"%s\" has failed.\n", pArgvNew[0] ); + return 0; + } + if ( Gia_ManRegNum(pAig) > 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9Iwls21Test(): This command works only for combinational AIGs.\n" ); + return 0; + } + if ( Gia_ManCoNum(pAig) != 10 ) + { + Abc_Print( -1, "Abc_CommandAbc9Iwls21Test(): Expecting an AIG with 10 outputs.\n" ); + return 0; + } + Gia_ManTestWordFile( pAig, pArgvNew[1], pDumpFile, fVerbose ); + Gia_ManStop( pAig ); + return 0; + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Iwls21Test(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManCoNum(pAbc->pGia) != 10 ) + { + Abc_Print( -1, "Abc_CommandAbc9Iwls21Test(): Expecting an AIG with 10 outputs.\n" ); + return 0; + } + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "Abc_CommandAbc9Iwls21Test(): Expecting data file name on the command line.\n" ); + return 0; + } + if ( Gia_ManRegNum(pAbc->pGia) > 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9Iwls21Test(): This command works only for combinational AIGs.\n" ); + return 0; + } + Vec_WrdFreeP( &pAbc->pGia->vSimsPi ); + Gia_ManTestWordFile( pAbc->pGia, pArgvNew[0], pDumpFile, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: &iwls21test [-vh] [-D file] \n" ); + Abc_Print( -2, "\t this command evaluates AIG for 2021 IWLS ML+LS Contest\n" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t-D file : file name to dump statistics [default = none]\n" ); + Abc_Print( -2, "\tfile1 : file with input AIG (or \"&read ; &iwls21test \" can be used)\n"); + Abc_Print( -2, "\tfile2 : file with CIFAR10 image data (https://www.cs.toronto.edu/~kriz/cifar.html)\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9ReadSim( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + int c, fOutputs = 0, nWords = 4, fTruth = 0, fVerbose = 0; + char ** pArgvNew; + int nArgcNew; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Wtovh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + nWords = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nWords < 0 ) + goto usage; + break; + case 't': + fTruth ^= 1; + 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_CommandAbc9ReadSim(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManRegNum(pAbc->pGia) > 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9ReadSim(): This command works only for combinational AIGs.\n" ); + return 0; + } + if ( fTruth ) + { + if ( Gia_ManCiNum(pAbc->pGia) > 20 ) + { + Abc_Print( -1, "Abc_CommandAbc9ReadSim(): More than 20 inputs.\n" ); + return 1; + } + Vec_WrdFreeP( &pAbc->pGia->vSimsPi ); + pAbc->pGia->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(pAbc->pGia) ); + Vec_WrdFreeP( &pAbc->pGia->vSimsPo ); + pAbc->pGia->vSimsPo = Gia_ManSimPatSimOut( pAbc->pGia, pAbc->pGia->vSimsPi, 1 ); + return 0; + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "File name is not given on the command line.\n" ); + return 1; + } + if ( fOutputs ) + { + Vec_WrdFreeP( &pAbc->pGia->vSimsPo ); + pAbc->pGia->vSimsPo = Vec_WrdReadHex( pArgvNew[0], NULL, 1 ); + if ( Vec_WrdSize(pAbc->pGia->vSimsPo) % Gia_ManCoNum(pAbc->pGia) != 0 ) + { + Vec_WrdFreeP( &pAbc->pGia->vSimsPo ); + Abc_Print( -1, "File size (%d words) does not match the number of AIG inputs (%d %% %d != %d).\n", + Vec_WrdSize(pAbc->pGia->vSimsPo), Vec_WrdSize(pAbc->pGia->vSimsPo), Gia_ManCiNum(pAbc->pGia), + Vec_WrdSize(pAbc->pGia->vSimsPo) % Gia_ManCiNum(pAbc->pGia) ); + return 1; + } + pAbc->pGia->nSimWords = Vec_WrdSize(pAbc->pGia->vSimsPo) / Gia_ManCoNum(pAbc->pGia); + } + else + { + Vec_WrdFreeP( &pAbc->pGia->vSimsPi ); + pAbc->pGia->vSimsPi = Vec_WrdReadHex( pArgvNew[0], NULL, 1 ); + if ( Vec_WrdSize(pAbc->pGia->vSimsPi) % Gia_ManCiNum(pAbc->pGia) != 0 ) + { + Vec_WrdFreeP( &pAbc->pGia->vSimsPi ); + Abc_Print( -1, "File size (%d words) does not match the number of AIG inputs (%d %% %d != %d).\n", + Vec_WrdSize(pAbc->pGia->vSimsPi), Vec_WrdSize(pAbc->pGia->vSimsPi), Gia_ManCiNum(pAbc->pGia), + Vec_WrdSize(pAbc->pGia->vSimsPi) % Gia_ManCiNum(pAbc->pGia) ); + return 1; + } + pAbc->pGia->nSimWords = Vec_WrdSize(pAbc->pGia->vSimsPi) / Gia_ManCiNum(pAbc->pGia); + } + return 0; + +usage: + Abc_Print( -2, "usage: &sim_read [-W num] [-tovh] \n" ); + Abc_Print( -2, "\t reads simulation patterns from file\n" ); + Abc_Print( -2, "\t-W num : the number of words to simulate [default = %d]\n", nWords ); + Abc_Print( -2, "\t-t : toggle creating exhaustive simulation info [default = %s]\n", fTruth? "yes": "no" ); + Abc_Print( -2, "\t-o : toggle reading output information [default = %s]\n", fOutputs? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : file to store the simulation info\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9WriteSim( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + int c, fOutputs = 0, fTrans = 0, fBool = 0, fVerbose = 0; + char ** pArgvNew; + int nArgcNew; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "otbvh" ) ) != EOF ) + { + switch ( c ) + { + case 'o': + fOutputs ^= 1; + break; + case 't': + fTrans ^= 1; + break; + case 'b': + fBool ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9WriteSim(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManRegNum(pAbc->pGia) > 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9WriteSim(): This command works only for combinational AIGs.\n" ); + return 0; + } + if ( (fOutputs ? pAbc->pGia->vSimsPo : pAbc->pGia->vSimsPi) == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9WriteSim(): Does not have simulation information available.\n" ); + return 0; + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "File name is not given on the command line.\n" ); + return 1; + } + if ( fOutputs ) + { + Vec_Wrd_t * vTemp; + int nWords = Vec_WrdSize(pAbc->pGia->vSimsPo) / Gia_ManCoNum(pAbc->pGia); + assert( Vec_WrdSize(pAbc->pGia->vSimsPo) % Gia_ManCoNum(pAbc->pGia) == 0 ); + if ( fTrans ) + { + int nSize = Vec_WrdSize(pAbc->pGia->vSimsPo); + Vec_WrdFillExtra( pAbc->pGia->vSimsPo, nWords * 64 * ((Gia_ManCoNum(pAbc->pGia) + 63)/64), 0 ); + vTemp = Vec_WrdStart( Vec_WrdSize(pAbc->pGia->vSimsPo) ); + Extra_BitMatrixTransposeP( pAbc->pGia->vSimsPo, nWords, vTemp, (Gia_ManCoNum(pAbc->pGia) + 63)/64 ); + if ( fBool ) + Vec_WrdDumpBool( pArgvNew[0], vTemp, (Gia_ManCoNum(pAbc->pGia) + 63)/64, Gia_ManCoNum(pAbc->pGia), 1, 1 ); + else + Vec_WrdDumpHex( pArgvNew[0], vTemp, (Gia_ManCoNum(pAbc->pGia) + 63)/64, 1 ); + Vec_WrdShrink( pAbc->pGia->vSimsPo, nSize ); + Vec_WrdFree( vTemp ); + } + else + { + if ( fBool ) + Vec_WrdDumpBool( pArgvNew[0], pAbc->pGia->vSimsPo, nWords, Gia_ManCoNum(pAbc->pGia), 1, 1 ); + else + Vec_WrdDumpHex( pArgvNew[0], pAbc->pGia->vSimsPo, nWords, 1 ); + } + } + else + { + Vec_Wrd_t * vTemp; + int nWords = Vec_WrdSize(pAbc->pGia->vSimsPi) / Gia_ManCiNum(pAbc->pGia); + assert( Vec_WrdSize(pAbc->pGia->vSimsPi) % Gia_ManCiNum(pAbc->pGia) == 0 ); + if ( fTrans ) + { + int nSize = Vec_WrdSize(pAbc->pGia->vSimsPi); + Vec_WrdFillExtra( pAbc->pGia->vSimsPi, nWords * 64 * ((Gia_ManCiNum(pAbc->pGia) + 63)/64), 0 ); + vTemp = Vec_WrdStart( Vec_WrdSize(pAbc->pGia->vSimsPi) ); + Extra_BitMatrixTransposeP( pAbc->pGia->vSimsPi, nWords, vTemp, (Gia_ManCiNum(pAbc->pGia) + 63)/64 ); + if ( fBool ) + Vec_WrdDumpBool( pArgvNew[0], vTemp, (Gia_ManCiNum(pAbc->pGia) + 63)/64, Gia_ManCiNum(pAbc->pGia), 1, 1 ); + else + Vec_WrdDumpHex( pArgvNew[0], vTemp, (Gia_ManCiNum(pAbc->pGia) + 63)/64, 1 ); + Vec_WrdShrink( pAbc->pGia->vSimsPi, nSize ); + Vec_WrdFree( vTemp ); + } + else + { + if ( fBool ) + Vec_WrdDumpBool( pArgvNew[0], pAbc->pGia->vSimsPi, nWords, Gia_ManCiNum(pAbc->pGia), 1, 1 ); + else + Vec_WrdDumpHex( pArgvNew[0], pAbc->pGia->vSimsPi, nWords, 1 ); + } + } + return 0; + +usage: + Abc_Print( -2, "usage: &sim_write [-otbvh] \n" ); + Abc_Print( -2, "\t writes simulation patterns into a file\n" ); + Abc_Print( -2, "\t-o : toggle writing output information [default = %s]\n", fOutputs? "yes": "no" ); + Abc_Print( -2, "\t-t : toggle transposing the simulation information [default = %s]\n", fTrans? "yes": "no" ); + Abc_Print( -2, "\t-b : toggle dumping in boolean vs hexadecimal notation [default = %s]\n", fBool? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : file to store the simulation info\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9PrintSim( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManSimProfile( Gia_Man_t * pGia ); + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9PrintSim(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManRegNum(pAbc->pGia) > 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9PrintSim(): This command works only for combinational AIGs.\n" ); + return 0; + } + if ( pAbc->pGia->vSimsPi == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9PrintSim(): Simulation patterns are not defined.\n" ); + return 0; + } + Gia_ManSimProfile( pAbc->pGia ); + return 0; + +usage: + Abc_Print( -2, "usage: &sim_print [-vh]\n" ); + Abc_Print( -2, "\t writes simulation patterns into a file\n" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9GenSim( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManSimProfile( Gia_Man_t * pGia ); + extern void Gia_ManPatSatImprove( Gia_Man_t * pGia, int nWords, int fVerbose ); + extern void Gia_ManPatDistImprove( Gia_Man_t * p, int fVerbose ); + extern void Gia_ManPatRareImprove( Gia_Man_t * p, int RareLimit, int fVerbose ); + int c, nWords = 4, nRare = -1, fDist = 0, fSatBased = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "WRsdvh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + nWords = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nWords < 0 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nRare = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nRare < 0 ) + goto usage; + break; + case 's': + fSatBased ^= 1; + break; + case 'd': + fDist ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9GenSim(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManRegNum(pAbc->pGia) > 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9GenSim(): This command works only for combinational AIGs.\n" ); + return 0; + } + if ( fSatBased ) + { + if ( pAbc->pGia->vSimsPi == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9GenSim(): Does not have simulation information available.\n" ); + return 0; + } + Gia_ManPatSatImprove( pAbc->pGia, nWords, fVerbose ); + } + else if ( fDist ) + { + if ( pAbc->pGia->vSimsPi == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9GenSim(): Does not have simulation information available.\n" ); + return 0; + } + Gia_ManPatDistImprove( pAbc->pGia, fVerbose ); + } + else if ( nRare >= 0 ) + { + if ( pAbc->pGia->vSimsPi == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9GenSim(): Does not have simulation information available.\n" ); + return 0; + } + Gia_ManPatRareImprove( pAbc->pGia, nRare, fVerbose ); + } + else + { + Abc_Random(1); + Vec_WrdFreeP( &pAbc->pGia->vSimsPi ); + pAbc->pGia->vSimsPi = Vec_WrdStartRandom( Gia_ManCiNum(pAbc->pGia) * nWords ); + printf( "Generated %d random patterns (%d 64-bit data words) for each input of the AIG.\n", 64*nWords, nWords ); + } + Gia_ManSimProfile( pAbc->pGia ); + return 0; + +usage: + Abc_Print( -2, "usage: &sim_gen [-WR num] [-sdvh]\n" ); + Abc_Print( -2, "\t generates random simulation patterns\n" ); + Abc_Print( -2, "\t-W num : the number of 64-bit words of simulation info [default = %d]\n", nWords ); + Abc_Print( -2, "\t-R num : the rarity parameter used to define scope [default = %d]\n", nRare ); + Abc_Print( -2, "\t-s : toggle using SAT-based improvement of available patterns [default = %s]\n", fSatBased? "yes": "no" ); + Abc_Print( -2, "\t-d : toggle using one improvement of available patterns [default = %s]\n", fDist? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9SimRsb( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManSimRsb( Gia_Man_t * p, int nCands, int fVerbose ); + int c, nCands = 32, 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; + } + nCands = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCands < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9SimRsb(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManRegNum(pAbc->pGia) > 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9SimRsb(): This command works only for combinational AIGs.\n" ); + return 0; + } + if ( pAbc->pGia->vSimsPi == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9SimRsb(): Does not have simulation information available.\n" ); + return 0; + } + Gia_ManSimRsb( pAbc->pGia, nCands, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: &simrsb [-N num] [-vh]\n" ); + Abc_Print( -2, "\t performs resubstitution\n" ); + Abc_Print( -2, "\t-C num : the number of candidates to try [default = %d]\n", nCands ); + 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************************************************************* @@ -31297,7 +34816,7 @@ int Abc_CommandAbc9Equiv( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeLimit ); Abc_Print( -2, "\t-s : toggle seq vs. comb simulation [default = %s]\n", pPars->fSeqSimulate? "yes": "no" ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" ); - Abc_Print( -2, "\t-d : toggle using two POs intead of XOR [default = %s]\n", pPars->fDualOut? "yes": "no" ); + Abc_Print( -2, "\t-d : toggle using two POs instead of XOR [default = %s]\n", pPars->fDualOut? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -31748,7 +35267,7 @@ int Abc_CommandAbc9Semi( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeLimit ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" ); - Abc_Print( -2, "\t-d : toggle using two POs intead of XOR [default = %s]\n", pPars->fDualOut? "yes": "no" ); + Abc_Print( -2, "\t-d : toggle using two POs instead of XOR [default = %s]\n", pPars->fDualOut? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -32370,6 +35889,72 @@ int Abc_CommandAbc9Fx( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Extract( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Abc_NtkShareXorGia( Gia_Man_t * p, int nMultiSize, int fAnd, int fVerbose ); + Gia_Man_t * pTemp; + int nMultiSize = 3; + int c, fAnds = 0; + int fVerbose = 0; + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "Kavh")) != EOF ) + { + switch (c) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nMultiSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMultiSize < 0 ) + goto usage; + break; + case 'a': + fAnds ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Shrink(): There is no AIG.\n" ); + return 1; + } + pTemp = Abc_NtkShareXorGia( pAbc->pGia, nMultiSize, fAnds, fVerbose ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &extract [-K ] [-vh]\n"); + Abc_Print( -2, "\t extract shared logic for XOR-rich circuits\n"); + Abc_Print( -2, "\t-K : the minimum gate size to consider for extraction [default = %d]\n", nMultiSize ); + Abc_Print( -2, "\t-a : toogle extracting ANDs instead of XORs [default = %s]\n", fAnds? "yes": "no" ); + Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -32557,6 +36142,170 @@ int Abc_CommandAbc9BalanceLut( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Resub( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManResub1( char * pFileName, int nNodes, int nSupp, int nDivs, int iChoice, int fUseXor, int fVerbose, int fVeryVerbose ); + extern Gia_Man_t * Gia_ManResub2( Gia_Man_t * pGia, int nNodes, int nSupp, int nDivs, int iChoice, int fUseXor, int fVerbose, int fVeryVerbose ); + Gia_Man_t * pTemp; + int nNodes = 0; + int nSupp = 0; + int nDivs = 0; + int c, fVerbose = 0; + int fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NSDvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( 1, "Command line switch \"-N\" should be followed by a floating point number.\n" ); + return 0; + } + nNodes = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodes < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( 1, "Command line switch \"-S\" should be followed by a floating point number.\n" ); + return 0; + } + nSupp = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSupp < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( 1, "Command line switch \"-D\" should be followed by a floating point number.\n" ); + return 0; + } + nDivs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nDivs < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == globalUtilOptind + 1 ) + { + pTemp = Gia_ManResub1( argv[globalUtilOptind], nNodes, nSupp, nDivs, 0, 0, fVerbose, fVeryVerbose ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Resub(): There is no AIG.\n" ); + return 1; + } + pTemp = Gia_ManResub2( pAbc->pGia, nNodes, nSupp, nDivs, 0, 0, fVerbose, fVeryVerbose ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &resub [-NSD num] [-vwh]\n" ); + Abc_Print( -2, "\t performs AIG resubstitution\n" ); + Abc_Print( -2, "\t-N num : the limit on added nodes (num >= 0) [default = %d]\n", nNodes ); + Abc_Print( -2, "\t-S num : the limit on support size (num > 0) [default = %d]\n", nSupp ); + Abc_Print( -2, "\t-D num : the limit on divisor count (num > 0) [default = %d]\n", nDivs ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggles printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Reshape( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManReshape1( Gia_Man_t * pGia, int fUseSimple, int fVerbose, int fVeryVerbose ); + extern Gia_Man_t * Gia_ManReshape2( Gia_Man_t * pGia, int fUseSimple, int fVerbose, int fVeryVerbose ); + Gia_Man_t * pTemp; + int fUseReshape1 = 0; + int fUseSimple = 0; + int c, fVerbose = 0; + int fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "asvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fUseReshape1 ^= 1; + break; + case 's': + fUseSimple ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Resub(): There is no AIG.\n" ); + return 1; + } + if ( fUseReshape1 ) + pTemp = Gia_ManReshape1( pAbc->pGia, fUseSimple, fVerbose, fVeryVerbose ); + else + pTemp = Gia_ManReshape2( pAbc->pGia, fUseSimple, fVerbose, fVeryVerbose ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &reshape [-asvwh]\n" ); + Abc_Print( -2, "\t performs AIG resubstitution\n" ); + Abc_Print( -2, "\t-a : toggles selecting the algorithm [default = %s]\n", fUseReshape1? "yes": "no" ); + Abc_Print( -2, "\t-s : toggles using simple method [default = %s]\n", fUseSimple? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggles printing additional information [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -32963,6 +36712,8 @@ int Abc_CommandAbc9False( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern Gia_Man_t * Gia_ManPairWiseMiter( Gia_Man_t * p ); + extern Gia_Man_t * Gia_ManDupWithCare( Gia_Man_t * p, Gia_Man_t * pCare ); FILE * pFile; Gia_Man_t * pAux; Gia_Man_t * pSecond; @@ -32973,13 +36724,15 @@ int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) int nInsDup = 0; int fDualOut = 0; int fSeq = 0; + int fPairWise= 0; int fTrans = 0; int fTransX = 0; int fConvert = 0; int fTransZ = 0; + int fWithCare= 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Idstxyzvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Idsptxyzcvh" ) ) != EOF ) { switch ( c ) { @@ -33000,6 +36753,9 @@ int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) case 's': fSeq ^= 1; break; + case 'p': + fPairWise ^= 1; + break; case 't': fTrans ^= 1; break; @@ -33012,6 +36768,9 @@ int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'z': fTransZ ^= 1; break; + case 'c': + fWithCare ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -33021,6 +36780,17 @@ int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + if ( fPairWise ) + { + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Miter(): There is no AIG.\n" ); + return 1; + } + pAux = Gia_ManPairWiseMiter( pAbc->pGia ); + Abc_FrameUpdateGia( pAbc, pAux ); + return 0; + } if ( fTrans || fTransX || fTransZ || fConvert ) { if ( pAbc->pGia == NULL ) @@ -33088,21 +36858,26 @@ int Abc_CommandAbc9Miter( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } // compute the miter - pAux = Gia_ManMiter( pAbc->pGia, pSecond, nInsDup, fDualOut, fSeq, 0, fVerbose ); + if ( fWithCare ) + pAux = Gia_ManDupWithCare( pAbc->pGia, pSecond ); + else + pAux = Gia_ManMiter( pAbc->pGia, pSecond, nInsDup, fDualOut, fSeq, 0, fVerbose ); Gia_ManStop( pSecond ); Abc_FrameUpdateGia( pAbc, pAux ); return 0; usage: - Abc_Print( -2, "usage: &miter [-I num] [-dstxyzvh] \n" ); + Abc_Print( -2, "usage: &miter [-I num] [-dsptxyzcvh] \n" ); Abc_Print( -2, "\t creates miter of two designs (current AIG vs. )\n" ); Abc_Print( -2, "\t-I num : the number of last PIs to replicate [default = %d]\n", nInsDup ); Abc_Print( -2, "\t-d : toggle creating dual-output miter [default = %s]\n", fDualOut? "yes": "no" ); Abc_Print( -2, "\t-s : toggle creating sequential miter [default = %s]\n", fSeq? "yes": "no" ); + Abc_Print( -2, "\t-p : toggle creating pair-wise miter [default = %s]\n", fPairWise? "yes": "no" ); Abc_Print( -2, "\t-t : toggle XORing POs of dual-output miter [default = %s]\n", fTrans? "yes": "no" ); Abc_Print( -2, "\t-x : toggle XORing POs of two-word miter [default = %s]\n", fTransX? "yes": "no" ); Abc_Print( -2, "\t-y : toggle convering two-word miter into dual-output miter [default = %s]\n", fConvert? "yes": "no" ); - Abc_Print( -2, "\t-z : toggle odering sides of the dual-output miter [default = %s]\n", fTransZ? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle ordering sides of the dual-output miter [default = %s]\n", fTransZ? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle duplicating AIG with the care set [default = %s]\n", fWithCare? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : AIGER file with the design to miter\n"); @@ -33361,117 +37136,7 @@ int Abc_CommandAbc9Lcorr( Abc_Frame_t * pAbc, int argc, char ** argv ) Cec_ManCorSetDefaultParams( pPars ); pPars->fLatchCorr = 1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FCPrcvwh" ) ) != EOF ) - { - switch ( c ) - { - case 'F': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nFrames = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nFrames < 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; - } - pPars->nBTLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nBTLimit < 0 ) - goto usage; - break; - case 'P': - if ( globalUtilOptind >= argc ) - { - Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nPrefix = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nPrefix < 0 ) - goto usage; - break; - case 'r': - pPars->fUseRings ^= 1; - break; - case 'c': - pPars->fUseCSat ^= 1; - break; - case 'v': - pPars->fVerbose ^= 1; - break; - case 'w': - pPars->fVerboseFlops ^= 1; - break; - default: - goto usage; - } - } - if ( pAbc->pGia == NULL ) - { - Abc_Print( -1, "Abc_CommandAbc9Lcorr(): There is no AIG.\n" ); - return 1; - } - if ( Gia_ManBoxNum(pAbc->pGia) && Gia_ManRegBoxNum(pAbc->pGia) ) - { - if ( pAbc->pGia->pAigExtra == NULL ) - { - printf( "Timing manager is given but there is no GIA of boxes.\n" ); - return 0; - } - pTemp = Gia_ManSweepWithBoxes( pAbc->pGia, NULL, pPars, 0, 0, pPars->fVerbose, pPars->fVerboseFlops ); - Abc_FrameUpdateGia( pAbc, pTemp ); - return 0; - } - if ( Gia_ManRegNum(pAbc->pGia) == 0 ) - { - Abc_Print( -1, "The network is combinational.\n" ); - return 0; - } - pTemp = Cec_ManLSCorrespondence( pAbc->pGia, pPars ); - Abc_FrameUpdateGia( pAbc, pTemp ); - return 0; - -usage: - Abc_Print( -2, "usage: &lcorr [-FCP num] [-rcvwh]\n" ); - Abc_Print( -2, "\t performs latch 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 ); - Abc_Print( -2, "\t-P num : the number of timeframes in the prefix [default = %d]\n", pPars->nPrefix ); - Abc_Print( -2, "\t-r : toggle using implication rings during refinement [default = %s]\n", pPars->fUseRings? "yes": "no" ); - Abc_Print( -2, "\t-c : toggle using circuit-based SAT solver [default = %s]\n", pPars->fUseCSat? "yes": "no" ); - Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-w : toggle printing verbose info about equivalent flops [default = %s]\n", pPars->fVerboseFlops? "yes": "no" ); - Abc_Print( -2, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Cec_ParCor_t Pars, * pPars = &Pars; - Gia_Man_t * pTemp; - int c; - Cec_ManCorSetDefaultParams( pPars ); - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FCPkrecqwvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "FCPXrcvwh" ) ) != EOF ) { switch ( c ) { @@ -33508,6 +37173,169 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nPrefix < 0 ) goto usage; break; + case 'X': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-X\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nLimitMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLimitMax < 0 ) + goto usage; + break; + case 'r': + pPars->fUseRings ^= 1; + break; + case 'c': + pPars->fUseCSat ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVerboseFlops ^= 1; + break; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Lcorr(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManBoxNum(pAbc->pGia) && Gia_ManRegBoxNum(pAbc->pGia) ) + { + if ( pAbc->pGia->pAigExtra == NULL ) + { + printf( "Timing manager is given but there is no GIA of boxes.\n" ); + return 0; + } + pTemp = Gia_ManSweepWithBoxes( pAbc->pGia, NULL, pPars, 0, 0, pPars->fVerbose, pPars->fVerboseFlops ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + } + if ( Gia_ManRegNum(pAbc->pGia) == 0 ) + { + Abc_Print( -1, "The network is combinational.\n" ); + return 0; + } + pTemp = Cec_ManLSCorrespondence( pAbc->pGia, pPars ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &lcorr [-FCPX num] [-rcvwh]\n" ); + Abc_Print( -2, "\t performs latch 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 ); + Abc_Print( -2, "\t-P num : the number of timeframes in the prefix [default = %d]\n", pPars->nPrefix ); + 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 : toggle using implication rings during refinement [default = %s]\n", pPars->fUseRings? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle using circuit-based SAT solver [default = %s]\n", pPars->fUseCSat? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing verbose info about equivalent flops [default = %s]\n", pPars->fVerboseFlops? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Cec_ManScorrCorrespondence( Gia_Man_t * p, Cec_ParCor_t * pPars ); + extern Gia_Man_t * Gia_ManScorrDivideTest( Gia_Man_t * p, Cec_ParCor_t * pPars ); + extern Gia_Man_t * Gia_SignalCorrespondencePart( Gia_Man_t * p, Cec_ParCor_t * pPars ); + Cec_ParCor_t Pars, * pPars = &Pars; + Gia_Man_t * pTemp; + int fPartition = 0; + int fUseOld = 0, c; + Cec_ManCorSetDefaultParams( pPars ); + pPars->nProcs = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "FCGXPSpkrecqowvh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nFrames < 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; + } + pPars->nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nBTLimit < 0 ) + goto usage; + break; + case 'G': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nPrefix = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nPrefix < 0 ) + goto usage; + break; + case 'X': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-X\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nLimitMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLimitMax < 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nProcs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nProcs < 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->nPartSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nPartSize < 0 ) + goto usage; + break; + case 'p': + fPartition ^= 1; + break; case 'k': pPars->fConstCorr ^= 1; break; @@ -33523,6 +37351,9 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'q': pPars->fStopWhenGone ^= 1; break; + case 'o': + fUseOld ^= 1; + break; case 'w': pPars->fVerboseFlops ^= 1; break; @@ -33554,21 +37385,33 @@ int Abc_CommandAbc9Scorr( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( 0, "The network is combinational.\n" ); return 0; } - pTemp = Cec_ManLSCorrespondence( pAbc->pGia, pPars ); + if ( pPars->nPartSize > 0 ) + pTemp = Gia_SignalCorrespondencePart( pAbc->pGia, pPars ); + else if ( fUseOld ) + pTemp = Cec_ManScorrCorrespondence( pAbc->pGia, pPars ); + else if ( fPartition ) + pTemp = Gia_ManScorrDivideTest( pAbc->pGia, pPars ); + else + pTemp = Cec_ManLSCorrespondence( pAbc->pGia, pPars ); Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &scorr [-FCP num] [-krecqwvh]\n" ); + Abc_Print( -2, "usage: &scorr [-FCGXPS 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 ); - Abc_Print( -2, "\t-P num : the number of timeframes in the prefix [default = %d]\n", pPars->nPrefix ); + Abc_Print( -2, "\t-G num : the number of timeframes in the prefix [default = %d]\n", pPars->nPrefix ); + 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-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" ); Abc_Print( -2, "\t-e : toggle using equivalences as choices [default = %s]\n", pPars->fMakeChoices? "yes": "no" ); Abc_Print( -2, "\t-c : toggle using circuit-based SAT solver [default = %s]\n", pPars->fUseCSat? "yes": "no" ); Abc_Print( -2, "\t-q : toggle quitting when PO is not a constant candidate [default = %s]\n", pPars->fStopWhenGone? "yes": "no" ); + Abc_Print( -2, "\t-o : toggle calling old engine [default = %s]\n", fUseOld? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing verbose info about equivalent flops [default = %s]\n", pPars->fVerboseFlops? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -33651,16 +37494,28 @@ int Abc_CommandAbc9Choice( Abc_Frame_t * pAbc, int argc, char ** argv ) int Abc_CommandAbc9Sat( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Vec_Int_t * Cbs2_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ); + extern Vec_Int_t * Cbs3_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, int nRestarts, Vec_Str_t ** pvStatus, int fVerbose ); Cec_ParSat_t ParsSat, * pPars = &ParsSat; Gia_Man_t * pTemp; int c; - int fNewSolver = 0, fCSat = 0; + int fNewSolver = 0, fNewSolver2 = 0, fCSat = 0, f0Proved = 0, nRestarts = 1; Cec_ManSatSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CSNanmtcvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "JCRSNanmtcxyzvh" ) ) != EOF ) { switch ( c ) { + case 'J': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-J\" should be followed by an integer.\n" ); + goto usage; + } + pPars->SolverType = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->SolverType < 0 ) + goto usage; + break; case 'C': if ( globalUtilOptind >= argc ) { @@ -33672,6 +37527,17 @@ int Abc_CommandAbc9Sat( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nBTLimit < 0 ) goto usage; break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nRestarts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nRestarts < 0 ) + goto usage; + break; case 'S': if ( globalUtilOptind >= argc ) { @@ -33695,7 +37561,7 @@ int Abc_CommandAbc9Sat( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; break; case 'a': - fNewSolver ^= 1; + pPars->fSaveCexes ^= 1; break; case 'n': pPars->fNonChrono ^= 1; @@ -33709,6 +37575,15 @@ int Abc_CommandAbc9Sat( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'c': fCSat ^= 1; break; + case 'x': + fNewSolver ^= 1; + break; + case 'y': + fNewSolver2 ^= 1; + break; + case 'z': + f0Proved ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -33727,10 +37602,12 @@ int Abc_CommandAbc9Sat( Abc_Frame_t * pAbc, int argc, char ** argv ) Vec_Str_t * vStatus; if ( fNewSolver ) vCounters = Cbs2_ManSolveMiterNc( pAbc->pGia, pPars->nBTLimit, &vStatus, pPars->fVerbose ); + else if ( fNewSolver2 ) + vCounters = Cbs3_ManSolveMiterNc( pAbc->pGia, pPars->nBTLimit, nRestarts, &vStatus, pPars->fVerbose ); else if ( pPars->fLearnCls ) vCounters = Tas_ManSolveMiterNc( pAbc->pGia, pPars->nBTLimit, &vStatus, pPars->fVerbose ); else if ( pPars->fNonChrono ) - vCounters = Cbs_ManSolveMiterNc( pAbc->pGia, pPars->nBTLimit, &vStatus, pPars->fVerbose ); + vCounters = Cbs_ManSolveMiterNc( pAbc->pGia, pPars->nBTLimit, &vStatus, f0Proved, pPars->fVerbose ); else vCounters = Cbs_ManSolveMiter( pAbc->pGia, pPars->nBTLimit, &vStatus, pPars->fVerbose ); Vec_IntFree( vCounters ); @@ -33738,22 +37615,33 @@ int Abc_CommandAbc9Sat( Abc_Frame_t * pAbc, int argc, char ** argv ) } else { - pTemp = Cec_ManSatSolving( pAbc->pGia, pPars ); + pTemp = Cec_ManSatSolving( pAbc->pGia, pPars, f0Proved ); Abc_FrameUpdateGia( pAbc, pTemp ); } + if ( pAbc->pGia->vSeqModelVec ) + { + Vec_Int_t * vStatuses = Abc_FrameDeriveStatusArray2( pAbc->pGia->vSeqModelVec ); + Abc_FrameReplacePoStatuses( pAbc, &vStatuses ); + Abc_FrameReplaceCexVec( pAbc, &pAbc->pGia->vSeqModelVec ); + } return 0; usage: - Abc_Print( -2, "usage: &sat [-CSN ] [-anmctvh]\n" ); + Abc_Print( -2, "usage: &sat [-JCRSN ] [-anmctxzvh]\n" ); Abc_Print( -2, "\t performs SAT solving for the combinational outputs\n" ); + Abc_Print( -2, "\t-J num : the SAT solver type [default = %d]\n", pPars->SolverType ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); + Abc_Print( -2, "\t-R num : the max number of restarts at a node [default = %d]\n", nRestarts ); Abc_Print( -2, "\t-S num : the min number of variables to recycle the solver [default = %d]\n", pPars->nSatVarMax ); Abc_Print( -2, "\t-N num : the min number of calls to recycle the solver [default = %d]\n", pPars->nCallsRecycle ); - Abc_Print( -2, "\t-a : toggle using new solver [default = %s]\n", fNewSolver? "yes": "no" ); + Abc_Print( -2, "\t-a : toggle solving all outputs and saving counter-examples [default = %s]\n", pPars->fSaveCexes? "yes": "no" ); Abc_Print( -2, "\t-n : toggle using non-chronological backtracking [default = %s]\n", pPars->fNonChrono? "yes": "no" ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" ); Abc_Print( -2, "\t-c : toggle using circuit-based SAT solver [default = %s]\n", fCSat? "yes": "no" ); Abc_Print( -2, "\t-t : toggle using learning in curcuit-based solver [default = %s]\n", pPars->fLearnCls? "yes": "no" ); + Abc_Print( -2, "\t-x : toggle using new solver [default = %s]\n", fNewSolver? "yes": "no" ); + Abc_Print( -2, "\t-y : toggle using new solver [default = %s]\n", fNewSolver2? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle replacing proved cones by const0 [default = %s]\n", f0Proved? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -33839,18 +37727,33 @@ int Abc_CommandAbc9SatEnum( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern void Cec4_ManSetParams( Cec_ParFra_t * pPars ); extern Gia_Man_t * Cec2_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); extern Gia_Man_t * Cec3_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); - Cec_ParFra_t ParsFra, * pPars = &ParsFra; - Gia_Man_t * pTemp; - int c, fUseAlgo = 0, fUseAlgoG = 0; - Cec_ManFraSetDefaultParams( pPars ); - pPars->fSatSweeping = 1; + extern Gia_Man_t * Cec4_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars ); + extern void Cec4_ManSimulateTest5( Gia_Man_t * p, int nConfs, int fVerbose ); + extern Gia_Man_t * Cec5_ManSimulateTest( Gia_Man_t * p, Cec_ParFra_t * pPars, int fCbs, int approxLim, int subBatchSz, int adaRecycle ); + extern Gia_Man_t * Gia_ManIvyFraig( Gia_Man_t * p, int nConfLimit, int fUseProve, int fVerbose ); + Cec_ParFra_t ParsFra, * pPars = &ParsFra; Gia_Man_t * pTemp; + int c, fUseAlgo = 0, fUseAlgoG = 0, fUseAlgoX = 0, fUseAlgoY = 0, fUseSave = 0, fUseIvy = 0, fUseProve = 0; + int fCbs = 1, approxLim = 600, subBatchSz = 1, adaRecycle = 500, nMaxNodes = 0; + Cec4_ManSetParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WRILDCrmdckngwvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "JWRILDCNPMrmdckngxysopwvh" ) ) != EOF ) { switch ( c ) { + case 'J': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-J\" should be followed by an integer.\n" ); + goto usage; + } + pPars->jType = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->jType < 0 ) + goto usage; + break; case 'W': if ( globalUtilOptind >= argc ) { @@ -33917,6 +37820,39 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pPars->nBTLimit < 0 ) goto usage; break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nCallsRecycle = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nCallsRecycle < 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nGenIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nGenIters < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMaxNodes = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMaxNodes < 0 ) + goto usage; + break; case 'r': pPars->fRewriting ^= 1; break; @@ -33938,6 +37874,21 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'g': fUseAlgoG ^= 1; break; + case 'x': + fUseAlgoX ^= 1; + break; + case 'y': + fUseAlgoY ^= 1; + break; + case 's': + fUseSave ^= 1; + break; + case 'o': + fUseIvy ^= 1; + break; + case 'p': + fUseProve ^= 1; + break; case 'w': pPars->fVeryVerbose ^= 1; break; @@ -33953,24 +37904,45 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Fraig(): There is no AIG.\n" ); return 1; } - if ( fUseAlgo ) + if ( fUseSave ) + { + Cec4_ManSimulateTest5( pAbc->pGia, pPars->nBTLimit, pPars->fVerbose ); + return 0; + } + else if ( fUseIvy && (!nMaxNodes || Gia_ManAndNum(pAbc->pGia) < nMaxNodes) ) + pTemp = Gia_ManIvyFraig( pAbc->pGia, pPars->nBTLimit, fUseProve, pPars->fVerbose ); + else if ( fUseAlgo ) pTemp = Cec2_ManSimulateTest( pAbc->pGia, pPars ); else if ( fUseAlgoG ) pTemp = Cec3_ManSimulateTest( pAbc->pGia, pPars ); - else + else if ( fUseAlgoX ) + pTemp = Cec4_ManSimulateTest( pAbc->pGia, pPars ); + else if ( fUseAlgoY ) + pTemp = Cec5_ManSimulateTest( pAbc->pGia, pPars, fCbs, approxLim, subBatchSz, adaRecycle ); + else pTemp = Cec_ManSatSweeping( pAbc->pGia, pPars, 0 ); + if ( pAbc->pGia->pCexSeq != NULL ) + { + pAbc->Status = 0; + pAbc->nFrames = 0; + Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexSeq ); + } Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &fraig [-WRILDC ] [-rmdckngwvh]\n" ); + Abc_Print( -2, "usage: &fraig [-JWRILDCNPM ] [-rmdckngxysopwvh]\n" ); Abc_Print( -2, "\t performs combinational SAT sweeping\n" ); + Abc_Print( -2, "\t-J num : the solver type [default = %d]\n", pPars->jType ); Abc_Print( -2, "\t-W num : the number of simulation words [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-R num : the number of simulation rounds [default = %d]\n", pPars->nRounds ); Abc_Print( -2, "\t-I num : the number of sweeping iterations [default = %d]\n", pPars->nItersMax ); Abc_Print( -2, "\t-L num : the max number of levels of nodes to consider [default = %d]\n", pPars->nLevelMax ); Abc_Print( -2, "\t-D num : the max number of steps of speculative reduction [default = %d]\n", pPars->nDepthMax ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); + Abc_Print( -2, "\t-N num : the min number of calls to recycle the solver [default = %d]\n", pPars->nCallsRecycle ); + Abc_Print( -2, "\t-P num : the number of pattern generation iterations [default = %d]\n", pPars->nGenIters ); + Abc_Print( -2, "\t-M num : the node count limit to call the old sweeper [default = %d]\n", nMaxNodes ); Abc_Print( -2, "\t-r : toggle the use of AIG rewriting [default = %s]\n", pPars->fRewriting? "yes": "no" ); Abc_Print( -2, "\t-m : toggle miter vs. any circuit [default = %s]\n", pPars->fCheckMiter? "miter": "circuit" ); Abc_Print( -2, "\t-d : toggle using double output miters [default = %s]\n", pPars->fDualOut? "yes": "no" ); @@ -33978,6 +37950,11 @@ int Abc_CommandAbc9Fraig( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-k : toggle using logic cones in the SAT solver [default = %s]\n", pPars->fUseCones? "yes": "no" ); Abc_Print( -2, "\t-n : toggle using new implementation [default = %s]\n", fUseAlgo? "yes": "no" ); Abc_Print( -2, "\t-g : toggle using another new implementation [default = %s]\n", fUseAlgoG? "yes": "no" ); + Abc_Print( -2, "\t-x : toggle using another new implementation [default = %s]\n", fUseAlgoX? "yes": "no" ); + Abc_Print( -2, "\t-y : toggle using another new implementation [default = %s]\n", fUseAlgoY? "yes": "no" ); + Abc_Print( -2, "\t-s : toggle dumping equivalences into a file [default = %s]\n", fUseSave? "yes": "no" ); + Abc_Print( -2, "\t-o : toggle using the old SAT sweeper [default = %s]\n", fUseIvy? "yes": "no" ); + Abc_Print( -2, "\t-p : toggle trying to prove when running the old SAT sweeper [default = %s]\n", fUseProve? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing even more verbose information [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -34085,8 +38062,9 @@ int Abc_CommandAbc9Srm( Abc_Frame_t * pAbc, int argc, char ** argv ) int fSpeculate = 1; int fSkipSome = 0; int fDualOut = 0; + int fComb = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Adrsfvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Adrsfcvh" ) ) != EOF ) { switch ( c ) { @@ -34111,6 +38089,9 @@ int Abc_CommandAbc9Srm( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'f': fSkipSome ^= 1; break; + case 'c': + fComb ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -34125,6 +38106,16 @@ int Abc_CommandAbc9Srm( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Srm(): There is no AIG.\n" ); return 1; } + if ( fComb ) + { + extern int Cec4_ManSimulateOnlyTest( Gia_Man_t * p, int fVerbose ); + int Result = Cec4_ManSimulateOnlyTest( pAbc->pGia, fVerbose ); + extern Gia_Man_t * Gia_ManCombSpecReduce( Gia_Man_t * p ); + pTemp = Gia_ManCombSpecReduce( pAbc->pGia ); + Abc_FrameUpdateGia( pAbc, pTemp ); + Result = 0; + return 0; + } sprintf(pFileName, "gsrm%s.aig", fSpeculate? "" : "s" ); sprintf(pFileName2, "gsyn%s.aig", fSpeculate? "" : "s" ); pTemp = Gia_ManSpecReduce( pAbc->pGia, fDualOut, fSynthesis, fSpeculate, fSkipSome, fVerbose ); @@ -34135,7 +38126,7 @@ int Abc_CommandAbc9Srm( Abc_Frame_t * pAbc, int argc, char ** argv ) pTemp = Gia_ManSeqStructSweep( pAux = pTemp, 1, 1, 0 ); Gia_ManStop( pAux ); } - Gia_AigerWrite( pTemp, pFileNameIn ? pFileNameIn : pFileName, 0, 0 ); + Gia_AigerWrite( pTemp, pFileNameIn ? pFileNameIn : pFileName, 0, 0, 0 ); Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", pFileName ); Gia_ManPrintStatsShort( pTemp ); Gia_ManStop( pTemp ); @@ -34148,7 +38139,7 @@ int Abc_CommandAbc9Srm( Abc_Frame_t * pAbc, int argc, char ** argv ) pTemp = Gia_ManSeqStructSweep( pAux = pTemp, 1, 1, 0 ); Gia_ManStop( pAux ); - Gia_AigerWrite( pTemp, pFileName2, 0, 0 ); + Gia_AigerWrite( pTemp, pFileName2, 0, 0, 0 ); Abc_Print( 1, "Reduced original network was written into file \"%s\".\n", pFileName2 ); Gia_ManPrintStatsShort( pTemp ); Gia_ManStop( pTemp ); @@ -34157,13 +38148,14 @@ int Abc_CommandAbc9Srm( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &srm [-A file] [-drsfvh]\n" ); - Abc_Print( -2, "\t writes speculatively reduced model into file \"%s\"\n", pFileName ); + Abc_Print( -2, "usage: &srm [-A file] [-drsfcvh]\n" ); + Abc_Print( -2, "\t derives or writes speculatively reduced model into file \"%s\"\n", pFileName ); Abc_Print( -2, "\t-A file : file name for dumping speculative-reduced model [default = \"gsrm.aig\"]\n" ); Abc_Print( -2, "\t-d : toggle creating dual-output miter [default = %s]\n", fDualOut? "yes": "no" ); Abc_Print( -2, "\t-r : toggle writing reduced network for synthesis [default = %s]\n", fSynthesis? "yes": "no" ); Abc_Print( -2, "\t-s : toggle using speculation at the internal nodes [default = %s]\n", fSpeculate? "yes": "no" ); Abc_Print( -2, "\t-f : toggle filtering to remove redundant equivalences [default = %s]\n", fSkipSome? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle using combinational speculation [default = %s]\n", fComb? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -34249,7 +38241,7 @@ int Abc_CommandAbc9Srm2( Abc_Frame_t * pAbc, int argc, char ** argv ) pTemp = Gia_ManSeqStructSweep( pAux = pTemp, 1, 1, 0 ); Gia_ManStop( pAux ); - Gia_AigerWrite( pTemp, pFileName, 0, 0 ); + Gia_AigerWrite( pTemp, pFileName, 0, 0, 0 ); Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", pFileName ); Gia_ManPrintStatsShort( pTemp ); Gia_ManStop( pTemp ); @@ -34540,10 +38532,10 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) FILE * pFile; Gia_Man_t * pGias[2] = {NULL, NULL}, * pMiter; char ** pArgvNew; - int c, nArgcNew, fMiter = 0, fDualOutput = 0, fDumpMiter = 0; + int c, nArgcNew, fUseSim = 0, fUseNewX = 0, fUseNewY = 0, fMiter = 0, fDualOutput = 0, fDumpMiter = 0; Cec_ManCecSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CTnmdasvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "CTnmdasxytvwh" ) ) != EOF ) { switch ( c ) { @@ -34584,9 +38576,21 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) case 's': pPars->fSilent ^= 1; break; + case 'x': + fUseNewX ^= 1; + break; + case 'y': + fUseNewY ^= 1; + break; + case 't': + fUseSim ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; case 'h': goto usage; default: @@ -34615,13 +38619,46 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) } else { - Gia_Man_t * pTemp; + abctime clk = Abc_Clock(); + Gia_Obj_t * pObj; int i; if ( !pPars->fSilent ) Abc_Print( 1, "Assuming the current network is a single-output miter.\n" ); - pTemp = Gia_ManDemiterToDual( pAbc->pGia ); - pAbc->Status = Cec_ManVerify( pTemp, pPars ); - ABC_SWAP( Abc_Cex_t *, pAbc->pGia->pCexComb, pTemp->pCexComb ); - Gia_ManStop( pTemp ); + if ( fUseSim ) + { + abctime clk = Abc_Clock(); + extern int Gia_ManCheckSimEquiv( Gia_Man_t * p, int fVerbose ); + int Status = Gia_ManCheckSimEquiv( pAbc->pGia, pPars->fVerbose ); + if ( Status == 1 ) + Abc_Print( 1, "Networks are equivalent. " ); + else if ( Status == 0 ) + Abc_Print( 1, "Networks are NOT equivalent. " ); + else + Abc_Print( 1, "Networks are UNDECIDED. " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return 0; + } + // handle the case when the output is disproved by an all-0 primary input pattern + ABC_FREE( pAbc->pGia->pCexComb ); + Gia_ManSetPhase( pAbc->pGia ); + Gia_ManForEachCo( pAbc->pGia, pObj, i ) + if ( pObj->fPhase ) + { + pAbc->pGia->pCexComb = Abc_CexAlloc( 0, Gia_ManCiNum(pAbc->pGia), 1 ); + if ( !pPars->fSilent ) + { + Abc_Print( 1, "Networks are NOT EQUIVALENT. Output %d trivially differs (different phase). ", i ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + pAbc->Status = 0;// satisfiable + break; + } + if ( pAbc->pGia->pCexComb == NULL ) + { + Gia_Man_t * pTemp = Gia_ManDemiterToDual( pAbc->pGia ); + pAbc->Status = Cec_ManVerify( pTemp, pPars ); + ABC_SWAP( Abc_Cex_t *, pAbc->pGia->pCexComb, pTemp->pCexComb ); + Gia_ManStop( pTemp ); + } } Abc_FrameReplaceCex( pAbc, &pAbc->pGia->pCexComb ); return 0; @@ -34700,16 +38737,81 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) } } // compute the miter - pMiter = Gia_ManMiter( pGias[0], pGias[1], 0, 1, 0, 0, pPars->fVerbose ); + if ( Gia_ManCiNum(pGias[0]) < 6 ) + { + Gia_Man_t * pGias0 = Gia_ManDup( pGias[0] ); + Gia_Man_t * pGias1 = Gia_ManDup( pGias[1] ); + for ( c = Gia_ManCiNum(pGias[0]); c < 6; c++ ) + { + Gia_ManAppendCi(pGias0); + Gia_ManAppendCi(pGias1); + } + pMiter = Gia_ManMiter( pGias0, pGias1, 0, !fUseNewX && !fUseNewY, 0, 0, pPars->fVerbose ); + Gia_ManStop( pGias0 ); + Gia_ManStop( pGias1 ); + } + else + pMiter = Gia_ManMiter( pGias[0], pGias[1], 0, !fUseNewX && !fUseNewY, 0, 0, pPars->fVerbose ); + if ( pMiter ) { if ( fDumpMiter ) { Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" ); - Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0 ); + Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0, 0 ); + } + if ( pGias[0]->vSimsPi ) + { + pMiter->vSimsPi = Vec_WrdDup(pGias[0]->vSimsPi); + pMiter->nSimWords = pGias[0]->nSimWords; + } + if ( fUseSim && Gia_ManCiNum(pMiter) > 40 ) + { + Abc_Print( -1, "This type of CEC can only be applied to AIGs with no more than 40 inputs.\n" ); + return 0; + } + if ( fUseSim ) + { + abctime clk = Abc_Clock(); + extern int Gia_ManCheckSimEquiv( Gia_Man_t * p, int fVerbose ); + int Status = Gia_ManCheckSimEquiv( pMiter, pPars->fVerbose ); + if ( Status == 1 ) + Abc_Print( 1, "Networks are equivalent. " ); + else if ( Status == 0 ) + Abc_Print( 1, "Networks are NOT equivalent. " ); + else + Abc_Print( 1, "Networks are UNDECIDED. " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + else if ( fUseNewX ) + { + abctime clk = Abc_Clock(); + extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pNew = Cec4_ManSimulateTest3( pMiter, pPars->nBTLimit, pPars->fVerbose ); + if ( Gia_ManAndNum(pNew) == 0 ) + Abc_Print( 1, "Networks are equivalent. " ); + else + Abc_Print( 1, "Networks are UNDECIDED. " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Gia_ManStop( pNew ); + } + else if ( fUseNewY ) + { + abctime clk = Abc_Clock(); + extern Gia_Man_t * Cec5_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pNew = Cec5_ManSimulateTest3( pMiter, pPars->nBTLimit, pPars->fVerbose ); + if ( Gia_ManAndNum(pNew) == 0 ) + Abc_Print( 1, "Networks are equivalent. " ); + else + Abc_Print( 1, "Networks are UNDECIDED. " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Gia_ManStop( pNew ); + } + else + { + pAbc->Status = Cec_ManVerify( pMiter, pPars ); + Abc_FrameReplaceCex( pAbc, &pGias[0]->pCexComb ); } - pAbc->Status = Cec_ManVerify( pMiter, pPars ); - Abc_FrameReplaceCex( pAbc, &pGias[0]->pCexComb ); Gia_ManStop( pMiter ); } if ( pGias[0] != pAbc->pGia ) @@ -34718,7 +38820,7 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &cec [-CT num] [-nmdasvh]\n" ); + Abc_Print( -2, "usage: &cec [-CT num] [-nmdasxytvwh]\n" ); Abc_Print( -2, "\t new combinational equivalence checker\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeLimit ); @@ -34727,7 +38829,196 @@ int Abc_CommandAbc9Cec( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-d : toggle using dual output miter [default = %s]\n", fDualOutput? "yes":"no"); Abc_Print( -2, "\t-a : toggle writing dual-output miter [default = %s]\n", fDumpMiter? "yes":"no"); Abc_Print( -2, "\t-s : toggle silent operation [default = %s]\n", pPars->fSilent ? "yes":"no"); + Abc_Print( -2, "\t-x : toggle using new solver [default = %s]\n", fUseNewX? "yes":"no"); + Abc_Print( -2, "\t-y : toggle using new solver [default = %s]\n", fUseNewY? "yes":"no"); + Abc_Print( -2, "\t-t : toggle using simulation [default = %s]\n", fUseSim? "yes":"no"); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes":"no"); + Abc_Print( -2, "\t-w : toggle printing SAT solver statistics [default = %s]\n", pPars->fVeryVerbose? "yes":"no"); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9ICec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Cec_ParCec_t ParsCec, * pPars = &ParsCec; + FILE * pFile; + Gia_Man_t * pGias[2] = {NULL, NULL}, * pMiter; + char ** pArgvNew; + int c, nArgcNew, fUseNew = 0, fDumpMiter = 0; + Cec_ManCecSetDefaultParams( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CTaxvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nBTLimit < 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + pPars->TimeLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->TimeLimit < 0 ) + goto usage; + break; + case 'a': + fDumpMiter ^= 1; + break; + case 'x': + fUseNew ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew > 2 ) + { + Abc_Print( -1, "Abc_CommandAbc9Cec(): Wrong number of command-line arguments.\n" ); + return 1; + } + if ( nArgcNew == 2 ) + { + char * pFileNames[2] = { pArgvNew[0], pArgvNew[1] }, * pTemp; + int n; + for ( n = 0; n < 2; n++ ) + { + // fix the wrong symbol + for ( pTemp = pFileNames[n]; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( pFileNames[n], "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", pFileNames[n] ); + if ( (pFileNames[n] = Extra_FileGetSimilarName( pFileNames[n], ".aig", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", pFileNames[n] ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pGias[n] = Gia_AigerRead( pFileNames[n], 0, 0, 0 ); + if ( pGias[n] == NULL ) + { + Abc_Print( -1, "Reading AIGER from file \"%s\" has failed.\n", pFileNames[n] ); + return 0; + } + } + } + else + { + char * FileName, * pTemp; + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Cec(): There is no current AIG.\n" ); + return 1; + } + pGias[0] = pAbc->pGia; + if ( nArgcNew == 1 ) + FileName = pArgvNew[0]; + else + { + assert( nArgcNew == 0 ); + if ( pAbc->pGia->pSpec == NULL ) + { + Abc_Print( -1, "File name is not given on the command line.\n" ); + return 1; + } + FileName = pAbc->pGia->pSpec; + } + // fix the wrong symbol + for ( pTemp = FileName; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pGias[1] = Gia_AigerRead( FileName, 0, 0, 0 ); + if ( pGias[1] == NULL ) + { + Abc_Print( -1, "Reading AIGER has failed.\n" ); + return 0; + } + } + // compute the miter + pMiter = Gia_ManMiterInverse( pGias[0], pGias[1], !fUseNew, pPars->fVerbose ); + if ( pMiter ) + { + if ( fDumpMiter ) + { + Abc_Print( 0, "The verification miter is written into file \"%s\".\n", "cec_miter.aig" ); + Gia_AigerWrite( pMiter, "cec_miter.aig", 0, 0, 0 ); + } + if ( fUseNew ) + { + abctime clk = Abc_Clock(); + extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pNew = Cec4_ManSimulateTest3( pMiter, pPars->nBTLimit, pPars->fVerbose ); + if ( Gia_ManAndNum(pNew) == 0 ) + Abc_Print( 1, "Networks are equivalent. " ); + else + Abc_Print( 1, "Networks are UNDECIDED. " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Gia_ManStop( pNew ); + } + else + { + pAbc->Status = Cec_ManVerify( pMiter, pPars ); + Abc_FrameReplaceCex( pAbc, &pGias[0]->pCexComb ); + } + Gia_ManStop( pMiter ); + } + if ( pGias[0] != pAbc->pGia ) + Gia_ManStop( pGias[0] ); + Gia_ManStop( pGias[1] ); + return 0; + +usage: + Abc_Print( -2, "usage: &icec [-CT num] [-axvwh]\n" ); + Abc_Print( -2, "\t combinational equivalence checker for inverse circuits\n" ); + Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); + Abc_Print( -2, "\t-T num : approximate runtime limit in seconds [default = %d]\n", pPars->TimeLimit ); + Abc_Print( -2, "\t-a : toggle writing the miter [default = %s]\n", fDumpMiter? "yes":"no"); + Abc_Print( -2, "\t-x : toggle using new solver [default = %s]\n", fUseNew? "yes":"no"); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", pPars->fVerbose? "yes":"no"); + Abc_Print( -2, "\t-w : toggle printing SAT solver statistics [default = %s]\n", pPars->fVeryVerbose? "yes":"no"); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } @@ -35587,7 +39878,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, "KCFAGRDEWSTXYqalepmrsdbgxyofuijkztncvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAGRDEWSTXYqalepmrsdbgxyofuijkztncvwh" ) ) != EOF ) { switch ( c ) { @@ -35749,7 +40040,7 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->fExpRed ^= 1; break; case 'l': - pPars->fLatchPaths ^= 1; + pPars->fLut6Filter ^= 1; break; case 'e': pPars->fEdge ^= 1; @@ -35767,7 +40058,8 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->fUse34Spec ^= 1; break; case 'b': - pPars->fUseBat ^= 1; + //pPars->fUseBat ^= 1; + pPars->fUseCheck1 ^= 1; break; case 'g': pPars->fDelayOpt ^= 1; @@ -35788,7 +40080,8 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->fEnableCheck75u ^= 1; break; case 'i': - pPars->fUseCofVars ^= 1; + //pPars->fUseCofVars ^= 1; + pPars->fUseCheck2 ^= 1; break; // case 'j': // pPars->fEnableCheck07 ^= 1; @@ -35814,6 +40107,9 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'v': pPars->fVerbose ^= 1; break; + case 'w': + pPars->fVerboseTrace ^= 1; + break; case 'h': pPars->fHashMapping ^= 1; break; @@ -35898,6 +40194,16 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->pFuncCell = If_CutPerformCheck07; pPars->fCutMin = 1; } + if ( pPars->fUseCheck1 || pPars->fUseCheck2 ) + { + if ( pPars->nLutSize > 6 ) + { + Abc_Print( -1, "This feature only works for no more than 6-LUTs.\n" ); + return 1; + } + pPars->pFuncCell = pPars->fUseCheck2 ? If_MatchCheck2 : If_MatchCheck1; + pPars->fCutMin = 1; + } if ( pPars->fUseCofVars ) { if ( !(pPars->nLutSize & 1) ) @@ -36006,7 +40312,7 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->nLutSize = pPars->nGateSize; } - if ( pPars->fUseDsd || pPars->fUseTtPerm ) + if ( pPars->fUseDsd || pPars->fUseTtPerm || pPars->fLut6Filter ) { pPars->fTruth = 1; pPars->fCutMin = 1; @@ -36069,8 +40375,24 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } + // add wire delay to LUT library delays + if ( pPars->WireDelay > 0 && pPars->pLutLib ) + { + int i, k; + for ( i = 0; i <= pPars->pLutLib->LutMax; i++ ) + for ( k = 0; k <= i; k++ ) + pPars->pLutLib->pLutDelays[i][k] += pPars->WireDelay; + } // perform mapping pNew = Gia_ManPerformMapping( pAbc->pGia, pPars ); + // subtract wire delay from LUT library delays + if ( pPars->WireDelay > 0 && pPars->pLutLib ) + { + int i, k; + for ( i = 0; i <= pPars->pLutLib->LutMax; i++ ) + for ( k = 0; k <= i; k++ ) + pPars->pLutLib->pLutDelays[i][k] -= pPars->WireDelay; + } if ( pNew == NULL ) { Abc_Print( -1, "Abc_CommandAbc9If(): Mapping of GIA has failed.\n" ); @@ -36088,7 +40410,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] [-qarlepmsdbgxyofuijkztnchv]\n" ); + Abc_Print( -2, "usage: &if [-KCFAGRTXY num] [-DEW float] [-S 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 ); @@ -36106,7 +40428,8 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) 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" ); - Abc_Print( -2, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" ); +// Abc_Print( -2, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" ); + Abc_Print( -2, "\t-l : toggle restricting the type of 6-input lookup tables [default = %s]\n", pPars->fLut6Filter? "yes": "no" ); Abc_Print( -2, "\t-e : uses edge-based cut selection heuristics [default = %s]\n", pPars->fEdge? "yes": "no" ); Abc_Print( -2, "\t-p : uses power-aware cut selection heuristics [default = %s]\n", pPars->fPower? "yes": "no" ); Abc_Print( -2, "\t-m : enables cut minimization by removing vacuous variables [default = %s]\n", pPars->fCutMin? "yes": "no" ); @@ -36129,6 +40452,7 @@ int Abc_CommandAbc9If( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-c : toggles computing truth tables in a new way [default = %s]\n", pPars->fUseTtPerm? "yes": "no" ); Abc_Print( -2, "\t-h : toggles rehashing AIG after mapping [default = %s]\n", pPars->fHashMapping? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggles printing delay trace [default = %s]\n", pPars->fVerboseTrace? "yes": "no" ); return 1; } @@ -36461,6 +40785,72 @@ int Abc_CommandAbc9If2( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Sif( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManSifPerform( Gia_Man_t * p, int nLutSize, int fEvalOnly, int fVerbose ); + Gia_Man_t * pNew; + int c, nLutSize = 6, fEvalOnly = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Kevh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by a positive integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 2 || nLutSize > 16 ) + { + Abc_Print( -1, "LUT size %d is not supported.\n", nLutSize ); + goto usage; + } + break; + case 'e': + fEvalOnly ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Empty GIA network.\n" ); + return 1; + } + pNew = Gia_ManSifPerform( pAbc->pGia, nLutSize, fEvalOnly, fVerbose ); + if ( pNew != NULL ) + Abc_FrameUpdateGia( pAbc, pNew ); + return 0; + +usage: + Abc_Print( -2, "usage: &sif [-K num] [-evh]\n" ); + Abc_Print( -2, "\t performs technology mapping\n" ); + Abc_Print( -2, "\t-K num : sets the LUT size for the mapping [default = %d]\n", nLutSize ); + Abc_Print( -2, "\t-e : toggles the evaluation mode [default = %s]\n", fEvalOnly? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -37050,7 +41440,7 @@ int Abc_CommandAbc9Mf( Abc_Frame_t * pAbc, int argc, char ** argv ) Gia_Man_t * pNew; int c; Mf_ManSetDefaultPars( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFARLEDWaekmcgvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFARLEDWaekmclgvwh" ) ) != EOF ) { switch ( c ) { @@ -37174,6 +41564,9 @@ int Abc_CommandAbc9Mf( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'c': pPars->fGenCnf ^= 1; break; + case 'l': + pPars->fGenLit ^= 1; + break; case 'g': pPars->fPureAig ^= 1; break; @@ -37226,6 +41619,7 @@ int Abc_CommandAbc9Mf( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-k : toggles coarsening the subject graph [default = %s]\n", pPars->fCoarsen? "yes": "no" ); Abc_Print( -2, "\t-m : toggles cut minimization [default = %s]\n", pPars->fCutMin? "yes": "no" ); Abc_Print( -2, "\t-c : toggles mapping for CNF generation [default = %s]\n", pPars->fGenCnf? "yes": "no" ); + Abc_Print( -2, "\t-l : toggles mapping for literals [default = %s]\n", pPars->fGenLit? "yes": "no" ); Abc_Print( -2, "\t-g : toggles generating AIG without mapping [default = %s]\n", pPars->fPureAig? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles very verbose output [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); @@ -37865,68 +42259,738 @@ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( pAbc->pGia == NULL ) - { - Abc_Print( -1, "Empty GIA network.\n" ); - return 1; - } - if ( fMapping ) + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Empty GIA network.\n" ); + return 1; + } + if ( fMapping ) + { + Sle_ManExplore( pAbc->pGia, nBTLimit, DelayMax, fDynamic, nEdges==2, fVerbose ); + return 0; + } + if ( !Gia_ManHasMapping(pAbc->pGia) ) + { + Abc_Print( -1, "Current AIG has no mapping. Run \"&if\".\n" ); + return 1; + } + if ( Gia_ManLutSizeMax(pAbc->pGia) > 6 ) + { + Abc_Print( 0, "Current AIG has mapping into %d-LUTs.\n", Gia_ManLutSizeMax(pAbc->pGia) ); + return 0; + } + if ( fUsePack ) + { + if ( pAbc->pGia->vPacking == NULL ) + { + Abc_Print( -1, "Packing information is not present.\n" ); + return 0; + } + Gia_ManConvertPackingToEdges( pAbc->pGia ); + return 0; + } + if ( !fUseOld ) + { + //Edg_ManAssignEdgeNew( pAbc->pGia, nEdges, fVerbose ); + Seg_ManComputeDelay( pAbc->pGia, DelayMax, nFanouts, nEdges==2, fVerbose ); + return 0; + } + if ( pAbc->pGia->pManTime && fReverse ) + { + Abc_Print( 0, "Reverse computation does not work when boxes are present.\n" ); + return 0; + } + if ( fReverse ) + DelayMax = Gia_ManComputeEdgeDelay2( pAbc->pGia ); + else + DelayMax = Gia_ManComputeEdgeDelay( pAbc->pGia, nEdges == 2 ); + //printf( "The number of edges = %d. Delay = %d.\n", Gia_ManEvalEdgeCount(pAbc->pGia), DelayMax ); + return 0; + +usage: + Abc_Print( -2, "usage: &edge [-CDFE num] [-rpomdvh]\n" ); + Abc_Print( -2, "\t find edge assignment of the LUT-mapped network\n" ); + Abc_Print( -2, "\t-C num : the SAT solver conflict limit (0 = unused) [default = %d]\n", nBTLimit ); + Abc_Print( -2, "\t-D num : the upper bound on delay [default = %d]\n", DelayMax ); + Abc_Print( -2, "\t-F num : skip using edge if fanout higher than this [default = %d]\n", nFanouts ); + Abc_Print( -2, "\t-E num : the limit on the number of edges (1 <= num <= 2) [default = %d]\n", nEdges ); + Abc_Print( -2, "\t-r : toggles using reverse order [default = %s]\n", fReverse? "yes": "no" ); + Abc_Print( -2, "\t-p : toggles deriving edges from packing [default = %s]\n", fUsePack? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles using old algorithm [default = %s]\n", fUseOld? "yes": "no" ); + Abc_Print( -2, "\t-m : toggles combining edge assignment with mapping [default = %s]\n", fMapping? "yes": "no" ); + Abc_Print( -2, "\t-d : toggles dynamic addition of clauses [default = %s]\n", fDynamic? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9SatLut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManLutSat( Gia_Man_t * p, int LutSize, int nNumber, int nImproves, int nBTLimit, int DelayMax, int nEdges, int fDelay, int fReverse, int fVerbose, int fVeryVerbose ); + int c, LutSize = 0, nNumber = 32, nImproves = 0, nBTLimit = 100, DelayMax = 0, nEdges = 0; + int fDelay = 0, fReverse = 0, fVeryVerbose = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NICDQdrwvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); + goto usage; + } + nNumber = atoi(argv[globalUtilOptind]); + if ( nNumber > 128 ) + { + Abc_Print( -1, "The number of AIG nodes should not exceed 128.\n" ); + goto usage; + } + globalUtilOptind++; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nImproves = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" ); + goto usage; + } + nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" ); + goto usage; + } + DelayMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'Q': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-Q\" should be followed by a positive integer.\n" ); + goto usage; + } + nEdges = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'd': + fDelay ^= 1; + break; + case 'r': + fReverse ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + default: + goto usage; + } + } + + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Empty GIA network.\n" ); + return 1; + } + if ( !Gia_ManHasMapping(pAbc->pGia) ) + { + Abc_Print( -1, "Current AIG has no mapping. Run \"&if\".\n" ); + return 1; + } + LutSize = Gia_ManLutSizeMax(pAbc->pGia); + if ( LutSize > 6 ) + Abc_Print( 0, "Current AIG is mapped into %d-LUTs (only 6-LUT mapping is currently supported).\n", Gia_ManLutSizeMax(pAbc->pGia) ); + else + Gia_ManLutSat( pAbc->pGia, LutSize, nNumber, nImproves, nBTLimit, DelayMax, nEdges, fDelay, fReverse, fVerbose, fVeryVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: &satlut [-NICDQ num] [-drwvh]\n" ); + Abc_Print( -2, "\t performs SAT-based remapping of the LUT-mapped network\n" ); + Abc_Print( -2, "\t-N num : the limit on AIG nodes in the window (num <= 128) [default = %d]\n", nNumber ); + Abc_Print( -2, "\t-I num : the limit on the number of improved windows [default = %d]\n", nImproves ); + Abc_Print( -2, "\t-C num : the limit on the number of conflicts [default = %d]\n", nBTLimit ); + Abc_Print( -2, "\t-D num : the user-specified required times at the outputs [default = %d]\n", DelayMax ); + Abc_Print( -2, "\t-Q num : the maximum number of edges [default = %d]\n", nEdges ); + Abc_Print( -2, "\t-d : toggles delay optimization [default = %s]\n", fDelay? "yes": "no" ); + Abc_Print( -2, "\t-r : toggles using reverse search [default = %s]\n", fReverse? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9LNetRead( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Vec_WrdReadTest( char * pFileName ); + extern void Gia_ManReadSimInfoInputs( char * pFileName, char * pFileOut1, int fVerbose ); + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + default: + goto usage; + } + } + if ( argc == globalUtilOptind + 2 ) // read 1 file, write 1 file + { + Gia_ManReadSimInfoInputs( argv[globalUtilOptind], argv[globalUtilOptind+1], fVerbose ); + return 0; + } + if ( strstr(argv[globalUtilOptind], ".v") ) + { + Gia_Man_t * pNew = Vec_WrdReadTest( argv[globalUtilOptind] ); + if ( pNew == NULL ) + { + printf( "Cannot read network from file \"%s\".\n", argv[globalUtilOptind] ); + return 0; + } + Abc_FrameUpdateGia( pAbc, pNew ); + } + return 0; + +usage: + Abc_Print( -2, "usage: &lnetread [-vh] \n" ); + Abc_Print( -2, "\t reads and converts the network or the simulation data\n" ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n"); + Abc_Print( -2, "\t : input file name with simulation information\n"); + Abc_Print( -2, "\t : output file name with simulation information\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9LNetSim( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManSimInfoPassTest( Gia_Man_t * p, char * pFileName, char * pFileName2, int fVerbose ); + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Empty GIA network.\n" ); + return 1; + } + if ( argc != globalUtilOptind + 2 ) + { + Abc_Print( -1, "Expecting two file names on the command line.\n" ); + return 1; + } + Gia_ManSimInfoPassTest( pAbc->pGia, argv[globalUtilOptind], argv[globalUtilOptind+1], fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: &lnetsim [-vh] \n" ); + Abc_Print( -2, "\t performs specialized AIG simulation\n" ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n"); + Abc_Print( -2, "\t : input file name with simulation information\n"); + Abc_Print( -2, "\t : output file name with simulation information\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9LNetEval( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManSimInfoEval( Gia_Man_t * p, char * pFileName, char * pFileName2, int nOuts, int fVerbose ); + int c, nOuts = -1, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ovh" ) ) != EOF ) + { + switch ( c ) + { + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by a positive integer.\n" ); + goto usage; + } + nOuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Empty GIA network.\n" ); + return 1; + } + if ( argc != globalUtilOptind + 2 ) + { + Abc_Print( -1, "Expecting two file names on the command line.\n" ); + return 1; + } + Gia_ManSimInfoEval( pAbc->pGia, argv[globalUtilOptind], argv[globalUtilOptind+1], nOuts, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: &lneteval [-O num] [-vh] \n" ); + Abc_Print( -2, "\t performs testing of the AIG on the simulation data\n" ); + Abc_Print( -2, "\t-O num : the output group size [default = %d]\n", nOuts ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n"); + Abc_Print( -2, "\t : file name with simulation information\n"); + Abc_Print( -2, "\t : file name with simulation information\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9LNetOpt( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManPerformLNetOpt( Gia_Man_t * p, int fTryNew, char * pFileName, int nIns, int nOuts, int Thresh, int nRounds, int fVerbose ); + extern Gia_Man_t * Gia_ManPerformLNetOptNew( Gia_Man_t * p, char * pFileName, int nIns, int nOuts, int Thresh, int nRounds, int fVerbose ); + Gia_Man_t * pTemp; + char * pFileName = NULL; + int c, nIns = 6, nOuts = 2, Limit = 0, nRounds = 20, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IORXvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nIns = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by a positive integer.\n" ); + goto usage; + } + nOuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by a positive integer.\n" ); + goto usage; + } + Limit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'X': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-X\" should be followed by a positive integer.\n" ); + goto usage; + } + nRounds = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + default: + goto usage; + } + } + if ( argc > globalUtilOptind + 1 ) + { + return 0; + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Empty GIA network.\n" ); + return 1; + } + if ( argc == globalUtilOptind + 1 ) + { + FILE * pFile = fopen( argv[globalUtilOptind], "rb" ); + if ( pFile == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9BCore(): Cannot open file \"%s\" for reading the simulation information.\n", argv[globalUtilOptind] ); + return 0; + } + fclose( pFile ); + pFileName = argv[globalUtilOptind]; + } + pTemp = Gia_ManPerformLNetOptNew( pAbc->pGia, pFileName, nIns, nOuts, Limit, nRounds, fVerbose ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &lnetopt [-IORX num] [-vh] \n" ); + Abc_Print( -2, "\t performs specialized AIG optimization\n" ); + Abc_Print( -2, "\t-I num : the input support size [default = %d]\n", nIns ); + Abc_Print( -2, "\t-O num : the output group size [default = %d]\n", nOuts ); + Abc_Print( -2, "\t-R num : patterns are cares starting this value [default = %d]\n", Limit ); + Abc_Print( -2, "\t-X num : the number of optimization rounds [default = %d]\n", nRounds ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n"); + Abc_Print( -2, "\t : file name with simulation information\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Ttopt( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Gia_Man_t * pTemp; + char * pFileName = NULL; + int c, nIns = 6, nOuts = 2, Limit = 0, nRounds = 20, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IORXvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nIns = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by a positive integer.\n" ); + goto usage; + } + nOuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by a positive integer.\n" ); + goto usage; + } + Limit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'X': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-X\" should be followed by a positive integer.\n" ); + goto usage; + } + nRounds = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + default: + goto usage; + } + } + if ( argc > globalUtilOptind + 1 ) + { + return 0; + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Empty GIA network.\n" ); + return 1; + } + if ( argc == globalUtilOptind + 1 ) + { + FILE * pFile = fopen( argv[globalUtilOptind], "rb" ); + if ( pFile == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9BCore(): Cannot open file \"%s\" for reading the simulation information.\n", argv[globalUtilOptind] ); + return 0; + } + fclose( pFile ); + pFileName = argv[globalUtilOptind]; + } + if ( pFileName ) + pTemp = Gia_ManTtoptCare( pAbc->pGia, nIns, nOuts, nRounds, pFileName, Limit ); + else + pTemp = Gia_ManTtopt( pAbc->pGia, nIns, nOuts, nRounds ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &ttopt [-IORX num] [-vh] \n" ); + Abc_Print( -2, "\t performs specialized AIG optimization\n" ); + Abc_Print( -2, "\t-I num : the input support size [default = %d]\n", nIns ); + Abc_Print( -2, "\t-O num : the output group size [default = %d]\n", nOuts ); + Abc_Print( -2, "\t-R num : patterns are cares starting this value [default = %d]\n", Limit ); + Abc_Print( -2, "\t-X num : the number of optimization rounds [default = %d]\n", nRounds ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n"); + Abc_Print( -2, "\t : file name with simulation information\n"); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t This command was contributed by Yukio Miyasaka.\n" ); + Abc_Print( -2, "\t The paper describing the method: Y. Miyasaka et al. \"Synthesizing\n" ); + Abc_Print( -2, "\t a class of practical Boolean functions using truth tables\". Proc. IWLS 2022.\n" ); + Abc_Print( -2, "\t https://people.eecs.berkeley.edu/~alanmi/publications/2022/iwls22_reo.pdf\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Transduction( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Gia_Man_t * pTemp, * pExdc = NULL; + int c, nType = 1, fMspf = 0, nRandom = 0, nSortType = 0, nPiShuffle = 0, nParameter = 0, fLevel = 0, fTruth = 0, fNewLine = 0, nVerbose = 2; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "TSIPRVtmnlh" ) ) != EOF ) + { + switch ( c ) + { + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer.\n" ); + goto usage; + } + nType = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by a positive integer.\n" ); + goto usage; + } + nRandom = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by a positive integer.\n" ); + goto usage; + } + nSortType = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nPiShuffle = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by a positive integer.\n" ); + goto usage; + } + nParameter = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'V': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-V\" should be followed by a positive integer.\n" ); + goto usage; + } + nVerbose = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 't': + fTruth ^= 1; + break; + case 'm': + fMspf ^= 1; + break; + case 'n': + fNewLine ^= 1; + break; + case 'l': + fLevel ^= 1; + break; + case 'h': + default: + goto usage; + } + } + if ( argc > globalUtilOptind + 1 ) { - Sle_ManExplore( pAbc->pGia, nBTLimit, DelayMax, fDynamic, nEdges==2, fVerbose ); - return 0; + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; } - if ( !Gia_ManHasMapping(pAbc->pGia) ) + if ( pAbc->pGia == NULL ) { - Abc_Print( -1, "Current AIG has no mapping. Run \"&if\".\n" ); + Abc_Print( -1, "Empty GIA network.\n" ); return 1; } - if ( Gia_ManLutSizeMax(pAbc->pGia) > 6 ) - { - Abc_Print( 0, "Current AIG has mapping into %d-LUTs.\n", Gia_ManLutSizeMax(pAbc->pGia) ); - return 0; - } - if ( fUsePack ) + if ( argc == globalUtilOptind + 1 ) { - if ( pAbc->pGia->vPacking == NULL ) + FILE * pFile = fopen( argv[globalUtilOptind], "rb" ); + if ( pFile == NULL ) { - Abc_Print( -1, "Packing information is not present.\n" ); - return 0; + Abc_Print( -1, "Cannot open input file \"%s\". ", argv[globalUtilOptind] ); + return 1; + } + fclose( pFile ); + pExdc = Gia_AigerRead( argv[globalUtilOptind], 0, 0, 0 ); + if ( pExdc == NULL ) + { + Abc_Print( -1, "Reading AIGER has failed.\n" ); + return 1; } - Gia_ManConvertPackingToEdges( pAbc->pGia ); - return 0; - } - if ( !fUseOld ) - { - //Edg_ManAssignEdgeNew( pAbc->pGia, nEdges, fVerbose ); - Seg_ManComputeDelay( pAbc->pGia, DelayMax, nFanouts, nEdges==2, fVerbose ); - return 0; } - if ( pAbc->pGia->pManTime && fReverse ) + + if ( fLevel && (nType == 3 || nType == 8) ) { - Abc_Print( 0, "Reverse computation does not work when boxes are present.\n" ); - return 0; + Abc_Print( -1, "Level preserving optimization does not work with transduction type 3 and 8.\n" ); + return 1; } - if ( fReverse ) - DelayMax = Gia_ManComputeEdgeDelay2( pAbc->pGia ); + + if ( fTruth ) + pTemp = Gia_ManTransductionTt( pAbc->pGia, nType, fMspf, nRandom, nSortType, nPiShuffle, nParameter, fLevel, pExdc, fNewLine, nVerbose ); else - DelayMax = Gia_ManComputeEdgeDelay( pAbc->pGia, nEdges == 2 ); - //printf( "The number of edges = %d. Delay = %d.\n", Gia_ManEvalEdgeCount(pAbc->pGia), DelayMax ); + pTemp = Gia_ManTransductionBdd( pAbc->pGia, nType, fMspf, nRandom, nSortType, nPiShuffle, nParameter, fLevel, pExdc, fNewLine, nVerbose ); + if ( pExdc != NULL ) + Gia_ManStop( pExdc ); + Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &edge [-CDFE num] [-rpomdvh]\n" ); - Abc_Print( -2, "\t find edge assignment of the LUT-mapped network\n" ); - Abc_Print( -2, "\t-C num : the SAT solver conflict limit (0 = unused) [default = %d]\n", nBTLimit ); - Abc_Print( -2, "\t-D num : the upper bound on delay [default = %d]\n", DelayMax ); - Abc_Print( -2, "\t-F num : skip using edge if fanout higher than this [default = %d]\n", nFanouts ); - Abc_Print( -2, "\t-E num : the limit on the number of edges (1 <= num <= 2) [default = %d]\n", nEdges ); - Abc_Print( -2, "\t-r : toggles using reverse order [default = %s]\n", fReverse? "yes": "no" ); - Abc_Print( -2, "\t-p : toggles deriving edges from packing [default = %s]\n", fUsePack? "yes": "no" ); - Abc_Print( -2, "\t-o : toggles using old algorithm [default = %s]\n", fUseOld? "yes": "no" ); - Abc_Print( -2, "\t-m : toggles combining edge assignment with mapping [default = %s]\n", fMapping? "yes": "no" ); - Abc_Print( -2, "\t-d : toggles dynamic addition of clauses [default = %s]\n", fDynamic? "yes": "no" ); - Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); - Abc_Print( -2, "\t-h : prints the command usage\n"); + Abc_Print( -2, "usage: &transduction [-TSIPRV num] [-bmlh] \n" ); + Abc_Print( -2, "\t performs transduction-based AIG optimization\n" ); + Abc_Print( -2, "\t-T num : transduction type [default = %d]\n", nType ); + Abc_Print( -2, "\t 0: remove simply redundant nodes\n" ); + Abc_Print( -2, "\t 1: Resub\n" ); + Abc_Print( -2, "\t 2: ResubMono\n" ); + Abc_Print( -2, "\t 3: ResubShared\n" ); + Abc_Print( -2, "\t 4: repeat Resub\n" ); + Abc_Print( -2, "\t 5: repeat ResubMono\n" ); + Abc_Print( -2, "\t 6: script RepeatInner\n" ); + Abc_Print( -2, "\t 7: script RepeatOuter\n" ); + Abc_Print( -2, "\t 8: script RepeatAll\n" ); + Abc_Print( -2, "\t-S num : fanin sort type [default = %d]\n", nSortType ); + Abc_Print( -2, "\t 0: topological order\n" ); + Abc_Print( -2, "\t 1: number of ones\n" ); + Abc_Print( -2, "\t 2: number of ones before complemented edges\n" ); + Abc_Print( -2, "\t 3: pseudo random\n" ); + Abc_Print( -2, "\t 4: no sorting\n" ); + Abc_Print( -2, "\t-I num : random seed to shuffle PIs (0 = no shuffle) [default = %d]\n", nPiShuffle ); + Abc_Print( -2, "\t-P num : parameters for scripts [default = %d]\n", nParameter ); + Abc_Print( -2, "\t-R num : random seed to set all parameters (0 = no random) ([default = %d]\n", nRandom ); + Abc_Print( -2, "\t-V num : verbosity level [default = %d]\n", nVerbose ); + Abc_Print( -2, "\t-t : toggles using truth table instead of BDD [default = %s]\n", fTruth? "yes": "no" ); + Abc_Print( -2, "\t-m : toggles using MSPF instead of CSPF [default = %s]\n", fMspf? "yes": "no" ); + Abc_Print( -2, "\t-n : toggles printing with a new line [default = %s]\n", fNewLine? "yes": "no" ); + Abc_Print( -2, "\t-l : toggles level preserving optimization [default = %s]\n", fLevel? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n" ); + Abc_Print( -2, "\t : AIGER specifying external don't-cares\n" ); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t This command was contributed by Yukio Miyasaka.\n" ); return 1; } @@ -37941,13 +43005,13 @@ int Abc_CommandAbc9Edge( Abc_Frame_t * pAbc, int argc, char ** argv ) SeeAlso [] ***********************************************************************/ -int Abc_CommandAbc9SatLut( Abc_Frame_t * pAbc, int argc, char ** argv ) +int Abc_CommandAbc9TranStoch( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Gia_ManLutSat( Gia_Man_t * p, int LutSize, int nNumber, int nImproves, int nBTLimit, int DelayMax, int nEdges, int fDelay, int fReverse, int fVerbose, int fVeryVerbose ); - int c, LutSize = 0, nNumber = 32, nImproves = 0, nBTLimit = 100, DelayMax = 0, nEdges = 0; - int fDelay = 0, fReverse = 0, fVeryVerbose = 0, fVerbose = 0; + extern Gia_Man_t * Gia_ManTranStoch( Gia_Man_t * pGia, int nRestarts, int nHops, int nSeedBase, int fMspf, int fMerge, int fResetHop, int fZeroCostHop, int fRefactor, int fTruth, int fSingle, int fOriginalOnly, int fNewLine, Gia_Man_t * pExdc, int nThreads, int nVerbose ); + Gia_Man_t * pTemp, * pExdc = NULL; + int c, nRestarts = 0, nHops = 10, nSeedBase = 0, fMspf = 1, fMerge = 1, fResetHop = 1, fZeroCostHop = 0, fRefactor = 0, fTruth = 0, fSingle = 0, fOriginalOnly = 0, fNewLine = 0, nThreads = 1, nVerbose = 1; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NICDQdrwvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "NMRPVmgrzftsonh" ) ) != EOF ) { switch ( c ) { @@ -37957,58 +43021,179 @@ int Abc_CommandAbc9SatLut( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); goto usage; } - nNumber = atoi(argv[globalUtilOptind]); - if ( nNumber > 128 ) + nRestarts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'M': + if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "The number of AIG nodes should not exceed 128.\n" ); + Abc_Print( -1, "Command line switch \"-M\" should be followed by a positive integer.\n" ); goto usage; } + nHops = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; - case 'I': + case 'R': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + Abc_Print( -1, "Command line switch \"-R\" should be followed by a positive integer.\n" ); goto usage; } - nImproves = atoi(argv[globalUtilOptind]); + nSeedBase = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; - case 'C': + case 'P': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-C\" should be followed by a positive integer.\n" ); + Abc_Print( -1, "Command line switch \"-P\" should be followed by a positive integer.\n" ); goto usage; } - nBTLimit = atoi(argv[globalUtilOptind]); + nThreads = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; - case 'D': + case 'V': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-D\" should be followed by a positive integer.\n" ); + Abc_Print( -1, "Command line switch \"-V\" should be followed by a positive integer.\n" ); goto usage; } - DelayMax = atoi(argv[globalUtilOptind]); + nVerbose = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; - case 'Q': + case 'm': + fMspf ^= 1; + break; + case 'g': + fMerge ^= 1; + break; + case 'r': + fResetHop ^= 1; + break; + case 'z': + fZeroCostHop ^= 1; + break; + case 'f': + fRefactor ^= 1; + break; + case 't': + fTruth ^= 1; + break; + case 's': + fSingle ^= 1; + break; + case 'o': + fOriginalOnly ^= 1; + break; + case 'n': + fNewLine ^= 1; + break; + case 'h': + default: + goto usage; + } + } + if ( argc > globalUtilOptind + 1 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Empty GIA network.\n" ); + return 1; + } + if ( argc == globalUtilOptind + 1 ) + { + FILE * pFile = fopen( argv[globalUtilOptind], "rb" ); + if ( pFile == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", argv[globalUtilOptind] ); + return 1; + } + fclose( pFile ); + pExdc = Gia_AigerRead( argv[globalUtilOptind], 0, 0, 0 ); + if ( pExdc == NULL ) + { + Abc_Print( -1, "Reading AIGER has failed.\n" ); + return 1; + } + } + + pTemp = Gia_ManTranStoch( pAbc->pGia, nRestarts, nHops, nSeedBase, fMspf, fMerge, fResetHop, fZeroCostHop, fRefactor, fTruth, fSingle, fOriginalOnly, fNewLine, pExdc, nThreads, nVerbose ); + if ( pExdc != NULL ) + Gia_ManStop( pExdc ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &transtoch [-NMRPV num] [-mgrzftsonh] \n" ); + Abc_Print( -2, "\t iterates transduction with randomized parameters\n" ); + Abc_Print( -2, "\t-N num : number of restarts [default = %d]\n", nRestarts ); + Abc_Print( -2, "\t-M num : number of hops (if; mfs2; strash) [default = %d]\n", nHops ); + Abc_Print( -2, "\t-R num : random seed [default = %d]\n", nSeedBase ); + Abc_Print( -2, "\t-P num : number of threads [default = %d]\n", nThreads ); + Abc_Print( -2, "\t-V num : verbosity level [default = %d]\n", nVerbose); + Abc_Print( -2, "\t-m : toggles using MSPF instead of CSPF [default = %s]\n", fMspf? "yes": "no" ); + Abc_Print( -2, "\t-g : toggles using ResubShared [default = %s]\n", fMerge? "yes": "no" ); + Abc_Print( -2, "\t-r : toggles resetting hop count when new minimum is found [default = %s]\n", fResetHop? "yes": "no" ); + Abc_Print( -2, "\t-z : toggles using \"drf -z\" instead of \"if;mfs2;st\" for hop [default = %s]\n", fZeroCostHop? "yes": "no" ); + Abc_Print( -2, "\t-f : toggles using \"drf -z\" instead of \"&dc2\" for ite [default = %s]\n", fRefactor? "yes": "no" ); + Abc_Print( -2, "\t-t : toggles using truth table instead of BDD [default = %s]\n", fTruth? "yes": "no" ); + Abc_Print( -2, "\t-s : toggles starting from the smallest starting point [default = %s]\n", fSingle? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles starting from the given AIG [default = %s]\n", fOriginalOnly? "yes": "no" ); + Abc_Print( -2, "\t-n : toggles printing with a new line [default = %s]\n", fNewLine? "yes": "no" ); + Abc_Print( -2, "\t-h : prints the command usage\n" ); + Abc_Print( -2, "\t : AIGER specifying external don't-cares\n" ); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t This command was contributed by Yukio Miyasaka.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9LNetMap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Gia_ManPerformLNetMap( Gia_Man_t * p, int GroupSize, int fUseFixed, int fTryNew, int fVerbose ); + Abc_Ntk_t * pTemp; + char * pFileName = NULL; + int c, fTryNew = 1, nIns = 6, nOuts = 2, fUseFixed = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IOfxvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-Q\" should be followed by a positive integer.\n" ); + Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); goto usage; } - nEdges = atoi(argv[globalUtilOptind]); + nIns = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; - case 'd': - fDelay ^= 1; + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by a positive integer.\n" ); + goto usage; + } + nOuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; break; - case 'r': - fReverse ^= 1; + case 'f': + fUseFixed ^= 1; break; - case 'w': - fVeryVerbose ^= 1; + case 'x': + fTryNew ^= 1; break; case 'v': fVerbose ^= 1; @@ -38018,36 +43203,36 @@ int Abc_CommandAbc9SatLut( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( pAbc->pGia == NULL ) { Abc_Print( -1, "Empty GIA network.\n" ); return 1; } - if ( !Gia_ManHasMapping(pAbc->pGia) ) + if ( argc == globalUtilOptind + 1 ) { - Abc_Print( -1, "Current AIG has no mapping. Run \"&if\".\n" ); - return 1; + FILE * pFile = fopen( argv[globalUtilOptind], "rb" ); + if ( pFile == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9BCore(): Cannot open file \"%s\" for reading the simulation information.\n", argv[globalUtilOptind] ); + return 0; + } + fclose( pFile ); + pFileName = argv[globalUtilOptind]; } - LutSize = Gia_ManLutSizeMax(pAbc->pGia); - if ( LutSize > 6 ) - Abc_Print( 0, "Current AIG is mapped into %d-LUTs (only 6-LUT mapping is currently supported).\n", Gia_ManLutSizeMax(pAbc->pGia) ); - else - Gia_ManLutSat( pAbc->pGia, LutSize, nNumber, nImproves, nBTLimit, DelayMax, nEdges, fDelay, fReverse, fVerbose, fVeryVerbose ); + pTemp = Gia_ManPerformLNetMap( pAbc->pGia, nOuts, fUseFixed, fTryNew, fVerbose ); + Abc_FrameReplaceCurrentNetwork( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &satlut [-NICDQ num] [-drwvh]\n" ); - Abc_Print( -2, "\t performs SAT-based remapping of the LUT-mapped network\n" ); - Abc_Print( -2, "\t-N num : the limit on AIG nodes in the window (num <= 128) [default = %d]\n", nNumber ); - Abc_Print( -2, "\t-I num : the limit on the number of improved windows [default = %d]\n", nImproves ); - Abc_Print( -2, "\t-C num : the limit on the number of conflicts [default = %d]\n", nBTLimit ); - Abc_Print( -2, "\t-D num : the user-specified required times at the outputs [default = %d]\n", DelayMax ); - Abc_Print( -2, "\t-Q num : the maximum number of edges [default = %d]\n", nEdges ); - Abc_Print( -2, "\t-d : toggles delay optimization [default = %s]\n", fDelay? "yes": "no" ); - Abc_Print( -2, "\t-r : toggles using reverse search [default = %s]\n", fReverse? "yes": "no" ); - Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "usage: &lnetmap [-IO num] [-fxvh] \n" ); + Abc_Print( -2, "\t performs specialized LUT mapping\n" ); + Abc_Print( -2, "\t-I num : the input support size [default = %d]\n", nIns ); + Abc_Print( -2, "\t-O num : the output group size [default = %d]\n", nOuts ); + Abc_Print( -2, "\t-f : toggles using fixed primitives [default = %s]\n", fUseFixed? "yes": "no" ); + Abc_Print( -2, "\t-x : toggles using another computation [default = %s]\n", fTryNew? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : prints the command usage\n"); + Abc_Print( -2, "\t : file name with simulation information\n"); return 1; } @@ -38416,13 +43601,14 @@ int Abc_CommandAbc9Era( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern Gia_Man_t * Gia_ManEquivReduce2( Gia_Man_t * p ); Gia_Man_t * pTemp; Dch_Pars_t Pars, * pPars = &Pars; - int c; + int c, fMinLevel = 0, fEquiv = 0; // set defaults Dch_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptfrvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptfremgcxyvh" ) ) != EOF ) { switch ( c ) { @@ -38474,6 +43660,24 @@ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'r': pPars->fSkipRedSupp ^= 1; break; + case 'e': + fEquiv ^= 1; + break; + case 'm': + fMinLevel ^= 1; + break; + case 'g': + pPars->fUseGia ^= 1; + break; + case 'c': + pPars->fUseCSat ^= 1; + break; + case 'x': + pPars->fUseNew ^= 1; + break; + case 'y': + pPars->fUseNew2 ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -38493,12 +43697,27 @@ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Dch(): This command does not work with barrier buffers.\n" ); return 1; } - pTemp = Gia_ManPerformDch( pAbc->pGia, pPars ); + if ( fEquiv ) + { + Aig_Man_t * pNew = Gia_ManToAigSimple( pAbc->pGia ); + assert( Gia_ManObjNum(pAbc->pGia) == Aig_ManObjNum(pNew) ); + Dch_ComputeEquivalences( pNew, (Dch_Pars_t *)pPars ); + Gia_ManReprFromAigRepr( pNew, pAbc->pGia ); + Aig_ManStop( pNew ); + pTemp = Gia_ManEquivReduce( pAbc->pGia, 1, 0, 0, 0 ); + } + else + { + pTemp = Gia_ManPerformDch( pAbc->pGia, pPars ); + Abc_FrameUpdateGia( pAbc, pTemp ); + if ( fMinLevel ) + pTemp = Gia_ManEquivReduce2( pAbc->pGia ); + } Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &dch [-WCS num] [-sptfrvh]\n" ); + Abc_Print( -2, "usage: &dch [-WCS num] [-sptfremgcxyvh]\n" ); Abc_Print( -2, "\t computes structural choices using a new approach\n" ); Abc_Print( -2, "\t-W num : the max number of simulation words [default = %d]\n", pPars->nWords ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); @@ -38508,6 +43727,12 @@ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-t : toggle simulation of the TFO classes [default = %s]\n", pPars->fSimulateTfo? "yes": "no" ); Abc_Print( -2, "\t-f : toggle using lighter logic synthesis [default = %s]\n", pPars->fLightSynth? "yes": "no" ); Abc_Print( -2, "\t-r : toggle skipping choices with redundant support [default = %s]\n", pPars->fSkipRedSupp? "yes": "no" ); + Abc_Print( -2, "\t-e : toggle computing and merging equivalences [default = %s]\n", fEquiv? "yes": "no" ); + Abc_Print( -2, "\t-m : toggle minimizing logic level after merging equivalences [default = %s]\n", fMinLevel? "yes": "no" ); + Abc_Print( -2, "\t-g : toggle using GIA to prove equivalences [default = %s]\n", pPars->fUseGia? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle using circuit-based SAT vs. MiniSat [default = %s]\n", pPars->fUseCSat? "yes": "no" ); + Abc_Print( -2, "\t-x : toggle using new choice computation [default = %s]\n", pPars->fUseNew? "yes": "no" ); + Abc_Print( -2, "\t-y : toggle using new choice computation [default = %s]\n", pPars->fUseNew2? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -38527,13 +43752,15 @@ int Abc_CommandAbc9Dch( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandAbc9Rpm( Abc_Frame_t * pAbc, int argc, char ** argv ) { + extern Gia_Man_t * Gia_ManDupReplaceCut( Gia_Man_t * p ); Gia_Man_t * pTemp; int c, nCutMax = 16; + int fUseNaive = 0; int fUseOldAlgo = 0; int fVerbose = 0; int fVeryVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Cavwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "Cnavwh" ) ) != EOF ) { switch ( c ) { @@ -38548,6 +43775,9 @@ int Abc_CommandAbc9Rpm( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nCutMax < 0 ) goto usage; break; + case 'n': + fUseNaive ^= 1; + break; case 'a': fUseOldAlgo ^= 1; break; @@ -38568,7 +43798,9 @@ int Abc_CommandAbc9Rpm( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Rpm(): There is no AIG.\n" ); return 0; } - if ( fUseOldAlgo ) + if ( fUseNaive ) + pTemp = Gia_ManDupReplaceCut( pAbc->pGia ); + else if ( fUseOldAlgo ) pTemp = Abs_RpmPerformOld( pAbc->pGia, fVerbose ); else pTemp = Abs_RpmPerform( pAbc->pGia, nCutMax, fVerbose, fVeryVerbose ); @@ -38576,9 +43808,10 @@ int Abc_CommandAbc9Rpm( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; usage: - Abc_Print( -2, "usage: &rpm [-C num] [-avwh]\n" ); + Abc_Print( -2, "usage: &rpm [-C num] [-navwh]\n" ); Abc_Print( -2, "\t performs structural reparametrization\n" ); Abc_Print( -2, "\t-C num : max cut size for testing range equivalence [default = %d]\n", nCutMax ); + Abc_Print( -2, "\t-n : toggle using naive reparametrization [default = %s]\n", fUseNaive? "yes": "no" ); Abc_Print( -2, "\t-a : toggle using old algorithm [default = %s]\n", fUseOldAlgo? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing more verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); @@ -38746,6 +43979,73 @@ int Abc_CommandAbc9Posplit( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Permute( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDupRandPerm( Gia_Man_t * p ); + Gia_Man_t * pTemp; + int c, RandSeed = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Svh" ) ) != EOF ) + { + switch ( c ) + { + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + RandSeed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( RandSeed < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Permute(): There is no AIG.\n" ); + return 1; + } + if ( Gia_ManRegNum(pAbc->pGia) > 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9Permute(): This command does not work for sequential AIGs.\n" ); + return 1; + } + Abc_Random(1); + for ( c = 0; c < RandSeed; c++ ) + Abc_Random(0); + pTemp = Gia_ManDupRandPerm( pAbc->pGia ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &permute [-S num] [-vh]\n" ); + Abc_Print( -2, "\t generates a random NPNP transformation of the combinational AIG\n" ); + Abc_Print( -2, "\t-S num : the seed used to randomize the process [default = %d]\n", RandSeed ); + 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; +} + #ifdef ABC_USE_CUDD /**Function************************************************************* @@ -39741,6 +45041,210 @@ int Abc_CommandAbc9IsoSt( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Compare( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_Iso4TestTwo( Gia_Man_t * pGia0, Gia_Man_t * pGia1 ); + extern void Gia_ManComparePrint( Gia_Man_t * p, Gia_Man_t * q ); + Gia_Man_t * pGia0, * pGia1; + char ** pArgvNew; int nArgcNew; + int c, fFunc = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "fvh" ) ) != EOF ) + { + switch ( c ) + { + case 'f': + fFunc ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 2 ) + { + Abc_Print( -1, "Abc_CommandAbc9Compare(): This command expects two AIG file names on the command line.\n" ); + return 1; + } + pGia0 = Gia_AigerRead( pArgvNew[0], 0, 0, 0 ); + pGia1 = Gia_AigerRead( pArgvNew[1], 0, 0, 0 ); + if ( pGia0 == NULL || pGia1 == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Compare(): Reading input files did not work.\n" ); + return 1; + } + if ( fFunc ) + Gia_ManComparePrint( pGia0, pGia1 ); + else + Gia_Iso4TestTwo( pGia0, pGia1 ); + Gia_ManStop( pGia0 ); + Gia_ManStop( pGia1 ); + return 0; + +usage: + Abc_Print( -2, "usage: &compare [-fvh]\n" ); + Abc_Print( -2, "\t compared two AIGs for structural similarity\n" ); + Abc_Print( -2, "\t-f : toggle functional comparison [default = %s]\n", fFunc? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9RevEng( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManCompareSims( Gia_Man_t * pHie, Gia_Man_t * pFlat, int nWords, int fVerbose ); + Gia_Man_t * pGia0, * pGia1; + char ** pArgvNew; int nArgcNew; + int c, nWords = 4, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Wvh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + nWords = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nWords < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9RevEng(): There is no AIG.\n" ); + return 1; + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "Abc_CommandAbc9RevEng(): This command expects one AIG file name on the command line.\n" ); + return 1; + } + pGia0 = pAbc->pGia; + pGia1 = Gia_AigerRead( pArgvNew[0], 0, 0, 0 ); + if ( pGia0 == NULL || pGia1 == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9RevEng(): Reading input files did not work.\n" ); + return 1; + } + Gia_ManCompareSims( pGia0, pGia1, nWords, fVerbose ); + Gia_ManStop( pGia1 ); + return 0; + +usage: + Abc_Print( -2, "usage: &reveng [-W num] [-vh] \n" ); + Abc_Print( -2, "\t compares two AIGs for structural similarity\n" ); + Abc_Print( -2, "\t the current AIG is expected to contain some hierarchy\n" ); + Abc_Print( -2, "\t the given AIG from is expected to be flat\n" ); + Abc_Print( -2, "\t-W num : the number of 64-bit words of simulation info [default = %d]\n", nWords ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9Uif( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDupUif( Gia_Man_t * p ); + extern Gia_Man_t * Gia_ManDupBlackBox( Gia_Man_t * p ); + Gia_Man_t * pNew = NULL, * pTemp = NULL; + int c, fBlackBox = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "bvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fBlackBox ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Uif(): There is no AIG.\n" ); + return 1; + } + if ( pAbc->pGia->vBarBufs == NULL || Vec_IntSize(pAbc->pGia->vBarBufs) == 0 ) + { + Abc_Print( -1, "Abc_CommandAbc9Uif(): Hierarchy is not defined.\n" ); + return 1; + } + pNew = Gia_ManDupUif( pAbc->pGia ); + if ( fBlackBox ) + { + pNew = Gia_ManDupBlackBox( pTemp = pNew ); + Gia_ManStop( pTemp ); + } + Abc_FrameUpdateGia( pAbc, pNew ); + return 0; + +usage: + Abc_Print( -2, "usage: &uif [-bvh]\n" ); + Abc_Print( -2, "\t eagerly adds UIF constraints when hierarchy is present\n" ); + Abc_Print( -2, "\t-b : toggle blackboxing while adding constraints [default = %s]\n", fBlackBox? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -39873,9 +45377,9 @@ int Abc_CommandAbc9Cone( Abc_Frame_t * pAbc, int argc, char ** argv ) { Gia_Man_t * pTemp; Vec_Int_t * vPos; - int c, iOutNum = -1, nOutRange = 1, iPartNum = -1, nLevelMax = 0, nTimeWindow = 0, fUseAllCis = 0, fExtractAll = 0, fVerbose = 0; + int c, nRegs = 0, iOutNum = -1, nOutRange = 1, iPartNum = -1, nLevelMax = 0, nTimeWindow = 0, fUseAllCis = 0, fExtractAll = 0, fComb = 0, fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ORPLWaevh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "ORPLWaecvh" ) ) != EOF ) { switch ( c ) { @@ -39940,6 +45444,9 @@ int Abc_CommandAbc9Cone( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'e': fExtractAll ^= 1; break; + case 'c': + fComb ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -39957,13 +45464,13 @@ int Abc_CommandAbc9Cone( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( fExtractAll ) { char Buffer[1000]; - Gia_Obj_t * pObj; - int i, nDigits = Abc_Base10Log(Gia_ManPoNum(pAbc->pGia)); + Gia_Obj_t * pObj; int i; + unsigned char nDigits = (unsigned char)Abc_Base10Log(Gia_ManPoNum(pAbc->pGia)); Gia_ManForEachPo( pAbc->pGia, pObj, i ) { Gia_Man_t * pOne = Gia_ManDupDfsCone( pAbc->pGia, pObj ); sprintf( Buffer, "%s_%0*d.aig", Extra_FileNameGeneric(pAbc->pGia->pSpec), nDigits, i ); - Gia_AigerWrite( pOne, Buffer, 0, 0 ); + Gia_AigerWrite( pOne, Buffer, 0, 0, 0 ); Gia_ManStop( pOne ); } printf( "Dumped all outputs into individual AIGER files.\n" ); @@ -40003,20 +45510,27 @@ int Abc_CommandAbc9Cone( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_FrameUpdateGia( pAbc, pTemp ); return 0; } + nRegs = Gia_ManRegNum( pAbc->pGia ); + if ( fComb ) + pAbc->pGia->nRegs = 0; if ( iOutNum < 0 || iOutNum + nOutRange > Gia_ManPoNum(pAbc->pGia) ) { Abc_Print( -1, "Abc_CommandAbc9Cone(): Range of outputs to extract is incorrect.\n" ); + if ( fComb ) + Gia_ManSetRegNum( pAbc->pGia, nRegs ); return 1; } vPos = Vec_IntStartRange( iOutNum, nOutRange ); pTemp = Gia_ManDupCones( pAbc->pGia, Vec_IntArray(vPos), nOutRange, !fUseAllCis ); + if ( fComb ) + Gia_ManSetRegNum( pAbc->pGia, nRegs ); Vec_IntFree( vPos ); if ( pTemp ) Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &cone [-ORPLW num] [-aevh]\n" ); + Abc_Print( -2, "usage: &cone [-ORPLW num] [-aecvh]\n" ); Abc_Print( -2, "\t extracting multi-output sequential logic cones\n" ); Abc_Print( -2, "\t-O num : the index of first PO to extract [default = %d]\n", iOutNum ); Abc_Print( -2, "\t-R num : (optional) the number of outputs to extract [default = %d]\n", nOutRange ); @@ -40025,6 +45539,7 @@ int Abc_CommandAbc9Cone( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-W num : (optional) extract cones falling into this window [default = %d]\n", nTimeWindow ); Abc_Print( -2, "\t-a : toggle keeping all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" ); Abc_Print( -2, "\t-e : toggle writing all outputs into individual files [default = %s]\n", fExtractAll? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle performing cone extraction combinationally [default = %s]\n", fComb? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -40459,7 +45974,7 @@ int Abc_CommandAbc9MultiProve( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-L num : approximate local runtime limit in seconds [default = %d]\n", pPars->TimeOutLoc ); Abc_Print( -2, "\t-M num : percentage of local runtime limit increase [default = %d]\n", pPars->TimeOutInc ); Abc_Print( -2, "\t-G num : approximate gap runtime limit in seconds [default = %d]\n", pPars->TimeOutGap ); - Abc_Print( -2, "\t-H num : timeout per output in miliseconds [default = %d]\n", pPars->TimePerOut ); + Abc_Print( -2, "\t-H num : timeout per output in milliseconds [default = %d]\n", pPars->TimePerOut ); Abc_Print( -2, "\t-s : toggle using combinational synthesis [default = %s]\n", pPars->fUseSyn? "yes": "no" ); Abc_Print( -2, "\t-d : toggle dumping invariant into a file [default = %s]\n", pPars->fDumpFinal? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); @@ -40578,6 +46093,163 @@ int Abc_CommandAbc9SplitProve( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9SplitSat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Cnf_SplitSat( char * pFileName, int iVarBeg, int iVarEnd, int nLits, int Value, int TimeOut, int nProcs, int nIters, int Seed, int fPrepro, int fVerbose ); + int c, iVarBeg = 0, iVarEnd = ABC_INFINITY, nLits = 10, Value = 2, TimeOut = 5, nProcs = 1, nIters = 1, Seed = 0, fPrepro = 0, fVerbose = 0; char * pFileName = NULL; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "BENVTPISpvh" ) ) != EOF ) + { + switch ( c ) + { + case 'B': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-B\" should be followed by a positive integer.\n" ); + goto usage; + } + iVarBeg = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iVarBeg < 0 ) + goto usage; + break; + case 'E': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-E\" should be followed by a positive integer.\n" ); + goto usage; + } + iVarEnd = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iVarEnd < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); + goto usage; + } + nLits = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLits < 0 ) + goto usage; + break; + case 'V': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-V\" should be followed by a positive integer.\n" ); + goto usage; + } + Value = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Value < 0 || Value > 2 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by a positive integer.\n" ); + goto usage; + } + TimeOut = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( TimeOut < 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by a positive integer.\n" ); + goto usage; + } + nProcs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nProcs <= 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 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Seed < 0 ) + goto usage; + break; + case 'p': + fPrepro ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + // get the file name + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( -1, "Abc_CommandAbc9SplitSat(): CNF file names should be given on the command line.\n" ); + return 1; + } + { + FILE * pFile; + pFileName = argv[globalUtilOptind]; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + Abc_Print( -1, "Cannot open file \"%s\" with the input test patterns.\n", pFileName ); + return 0; + } + fclose( pFile ); + } + Cnf_SplitSat( pFileName, iVarBeg, iVarEnd, nLits, Value, TimeOut, nProcs, nIters, Seed, fPrepro, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: &splitsat [-BENVTPIS num] [-pvh]\n" ); + Abc_Print( -2, "\t solves CNF-based SAT problem by randomized case-splitting\n" ); + Abc_Print( -2, "\t-B num : the first CNF variable to use for splitting [default = %d]\n", iVarBeg ); + Abc_Print( -2, "\t-E num : the last CNF variable to use for splitting [default = %d]\n", iVarEnd ); + Abc_Print( -2, "\t-N num : the number of CNF variables to use for splitting [default = %d]\n", nLits ); + Abc_Print( -2, "\t-V num : the variable values to use (0, 1, or 2 for \"any\") [default = %d]\n", Value ); + Abc_Print( -2, "\t-T num : the runtime limit in seconds per subproblem [default = %d]\n", TimeOut ); + Abc_Print( -2, "\t-P num : the number of concurrent processes [default = %d]\n", nProcs ); + Abc_Print( -2, "\t-I num : the max number of iterations (0 = infinity) [default = %d]\n", nIters ); + Abc_Print( -2, "\t-S num : the random seed used to generate cofactors [default = %d]\n", Seed ); + Abc_Print( -2, "\t-p : toggle using SatELIte (http://minisat.se/SatELite.html) [default = %s]\n", fPrepro? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + /**Function************************************************************* Synopsis [] @@ -41244,12 +46916,12 @@ int Abc_CommandAbc9FFTest( Abc_Frame_t * pAbc, int argc, char ** argv ) extern void Gia_ParFfSetDefault( Bmc_ParFf_t * p ); extern void Gia_ManFaultTest( Gia_Man_t * p, Gia_Man_t * pG, Bmc_ParFf_t * pPars ); Bmc_ParFf_t Pars, * pPars = &Pars; - char * pFileName = NULL; + char * pFileName = NULL, * pFileName2 = NULL; Gia_Man_t * pGold = NULL; int c; Gia_ParFfSetDefault( pPars ); Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ATNKSGkbsfdeunvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "ATNKSGFkbsfcdeunvh" ) ) != EOF ) { switch ( c ) { @@ -41300,16 +46972,25 @@ int Abc_CommandAbc9FFTest( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'S': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-S\" should be followed by string.\n" ); + Abc_Print( -1, "Command line switch \"-S\" should be followed by a string.\n" ); goto usage; } pPars->pFormStr = argv[globalUtilOptind]; globalUtilOptind++; break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by a file name.\n" ); + goto usage; + } + pFileName2 = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'G': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-G\" should be followed by string.\n" ); + Abc_Print( -1, "Command line switch \"-G\" should be followed by a file name.\n" ); goto usage; } pFileName = argv[globalUtilOptind]; @@ -41327,6 +47008,9 @@ int Abc_CommandAbc9FFTest( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'f': pPars->fFfOnly ^= 1; break; + case 'c': + pPars->fCheckUntest ^= 1; + break; case 'd': pPars->fDump ^= 1; break; @@ -41348,6 +47032,50 @@ int Abc_CommandAbc9FFTest( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } + // read string from file + if ( pFileName2 ) + { + if ( !strcmp( Extra_FileNameExtension(pFileName2), "blif" ) ) + { + extern char * Gia_DeriveFormula( Gia_Man_t * pGia, char ** ppNamesIn ); + Abc_Ntk_t * pNtk2 = Io_Read( pFileName2, Io_ReadFileType(pFileName2), 1, 0 ); + Abc_Ntk_t * pNtk3 = Abc_NtkStrash( pNtk2, 0, 0, 0 ); + Gia_Man_t * pGia = Abc_NtkClpGia( pNtk3 ); + char ** ppNamesIn = Abc_NtkCollectCioNames( pNtk2, 0 ); + if ( Gia_ManCoNum(pGia) == 1 ) + pPars->pFormStr = Gia_DeriveFormula( pGia, ppNamesIn ); + else + printf( "The formula BLIF file contains the network with more one output.\n" ); + ABC_FREE( ppNamesIn ); + Gia_ManStop( pGia ); + Abc_NtkDelete( pNtk2 ); + Abc_NtkDelete( pNtk3 ); + if ( pPars->pFormStr == NULL ) + goto usage; + } + else + { + FILE * pFile = fopen( pFileName2, "r" ); + if ( pFile == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9FFTest(): File name \"%s\" with formula is invalid.\n", pFileName2 ); + return 0; + } + pPars->pFormStr = Extra_FileRead(pFile); + fclose( pFile ); + // skip spaces + while ( 1 ) + { + int Len = strlen(pPars->pFormStr); + char Char = pPars->pFormStr[Len-1]; + if ( Char == ' ' || Char == '\n' || Char == '\r' || Char == '\t' || Char == -51 ) + pPars->pFormStr[Len-1] = '\0'; + else + break; + } + } + printf( "Using formula \"%s\" from file \"%s\".\n", pPars->pFormStr, pFileName2 ); + } if ( pPars->Algo == 0 && pPars->pFormStr == NULL ) { Abc_Print( -1, "Formula string (-S ) should be selected when algorithm is 0 (-A 0).\n" ); @@ -41414,10 +47142,12 @@ int Abc_CommandAbc9FFTest( Abc_Frame_t * pAbc, int argc, char ** argv ) } Gia_ManFaultTest( pAbc->pGia, pGold ? pGold : pAbc->pGia, pPars ); Gia_ManStopP( &pGold ); + if ( pFileName2 ) + ABC_FREE( pPars->pFormStr ); return 0; usage: - Abc_Print( -2, "usage: &fftest [-ATNK num] [-kbsfdeunvh] [-G file] [-S str]\n" ); + Abc_Print( -2, "usage: &fftest [-ATNK num] [-kbsfcdeunvh] [-GF file] [-S str]\n" ); Abc_Print( -2, "\t performs functional fault test generation\n" ); Abc_Print( -2, "\t-A num : selects fault model for all gates [default = %d]\n", pPars->Algo ); Abc_Print( -2, "\t 0: fault model is not selected (use -S str)\n" ); @@ -41432,14 +47162,16 @@ int Abc_CommandAbc9FFTest( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-b : toggles testing for single faults (the same as \"-K 1\") [default = %s]\n", pPars->fBasic? "yes": "no" ); Abc_Print( -2, "\t-s : toggles starting with the all-0 and all-1 patterns [default = %s]\n", pPars->fStartPats? "yes": "no" ); Abc_Print( -2, "\t-f : toggles faults at flop inputs only with \"-A 1\" and \"-S str\" [default = %s]\n", pPars->fFfOnly? "yes": "no" ); - Abc_Print( -2, "\t-d : toggles dumping test patterns into file \"tests.txt\" [default = %s]\n", pPars->fDump? "yes": "no" ); + Abc_Print( -2, "\t-c : toggles checking if there are untestable faults [default = %s]\n", pPars->fCheckUntest? "yes": "no" ); + Abc_Print( -2, "\t-d : toggles dumping test patterns into file \"_tests.txt\" [default = %s]\n", pPars->fDump? "yes": "no" ); Abc_Print( -2, "\t-e : toggles dumping test pattern pairs (delay faults only) [default = %s]\n", pPars->fDumpDelay? "yes": "no" ); - Abc_Print( -2, "\t-u : toggles dumping untestable faults into \"untest.txt\" [default = %s]\n", pPars->fDumpUntest? "yes": "no" ); + Abc_Print( -2, "\t-u : toggles dumping untestable faults into \"_untest.txt\" [default = %s]\n", pPars->fDumpUntest? "yes": "no" ); Abc_Print( -2, "\t-n : toggles dumping faults not detected by a given test set [default = %s]\n", pPars->fDumpNewFaults? "yes": "no" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : (optional) file name with input test patterns\n\n"); Abc_Print( -2, "\t-G file : (optional) file name with the golden model\n\n"); + Abc_Print( -2, "\t-F file : (optional) file name with the fault model in BLIF format\n"); Abc_Print( -2, "\t-S str : (optional) string representing the fault model\n"); Abc_Print( -2, "\t The following notations are used:\n"); Abc_Print( -2, "\t Functional variables: {a,b} (both a and b are always present)\n"); @@ -41456,6 +47188,11 @@ int Abc_CommandAbc9FFTest( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t (((a^p)&(b^q))^r) complement at the inputs and at the output\n"); Abc_Print( -2, "\t (a?(b?~s:r):(b?q:p)) functionally observable fault at the output\n"); Abc_Print( -2, "\t (p?(a|b):(a&b)) replace AND by OR\n"); + Abc_Print( -2, "\t If the BLIF file is used for the formula with option \'-F\', following rules apply:\n"); + Abc_Print( -2, "\t - the network should be combinational and have exactly one primary output\n"); + Abc_Print( -2, "\t - input names should have only one character:\n"); + Abc_Print( -2, "\t {a, b} (for functional variables)\n"); + Abc_Print( -2, "\t {p,q,r,s,t,u,v,w} (for parameter variables)\n"); return 1; } @@ -41473,16 +47210,19 @@ int Abc_CommandAbc9FFTest( Abc_Frame_t * pAbc, int argc, char ** argv ) int Abc_CommandAbc9Qbf( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Gia_QbfDumpFile( Gia_Man_t * pGia, int nPars ); - extern int Gia_QbfSolve( Gia_Man_t * pGia, int nPars, int nIterLimit, int nConfLimit, int nTimeOut, int fGlucose, int fVerbose ); + extern void Gia_QbfDumpFileInv( Gia_Man_t * pGia, int nPars ); + extern int Gia_QbfSolve( Gia_Man_t * pGia, int nPars, int nIterLimit, int nConfLimit, int nTimeOut, int nEncVars, int fGlucose, int fVerbose ); int c, nPars = -1; int nIterLimit = 0; int nConfLimit = 0; int nTimeOut = 0; + int nEncVars = 0; int fDumpCnf = 0; + int fDumpCnf2 = 0; int fGlucose = 0; int fVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PICTdgvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "PICTKdegvh" ) ) != EOF ) { switch ( c ) { @@ -41530,9 +47270,23 @@ int Abc_CommandAbc9Qbf( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nTimeOut < 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; + } + nEncVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nEncVars < 0 ) + goto usage; + break; case 'd': fDumpCnf ^= 1; break; + case 'e': + fDumpCnf2 ^= 1; + break; case 'g': fGlucose ^= 1; break; @@ -41567,18 +47321,22 @@ int Abc_CommandAbc9Qbf( Abc_Frame_t * pAbc, int argc, char ** argv ) } if ( fDumpCnf ) Gia_QbfDumpFile( pAbc->pGia, nPars ); + else if ( fDumpCnf2 ) + Gia_QbfDumpFileInv( pAbc->pGia, nPars ); else - Gia_QbfSolve( pAbc->pGia, nPars, nIterLimit, nConfLimit, nTimeOut, fGlucose, fVerbose ); + Gia_QbfSolve( pAbc->pGia, nPars, nIterLimit, nConfLimit, nTimeOut, nEncVars, fGlucose, fVerbose ); return 0; usage: - Abc_Print( -2, "usage: &qbf [-PICT num] [-dgvh]\n" ); + Abc_Print( -2, "usage: &qbf [-PICTK num] [-degvh]\n" ); Abc_Print( -2, "\t solves QBF problem EpVxM(p,x)\n" ); Abc_Print( -2, "\t-P num : number of parameters p (should be the first PIs) [default = %d]\n", nPars ); Abc_Print( -2, "\t-I num : quit after the given iteration even if unsolved [default = %d]\n", nIterLimit ); Abc_Print( -2, "\t-C num : conflict limit per problem [default = %d]\n", nConfLimit ); Abc_Print( -2, "\t-T num : global timeout [default = %d]\n", nTimeOut ); - Abc_Print( -2, "\t-d : toggle dumping QDIMACS file instead of solving [default = %s]\n", fDumpCnf? "yes": "no" ); + Abc_Print( -2, "\t-K num : the number of input bits (for encoding miters only) [default = %d]\n", nEncVars ); + Abc_Print( -2, "\t-d : toggle dumping QDIMACS file instead of solving (complemented QBF) [default = %s]\n", fDumpCnf? "yes": "no" ); + 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"); @@ -41678,16 +47436,17 @@ int Abc_CommandAbc9QVar( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandAbc9GenQbf( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern Gia_Man_t * Gia_GenQbfMiter( Gia_Man_t * pGia, int nFrames, int nLutNum, int nLutSize, char * pStr, int fVerbose ); + extern Gia_Man_t * Gia_GenQbfMiter( Gia_Man_t * pGia, int nFrames, int nLutNum, int nLutSize, char * pStr, int fUseOut, int fVerbose ); int nFrames = 1; int nLutNum = 1; int nLutSize = 6; char * pStr = NULL; + int fUseOut = 0; int fVerbose = 0; int c; Gia_Man_t * pTemp; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FKNSvh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "FKNSovh" ) ) != EOF ) { switch ( c ) { @@ -41727,7 +47486,7 @@ int Abc_CommandAbc9GenQbf( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'S': if ( globalUtilOptind >= argc ) { - Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + Abc_Print( -1, "Command line switch \"-S\" should be followed by a string.\n" ); goto usage; } pStr = Abc_UtilStrsav(argv[globalUtilOptind]); @@ -41735,6 +47494,9 @@ int Abc_CommandAbc9GenQbf( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( pStr == NULL ) goto usage; break; + case 'o': + fUseOut ^= 1; + break; case 'v': fVerbose ^= 1; break; @@ -41764,17 +47526,87 @@ int Abc_CommandAbc9GenQbf( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Currently this commands works for one frame and one LUT.\n" ); return 1; } - pTemp = Gia_GenQbfMiter( pAbc->pGia, nFrames, nLutNum, nLutSize, pStr, fVerbose ); + pTemp = Gia_GenQbfMiter( pAbc->pGia, nFrames, nLutNum, nLutSize, pStr, fUseOut, fVerbose ); Abc_FrameUpdateGia( pAbc, pTemp ); ABC_FREE( pStr ); return 0; usage: - Abc_Print( -2, "usage: &genqbf [-FKN num] [-vh]\n" ); + Abc_Print( -2, "usage: &genqbf [-FKN num] [-ovh]\n" ); Abc_Print( -2, "\t generates QBF miter for computing an inductive invariant\n" ); Abc_Print( -2, "\t-F num : the number of time frames for induction [default = %d]\n", nFrames ); Abc_Print( -2, "\t-K num : the LUT size [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-N num : the number of LUTs [default = %d]\n", nLutNum ); + Abc_Print( -2, "\t-o : toggle using the last output [default = %s]\n", fUseOut? "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"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9HomoQbf( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_Gen2CreateMiter( int nLutSize, int nLutNum ); + int nLutSize = 2; + int nLutNum = 3; + int fVerbose = 0; + int c; + Gia_Man_t * pTemp; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KNvh" ) ) != 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; + } + nLutNum = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutNum < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + pTemp = Gia_Gen2CreateMiter( nLutSize, nLutNum ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &homoqbf [-KN num] [-vh]\n" ); + Abc_Print( -2, "\t generates QBF miter for the encoding problem\n" ); + Abc_Print( -2, "\t-K num : the LUT size [default = %d]\n", nLutSize ); + Abc_Print( -2, "\t-N num : the number of LUTs [default = %d]\n", nLutNum ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; @@ -41926,6 +47758,7 @@ int Abc_CommandAbc9SatClp( Abc_Frame_t * pAbc, int argc, char ** argv ) return 0; } vSop = Bmc_CollapseOne( pAbc->pGia, nCubeLim, nBTLimit, fCanon, 0, fVerbose ); + printf( "%s\n", Vec_StrArray(vSop) ); Vec_StrFree( vSop ); return 0; @@ -42350,8 +48183,8 @@ int Abc_CommandAbc9Demiter( Abc_Frame_t * pAbc, int argc, char ** argv ) sprintf( pName1, "%s_2.aig", pGen ); ABC_FREE( pGen ); } - Gia_AigerWrite( pPart1, pName0, 0, 0 ); - Gia_AigerWrite( pPart2, pName1, 0, 0 ); + Gia_AigerWrite( pPart1, pName0, 0, 0, 0 ); + Gia_AigerWrite( pPart2, pName1, 0, 0, 0 ); Gia_ManStop( pPart1 ); Gia_ManStop( pPart2 ); if ( fDumpFilesTwo ) @@ -42599,11 +48432,11 @@ int Abc_CommandAbc9ATree( Abc_Frame_t * pAbc, int argc, char ** argv ) ***********************************************************************/ int Abc_CommandAbc9Polyn( Abc_Frame_t * pAbc, int argc, char ** argv ) { - extern void Gia_PolynBuild2Test( Gia_Man_t * pGia, int nExtra, int fSigned, int fVerbose, int fVeryVerbose ); - Vec_Int_t * vOrder = NULL; - int c, nExtra = -1, fOld = 0, fSimple = 1, fSigned = 0, fVerbose = 0, fVeryVerbose = 0; + extern void Gia_PolynBuild2Test( Gia_Man_t * pGia, char * pSign, int nExtra, int fSigned, int fVerbose, int fVeryVerbose ); + Vec_Int_t * vOrder = NULL; char * pSign = NULL; + int c, nExtra = 0, fOld = 0, fSimple = 1, fSigned = 0, fVerbose = 0, fVeryVerbose = 0; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Noasvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "NSoasvwh" ) ) != EOF ) { switch ( c ) { @@ -42618,6 +48451,15 @@ int Abc_CommandAbc9Polyn( Abc_Frame_t * pAbc, int argc, char ** argv ) if ( nExtra < 0 ) goto usage; break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by a char string without spaces.\n" ); + goto usage; + } + pSign = argv[globalUtilOptind]; + globalUtilOptind++; + break; case 'o': fOld ^= 1; break; @@ -42644,6 +48486,11 @@ int Abc_CommandAbc9Polyn( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Esop(): There is no AIG.\n" ); return 0; } + if ( argc >= globalUtilOptind + 1 ) + { + printf( "Trailing symbols on the command line (\"%s\").\n", argv[globalUtilOptind] ); + return 0; + } if ( fOld ) { vOrder = fSimple ? NULL : Gia_PolynReorder( pAbc->pGia, fVerbose, fVeryVerbose ); @@ -42651,11 +48498,11 @@ int Abc_CommandAbc9Polyn( Abc_Frame_t * pAbc, int argc, char ** argv ) Vec_IntFreeP( &vOrder ); } else - Gia_PolynBuild2Test( pAbc->pGia, nExtra, fSigned, fVerbose, fVeryVerbose ); + Gia_PolynBuild2Test( pAbc->pGia, pSign, nExtra, fSigned, fVerbose, fVeryVerbose ); return 0; usage: - Abc_Print( -2, "usage: &polyn [-N num] [-oasvwh]\n" ); + Abc_Print( -2, "usage: &polyn [-N num] [-oasvwh] [-S str]\n" ); Abc_Print( -2, "\t derives algebraic polynomial from AIG\n" ); Abc_Print( -2, "\t-N num : the number of additional primary outputs (-1 = unused) [default = %d]\n", nExtra ); Abc_Print( -2, "\t-o : toggles old computation [default = %s]\n", fOld? "yes": "no" ); @@ -42664,6 +48511,18 @@ int Abc_CommandAbc9Polyn( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggles printing very verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t\n"); + Abc_Print( -2, "\t-S str : (optional) the output signature as a character string\n" ); + Abc_Print( -2, "\t The format used to represent the output signature is very restrictive.\n" ); + Abc_Print( -2, "\t It should be a string without spaces containing monomials in terms of\n" ); + Abc_Print( -2, "\t inputs (i) and outputs (o) where is 0-based. Coefficients\n" ); + Abc_Print( -2, "\t are degrees of two, represented by log2 of their value: for example, \n" ); + Abc_Print( -2, "\t \"2\" is 2^2 = 4, \"-4\" is -2^4=-16, \"-0\" is -2^0=-1, etc\n" ); + Abc_Print( -2, "\t Two types of signature are accepted:\n" ); + Abc_Print( -2, "\t (1) a sequence of monomials without parentheses (for example, \"-2*o0+1*o1+0*o2\")\n" ); + Abc_Print( -2, "\t (2) a product of two sequences followed by a sum with a sequence\n" ); + Abc_Print( -2, "\t (for example, \"(4*o0+2*o1+1*o2)*(4*i3+2*i4+1*i5)+(4*o3+2*o4+1*o5)\")\n" ); + Abc_Print( -2, "\t Here is the signature of a signed 2-bit multiplier: \"(0*o0+1*o1+2*o2-3*o3)\"\n" ); return 1; } @@ -43043,10 +48902,16 @@ int Abc_CommandAbc9Esop( Abc_Frame_t * pAbc, int argc, char ** argv ) int Abc_CommandAbc9Exorcism( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_ExorcismMain( Vec_Wec_t * vEsop, int nIns, int nOuts, char * pFileNameOut, int Quality, int Verbosity, int nCubesMax, int fUseQCost ); + extern Vec_Wec_t * Abc_ExorcismNtk2Esop( Abc_Ntk_t * pNtk ); + extern Gia_Man_t * Eso_ManCompute( Gia_Man_t * pGia, int fVerbose, Vec_Wec_t ** pvRes ); Vec_Wec_t * vEsop = NULL; + Abc_Ntk_t * pNtk = NULL; + char * pFileNameIn = NULL; char * pFileNameOut = NULL; int c, Quality = 2, Verbosity = 0, nCubesMax = 20000, fUseQCost = 0, fVerbose = 0; + int nInputs = -1, nOutputs = -1; + Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "QVCqvh" ) ) != EOF ) { @@ -43097,30 +48962,72 @@ int Abc_CommandAbc9Exorcism( Abc_Frame_t * pAbc, int argc, char ** argv ) goto usage; } } - if ( pAbc->pGia == NULL ) + + if ( argc == globalUtilOptind + 2 ) { - Abc_Print( -1, "Abc_CommandAbc9Exorcism(): There is no AIG.\n" ); - return 0; + pFileNameIn = argv[globalUtilOptind]; + pFileNameOut = argv[globalUtilOptind + 1]; } - // get the output file name - if ( argc == globalUtilOptind + 1 ) + else if ( argc == globalUtilOptind + 1 ) + { pFileNameOut = argv[globalUtilOptind]; - // generate starting cover and run minimization - Eso_ManCompute( pAbc->pGia, fVerbose, &vEsop ); - Abc_ExorcismMain( vEsop, Gia_ManCiNum(pAbc->pGia), Gia_ManCoNum(pAbc->pGia), pFileNameOut, Quality, Verbosity, nCubesMax, fUseQCost ); - Vec_WecFree( vEsop ); - return 0; - -usage: - Abc_Print( -2, "usage: &exorcism [-Q N] [-V N] [-C N] -q \n" ); - Abc_Print( -2, " performs heuristic exclusive sum-of-project minimization\n" ); - Abc_Print( -2, " -Q N : minimization quality [default = %d]\n", Quality); - Abc_Print( -2, " increasing this number improves quality and adds to runtime\n"); - Abc_Print( -2, " -V N : verbosity level [default = %d]\n", Verbosity); - Abc_Print( -2, " 0 = no output; 1 = outline; 2 = verbose\n"); - Abc_Print( -2, " -C N : maximum number of cubes in startign cover [default = %d]\n", nCubesMax ); - Abc_Print( -2, " -q : toggle using quantum cost [default = %s]\n", fUseQCost? "yes": "no" ); - Abc_Print( -2, " : the output file name in ESOP-PLA format\n"); + } + else + { + Abc_Print( -1, "Abc_CommandAbc9Exorcism(): Argument error.\n" ); + goto usage; + } + + if ( pAbc->pGia == NULL && pFileNameIn == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9Exorcism(): There is neither an AIG nor an ESOP-PLA file.\n" ); + return 0; + } + + if ( pFileNameIn ) + { + pNtk = Io_ReadPla( pFileNameIn, 0, 0, 0, /* no preprocessing = */1, /* check = */1 ); + if ( pNtk == NULL ) + { + printf( "Reading PLA file has failed.\n" ); + return 1; + } + nInputs = Abc_NtkCiNum( pNtk ); + nOutputs = Abc_NtkCoNum( pNtk ); + vEsop = Abc_ExorcismNtk2Esop( pNtk ); + if ( vEsop == NULL ) + { + printf( "Converting PLA to ESOP failed.\n" ); + return 1; + } + } + else if ( pAbc->pGia ) + { + // generate starting cover + nInputs = Gia_ManCiNum( pAbc->pGia ); + nOutputs = Gia_ManCoNum( pAbc->pGia ); + Eso_ManCompute( pAbc->pGia, fVerbose, &vEsop ); + } + + if ( vEsop ) + { + // run minimization + Abc_ExorcismMain( vEsop, nInputs, nOutputs, pFileNameOut, Quality, Verbosity, nCubesMax, fUseQCost ); + Vec_WecFree( vEsop ); + } + return 0; + +usage: + Abc_Print( -2, "usage: &exorcism [-Q N] [-V N] [-C N] -q [file_in] \n" ); + Abc_Print( -2, " performs heuristic exclusive sum-of-project minimization\n" ); + Abc_Print( -2, " -Q N : minimization quality [default = %d]\n", Quality); + Abc_Print( -2, " increasing this number improves quality and adds to runtime\n"); + Abc_Print( -2, " -V N : verbosity level [default = %d]\n", Verbosity); + Abc_Print( -2, " 0 = no output; 1 = outline; 2 = verbose\n"); + Abc_Print( -2, " -C N : maximum number of cubes in startign cover [default = %d]\n", nCubesMax ); + Abc_Print( -2, " -q : toggle using quantum cost [default = %s]\n", fUseQCost? "yes": "no" ); + Abc_Print( -2, " [file_in] : optional input file in ESOP-PLA format (otherwise current AIG is used)\n"); + Abc_Print( -2, " : output file in ESOP-PLA format\n"); Abc_Print( -2, "\n" ); return 1; } @@ -43146,7 +49053,7 @@ int Abc_CommandAbc9Mfs( Abc_Frame_t * pAbc, int argc, char ** argv ) pPars->nDepthMax = 100; pPars->nWinSizeMax = 2000; Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCNdaebvwh" ) ) != EOF ) + while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCNdaeblvwh" ) ) != EOF ) { switch ( c ) { @@ -43239,6 +49146,9 @@ int Abc_CommandAbc9Mfs( Abc_Frame_t * pAbc, int argc, char ** argv ) case 'b': pPars->fAllBoxes ^= 1; break; + case 'l': + pPars->fUseDcs ^= 1; + break; case 'v': pPars->fVerbose ^= 1; break; @@ -43266,12 +49176,33 @@ int Abc_CommandAbc9Mfs( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -1, "Abc_CommandAbc9Mfs(): The current AIG has no mapping.\n" ); return 0; } - pTemp = Gia_ManPerformMfs( pAbc->pGia, pPars ); + if ( Gia_ManLutSizeMax(pAbc->pGia) > 15 ) + { + Abc_Print( -1, "Abc_CommandAbc9Mfs(): The current mapping has nodes with more than 15 inputs. Cannot use \"mfs\".\n" ); + return 0; + } +/* + if ( pAbc->pGia->pAigExtra && Gia_ManPiNum(pAbc->pGia->pAigExtra) > 6 ) + { + Abc_Print( -1, "Abc_CommandAbc9Mfs(): The current white-boxes have more than 6 inputs. Cannot use \"mfs\".\n" ); + return 0; + } +*/ + if ( Gia_ManRegNum(pAbc->pGia) == 0 ) + pTemp = Gia_ManPerformMfs( pAbc->pGia, pPars ); + else + { + int nRegs = Gia_ManRegNum(pAbc->pGia); + pAbc->pGia->nRegs = 0; + pTemp = Gia_ManPerformMfs( pAbc->pGia, pPars ); + Gia_ManSetRegNum( pAbc->pGia, nRegs ); + Gia_ManSetRegNum( pTemp, nRegs ); + } Abc_FrameUpdateGia( pAbc, pTemp ); return 0; usage: - Abc_Print( -2, "usage: &mfs [-WFDMLCN ] [-daebvwh]\n" ); + Abc_Print( -2, "usage: &mfs [-WFDMLCN ] [-daeblvwh]\n" ); Abc_Print( -2, "\t performs don't-care-based optimization of logic networks\n" ); Abc_Print( -2, "\t-W : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nTfoLevMax ); Abc_Print( -2, "\t-F : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutMax ); @@ -43283,7 +49214,8 @@ int Abc_CommandAbc9Mfs( Abc_Frame_t * pAbc, int argc, char ** argv ) Abc_Print( -2, "\t-d : toggle performing redundancy removal [default = %s]\n", pPars->fRrOnly? "yes": "no" ); Abc_Print( -2, "\t-a : toggle minimizing area or area+edges [default = %s]\n", pPars->fArea? "area": "area+edges" ); Abc_Print( -2, "\t-e : toggle high-effort resubstitution [default = %s]\n", pPars->fMoreEffort? "yes": "no" ); - Abc_Print( -2, "\t-b : toggle preserving all while boxes [default = %s]\n", pPars->fAllBoxes? "yes": "no" ); + Abc_Print( -2, "\t-b : toggle preserving all white boxes [default = %s]\n", pPars->fAllBoxes? "yes": "no" ); + Abc_Print( -2, "\t-l : toggle deriving don't-cares [default = %s]\n", pPars->fUseDcs? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); @@ -43461,6 +49393,319 @@ int Abc_CommandAbc9Mfsd( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9DeepSyn( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManDeepSyn( Gia_Man_t * pGia, int nIters, int nNoImpr, int TimeOut, int nAnds, int Seed, int fUseTwo, int fVerbose ); + Gia_Man_t * pTemp; int c, nIters = 1, nNoImpr = ABC_INFINITY, TimeOut = 0, nAnds = 0, Seed = 0, fUseTwo = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IJTAStvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'J': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-J\" should be followed by an integer.\n" ); + goto usage; + } + nNoImpr = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNoImpr < 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + TimeOut = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( TimeOut < 0 ) + goto usage; + break; + case 'A': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" ); + goto usage; + } + nAnds = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nAnds < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Seed < 0 ) + goto usage; + break; + case 't': + fUseTwo ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9DeepSyn(): There is no AIG.\n" ); + return 0; + } + pTemp = Gia_ManDeepSyn( pAbc->pGia, nIters, nNoImpr, TimeOut, nAnds, Seed, fUseTwo, fVerbose ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &deepsyn [-IJTAS ] [-tvh]\n" ); + Abc_Print( -2, "\t performs synthesis\n" ); + Abc_Print( -2, "\t-I : the number of iterations [default = %d]\n", nIters ); + Abc_Print( -2, "\t-J : the number of steps without improvements [default = %d]\n", nNoImpr ); + Abc_Print( -2, "\t-T : the timeout in seconds (0 = no timeout) [default = %d]\n", TimeOut ); + Abc_Print( -2, "\t-A : the number of nodes to stop (0 = no limit) [default = %d]\n", nAnds ); + Abc_Print( -2, "\t-S : user-specified random seed (0 <= num <= 100) [default = %d]\n", Seed ); + Abc_Print( -2, "\t-t : toggle using two-input LUTs [default = %s]\n", fUseTwo? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9SatSyn( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManSyn( Gia_Man_t * p, int nNodes, int nOuts, int TimeOut, int fUseXor, int fFancy, int fVerbose ); + Gia_Man_t * pTemp; int c, nNodes = 0, nOuts = 0, TimeOut = 0, fUseXor = 0, fFancy = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NTafvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNodes = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodes < 0 ) + goto usage; + break; + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); + goto usage; + } + nOuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nOuts < 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + TimeOut = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( TimeOut < 0 ) + goto usage; + break; + case 'a': + fUseXor ^= 1; + break; + case 'f': + fFancy ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9SatSyn(): There is no AIG.\n" ); + return 0; + } + pTemp = Gia_ManSyn( pAbc->pGia, nNodes, nOuts, TimeOut, fUseXor, fFancy, fVerbose ); + Abc_FrameUpdateGia( pAbc, pTemp ); + return 0; + +usage: + Abc_Print( -2, "usage: &satsyn [-NOT ] [-afvh]\n" ); + Abc_Print( -2, "\t performs synthesis\n" ); + Abc_Print( -2, "\t-N : the number of window nodes [default = %d]\n", nNodes ); + Abc_Print( -2, "\t-O : the number of window outputs [default = %d]\n", nOuts ); + Abc_Print( -2, "\t-T : the timeout in seconds (0 = no timeout) [default = %d]\n", TimeOut ); + Abc_Print( -2, "\t-a : toggle using xor-nodes [default = %s]\n", fUseXor? "yes": "no" ); + Abc_Print( -2, "\t-f : toggle using additional feature [default = %s]\n", fFancy? "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; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAbc9StochSyn( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_ManStochSyn( int nMaxSize, int nIters, int TimeOut, int Seed, int fVerbose, char * pScript, int nProcs ); + int c, nMaxSize = 1000, nIters = 10, TimeOut = 0, Seed = 0, nProcs = 1, fVerbose = 0; char * pScript; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NITSPvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nMaxSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMaxSize < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + TimeOut = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( TimeOut < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Seed < 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nProcs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nProcs < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "Abc_CommandAbc9StochSyn(): There is no AIG.\n" ); + return 0; + } + if ( argc != globalUtilOptind + 1 ) + { + printf( "Expecting a synthesis script in quotes on the command line (for example: \"&st; &dch; &if\").\n" ); + goto usage; + } + pScript = Abc_UtilStrsav( argv[globalUtilOptind] ); + Gia_ManStochSyn( nMaxSize, nIters, TimeOut, Seed, fVerbose, pScript, nProcs ); + ABC_FREE( pScript ); + return 0; + +usage: + Abc_Print( -2, "usage: &stochsyn [-NITSP ] [-tvh]