abc-0.52/000077500000000000000000000000001477524141600122005ustar00rootroot00000000000000abc-0.52/.gitcommit000066400000000000000000000000511477524141600141710ustar00rootroot00000000000000e55d316cc9a7f72a84a76eda555aa6ec083c9d0d abc-0.52/.github/000077500000000000000000000000001477524141600135405ustar00rootroot00000000000000abc-0.52/.github/workflows/000077500000000000000000000000001477524141600155755ustar00rootroot00000000000000abc-0.52/.github/workflows/build-posix-cmake.yml000066400000000000000000000032151477524141600216360ustar00rootroot00000000000000name: Build Posix CMake on: push: pull_request: jobs: build-posix-cmake: strategy: matrix: os: [macos-latest, ubuntu-latest] use_namespace: [false, true] runs-on: ${{ matrix.os }} env: CMAKE_ARGS: ${{ matrix.use_namespace && '-DABC_USE_NAMESPACE=xxx' || '' }} DEMO_ARGS: ${{ matrix.use_namespace && '-DABC_NAMESPACE=xxx' || '' }} DEMO_GCC: ${{ matrix.use_namespace && 'g++ -x c++' || 'gcc' }} steps: - name: Git Checkout uses: actions/checkout@v4 with: submodules: recursive - name: Install brew dependencies run: | HOMEBREW_NO_AUTO_UPDATE=1 brew install readline ninja if: ${{ contains(matrix.os, 'macos') }} - name: Install APT dependencies run: | sudo apt install -y libreadline-dev ninja-build if: ${{ !contains(matrix.os, 'macos') }} - name: Configure CMake run: | cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ${CMAKE_ARGS} -B build - name: Build CMake run: | cmake --build build - name: Test Executable run: | ./build/abc -c "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec" - name: Test Library run: | ${DEMO_GCC} ${DEMO_ARGS} -Wall -c src/demo.c -o demo.o g++ -o demo demo.o build/libabc.a -lm -ldl -lreadline -lpthread ./demo i10.aig - name: Stage Executable run: | mkdir staging cp build/abc build/libabc.a staging/ - name: Upload pacakge artifact uses: actions/upload-artifact@v4 with: name: package-cmake-${{ matrix.os }}-${{ matrix.use_namespace }} path: staging/ abc-0.52/.github/workflows/build-posix.yml000066400000000000000000000030731477524141600205620ustar00rootroot00000000000000name: Build Posix on: push: pull_request: jobs: build-posix: strategy: matrix: os: [macos-latest, ubuntu-latest] use_namespace: [false, true] runs-on: ${{ matrix.os }} env: MAKE_ARGS: ${{ matrix.use_namespace && 'ABC_USE_NAMESPACE=xxx' || '' }} DEMO_ARGS: ${{ matrix.use_namespace && '-DABC_NAMESPACE=xxx' || '' }} DEMO_GCC: ${{ matrix.use_namespace && 'g++ -x c++' || 'gcc' }} steps: - name: Git Checkout uses: actions/checkout@v4 with: submodules: recursive - name: Install brew dependencies run: | HOMEBREW_NO_AUTO_UPDATE=1 brew install readline if: ${{ contains(matrix.os, 'macos') }} - name: Install APT dependencies run: | sudo apt install -y libreadline-dev if: ${{ !contains(matrix.os, 'macos') }} - name: Build Executable run: | make -j3 ${MAKE_ARGS} abc - name: Test Executable run: | ./abc -c "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec" - name: Build Library run: | make -j3 ${MAKE_ARGS} libabc.a - name: Test Library run: | ${DEMO_GCC} ${DEMO_ARGS} -Wall -c src/demo.c -o demo.o g++ -o demo demo.o libabc.a -lm -ldl -lreadline -lpthread ./demo i10.aig - name: Stage Executable run: | mkdir staging cp abc libabc.a staging/ - name: Upload pacakge artifact uses: actions/upload-artifact@v4 with: name: package-posix-${{ matrix.os }}-${{ matrix.use_namespace }} path: staging/ abc-0.52/.github/workflows/build-windows.yml000066400000000000000000000025701477524141600211130ustar00rootroot00000000000000name: Build Windows on: push: pull_request: jobs: build-windows: runs-on: windows-2019 steps: - name: Git Checkout uses: actions/checkout@v4 with: submodules: recursive - name: Process project files to compile on Github Actions run: | sed -i 's#ABC_USE_PTHREADS\"#ABC_DONT_USE_PTHREADS\" /D \"_ALLOW_KEYWORD_MACROS=1\"#g' *.dsp awk 'BEGIN { del=0; } /# Begin Group "uap"/ { del=1; } /# End Group/ { if( del > 0 ) {del=0; next;} } del==0 {print;} ' abclib.dsp > tmp.dsp copy tmp.dsp abclib.dsp del tmp.dsp unix2dos *.dsp - name: Prepare MSVC uses: bus1/cabuild/action/msdevshell@v1 with: architecture: x86 - name: Upgrade project files to latest Visual Studio, ignoring upgrade errors, and build run: | devenv abcspace.dsw /upgrade ; if (-not $? ) { cat UpgradeLog.htm } msbuild abcspace.sln /m /nologo /p:Configuration=Release /p:PlatformTarget=x86 - name: Test Executable run: | _TEST\abc.exe -c "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec" - name: Stage Executable run: | mkdir staging copy _TEST/abc.exe staging/ copy UpgradeLog.htm staging/ - name: Upload pacakge artifact uses: actions/upload-artifact@v4 with: name: package-windows path: staging/ abc-0.52/.gitignore000066400000000000000000000007711477524141600141750ustar00rootroot00000000000000DebugLib/ DebugExe/ DebugExt/ ReleaseLib/ ReleaseExe/ ReleaseExt/ _/ _TEST/ lib/abc* lib/m114* lib/bip* docs/ .vscode/ .cache/ src/ext* src/xxx/ src/aig/au/ src/aig/ssm/ src/aig/ddb/ *~ *.orig *.[od] *.ncb *.opt *.plg *.zip *.DS_Store abcspaceext.dsw abcext.dsp abcexe.vcproj* abclib.vcproj* abcspace.sln abcspace.suo *.pyc src/python/build src/python/bdist src/python/pyabc.py src/python/pyabc_wrap.* .idea/ build/ *.rej *.orig tags /libabc.a /abc /arch_flags /cmake /cscope abc.history abc-0.52/.hgignore000066400000000000000000000007561477524141600140130ustar00rootroot00000000000000syntax:glob DebugLib/ DebugExe/ DebugExt/ ReleaseLib/ ReleaseExe/ ReleaseExt/ _TEST/ lib/abc* lib/m114* lib/bip* docs/ src/ext* src/xxx/ src/aig/au/ src/aig/ssm/ src/aig/ddb/ *~ *.orig *.[od] *.ncb *.opt *.plg *.zip abcspaceext.dsw abcext.dsp abcexe.vcproj* abclib.vcproj* abcspace.sln abcspace.suo *.pyc src/python/build src/python/bdist src/python/pyabc.py src/python/pyabc_wrap.* .idea/ build/ *.rej *.orig tags syntax: regexp ^libabc.a$ ^abc$ ^arch_flags$ ^cmake ^cscope abc-0.52/CMakeLists.txt000066400000000000000000000101321477524141600147350ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.5.0) include(CMakeParseArguments) include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) # Generate compilation database compile_commands.json set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Default c++ standard used unless otherwise specified in target_compile_features. set(CMAKE_CXX_STANDARD 17 CACHE STRING "the C++ standard to use for this project") set(CMAKE_CXX_STANDARD_REQUIRED ON) function(addprefix var prefix) foreach( s ${ARGN} ) list(APPEND tmp "-I${s}") endforeach() set(${var} ${tmp} PARENT_SCOPE) endfunction() # filter out flags that are not appropriate for the compiler being used function(target_compile_options_filtered target visibility) foreach( flag ${ARGN} ) if( flag MATCHES "^-D.*" ) target_compile_options( ${target} ${visibility} ${flag} ) else() check_c_compiler_flag( ${flag} C_COMPILER_SUPPORTS__${flag} ) if( C_COMPILER_SUPPORTS__${flag} ) target_compile_options( ${target} ${visibility} $<$:${flag}> ) endif() check_cxx_compiler_flag( ${flag} CXX_COMPILER_SUPPORTS__${flag} ) if( CXX_COMPILER_SUPPORTS__${flag} ) target_compile_options( ${target} ${visibility} $<$:${flag}> ) endif() endif() endforeach() endfunction() project(abc) if(READLINE_FOUND MATCHES TRUE) addprefix(ABC_READLINE_INCLUDES_FLAGS "-I" ${READLINE_INCLUDE}) string(REPLACE ";" " " ABC_READLINE_INCLUDES_FLAGS "${ABC_READLINE_INCLUDES_FLAGS}") list(APPEND ABC_READLINE_FLAGS "ABC_READLINE_INCLUDES=${ABC_READLINE_INCLUDES_FLAGS}") string(REPLACE ";" " " ABC_READLINE_LIBRARIES_FLAGS "${READLINE_LIBRARIES}") list(APPEND ABC_READLINE_FLAGS "ABC_READLINE_LIBRARIES=${ABC_READLINE_LIBRARIES_FLAGS}") elseif(READLINE_FOUND MATCHES FALSE) list(APPEND ABC_READLINE_FLAGS "ABC_USE_NO_READLINE=1") endif() 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} ARCHFLAGS_EXE=${CMAKE_CURRENT_BINARY_DIR}/abc_arch_flags_program.exe ABC_MAKE_NO_DEPS=1 CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_CXX_COMPILER} cmake_info WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE MAKE_OUTPUT ) # extract options from make output function(extract_var SEPARATOR DEST_VARIABLE MAKE_OUTPUT) string(REGEX MATCH "${SEPARATOR} .* ${SEPARATOR}" TMP "${MAKE_OUTPUT}") string(REGEX REPLACE "${SEPARATOR} (.*) ${SEPARATOR}" "\\1" TMP "${TMP}") separate_arguments(TMP) set(${DEST_VARIABLE} ${TMP} PARENT_SCOPE) endfunction() extract_var(SEPARATOR_SRC ABC_SRC ${MAKE_OUTPUT}) extract_var(SEPARATOR_LIBS ABC_LIBS ${MAKE_OUTPUT}) extract_var(SEPARATOR_CFLAGS ABC_CFLAGS ${MAKE_OUTPUT}) extract_var(SEPARATOR_CXXFLAGS ABC_CXXFLAGS ${MAKE_OUTPUT}) if(ABC_USE_NAMESPACE) set_source_files_properties(${ABC_SRC} PROPERTIES LANGUAGE CXX) endif() function(abc_properties target visibility) target_include_directories(${target} ${visibility} ${CMAKE_CURRENT_SOURCE_DIR}/src ) target_compile_options_filtered(${target} ${visibility} ${ABC_CFLAGS} ${ABC_CXXFLAGS} -Wno-unused-but-set-variable ) target_link_libraries(${target} ${visibility} ${ABC_LIBS}) endfunction() set(ABC_MAIN_SRC src/base/main/main.c) list(REMOVE_ITEM ABC_SRC ${ABC_MAIN_SRC}) add_library(libabc EXCLUDE_FROM_ALL ${ABC_SRC}) abc_properties(libabc PUBLIC) set_property(TARGET libabc PROPERTY OUTPUT_NAME abc) add_executable(abc ${ABC_MAIN_SRC}) target_link_libraries(abc PRIVATE libabc) abc_properties(abc PRIVATE) add_library(libabc-pic EXCLUDE_FROM_ALL ${ABC_SRC}) abc_properties(libabc-pic PUBLIC) set_property(TARGET libabc-pic PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET libabc-pic PROPERTY OUTPUT_NAME abc-pic) abc-0.52/Makefile000066400000000000000000000157101477524141600136440ustar00rootroot00000000000000 CC := gcc CXX := g++ AR := ar LD := $(CXX) MSG_PREFIX ?= ABCSRC ?= . VPATH = $(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 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/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/if/acd \ 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 \ src/misc/vec src/misc/hash src/misc/tim src/misc/bzlib src/misc/zlib \ src/misc/mem src/misc/bar src/misc/bbl src/misc/parse \ 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/rar \ src/opt/cgt src/opt/csw src/opt/dar src/opt/dau src/opt/dsc src/opt/sfm src/opt/sbd src/opt/eslim \ 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/sat/kissat src/sat/cadical \ 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 \ src/proof/cec src/proof/acec src/proof/dch src/proof/fraig src/proof/fra src/proof/ssw \ src/aig/aig src/aig/saig src/aig/gia src/aig/ioa src/aig/ivy src/aig/hop \ src/aig/miniaig all: $(PROG) default: $(PROG) ARCHFLAGS_EXE ?= ./arch_flags $(ARCHFLAGS_EXE) : arch_flags.c $(CC) $< -o $(ARCHFLAGS_EXE) INCLUDES += -I$(ABCSRC)/src # Use C99 stdint.h header for platform-dependent types ifdef ABC_USE_STDINT_H ARCHFLAGS ?= -DABC_USE_STDINT_H=1 else ARCHFLAGS ?= $(shell $(CC) $(ABCSRC)/arch_flags.c -o $(ARCHFLAGS_EXE) && $(ARCHFLAGS_EXE)) endif ARCHFLAGS := $(ARCHFLAGS) OPTFLAGS ?= -g -O CFLAGS += -Wall -Wno-unused-function -Wno-write-strings -Wno-sign-compare $(ARCHFLAGS) ifneq ($(findstring arm,$(shell uname -m)),) CFLAGS += -DABC_MEMALIGN=4 endif # 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 -x c++ CC := $(CXX) $(info $(MSG_PREFIX)Compiling in namespace $(ABC_NAMESPACE)) endif # compile CUDD with ABC ifndef ABC_USE_NO_CUDD CFLAGS += -DABC_USE_CUDD=1 MODULES += src/bdd/cudd src/bdd/extrab src/bdd/dsd src/bdd/epd src/bdd/mtr src/bdd/reo src/bdd/cas src/bdd/bbr src/bdd/llb $(info $(MSG_PREFIX)Compiling with CUDD) endif ABC_READLINE_INCLUDES ?= ABC_READLINE_LIBRARIES ?= -lreadline # whether to use libreadline ifndef ABC_USE_NO_READLINE CFLAGS += -DABC_USE_READLINE $(ABC_READLINE_INCLUDES) LIBS += $(ABC_READLINE_LIBRARIES) ifeq ($(OS), FreeBSD) CFLAGS += -I/usr/local/include LDFLAGS += -L/usr/local/lib endif $(info $(MSG_PREFIX)Using libreadline) endif # whether to compile with thread support ifndef ABC_USE_NO_PTHREADS CFLAGS += -DABC_USE_PTHREADS LIBS += -lpthread $(info $(MSG_PREFIX)Using pthreads) endif # whether to compile into position independent code ifdef ABC_USE_PIC CFLAGS += -fPIC LIBS += -fPIC $(info $(MSG_PREFIX)Compiling position independent code) endif # whether to echo commands while building ifdef ABC_MAKE_VERBOSE VERBOSE= else VERBOSE=@ endif # Set -Wno-unused-bug-set-variable for GCC 4.6.0 and greater only ifneq ($(or $(findstring gcc,$(CC)),$(findstring g++,$(CC))),) empty:= space:=$(empty) $(empty) GCC_VERSION=$(shell $(CC) -dumpversion) GCC_MAJOR=$(word 1,$(subst .,$(space),$(GCC_VERSION))) GCC_MINOR=$(word 2,$(subst .,$(space),$(GCC_VERSION))) $(info $(MSG_PREFIX)Found GCC_VERSION $(GCC_VERSION)) ifeq ($(findstring $(GCC_MAJOR),0 1 2 3),) 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 # LIBS := -ldl -lrt LIBS += -lm ifneq ($(OS), $(filter $(OS), FreeBSD OpenBSD NetBSD)) LIBS += -ldl endif ifneq ($(OS), $(filter $(OS), FreeBSD OpenBSD NetBSD Darwin)) LIBS += -lrt endif ifdef ABC_USE_LIBSTDCXX LIBS += -lstdc++ $(info $(MSG_PREFIX)Using explicit -lstdc++) endif $(info $(MSG_PREFIX)Using CFLAGS=$(CFLAGS)) CXXFLAGS += $(CFLAGS) -std=c++17 -fno-exceptions SRC := GARBAGE := core core.* *.stackdump ./tags $(PROG) arch_flags .PHONY: all default tags clean docs cmake_info include $(patsubst %, $(ABCSRC)/%/module.make, $(MODULES)) OBJ := \ $(patsubst %.cc, %.o, $(filter %.cc, $(SRC))) \ $(patsubst %.cpp, %.o, $(filter %.cpp, $(SRC))) \ $(patsubst %.c, %.o, $(filter %.c, $(SRC))) \ $(patsubst %.y, %.o, $(filter %.y, $(SRC))) LIBOBJ := $(filter-out src/base/main/main.o,$(OBJ)) DEP := $(OBJ:.o=.d) # implicit rules %.o: %.c @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$< $(VERBOSE)$(CC) -c $(OPTFLAGS) $(INCLUDES) $(CFLAGS) $< -o $@ %.o: %.cc @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$< $(VERBOSE)$(CXX) -c $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< -o $@ %.o: %.cpp @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$< $(VERBOSE)$(CXX) -c $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< -o $@ %.d: %.c @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< $(VERBOSE)$(ABCSRC)/depends.sh "$(CC)" `dirname $*.c` $(OPTFLAGS) $(INCLUDES) $(CFLAGS) $< > $@ %.d: %.cc @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< $(VERBOSE)$(ABCSRC)/depends.sh "$(CXX)" `dirname $*.cc` $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< > $@ %.d: %.cpp @mkdir -p $(dir $@) @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< $(VERBOSE)$(ABCSRC)/depends.sh "$(CXX)" `dirname $*.cpp` $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< > $@ ifndef ABC_MAKE_NO_DEPS -include $(DEP) endif # Actual targets depend: $(DEP) clean: @echo "$(MSG_PREFIX)\`\` Cleaning up..." $(VERBOSE)rm -rvf $(PROG) lib$(PROG).a $(VERBOSE)rm -rvf $(OBJ) $(VERBOSE)rm -rvf $(GARBAGE) $(VERBOSE)rm -rvf $(OBJ:.o=.d) tags: etags `find . -type f -regex '.*\.\(c\|h\)'` $(PROG): $(OBJ) @echo "$(MSG_PREFIX)\`\` Building binary:" $(notdir $@) $(VERBOSE)$(LD) -o $@ $^ $(LDFLAGS) $(LIBS) lib$(PROG).a: $(LIBOBJ) @echo "$(MSG_PREFIX)\`\` Linking:" $(notdir $@) $(VERBOSE)$(AR) rsv $@ $? lib$(PROG).so: $(LIBOBJ) @echo "$(MSG_PREFIX)\`\` Linking:" $(notdir $@) $(VERBOSE)$(CXX) -shared -o $@ $^ $(LIBS) docs: @echo "$(MSG_PREFIX)\`\` Building documentation." $(notdir $@) $(VERBOSE)doxygen doxygen.conf cmake_info: @echo SEPARATOR_CFLAGS $(CFLAGS) SEPARATOR_CFLAGS @echo SEPARATOR_CXXFLAGS $(CXXFLAGS) SEPARATOR_CXXFLAGS @echo SEPARATOR_LIBS $(LIBS) SEPARATOR_LIBS @echo SEPARATOR_SRC $(SRC) SEPARATOR_SRC abc-0.52/README.md000066400000000000000000000151031477524141600134570ustar00rootroot00000000000000[![.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 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: To compile ABC as a binary, download and unzip the code, then type `make`. To compile ABC as a static library, type `make libabc.a`. When ABC is used as a static library, two additional procedures, `Abc_Start()` and `Abc_Stop()`, are provided for starting and quitting the ABC framework in the calling application. A simple demo program (file src/demo.c) shows how to create a stand-alone program performing DAG-aware AIG rewriting, by calling APIs of ABC compiled as a static library. To build the demo program * 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` To run the demo program, give it a file with the logic network in AIGER or BLIF. For example: [...] ~/abc> demo i10.aig i10 : i/o = 257/ 224 lat = 0 and = 2396 lev = 37 i10 : i/o = 257/ 224 lat = 0 and = 1851 lev = 35 Networks are equivalent. Reading = 0.00 sec Rewriting = 0.18 sec Verification = 0.41 sec The same can be produced by running the binary in the command-line mode: [...] ~/abc> ./abc UC Berkeley, ABC 1.01 (compiled Oct 6 2012 19:05:18) abc 01> r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec i10 : i/o = 257/ 224 lat = 0 and = 2396 lev = 37 i10 : i/o = 257/ 224 lat = 0 and = 1851 lev = 35 Networks are equivalent. or in the batch mode: [...] ~/abc> ./abc -c "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec" ABC command line: "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec". i10 : i/o = 257/ 224 lat = 0 and = 2396 lev = 37 i10 : i/o = 257/ 224 lat = 0 and = 1851 lev = 35 Networks are equivalent. ## Compiling as C or C++ The current version of ABC can be compiled with C compiler or C++ compiler. * To compile as C code (default): make sure that `CC=gcc` and `ABC_NAMESPACE` is not defined. * To compile as C++ code without namespaces: make sure that `CC=g++` and `ABC_NAMESPACE` is not defined. * To compile as C++ code with namespaces: make sure that `CC=g++` and `ABC_NAMESPACE` is set to the name of the requested namespace. For example, add `-DABC_NAMESPACE=xxx` to OPTFLAGS. ## Building a shared library * Compile the code as position-independent by adding `ABC_USE_PIC=1`. * Build the `libabc.so` target: make ABC_USE_PIC=1 libabc.so ## Bug reporting: Please try to reproduce all the reported bugs and unexpected features using the latest version of ABC available from https://github.com/berkeley-abc/abc If the bug still persists, please provide the following information: 1. ABC version (when it was downloaded from GitHub) 1. Linux distribution and version (32-bit or 64-bit) 1. The exact command-line and error message when trying to run the tool 1. The output of the `ldd` command run on the exeutable (e.g. `ldd abc`). 1. Versions of relevant tools or packages used. ## Troubleshooting: 1. If compilation does not start because of the cyclic dependency check, try touching all files as follows: `find ./ -type f -exec touch "{}" \;` 1. If compilation fails because readline is missing, install 'readline' library or compile with `make ABC_USE_NO_READLINE=1` 1. If compilation fails because pthreads are missing, install 'pthread' library or compile with `make ABC_USE_NO_PTHREADS=1` * See http://sourceware.org/pthreads-win32/ for pthreads on Windows * Precompiled DLLs are available from ftp://sourceware.org/pub/pthreads-win32/dll-latest 1. If compilation fails in file "src/base/main/libSupport.c", try the following: * Remove "src/base/main/libSupport.c" from "src/base/main/module.make" * Comment out calls to `Libs_Init()` and `Libs_End()` in "src/base/main/mainInit.c" 1. On some systems, readline requires adding '-lcurses' to Makefile. The following comment was added by Krish Sundaresan: "I found that the code does compile correctly on Solaris if gcc is used (instead of g++ that I was using for some reason). Also readline which is not available by default on most Sol10 systems, needs to be installed. I downloaded the readline-5.2 package from sunfreeware.com and installed it locally. Also modified CFLAGS to add the local include files for readline and LIBS to add the local libreadline.a. Perhaps you can add these steps in the readme to help folks compiling this on Solaris." The following tutorial is kindly offered by Ana Petkovska from EPFL: https://www.dropbox.com/s/qrl9svlf0ylxy8p/ABC_GettingStarted.pdf ## Final remarks: Unfortunately, there is no comprehensive regression test. Good luck! This system is maintained by Alan Mishchenko . Consider also using ZZ framework developed by Niklas Een: https://bitbucket.org/niklaseen/abc-zz (or https://github.com/berkeley-abc/abc-zz) abc-0.52/abc.rc000066400000000000000000000120611477524141600132530ustar00rootroot00000000000000# global parameters set check # checks intermediate networks #set checkfio # prints warnings when fanins/fanouts are duplicated #unset checkread # does not check new networks after reading from file #set backup # saves backup networks retrived by "undo" and "recall" #set savesteps 1 # sets the maximum number of backup networks to save #set progressbar # display the progress bar # program names for internal calls set dotwin dot.exe set dotunix dot set gsviewwin gsview32.exe set gsviewunix gv set siswin sis.exe set sisunix sis set mvsiswin mvsis.exe set mvsisunix mvsis set capowin MetaPl-Capo10.1-Win32.exe set capounix MetaPl-Capo10.1 set gnuplotwin wgnuplot.exe set gnuplotunix gnuplot # Niklas Een's commands #load_plugin C:\_projects\abc\lib\bip_win.exe "BIP" # standard aliases alias hi history alias b balance alias cg clockgate alias cl cleanup alias clp collapse alias cs care_set alias el eliminate alias esd ext_seq_dcs alias f fraig alias fs fraig_sweep alias fsto fraig_store alias fres fraig_restore alias fr fretime alias ft fraig_trust alias ic indcut alias lp lutpack alias pcon print_cone alias pd print_dsd alias pex print_exdc -d alias pf print_factor alias pfan print_fanio alias pg print_gates alias pl print_level alias plat print_latch alias pio print_io alias pk print_kmap alias pm print_miter alias ps print_stats alias psb print_stats -b alias psu print_supp alias psy print_symm alias pun print_unate alias q quit alias r read alias ra read_aiger alias r3 retime -M 3 alias r3f retime -M 3 -f alias r3b retime -M 3 -b alias ren renode alias rh read_hie alias ri read_init alias rl read_blif alias rb read_bench alias ret retime alias dret dretime alias rp read_pla alias rt read_truth alias rv read_verilog alias rvl read_verlib alias rsup read_super mcnc5_old.super alias rlib read_library alias rlibc read_library cadence.genlib alias rty read_liberty alias rlut read_lut alias rw rewrite alias rwz rewrite -z alias rf refactor alias rfz refactor -z alias re restructure alias rez restructure -z alias rs resub alias rsz resub -z alias sa set autoexec ps alias scl scleanup alias sif if -s alias so source -x alias st strash alias sw sweep alias ssw ssweep alias tr0 trace_start alias tr1 trace_check alias trt "r c.blif; st; tr0; b; tr1" alias u undo alias w write alias wa write_aiger alias wb write_bench alias wc write_cnf alias wh write_hie alias wl write_blif alias wp write_pla alias wv write_verilog # standard scripts alias resyn "b; rw; rwz; b; rwz; b" alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b" alias resyn2a "b; rw; b; rw; rwz; b; rwz; b" alias resyn3 "b; rs; rs -K 6; b; rsz; rsz -K 6; b; rsz -K 5; b" alias compress "b -l; rw -l; rwz -l; b -l; rwz -l; b -l" alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l" alias choice "fraig_store; resyn; fraig_store; resyn2; fraig_store; fraig_restore" alias choice2 "fraig_store; balance; fraig_store; resyn; fraig_store; resyn2; fraig_store; resyn2; fraig_store; fraig_restore" alias rwsat "st; rw -l; b -l; rw -l; rf -l" alias drwsat2 "st; drw; b -l; drw; drf; ifraig -C 20; drw; b -l; drw; drf" alias share "st; multi -m; sop; fx; resyn2" alias addinit "read_init; undc; strash; zero" alias blif2aig "undc; strash; zero" alias v2p "&vta_gla; &ps; &gla_derive; &put; w 1.aig; pdr -v" alias g2p "&ps; &gla_derive; &put; w 2.aig; pdr -v" alias &sw_ "&put; sweep; st; &get" alias &fx_ "&put; sweep; sop; fx; st; &get" alias &dc3 "&b; &jf -K 6; &b; &jf -K 4; &b" alias &dc4 "&b; &jf -K 7; &fx; &b; &jf -K 5; &fx; &b" # resubstitution scripts for the IWLS paper 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" alias &resyn2rs "&put; resyn2rs; &get" alias &compress2rs "&put; compress2rs; &get" # use this script to convert 1-valued and DC-valued flops for an AIG alias fix_aig "logic; undc; strash; zero" # use this script to convert 1-valued and DC-valued flops for a logic network coming from BLIF alias fix_blif "undc; strash; zero" # lazy man's synthesis alias recadd3 "st; rec_add3; b; rec_add3; dc2; rec_add3; if -K 8; bidec; st; rec_add3; dc2; rec_add3; if -g -K 6; st; rec_add3" abc-0.52/abcexe.dsp000066400000000000000000000112111477524141600141330ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="abcexe" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=abcexe - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "abcexe.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "abcexe.mak" CFG="abcexe - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "abcexe - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "abcexe - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "abcexe - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseExe" # PROP BASE Intermediate_Dir "ReleaseExe" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseExe" # PROP Intermediate_Dir "ReleaseExe" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "src" /D "WIN32" /D "WINDOWS" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /D "ABC_USE_PTHREADS" /D "ABC_USE_CUDD" /FR /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib lib\x86\pthreadVC2.lib /nologo /subsystem:console /incremental:yes /debug /machine:I386 /out:"_TEST/abc.exe" # SUBTRACT LINK32 /profile !ELSEIF "$(CFG)" == "abcexe - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugExe" # PROP BASE Intermediate_Dir "DebugExe" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugExe" # PROP Intermediate_Dir "DebugExe" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "src" /D "WIN32" /D "WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /D "ABC_USE_PTHREADS" /D "ABC_USE_CUDD" /FR /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib lib\x86\pthreadVC2.lib /nologo /subsystem:console /debug /machine:I386 /out:"_TEST/abc.exe" !ENDIF # Begin Target # Name "abcexe - Win32 Release" # Name "abcexe - Win32 Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\src\base\main\main.c # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project abc-0.52/abclib.dsp000066400000000000000000004136041477524141600141340ustar00rootroot00000000000000# Microsoft Developer Studio Project File - Name="abclib" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Static Library" 0x0104 CFG=abclib - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "abclib.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "abclib.mak" CFG="abclib - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "abclib - Win32 Release" (based on "Win32 (x86) Static Library") !MESSAGE "abclib - Win32 Debug" (based on "Win32 (x86) Static Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "abclib - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "ReleaseLib" # PROP BASE Intermediate_Dir "ReleaseLib" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "ReleaseLib" # PROP Intermediate_Dir "ReleaseLib" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "src" /D "WIN32" /D "WINDOWS" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /D "ABC_USE_PTHREADS" /D "ABC_USE_CUDD" /FR /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo /out:"lib\abcr.lib" !ELSEIF "$(CFG)" == "abclib - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "DebugLib" # PROP BASE Intermediate_Dir "DebugLib" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "DebugLib" # PROP Intermediate_Dir "DebugLib" # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c # ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "src" /D "WIN32" /D "WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /D "ABC_USE_PTHREADS" /D "ABC_USE_CUDD" /FR /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LIB32=link.exe -lib # ADD BASE LIB32 /nologo # ADD LIB32 /nologo /out:"lib\abcd.lib" !ENDIF # Begin Target # Name "abclib - Win32 Release" # Name "abclib - Win32 Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Group "base" # PROP Default_Filter "" # Begin Group "abc" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\base\abc\abc.h # End Source File # Begin Source File SOURCE=.\src\base\abc\abcAig.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcBarBuf.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcBlifMv.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcCheck.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcDfs.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcFanio.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcFanOrder.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcFunc.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcHie.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcHieCec.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcHieGia.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcHieNew.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcInt.h # End Source File # Begin Source File SOURCE=.\src\base\abc\abcLatch.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcLib.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcMinBase.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcNames.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcNetlist.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcNtk.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcObj.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcRefs.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcShow.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcSop.c # End Source File # Begin Source File SOURCE=.\src\base\abc\abcUtil.c # End Source File # End Group # Begin Group "abci" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\base\abci\abc.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcAttach.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcAuto.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcBalance.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcBidec.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcBm.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcBmc.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcCas.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcCascade.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcCollapse.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcCut.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcDar.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcDebug.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcDec.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcDetect.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcDress.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcDress2.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcDress3.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcDsd.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcEco.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcExact.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcExtract.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcFraig.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcFx.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcFxu.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcGen.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcHaig.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcIf.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcIfif.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcIfMux.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcIvy.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcLog.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcLut.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcLutmin.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcMap.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcMeasure.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcMerge.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcMffc.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcMfs.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcMini.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcMiter.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcMulti.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcMv.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcNpn.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcNpnSave.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcNtbdd.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcOdc.c # End Source File # Begin Source File 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 SOURCE=.\src\base\abci\abcPrint.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcProve.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcQbf.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcQuant.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcReach.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcRec3.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcReconv.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcRefactor.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcRenode.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcReorder.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcRestruct.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcResub.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcRewrite.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcRpo.c # End Source File # Begin Source File 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 SOURCE=.\src\base\abci\abcSaucy.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcScorr.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcSense.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcSpeedup.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcStrash.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcSweep.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcSymm.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcTim.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcTiming.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcUnate.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcUnreach.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcVerify.c # End Source File # Begin Source File SOURCE=.\src\base\abci\abcXsim.c # End Source File # End Group # Begin Group "cmd" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\base\cmd\cmd.c # End Source File # Begin Source File SOURCE=.\src\base\cmd\cmd.h # End Source File # Begin Source File SOURCE=.\src\base\cmd\cmdAlias.c # End Source File # Begin Source File SOURCE=.\src\base\cmd\cmdApi.c # End Source File # Begin Source File SOURCE=.\src\base\cmd\cmdAuto.c # End Source File # Begin Source File SOURCE=.\src\base\cmd\cmdFlag.c # End Source File # Begin Source File SOURCE=.\src\base\cmd\cmdHist.c # End Source File # Begin Source File SOURCE=.\src\base\cmd\cmdInt.h # End Source File # Begin Source File SOURCE=.\src\base\cmd\cmdLoad.c # End Source File # Begin Source File SOURCE=.\src\base\cmd\cmdPlugin.c # End Source File # Begin Source File SOURCE=.\src\base\cmd\cmdStarter.c # End Source File # Begin Source File SOURCE=.\src\base\cmd\cmdUtils.c # End Source File # End Group # Begin Group "io" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\base\io\io.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioabc.h # End Source File # Begin Source File SOURCE=.\src\base\io\ioInt.h # End Source File # Begin Source File SOURCE=.\src\base\io\ioJson.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioReadAiger.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioReadBaf.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioReadBblif.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioReadBench.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioReadBlif.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioReadBlifAig.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioReadBlifMv.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioReadDsd.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioReadEdif.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioReadEqn.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioReadPla.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioReadPlaMo.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioReadVerilog.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioUtil.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioWriteAiger.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioWriteBaf.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioWriteBblif.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioWriteBench.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioWriteBlif.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioWriteBlifMv.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioWriteBook.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioWriteCnf.c # End Source File # Begin Source File 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 SOURCE=.\src\base\io\ioWriteGml.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioWriteHMetis.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioWriteList.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioWritePla.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioWriteSmv.c # End Source File # Begin Source File SOURCE=.\src\base\io\ioWriteVerilog.c # End Source File # End Group # Begin Group "main" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\base\main\abcapis.h # End Source File # Begin Source File SOURCE=.\src\base\main\libSupport.c # End Source File # Begin Source File SOURCE=.\src\base\main\main.h # End Source File # Begin Source File SOURCE=.\src\base\main\mainFrame.c # End Source File # Begin Source File SOURCE=.\src\base\main\mainInit.c # End Source File # Begin Source File SOURCE=.\src\base\main\mainInt.h # End Source File # Begin Source File SOURCE=.\src\base\main\mainLib.c # End Source File # Begin Source File SOURCE=.\src\base\main\mainReal.c # End Source File # Begin Source File SOURCE=.\src\base\main\mainUtils.c # End Source File # End Group # Begin Group "ver" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\base\ver\ver.h # End Source File # Begin Source File SOURCE=.\src\base\ver\verCore.c # End Source File # Begin Source File SOURCE=.\src\base\ver\verFormula.c # End Source File # Begin Source File SOURCE=.\src\base\ver\verParse.c # End Source File # Begin Source File SOURCE=.\src\base\ver\verStream.c # End Source File # End Group # Begin Group "test" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\base\test\test.c # End Source File # End Group # Begin Group "wlc" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\base\wlc\wlc.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlc.h # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcAbc.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcAbs.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcAbs2.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcBlast.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcCom.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcGraft.c # End Source File # Begin Source File 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 SOURCE=.\src\base\wlc\wlcNtk.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcPth.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcReadSmt.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcReadVer.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcShow.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcSim.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcStdin.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcUif.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcWin.c # End Source File # Begin Source File SOURCE=.\src\base\wlc\wlcWriteVer.c # End Source File # End Group # Begin Group "pla" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\base\pla\pla.h # End Source File # Begin Source File SOURCE=.\src\base\pla\plaCom.c # End Source File # Begin Source File SOURCE=.\src\base\pla\plaHash.c # End Source File # Begin Source File SOURCE=.\src\base\pla\plaMan.c # End Source File # Begin Source File SOURCE=.\src\base\pla\plaMerge.c # End Source File # Begin Source File SOURCE=.\src\base\pla\plaRead.c # End Source File # Begin Source File SOURCE=.\src\base\pla\plaSimple.c # End Source File # Begin Source File SOURCE=.\src\base\pla\plaWrite.c # End Source File # End Group # Begin Group "bac" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\base\bac\bac.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bac.h # End Source File # Begin Source File SOURCE=.\src\base\bac\bacBac.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bacBlast.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bacCom.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bacLib.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bacNtk.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bacOper.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bacPrs.h # End Source File # Begin Source File SOURCE=.\src\base\bac\bacPrsBuild.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bacPrsTrans.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bacPtr.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bacPtrAbc.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bacReadBlif.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bacReadSmt.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bacReadVer.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bacWriteBlif.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bacWriteSmt.c # End Source File # Begin Source File SOURCE=.\src\base\bac\bacWriteVer.c # End Source File # End Group # Begin Group "cba" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\base\cba\cba.c # End Source File # Begin Source File SOURCE=.\src\base\cba\cba.h # End Source File # Begin Source File SOURCE=.\src\base\cba\cbaBlast.c # End Source File # Begin Source File SOURCE=.\src\base\cba\cbaCba.c # End Source File # Begin Source File SOURCE=.\src\base\cba\cbaCom.c # End Source File # Begin Source File SOURCE=.\src\base\cba\cbaNtk.c # End Source File # Begin Source File SOURCE=.\src\base\cba\cbaPrs.h # End Source File # Begin Source File SOURCE=.\src\base\cba\cbaReadBlif.c # End Source File # Begin Source File SOURCE=.\src\base\cba\cbaReadVer.c # End Source File # Begin Source File SOURCE=.\src\base\cba\cbaTypes.h # End Source File # Begin Source File SOURCE=.\src\base\cba\cbaWriteBlif.c # End Source File # Begin Source File SOURCE=.\src\base\cba\cbaWriteVer.c # End Source File # End Group # Begin Group "exor" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\base\exor\exor.c # End Source File # Begin Source File SOURCE=.\src\base\exor\exor.h # End Source File # Begin Source File SOURCE=.\src\base\exor\exorBits.c # End Source File # Begin Source File SOURCE=.\src\base\exor\exorCubes.c # End Source File # Begin Source File SOURCE=.\src\base\exor\exorLink.c # End Source File # Begin Source File SOURCE=.\src\base\exor\exorList.c # End Source File # Begin Source File SOURCE=.\src\base\exor\exorUtil.c # End Source File # End Group # Begin Group "acb" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\base\acb\acb.c # End Source File # Begin Source File SOURCE=.\src\base\acb\acb.h # End Source File # Begin Source File SOURCE=.\src\base\acb\acbAbc.c # End Source File # Begin Source File SOURCE=.\src\base\acb\acbAig.c # End Source File # Begin Source File SOURCE=.\src\base\acb\acbCom.c # End Source File # Begin Source File SOURCE=.\src\base\acb\acbFunc.c # End Source File # Begin Source File SOURCE=.\src\base\acb\acbMfs.c # End Source File # Begin Source File SOURCE=.\src\base\acb\acbPar.h # End Source File # Begin Source File SOURCE=.\src\base\acb\acbPush.c # End Source File # Begin Source File SOURCE=.\src\base\acb\acbSets.c # End Source File # Begin Source File 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" # PROP Default_Filter "" # Begin Group "extrab" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bdd\extrab\extraBdd.h # End Source File # Begin Source File SOURCE=.\src\bdd\extrab\extraLutCas.h # End Source File # Begin Source File SOURCE=.\src\bdd\extrab\extraBddAuto.c # End Source File # Begin Source File SOURCE=.\src\bdd\extrab\extraBddCas.c # End Source File # Begin Source File SOURCE=.\src\bdd\extrab\extraBddImage.c # End Source File # Begin Source File 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 SOURCE=.\src\bdd\extrab\extraBddThresh.c # End Source File # Begin Source File SOURCE=.\src\bdd\extrab\extraBddTime.c # End Source File # Begin Source File SOURCE=.\src\bdd\extrab\extraBddUnate.c # End Source File # End Group # Begin Group "llb" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bdd\llb\llb.h # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb1Cluster.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb1Constr.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb1Core.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb1Group.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb1Hint.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb1Man.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb1Matrix.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb1Pivot.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb1Reach.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb1Sched.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb2Bad.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb2Core.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb2Driver.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb2Dump.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb2Flow.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb2Image.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb3Image.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb3Nonlin.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb4Cex.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb4Cluster.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb4Image.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb4Map.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb4Nonlin.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llb4Sweep.c # End Source File # Begin Source File SOURCE=.\src\bdd\llb\llbInt.h # End Source File # End Group # Begin Group "bbr" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bdd\bbr\bbr.h # End Source File # Begin Source File SOURCE=.\src\bdd\bbr\bbrCex.c # End Source File # Begin Source File SOURCE=.\src\bdd\bbr\bbrImage.c # End Source File # Begin Source File SOURCE=.\src\bdd\bbr\bbrNtbdd.c # End Source File # Begin Source File SOURCE=.\src\bdd\bbr\bbrReach.c # End Source File # End Group # Begin Group "cas" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bdd\cas\cas.h # End Source File # Begin Source File SOURCE=.\src\bdd\cas\casCore.c # End Source File # Begin Source File SOURCE=.\src\bdd\cas\casDec.c # End Source File # End Group # Begin Group "reo" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bdd\reo\reo.h # End Source File # Begin Source File SOURCE=.\src\bdd\reo\reoApi.c # End Source File # Begin Source File SOURCE=.\src\bdd\reo\reoCore.c # End Source File # Begin Source File SOURCE=.\src\bdd\reo\reoProfile.c # End Source File # Begin Source File SOURCE=.\src\bdd\reo\reoShuffle.c # End Source File # Begin Source File SOURCE=.\src\bdd\reo\reoSift.c # End Source File # Begin Source File SOURCE=.\src\bdd\reo\reoSwap.c # End Source File # Begin Source File SOURCE=.\src\bdd\reo\reoTest.c # End Source File # Begin Source File SOURCE=.\src\bdd\reo\reoTransfer.c # End Source File # Begin Source File SOURCE=.\src\bdd\reo\reoUnits.c # End Source File # End Group # Begin Group "dsd" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bdd\dsd\dsd.h # End Source File # Begin Source File SOURCE=.\src\bdd\dsd\dsdApi.c # End Source File # Begin Source File SOURCE=.\src\bdd\dsd\dsdCheck.c # End Source File # Begin Source File SOURCE=.\src\bdd\dsd\dsdInt.h # End Source File # Begin Source File SOURCE=.\src\bdd\dsd\dsdLocal.c # End Source File # Begin Source File SOURCE=.\src\bdd\dsd\dsdMan.c # End Source File # Begin Source File SOURCE=.\src\bdd\dsd\dsdProc.c # End Source File # Begin Source File SOURCE=.\src\bdd\dsd\dsdTree.c # End Source File # End Group # Begin Group "mtr" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bdd\mtr\mtr.h # End Source File # Begin Source File SOURCE=.\src\bdd\mtr\mtrBasic.c # End Source File # Begin Source File SOURCE=.\src\bdd\mtr\mtrGroup.c # End Source File # Begin Source File SOURCE=.\src\bdd\mtr\mtrInt.h # End Source File # End Group # Begin Group "epd" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bdd\epd\epd.c # End Source File # Begin Source File SOURCE=.\src\bdd\epd\epd.h # End Source File # End Group # Begin Group "cudd" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bdd\cudd\cudd.h # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddAddAbs.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddAddApply.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddAddFind.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddAddInv.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddAddIte.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddAddNeg.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddAddWalsh.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddAndAbs.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddAnneal.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddApa.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddAPI.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddApprox.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddBddAbs.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddBddCorr.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddBddIte.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddBridge.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddCache.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddCheck.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddClip.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddCof.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddCompose.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddDecomp.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddEssent.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddExact.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddExport.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddGenCof.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddGenetic.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddGroup.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddHarwell.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddInit.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddInt.h # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddInteract.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddLCache.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddLevelQ.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddLinear.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddLiteral.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddMatMult.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddPriority.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddRead.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddRef.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddReorder.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddSat.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddSign.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddSolve.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddSplit.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddSubsetHB.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddSubsetSP.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddSymmetry.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddTable.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddUtil.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddWindow.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddZddCount.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddZddFuncs.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddZddGroup.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddZddIsop.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddZddLin.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddZddMisc.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddZddPort.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddZddReord.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddZddSetop.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddZddSymm.c # End Source File # Begin Source File SOURCE=.\src\bdd\cudd\cuddZddUtil.c # End Source File # End Group # End Group # Begin Group "sat" # PROP Default_Filter "" # Begin Group "msat" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\sat\msat\msat.h # End Source File # Begin Source File SOURCE=.\src\sat\msat\msatActivity.c # End Source File # Begin Source File SOURCE=.\src\sat\msat\msatClause.c # End Source File # Begin Source File SOURCE=.\src\sat\msat\msatClauseVec.c # End Source File # Begin Source File SOURCE=.\src\sat\msat\msatInt.h # End Source File # Begin Source File SOURCE=.\src\sat\msat\msatMem.c # End Source File # Begin Source File SOURCE=.\src\sat\msat\msatOrderH.c # End Source File # Begin Source File SOURCE=.\src\sat\msat\msatQueue.c # End Source File # Begin Source File SOURCE=.\src\sat\msat\msatRead.c # End Source File # Begin Source File SOURCE=.\src\sat\msat\msatSolverApi.c # End Source File # Begin Source File SOURCE=.\src\sat\msat\msatSolverCore.c # End Source File # Begin Source File SOURCE=.\src\sat\msat\msatSolverIo.c # End Source File # Begin Source File SOURCE=.\src\sat\msat\msatSolverSearch.c # End Source File # Begin Source File SOURCE=.\src\sat\msat\msatSort.c # End Source File # Begin Source File SOURCE=.\src\sat\msat\msatVec.c # End Source File # End Group # Begin Group "csat" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\sat\csat\csat_apis.c # End Source File # Begin Source File SOURCE=.\src\sat\csat\csat_apis.h # End Source File # End Group # Begin Group "bsat" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\sat\bsat\satClause.h # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satInter.c # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satInterA.c # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satInterB.c # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satInterP.c # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satMem.c # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satMem.h # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satProof.c # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satProof2.h # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satSolver.c # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satSolver.h # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satSolver2.c # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satSolver2.h # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satSolver2i.c # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satSolver3.c # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satSolver3.h # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satStore.c # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satStore.h # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satTrace.c # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satTruth.c # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satTruth.h # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satUtil.c # End Source File # Begin Source File SOURCE=.\src\sat\bsat\satVec.h # End Source File # End Group # Begin Group "proof" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\sat\proof\pr.c # End Source File # Begin Source File SOURCE=.\src\sat\proof\pr.h # End Source File # End Group # Begin Group "psat" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\sat\psat\m114p.h # End Source File # Begin Source File SOURCE=.\src\sat\psat\m114p_types.h # End Source File # End Group # Begin Group "lsat" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\sat\lsat\solver.h # End Source File # End Group # Begin Group "cnf" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\sat\cnf\cnf.h # End Source File # Begin Source File SOURCE=.\src\sat\cnf\cnfCore.c # End Source File # Begin Source File SOURCE=.\src\sat\cnf\cnfCut.c # End Source File # Begin Source File SOURCE=.\src\sat\cnf\cnfData.c # End Source File # Begin Source File SOURCE=.\src\sat\cnf\cnfFast.c # End Source File # Begin Source File SOURCE=.\src\sat\cnf\cnfMan.c # End Source File # Begin Source File SOURCE=.\src\sat\cnf\cnfMap.c # End Source File # Begin Source File SOURCE=.\src\sat\cnf\cnfPost.c # End Source File # Begin Source File SOURCE=.\src\sat\cnf\cnfUtil.c # End Source File # Begin Source File SOURCE=.\src\sat\cnf\cnfWrite.c # End Source File # End Group # Begin Group "bmc" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\sat\bmc\bmc.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmc.h # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcBCore.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcBmc.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcBmc2.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcBmc3.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcBmcAnd.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcBmcG.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcBmci.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcBmcS.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcCexCare.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcCexCut.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcCexDepth.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcCexMin1.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcCexMin2.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcCexTools.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcChain.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcClp.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcEco.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcExpand.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcFault.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcFx.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcGen.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcICheck.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcInse.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcLoad.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcMaj.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcMaj2.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcMaj3.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcMaxi.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcMesh.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcMesh2.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcMulti.c # End Source File # Begin Source File SOURCE=.\src\sat\bmc\bmcUnroll.c # End Source File # End Group # Begin Group "bsat2" # PROP Default_Filter "" # End Group # Begin Group "satoko" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\sat\satoko\act_clause.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\act_var.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\utils\b_queue.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\cdb.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\clause.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\cnf_reader.c # End Source File # Begin Source File SOURCE=.\src\sat\satoko\utils\heap.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\utils\mem.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\utils\misc.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\satoko.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\utils\sdbl.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\solver.c # End Source File # Begin Source File SOURCE=.\src\sat\satoko\solver.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\solver_api.c # End Source File # Begin Source File SOURCE=.\src\sat\satoko\utils\sort.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\types.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\utils\vec\vec_char.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\utils\vec\vec_flt.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\utils\vec\vec_int.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\utils\vec\vec_uint.h # End Source File # Begin Source File SOURCE=.\src\sat\satoko\watch_list.h # End Source File # End Group # Begin Group "xsat" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\sat\xsat\xsat.h # End Source File # Begin Source File SOURCE=.\src\sat\xsat\xsatBQueue.h # End Source File # Begin Source File SOURCE=.\src\sat\xsat\xsatClause.h # End Source File # Begin Source File SOURCE=.\src\sat\xsat\xsatCnfReader.c # End Source File # Begin Source File SOURCE=.\src\sat\xsat\xsatHeap.h # End Source File # Begin Source File SOURCE=.\src\sat\xsat\xsatMemory.h # End Source File # Begin Source File SOURCE=.\src\sat\xsat\xsatSolver.c # End Source File # Begin Source File SOURCE=.\src\sat\xsat\xsatSolver.h # End Source File # Begin Source File SOURCE=.\src\sat\xsat\xsatSolverAPI.c # End Source File # Begin Source File SOURCE=.\src\sat\xsat\xsatUtils.h # End Source File # Begin Source File SOURCE=.\src\sat\xsat\xsatWatchList.h # End Source File # End Group # Begin Group "glucose" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\sat\glucose\AbcGlucose.cpp # End Source File # Begin Source File SOURCE=.\src\sat\glucose\AbcGlucose.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\AbcGlucoseCmd.cpp # End Source File # Begin Source File SOURCE=.\src\sat\glucose\Alg.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\Alloc.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\BoundedQueue.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\Constants.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\Dimacs.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\Glucose.cpp # End Source File # Begin Source File SOURCE=.\src\sat\glucose\Heap.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\IntTypes.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\Map.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\Options.cpp # End Source File # Begin Source File SOURCE=.\src\sat\glucose\Options.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\ParseUtils.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\pstdint.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\Queue.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\SimpSolver.cpp # End Source File # Begin Source File SOURCE=.\src\sat\glucose\SimpSolver.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\Solver.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\SolverTypes.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\Sort.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\System.cpp # End Source File # Begin Source File SOURCE=.\src\sat\glucose\System.h # End Source File # Begin Source File SOURCE=.\src\sat\glucose\Vec.h # End Source File # Begin Source File 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 # Begin Group "kissat" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\sat\kissat\allocate.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\analyze.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\ands.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\arena.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\assign.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\averages.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\backbone.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\backtrack.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\build.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\bump.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\check.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\classify.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\clause.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\collect.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\colors.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\compact.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\config.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\congruence.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\decide.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\deduce.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\definition.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\dense.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\dump.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\eliminate.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\equivalences.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\error.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\extend.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\factor.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\fastel.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\file.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\flags.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\format.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\forward.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\gates.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\heap.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\ifthenelse.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\import.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\internal.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\kimits.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\kissatSolver.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\kissatTest.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\kitten.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\kptions.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\krite.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\kucky.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\learn.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\logging.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\minimize.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\mode.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\phases.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\preprocess.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\print.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\probe.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\profile.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\promote.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\proof.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\propbeyond.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\propdense.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\propinitially.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\proprobe.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\propsearch.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\queue.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\reduce.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\reluctant.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\reorder.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\rephase.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\report.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\resize.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\resolve.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\resources.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\restart.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\search.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\shrink.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\smooth.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\sort.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\stack.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\statistics.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\strengthen.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\substitute.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\sweep.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\terminate.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\tiers.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\trail.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\transitive.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\utilities.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\vector.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\vivify.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\walk.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\warmup.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\watch.c # End Source File # Begin Source File SOURCE=.\src\sat\kissat\weaken.c # End Source File # End Group # Begin Group "cadical" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\sat\cadical\cadical_kitten.c # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_analyze.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_arena.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_assume.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_averages.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_backtrack.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_backward.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_bins.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_block.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_ccadical.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_checker.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_clause.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_collect.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_compact.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_condition.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_config.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_congruence.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_constrain.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_contract.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_cover.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_decide.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_decompose.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_deduplicate.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_definition.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_drattracer.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_elim.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_elimfast.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_ema.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_extend.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_external.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_external_propagate.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_factor.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_file.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_flags.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_flip.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_format.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_frattracer.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_gates.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_idruptracer.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_instantiate.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_internal.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_ipasir.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_lidruptracer.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_limit.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_logging.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_lookahead.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_lratchecker.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_lrattracer.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_lucky.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_message.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_minimize.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_occs.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_options.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_parse.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_phases.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_probe.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_profile.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_proof.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_propagate.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_queue.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_random.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_reap.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_reduce.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_rephase.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_report.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_resources.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_restart.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_restore.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_score.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_shrink.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_signal.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_solution.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_solver.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_stable.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_stats.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_subsume.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_sweep.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_terminal.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_ternary.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_tier.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_transred.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_unstable.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_util.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_var.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_veripbtracer.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_version.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_vivify.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_walk.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadical_watch.cpp # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadicalSolver.c # End Source File # Begin Source File SOURCE=.\src\sat\cadical\cadicalTest.c # End Source File # End Group # End Group # Begin Group "opt" # PROP Default_Filter "" # Begin Group "fxu" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\fxu\fxu.c # End Source File # Begin Source File SOURCE=.\src\opt\fxu\fxu.h # End Source File # Begin Source File SOURCE=.\src\opt\fxu\fxuCreate.c # End Source File # Begin Source File SOURCE=.\src\opt\fxu\fxuHeapD.c # End Source File # Begin Source File SOURCE=.\src\opt\fxu\fxuHeapS.c # End Source File # Begin Source File SOURCE=.\src\opt\fxu\fxuInt.h # End Source File # Begin Source File SOURCE=.\src\opt\fxu\fxuList.c # End Source File # Begin Source File SOURCE=.\src\opt\fxu\fxuMatrix.c # End Source File # Begin Source File SOURCE=.\src\opt\fxu\fxuPair.c # End Source File # Begin Source File SOURCE=.\src\opt\fxu\fxuPrint.c # End Source File # Begin Source File SOURCE=.\src\opt\fxu\fxuReduce.c # End Source File # Begin Source File SOURCE=.\src\opt\fxu\fxuSelect.c # End Source File # Begin Source File SOURCE=.\src\opt\fxu\fxuSingle.c # End Source File # Begin Source File SOURCE=.\src\opt\fxu\fxuUpdate.c # End Source File # End Group # Begin Group "rar" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\rar\rewire_map.h # End Source File # Begin Source File SOURCE=.\src\opt\rar\rewire_miaig.h # End Source File # Begin Source File SOURCE=.\src\opt\rar\rewire_rar.h # End Source File # Begin Source File SOURCE=.\src\opt\rar\rewire_rng.h # End Source File # Begin Source File SOURCE=.\src\opt\rar\rewire_time.h # End Source File # Begin Source File SOURCE=.\src\opt\rar\rewire_tt.h # End Source File # Begin Source File SOURCE=.\src\opt\rar\rewire_vec.h # End Source File # Begin Source File SOURCE=.\src\opt\rar\rewire_map.c # End Source File # Begin Source File SOURCE=.\src\opt\rar\rewire_miaig.cpp # End Source File # Begin Source File SOURCE=.\src\opt\rar\rewire_rar.c # End Source File # Begin Source File SOURCE=.\src\opt\rar\rewire_rng.c # End Source File # End Group # Begin Group "rwr" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\rwr\rwr.h # End Source File # Begin Source File SOURCE=.\src\opt\rwr\rwrDec.c # End Source File # Begin Source File SOURCE=.\src\opt\rwr\rwrEva.c # End Source File # Begin Source File SOURCE=.\src\opt\rwr\rwrExp.c # End Source File # Begin Source File SOURCE=.\src\opt\rwr\rwrLib.c # End Source File # Begin Source File SOURCE=.\src\opt\rwr\rwrMan.c # End Source File # Begin Source File SOURCE=.\src\opt\rwr\rwrPrint.c # End Source File # Begin Source File SOURCE=.\src\opt\rwr\rwrTemp.c # End Source File # Begin Source File SOURCE=.\src\opt\rwr\rwrUtil.c # End Source File # End Group # Begin Group "cut" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\cut\cut.h # End Source File # Begin Source File SOURCE=.\src\opt\cut\cutApi.c # End Source File # Begin Source File SOURCE=.\src\opt\cut\cutCut.c # End Source File # Begin Source File SOURCE=.\src\opt\cut\cutExpand.c # End Source File # Begin Source File SOURCE=.\src\opt\cut\cutInt.h # End Source File # Begin Source File SOURCE=.\src\opt\cut\cutList.h # End Source File # Begin Source File SOURCE=.\src\opt\cut\cutMan.c # End Source File # Begin Source File SOURCE=.\src\opt\cut\cutMerge.c # End Source File # Begin Source File SOURCE=.\src\opt\cut\cutNode.c # End Source File # Begin Source File SOURCE=.\src\opt\cut\cutOracle.c # End Source File # Begin Source File SOURCE=.\src\opt\cut\cutPre22.c # End Source File # Begin Source File SOURCE=.\src\opt\cut\cutSeq.c # End Source File # Begin Source File SOURCE=.\src\opt\cut\cutTruth.c # End Source File # End Group # Begin Group "sim" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\sim\sim.h # End Source File # Begin Source File SOURCE=.\src\opt\sim\simMan.c # End Source File # Begin Source File SOURCE=.\src\opt\sim\simSat.c # End Source File # Begin Source File SOURCE=.\src\opt\sim\simSeq.c # End Source File # Begin Source File SOURCE=.\src\opt\sim\simSupp.c # End Source File # Begin Source File SOURCE=.\src\opt\sim\simSwitch.c # End Source File # Begin Source File SOURCE=.\src\opt\sim\simSym.c # End Source File # Begin Source File SOURCE=.\src\opt\sim\simSymSat.c # End Source File # Begin Source File SOURCE=.\src\opt\sim\simSymSim.c # End Source File # Begin Source File SOURCE=.\src\opt\sim\simSymStr.c # End Source File # Begin Source File SOURCE=.\src\opt\sim\simUtils.c # End Source File # End Group # Begin Group "ret" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\ret\retArea.c # End Source File # Begin Source File SOURCE=.\src\opt\ret\retCore.c # End Source File # Begin Source File SOURCE=.\src\opt\ret\retDelay.c # End Source File # Begin Source File SOURCE=.\src\opt\ret\retFlow.c # End Source File # Begin Source File SOURCE=.\src\opt\ret\retIncrem.c # End Source File # Begin Source File SOURCE=.\src\opt\ret\retInit.c # End Source File # Begin Source File SOURCE=.\src\opt\ret\retInt.h # End Source File # Begin Source File SOURCE=.\src\opt\ret\retLvalue.c # End Source File # End Group # Begin Group "res" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\res\res.h # End Source File # Begin Source File SOURCE=.\src\opt\res\resCore.c # End Source File # Begin Source File SOURCE=.\src\opt\res\resDivs.c # End Source File # Begin Source File SOURCE=.\src\opt\res\resFilter.c # End Source File # Begin Source File SOURCE=.\src\opt\res\resInt.h # End Source File # Begin Source File SOURCE=.\src\opt\res\resSat.c # End Source File # Begin Source File SOURCE=.\src\opt\res\resSim.c # End Source File # Begin Source File SOURCE=.\src\opt\res\resStrash.c # End Source File # Begin Source File SOURCE=.\src\opt\res\resWin.c # End Source File # End Group # Begin Group "lpk" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\lpk\lpk.h # End Source File # Begin Source File SOURCE=.\src\opt\lpk\lpkAbcDec.c # End Source File # Begin Source File SOURCE=.\src\opt\lpk\lpkAbcDsd.c # End Source File # Begin Source File SOURCE=.\src\opt\lpk\lpkAbcMux.c # End Source File # Begin Source File SOURCE=.\src\opt\lpk\lpkAbcUtil.c # End Source File # Begin Source File SOURCE=.\src\opt\lpk\lpkCore.c # End Source File # Begin Source File SOURCE=.\src\opt\lpk\lpkCut.c # End Source File # Begin Source File SOURCE=.\src\opt\lpk\lpkInt.h # End Source File # Begin Source File SOURCE=.\src\opt\lpk\lpkMan.c # End Source File # Begin Source File SOURCE=.\src\opt\lpk\lpkMap.c # End Source File # Begin Source File SOURCE=.\src\opt\lpk\lpkMulti.c # End Source File # Begin Source File SOURCE=.\src\opt\lpk\lpkMux.c # End Source File # Begin Source File SOURCE=.\src\opt\lpk\lpkSets.c # End Source File # End Group # Begin Group "mfs" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\mfs\mfs.h # End Source File # Begin Source File SOURCE=.\src\opt\mfs\mfsCore.c # End Source File # Begin Source File SOURCE=.\src\opt\mfs\mfsDiv.c # End Source File # Begin Source File SOURCE=.\src\opt\mfs\mfsInt.h # End Source File # Begin Source File SOURCE=.\src\opt\mfs\mfsInter.c # End Source File # Begin Source File SOURCE=.\src\opt\mfs\mfsMan.c # End Source File # Begin Source File SOURCE=.\src\opt\mfs\mfsResub.c # End Source File # Begin Source File SOURCE=.\src\opt\mfs\mfsSat.c # End Source File # Begin Source File SOURCE=.\src\opt\mfs\mfsStrash.c # End Source File # Begin Source File SOURCE=.\src\opt\mfs\mfsWin.c # End Source File # End Group # Begin Group "cgt" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\cgt\cgt.h # End Source File # Begin Source File SOURCE=.\src\opt\cgt\cgtAig.c # End Source File # Begin Source File SOURCE=.\src\opt\cgt\cgtCore.c # End Source File # Begin Source File SOURCE=.\src\opt\cgt\cgtDecide.c # End Source File # Begin Source File SOURCE=.\src\opt\cgt\cgtInt.h # End Source File # Begin Source File SOURCE=.\src\opt\cgt\cgtMan.c # End Source File # Begin Source File SOURCE=.\src\opt\cgt\cgtSat.c # End Source File # End Group # Begin Group "csw" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\csw\csw.h # End Source File # Begin Source File SOURCE=.\src\opt\csw\cswCore.c # End Source File # Begin Source File SOURCE=.\src\opt\csw\cswCut.c # End Source File # Begin Source File SOURCE=.\src\opt\csw\cswInt.h # End Source File # Begin Source File SOURCE=.\src\opt\csw\cswMan.c # End Source File # Begin Source File SOURCE=.\src\opt\csw\cswTable.c # End Source File # End Group # Begin Group "dar" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\dar\dar.h # End Source File # Begin Source File SOURCE=.\src\opt\dar\darBalance.c # End Source File # Begin Source File SOURCE=.\src\opt\dar\darCore.c # End Source File # Begin Source File SOURCE=.\src\opt\dar\darCut.c # End Source File # Begin Source File SOURCE=.\src\opt\dar\darData.c # End Source File # Begin Source File SOURCE=.\src\opt\dar\darInt.h # End Source File # Begin Source File SOURCE=.\src\opt\dar\darLib.c # End Source File # Begin Source File SOURCE=.\src\opt\dar\darMan.c # End Source File # Begin Source File SOURCE=.\src\opt\dar\darPrec.c # End Source File # Begin Source File SOURCE=.\src\opt\dar\darRefact.c # End Source File # Begin Source File SOURCE=.\src\opt\dar\darResub.c # End Source File # Begin Source File SOURCE=.\src\opt\dar\darScript.c # End Source File # End Group # Begin Group "rwt" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\rwt\rwt.h # End Source File # Begin Source File SOURCE=.\src\opt\rwt\rwtDec.c # End Source File # Begin Source File SOURCE=.\src\opt\rwt\rwtMan.c # End Source File # Begin Source File SOURCE=.\src\opt\rwt\rwtUtil.c # End Source File # End Group # Begin Group "nwk" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\nwk\ntlnwk.h # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwk.h # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwkAig.c # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwkBidec.c # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwkCheck.c # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwkDfs.c # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwkFanio.c # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwkFlow.c # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwkMan.c # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwkMap.c # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwkMerge.c # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwkMerge.h # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwkObj.c # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwkSpeedup.c # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwkStrash.c # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwkTiming.c # End Source File # Begin Source File SOURCE=.\src\opt\nwk\nwkUtil.c # End Source File # End Group # Begin Group "dau" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\dau\dau.c # End Source File # Begin Source File SOURCE=.\src\opt\dau\dau.h # End Source File # Begin Source File SOURCE=.\src\opt\dau\dauCanon.c # End Source File # Begin Source File 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 SOURCE=.\src\opt\dau\dauDsd.c # End Source File # Begin Source File SOURCE=.\src\opt\dau\dauEnum.c # End Source File # Begin Source File SOURCE=.\src\opt\dau\dauGia.c # End Source File # Begin Source File SOURCE=.\src\opt\dau\dauInt.h # End Source File # Begin Source File SOURCE=.\src\opt\dau\dauMerge.c # End Source File # Begin Source File 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 # Begin Group "sfm" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\sfm\sfm.h # End Source File # Begin Source File SOURCE=.\src\opt\sfm\sfmArea.c # End Source File # Begin Source File SOURCE=.\src\opt\sfm\sfmCnf.c # End Source File # Begin Source File SOURCE=.\src\opt\sfm\sfmCore.c # End Source File # Begin Source File SOURCE=.\src\opt\sfm\sfmDec.c # End Source File # Begin Source File SOURCE=.\src\opt\sfm\sfmInt.h # End Source File # Begin Source File SOURCE=.\src\opt\sfm\sfmLib.c # End Source File # Begin Source File SOURCE=.\src\opt\sfm\sfmMit.c # End Source File # Begin Source File SOURCE=.\src\opt\sfm\sfmNtk.c # End Source File # Begin Source File SOURCE=.\src\opt\sfm\sfmSat.c # End Source File # Begin Source File SOURCE=.\src\opt\sfm\sfmTim.c # End Source File # Begin Source File SOURCE=.\src\opt\sfm\sfmWin.c # End Source File # End Group # Begin Group "fret" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\fret\fretFlow.c # End Source File # Begin Source File SOURCE=.\src\opt\fret\fretime.h # End Source File # Begin Source File SOURCE=.\src\opt\fret\fretInit.c # End Source File # Begin Source File SOURCE=.\src\opt\fret\fretMain.c # End Source File # Begin Source File SOURCE=.\src\opt\fret\fretTime.c # End Source File # End Group # Begin Group "fxch" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\fxch\Fxch.c # End Source File # Begin Source File SOURCE=.\src\opt\fxch\Fxch.h # End Source File # Begin Source File SOURCE=.\src\opt\fxch\FxchDiv.c # End Source File # Begin Source File SOURCE=.\src\opt\fxch\FxchMan.c # End Source File # Begin Source File SOURCE=.\src\opt\fxch\FxchSCHashTable.c # End Source File # End Group # Begin Group "dsc" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\dsc\dsc.c # End Source File # Begin Source File SOURCE=.\src\opt\dsc\dsc.h # End Source File # End Group # Begin Group "sbd" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\sbd\sbd.c # End Source File # Begin Source File SOURCE=.\src\opt\sbd\sbd.h # End Source File # Begin Source File SOURCE=.\src\opt\sbd\sbdCnf.c # End Source File # Begin Source File SOURCE=.\src\opt\sbd\sbdCore.c # End Source File # Begin Source File SOURCE=.\src\opt\sbd\sbdCut.c # End Source File # Begin Source File SOURCE=.\src\opt\sbd\sbdCut2.c # End Source File # Begin Source File SOURCE=.\src\opt\sbd\sbdInt.h # End Source File # Begin Source File SOURCE=.\src\opt\sbd\sbdLut.c # End Source File # Begin Source File SOURCE=.\src\opt\sbd\sbdPath.c # End Source File # Begin Source File SOURCE=.\src\opt\sbd\sbdSat.c # End Source File # Begin Source File SOURCE=.\src\opt\sbd\sbdWin.c # End Source File # End Group # Begin Group "eslim" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\opt\eslim\eSLIM.cpp # End Source File # Begin Source File SOURCE=.\src\opt\eslim\eSLIM.h # End Source File # Begin Source File SOURCE=.\src\opt\eslim\eSLIMMan.hpp # End Source File # Begin Source File SOURCE=.\src\opt\eslim\relationGeneration.cpp # End Source File # Begin Source File SOURCE=.\src\opt\eslim\relationGeneration.hpp # End Source File # Begin Source File SOURCE=.\src\opt\eslim\satInterfaces.hpp # End Source File # Begin Source File SOURCE=.\src\opt\eslim\selectionStrategy.hpp # End Source File # Begin Source File SOURCE=.\src\opt\eslim\utils.hpp # End Source File # Begin Source File SOURCE=.\src\opt\eslim\synthesisEngine.hpp # End Source File # End Group # End Group # Begin Group "map" # PROP Default_Filter "" # Begin Group "mapper" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\map\mapper\mapper.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapper.h # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperCanon.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperCore.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperCreate.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperCut.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperCutUtils.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperFanout.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperInt.h # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperLib.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperMatch.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperRefs.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperSuper.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperSwitch.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperTable.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperTime.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperTree.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperTruth.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperUtils.c # End Source File # Begin Source File SOURCE=.\src\map\mapper\mapperVec.c # End Source File # End Group # Begin Group "mio" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\map\mio\exp.h # End Source File # Begin Source File SOURCE=.\src\map\mio\mio.c # End Source File # Begin Source File SOURCE=.\src\map\mio\mio.h # End Source File # Begin Source File SOURCE=.\src\map\mio\mioApi.c # End Source File # Begin Source File SOURCE=.\src\map\mio\mioFunc.c # End Source File # Begin Source File SOURCE=.\src\map\mio\mioInt.h # End Source File # Begin Source File SOURCE=.\src\map\mio\mioParse.c # End Source File # Begin Source File SOURCE=.\src\map\mio\mioRead.c # End Source File # Begin Source File SOURCE=.\src\map\mio\mioSop.c # End Source File # Begin Source File SOURCE=.\src\map\mio\mioUtils.c # End Source File # End Group # Begin Group "super" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\map\super\super.c # End Source File # Begin Source File SOURCE=.\src\map\super\super.h # End Source File # Begin Source File SOURCE=.\src\map\super\superAnd.c # End Source File # Begin Source File SOURCE=.\src\map\super\superGate.c # End Source File # Begin Source File SOURCE=.\src\map\super\superInt.h # End Source File # End Group # Begin Group "if" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\map\if\if.h # End Source File # Begin Source File SOURCE=.\src\map\if\ifCache.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifCom.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifCore.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifCount.h # End Source File # Begin Source File SOURCE=.\src\map\if\ifCut.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifData2.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifDec07.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifDec08.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifDec10.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifDec16.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifDec66.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifDec75.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifDelay.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifDsd.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifLibBox.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifLibLut.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifMan.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifMap.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifMatch2.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifReduce.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifSat.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifSelect.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifSeq.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifTest.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifTime.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifTruth.c # End Source File # Begin Source File SOURCE=.\src\map\if\ifTune.c # End Source File # Begin Source File SOURCE=.\src\map\if\acd\ac_wrapper.cpp # End Source File # Begin Source File SOURCE=.\src\map\if\ifUtil.c # End Source File # End Group # Begin Group "amap" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\map\amap\amap.h # End Source File # Begin Source File SOURCE=.\src\map\amap\amapCore.c # End Source File # Begin Source File SOURCE=.\src\map\amap\amapGraph.c # End Source File # Begin Source File SOURCE=.\src\map\amap\amapInt.h # End Source File # Begin Source File SOURCE=.\src\map\amap\amapLib.c # End Source File # Begin Source File SOURCE=.\src\map\amap\amapLiberty.c # End Source File # Begin Source File SOURCE=.\src\map\amap\amapMan.c # End Source File # Begin Source File SOURCE=.\src\map\amap\amapMatch.c # End Source File # Begin Source File SOURCE=.\src\map\amap\amapMerge.c # End Source File # Begin Source File SOURCE=.\src\map\amap\amapOutput.c # End Source File # Begin Source File SOURCE=.\src\map\amap\amapParse.c # End Source File # Begin Source File SOURCE=.\src\map\amap\amapPerm.c # End Source File # Begin Source File SOURCE=.\src\map\amap\amapRead.c # End Source File # Begin Source File SOURCE=.\src\map\amap\amapRule.c # End Source File # Begin Source File SOURCE=.\src\map\amap\amapUniq.c # End Source File # End Group # Begin Group "cov" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\map\cov\cov.h # End Source File # Begin Source File SOURCE=.\src\map\cov\covBuild.c # End Source File # Begin Source File SOURCE=.\src\map\cov\covCore.c # End Source File # Begin Source File SOURCE=.\src\map\cov\covInt.h # End Source File # Begin Source File SOURCE=.\src\map\cov\covMan.c # End Source File # Begin Source File SOURCE=.\src\map\cov\covMinEsop.c # End Source File # Begin Source File SOURCE=.\src\map\cov\covMinMan.c # End Source File # Begin Source File SOURCE=.\src\map\cov\covMinSop.c # End Source File # Begin Source File SOURCE=.\src\map\cov\covMinUtil.c # End Source File # End Group # Begin Group "scl" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\map\scl\scl.c # End Source File # Begin Source File SOURCE=.\src\map\scl\scl.h # End Source File # Begin Source File SOURCE=.\src\map\scl\sclBuffer.c # End Source File # Begin Source File SOURCE=.\src\map\scl\sclBufSize.c # End Source File # Begin Source File SOURCE=.\src\map\scl\sclCon.h # End Source File # Begin Source File SOURCE=.\src\map\scl\sclDnsize.c # End Source File # Begin Source File SOURCE=.\src\map\scl\sclLib.h # End Source File # Begin Source File SOURCE=.\src\map\scl\sclLiberty.c # End Source File # Begin Source File SOURCE=.\src\map\scl\sclLibScl.c # End Source File # Begin Source File SOURCE=.\src\map\scl\sclLibUtil.c # End Source File # Begin Source File SOURCE=.\src\map\scl\sclLoad.c # End Source File # Begin Source File SOURCE=.\src\map\scl\sclSize.c # End Source File # Begin Source File SOURCE=.\src\map\scl\sclSize.h # End Source File # Begin Source File SOURCE=.\src\map\scl\sclTime.h # End Source File # Begin Source File SOURCE=.\src\map\scl\sclUpsize.c # End Source File # Begin Source File SOURCE=.\src\map\scl\sclUtil.c # End Source File # End Group # Begin Group "mpm" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\map\mpm\mpm.c # End Source File # Begin Source File SOURCE=.\src\map\mpm\mpm.h # End Source File # Begin Source File SOURCE=.\src\map\mpm\mpmAbc.c # End Source File # Begin Source File SOURCE=.\src\map\mpm\mpmCore.c # End Source File # Begin Source File SOURCE=.\src\map\mpm\mpmDsd.c # End Source File # Begin Source File SOURCE=.\src\map\mpm\mpmGates.c # End Source File # Begin Source File SOURCE=.\src\map\mpm\mpmInt.h # End Source File # Begin Source File SOURCE=.\src\map\mpm\mpmLib.c # End Source File # Begin Source File SOURCE=.\src\map\mpm\mpmMan.c # End Source File # Begin Source File SOURCE=.\src\map\mpm\mpmMap.c # End Source File # Begin Source File SOURCE=.\src\map\mpm\mpmMig.c # End Source File # Begin Source File SOURCE=.\src\map\mpm\mpmMig.h # End Source File # Begin Source File SOURCE=.\src\map\mpm\mpmPre.c # End Source File # Begin Source File SOURCE=.\src\map\mpm\mpmTruth.c # End Source File # Begin Source File SOURCE=.\src\map\mpm\mpmUtil.c # End Source File # End Group # End Group # Begin Group "misc" # PROP Default_Filter "" # Begin Group "extra" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\misc\extra\extra.h # End Source File # Begin Source File SOURCE=.\src\misc\extra\extraUtilBitMatrix.c # End Source File # Begin Source File 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 SOURCE=.\src\misc\extra\extraUtilDsd.c # End Source File # Begin Source File SOURCE=.\src\misc\extra\extraUtilEnum.c # End Source File # Begin Source File 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 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 SOURCE=.\src\misc\extra\extraUtilPrime.c # End Source File # Begin Source File SOURCE=.\src\misc\extra\extraUtilProgress.c # End Source File # Begin Source File SOURCE=.\src\misc\extra\extraUtilReader.c # End Source File # Begin Source File SOURCE=.\src\misc\extra\extraUtilSupp.c # End Source File # Begin Source File SOURCE=.\src\misc\extra\extraUtilTruth.c # End Source File # Begin Source File SOURCE=.\src\misc\extra\extraUtilUtil.c # End Source File # End Group # Begin Group "st" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\misc\st\st.c # End Source File # Begin Source File SOURCE=.\src\misc\st\st.h # End Source File # Begin Source File SOURCE=.\src\misc\st\stmm.c # End Source File # Begin Source File SOURCE=.\src\misc\st\stmm.h # End Source File # End Group # Begin Group "mvc" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\misc\mvc\mvc.c # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvc.h # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvcApi.c # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvcCompare.c # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvcContain.c # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvcCover.c # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvcCube.c # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvcDivide.c # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvcDivisor.c # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvcList.c # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvcLits.c # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvcMan.c # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvcOpAlg.c # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvcOpBool.c # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvcPrint.c # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvcSort.c # End Source File # Begin Source File SOURCE=.\src\misc\mvc\mvcUtils.c # End Source File # End Group # Begin Group "vec" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\misc\vec\vec.h # End Source File # Begin Source File SOURCE=.\src\misc\vec\vecAtt.h # End Source File # Begin Source File SOURCE=.\src\misc\vec\vecBit.h # End Source File # Begin Source File SOURCE=.\src\misc\vec\vecFlt.h # End Source File # Begin Source File SOURCE=.\src\misc\vec\vecHash.h # End Source File # Begin Source File SOURCE=.\src\misc\vec\vecHsh.h # End Source File # Begin Source File SOURCE=.\src\misc\vec\vecInt.h # End Source File # Begin Source File SOURCE=.\src\misc\vec\vecMem.h # End Source File # Begin Source File SOURCE=.\src\misc\vec\vecPtr.h # End Source File # Begin Source File SOURCE=.\src\misc\vec\vecQue.h # End Source File # Begin Source File SOURCE=.\src\misc\vec\vecSet.h # End Source File # Begin Source File SOURCE=.\src\misc\vec\vecStr.h # End Source File # Begin Source File SOURCE=.\src\misc\vec\vecVec.h # End Source File # Begin Source File SOURCE=.\src\misc\vec\vecWec.h # End Source File # Begin Source File SOURCE=.\src\misc\vec\vecWrd.h # End Source File # End Group # Begin Group "util" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\misc\util\abc_global.h # End Source File # Begin Source File SOURCE=.\src\misc\util\util_hack.h # End Source File # Begin Source File SOURCE=.\src\misc\util\utilBridge.c # End Source File # Begin Source File SOURCE=.\src\misc\util\utilBSet.c # End Source File # Begin Source File SOURCE=.\src\misc\util\utilCex.c # End Source File # Begin Source File SOURCE=.\src\misc\util\utilCex.h # End Source File # Begin Source File SOURCE=.\src\misc\util\utilColor.c # End Source File # Begin Source File SOURCE=.\src\misc\util\utilDouble.h # End Source File # Begin Source File SOURCE=.\src\misc\util\utilFile.c # End Source File # Begin Source File SOURCE=.\src\misc\util\utilFloat.h # End Source File # Begin Source File SOURCE=.\src\misc\util\utilIsop.c # End Source File # Begin Source File SOURCE=.\src\misc\util\utilMem.c # End Source File # Begin Source File SOURCE=.\src\misc\util\utilMem.h # End Source File # Begin Source File SOURCE=.\src\misc\util\utilNam.c # End Source File # Begin Source File SOURCE=.\src\misc\util\utilNam.h # End Source File # Begin Source File SOURCE=.\src\misc\util\utilPth.c # End Source File # Begin Source File SOURCE=.\src\misc\util\utilSignal.c # End Source File # Begin Source File SOURCE=.\src\misc\util\utilSignal.h # End Source File # Begin Source File SOURCE=.\src\misc\util\utilSort.c # End Source File # Begin Source File SOURCE=.\src\misc\util\utilTruth.h # End Source File # End Group # Begin Group "nm" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\misc\nm\nm.h # End Source File # Begin Source File SOURCE=.\src\misc\nm\nmApi.c # End Source File # Begin Source File SOURCE=.\src\misc\nm\nmInt.h # End Source File # Begin Source File SOURCE=.\src\misc\nm\nmTable.c # End Source File # End Group # Begin Group "hash" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\misc\hash\hash.h # End Source File # Begin Source File SOURCE=.\src\misc\hash\hashFlt.h # End Source File # Begin Source File SOURCE=.\src\misc\hash\hashInt.h # End Source File # Begin Source File SOURCE=.\src\misc\hash\hashPtr.h # End Source File # End Group # Begin Group "bzlib" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\misc\bzlib\blocksort.c # End Source File # Begin Source File SOURCE=.\src\misc\bzlib\bzlib.c # End Source File # Begin Source File SOURCE=.\src\misc\bzlib\bzlib.h # End Source File # Begin Source File SOURCE=.\src\misc\bzlib\bzlib_private.h # End Source File # Begin Source File SOURCE=.\src\misc\bzlib\compress.c # End Source File # Begin Source File SOURCE=.\src\misc\bzlib\crctable.c # End Source File # Begin Source File SOURCE=.\src\misc\bzlib\decompress.c # End Source File # Begin Source File SOURCE=.\src\misc\bzlib\huffman.c # End Source File # Begin Source File SOURCE=.\src\misc\bzlib\randtable.c # End Source File # End Group # Begin Group "zlib" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\misc\zlib\adler32.c # End Source File # Begin Source File SOURCE=.\src\misc\zlib\compress_.c # End Source File # Begin Source File SOURCE=.\src\misc\zlib\crc32.c # End Source File # Begin Source File SOURCE=.\src\misc\zlib\crc32.h # End Source File # Begin Source File SOURCE=.\src\misc\zlib\deflate.c # End Source File # Begin Source File SOURCE=.\src\misc\zlib\deflate.h # End Source File # Begin Source File SOURCE=.\src\misc\zlib\gzclose.c # End Source File # Begin Source File SOURCE=.\src\misc\zlib\gzguts.h # End Source File # Begin Source File SOURCE=.\src\misc\zlib\gzlib.c # End Source File # Begin Source File SOURCE=.\src\misc\zlib\gzread.c # End Source File # Begin Source File SOURCE=.\src\misc\zlib\gzwrite.c # End Source File # Begin Source File SOURCE=.\src\misc\zlib\infback.c # End Source File # Begin Source File SOURCE=.\src\misc\zlib\inffast.c # End Source File # Begin Source File SOURCE=.\src\misc\zlib\inffast.h # End Source File # Begin Source File SOURCE=.\src\misc\zlib\inffixed.h # End Source File # Begin Source File SOURCE=.\src\misc\zlib\inflate.c # End Source File # Begin Source File SOURCE=.\src\misc\zlib\inflate.h # End Source File # Begin Source File SOURCE=.\src\misc\zlib\inftrees.c # End Source File # Begin Source File SOURCE=.\src\misc\zlib\inftrees.h # End Source File # Begin Source File SOURCE=.\src\misc\zlib\trees.c # End Source File # Begin Source File SOURCE=.\src\misc\zlib\trees.h # End Source File # Begin Source File SOURCE=.\src\misc\zlib\uncompr.c # End Source File # Begin Source File SOURCE=.\src\misc\zlib\zconf.h # End Source File # Begin Source File SOURCE=.\src\misc\zlib\zlib.h # End Source File # Begin Source File SOURCE=.\src\misc\zlib\zutil.c # End Source File # Begin Source File SOURCE=.\src\misc\zlib\zutil.h # End Source File # End Group # Begin Group "bar" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\misc\bar\bar.c # End Source File # Begin Source File SOURCE=.\src\misc\bar\bar.h # End Source File # End Group # Begin Group "bbl" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\misc\bbl\bblif.c # End Source File # Begin Source File SOURCE=.\src\misc\bbl\bblif.h # End Source File # End Group # Begin Group "mem" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\misc\mem\mem.c # End Source File # Begin Source File SOURCE=.\src\misc\mem\mem.h # End Source File # Begin Source File SOURCE=.\src\misc\mem\mem2.h # End Source File # End Group # Begin Group "tim" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\misc\tim\tim.c # End Source File # Begin Source File SOURCE=.\src\misc\tim\tim.h # End Source File # Begin Source File SOURCE=.\src\misc\tim\timBox.c # End Source File # Begin Source File SOURCE=.\src\misc\tim\timDump.c # End Source File # Begin Source File SOURCE=.\src\misc\tim\timInt.h # End Source File # Begin Source File SOURCE=.\src\misc\tim\timMan.c # End Source File # Begin Source File SOURCE=.\src\misc\tim\timTime.c # End Source File # Begin Source File SOURCE=.\src\misc\tim\timTrav.c # End Source File # End Group # Begin Group "parse" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\misc\parse\parseEqn.c # End Source File # Begin Source File SOURCE=.\src\misc\parse\parseInt.h # End Source File # Begin Source File SOURCE=.\src\misc\parse\parseStack.c # End Source File # End Group # End Group # Begin Group "ai" # PROP Default_Filter "" # Begin Group "hop" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\aig\hop\hop.h # End Source File # Begin Source File SOURCE=.\src\aig\hop\hopBalance.c # End Source File # Begin Source File SOURCE=.\src\aig\hop\hopCheck.c # End Source File # Begin Source File SOURCE=.\src\aig\hop\hopDfs.c # End Source File # Begin Source File SOURCE=.\src\aig\hop\hopMan.c # End Source File # Begin Source File SOURCE=.\src\aig\hop\hopMem.c # End Source File # Begin Source File SOURCE=.\src\aig\hop\hopObj.c # End Source File # Begin Source File SOURCE=.\src\aig\hop\hopOper.c # End Source File # Begin Source File SOURCE=.\src\aig\hop\hopTable.c # End Source File # Begin Source File SOURCE=.\src\aig\hop\hopTruth.c # End Source File # Begin Source File SOURCE=.\src\aig\hop\hopUtil.c # End Source File # End Group # Begin Group "ivy" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\aig\ivy\ivy.h # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyBalance.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyCanon.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyCheck.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyCut.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyCutTrav.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyDfs.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyDsd.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyFanout.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyFastMap.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyFraig.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyHaig.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyMan.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyMem.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyMulti.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyObj.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyOper.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyResyn.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyRwr.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivySeq.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyShow.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyTable.c # End Source File # Begin Source File SOURCE=.\src\aig\ivy\ivyUtil.c # End Source File # End Group # Begin Group "ioa" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\aig\ioa\ioa.h # End Source File # Begin Source File SOURCE=.\src\aig\ioa\ioaReadAig.c # End Source File # Begin Source File SOURCE=.\src\aig\ioa\ioaUtil.c # End Source File # Begin Source File SOURCE=.\src\aig\ioa\ioaWriteAig.c # End Source File # End Group # Begin Group "aig" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\aig\aig\aig.h # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigCanon.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigCheck.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigCuts.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigDfs.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigDoms.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigDup.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigFact.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigFanout.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigFrames.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigInter.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigJust.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigMan.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigMem.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigMffc.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigObj.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigOper.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigOrder.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigPack.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigPart.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigPartReg.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigPartSat.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigRepr.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigRet.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigRetF.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigScl.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigShow.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigSplit.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigTable.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigTiming.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigTruth.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigTsim.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigUtil.c # End Source File # Begin Source File SOURCE=.\src\aig\aig\aigWin.c # End Source File # End Group # Begin Group "saig" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\aig\saig\saig.h # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigCone.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigConstr.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigConstr2.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigDual.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigDup.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigInd.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigIoa.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigIso.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigIsoFast.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigIsoSlow.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigMiter.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigOutDec.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigPhase.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigRetFwd.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigRetMin.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigRetStep.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigScl.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigSimFast.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigSimMv.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigSimSeq.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigStrSim.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigSwitch.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigSynch.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigTempor.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigTrans.c # End Source File # Begin Source File SOURCE=.\src\aig\saig\saigWnd.c # End Source File # End Group # Begin Group "gia" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\aig\gia\gia.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\gia.h # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaAig.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaAig.h # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaAiger.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaAigerExt.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaBalAig.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaBalLut.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaBalMap.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaBidec.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaBound.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaCCof.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaCex.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaClp.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaCof.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaCone.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaCSat.c # End Source File # Begin Source File 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 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 SOURCE=.\src\aig\gia\giaDup.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaEdge.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaEmbed.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaEnable.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaEquiv.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaEra.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaEra2.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaEsop.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaExist.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaFalse.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaFanout.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaForce.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaFrames.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaFront.c # End Source File # Begin Source File 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 SOURCE=.\src\aig\gia\giaGlitch.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaHash.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaIf.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaIff.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaIiff.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaIiff.h # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaIso.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaIso2.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaIso3.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaJf.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaKf.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaLf.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaMan.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaMem.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaMf.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaMfs.c # End Source File # Begin Source File 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\giaMulFind.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 SOURCE=.\src\aig\gia\giaOf.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaPack.c # End Source File # Begin Source File 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 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 SOURCE=.\src\aig\gia\giaRex.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaRrr.cpp # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaSat3.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaSatEdge.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaSatLE.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaSatLut.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaSatMap.c # End Source File # Begin Source File 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 SOURCE=.\src\aig\gia\giaScript.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaShow.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaShrink.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaShrink6.c # End Source File # Begin Source File 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 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 SOURCE=.\src\aig\gia\giaSpeedup.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaSplit.c # End Source File # Begin Source File 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 SOURCE=.\src\aig\gia\giaSupMin.c # End Source File # Begin Source File 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 SOURCE=.\src\aig\gia\giaSweeper.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaSwitch.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaTim.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaTis.c # End Source File # Begin Source File SOURCE=.\src\aig\gia\giaTruth.c # End Source File # Begin Source File 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 SOURCE=.\src\aig\gia\giaUtil.c # End Source File # End Group # Begin Group "miniaig" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\aig\miniaig\abcOper.h # End Source File # Begin Source File SOURCE=.\src\aig\miniaig\miniaig.h # End Source File # Begin Source File SOURCE=.\src\aig\miniaig\minilut.h # End Source File # Begin Source File SOURCE=.\src\aig\miniaig\ndr.h # End Source File # End Group # End Group # Begin Group "bool" # PROP Default_Filter "" # Begin Group "bdc" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bool\bdc\bdc.h # End Source File # Begin Source File SOURCE=.\src\bool\bdc\bdcCore.c # End Source File # Begin Source File SOURCE=.\src\bool\bdc\bdcDec.c # End Source File # Begin Source File SOURCE=.\src\bool\bdc\bdcInt.h # End Source File # Begin Source File SOURCE=.\src\bool\bdc\bdcSpfd.c # End Source File # Begin Source File SOURCE=.\src\bool\bdc\bdcTable.c # End Source File # End Group # Begin Group "dec" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bool\dec\dec.h # End Source File # Begin Source File SOURCE=.\src\bool\dec\decAbc.c # End Source File # Begin Source File SOURCE=.\src\bool\dec\decFactor.c # End Source File # Begin Source File SOURCE=.\src\bool\dec\decMan.c # End Source File # Begin Source File SOURCE=.\src\bool\dec\decPrint.c # End Source File # Begin Source File SOURCE=.\src\bool\dec\decUtil.c # End Source File # End Group # Begin Group "deco" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bool\deco\deco.h # End Source File # End Group # Begin Group "kit" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bool\kit\cloud.c # End Source File # Begin Source File SOURCE=.\src\bool\kit\cloud.h # End Source File # Begin Source File SOURCE=.\src\bool\kit\kit.h # End Source File # Begin Source File SOURCE=.\src\bool\kit\kitAig.c # End Source File # Begin Source File SOURCE=.\src\bool\kit\kitBdd.c # End Source File # Begin Source File SOURCE=.\src\bool\kit\kitCloud.c # End Source File # Begin Source File SOURCE=.\src\bool\kit\kitDec.c # End Source File # Begin Source File SOURCE=.\src\bool\kit\kitDsd.c # End Source File # Begin Source File SOURCE=.\src\bool\kit\kitFactor.c # End Source File # Begin Source File SOURCE=.\src\bool\kit\kitGraph.c # End Source File # Begin Source File SOURCE=.\src\bool\kit\kitHop.c # End Source File # Begin Source File SOURCE=.\src\bool\kit\kitIsop.c # End Source File # Begin Source File SOURCE=.\src\bool\kit\kitPerm.c # End Source File # Begin Source File SOURCE=.\src\bool\kit\kitPla.c # End Source File # Begin Source File SOURCE=.\src\bool\kit\kitSop.c # End Source File # Begin Source File SOURCE=.\src\bool\kit\kitTruth.c # End Source File # End Group # Begin Group "lucky" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bool\lucky\lucky.c # End Source File # Begin Source File SOURCE=.\src\bool\lucky\lucky.h # End Source File # Begin Source File SOURCE=.\src\bool\lucky\luckyFast16.c # End Source File # Begin Source File SOURCE=.\src\bool\lucky\luckyFast6.c # End Source File # Begin Source File SOURCE=.\src\bool\lucky\luckyInt.h # End Source File # Begin Source File SOURCE=.\src\bool\lucky\luckyRead.c # End Source File # Begin Source File SOURCE=.\src\bool\lucky\luckySimple.c # End Source File # Begin Source File SOURCE=.\src\bool\lucky\luckySwap.c # End Source File # Begin Source File SOURCE=.\src\bool\lucky\luckySwapIJ.c # End Source File # End Group # Begin Group "rsb" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bool\rsb\rsb.h # End Source File # Begin Source File SOURCE=.\src\bool\rsb\rsbDec6.c # End Source File # Begin Source File SOURCE=.\src\bool\rsb\rsbInt.h # End Source File # Begin Source File SOURCE=.\src\bool\rsb\rsbMan.c # End Source File # End Group # Begin Group "rpo" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\bool\rpo\literal.h # End Source File # Begin Source File SOURCE=.\src\bool\rpo\rpo.c # End Source File # Begin Source File SOURCE=.\src\bool\rpo\rpo.h # End Source File # End Group # End Group # Begin Group "prove" # PROP Default_Filter "" # Begin Group "cec" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\proof\cec\cec.h # End Source File # Begin Source File SOURCE=.\src\proof\cec\cecCec.c # End Source File # Begin Source File SOURCE=.\src\proof\cec\cecChoice.c # End Source File # Begin Source File SOURCE=.\src\proof\cec\cecClass.c # End Source File # Begin Source File SOURCE=.\src\proof\cec\cecCore.c # End Source File # Begin Source File SOURCE=.\src\proof\cec\cecCorr.c # End Source File # Begin Source File SOURCE=.\src\proof\cec\cecInt.h # End Source File # Begin Source File SOURCE=.\src\proof\cec\cecIso.c # End Source File # Begin Source File SOURCE=.\src\proof\cec\cecMan.c # End Source File # Begin Source File SOURCE=.\src\proof\cec\cecPat.c # End Source File # Begin Source File SOURCE=.\src\proof\cec\cecProve.c # End Source File # Begin Source File SOURCE=.\src\proof\cec\cecSat.c # End Source File # Begin Source File 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 SOURCE=.\src\proof\cec\cecSweep.c # End Source File # Begin Source File SOURCE=.\src\proof\cec\cecSynth.c # End Source File # End Group # Begin Group "dch" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\proof\dch\dch.h # End Source File # Begin Source File SOURCE=.\src\proof\dch\dchAig.c # End Source File # Begin Source File SOURCE=.\src\proof\dch\dchChoice.c # End Source File # Begin Source File SOURCE=.\src\proof\dch\dchClass.c # End Source File # Begin Source File SOURCE=.\src\proof\dch\dchCnf.c # End Source File # Begin Source File SOURCE=.\src\proof\dch\dchCore.c # End Source File # Begin Source File SOURCE=.\src\proof\dch\dchInt.h # End Source File # Begin Source File SOURCE=.\src\proof\dch\dchMan.c # End Source File # Begin Source File SOURCE=.\src\proof\dch\dchSat.c # End Source File # Begin Source File SOURCE=.\src\proof\dch\dchSim.c # End Source File # Begin Source File SOURCE=.\src\proof\dch\dchSimSat.c # End Source File # Begin Source File SOURCE=.\src\proof\dch\dchSweep.c # End Source File # End Group # Begin Group "fra" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\proof\fra\fra.h # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraBmc.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraCec.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraClass.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraClau.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraClaus.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraCnf.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraCore.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraHot.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraImp.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraInd.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraIndVer.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraLcr.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraMan.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraPart.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraSat.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraSec.c # End Source File # Begin Source File SOURCE=.\src\proof\fra\fraSim.c # End Source File # End Group # Begin Group "fraig" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\proof\fraig\fraig.h # End Source File # Begin Source File SOURCE=.\src\proof\fraig\fraigApi.c # End Source File # Begin Source File SOURCE=.\src\proof\fraig\fraigCanon.c # End Source File # Begin Source File SOURCE=.\src\proof\fraig\fraigChoice.c # End Source File # Begin Source File SOURCE=.\src\proof\fraig\fraigFanout.c # End Source File # Begin Source File SOURCE=.\src\proof\fraig\fraigFeed.c # End Source File # Begin Source File SOURCE=.\src\proof\fraig\fraigInt.h # End Source File # Begin Source File SOURCE=.\src\proof\fraig\fraigMan.c # End Source File # Begin Source File SOURCE=.\src\proof\fraig\fraigMem.c # End Source File # Begin Source File SOURCE=.\src\proof\fraig\fraigNode.c # End Source File # Begin Source File SOURCE=.\src\proof\fraig\fraigPrime.c # End Source File # Begin Source File SOURCE=.\src\proof\fraig\fraigSat.c # End Source File # Begin Source File SOURCE=.\src\proof\fraig\fraigTable.c # End Source File # Begin Source File SOURCE=.\src\proof\fraig\fraigUtil.c # End Source File # Begin Source File SOURCE=.\src\proof\fraig\fraigVec.c # End Source File # End Group # Begin Group "int" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\proof\int\int.h # End Source File # Begin Source File SOURCE=.\src\proof\int\intCheck.c # End Source File # Begin Source File SOURCE=.\src\proof\int\intContain.c # End Source File # Begin Source File SOURCE=.\src\proof\int\intCore.c # End Source File # Begin Source File SOURCE=.\src\proof\int\intCtrex.c # End Source File # Begin Source File SOURCE=.\src\proof\int\intDup.c # End Source File # Begin Source File SOURCE=.\src\proof\int\intFrames.c # End Source File # Begin Source File SOURCE=.\src\proof\int\intInt.h # End Source File # Begin Source File SOURCE=.\src\proof\int\intInter.c # End Source File # Begin Source File SOURCE=.\src\proof\int\intM114.c # End Source File # Begin Source File SOURCE=.\src\proof\int\intMan.c # End Source File # Begin Source File SOURCE=.\src\proof\int\intUtil.c # End Source File # End Group # Begin Group "live" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\proof\live\arenaViolation.c # End Source File # Begin Source File SOURCE=.\src\proof\live\combination.c # End Source File # Begin Source File SOURCE=.\src\proof\live\disjunctiveMonotone.c # End Source File # Begin Source File SOURCE=.\src\proof\live\kLiveConstraints.c # End Source File # Begin Source File SOURCE=.\src\proof\live\kliveness.c # End Source File # Begin Source File SOURCE=.\src\proof\live\liveness.c # End Source File # Begin Source File SOURCE=.\src\proof\live\liveness_sim.c # End Source File # Begin Source File SOURCE=.\src\proof\live\ltl_parser.c # End Source File # Begin Source File SOURCE=.\src\proof\live\monotone.c # End Source File # End Group # Begin Group "pdr" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\proof\pdr\pdr.h # End Source File # Begin Source File SOURCE=.\src\proof\pdr\pdrClass.c # End Source File # Begin Source File SOURCE=.\src\proof\pdr\pdrCnf.c # End Source File # Begin Source File SOURCE=.\src\proof\pdr\pdrCore.c # End Source File # Begin Source File SOURCE=.\src\proof\pdr\pdrIncr.c # End Source File # Begin Source File SOURCE=.\src\proof\pdr\pdrInt.h # End Source File # Begin Source File SOURCE=.\src\proof\pdr\pdrInv.c # End Source File # Begin Source File SOURCE=.\src\proof\pdr\pdrMan.c # End Source File # Begin Source File SOURCE=.\src\proof\pdr\pdrSat.c # End Source File # Begin Source File SOURCE=.\src\proof\pdr\pdrTsim.c # End Source File # Begin Source File SOURCE=.\src\proof\pdr\pdrTsim2.c # End Source File # Begin Source File SOURCE=.\src\proof\pdr\pdrTsim3.c # End Source File # Begin Source File SOURCE=.\src\proof\pdr\pdrUtil.c # End Source File # End Group # Begin Group "ssw" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\proof\ssw\ssw.h # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswAig.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswBmc.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswClass.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswCnf.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswConstr.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswCore.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswDyn.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswFilter.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswInt.h # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswIslands.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswLcorr.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswMan.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswPairs.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswPart.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswRarity.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswRarity2.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswSat.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswSemi.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswSim.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswSimSat.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswSweep.c # End Source File # Begin Source File SOURCE=.\src\proof\ssw\sswUnique.c # End Source File # End Group # Begin Group "abs" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\proof\abs\abs.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\abs.h # End Source File # Begin Source File SOURCE=.\src\proof\abs\absDup.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\absGla.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\absGlaOld.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\absIter.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\absOldCex.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\absOldRef.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\absOldSat.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\absOldSim.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\absOut.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\absPth.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\absRef.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\absRef.h # End Source File # Begin Source File SOURCE=.\src\proof\abs\absRefSelect.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\absRpm.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\absRpmOld.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\absUtil.c # End Source File # Begin Source File SOURCE=.\src\proof\abs\absVta.c # End Source File # End Group # Begin Group "ssc" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\proof\ssc\ssc.h # End Source File # Begin Source File SOURCE=.\src\proof\ssc\sscClass.c # End Source File # Begin Source File SOURCE=.\src\proof\ssc\sscCore.c # End Source File # Begin Source File SOURCE=.\src\proof\ssc\sscInt.h # End Source File # Begin Source File SOURCE=.\src\proof\ssc\sscSat.c # End Source File # Begin Source File SOURCE=.\src\proof\ssc\sscSim.c # End Source File # Begin Source File SOURCE=.\src\proof\ssc\sscUtil.c # End Source File # End Group # Begin Group "int2" # PROP Default_Filter "" # End Group # Begin Group "acec" # PROP Default_Filter "" # Begin Source File SOURCE=.\src\proof\acec\acec.h # End Source File # Begin Source File SOURCE=.\src\proof\acec\acec2Mult.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecBo.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecCl.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecCo.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecCore.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecCover.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecFadds.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecInt.h # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecMult.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecNorm.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecOrder.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecPa.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecPo.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecPolyn.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecPool.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecRe.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecSt.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecStruct.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecTree.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecUtil.c # End Source File # Begin Source File SOURCE=.\src\proof\acec\acecXor.c # End Source File # End Group # End Group # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # End Target # End Project abc-0.52/abcspace.dsw000066400000000000000000000014511477524141600144610ustar00rootroot00000000000000Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "abcexe"=.\abcexe.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ Begin Project Dependency Project_Dep_Name abclib End Project Dependency }}} ############################################################################### Project: "abclib"=.\abclib.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### abc-0.52/arch_flags.c000066400000000000000000000005431477524141600144370ustar00rootroot00000000000000#include int main() { if (sizeof(void*) == 8) // Assume 64-bit Linux if pointers are 8 bytes. printf("-DLIN64 "); else printf("-DLIN "); printf("-DSIZEOF_VOID_P=%d -DSIZEOF_LONG=%d -DSIZEOF_INT=%d\n", (int)sizeof(void*), (int)sizeof(long), (int)sizeof(int) ); return 0; } abc-0.52/copyright.txt000066400000000000000000000021511477524141600147500ustar00rootroot00000000000000ABC: System for Sequential Synthesis and Verification http://www.eecs.berkeley.edu/~alanmi/abc/ Copyright (c) The Regents of the University of California. All rights reserved. Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. abc-0.52/depends.sh000077500000000000000000000003531477524141600141620ustar00rootroot00000000000000#!/bin/sh #echo "## Got: $*" CC="$1" DIR="$2" shift 2 case "$DIR" in "" | ".") $CC -MM -MG "$@" | sed -e 's@^\(.*\)\.o:@\1.d \1.o:@' ;; *) $CC -MM -MG "$@" | sed -e "s@^\(.*\)\.o:@$DIR/\1.d $DIR/\1.o:@" ;; esac abc-0.52/i10.aig000066400000000000000000000345501477524141600132620ustar00rootroot00000000000000aig 2932 257 0 224 2675 886 1864 2106 2108 2155 2164 2389 2491 2509 2461 2754 2787 2789 2817 2821 2834 2864 2866 2868 2870 2872 2912 2958 3004 3056 3108 3160 3214 3262 3303 3325 3349 3417 3487 3557 3651 3745 3841 3873 67 3876 3887 3897 3907 3917 3940 3948 2784 3962 3955 93 766 578 4068 2126 4072 2124 4082 4084 4086 4088 2128 2116 4233 4234 555 4243 4255 4276 4298 3261 3213 3159 3107 3055 3003 2957 2911 979 1367 1199 1319 2355 2279 2317 3393 3461 3531 3639 3733 3829 887 4300 4330 2136 2120 4332 4334 4336 2118 4338 4340 4342 4344 4381 4437 4449 4461 4473 4485 4497 4512 317 4516 4546 4554 4564 4574 2122 4595 2132 4596 4598 4600 2134 4604 4611 4613 4635 4651 4667 4672 4683 45 4699 353 4755 4779 4799 4735 4802 4808 4823 4841 5120 5266 5279 5295 5301 5311 5364 383 5367 5399 5411 5423 5435 5447 5459 5477 2178 5487 5492 4209 5499 2505 5503 5517 413 5527 5537 5547 5557 5567 5577 5587 5597 5607 5617 5627 5637 5647 5653 5662 385 423 81 5671 5677 5683 5689 5693 5697 4895 4933 4983 5021 5065 5103 4846 5161 5175 5201 5215 5235 5249 4861 5131 5141 5717 5735 5755 5773 5785 5795 5805 5813 5821 5827 5833 5843 5851 5859 5865 —1––•›Ÿ£Ú¡Üâä«æì  !·Uœ»¹ ©ËÑÄXÄʰÐÎØÎÚØÜÂâÞãìâîçü€ƒj礥َ‘r—0––• ì˨/‘æ)2:7!-•2€M=! X*©‹ÈÃ^Žj™©ñÔ¬²àëý6¸ðïïóûÃþý ÄÌÃÐýŠþô  £à>üæ¤ žÃË8¾„ƒÓ9Æ‹,E%À‹Õí˜Ù rˆÄ½†è¿ÅÖ—æ÷æûæÿô  ƒù')³Çˆ¸®‹û*ÖÇ[`bäc·ý·ÅR[c Yg\êøôü82 4þ€‹  !#229;ÃÄ¥ªVXWXVV¾ ¾ÉÌÍ$¹ÔËÚÛÖ†‡D‘Ãæ–ªéݲ£Ý·¼¾è¿’––šš•²™  ™3Î4  ßàÁÆ ‚ ‚„„ÔÕttþÿ ‰ÁÞŽ¨áÕª›Õ¯´¶ê·Ñר­Ö¬®¯¹Å޾¬‘…ÚË…ßäææç½øˆU¬6Ñâ”A”—B—í﫩ǵüËc®dÐЗdýÄÅ©#ÌÿÒÓ<²³8“‘óÍÀ÷ûò?¼B¼88€((Þß ÇÅ÷uìE<Dòó«©åüˆÿD мI¼¿J¿•—ÕÓý§¤UÖÈ\††Ï\­ìíáô¯úû<ÚÛ8½»­»è±éš?öBö88¨©((†‡ ñï¯e”E<Dš›ÕÓ €ˆ©DìOšìŸñÔš¤ú¸ ¸ ‚@ƒ@ aÙd×¥ë¨éÕ Ð¤:¥:éåìã­¯°­ñAô?÷ þÆ4Ç4ðIñKþ3ÿ5ÔíÕï™ ¬Ñå§wmM- ø#ù%¢7£9°'±)†Ñ‡ÓË À õ¥ø£Í÷Ðõ—»š¹Ë]Î[í ä íÏðÍšȟå’ãÇƅ ˆÝP‚ŒÞ Œ«”å몪ô?õAž}Ÿ¬a­c‚çƒéÇ Â–9—;ÀqÁsÎQÏS¤Ù¥Ûé ð¸3¹5âeãgðAñCÆùÇû‹  žÁÿ ŸwmM- ¬Ò ”­×¬°,œÂ„ܼ&À$æ*„½ê,®À ênõöÞß°®®ƒúï › ߺÃÛÑ»çÉýü…§‹…« “‹ »ý¹ïÍ }£ óÑ¿‰ Í—   ¿ ¥” Ä — ° à Ñ ‹  ˆ ¼’ ” ð ô ö Ô÷ å £º ê Ž½ Ö † ÷ ± ³ ® º¸ º – š œ Ò ‹ §à ’ã ü ¬  × Ù Ô ¾Þ à ¼ À  Öà s¦M)¸ÊÆÄÂÆÌÒØ±Ì´¯ 䬫 6¯ßÙœ»œ Œð ðØ ‰Ä Á ŒÅ ëª âË ª ÒÅ Û ³ šéä Š¡Å5Ú œè¤ý ¤²¦Q¬   aw ¯Må7ç0ª¬Ä¨ó Öö Öñ â ô â “ Ä– ÄÚÆ Ö¢ „ è ¸œ”«ÄØ“zØÁˆUîùêåÔøÛØ× ‘,¢£•˜ Ÿ¢Îγ¶µ¸úûñô€€0’…øÐÖ}¨‹©n£ð¾Ú«ùºÙƒäÕ —‘‘éÿ•·Øâ™™¼ÒØÃÛÙ§‚ ðΊ¶ý¸ŽG¾lôéäôåï ΠЗší‡ï´Ú®âœàϯ Š…ø­ƒ‹ ³… »ß ãåßÍ…½¢½É’°•ÝͱŒçìîÞïëõéåÊå˺경…õÙ´µ¯ º–šœà™£‹“ø“Í蘴볣‡âãÞ èÄÈÊâËÇщÁ¦Áϖƶ™áѵ‘‹Í‹Ž›œ øüþäÿû…õÚõÑÊú¸Í•…éÄſ˿ÂÏÐ ¬°²æ³¯¹‡©Ž©Óþ®ºÉ¹øùóÉóöƒ„ à俨çãíÝÂÝղ⼵ýíѬ­¨Ì©Ç©¹º –šœÚ™×â’¾å­àÜÝØÊÙÁÙéê ÆÊÌÜÍÉÇO‘øÊÙ½ïÒâæâG£ˆâêI ä ¼ ôþÿ # ñâ Š.-”“‘8;1“¡è˜Œë„´¥ßáÜÈÝ¿Ýíî ÊÎÐÐÑ–ÎrqŒÌÕÓ|uן¬ÜŠ¯Èøé£¥ Æ¡½¡±² Ž’”Εڒ¶µÐÈœ™—ÂÅ»ò¢ˆõ޾¯éëæÄç»ç÷ø ÔØÚÌÛ Øüû” ÊâÝÛˆ‹»õô–‹® Æøþ÷õ¤§ý›Ò‚†ÕñÚ— ¨ü Ö×ÒÂÓÉÓãä ÀÄÆÊÇŒÄèçA™óÒôéŠ ÈÖÜÓÑ‚…ûÛ™°à„³ûë϶õþ†Ú ´µ°À±Ç±Á ž¢¤È¥ê¢ÆÅA÷ñ°ÒÇè ݶ¼±¯âåÛ»—À‚“Û˯”ÕÞæº ”•Ƒő¡¢ þ‚„Æ…Ê‚¦¥A×ï²§½ ËÀ ɺ½³ŸÌ¢ÆÅ ó„Þàã¹ ¯ ¾ ­Á ¯Æ ­É ¯!Î ­%¡¼ Ñ ¯ ¦à©ñº¯ ß ìÅíÇœ•½ÀœÁ¢þ ßü· ÉÖ–©Žþ Ó‰è ðì¥î ô´ ôø £‘ ù£á€ œ ‡£¼¤Ž‹Åùõ –Ú²œÜïÔ )³ [®óÜ´ÕÖÁŸÇàÝà¦âäT‡<¾êÄÇ òòÉÏŽÆŠüžŠ ÏÝ̰²µ´·º³·ážá¬ ÕÏÌçç–.ÞÜ±Ì Ã¨     Ë Æ öÅ ½ Ì—æàÄ£À© Ò¾ šë® è EæÌ Q‡Ð®³ìÒ ëô Ð ëæà¸ùµsŠ“ Õ„ÉÏœ’ dß1Ó ¡!ëšæ¼º Ç‚!Ûê‹ °ñ"ñ¶˜½! Õ!À˜Í!ŠÐÜ æ à Ζž®ÌÞ!• öò ™â §æƒ‹ãƒ“ºêÖ¾  ¯ü8˜–ü¡ˆ ¯³õ Ž ÖÚñŽ Å!­!Í!Ë!¨ Œ "º!"$Š ').¼!.0ˆ 35:¾!:<† ?AFÀ!FH„ KMR¢!R˜å ‡“ª•Ì€#õ‚®â š°N€äÿ 軌®õ â Í«îæ‡#âÍõ¼­#ìí Þ·#ìš#öæ¸ã"Ê"é"è"À#òç Ð"ÅŽ¨â"Væ"Tž¶Ì!‰¥Ð!È‹ËÈ!Æ!Æ!Æ!î 4â!è"ã!ë"B¯"ä"Ì!ô!Ì!ø!Ç!Ê!Ú!„"Ú!ˆ"½Ñàæ!ùžÂýȤî!±ó!²§$ó!¦"Ф Ùùö!±Ý€"É$Ó$&°×ÌФööÀ$ ©×"›¿³“óÓ©ïÀ³í᫹ë)Â.‘£ŸÍÿ=ä‚’#Û" é˜# !Íì‡ò´žŽù#ü#³!€ ›ê °î£ß¶ì©å»‰¯ìÀ¾»ËýÇ“ÄÓ…Ï‘ËÜ Ü¼×ç™ã‘àï¡ëçø©ó•ïÿ²%'GIŽº‰™Ë•’¡Ó™ªÛ¥—¡±ä´¸¯¿ñ»¸ÇùË¿ÐË™Ç׊%'à¶Ûëç‹äó¥ï‰ëü­÷›óƒ¶†À‘Ã•Š™Ë•‡‘¢Ó™©Ü%'QS©«¼êŠ¿çÆè”Éå—  âúÕ‘çëÜ—ðøãŸõéê¥ !#Šöý¹ç„¿˜ô‹Çå’Í ¬òŸÛ±ã¦áºð­é¿á´ï !#IK–ܨ&Á µÚ$¬&Ö°&Ò‘•œ¿½ ¨Ò€‹Ê$ß™)åÀ&(ë&´é&˜(Ä&TÆ&á$… » › Ë)éþÍ„ Ó Ž é Ê•Â%Ü-ß$´ º ç%ýÞ(üÜÑÝ%Ë'†' º „' þ( ‚'%',€),&€'138‚)82þ&=?D„)D>ü&IKPæ(Pö$»×ú Ê'÷'…ü ¶&Ô'dº%¦•설Æ&Ó)Ï&‘ê*í&á'¸ò&î&ø ‚ é'Ø(¢%å¢%¥%„¥%¬%ç¬%¯%‚¯%æÏµ%º%ûº% Ÿ¿%Ä%ýÄ%„„ˆ+Ä$Ç‹+Ú¸’+ˆ•+¾Þœ+ÂÝŸ+”’¦+‚§©+ÚÖ°+Àó³+žœº+þ¿½+¼ˆÄ+¼‹Ç+èæÎ+ôÝÑ+’ÆØ+¬¯Û+º!¨ â+VÍÇ&½™)Œï)– € ù(‚݈¬ ÷(” õ(š Œó(ñ(ö¹Ó'Âþ“¦)€ ¼ ß(œ*Й'è(Â(³ Ú µ º» Û —á½ ý(€)Ê ¦«ßÑ ž,œ,œ,œ,œ,œ,ƒ++š,¨,¨,±,¯,˜,²,¹,·,(–,¼,Ç,Å,2”,É,Ç,Î, Ù,×,Ö, ×, · ï º í Ä Ä!†++‹+Î Â!“+‘+˜+Ÿ++ +¡+ i0 V32(0) i1 V32(1) i2 V32(2) i3 V32(3) i4 V56(0) i5 V289(0) i6 V10(0) i7 V13(0) i8 V35(0) i9 V203(0) i10 V288(6) i11 V288(7) i12 V248(0) i13 V249(0) i14 V62(0) i15 V59(0) i16 V174(0) i17 V215(0) i18 V66(0) i19 V70(0) i20 V43(0) i21 V214(0) i22 V37(0) i23 V271(0) i24 V40(0) i25 V45(0) i26 V149(7) i27 V149(6) i28 V149(5) i29 V149(4) i30 V1(0) i31 V7(0) i32 V34(0) i33 V243(0) i34 V244(0) i35 V245(0) i36 V246(0) i37 V247(0) i38 V293(0) i39 V302(0) i40 V270(0) i41 V269(0) i42 V274(0) i43 V202(0) i44 V275(0) i45 V257(7) i46 V257(5) i47 V257(3) i48 V257(1) i49 V257(2) i50 V257(4) i51 V257(6) i52 V9(0) i53 V149(0) i54 V149(1) i55 V149(2) i56 V149(3) i57 V169(1) i58 V165(0) i59 V165(2) i60 V165(4) i61 V165(5) i62 V165(6) i63 V165(7) i64 V165(1) i65 V88(2) i66 V88(3) i67 V55(0) i68 V169(0) i69 V52(0) i70 V5(0) i71 V6(0) i72 V12(0) i73 V11(0) i74 V4(0) i75 V165(3) i76 V51(0) i77 V65(0) i78 V290(0) i79 V279(0) i80 V280(0) i81 V288(4) i82 V288(2) i83 V288(0) i84 V258(0) i85 V229(5) i86 V229(4) i87 V229(3) i88 V229(2) i89 V229(1) i90 V229(0) i91 V223(5) i92 V223(4) i93 V223(3) i94 V223(2) i95 V223(1) i96 V223(0) i97 V189(5) i98 V189(4) i99 V189(3) i100 V189(2) i101 V189(1) i102 V189(0) i103 V183(5) i104 V183(4) i105 V183(3) i106 V183(2) i107 V183(1) i108 V183(0) i109 V239(4) i110 V239(3) i111 V239(2) i112 V239(1) i113 V239(0) i114 V234(4) i115 V234(3) i116 V234(2) i117 V234(1) i118 V234(0) i119 V199(4) i120 V199(3) i121 V199(2) i122 V199(1) i123 V199(0) i124 V194(4) i125 V194(3) i126 V194(2) i127 V194(1) i128 V194(0) i129 V257(0) i130 V32(8) i131 V32(7) i132 V32(6) i133 V32(5) i134 V32(4) i135 V32(11) i136 V32(10) i137 V32(9) i138 V88(1) i139 V88(0) i140 V84(5) i141 V84(4) i142 V84(3) i143 V84(2) i144 V84(1) i145 V84(0) i146 V78(5) i147 V78(4) i148 V2(0) i149 V3(0) i150 V14(0) i151 V213(0) i152 V213(5) i153 V213(4) i154 V213(3) i155 V213(2) i156 V213(1) i157 V268(5) i158 V268(3) i159 V268(1) i160 V268(2) i161 V268(4) i162 V8(0) i163 V60(0) i164 V53(0) i165 V57(0) i166 V109(0) i167 V277(0) i168 V278(0) i169 V259(0) i170 V260(0) i171 V67(0) i172 V68(0) i173 V69(0) i174 V216(0) i175 V175(0) i176 V177(0) i177 V172(0) i178 V171(0) i179 V50(0) i180 V63(0) i181 V71(0) i182 V292(0) i183 V291(0) i184 V91(0) i185 V91(1) i186 V294(0) i187 V207(0) i188 V295(0) i189 V204(0) i190 V205(0) i191 V261(0) i192 V262(0) i193 V100(0) i194 V100(5) i195 V100(4) i196 V100(3) i197 V100(2) i198 V100(1) i199 V240(0) i200 V242(0) i201 V241(0) i202 V33(0) i203 V16(0) i204 V15(0) i205 V101(0) i206 V268(0) i207 V288(1) i208 V288(3) i209 V288(5) i210 V301(0) i211 V108(0) i212 V108(1) i213 V108(2) i214 V108(3) i215 V108(4) i216 V108(5) i217 V124(5) i218 V124(4) i219 V124(3) i220 V124(2) i221 V124(1) i222 V124(0) i223 V132(7) i224 V132(6) i225 V132(5) i226 V132(4) i227 V132(3) i228 V132(2) i229 V132(1) i230 V132(0) i231 V118(5) i232 V118(4) i233 V118(3) i234 V118(2) i235 V118(1) i236 V118(0) i237 V118(7) i238 V118(6) i239 V46(0) i240 V48(0) i241 V102(0) i242 V110(0) i243 V134(1) i244 V134(0) i245 V272(0) i246 V78(2) i247 V78(3) i248 V39(0) i249 V38(0) i250 V42(0) i251 V44(0) i252 V41(0) i253 V78(1) i254 V78(0) i255 V94(0) i256 V94(1) o0 V321(2) o1 V356 o2 V357 o3 V373 o4 V375(0) o5 V377 o6 V393(0) o7 V398(0) o8 V410(0) o9 V423(0) o10 V432 o11 V435(0) o12 V500(0) o13 V508(0) o14 V511(0) o15 V512 o16 V527 o17 V537 o18 V538 o19 V539 o20 V540 o21 V541 o22 V542 o23 V543 o24 V544 o25 V545 o26 V546 o27 V547 o28 V548 o29 V572(9) o30 V572(8) o31 V572(7) o32 V572(6) o33 V572(5) o34 V572(4) o35 V572(3) o36 V572(2) o37 V572(1) o38 V572(0) o39 V585(0) o40 V587 o41 V591(0) o42 V597(0) o43 V603(0) o44 V609(0) o45 V620 o46 V621 o47 V630 o48 V634(0) o49 V640(0) o50 V657 o51 V707 o52 V763 o53 V775 o54 V778 o55 V779 o56 V780 o57 V781 o58 V782 o59 V783 o60 V784 o61 V787 o62 V789 o63 V798(0) o64 V801 o65 V802(0) o66 V821(0) o67 V826(0) o68 V966 o69 V986 o70 V1213(11) o71 V1213(10) o72 V1213(9) o73 V1213(8) o74 V1213(7) o75 V1213(6) o76 V1213(5) o77 V1213(4) o78 V1213(3) o79 V1213(2) o80 V1213(1) o81 V1213(0) o82 V1243(9) o83 V1243(8) o84 V1243(7) o85 V1243(6) o86 V1243(5) o87 V1243(4) o88 V1243(3) o89 V1243(2) o90 V1243(1) o91 V1243(0) o92 V1256 o93 V1257 o94 V1258 o95 V1259 o96 V1260 o97 V1261 o98 V1262 o99 V1263 o100 V1264 o101 V1265 o102 V1266 o103 V1267 o104 V1274(0) o105 V1281(0) o106 V1297(4) o107 V1297(3) o108 V1297(2) o109 V1297(1) o110 V1297(0) o111 V1365 o112 V1375 o113 V1378 o114 V1380 o115 V1382 o116 V1384 o117 V1386 o118 V1387 o119 V1392(0) o120 V1423 o121 V1426 o122 V1428 o123 V1429 o124 V1431 o125 V1432 o126 V1439(0) o127 V1440(0) o128 V1451(0) o129 V1459(0) o130 V1467(0) o131 V1470 o132 V1480(0) o133 V1481(0) o134 V1492(0) o135 V1495(0) o136 V1512(3) o137 V1512(2) o138 V1512(1) o139 V1536(0) o140 V1537 o141 V1539 o142 V1552(1) o143 V1552(0) o144 V1613(0) o145 V1613(1) o146 V1620(0) o147 V1629(0) o148 V1645(0) o149 V1652(0) o150 V1669 o151 V1671(0) o152 V1679(0) o153 V1693(0) o154 V1709(4) o155 V1709(3) o156 V1709(2) o157 V1709(1) o158 V1709(0) o159 V1717(0) o160 V1719 o161 V1726(0) o162 V1736 o163 V1741(0) o164 V1745(0) o165 V1757(0) o166 V1758(0) o167 V1759(0) o168 V1760(0) o169 V1771(1) o170 V1771(0) o171 V1781(1) o172 V1781(0) o173 V1829(9) o174 V1829(8) o175 V1829(7) o176 V1829(6) o177 V1829(5) o178 V1829(4) o179 V1829(3) o180 V1829(2) o181 V1829(1) o182 V1829(0) o183 V1832 o184 V1833(0) o185 V1863(0) o186 V1864(0) o187 V1896(0) o188 V1897(0) o189 V1898(0) o190 V1899(0) o191 V1900(0) o192 V1901(0) o193 V1921(5) o194 V1921(4) o195 V1921(3) o196 V1921(2) o197 V1921(1) o198 V1921(0) o199 V1953(1) o200 V1953(7) o201 V1953(6) o202 V1953(5) o203 V1953(4) o204 V1953(3) o205 V1953(2) o206 V1953(0) o207 V1960(1) o208 V1960(0) o209 V1968(0) o210 V1992(1) o211 V1992(0) o212 V650 o213 V651 o214 V652 o215 V653 o216 V654 o217 V655 o218 V656 o219 V1370 o220 V1371 o221 V1372 o222 V1373 o223 V1374 c i10 This file was written by ABC on Sat Mar 12 12:08:09 2011 For information about AIGER format, refer to http://fmv.jku.at/aiger abc-0.52/lib/000077500000000000000000000000001477524141600127465ustar00rootroot00000000000000abc-0.52/lib/pthread.h000066400000000000000000001215561477524141600145600ustar00rootroot00000000000000/* This is an implementation of the threads API of POSIX 1003.1-2001. * * -------------------------------------------------------------------------- * * Pthreads-win32 - POSIX Threads Library for Win32 * Copyright(C) 1998 John E. Bossom * Copyright(C) 1999,2005 Pthreads-win32 contributors * * Contact Email: rpj@callisto.canberra.edu.au * * The current list of contributors is contained * in the file CONTRIBUTORS included with the source * code distribution. The list can also be seen at the * following World Wide Web location: * http://sources.redhat.com/pthreads-win32/contributors.html * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library in the file COPYING.LIB; * if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined( PTHREAD_H ) #define PTHREAD_H /* * See the README file for an explanation of the pthreads-win32 version * numbering scheme and how the DLL is named etc. */ #define PTW32_VERSION 2,8,0,0 #define PTW32_VERSION_STRING "2, 8, 0, 0\0" /* There are three implementations of cancel cleanup. * Note that pthread.h is included in both application * compilation units and also internally for the library. * The code here and within the library aims to work * for all reasonable combinations of environments. * * The three implementations are: * * WIN32 SEH * C * C++ * * Please note that exiting a push/pop block via * "return", "exit", "break", or "continue" will * lead to different behaviour amongst applications * depending upon whether the library was built * using SEH, C++, or C. For example, a library built * with SEH will call the cleanup routine, while both * C++ and C built versions will not. */ /* * Define defaults for cleanup code. * Note: Unless the build explicitly defines one of the following, then * we default to standard C style cleanup. This style uses setjmp/longjmp * in the cancelation and thread exit implementations and therefore won't * do stack unwinding if linked to applications that have it (e.g. * C++ apps). This is currently consistent with most/all commercial Unix * POSIX threads implementations. */ #if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) # define __CLEANUP_C #endif #if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) #error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. #endif /* * Stop here if we are being included by the resource compiler. */ #ifndef RC_INVOKED #undef PTW32_LEVEL #if defined(_POSIX_SOURCE) #define PTW32_LEVEL 0 /* Early POSIX */ #endif #if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 #undef PTW32_LEVEL #define PTW32_LEVEL 1 /* Include 1b, 1c and 1d */ #endif #if defined(INCLUDE_NP) #undef PTW32_LEVEL #define PTW32_LEVEL 2 /* Include Non-Portable extensions */ #endif #define PTW32_LEVEL_MAX 3 #if !defined(PTW32_LEVEL) #define PTW32_LEVEL PTW32_LEVEL_MAX /* Include everything */ #endif #ifdef _UWIN # define HAVE_STRUCT_TIMESPEC 1 # define HAVE_SIGNAL_H 1 # undef HAVE_CONFIG_H # pragma comment(lib, "pthread") #endif /* * ------------------------------------------------------------- * * * Module: pthread.h * * Purpose: * Provides an implementation of PThreads based upon the * standard: * * POSIX 1003.1-2001 * and * The Single Unix Specification version 3 * * (these two are equivalent) * * in order to enhance code portability between Windows, * various commercial Unix implementations, and Linux. * * See the ANNOUNCE file for a full list of conforming * routines and defined constants, and a list of missing * routines and constants not defined in this implementation. * * Authors: * There have been many contributors to this library. * The initial implementation was contributed by * John Bossom, and several others have provided major * sections or revisions of parts of the implementation. * Often significant effort has been contributed to * find and fix important bugs and other problems to * improve the reliability of the library, which sometimes * is not reflected in the amount of code which changed as * result. * As much as possible, the contributors are acknowledged * in the ChangeLog file in the source code distribution * where their changes are noted in detail. * * Contributors are listed in the CONTRIBUTORS file. * * As usual, all bouquets go to the contributors, and all * brickbats go to the project maintainer. * * Maintainer: * The code base for this project is coordinated and * eventually pre-tested, packaged, and made available by * * Ross Johnson * * QA Testers: * Ultimately, the library is tested in the real world by * a host of competent and demanding scientists and * engineers who report bugs and/or provide solutions * which are then fixed or incorporated into subsequent * versions of the library. Each time a bug is fixed, a * test case is written to prove the fix and ensure * that later changes to the code don't reintroduce the * same error. The number of test cases is slowly growing * and therefore so is the code reliability. * * Compliance: * See the file ANNOUNCE for the list of implemented * and not-implemented routines and defined options. * Of course, these are all defined is this file as well. * * Web site: * The source code and other information about this library * are available from * * http://sources.redhat.com/pthreads-win32/ * * ------------------------------------------------------------- */ /* Try to avoid including windows.h */ #if defined(__MINGW32__) && defined(__cplusplus) #define PTW32_INCLUDE_WINDOWS_H #endif #ifdef PTW32_INCLUDE_WINDOWS_H #include #endif #if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) /* * VC++6.0 or early compiler's header has no DWORD_PTR type. */ typedef unsigned long DWORD_PTR; #endif /* * ----------------- * autoconf switches * ----------------- */ #if HAVE_CONFIG_H #include "config.h" #endif /* HAVE_CONFIG_H */ #ifndef NEED_FTIME #include #else /* NEED_FTIME */ /* use native WIN32 time API */ #endif /* NEED_FTIME */ #if HAVE_SIGNAL_H #include #endif /* HAVE_SIGNAL_H */ #include #include /* * Boolean values to make us independent of system includes. */ enum { PTW32_FALSE = 0, PTW32_TRUE = (! PTW32_FALSE) }; /* * This is a duplicate of what is in the autoconf config.h, * which is only used when building the pthread-win32 libraries. */ #ifndef PTW32_CONFIG_H # if defined(WINCE) # define NEED_ERRNO # define NEED_SEM # endif # if defined(_UWIN) || defined(__MINGW32__) # define HAVE_MODE_T # endif #endif /* * */ #if PTW32_LEVEL >= PTW32_LEVEL_MAX #ifdef NEED_ERRNO #include "need_errno.h" #else #include #endif #endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ /* * Several systems don't define some error numbers. */ #ifndef ENOTSUP # define ENOTSUP 48 /* This is the value in Solaris. */ #endif #ifndef ETIMEDOUT # define ETIMEDOUT 10060 /* This is the value in winsock.h. */ #endif #ifndef ENOSYS # define ENOSYS 140 /* Semi-arbitrary value */ #endif #ifndef EDEADLK # ifdef EDEADLOCK # define EDEADLK EDEADLOCK # else # define EDEADLK 36 /* This is the value in MSVC. */ # endif #endif //#include -- changed by alanmi #include "sched.h" /* * To avoid including windows.h we define only those things that we * actually need from it. */ #ifndef PTW32_INCLUDE_WINDOWS_H #ifndef HANDLE # define PTW32__HANDLE_DEF # define HANDLE void * #endif #ifndef DWORD # define PTW32__DWORD_DEF # define DWORD unsigned long #endif #endif #ifndef HAVE_STRUCT_TIMESPEC #define HAVE_STRUCT_TIMESPEC 1 struct timespec { long tv_sec; long tv_nsec; }; #endif /* HAVE_STRUCT_TIMESPEC */ #ifndef SIG_BLOCK #define SIG_BLOCK 0 #endif /* SIG_BLOCK */ #ifndef SIG_UNBLOCK #define SIG_UNBLOCK 1 #endif /* SIG_UNBLOCK */ #ifndef SIG_SETMASK #define SIG_SETMASK 2 #endif /* SIG_SETMASK */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* * ------------------------------------------------------------- * * POSIX 1003.1-2001 Options * ========================= * * Options are normally set in , which is not provided * with pthreads-win32. * * For conformance with the Single Unix Specification (version 3), all of the * options below are defined, and have a value of either -1 (not supported) * or 200112L (supported). * * These options can neither be left undefined nor have a value of 0, because * either indicates that sysconf(), which is not implemented, may be used at * runtime to check the status of the option. * * _POSIX_THREADS (== 200112L) * If == 200112L, you can use threads * * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) * If == 200112L, you can control the size of a thread's * stack * pthread_attr_getstacksize * pthread_attr_setstacksize * * _POSIX_THREAD_ATTR_STACKADDR (== -1) * If == 200112L, you can allocate and control a thread's * stack. If not supported, the following functions * will return ENOSYS, indicating they are not * supported: * pthread_attr_getstackaddr * pthread_attr_setstackaddr * * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) * If == 200112L, you can use realtime scheduling. * This option indicates that the behaviour of some * implemented functions conforms to the additional TPS * requirements in the standard. E.g. rwlocks favour * writers over readers when threads have equal priority. * * _POSIX_THREAD_PRIO_INHERIT (== -1) * If == 200112L, you can create priority inheritance * mutexes. * pthread_mutexattr_getprotocol + * pthread_mutexattr_setprotocol + * * _POSIX_THREAD_PRIO_PROTECT (== -1) * If == 200112L, you can create priority ceiling mutexes * Indicates the availability of: * pthread_mutex_getprioceiling * pthread_mutex_setprioceiling * pthread_mutexattr_getprioceiling * pthread_mutexattr_getprotocol + * pthread_mutexattr_setprioceiling * pthread_mutexattr_setprotocol + * * _POSIX_THREAD_PROCESS_SHARED (== -1) * If set, you can create mutexes and condition * variables that can be shared with another * process.If set, indicates the availability * of: * pthread_mutexattr_getpshared * pthread_mutexattr_setpshared * pthread_condattr_getpshared * pthread_condattr_setpshared * * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) * If == 200112L you can use the special *_r library * functions that provide thread-safe behaviour * * _POSIX_READER_WRITER_LOCKS (== 200112L) * If == 200112L, you can use read/write locks * * _POSIX_SPIN_LOCKS (== 200112L) * If == 200112L, you can use spin locks * * _POSIX_BARRIERS (== 200112L) * If == 200112L, you can use barriers * * + These functions provide both 'inherit' and/or * 'protect' protocol, based upon these macro * settings. * * ------------------------------------------------------------- */ /* * POSIX Options */ #undef _POSIX_THREADS #define _POSIX_THREADS 200112L #undef _POSIX_READER_WRITER_LOCKS #define _POSIX_READER_WRITER_LOCKS 200112L #undef _POSIX_SPIN_LOCKS #define _POSIX_SPIN_LOCKS 200112L #undef _POSIX_BARRIERS #define _POSIX_BARRIERS 200112L #undef _POSIX_THREAD_SAFE_FUNCTIONS #define _POSIX_THREAD_SAFE_FUNCTIONS 200112L #undef _POSIX_THREAD_ATTR_STACKSIZE #define _POSIX_THREAD_ATTR_STACKSIZE 200112L /* * The following options are not supported */ #undef _POSIX_THREAD_ATTR_STACKADDR #define _POSIX_THREAD_ATTR_STACKADDR -1 #undef _POSIX_THREAD_PRIO_INHERIT #define _POSIX_THREAD_PRIO_INHERIT -1 #undef _POSIX_THREAD_PRIO_PROTECT #define _POSIX_THREAD_PRIO_PROTECT -1 /* TPS is not fully supported. */ #undef _POSIX_THREAD_PRIORITY_SCHEDULING #define _POSIX_THREAD_PRIORITY_SCHEDULING -1 #undef _POSIX_THREAD_PROCESS_SHARED #define _POSIX_THREAD_PROCESS_SHARED -1 /* * POSIX 1003.1-2001 Limits * =========================== * * These limits are normally set in , which is not provided with * pthreads-win32. * * PTHREAD_DESTRUCTOR_ITERATIONS * Maximum number of attempts to destroy * a thread's thread-specific data on * termination (must be at least 4) * * PTHREAD_KEYS_MAX * Maximum number of thread-specific data keys * available per process (must be at least 128) * * PTHREAD_STACK_MIN * Minimum supported stack size for a thread * * PTHREAD_THREADS_MAX * Maximum number of threads supported per * process (must be at least 64). * * SEM_NSEMS_MAX * The maximum number of semaphores a process can have. * (must be at least 256) * * SEM_VALUE_MAX * The maximum value a semaphore can have. * (must be at least 32767) * */ #undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS #define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 #undef PTHREAD_DESTRUCTOR_ITERATIONS #define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS #undef _POSIX_THREAD_KEYS_MAX #define _POSIX_THREAD_KEYS_MAX 128 #undef PTHREAD_KEYS_MAX #define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX #undef PTHREAD_STACK_MIN #define PTHREAD_STACK_MIN 0 #undef _POSIX_THREAD_THREADS_MAX #define _POSIX_THREAD_THREADS_MAX 64 /* Arbitrary value */ #undef PTHREAD_THREADS_MAX #define PTHREAD_THREADS_MAX 2019 #undef _POSIX_SEM_NSEMS_MAX #define _POSIX_SEM_NSEMS_MAX 256 /* Arbitrary value */ #undef SEM_NSEMS_MAX #define SEM_NSEMS_MAX 1024 #undef _POSIX_SEM_VALUE_MAX #define _POSIX_SEM_VALUE_MAX 32767 #undef SEM_VALUE_MAX #define SEM_VALUE_MAX INT_MAX #if __GNUC__ && ! defined (__declspec) # error Please upgrade your GNU compiler to one that supports __declspec. #endif /* * When building the DLL code, you should define PTW32_BUILD so that * the variables/functions are exported correctly. When using the DLL, * do NOT define PTW32_BUILD, and then the variables/functions will * be imported correctly. */ #ifndef PTW32_STATIC_LIB # ifdef PTW32_BUILD # define PTW32_DLLPORT __declspec (dllexport) # else # define PTW32_DLLPORT __declspec (dllimport) # endif #else # define PTW32_DLLPORT #endif /* * The Open Watcom C/C++ compiler uses a non-standard calling convention * that passes function args in registers unless __cdecl is explicitly specified * in exposed function prototypes. * * We force all calls to cdecl even though this could slow Watcom code down * slightly. If you know that the Watcom compiler will be used to build both * the DLL and application, then you can probably define this as a null string. * Remember that pthread.h (this file) is used for both the DLL and application builds. */ #define PTW32_CDECL __cdecl #if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX # include #else /* * Generic handle type - intended to extend uniqueness beyond * that available with a simple pointer. It should scale for either * IA-32 or IA-64. */ typedef struct { void * p; /* Pointer to actual object */ unsigned int x; /* Extra information - reuse count etc */ } ptw32_handle_t; typedef ptw32_handle_t pthread_t; typedef struct pthread_attr_t_ * pthread_attr_t; typedef struct pthread_once_t_ pthread_once_t; typedef struct pthread_key_t_ * pthread_key_t; typedef struct pthread_mutex_t_ * pthread_mutex_t; typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; typedef struct pthread_cond_t_ * pthread_cond_t; typedef struct pthread_condattr_t_ * pthread_condattr_t; #endif typedef struct pthread_rwlock_t_ * pthread_rwlock_t; typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; typedef struct pthread_spinlock_t_ * pthread_spinlock_t; typedef struct pthread_barrier_t_ * pthread_barrier_t; typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; /* * ==================== * ==================== * POSIX Threads * ==================== * ==================== */ enum { /* * pthread_attr_{get,set}detachstate */ PTHREAD_CREATE_JOINABLE = 0, /* Default */ PTHREAD_CREATE_DETACHED = 1, /* * pthread_attr_{get,set}inheritsched */ PTHREAD_INHERIT_SCHED = 0, PTHREAD_EXPLICIT_SCHED = 1, /* Default */ /* * pthread_{get,set}scope */ PTHREAD_SCOPE_PROCESS = 0, PTHREAD_SCOPE_SYSTEM = 1, /* Default */ /* * pthread_setcancelstate paramters */ PTHREAD_CANCEL_ENABLE = 0, /* Default */ PTHREAD_CANCEL_DISABLE = 1, /* * pthread_setcanceltype parameters */ PTHREAD_CANCEL_ASYNCHRONOUS = 0, PTHREAD_CANCEL_DEFERRED = 1, /* Default */ /* * pthread_mutexattr_{get,set}pshared * pthread_condattr_{get,set}pshared */ PTHREAD_PROCESS_PRIVATE = 0, PTHREAD_PROCESS_SHARED = 1, /* * pthread_barrier_wait */ PTHREAD_BARRIER_SERIAL_THREAD = -1 }; /* * ==================== * ==================== * Cancelation * ==================== * ==================== */ #define PTHREAD_CANCELED ((void *) -1) /* * ==================== * ==================== * Once Key * ==================== * ==================== */ #define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0} struct pthread_once_t_ { int done; /* indicates if user function has been executed */ void * lock; int reserved1; int reserved2; }; /* * ==================== * ==================== * Object initialisers * ==================== * ==================== */ #define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1) #define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2) #define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3) /* * Compatibility with LinuxThreads */ #define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER #define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER #define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1) #define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1) #define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1) /* * Mutex types. */ enum { /* Compatibility with LinuxThreads */ PTHREAD_MUTEX_FAST_NP, PTHREAD_MUTEX_RECURSIVE_NP, PTHREAD_MUTEX_ERRORCHECK_NP, PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, /* For compatibility with POSIX */ PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL }; typedef struct ptw32_cleanup_t ptw32_cleanup_t; #if defined(_MSC_VER) /* Disable MSVC 'anachronism used' warning */ #pragma warning( disable : 4229 ) #endif typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); #if defined(_MSC_VER) #pragma warning( default : 4229 ) #endif struct ptw32_cleanup_t { ptw32_cleanup_callback_t routine; void *arg; struct ptw32_cleanup_t *prev; }; #ifdef __CLEANUP_SEH /* * WIN32 SEH version of cancel cleanup. */ #define pthread_cleanup_push( _rout, _arg ) \ { \ ptw32_cleanup_t _cleanup; \ \ _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ _cleanup.arg = (_arg); \ __try \ { \ #define pthread_cleanup_pop( _execute ) \ } \ __finally \ { \ if( _execute || AbnormalTermination()) \ { \ (*(_cleanup.routine))( _cleanup.arg ); \ } \ } \ } #else /* __CLEANUP_SEH */ #ifdef __CLEANUP_C /* * C implementation of PThreads cancel cleanup */ #define pthread_cleanup_push( _rout, _arg ) \ { \ ptw32_cleanup_t _cleanup; \ \ ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ #define pthread_cleanup_pop( _execute ) \ (void) ptw32_pop_cleanup( _execute ); \ } #else /* __CLEANUP_C */ #ifdef __CLEANUP_CXX /* * C++ version of cancel cleanup. * - John E. Bossom. */ class PThreadCleanup { /* * PThreadCleanup * * Purpose * This class is a C++ helper class that is * used to implement pthread_cleanup_push/ * pthread_cleanup_pop. * The destructor of this class automatically * pops the pushed cleanup routine regardless * of how the code exits the scope * (i.e. such as by an exception) */ ptw32_cleanup_callback_t cleanUpRout; void * obj; int executeIt; public: PThreadCleanup() : cleanUpRout( 0 ), obj( 0 ), executeIt( 0 ) /* * No cleanup performed */ { } PThreadCleanup( ptw32_cleanup_callback_t routine, void * arg ) : cleanUpRout( routine ), obj( arg ), executeIt( 1 ) /* * Registers a cleanup routine for 'arg' */ { } ~PThreadCleanup() { if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) { (void) (*cleanUpRout)( obj ); } } void execute( int exec ) { executeIt = exec; } }; /* * C++ implementation of PThreads cancel cleanup; * This implementation takes advantage of a helper * class who's destructor automatically calls the * cleanup routine if we exit our scope weirdly */ #define pthread_cleanup_push( _rout, _arg ) \ { \ PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ (void *) (_arg) ); #define pthread_cleanup_pop( _execute ) \ cleanup.execute( _execute ); \ } #else #error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. #endif /* __CLEANUP_CXX */ #endif /* __CLEANUP_C */ #endif /* __CLEANUP_SEH */ /* * =============== * =============== * Methods * =============== * =============== */ /* * PThread Attribute Functions */ PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, int *detachstate); PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, void **stackaddr); PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, size_t * stacksize); PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, int detachstate); PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, void *stackaddr); PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, size_t stacksize); PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, struct sched_param *param); PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, const struct sched_param *param); PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, int); PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *, int *); PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, int inheritsched); PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr, int * inheritsched); PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, int); PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, int *); /* * PThread Functions */ PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, const pthread_attr_t * attr, void *(*start) (void *), void *arg); PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, pthread_t t2); PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, void **value_ptr); PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, int *oldstate); PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, int *oldtype); PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, void (*init_routine) (void)); #if PTW32_LEVEL >= PTW32_LEVEL_MAX PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, void (*routine) (void *), void *arg); #endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ /* * Thread Specific Data Functions */ PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, void (*destructor) (void *)); PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, const void *value); PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); /* * Mutex Attribute Functions */ PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t * attr, int *pshared); PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, int pshared); PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind); /* * Barrier Attribute Functions */ PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t * attr, int *pshared); PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, int pshared); /* * Mutex Functions */ PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t * attr); PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime); PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); /* * Spinlock Functions */ PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); /* * Barrier Functions */ PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, const pthread_barrierattr_t * attr, unsigned int count); PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); /* * Condition Variable Attribute Functions */ PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, int *pshared); PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, int pshared); /* * Condition Variable Functions */ PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr); PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex); PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, pthread_mutex_t * mutex, const struct timespec *abstime); PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); /* * Scheduling */ PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, int policy, const struct sched_param *param); PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, int *policy, struct sched_param *param); PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); /* * Read-Write Lock Functions */ PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, const pthread_rwlockattr_t *attr); PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, const struct timespec *abstime); PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, const struct timespec *abstime); PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, int *pshared); PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, int pshared); #if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 /* * Signal Functions. Should be defined in but MSVC and MinGW32 * already have signal.h that don't define these. */ PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); /* * Non-portable functions */ /* * Compatibility with Linux. */ PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, int kind); PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, int *kind); /* * Possibly supported by other POSIX threads implementations */ PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); /* * Useful if an application wants to statically link * the lib rather than load the DLL at run-time. */ PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); /* * Features that are auto-detected at load/run time. */ PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); enum ptw32_features { PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ }; /* * Register a system time change with the library. * Causes the library to perform various functions * in response to the change. Should be called whenever * the application's top level window receives a * WM_TIMECHANGE message. It can be passed directly to * pthread_create() as a new thread if desired. */ PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); #endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ #if PTW32_LEVEL >= PTW32_LEVEL_MAX /* * Returns the Win32 HANDLE for the POSIX thread. */ PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); /* * Protected Methods * * This function blocks until the given WIN32 handle * is signaled or pthread_cancel had been called. * This function allows the caller to hook into the * PThreads cancel mechanism. It is implemented using * * WaitForMultipleObjects * * on 'waitHandle' and a manually reset WIN32 Event * used to implement pthread_cancel. The 'timeout' * argument to TimedWait is simply passed to * WaitForMultipleObjects. */ PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout); #endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ /* * Thread-Safe C Runtime Library Mappings. */ #ifndef _UWIN # if defined(NEED_ERRNO) PTW32_DLLPORT int * PTW32_CDECL _errno( void ); # else # ifndef errno # if (defined(_MT) || defined(_DLL)) __declspec(dllimport) extern int * __cdecl _errno(void); # define errno (*_errno()) # endif # endif # endif #endif /* * WIN32 C runtime library had been made thread-safe * without affecting the user interface. Provide * mappings from the UNIX thread-safe versions to * the standard C runtime library calls. * Only provide function mappings for functions that * actually exist on WIN32. */ #if !defined(__MINGW32__) #define strtok_r( _s, _sep, _lasts ) \ ( *(_lasts) = strtok( (_s), (_sep) ) ) #endif /* !__MINGW32__ */ #define asctime_r( _tm, _buf ) \ ( strcpy( (_buf), asctime( (_tm) ) ), \ (_buf) ) #define ctime_r( _clock, _buf ) \ ( strcpy( (_buf), ctime( (_clock) ) ), \ (_buf) ) #define gmtime_r( _clock, _result ) \ ( *(_result) = *gmtime( (_clock) ), \ (_result) ) #define localtime_r( _clock, _result ) \ ( *(_result) = *localtime( (_clock) ), \ (_result) ) #define rand_r( _seed ) \ ( _seed == _seed? rand() : rand() ) /* * Some compiler environments don't define some things. */ #if defined(__BORLANDC__) # define _ftime ftime # define _timeb timeb #endif #ifdef __cplusplus /* * Internal exceptions */ class ptw32_exception {}; class ptw32_exception_cancel : public ptw32_exception {}; class ptw32_exception_exit : public ptw32_exception {}; #endif #if PTW32_LEVEL >= PTW32_LEVEL_MAX /* FIXME: This is only required if the library was built using SEH */ /* * Get internal SEH tag */ PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); #endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ #ifndef PTW32_BUILD #ifdef __CLEANUP_SEH /* * Redefine the SEH __except keyword to ensure that applications * propagate our internal exceptions up to the library's internal handlers. */ #define __except( E ) \ __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) #endif /* __CLEANUP_SEH */ #ifdef __CLEANUP_CXX /* * Redefine the C++ catch keyword to ensure that applications * propagate our internal exceptions up to the library's internal handlers. */ #ifdef _MSC_VER /* * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' * if you want Pthread-Win32 cancelation and pthread_exit to work. */ #ifndef PtW32NoCatchWarn #pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") #pragma message("------------------------------------------------------------------") #pragma message("When compiling applications with MSVC++ and C++ exception handling:") #pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") #pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") #pragma message(" cancelation and pthread_exit to work. For example:") #pragma message("") #pragma message(" #ifdef PtW32CatchAll") #pragma message(" PtW32CatchAll") #pragma message(" #else") #pragma message(" catch(...)") #pragma message(" #endif") #pragma message(" {") #pragma message(" /* Catchall block processing */") #pragma message(" }") #pragma message("------------------------------------------------------------------") #endif #define PtW32CatchAll \ catch( ptw32_exception & ) { throw; } \ catch( ... ) #else /* _MSC_VER */ #define catch( E ) \ catch( ptw32_exception & ) { throw; } \ catch( E ) #endif /* _MSC_VER */ #endif /* __CLEANUP_CXX */ #endif /* ! PTW32_BUILD */ #ifdef __cplusplus } /* End of extern "C" */ #endif /* __cplusplus */ #ifdef PTW32__HANDLE_DEF # undef HANDLE #endif #ifdef PTW32__DWORD_DEF # undef DWORD #endif #undef PTW32_LEVEL #undef PTW32_LEVEL_MAX #endif /* ! RC_INVOKED */ #endif /* PTHREAD_H */ abc-0.52/lib/sched.h000066400000000000000000000110721477524141600142060ustar00rootroot00000000000000/* * Module: sched.h * * Purpose: * Provides an implementation of POSIX realtime extensions * as defined in * * POSIX 1003.1b-1993 (POSIX.1b) * * -------------------------------------------------------------------------- * * Pthreads-win32 - POSIX Threads Library for Win32 * Copyright(C) 1998 John E. Bossom * Copyright(C) 1999,2005 Pthreads-win32 contributors * * Contact Email: rpj@callisto.canberra.edu.au * * The current list of contributors is contained * in the file CONTRIBUTORS included with the source * code distribution. The list can also be seen at the * following World Wide Web location: * http://sources.redhat.com/pthreads-win32/contributors.html * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library in the file COPYING.LIB; * if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifndef _SCHED_H #define _SCHED_H #undef PTW32_LEVEL #if defined(_POSIX_SOURCE) #define PTW32_LEVEL 0 /* Early POSIX */ #endif #if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 #undef PTW32_LEVEL #define PTW32_LEVEL 1 /* Include 1b, 1c and 1d */ #endif #if defined(INCLUDE_NP) #undef PTW32_LEVEL #define PTW32_LEVEL 2 /* Include Non-Portable extensions */ #endif #define PTW32_LEVEL_MAX 3 #if !defined(PTW32_LEVEL) #define PTW32_LEVEL PTW32_LEVEL_MAX /* Include everything */ #endif #if __GNUC__ && ! defined (__declspec) # error Please upgrade your GNU compiler to one that supports __declspec. #endif /* * When building the DLL code, you should define PTW32_BUILD so that * the variables/functions are exported correctly. When using the DLL, * do NOT define PTW32_BUILD, and then the variables/functions will * be imported correctly. */ #ifndef PTW32_STATIC_LIB # ifdef PTW32_BUILD # define PTW32_DLLPORT __declspec (dllexport) # else # define PTW32_DLLPORT __declspec (dllimport) # endif #else # define PTW32_DLLPORT #endif /* * This is a duplicate of what is in the autoconf config.h, * which is only used when building the pthread-win32 libraries. */ #ifndef PTW32_CONFIG_H # if defined(WINCE) # define NEED_ERRNO # define NEED_SEM # endif # if defined(_UWIN) || defined(__MINGW32__) # define HAVE_MODE_T # endif #endif /* * */ #if PTW32_LEVEL >= PTW32_LEVEL_MAX #ifdef NEED_ERRNO #include "need_errno.h" #else #include #endif #endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ #if defined(__MINGW32__) || defined(_UWIN) #if PTW32_LEVEL >= PTW32_LEVEL_MAX /* For pid_t */ # include /* Required by Unix 98 */ # include #endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ #else typedef int pid_t; #endif /* Thread scheduling policies */ enum { SCHED_OTHER = 0, SCHED_FIFO, SCHED_RR, SCHED_MIN = SCHED_OTHER, SCHED_MAX = SCHED_RR }; struct sched_param { int sched_priority; }; #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ PTW32_DLLPORT int __cdecl sched_yield (void); PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); /* * Note that this macro returns ENOTSUP rather than * ENOSYS as might be expected. However, returning ENOSYS * should mean that sched_get_priority_{min,max} are * not implemented as well as sched_rr_get_interval. * This is not the case, since we just don't support * round-robin scheduling. Therefore I have chosen to * return the same value as sched_setscheduler when * SCHED_RR is passed to it. */ #define sched_rr_get_interval(_pid, _interval) \ ( errno = ENOTSUP, (int) -1 ) #ifdef __cplusplus } /* End of extern "C" */ #endif /* __cplusplus */ #undef PTW32_LEVEL #undef PTW32_LEVEL_MAX #endif /* !_SCHED_H */ abc-0.52/lib/semaphore.h000066400000000000000000000104671477524141600151120ustar00rootroot00000000000000/* * Module: semaphore.h * * Purpose: * Semaphores aren't actually part of the PThreads standard. * They are defined by the POSIX Standard: * * POSIX 1003.1b-1993 (POSIX.1b) * * -------------------------------------------------------------------------- * * Pthreads-win32 - POSIX Threads Library for Win32 * Copyright(C) 1998 John E. Bossom * Copyright(C) 1999,2005 Pthreads-win32 contributors * * Contact Email: rpj@callisto.canberra.edu.au * * The current list of contributors is contained * in the file CONTRIBUTORS included with the source * code distribution. The list can also be seen at the * following World Wide Web location: * http://sources.redhat.com/pthreads-win32/contributors.html * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library in the file COPYING.LIB; * if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined( SEMAPHORE_H ) #define SEMAPHORE_H #undef PTW32_LEVEL #if defined(_POSIX_SOURCE) #define PTW32_LEVEL 0 /* Early POSIX */ #endif #if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 #undef PTW32_LEVEL #define PTW32_LEVEL 1 /* Include 1b, 1c and 1d */ #endif #if defined(INCLUDE_NP) #undef PTW32_LEVEL #define PTW32_LEVEL 2 /* Include Non-Portable extensions */ #endif #define PTW32_LEVEL_MAX 3 #if !defined(PTW32_LEVEL) #define PTW32_LEVEL PTW32_LEVEL_MAX /* Include everything */ #endif #if __GNUC__ && ! defined (__declspec) # error Please upgrade your GNU compiler to one that supports __declspec. #endif /* * When building the DLL code, you should define PTW32_BUILD so that * the variables/functions are exported correctly. When using the DLL, * do NOT define PTW32_BUILD, and then the variables/functions will * be imported correctly. */ #ifndef PTW32_STATIC_LIB # ifdef PTW32_BUILD # define PTW32_DLLPORT __declspec (dllexport) # else # define PTW32_DLLPORT __declspec (dllimport) # endif #else # define PTW32_DLLPORT #endif /* * This is a duplicate of what is in the autoconf config.h, * which is only used when building the pthread-win32 libraries. */ #ifndef PTW32_CONFIG_H # if defined(WINCE) # define NEED_ERRNO # define NEED_SEM # endif # if defined(_UWIN) || defined(__MINGW32__) # define HAVE_MODE_T # endif #endif /* * */ #if PTW32_LEVEL >= PTW32_LEVEL_MAX #ifdef NEED_ERRNO #include "need_errno.h" #else #include #endif #endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ #define _POSIX_SEMAPHORES #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifndef HAVE_MODE_T typedef unsigned int mode_t; #endif typedef struct sem_t_ * sem_t; PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, int pshared, unsigned int value); PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem); PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, const struct timespec * abstime); PTW32_DLLPORT int __cdecl sem_post (sem_t * sem); PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, int count); PTW32_DLLPORT int __cdecl sem_open (const char * name, int oflag, mode_t mode, unsigned int value); PTW32_DLLPORT int __cdecl sem_close (sem_t * sem); PTW32_DLLPORT int __cdecl sem_unlink (const char * name); PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, int * sval); #ifdef __cplusplus } /* End of extern "C" */ #endif /* __cplusplus */ #undef PTW32_LEVEL #undef PTW32_LEVEL_MAX #endif /* !SEMAPHORE_H */ abc-0.52/readmeaig000066400000000000000000000114671477524141600140520ustar00rootroot00000000000000Using AIG Package in ABC - Download the latest snapshot of ABC - Compile the code found in "abc\src\aig\aig", "abc\src\aig\saig", and "abc\src\misc\vec" as a static library. - Link the library to the project. - Add #include "saig.h". - Start the AIG package using Aig_ManStart(). - Assign primary inputs using Aig_ObjCreateCi(). - Assign register outputs using Aig_ObjCreateCi(). (it is important to create all PIs first, before creating register outputs). - Construct AIG in the topological order using Aig_And(), Aig_Or(), Aig_Not(), etc. - If constant-0/1 AIG nodes are needed, use Aig_ManConst0() or Aig_ManConst1() - Create primary outputs using Aig_ObjCreateCo(). - Create register inputs using Aig_ObjCreateCo(). (it is important to create all POs first, before creating register inputs). - Set the number of registers by calling Aig_ManSetRegNum(). - Remove dangling AIG nodes (produced by structural hashing) using Aig_ManCleanup(). - Call the consistency checking procedure Aig_ManCheck(). - Dump AIG into a file using the new BLIF dumper Saig_ManDumpBlif(). - For each object in the design annotated with the constructed AIG node (pNode), remember its AIG node ID by calling Aig_ObjId( Aig_Regular(pNode) ). To check whether the corresponding AIG node is complemented use Aig_IsComplement(pNode). - Quit the AIG package using Aig_ManStop(). The above process should not produce memory leaks. Using GIA Package in ABC - Add #include "gia.h". - Start the AIG package using Gia_ManStart( int nObjMax ). (Parameter 'nNodeMax' should approximately reflect the expected number of objects, including PIs, POs, flop inputs, and flop outputs. If the number of objects is more, memory will be automatically reallocated.) - If structural hashing is to be used, start hash table by calling Gia_ManHashStart(). - Similarly, whenever structural hashingn is no longer needed, deallocate hash table by calling Gia_ManHashStop(). - Assign primary inputs using Gia_ManAppendCi(). - Assign flop outputs using Gia_ManAppendCi(). (It is important to create all PIs first, before creating flop outputs). (Flop control logic, if present, should be elaborated into AND gates. For example, to represent a flop enable, create the driver of enable signal, which can be a PI or an internal node, and then add logic for = MUX( , , ). The output of this logic feeds into the flop. - Construct AIG in the topological order using Gia_ManHashAnd(), Gia_ManHashOr(), Gia_Not(), etc. - If constant-0/1 AIG nodes are needed, use Gia_ManConst0() or Gia_ManConst1() - Create primary outputs using Gia_ManAppendCo(). - Create flop inputs using Gia_ManAppendCo(). (it is important to create all POs first, before creating register inputs). - Set the number of flops by calling Gia_ManSetRegNum(). - Remove dangling AIG nodes (produced by structural hashing) by running Gia_ManCleanup(), which will return a new AIG. If object mapping is defined for the original AIG, it should be remapped into the new AIG. - Dump AIG into an AIGER file use Gia_DumpAiger(). - For each object in the design annotated with the constructed AIG node (pNode), remember its AIG node ID by calling Gia_ObjId(pMan,pNode). - Quit the AIG package using Gia_ManStop(). The above process should not produce memory leaks. Using MiniAIG Package - Add #include "miniaig.h". - Start the AIG package using Mini_AigStart(). - Assign primary inputs using Mini_AigCreatePi(). - Assign flop outputs using Mini_AigCreatePi(). (It is important to create all PIs first, before creating flop outputs.) (Flop control logic, if present, should be elaborated into AND gates. For example, to represent a flop enable, create the driver of enable signal, which can be a PI or an internal node, and then add logic for = MUX( , , ). The output of this logic feeds into the flop. - Construct AIG in a topological order using Mini_AigAnd(), Mini_AigOr(), etc. - If constant-0 or constant-1 functions are needed, use 0 or 1. - Create primary outputs using Mini_AigCreatePo(). - Create flop inputs using Mini_AigCreatePo(). (It is important to create all POs first, before creating register inputs.) - Set the number of flops by calling Mini_AigSetRegNum(). - The AIG may contain internal nodes without fanout and/or internal nodes fed by constants. - Dump AIG in internal MiniAIG binary format using Mini_AigDump() and read it into ABC using "&read -m file.mini" - Dump AIG in standard AIGER format (https://fmv.jku.at/aiger/index.html) using Mini_AigerWrite() and read it into ABC using "&read file.aig" - For each object in the design represented using MiniAIG, it may be helpful to save the MiniAIG literal returned by Mini_AigAnd(), Mini_AigOr(), etc when constructing that object. - Quit the AIG package using Mini_AigStop(). The above process should not produce memory leaks. abc-0.52/src/000077500000000000000000000000001477524141600127675ustar00rootroot00000000000000abc-0.52/src/aig/000077500000000000000000000000001477524141600135275ustar00rootroot00000000000000abc-0.52/src/aig/aig/000077500000000000000000000000001477524141600142675ustar00rootroot00000000000000abc-0.52/src/aig/aig/aig.h000066400000000000000000001346701477524141600152130ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aig.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aig.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__aig__aig_h #define ABC__aig__aig__aig_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "misc/vec/vec.h" #include "misc/util/utilCex.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Aig_Man_t_ Aig_Man_t; typedef struct Aig_Obj_t_ Aig_Obj_t; typedef struct Aig_MmFixed_t_ Aig_MmFixed_t; typedef struct Aig_MmFlex_t_ Aig_MmFlex_t; typedef struct Aig_MmStep_t_ Aig_MmStep_t; // object types typedef enum { AIG_OBJ_NONE, // 0: non-existent object AIG_OBJ_CONST1, // 1: constant 1 AIG_OBJ_CI, // 2: combinational input AIG_OBJ_CO, // 3: combinational output AIG_OBJ_BUF, // 4: buffer node AIG_OBJ_AND, // 5: AND node AIG_OBJ_EXOR, // 6: EXOR node AIG_OBJ_VOID // 7: unused object } Aig_Type_t; // the AIG node struct Aig_Obj_t_ // 8 words { union { Aig_Obj_t * pNext; // strashing table int CioId; // 0-based number of CI/CO }; Aig_Obj_t * pFanin0; // fanin Aig_Obj_t * pFanin1; // fanin unsigned int Type : 3; // object type unsigned int fPhase : 1; // value under 000...0 pattern unsigned int fMarkA : 1; // multipurpose mask unsigned int fMarkB : 1; // multipurpose mask unsigned int nRefs : 26; // reference count unsigned Level : 24; // the level of this node unsigned nCuts : 8; // the number of cuts int TravId; // unique ID of last traversal involving the node int Id; // unique ID of the node union { // temporary store for user's data void * pData; int iData; float dData; }; }; // the AIG manager struct Aig_Man_t_ { char * pName; // the design name char * pSpec; // the input file name // AIG nodes Vec_Ptr_t * vCis; // the array of PIs Vec_Ptr_t * vCos; // the array of POs Vec_Ptr_t * vObjs; // the array of all nodes (optional) Vec_Ptr_t * vBufs; // the array of buffers Aig_Obj_t * pConst1; // the constant 1 node Aig_Obj_t Ghost; // the ghost node int nRegs; // the number of registers (registers are last POs) int nTruePis; // the number of true primary inputs int nTruePos; // the number of true primary outputs int nAsserts; // the number of asserts among POs (asserts are first POs) int nConstrs; // the number of constraints (model checking only) int nBarBufs; // the number of barrier buffers // AIG node counters int nObjs[AIG_OBJ_VOID];// the number of objects by type int nDeleted; // the number of deleted objects // structural hash table Aig_Obj_t ** pTable; // structural hash table int nTableSize; // structural hash table size // representation of fanouts int * pFanData; // the database to store fanout information int nFansAlloc; // the size of fanout representation Vec_Vec_t * vLevels; // used to update timing information int nBufReplaces; // the number of times replacement led to a buffer int nBufFixes; // the number of times buffers were propagated int nBufMax; // the maximum number of buffers during computation // topological order unsigned * pOrderData; int nOrderAlloc; int iPrev; int iNext; int nAndTotal; int nAndPrev; // representatives Aig_Obj_t ** pEquivs; // linked list of equivalent nodes (when choices are used) Aig_Obj_t ** pReprs; // representatives of each node int nReprsAlloc; // the number of allocated representatives // various data members Aig_MmFixed_t * pMemObjs; // memory manager for objects Vec_Int_t * vLevelR; // the reverse level of the nodes int nLevelMax; // maximum number of levels void * pData; // the temporary data void * pData2; // the temporary data int nTravIds; // the current traversal ID int fCatchExor; // enables EXOR nodes int fAddStrash; // performs additional strashing Aig_Obj_t ** pObjCopies; // mapping of AIG nodes into FRAIG nodes void (*pImpFunc) (void*, void*); // implication checking precedure void * pImpData; // implication checking data void * pManTime; // the timing manager void * pManCuts; int * pFastSim; unsigned * pTerSimData; // ternary simulation data Vec_Ptr_t * vMapped; Vec_Int_t * vFlopNums; Vec_Int_t * vFlopReprs; Abc_Cex_t * pSeqModel; Vec_Ptr_t * vSeqModelVec; // vector of counter-examples (for sequential miters) Aig_Man_t * pManExdc; Vec_Ptr_t * vOnehots; int fCreatePios; Vec_Int_t * vEquPairs; Vec_Vec_t * vClockDoms; Vec_Int_t * vProbs; // probability of node being 1 Vec_Int_t * vCiNumsOrig; // original CI names int nComplEdges; // complemented edges abctime Time2Quit; // timing statistics abctime time1; abctime time2; //-- jlong -- begin Vec_Ptr_t * unfold2_type_I; Vec_Ptr_t * unfold2_type_II; //-- jlong -- end }; // cut computation typedef struct Aig_ManCut_t_ Aig_ManCut_t; typedef struct Aig_Cut_t_ Aig_Cut_t; // the cut used to represent node in the AIG struct Aig_Cut_t_ { Aig_Cut_t * pNext; // the next cut in the table int Cost; // the cost of the cut unsigned uSign; // cut signature int iNode; // the node, for which it is the cut short nCutSize; // the number of bytes in the cut char nLeafMax; // the maximum number of fanins char nFanins; // the current number of fanins int pFanins[0]; // the fanins (followed by the truth table) }; // the CNF computation manager struct Aig_ManCut_t_ { // AIG manager Aig_Man_t * pAig; // the input AIG manager Aig_Cut_t ** pCuts; // the cuts for each node in the output manager // parameters int nCutsMax; // the max number of cuts at the node int nLeafMax; // the max number of leaves of a cut int fTruth; // enables truth table computation int fVerbose; // enables verbose output // internal variables int nCutSize; // the number of bytes needed to store one cut int nTruthWords; // the number of truth table words Aig_MmFixed_t * pMemCuts; // memory manager for cuts unsigned * puTemp[4]; // used for the truth table computation }; static inline Aig_Cut_t * Aig_ObjCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj ) { return p->pCuts[pObj->Id]; } static inline void Aig_ObjSetCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, Aig_Cut_t * pCuts ) { p->pCuts[pObj->Id] = pCuts; } static inline int Aig_CutLeaveNum( Aig_Cut_t * pCut ) { return pCut->nFanins; } static inline int * Aig_CutLeaves( Aig_Cut_t * pCut ) { return pCut->pFanins; } static inline unsigned * Aig_CutTruth( Aig_Cut_t * pCut ) { return (unsigned *)(pCut->pFanins + pCut->nLeafMax); } static inline Aig_Cut_t * Aig_CutNext( Aig_Cut_t * pCut ) { return (Aig_Cut_t *)(((char *)pCut) + pCut->nCutSize); } // iterator over cuts of the node #define Aig_ObjForEachCut( p, pObj, pCut, i ) \ for ( i = 0, pCut = Aig_ObjCuts(p, pObj); i < p->nCutsMax; i++, pCut = Aig_CutNext(pCut) ) // iterator over leaves of the cut #define Aig_CutForEachLeaf( p, pCut, pLeaf, i ) \ for ( i = 0; (i < (int)(pCut)->nFanins) && ((pLeaf) = Aig_ManObj(p, (pCut)->pFanins[i])); i++ ) //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline unsigned Aig_ObjCutSign( unsigned ObjId ) { return (1U << (ObjId & 31)); } static inline int Aig_WordCountOnes( unsigned uWord ) { uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); return (uWord & 0x0000FFFF) + (uWord>>16); } static inline int Aig_WordFindFirstBit( unsigned uWord ) { int i; for ( i = 0; i < 32; i++ ) if ( uWord & (1 << i) ) return i; return -1; } static inline Aig_Obj_t * Aig_Regular( Aig_Obj_t * p ) { return (Aig_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } static inline Aig_Obj_t * Aig_Not( Aig_Obj_t * p ) { return (Aig_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } static inline Aig_Obj_t * Aig_NotCond( Aig_Obj_t * p, int c ) { return (Aig_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } static inline int Aig_IsComplement( Aig_Obj_t * p ) { return (int)((ABC_PTRUINT_T)(p) & 01); } static inline int Aig_ManCiNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_CI]; } static inline int Aig_ManCoNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_CO]; } static inline int Aig_ManBufNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_BUF]; } static inline int Aig_ManAndNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_AND]; } static inline int Aig_ManExorNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_EXOR]; } static inline int Aig_ManNodeNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_AND]+p->nObjs[AIG_OBJ_EXOR]; } static inline int Aig_ManGetCost( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_AND]+3*p->nObjs[AIG_OBJ_EXOR]; } static inline int Aig_ManObjNum( Aig_Man_t * p ) { return Vec_PtrSize(p->vObjs) - p->nDeleted; } static inline int Aig_ManObjNumMax( Aig_Man_t * p ) { return Vec_PtrSize(p->vObjs); } static inline int Aig_ManRegNum( Aig_Man_t * p ) { return p->nRegs; } static inline int Aig_ManConstrNum( Aig_Man_t * p ) { return p->nConstrs; } static inline Aig_Obj_t * Aig_ManConst0( Aig_Man_t * p ) { return Aig_Not(p->pConst1); } static inline Aig_Obj_t * Aig_ManConst1( Aig_Man_t * p ) { return p->pConst1; } static inline Aig_Obj_t * Aig_ManGhost( Aig_Man_t * p ) { return &p->Ghost; } static inline Aig_Obj_t * Aig_ManCi( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vCis, i); } static inline Aig_Obj_t * Aig_ManCo( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vCos, i); } static inline Aig_Obj_t * Aig_ManLo( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vCis, Aig_ManCiNum(p)-Aig_ManRegNum(p)+i); } static inline Aig_Obj_t * Aig_ManLi( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vCos, Aig_ManCoNum(p)-Aig_ManRegNum(p)+i); } static inline Aig_Obj_t * Aig_ManObj( Aig_Man_t * p, int i ) { return p->vObjs ? (Aig_Obj_t *)Vec_PtrEntry(p->vObjs, i) : NULL; } static inline Aig_Type_t Aig_ObjType( Aig_Obj_t * pObj ) { return (Aig_Type_t)pObj->Type; } static inline int Aig_ObjIsNone( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_NONE; } static inline int Aig_ObjIsConst1( Aig_Obj_t * pObj ) { assert(!Aig_IsComplement(pObj)); return pObj->Type == AIG_OBJ_CONST1; } static inline int Aig_ObjIsCi( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_CI; } static inline int Aig_ObjIsCo( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_CO; } static inline int Aig_ObjIsBuf( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_BUF; } static inline int Aig_ObjIsAnd( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_AND; } static inline int Aig_ObjIsExor( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_EXOR; } static inline int Aig_ObjIsNode( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_AND || pObj->Type == AIG_OBJ_EXOR; } static inline int Aig_ObjIsTerm( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_CI || pObj->Type == AIG_OBJ_CO || pObj->Type == AIG_OBJ_CONST1; } static inline int Aig_ObjIsHash( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_AND || pObj->Type == AIG_OBJ_EXOR; } static inline int Aig_ObjIsChoice( Aig_Man_t * p, Aig_Obj_t * pObj ) { return p->pEquivs && p->pEquivs[pObj->Id] && pObj->nRefs > 0; } static inline int Aig_ObjIsCand( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_CI || pObj->Type == AIG_OBJ_AND || pObj->Type == AIG_OBJ_EXOR; } static inline int Aig_ObjCioId( Aig_Obj_t * pObj ) { assert( !Aig_ObjIsNode(pObj) ); return pObj->CioId; } static inline int Aig_ObjId( Aig_Obj_t * pObj ) { return pObj->Id; } static inline int Aig_ObjIsMarkA( Aig_Obj_t * pObj ) { return pObj->fMarkA; } static inline void Aig_ObjSetMarkA( Aig_Obj_t * pObj ) { pObj->fMarkA = 1; } static inline void Aig_ObjClearMarkA( Aig_Obj_t * pObj ) { pObj->fMarkA = 0; } static inline void Aig_ObjSetTravId( Aig_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } static inline void Aig_ObjSetTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } static inline void Aig_ObjSetTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1; } static inline int Aig_ObjIsTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj ) { return (int)(pObj->TravId == p->nTravIds); } static inline int Aig_ObjIsTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj ) { return (int)(pObj->TravId == p->nTravIds - 1); } static inline int Aig_ObjPhase( Aig_Obj_t * pObj ) { return pObj->fPhase; } static inline int Aig_ObjPhaseReal( Aig_Obj_t * pObj ) { return pObj? Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) : 1; } static inline int Aig_ObjRefs( Aig_Obj_t * pObj ) { return pObj->nRefs; } static inline void Aig_ObjRef( Aig_Obj_t * pObj ) { pObj->nRefs++; } static inline void Aig_ObjDeref( Aig_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } static inline void Aig_ObjClearRef( Aig_Obj_t * pObj ) { pObj->nRefs = 0; } static inline int Aig_ObjFaninId0( Aig_Obj_t * pObj ) { return pObj->pFanin0? Aig_Regular(pObj->pFanin0)->Id : -1; } static inline int Aig_ObjFaninId1( Aig_Obj_t * pObj ) { return pObj->pFanin1? Aig_Regular(pObj->pFanin1)->Id : -1; } static inline int Aig_ObjFaninC0( Aig_Obj_t * pObj ) { return Aig_IsComplement(pObj->pFanin0); } static inline int Aig_ObjFaninC1( Aig_Obj_t * pObj ) { return Aig_IsComplement(pObj->pFanin1); } static inline Aig_Obj_t * Aig_ObjFanin0( Aig_Obj_t * pObj ) { return Aig_Regular(pObj->pFanin0); } static inline Aig_Obj_t * Aig_ObjFanin1( Aig_Obj_t * pObj ) { return Aig_Regular(pObj->pFanin1); } static inline Aig_Obj_t * Aig_ObjChild0( Aig_Obj_t * pObj ) { return pObj->pFanin0; } static inline Aig_Obj_t * Aig_ObjChild1( Aig_Obj_t * pObj ) { return pObj->pFanin1; } static inline Aig_Obj_t * Aig_ObjChild0Copy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj)) : NULL; } static inline Aig_Obj_t * Aig_ObjChild1Copy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj)) : NULL; } static inline Aig_Obj_t * Aig_ObjChild0Next( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj)->pNext, Aig_ObjFaninC0(pObj)) : NULL; } static inline Aig_Obj_t * Aig_ObjChild1Next( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin1(pObj)->pNext, Aig_ObjFaninC1(pObj)) : NULL; } static inline void Aig_ObjChild0Flip( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); pObj->pFanin0 = Aig_Not(pObj->pFanin0); } static inline void Aig_ObjChild1Flip( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); pObj->pFanin1 = Aig_Not(pObj->pFanin1); } static inline Aig_Obj_t * Aig_ObjCopy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return (Aig_Obj_t *)pObj->pData; } static inline void Aig_ObjSetCopy( Aig_Obj_t * pObj, Aig_Obj_t * pCopy ) { assert( !Aig_IsComplement(pObj) ); pObj->pData = pCopy; } static inline Aig_Obj_t * Aig_ObjRealCopy( Aig_Obj_t * pObj ) { return Aig_NotCond((Aig_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj));} static inline int Aig_ObjToLit( Aig_Obj_t * pObj ) { return Abc_Var2Lit( Aig_ObjId(Aig_Regular(pObj)), Aig_IsComplement(pObj) ); } static inline Aig_Obj_t * Aig_ObjFromLit( Aig_Man_t * p,int iLit){ return Aig_NotCond( Aig_ManObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit) ); } static inline int Aig_ObjLevel( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return pObj->Level; } static inline int Aig_ObjLevelNew( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? 1 + Aig_ObjIsExor(pObj) + Abc_MaxInt(Aig_ObjFanin0(pObj)->Level, Aig_ObjFanin1(pObj)->Level) : Aig_ObjFanin0(pObj)->Level; } static inline int Aig_ObjSetLevel( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return pObj->Level = i; } static inline void Aig_ObjClean( Aig_Obj_t * pObj ) { memset( pObj, 0, sizeof(Aig_Obj_t) ); } static inline Aig_Obj_t * Aig_ObjFanout0( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert(p->pFanData && pObj->Id < p->nFansAlloc); return Aig_ManObj(p, p->pFanData[5*pObj->Id] >> 1); } static inline Aig_Obj_t * Aig_ObjEquiv( Aig_Man_t * p, Aig_Obj_t * pObj ) { return p->pEquivs? p->pEquivs[pObj->Id] : NULL; } static inline void Aig_ObjSetEquiv( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pEqu ) { assert(p->pEquivs); p->pEquivs[pObj->Id] = pEqu; } static inline Aig_Obj_t * Aig_ObjRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return p->pReprs? p->pReprs[pObj->Id] : NULL; } static inline void Aig_ObjSetRepr( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ) { assert(p->pReprs); p->pReprs[pObj->Id] = pRepr; } static inline int Aig_ObjWhatFanin( Aig_Obj_t * pObj, Aig_Obj_t * pFanin ) { if ( Aig_ObjFanin0(pObj) == pFanin ) return 0; if ( Aig_ObjFanin1(pObj) == pFanin ) return 1; assert(0); return -1; } static inline int Aig_ObjFanoutC( Aig_Obj_t * pObj, Aig_Obj_t * pFanout ) { if ( Aig_ObjFanin0(pFanout) == pObj ) return Aig_ObjFaninC0(pObj); if ( Aig_ObjFanin1(pFanout) == pObj ) return Aig_ObjFaninC1(pObj); assert(0); return -1; } // create the ghost of the new node static inline Aig_Obj_t * Aig_ObjCreateGhost( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ) { Aig_Obj_t * pGhost; assert( Type != AIG_OBJ_AND || !Aig_ObjIsConst1(Aig_Regular(p0)) ); assert( p1 == NULL || !Aig_ObjIsConst1(Aig_Regular(p1)) ); assert( Type == AIG_OBJ_CI || Aig_Regular(p0) != Aig_Regular(p1) ); pGhost = Aig_ManGhost(p); pGhost->Type = Type; if ( p1 == NULL || Aig_Regular(p0)->Id < Aig_Regular(p1)->Id ) { pGhost->pFanin0 = p0; pGhost->pFanin1 = p1; } else { pGhost->pFanin0 = p1; pGhost->pFanin1 = p0; } return pGhost; } // internal memory manager static inline Aig_Obj_t * Aig_ManFetchMemory( Aig_Man_t * p ) { extern char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p ); Aig_Obj_t * pTemp; pTemp = (Aig_Obj_t *)Aig_MmFixedEntryFetch( p->pMemObjs ); memset( pTemp, 0, sizeof(Aig_Obj_t) ); pTemp->Id = Vec_PtrSize(p->vObjs); Vec_PtrPush( p->vObjs, pTemp ); return pTemp; } static inline void Aig_ManRecycleMemory( Aig_Man_t * p, Aig_Obj_t * pEntry ) { extern void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry ); assert( pEntry->nRefs == 0 ); pEntry->Type = AIG_OBJ_NONE; // distinquishes a dead node from a live node Aig_MmFixedEntryRecycle( p->pMemObjs, (char *)pEntry ); p->nDeleted++; } //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// // iterator over the combinational inputs #define Aig_ManForEachCi( p, pObj, i ) \ Vec_PtrForEachEntry( Aig_Obj_t *, p->vCis, pObj, i ) #define Aig_ManForEachCiReverse( p, pObj, i ) \ Vec_PtrForEachEntryReverse( Aig_Obj_t *, p->vCis, pObj, i ) // iterator over the combinational outputs #define Aig_ManForEachCo( p, pObj, i ) \ Vec_PtrForEachEntry( Aig_Obj_t *, p->vCos, pObj, i ) #define Aig_ManForEachCoReverse( p, pObj, i ) \ Vec_PtrForEachEntryReverse( Aig_Obj_t *, p->vCos, pObj, i ) // iterators over all objects, including those currently not used #define Aig_ManForEachObj( p, pObj, i ) \ Vec_PtrForEachEntry( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else #define Aig_ManForEachObjReverse( p, pObj, i ) \ Vec_PtrForEachEntryReverse( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else // iterators over the objects whose IDs are stored in an array #define Aig_ManForEachObjVec( vIds, p, pObj, i ) \ for ( i = 0; i < Vec_IntSize(vIds) && (((pObj) = Aig_ManObj(p, Vec_IntEntry(vIds,i))), 1); i++ ) #define Aig_ManForEachObjVecReverse( vIds, p, pObj, i ) \ for ( i = Vec_IntSize(vIds) - 1; i >= 0 && (((pObj) = Aig_ManObj(p, Vec_IntEntry(vIds,i))), 1); i-- ) // iterators over all nodes #define Aig_ManForEachNode( p, pObj, i ) \ Vec_PtrForEachEntry( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL || !Aig_ObjIsNode(pObj) ) {} else #define Aig_ManForEachNodeReverse( p, pObj, i ) \ Vec_PtrForEachEntryReverse( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL || !Aig_ObjIsNode(pObj) ) {} else // iterator over all nodes #define Aig_ManForEachExor( p, pObj, i ) \ Vec_PtrForEachEntry( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL || !Aig_ObjIsExor(pObj) ) {} else #define Aig_ManForEachExorReverse( p, pObj, i ) \ Vec_PtrForEachEntryReverse( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL || !Aig_ObjIsExor(pObj) ) {} else // these two procedures are only here for the use inside the iterator static inline int Aig_ObjFanout0Int( Aig_Man_t * p, int ObjId ) { assert(ObjId < p->nFansAlloc); return p->pFanData[5*ObjId]; } static inline int Aig_ObjFanoutNext( Aig_Man_t * p, int iFan ) { assert(iFan/2 < p->nFansAlloc); return p->pFanData[5*(iFan >> 1) + 3 + (iFan & 1)]; } // iterator over the fanouts #define Aig_ObjForEachFanout( p, pObj, pFanout, iFan, i ) \ for ( assert(p->pFanData), i = 0; (i < (int)(pObj)->nRefs) && \ (((iFan) = i? Aig_ObjFanoutNext(p, iFan) : Aig_ObjFanout0Int(p, pObj->Id)), 1) && \ (((pFanout) = Aig_ManObj(p, iFan>>1)), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// SEQUENTIAL ITERATORS /// //////////////////////////////////////////////////////////////////////// // iterator over the primary inputs #define Aig_ManForEachPiSeq( p, pObj, i ) \ Vec_PtrForEachEntryStop( Aig_Obj_t *, p->vCis, pObj, i, Aig_ManCiNum(p)-Aig_ManRegNum(p) ) // iterator over the latch outputs #define Aig_ManForEachLoSeq( p, pObj, i ) \ Vec_PtrForEachEntryStart( Aig_Obj_t *, p->vCis, pObj, i, Aig_ManCiNum(p)-Aig_ManRegNum(p) ) // iterator over the primary outputs #define Aig_ManForEachPoSeq( p, pObj, i ) \ Vec_PtrForEachEntryStop( Aig_Obj_t *, p->vCos, pObj, i, Aig_ManCoNum(p)-Aig_ManRegNum(p) ) // iterator over the latch inputs #define Aig_ManForEachLiSeq( p, pObj, i ) \ Vec_PtrForEachEntryStart( Aig_Obj_t *, p->vCos, pObj, i, Aig_ManCoNum(p)-Aig_ManRegNum(p) ) // iterator over the latch input and outputs #define Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, k ) \ for ( k = 0; (k < Aig_ManRegNum(p)) && (((pObjLi) = Aig_ManLi(p, k)), 1) \ && (((pObjLo)=Aig_ManLo(p, k)), 1); k++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== aigCheck.c ========================================================*/ extern ABC_DLL int Aig_ManCheck( Aig_Man_t * p ); extern void Aig_ManCheckMarkA( Aig_Man_t * p ); extern void Aig_ManCheckPhase( Aig_Man_t * p ); /*=== aigCuts.c ========================================================*/ extern Aig_ManCut_t * Aig_ComputeCuts( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fTruth, int fVerbose ); extern void Aig_ManCutStop( Aig_ManCut_t * p ); /*=== aigDfs.c ==========================================================*/ extern int Aig_ManVerifyTopoOrder( Aig_Man_t * p ); extern Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p, int fNodesOnly ); extern Vec_Ptr_t * Aig_ManDfsAll( Aig_Man_t * p ); extern Vec_Ptr_t * Aig_ManDfsPreorder( Aig_Man_t * p, int fNodesOnly ); extern Vec_Vec_t * Aig_ManLevelize( Aig_Man_t * p ); extern Vec_Ptr_t * Aig_ManDfsNodes( Aig_Man_t * p, Aig_Obj_t ** ppNodes, int nNodes ); extern Vec_Ptr_t * Aig_ManDfsChoices( Aig_Man_t * p ); extern Vec_Ptr_t * Aig_ManDfsReverse( Aig_Man_t * p ); extern int Aig_ManLevelNum( Aig_Man_t * p ); extern int Aig_ManChoiceLevel( Aig_Man_t * p ); extern int Aig_DagSize( Aig_Obj_t * pObj ); extern int Aig_SupportSize( Aig_Man_t * p, Aig_Obj_t * pObj ); extern Vec_Ptr_t * Aig_Support( Aig_Man_t * p, Aig_Obj_t * pObj ); extern void Aig_SupportNodes( Aig_Man_t * p, Aig_Obj_t ** ppObjs, int nObjs, Vec_Ptr_t * vSupp ); extern void Aig_ConeUnmark_rec( Aig_Obj_t * pObj ); extern Aig_Obj_t * Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pObj, int nVars ); extern Aig_Obj_t * Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar ); extern void Aig_ObjCollectCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes ); extern int Aig_ObjCollectSuper( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ); /*=== aigDup.c ==========================================================*/ extern Aig_Obj_t * Aig_ManDupSimpleDfs_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ); extern Aig_Man_t * Aig_ManDupSimple( Aig_Man_t * p ); extern Aig_Man_t * Aig_ManDupSimpleWithHints( Aig_Man_t * p, Vec_Int_t * vHints ); extern Aig_Man_t * Aig_ManDupSimpleDfs( Aig_Man_t * p ); extern Aig_Man_t * Aig_ManDupSimpleDfsPart( Aig_Man_t * p, Vec_Ptr_t * vPis, Vec_Ptr_t * vCos ); extern Aig_Man_t * Aig_ManDupOrdered( Aig_Man_t * p ); extern Aig_Man_t * Aig_ManDupCof( Aig_Man_t * p, int iInput, int Value ); extern Aig_Man_t * Aig_ManDupTrim( Aig_Man_t * p ); extern Aig_Man_t * Aig_ManDupExor( Aig_Man_t * p ); extern Aig_Man_t * Aig_ManDupDfs( Aig_Man_t * p ); extern Vec_Ptr_t * Aig_ManOrderPios( Aig_Man_t * p, Aig_Man_t * pOrder ); extern Aig_Man_t * Aig_ManDupDfsGuided( Aig_Man_t * p, Vec_Ptr_t * vPios ); extern Aig_Man_t * Aig_ManDupLevelized( Aig_Man_t * p ); extern Aig_Man_t * Aig_ManDupWithoutPos( Aig_Man_t * p ); extern Aig_Man_t * Aig_ManDupFlopsOnly( Aig_Man_t * p ); extern Aig_Man_t * Aig_ManDupRepres( Aig_Man_t * p ); extern Aig_Man_t * Aig_ManDupRepresDfs( Aig_Man_t * p ); extern Aig_Man_t * Aig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int fImpl ); extern Aig_Man_t * Aig_ManDupOrpos( Aig_Man_t * p, int fAddRegs ); extern Aig_Man_t * Aig_ManDupOneOutput( Aig_Man_t * p, int iPoNum, int fAddRegs ); extern Aig_Man_t * Aig_ManDupUnsolvedOutputs( Aig_Man_t * p, int fAddRegs ); extern Aig_Man_t * Aig_ManDupArray( Vec_Ptr_t * vArray ); extern Aig_Man_t * Aig_ManDupNodes( Aig_Man_t * pMan, Vec_Ptr_t * vArray ); /*=== aigFanout.c ==========================================================*/ extern void Aig_ObjAddFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ); extern void Aig_ObjRemoveFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ); extern void Aig_ManFanoutStart( Aig_Man_t * p ); extern void Aig_ManFanoutStop( Aig_Man_t * p ); /*=== aigFrames.c ==========================================================*/ extern Aig_Man_t * Aig_ManFrames( Aig_Man_t * pAig, int nFs, int fInit, int fOuts, int fRegs, int fEnlarge, Aig_Obj_t *** ppObjMap ); /*=== aigMan.c ==========================================================*/ extern Aig_Man_t * Aig_ManStart( int nNodesMax ); extern Aig_Man_t * Aig_ManStartFrom( Aig_Man_t * p ); extern Aig_Man_t * Aig_ManExtractMiter( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ); extern void Aig_ManStop( Aig_Man_t * p ); extern void Aig_ManStopP( Aig_Man_t ** p ); extern int Aig_ManCleanup( Aig_Man_t * p ); extern int Aig_ManAntiCleanup( Aig_Man_t * p ); extern int Aig_ManCiCleanup( Aig_Man_t * p ); extern int Aig_ManCoCleanup( Aig_Man_t * p ); extern void Aig_ManPrintStats( Aig_Man_t * p ); extern void Aig_ManReportImprovement( Aig_Man_t * p, Aig_Man_t * pNew ); extern void Aig_ManSetRegNum( Aig_Man_t * p, int nRegs ); extern void Aig_ManFlipFirstPo( Aig_Man_t * p ); extern void * Aig_ManReleaseData( Aig_Man_t * p ); /*=== aigMem.c ==========================================================*/ extern void Aig_ManStartMemory( Aig_Man_t * p ); extern void Aig_ManStopMemory( Aig_Man_t * p ); /*=== aigMffc.c ==========================================================*/ extern int Aig_NodeRef_rec( Aig_Obj_t * pNode, unsigned LevelMin ); extern int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin, float * pPower, float * pProbs ); extern int Aig_NodeMffcSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp ); extern int Aig_NodeMffcLabel( Aig_Man_t * p, Aig_Obj_t * pNode, float * pPower ); extern int Aig_NodeMffcLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves ); extern int Aig_NodeMffcExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult ); /*=== aigObj.c ==========================================================*/ extern Aig_Obj_t * Aig_ObjCreateCi( Aig_Man_t * p ); extern Aig_Obj_t * Aig_ObjCreateCo( Aig_Man_t * p, Aig_Obj_t * pDriver ); extern Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost ); extern void Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 ); extern void Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj ); extern void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj ); extern void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fFreeTop ); extern void Aig_ObjDeletePo( Aig_Man_t * p, Aig_Obj_t * pObj ); extern void Aig_ObjPrint( Aig_Man_t * p, Aig_Obj_t * pObj ); extern void Aig_ObjPatchFanin0( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFaninNew ); extern void Aig_ObjReplace( Aig_Man_t * p, Aig_Obj_t * pObjOld, Aig_Obj_t * pObjNew, int fUpdateLevel ); /*=== aigOper.c =========================================================*/ extern Aig_Obj_t * Aig_IthVar( Aig_Man_t * p, int i ); extern Aig_Obj_t * Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ); extern Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); extern Aig_Obj_t * Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); extern Aig_Obj_t * Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); extern Aig_Obj_t * Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 ); extern Aig_Obj_t * Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC ); extern Aig_Obj_t * Aig_Multi( Aig_Man_t * p, Aig_Obj_t ** pArgs, int nArgs, Aig_Type_t Type ); extern Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs ); extern Aig_Obj_t * Aig_MiterTwo( Aig_Man_t * p, Vec_Ptr_t * vNodes1, Vec_Ptr_t * vNodes2 ); extern Aig_Obj_t * Aig_CreateAnd( Aig_Man_t * p, int nVars ); extern Aig_Obj_t * Aig_CreateOr( Aig_Man_t * p, int nVars ); extern Aig_Obj_t * Aig_CreateExor( Aig_Man_t * p, int nVars ); /*=== aigOrder.c =========================================================*/ extern void Aig_ManOrderStart( Aig_Man_t * p ); extern void Aig_ManOrderStop( Aig_Man_t * p ); extern void Aig_ObjOrderInsert( Aig_Man_t * p, int ObjId ); extern void Aig_ObjOrderRemove( Aig_Man_t * p, int ObjId ); extern void Aig_ObjOrderAdvance( Aig_Man_t * p ); /*=== aigPart.c =========================================================*/ extern Vec_Ptr_t * Aig_ManSupports( Aig_Man_t * p ); extern Vec_Ptr_t * Aig_ManSupportsInverse( Aig_Man_t * p ); extern Vec_Ptr_t * Aig_ManSupportsRegisters( Aig_Man_t * p ); extern Vec_Ptr_t * Aig_ManPartitionSmart( Aig_Man_t * p, int nPartSizeLimit, int fVerbose, Vec_Ptr_t ** pvPartSupps ); extern Vec_Ptr_t * Aig_ManPartitionSmartRegisters( Aig_Man_t * pAig, int nSuppSizeLimit, int fVerbose ); extern Vec_Ptr_t * Aig_ManPartitionNaive( Aig_Man_t * p, int nPartSize ); extern Vec_Ptr_t * Aig_ManMiterPartitioned( Aig_Man_t * p1, Aig_Man_t * p2, int nPartSize, int fSmart ); extern Aig_Man_t * Aig_ManChoicePartitioned( Vec_Ptr_t * vAigs, int nPartSize, int nConfMax, int nLevelMax, int fVerbose ); extern Aig_Man_t * Aig_ManFraigPartitioned( Aig_Man_t * pAig, int nPartSize, int nConfMax, int nLevelMax, int fVerbose ); extern Aig_Man_t * Aig_ManChoiceConstructive( Vec_Ptr_t * vAigs, int fVerbose ); /*=== aigPartReg.c =========================================================*/ extern Vec_Ptr_t * Aig_ManRegPartitionSimple( Aig_Man_t * pAig, int nPartSize, int nOverSize ); extern void Aig_ManPartDivide( Vec_Ptr_t * vResult, Vec_Int_t * vDomain, int nPartSize, int nOverSize ); extern Vec_Ptr_t * Aig_ManRegPartitionSmart( Aig_Man_t * pAig, int nPartSize ); extern Aig_Man_t * Aig_ManRegCreatePart( Aig_Man_t * pAig, Vec_Int_t * vPart, int * pnCountPis, int * pnCountRegs, int ** ppMapBack ); extern Vec_Ptr_t * Aig_ManRegProjectOnehots( Aig_Man_t * pAig, Aig_Man_t * pPart, Vec_Ptr_t * vOnehots, int fVerbose ); /*=== aigRepr.c =========================================================*/ extern void Aig_ManReprStart( Aig_Man_t * p, int nIdMax ); extern void Aig_ManReprStop( Aig_Man_t * p ); extern void Aig_ObjCreateRepr( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ); extern void Aig_ManTransferRepr( Aig_Man_t * pNew, Aig_Man_t * p ); extern Aig_Man_t * Aig_ManDupRepr( Aig_Man_t * p, int fOrdered ); extern Aig_Man_t * Aig_ManDupReprBasic( Aig_Man_t * p ); extern int Aig_ManCountReprs( Aig_Man_t * p ); extern Aig_Man_t * Aig_ManRehash( Aig_Man_t * p ); extern int Aig_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pNew, Aig_Obj_t * pOld ); extern void Aig_ManMarkValidChoices( Aig_Man_t * p ); extern int Aig_TransferMappedClasses( Aig_Man_t * pAig, Aig_Man_t * pPart, int * pMapBack ); /*=== aigRet.c ========================================================*/ extern Aig_Man_t * Rtm_ManRetime( Aig_Man_t * p, int fForward, int nStepsMax, int fVerbose ); /*=== aigRetF.c ========================================================*/ extern Aig_Man_t * Aig_ManRetimeFrontier( Aig_Man_t * p, int nStepsMax ); /*=== aigScl.c ==========================================================*/ extern Aig_Man_t * Aig_ManRemap( Aig_Man_t * p, Vec_Ptr_t * vMap ); extern int Aig_ManSeqCleanup( Aig_Man_t * p ); extern int Aig_ManSeqCleanupBasic( Aig_Man_t * p ); extern int Aig_ManCountMergeRegs( Aig_Man_t * p ); extern Aig_Man_t * Aig_ManReduceLaches( Aig_Man_t * p, int fVerbose ); extern void Aig_ManComputeSccs( Aig_Man_t * p ); extern Aig_Man_t * Aig_ManScl( Aig_Man_t * pAig, int fLatchConst, int fLatchEqual, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose ); /*=== aigShow.c ========================================================*/ extern void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ); /*=== aigTable.c ========================================================*/ extern Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost ); extern Aig_Obj_t * Aig_TableLookupTwo( Aig_Man_t * p, Aig_Obj_t * pFanin0, Aig_Obj_t * pFanin1 ); extern void Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj ); extern void Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj ); extern int Aig_TableCountEntries( Aig_Man_t * p ); extern void Aig_TableProfile( Aig_Man_t * p ); extern void Aig_TableClear( Aig_Man_t * p ); /*=== aigTiming.c ========================================================*/ extern void Aig_ObjClearReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj ); extern int Aig_ObjRequiredLevel( Aig_Man_t * p, Aig_Obj_t * pObj ); extern void Aig_ManStartReverseLevels( Aig_Man_t * p, int nMaxLevelIncrease ); extern void Aig_ManStopReverseLevels( Aig_Man_t * p ); extern void Aig_ManUpdateLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ); extern void Aig_ManUpdateReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ); extern void Aig_ManVerifyLevel( Aig_Man_t * p ); extern void Aig_ManVerifyReverseLevel( Aig_Man_t * p ); /*=== aigTruth.c ========================================================*/ extern unsigned * Aig_ManCutTruth( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore ); /*=== aigTsim.c ========================================================*/ extern Aig_Man_t * Aig_ManConstReduce( Aig_Man_t * p, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose ); /*=== aigUtil.c =========================================================*/ extern void Aig_ManIncrementTravId( Aig_Man_t * p ); extern char * Aig_TimeStamp(); extern int Aig_ManHasNoGaps( Aig_Man_t * p ); extern int Aig_ManLevels( Aig_Man_t * p ); extern void Aig_ManResetRefs( Aig_Man_t * p ); extern void Aig_ManCleanMarkA( Aig_Man_t * p ); extern void Aig_ManCleanMarkB( Aig_Man_t * p ); extern void Aig_ManCleanMarkAB( Aig_Man_t * p ); extern void Aig_ManCleanData( Aig_Man_t * p ); extern void Aig_ObjCleanData_rec( Aig_Obj_t * pObj ); extern void Aig_ManCleanNext( Aig_Man_t * p ); extern void Aig_ObjCollectMulti( Aig_Obj_t * pFunc, Vec_Ptr_t * vSuper ); extern int Aig_ObjIsMuxType( Aig_Obj_t * pObj ); extern int Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ); extern Aig_Obj_t * Aig_ObjRecognizeMux( Aig_Obj_t * pObj, Aig_Obj_t ** ppObjT, Aig_Obj_t ** ppObjE ); extern Aig_Obj_t * Aig_ObjReal_rec( Aig_Obj_t * pObj ); extern int Aig_ObjCompareIdIncrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ); extern void Aig_ObjPrintEqn( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); extern void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); extern void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig ); extern void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig ); extern void Aig_ManDump( Aig_Man_t * p ); extern void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames ); extern void Aig_ManDumpVerilog( Aig_Man_t * p, char * pFileName ); extern void Aig_ManSetCioIds( Aig_Man_t * p ); extern void Aig_ManCleanCioIds( Aig_Man_t * p ); extern int Aig_ManChoiceNum( Aig_Man_t * p ); extern char * Aig_FileNameGenericAppend( char * pBase, char * pSuffix ); extern unsigned Aig_ManRandom( int fReset ); extern word Aig_ManRandom64( int fReset ); extern void Aig_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int iWordStop ); extern void Aig_NodeUnionLists( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * vArr ); extern void Aig_NodeIntersectLists( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * vArr ); extern void Aig_ManSetPhase( Aig_Man_t * pAig ); extern Vec_Ptr_t * Aig_ManMuxesCollect( Aig_Man_t * pAig ); extern void Aig_ManMuxesDeref( Aig_Man_t * pAig, Vec_Ptr_t * vMuxes ); extern void Aig_ManMuxesRef( Aig_Man_t * pAig, Vec_Ptr_t * vMuxes ); extern void Aig_ManInvertConstraints( Aig_Man_t * pAig ); /*=== aigWin.c =========================================================*/ extern void Aig_ManFindCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit ); /*=== aigMem.c ===========================================================*/ // fixed-size-block memory manager extern Aig_MmFixed_t * Aig_MmFixedStart( int nEntrySize, int nEntriesMax ); extern void Aig_MmFixedStop( Aig_MmFixed_t * p, int fVerbose ); extern char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p ); extern void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry ); extern void Aig_MmFixedRestart( Aig_MmFixed_t * p ); extern int Aig_MmFixedReadMemUsage( Aig_MmFixed_t * p ); extern int Aig_MmFixedReadMaxEntriesUsed( Aig_MmFixed_t * p ); // flexible-size-block memory manager extern Aig_MmFlex_t * Aig_MmFlexStart(); extern void Aig_MmFlexStop( Aig_MmFlex_t * p, int fVerbose ); extern char * Aig_MmFlexEntryFetch( Aig_MmFlex_t * p, int nBytes ); extern void Aig_MmFlexRestart( Aig_MmFlex_t * p ); extern int Aig_MmFlexReadMemUsage( Aig_MmFlex_t * p ); // hierarchical memory manager extern Aig_MmStep_t * Aig_MmStepStart( int nSteps ); extern void Aig_MmStepStop( Aig_MmStep_t * p, int fVerbose ); extern char * Aig_MmStepEntryFetch( Aig_MmStep_t * p, int nBytes ); extern void Aig_MmStepEntryRecycle( Aig_MmStep_t * p, char * pEntry, int nBytes ); extern int Aig_MmStepReadMemUsage( Aig_MmStep_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/aig/aig/aigCanon.c000066400000000000000000000504141477524141600161560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigCanon.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Processing the library of semi-canonical AIGs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigCanon.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" #include "bool/kit/kit.h" #include "bool/bdc/bdc.h" #include "aig/ioa/ioa.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define RMAN_MAXVARS 12 #define RMAX_MAXWORD (RMAN_MAXVARS <= 5 ? 1 : (1 << (RMAN_MAXVARS - 5))) typedef struct Aig_VSig_t_ Aig_VSig_t; struct Aig_VSig_t_ { int nOnes; int nCofOnes[RMAN_MAXVARS]; }; typedef struct Aig_Tru_t_ Aig_Tru_t; struct Aig_Tru_t_ { Aig_Tru_t * pNext; int Id; unsigned nVisits : 27; unsigned nVars : 5; unsigned pTruth[0]; }; typedef struct Aig_RMan_t_ Aig_RMan_t; struct Aig_RMan_t_ { int nVars; // the largest variable number Aig_Man_t * pAig; // recorded subgraphs // hash table int nBins; Aig_Tru_t ** pBins; int nEntries; Aig_MmFlex_t* pMemTrus; // bidecomposion Bdc_Man_t * pBidec; // temporaries unsigned pTruthInit[RMAX_MAXWORD]; // canonical truth table unsigned pTruth[RMAX_MAXWORD]; // current truth table unsigned pTruthC[RMAX_MAXWORD]; // canonical truth table unsigned pTruthTemp[RMAX_MAXWORD]; // temporary truth table Aig_VSig_t pMints[2*RMAN_MAXVARS]; // minterm count char pPerm[RMAN_MAXVARS]; // permutation char pPermR[RMAN_MAXVARS]; // reverse permutation // statistics int nVarFuncs[RMAN_MAXVARS+1]; int nTotal; int nTtDsd; int nTtDsdPart; int nTtDsdNot; int nUniqueVars; }; static Aig_RMan_t * s_pRMan = NULL; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates recording manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_RMan_t * Aig_RManStart() { static Bdc_Par_t Pars = {0}, * pPars = &Pars; Aig_RMan_t * p; p = ABC_ALLOC( Aig_RMan_t, 1 ); memset( p, 0, sizeof(Aig_RMan_t) ); p->nVars = RMAN_MAXVARS; p->pAig = Aig_ManStart( 1000000 ); Aig_IthVar( p->pAig, p->nVars-1 ); // create hash table p->nBins = Abc_PrimeCudd(5000); p->pBins = ABC_CALLOC( Aig_Tru_t *, p->nBins ); p->pMemTrus = Aig_MmFlexStart(); // bi-decomposition manager pPars->nVarsMax = p->nVars; pPars->fVerbose = 0; p->pBidec = Bdc_ManAlloc( pPars ); return p; } /**Function************************************************************* Synopsis [Returns the hash key.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_RManTableHash( unsigned * pTruth, int nVars, int nBins, int * pPrimes ) { int i, nWords = Kit_TruthWordNum( nVars ); unsigned uHash = 0; for ( i = 0; i < nWords; i++ ) uHash ^= pTruth[i] * pPrimes[i & 0xf]; return (int)(uHash % nBins); } /**Function************************************************************* Synopsis [Returns the given record.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Tru_t ** Aig_RManTableLookup( Aig_RMan_t * p, unsigned * pTruth, int nVars ) { static int s_Primes[16] = { 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 }; Aig_Tru_t ** ppSpot, * pEntry; ppSpot = p->pBins + Aig_RManTableHash( pTruth, nVars, p->nBins, s_Primes ); for ( pEntry = *ppSpot; pEntry; ppSpot = &pEntry->pNext, pEntry = pEntry->pNext ) if ( Kit_TruthIsEqual( pEntry->pTruth, pTruth, nVars ) ) return ppSpot; return ppSpot; } /**Function************************************************************* Synopsis [Find or add new entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_RManTableResize( Aig_RMan_t * p ) { Aig_Tru_t * pEntry, * pNext; Aig_Tru_t ** pBinsOld, ** ppPlace; int nBinsOld, Counter, i; abctime clk; assert( p->pBins != NULL ); clk = Abc_Clock(); // save the old Bins pBinsOld = p->pBins; nBinsOld = p->nBins; // get the new Bins p->nBins = Abc_PrimeCudd( 3 * nBinsOld ); p->pBins = ABC_CALLOC( Aig_Tru_t *, p->nBins ); // rehash the entries from the old table Counter = 0; for ( i = 0; i < nBinsOld; i++ ) for ( pEntry = pBinsOld[i], pNext = pEntry? pEntry->pNext : NULL; pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL ) { // get the place where this entry goes in the Bins ppPlace = Aig_RManTableLookup( p, pEntry->pTruth, pEntry->nVars ); assert( *ppPlace == NULL ); // should not be there // add the entry to the list *ppPlace = pEntry; pEntry->pNext = NULL; Counter++; } assert( Counter == p->nEntries ); // ABC_PRT( "Time", Abc_Clock() - clk ); ABC_FREE( pBinsOld ); } /**Function************************************************************* Synopsis [Find or add new entry.] Description [Returns 1 if this is a new entry.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_RManTableFindOrAdd( Aig_RMan_t * p, unsigned * pTruth, int nVars ) { Aig_Tru_t ** ppSpot, * pEntry; int nBytes; ppSpot = Aig_RManTableLookup( p, pTruth, nVars ); if ( *ppSpot ) { (*ppSpot)->nVisits++; return 0; } nBytes = sizeof(Aig_Tru_t) + sizeof(unsigned) * Kit_TruthWordNum(nVars); if ( p->nEntries == 3*p->nBins ) Aig_RManTableResize( p ); pEntry = (Aig_Tru_t *)Aig_MmFlexEntryFetch( p->pMemTrus, nBytes ); pEntry->Id = p->nEntries++; pEntry->nVars = nVars; pEntry->nVisits = 1; pEntry->pNext = NULL; memcpy( pEntry->pTruth, pTruth, sizeof(unsigned) * Kit_TruthWordNum(nVars) ); *ppSpot = pEntry; return 1; } /**Function************************************************************* Synopsis [Deallocates recording manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_RManStop( Aig_RMan_t * p ) { int i; printf( "Total funcs = %10d\n", p->nTotal ); printf( "Full DSD funcs = %10d\n", p->nTtDsd ); printf( "Part DSD funcs = %10d\n", p->nTtDsdPart ); printf( "Non- DSD funcs = %10d\n", p->nTtDsdNot ); printf( "Uniq-var funcs = %10d\n", p->nUniqueVars ); printf( "Unique funcs = %10d\n", p->nEntries ); printf( "Distribution of functions:\n" ); for ( i = 5; i <= p->nVars; i++ ) printf( "%2d = %8d\n", i, p->nVarFuncs[i] ); Aig_MmFlexStop( p->pMemTrus, 0 ); Aig_ManStop( p->pAig ); Bdc_ManFree( p->pBidec ); ABC_FREE( p->pBins ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Stops recording.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_RManQuit() { // extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); char Buffer[20]; if ( s_pRMan == NULL ) return; // dump the library file sprintf( Buffer, "aiglib%02d.aig", s_pRMan->nVars ); Ioa_WriteAiger( s_pRMan->pAig, Buffer, 0, 1 ); // quit the manager Aig_RManStop( s_pRMan ); s_pRMan = NULL; } /**Function************************************************************* Synopsis [Returns 1 if all variables are unique.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_RManPrintVarProfile( unsigned * pTruth, int nVars, unsigned * pTruthAux ) { int pStore2[32]; int i; Kit_TruthCountOnesInCofsSlow( pTruth, nVars, pStore2, pTruthAux ); for ( i = 0; i < nVars; i++ ) printf( "%2d/%2d ", pStore2[2*i], pStore2[2*i+1] ); printf( "\n" ); } /**Function************************************************************* Synopsis [Sorts numbers in the increasing order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_RManSortNums( int * pArray, int nVars ) { int i, j, best_i, tmp; for ( i = 0; i < nVars-1; i++ ) { best_i = i; for ( j = i+1; j < nVars; j++ ) if ( pArray[j] > pArray[best_i] ) best_i = j; tmp = pArray[i]; pArray[i] = pArray[best_i]; pArray[best_i] = tmp; } } /**Function************************************************************* Synopsis [Prints signatures for all variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_RManPrintSigs( Aig_VSig_t * pSigs, int nVars ) { int v, i, k; for ( v = 0; v < nVars; v++ ) { printf( "%2d : ", v ); for ( k = 0; k < 2; k++ ) { printf( "%5d ", pSigs[2*v+k].nOnes ); printf( "(" ); for ( i = 0; i < nVars; i++ ) printf( "%4d ", pSigs[2*v+k].nCofOnes[i] ); printf( ") " ); } printf( "\n" ); } } /**Function************************************************************* Synopsis [Computes signatures for all variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_RManComputeVSigs( unsigned * pTruth, int nVars, Aig_VSig_t * pSigs, unsigned * pAux ) { int v; for ( v = 0; v < nVars; v++ ) { Kit_TruthCofactor0New( pAux, pTruth, nVars, v ); pSigs[2*v+0].nOnes = Kit_TruthCountOnes( pAux, nVars ); Kit_TruthCountOnesInCofs0( pAux, nVars, pSigs[2*v+0].nCofOnes ); Aig_RManSortNums( pSigs[2*v+0].nCofOnes, nVars ); Kit_TruthCofactor1New( pAux, pTruth, nVars, v ); pSigs[2*v+1].nOnes = Kit_TruthCountOnes( pAux, nVars ); Kit_TruthCountOnesInCofs0( pAux, nVars, pSigs[2*v+1].nCofOnes ); Aig_RManSortNums( pSigs[2*v+1].nCofOnes, nVars ); } } /**Function************************************************************* Synopsis [Computs signatures for all variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_RManCompareSigs( Aig_VSig_t * p0, Aig_VSig_t * p1, int nVars ) { // return memcmp( p0, p1, sizeof(int) + sizeof(int) * nVars ); return memcmp( p0, p1, sizeof(int) ); } /**Function************************************************************* Synopsis [Returns 1 if all variables are unique.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_RManVarsAreUnique( Aig_VSig_t * pMints, int nVars ) { int i; for ( i = 0; i < nVars - 1; i++ ) if ( Aig_RManCompareSigs( &pMints[2*i], &pMints[2*(i+1)], nVars ) == 0 ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if all variables are unique.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_RManPrintUniqueVars( Aig_VSig_t * pMints, int nVars ) { int i; for ( i = 0; i < nVars; i++ ) if ( Aig_RManCompareSigs( &pMints[2*i], &pMints[2*i+1], nVars ) == 0 ) printf( "=" ); else printf( "x" ); printf( "\n" ); printf( "0" ); for ( i = 1; i < nVars; i++ ) if ( Aig_RManCompareSigs( &pMints[2*(i-1)], &pMints[2*i], nVars ) == 0 ) printf( "-" ); else if ( i < 10 ) printf( "%c", '0' + i ); else printf( "%c", 'A' + i-10 ); printf( "\n" ); } /**Function************************************************************* Synopsis [Canonicize the truth table.] Description [Returns the phase. ] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Aig_RManSemiCanonicize( unsigned * pOut, unsigned * pIn, int nVars, char * pCanonPerm, Aig_VSig_t * pSigs, int fReturnIn ) { Aig_VSig_t TempSig; int i, Temp, fChange, Counter; unsigned * pTemp, uCanonPhase = 0; // collect signatures Aig_RManComputeVSigs( pIn, nVars, pSigs, pOut ); // canonicize phase for ( i = 0; i < nVars; i++ ) { // if ( pStore[2*i+0] <= pStore[2*i+1] ) if ( Aig_RManCompareSigs( &pSigs[2*i+0], &pSigs[2*i+1], nVars ) <= 0 ) continue; uCanonPhase |= (1 << i); TempSig = pSigs[2*i+0]; pSigs[2*i+0] = pSigs[2*i+1]; pSigs[2*i+1] = TempSig; Kit_TruthChangePhase( pIn, nVars, i ); } // permute Counter = 0; do { fChange = 0; for ( i = 0; i < nVars-1; i++ ) { // if ( pStore[2*i] <= pStore[2*(i+1)] ) if ( Aig_RManCompareSigs( &pSigs[2*i], &pSigs[2*(i+1)], nVars ) <= 0 ) continue; Counter++; fChange = 1; Temp = pCanonPerm[i]; pCanonPerm[i] = pCanonPerm[i+1]; pCanonPerm[i+1] = Temp; TempSig = pSigs[2*i]; pSigs[2*i] = pSigs[2*(i+1)]; pSigs[2*(i+1)] = TempSig; TempSig = pSigs[2*i+1]; pSigs[2*i+1] = pSigs[2*(i+1)+1]; pSigs[2*(i+1)+1] = TempSig; Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); pTemp = pIn; pIn = pOut; pOut = pTemp; } } while ( fChange ); // swap if it was moved an even number of times if ( fReturnIn ^ !(Counter & 1) ) Kit_TruthCopy( pOut, pIn, nVars ); return uCanonPhase; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Aig_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj ) { return Aig_NotCond( (Aig_Obj_t *)Bdc_FuncCopy(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) ); } /**Function************************************************************* Synopsis [Records one function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_RManSaveOne( Aig_RMan_t * p, unsigned * pTruth, int nVars ) { int i, nNodes, RetValue; Bdc_Fun_t * pFunc; Aig_Obj_t * pTerm; // perform decomposition RetValue = Bdc_ManDecompose( p->pBidec, pTruth, NULL, nVars, NULL, 1000 ); if ( RetValue < 0 ) { printf( "Decomposition failed.\n" ); return; } // convert back into HOP Bdc_FuncSetCopy( Bdc_ManFunc( p->pBidec, 0 ), Aig_ManConst1(p->pAig) ); for ( i = 0; i < nVars; i++ ) Bdc_FuncSetCopy( Bdc_ManFunc( p->pBidec, i+1 ), Aig_IthVar(p->pAig, i) ); nNodes = Bdc_ManNodeNum(p->pBidec); for ( i = nVars + 1; i < nNodes; i++ ) { pFunc = Bdc_ManFunc( p->pBidec, i ); Bdc_FuncSetCopy( pFunc, Aig_And( p->pAig, Bdc_FunCopyHop(Bdc_FuncFanin0(pFunc)), Bdc_FunCopyHop(Bdc_FuncFanin1(pFunc)) ) ); } pTerm = Bdc_FunCopyHop( Bdc_ManRoot(p->pBidec) ); pTerm = Aig_ObjCreateCo( p->pAig, pTerm ); // assert( pTerm->fPhase == 0 ); } /**Function************************************************************* Synopsis [Records one function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_RManRecord( unsigned * pTruth, int nVarsInit ) { int fVerify = 1; Kit_DsdNtk_t * pNtk; Kit_DsdObj_t * pObj; unsigned uPhaseC; int i, nVars, nWords; int fUniqueVars; if ( nVarsInit > RMAN_MAXVARS ) { printf( "The number of variables in too large.\n" ); return; } if ( s_pRMan == NULL ) s_pRMan = Aig_RManStart(); s_pRMan->nTotal++; // canonicize the function pNtk = Kit_DsdDecompose( pTruth, nVarsInit ); pObj = Kit_DsdNonDsdPrimeMax( pNtk ); if ( pObj == NULL || pObj->nFans == 3 ) { s_pRMan->nTtDsd++; Kit_DsdNtkFree( pNtk ); return; } nVars = pObj->nFans; s_pRMan->nVarFuncs[nVars]++; if ( nVars < nVarsInit ) s_pRMan->nTtDsdPart++; else s_pRMan->nTtDsdNot++; // compute the number of words nWords = Abc_TruthWordNum( nVars ); // copy the function memcpy( s_pRMan->pTruthInit, Kit_DsdObjTruth(pObj), (size_t)(4*nWords) ); Kit_DsdNtkFree( pNtk ); // canonicize the output if ( s_pRMan->pTruthInit[0] & 1 ) Kit_TruthNot( s_pRMan->pTruthInit, s_pRMan->pTruthInit, nVars ); memcpy( s_pRMan->pTruth, s_pRMan->pTruthInit, 4*nWords ); // canonize the function for ( i = 0; i < nVars; i++ ) s_pRMan->pPerm[i] = i; uPhaseC = Aig_RManSemiCanonicize( s_pRMan->pTruthTemp, s_pRMan->pTruth, nVars, s_pRMan->pPerm, s_pRMan->pMints, 1 ); // check unique variables fUniqueVars = Aig_RManVarsAreUnique( s_pRMan->pMints, nVars ); s_pRMan->nUniqueVars += fUniqueVars; /* printf( "%4d : ", s_pRMan->nTotal ); printf( "%2d %2d ", nVarsInit, nVars ); Extra_PrintBinary( stdout, &uPhaseC, nVars ); printf( " " ); for ( i = 0; i < nVars; i++ ) printf( "%2d/%2d ", s_pRMan->pMints[2*i], s_pRMan->pMints[2*i+1] ); printf( "\n" ); Aig_RManPrintUniqueVars( s_pRMan->pMints, nVars ); Extra_PrintBinary( stdout, s_pRMan->pTruth, 1<nTotal ); printf( "%2d %2d ", nVarsInit, nVars ); printf( " " ); printf( "\n" ); Aig_RManPrintUniqueVars( s_pRMan->pMints, nVars ); // Aig_RManPrintSigs( s_pRMan->pMints, nVars ); */ //Extra_PrintBinary( stdout, s_pRMan->pTruth, 1<pTruth, nVars ) ) Aig_RManSaveOne( s_pRMan, s_pRMan->pTruth, nVars ); if ( fVerify ) { // derive reverse permutation for ( i = 0; i < nVars; i++ ) s_pRMan->pPermR[i] = s_pRMan->pPerm[i]; // implement permutation Kit_TruthPermute( s_pRMan->pTruthTemp, s_pRMan->pTruth, nVars, s_pRMan->pPermR, 1 ); // implement polarity for ( i = 0; i < nVars; i++ ) if ( uPhaseC & (1 << i) ) Kit_TruthChangePhase( s_pRMan->pTruth, nVars, i ); // perform verification if ( fUniqueVars && !Kit_TruthIsEqual( s_pRMan->pTruth, s_pRMan->pTruthInit, nVars ) ) printf( "Verification failed.\n" ); } //Aig_RManPrintVarProfile( s_pRMan->pTruth, nVars, s_pRMan->pTruthTemp ); //Extra_PrintBinary( stdout, s_pRMan->pTruth, 1<Id >= Aig_ObjFanin1(pObj)->Id ) { printf( "Aig_ManCheck: The AIG has node \"%p\" with a wrong ordering of fanins.\n", pObj ); return 0; } pObj2 = Aig_TableLookup( p, pObj ); if ( pObj2 != pObj ) { printf( "Aig_ManCheck: Node \"%p\" is not in the structural hashing table.\n", pObj ); return 0; } } // count the total number of nodes if ( Aig_ManObjNum(p) != 1 + Aig_ManCiNum(p) + Aig_ManCoNum(p) + Aig_ManBufNum(p) + Aig_ManAndNum(p) + Aig_ManExorNum(p) ) { printf( "Aig_ManCheck: The number of created nodes is wrong.\n" ); printf( "C1 = %d. Pi = %d. Po = %d. Buf = %d. And = %d. Xor = %d. Total = %d.\n", 1, Aig_ManCiNum(p), Aig_ManCoNum(p), Aig_ManBufNum(p), Aig_ManAndNum(p), Aig_ManExorNum(p), 1 + Aig_ManCiNum(p) + Aig_ManCoNum(p) + Aig_ManBufNum(p) + Aig_ManAndNum(p) + Aig_ManExorNum(p) ); printf( "Created = %d. Deleted = %d. Existing = %d.\n", Aig_ManObjNumMax(p), p->nDeleted, Aig_ManObjNum(p) ); return 0; } // count the number of nodes in the table if ( Aig_TableCountEntries(p) != Aig_ManAndNum(p) + Aig_ManExorNum(p) ) { printf( "Aig_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); printf( "Entries = %d. And = %d. Xor = %d. Total = %d.\n", Aig_TableCountEntries(p), Aig_ManAndNum(p), Aig_ManExorNum(p), Aig_ManAndNum(p) + Aig_ManExorNum(p) ); return 0; } // if ( !Aig_ManIsAcyclic(p) ) // return 0; return 1; } /**Function************************************************************* Synopsis [Checks if the markA is reset.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManCheckMarkA( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManForEachObj( p, pObj, i ) assert( pObj->fMarkA == 0 ); } /**Function************************************************************* Synopsis [Checks the consistency of phase assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManCheckPhase( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManForEachObj( p, pObj, i ) if ( Aig_ObjIsCi(pObj) ) assert( (int)pObj->fPhase == 0 ); else assert( (int)pObj->fPhase == (Aig_ObjPhaseReal(Aig_ObjChild0(pObj)) & Aig_ObjPhaseReal(Aig_ObjChild1(pObj))) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigCuts.c000066400000000000000000000456171477524141600160470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigCuts.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Computation of K-feasible priority cuts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigCuts.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the cut sweeping manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_ManCut_t * Aig_ManCutStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fTruth, int fVerbose ) { Aig_ManCut_t * p; assert( nCutsMax >= 2 ); assert( nLeafMax <= 16 ); // allocate the fraiging manager p = ABC_ALLOC( Aig_ManCut_t, 1 ); memset( p, 0, sizeof(Aig_ManCut_t) ); p->nCutsMax = nCutsMax; p->nLeafMax = nLeafMax; p->fTruth = fTruth; p->fVerbose = fVerbose; p->pAig = pMan; p->pCuts = ABC_CALLOC( Aig_Cut_t *, Aig_ManObjNumMax(pMan) ); // allocate memory manager p->nTruthWords = Abc_TruthWordNum(nLeafMax); p->nCutSize = sizeof(Aig_Cut_t) + sizeof(int) * nLeafMax + fTruth * sizeof(unsigned) * p->nTruthWords; p->pMemCuts = Aig_MmFixedStart( p->nCutSize * p->nCutsMax, 512 ); // room for temporary truth tables if ( fTruth ) { p->puTemp[0] = ABC_ALLOC( unsigned, 4 * p->nTruthWords ); p->puTemp[1] = p->puTemp[0] + p->nTruthWords; p->puTemp[2] = p->puTemp[1] + p->nTruthWords; p->puTemp[3] = p->puTemp[2] + p->nTruthWords; } return p; } /**Function************************************************************* Synopsis [Stops the fraiging manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManCutStop( Aig_ManCut_t * p ) { Aig_MmFixedStop( p->pMemCuts, 0 ); ABC_FREE( p->puTemp[0] ); ABC_FREE( p->pCuts ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_CutPrint( Aig_Cut_t * pCut ) { int i; printf( "{" ); for ( i = 0; i < pCut->nFanins; i++ ) printf( " %d", pCut->pFanins[i] ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Prints one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjCutPrint( Aig_ManCut_t * p, Aig_Obj_t * pObj ) { Aig_Cut_t * pCut; int i; printf( "Cuts for node %d:\n", pObj->Id ); Aig_ObjForEachCut( p, pObj, pCut, i ) if ( pCut->nFanins ) Aig_CutPrint( pCut ); // printf( "\n" ); } /**Function************************************************************* Synopsis [Computes the total number of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManCutCount( Aig_ManCut_t * p, int * pnCutsK ) { Aig_Cut_t * pCut; Aig_Obj_t * pObj; int i, k, nCuts = 0, nCutsK = 0; Aig_ManForEachNode( p->pAig, pObj, i ) Aig_ObjForEachCut( p, pObj, pCut, k ) { if ( pCut->nFanins == 0 ) continue; nCuts++; if ( pCut->nFanins == p->nLeafMax ) nCutsK++; } if ( pnCutsK ) *pnCutsK = nCutsK; return nCuts; } /**Function************************************************************* Synopsis [Compute the cost of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_CutFindCost( Aig_ManCut_t * p, Aig_Cut_t * pCut ) { Aig_Obj_t * pLeaf; int i, Cost = 0; assert( pCut->nFanins > 0 ); Aig_CutForEachLeaf( p->pAig, pCut, pLeaf, i ) Cost += pLeaf->nRefs; return Cost * 1000 / pCut->nFanins; } /**Function************************************************************* Synopsis [Compute the cost of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline float Aig_CutFindCost2( Aig_ManCut_t * p, Aig_Cut_t * pCut ) { Aig_Obj_t * pLeaf; float Cost = 0.0; int i; assert( pCut->nFanins > 0 ); Aig_CutForEachLeaf( p->pAig, pCut, pLeaf, i ) Cost += (float)1.0/pLeaf->nRefs; return 1/Cost; } /**Function************************************************************* Synopsis [Returns the next free cut to use.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Aig_Cut_t * Aig_CutFindFree( Aig_ManCut_t * p, Aig_Obj_t * pObj ) { Aig_Cut_t * pCut, * pCutMax; int i; pCutMax = NULL; Aig_ObjForEachCut( p, pObj, pCut, i ) { if ( pCut->nFanins == 0 ) return pCut; if ( pCutMax == NULL || pCutMax->Cost < pCut->Cost ) pCutMax = pCut; } assert( pCutMax != NULL ); pCutMax->nFanins = 0; return pCutMax; } /**Function************************************************************* Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Aig_CutTruthPhase( Aig_Cut_t * pCut, Aig_Cut_t * pCut1 ) { unsigned uPhase = 0; int i, k; for ( i = k = 0; i < pCut->nFanins; i++ ) { if ( k == pCut1->nFanins ) break; if ( pCut->pFanins[i] < pCut1->pFanins[k] ) continue; assert( pCut->pFanins[i] == pCut1->pFanins[k] ); uPhase |= (1 << i); k++; } return uPhase; } /**Function************************************************************* Synopsis [Performs truth table computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Aig_CutComputeTruth( Aig_ManCut_t * p, Aig_Cut_t * pCut, Aig_Cut_t * pCut0, Aig_Cut_t * pCut1, int fCompl0, int fCompl1 ) { // permute the first table if ( fCompl0 ) Kit_TruthNot( p->puTemp[0], Aig_CutTruth(pCut0), p->nLeafMax ); else Kit_TruthCopy( p->puTemp[0], Aig_CutTruth(pCut0), p->nLeafMax ); Kit_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nFanins, p->nLeafMax, Aig_CutTruthPhase(pCut, pCut0), 0 ); // permute the second table if ( fCompl1 ) Kit_TruthNot( p->puTemp[1], Aig_CutTruth(pCut1), p->nLeafMax ); else Kit_TruthCopy( p->puTemp[1], Aig_CutTruth(pCut1), p->nLeafMax ); Kit_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nFanins, p->nLeafMax, Aig_CutTruthPhase(pCut, pCut1), 0 ); // produce the resulting table Kit_TruthAnd( Aig_CutTruth(pCut), p->puTemp[2], p->puTemp[3], p->nLeafMax ); // assert( pCut->nFanins >= Kit_TruthSupportSize( Aig_CutTruth(pCut), p->nLeafMax ) ); return Aig_CutTruth(pCut); } /**Function************************************************************* Synopsis [Performs support minimization for the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_CutSupportMinimize( Aig_ManCut_t * p, Aig_Cut_t * pCut ) { unsigned * pTruth; int uSupp, nFansNew, i, k; // get truth table pTruth = Aig_CutTruth( pCut ); // get support uSupp = Kit_TruthSupport( pTruth, p->nLeafMax ); // get the new support size nFansNew = Kit_WordCountOnes( uSupp ); // check if there are redundant variables if ( nFansNew == pCut->nFanins ) return nFansNew; assert( nFansNew < pCut->nFanins ); // minimize support Kit_TruthShrink( p->puTemp[0], pTruth, nFansNew, p->nLeafMax, uSupp, 1 ); for ( i = k = 0; i < pCut->nFanins; i++ ) if ( uSupp & (1 << i) ) pCut->pFanins[k++] = pCut->pFanins[i]; assert( k == nFansNew ); pCut->nFanins = nFansNew; // assert( nFansNew == Kit_TruthSupportSize( pTruth, p->nLeafMax ) ); //Extra_PrintBinary( stdout, pTruth, (1<nLeafMax) ); printf( "\n" ); return nFansNew; } /**Function************************************************************* Synopsis [Returns 1 if pDom is contained in pCut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_CutCheckDominance( Aig_Cut_t * pDom, Aig_Cut_t * pCut ) { int i, k; for ( i = 0; i < (int)pDom->nFanins; i++ ) { for ( k = 0; k < (int)pCut->nFanins; k++ ) if ( pDom->pFanins[i] == pCut->pFanins[k] ) break; if ( k == (int)pCut->nFanins ) // node i in pDom is not contained in pCut return 0; } // every node in pDom is contained in pCut return 1; } /**Function************************************************************* Synopsis [Returns 1 if the cut is contained.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_CutFilter( Aig_ManCut_t * p, Aig_Obj_t * pObj, Aig_Cut_t * pCut ) { Aig_Cut_t * pTemp; int i; // go through the cuts of the node Aig_ObjForEachCut( p, pObj, pTemp, i ) { if ( pTemp->nFanins < 2 ) continue; if ( pTemp == pCut ) continue; if ( pTemp->nFanins > pCut->nFanins ) { // skip the non-contained cuts if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) continue; // check containment seriously if ( Aig_CutCheckDominance( pCut, pTemp ) ) { // remove contained cut pTemp->nFanins = 0; } } else { // skip the non-contained cuts if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) continue; // check containment seriously if ( Aig_CutCheckDominance( pTemp, pCut ) ) { // remove the given pCut->nFanins = 0; return 1; } } } return 0; } /**Function************************************************************* Synopsis [Merges two cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_CutMergeOrdered( Aig_ManCut_t * p, Aig_Cut_t * pC0, Aig_Cut_t * pC1, Aig_Cut_t * pC ) { int i, k, c; assert( pC0->nFanins >= pC1->nFanins ); // the case of the largest cut sizes if ( pC0->nFanins == p->nLeafMax && pC1->nFanins == p->nLeafMax ) { for ( i = 0; i < pC0->nFanins; i++ ) if ( pC0->pFanins[i] != pC1->pFanins[i] ) return 0; for ( i = 0; i < pC0->nFanins; i++ ) pC->pFanins[i] = pC0->pFanins[i]; pC->nFanins = pC0->nFanins; return 1; } // the case when one of the cuts is the largest if ( pC0->nFanins == p->nLeafMax ) { for ( i = 0; i < pC1->nFanins; i++ ) { for ( k = pC0->nFanins - 1; k >= 0; k-- ) if ( pC0->pFanins[k] == pC1->pFanins[i] ) break; if ( k == -1 ) // did not find return 0; } for ( i = 0; i < pC0->nFanins; i++ ) pC->pFanins[i] = pC0->pFanins[i]; pC->nFanins = pC0->nFanins; return 1; } // compare two cuts with different numbers i = k = 0; for ( c = 0; c < p->nLeafMax; c++ ) { if ( k == pC1->nFanins ) { if ( i == pC0->nFanins ) { pC->nFanins = c; return 1; } pC->pFanins[c] = pC0->pFanins[i++]; continue; } if ( i == pC0->nFanins ) { if ( k == pC1->nFanins ) { pC->nFanins = c; return 1; } pC->pFanins[c] = pC1->pFanins[k++]; continue; } if ( pC0->pFanins[i] < pC1->pFanins[k] ) { pC->pFanins[c] = pC0->pFanins[i++]; continue; } if ( pC0->pFanins[i] > pC1->pFanins[k] ) { pC->pFanins[c] = pC1->pFanins[k++]; continue; } pC->pFanins[c] = pC0->pFanins[i++]; k++; } if ( i < pC0->nFanins || k < pC1->nFanins ) return 0; pC->nFanins = c; return 1; } /**Function************************************************************* Synopsis [Prepares the object for FPGA mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_CutMerge( Aig_ManCut_t * p, Aig_Cut_t * pCut0, Aig_Cut_t * pCut1, Aig_Cut_t * pCut ) { assert( p->nLeafMax > 0 ); // merge the nodes if ( pCut0->nFanins < pCut1->nFanins ) { if ( !Aig_CutMergeOrdered( p, pCut1, pCut0, pCut ) ) return 0; } else { if ( !Aig_CutMergeOrdered( p, pCut0, pCut1, pCut ) ) return 0; } pCut->uSign = pCut0->uSign | pCut1->uSign; return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Cut_t * Aig_ObjPrepareCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, int fTriv ) { Aig_Cut_t * pCutSet, * pCut; int i; // create the cutset of the node pCutSet = (Aig_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts ); Aig_ObjSetCuts( p, pObj, pCutSet ); Aig_ObjForEachCut( p, pObj, pCut, i ) { pCut->nFanins = 0; pCut->iNode = pObj->Id; pCut->nCutSize = p->nCutSize; pCut->nLeafMax = p->nLeafMax; } // add unit cut if needed if ( fTriv ) { pCut = pCutSet; pCut->Cost = 0; pCut->iNode = pObj->Id; pCut->nFanins = 1; pCut->pFanins[0] = pObj->Id; pCut->uSign = Aig_ObjCutSign( pObj->Id ); if ( p->fTruth ) memset( Aig_CutTruth(pCut), 0xAA, sizeof(unsigned) * p->nTruthWords ); } return pCutSet; } /**Function************************************************************* Synopsis [Derives cuts for one node and sweeps this node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjComputeCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, int fTriv ) { Aig_Cut_t * pCut0, * pCut1, * pCut, * pCutSet; Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj); Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj); int i, k; // the node is not processed yet assert( Aig_ObjIsNode(pObj) ); assert( Aig_ObjCuts(p, pObj) == NULL ); // set up the first cut pCutSet = Aig_ObjPrepareCuts( p, pObj, fTriv ); // compute pair-wise cut combinations while checking table Aig_ObjForEachCut( p, pFanin0, pCut0, i ) if ( pCut0->nFanins > 0 ) Aig_ObjForEachCut( p, pFanin1, pCut1, k ) if ( pCut1->nFanins > 0 ) { // make sure K-feasible cut exists if ( Kit_WordCountOnes(pCut0->uSign | pCut1->uSign) > p->nLeafMax ) continue; // get the next cut of this node pCut = Aig_CutFindFree( p, pObj ); // assemble the new cut if ( !Aig_CutMerge( p, pCut0, pCut1, pCut ) ) { assert( pCut->nFanins == 0 ); continue; } // check containment if ( Aig_CutFilter( p, pObj, pCut ) ) { assert( pCut->nFanins == 0 ); continue; } // create its truth table if ( p->fTruth ) Aig_CutComputeTruth( p, pCut, pCut0, pCut1, Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) ); // assign the cost pCut->Cost = Aig_CutFindCost( p, pCut ); assert( pCut->nFanins > 0 ); assert( pCut->Cost > 0 ); } } /**Function************************************************************* Synopsis [Computes the cuts for all nodes in the static AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_ManCut_t * Aig_ComputeCuts( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fTruth, int fVerbose ) { Aig_ManCut_t * p; Aig_Obj_t * pObj; int i; abctime clk = Abc_Clock(); assert( pAig->pManCuts == NULL ); // start the manager p = Aig_ManCutStart( pAig, nCutsMax, nLeafMax, fTruth, fVerbose ); // set elementary cuts at the PIs Aig_ManForEachCi( pAig, pObj, i ) Aig_ObjPrepareCuts( p, pObj, 1 ); // process the nodes Aig_ManForEachNode( pAig, pObj, i ) Aig_ObjComputeCuts( p, pObj, 1 ); // print stats if ( fVerbose ) { int nCuts, nCutsK; nCuts = Aig_ManCutCount( p, &nCutsK ); printf( "Nodes = %6d. Total cuts = %6d. %d-input cuts = %6d.\n", Aig_ManObjNum(pAig), nCuts, nLeafMax, nCutsK ); printf( "Cut size = %2d. Truth size = %2d. Total mem = %5.2f MB ", p->nCutSize, 4*p->nTruthWords, 1.0*Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) ); ABC_PRT( "Runtime", Abc_Clock() - clk ); /* Aig_ManForEachNode( pAig, pObj, i ) if ( i % 300 == 0 ) Aig_ObjCutPrint( p, pObj ); */ } // remember the cut manager pAig->pManCuts = p; return p; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigDfs.c000066400000000000000000001022421477524141600156310ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigDfs.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [DFS traversal procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigDfs.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" #include "misc/tim/tim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Verifies that the objects are in a topo order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManVerifyTopoOrder( Aig_Man_t * p ) { Aig_Obj_t * pObj, * pNext; int i, k, iBox, iTerm1, nTerms; Aig_ManSetCioIds( p ); Aig_ManIncrementTravId( p ); Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjIsNode(pObj) ) { pNext = Aig_ObjFanin0(pObj); if ( !Aig_ObjIsTravIdCurrent(p,pNext) ) { printf( "Node %d has fanin %d that is not in a topological order.\n", pObj->Id, pNext->Id ); return 0; } pNext = Aig_ObjFanin1(pObj); if ( !Aig_ObjIsTravIdCurrent(p,pNext) ) { printf( "Node %d has fanin %d that is not in a topological order.\n", pObj->Id, pNext->Id ); return 0; } } else if ( Aig_ObjIsCo(pObj) || Aig_ObjIsBuf(pObj) ) { pNext = Aig_ObjFanin0(pObj); if ( !Aig_ObjIsTravIdCurrent(p,pNext) ) { printf( "Node %d has fanin %d that is not in a topological order.\n", pObj->Id, pNext->Id ); return 0; } } else if ( Aig_ObjIsCi(pObj) ) { if ( p->pManTime ) { iBox = Tim_ManBoxForCi( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pObj) ); if ( iBox >= 0 ) // this is not a true PI { iTerm1 = Tim_ManBoxInputFirst( (Tim_Man_t *)p->pManTime, iBox ); nTerms = Tim_ManBoxInputNum( (Tim_Man_t *)p->pManTime, iBox ); for ( k = 0; k < nTerms; k++ ) { pNext = Aig_ManCo( p, iTerm1 + k ); assert( Tim_ManBoxForCo( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pNext) ) == iBox ); if ( !Aig_ObjIsTravIdCurrent(p,pNext) ) { printf( "Box %d has input %d that is not in a topological order.\n", iBox, pNext->Id ); return 0; } } } } } else if ( !Aig_ObjIsConst1(pObj) ) assert( 0 ); Aig_ObjSetTravIdCurrent( p, pObj ); } Aig_ManCleanCioIds( p ); return 1; } /**Function************************************************************* Synopsis [Collects internal nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManDfs_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) { if ( pObj == NULL ) return; assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); if ( p->pEquivs && Aig_ObjEquiv(p, pObj) ) Aig_ManDfs_rec( p, Aig_ObjEquiv(p, pObj), vNodes ); Aig_ManDfs_rec( p, Aig_ObjFanin0(pObj), vNodes ); Aig_ManDfs_rec( p, Aig_ObjFanin1(pObj), vNodes ); Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [Collects objects of the AIG in the DFS order.] Description [Works with choice nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p, int fNodesOnly ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; Aig_ManIncrementTravId( p ); Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); // start the array of nodes vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) ); // mark PIs if they should not be collected if ( fNodesOnly ) Aig_ManForEachCi( p, pObj, i ) Aig_ObjSetTravIdCurrent( p, pObj ); else Vec_PtrPush( vNodes, Aig_ManConst1(p) ); // collect nodes reachable in the DFS order Aig_ManForEachCo( p, pObj, i ) Aig_ManDfs_rec( p, fNodesOnly? Aig_ObjFanin0(pObj): pObj, vNodes ); if ( fNodesOnly ) assert( Vec_PtrSize(vNodes) == Aig_ManNodeNum(p) ); else assert( Vec_PtrSize(vNodes) == Aig_ManObjNum(p) ); return vNodes; } /**Function************************************************************* Synopsis [Collects internal nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManDfsAll_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); if ( Aig_ObjIsCi(pObj) ) { Vec_PtrPush( vNodes, pObj ); return; } if ( Aig_ObjIsCo(pObj) ) { Aig_ManDfsAll_rec( p, Aig_ObjFanin0(pObj), vNodes ); Vec_PtrPush( vNodes, pObj ); return; } assert( Aig_ObjIsNode(pObj) ); Aig_ManDfsAll_rec( p, Aig_ObjFanin0(pObj), vNodes ); Aig_ManDfsAll_rec( p, Aig_ObjFanin1(pObj), vNodes ); Vec_PtrPush( vNodes, pObj ); } Vec_Ptr_t * Aig_ManDfsArray( Aig_Man_t * p, Aig_Obj_t ** pNodes, int nNodes ) { Vec_Ptr_t * vNodes; int i; Aig_ManIncrementTravId( p ); vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) ); // add constant Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); Vec_PtrPush( vNodes, Aig_ManConst1(p) ); // collect nodes reachable in the DFS order for ( i = 0; i < nNodes; i++ ) Aig_ManDfsAll_rec( p, pNodes[i], vNodes ); return vNodes; } /**Function************************************************************* Synopsis [Collects objects of the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManDfsAll( Aig_Man_t * p ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; Aig_ManIncrementTravId( p ); vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) ); // add constant Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); Vec_PtrPush( vNodes, Aig_ManConst1(p) ); // collect nodes reachable in the DFS order Aig_ManForEachCo( p, pObj, i ) Aig_ManDfsAll_rec( p, pObj, vNodes ); Aig_ManForEachCi( p, pObj, i ) if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) Vec_PtrPush( vNodes, pObj ); assert( Vec_PtrSize(vNodes) == Aig_ManObjNum(p) ); return vNodes; } /**Function************************************************************* Synopsis [Collects internal nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManDfsPreorder_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) { if ( pObj == NULL ) return; assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); Vec_PtrPush( vNodes, pObj ); if ( p->pEquivs && Aig_ObjEquiv(p, pObj) ) Aig_ManDfs_rec( p, Aig_ObjEquiv(p, pObj), vNodes ); Aig_ManDfsPreorder_rec( p, Aig_ObjFanin0(pObj), vNodes ); Aig_ManDfsPreorder_rec( p, Aig_ObjFanin1(pObj), vNodes ); } /**Function************************************************************* Synopsis [Collects objects of the AIG in the DFS order.] Description [Works with choice nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManDfsPreorder( Aig_Man_t * p, int fNodesOnly ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; Aig_ManIncrementTravId( p ); Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); // start the array of nodes vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) ); // mark PIs if they should not be collected if ( fNodesOnly ) Aig_ManForEachCi( p, pObj, i ) Aig_ObjSetTravIdCurrent( p, pObj ); else Vec_PtrPush( vNodes, Aig_ManConst1(p) ); // collect nodes reachable in the DFS order Aig_ManForEachCo( p, pObj, i ) Aig_ManDfsPreorder_rec( p, fNodesOnly? Aig_ObjFanin0(pObj): pObj, vNodes ); if ( fNodesOnly ) assert( Vec_PtrSize(vNodes) == Aig_ManNodeNum(p) ); else assert( Vec_PtrSize(vNodes) == Aig_ManObjNum(p) ); return vNodes; } /**Function************************************************************* Synopsis [Levelizes the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Aig_ManLevelize( Aig_Man_t * p ) { Aig_Obj_t * pObj; Vec_Vec_t * vLevels; int nLevels, i; nLevels = Aig_ManLevelNum( p ); vLevels = Vec_VecStart( nLevels + 1 ); Aig_ManForEachObj( p, pObj, i ) { assert( (int)pObj->Level <= nLevels ); Vec_VecPush( vLevels, pObj->Level, pObj ); } return vLevels; } /**Function************************************************************* Synopsis [Collects internal nodes and PIs in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManDfsNodes( Aig_Man_t * p, Aig_Obj_t ** ppNodes, int nNodes ) { Vec_Ptr_t * vNodes; // Aig_Obj_t * pObj; int i; Aig_ManIncrementTravId( p ); // mark constant and PIs Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); // Aig_ManForEachCi( p, pObj, i ) // Aig_ObjSetTravIdCurrent( p, pObj ); // go through the nodes vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); for ( i = 0; i < nNodes; i++ ) if ( Aig_ObjIsCo(ppNodes[i]) ) Aig_ManDfs_rec( p, Aig_ObjFanin0(ppNodes[i]), vNodes ); else Aig_ManDfs_rec( p, ppNodes[i], vNodes ); return vNodes; } /**Function************************************************************* Synopsis [Collects internal nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManDfsChoices_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) { if ( pObj == NULL ) return; assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; assert( Aig_ObjIsNode(pObj) ); Aig_ManDfsChoices_rec( p, Aig_ObjFanin0(pObj), vNodes ); Aig_ManDfsChoices_rec( p, Aig_ObjFanin1(pObj), vNodes ); Aig_ManDfsChoices_rec( p, Aig_ObjEquiv(p, pObj), vNodes ); assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection Aig_ObjSetTravIdCurrent(p, pObj); Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [Collects internal nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManDfsChoices( Aig_Man_t * p ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i, Counter = 0; Aig_ManForEachNode( p, pObj, i ) { if ( Aig_ObjEquiv(p, pObj) == NULL ) continue; Counter = 0; for ( pObj = Aig_ObjEquiv(p, pObj) ; pObj; pObj = Aig_ObjEquiv(p, pObj) ) Counter++; // printf( "%d ", Counter ); } // printf( "\n" ); assert( p->pEquivs != NULL ); Aig_ManIncrementTravId( p ); // mark constant and PIs Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); Aig_ManForEachCi( p, pObj, i ) Aig_ObjSetTravIdCurrent( p, pObj ); // go through the nodes vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); Aig_ManForEachCo( p, pObj, i ) Aig_ManDfsChoices_rec( p, Aig_ObjFanin0(pObj), vNodes ); return vNodes; } /**Function************************************************************* Synopsis [Collects internal nodes in the reverse DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManDfsReverse_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) { Aig_Obj_t * pFanout; int iFanout = -1, i; assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ); Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) Aig_ManDfsReverse_rec( p, pFanout, vNodes ); assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection Aig_ObjSetTravIdCurrent(p, pObj); Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [Collects internal nodes in the reverse DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManDfsReverse( Aig_Man_t * p ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; Aig_ManIncrementTravId( p ); // mark POs Aig_ManForEachCo( p, pObj, i ) Aig_ObjSetTravIdCurrent( p, pObj ); // go through the nodes vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); Aig_ManForEachObj( p, pObj, i ) if ( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ) Aig_ManDfsReverse_rec( p, pObj, vNodes ); return vNodes; } /**Function************************************************************* Synopsis [Computes the max number of levels in the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManLevelNum( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, LevelsMax; LevelsMax = 0; Aig_ManForEachCo( p, pObj, i ) LevelsMax = Abc_MaxInt( LevelsMax, (int)Aig_ObjFanin0(pObj)->Level ); return LevelsMax; } //#if 0 /**Function************************************************************* Synopsis [Computes levels for AIG with choices and white boxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManChoiceLevel_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pNext; int i, iBox, iTerm1, nTerms, LevelMax = 0; if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) return; Aig_ObjSetTravIdCurrent( p, pObj ); if ( Aig_ObjIsCi(pObj) ) { if ( p->pManTime ) { iBox = Tim_ManBoxForCi( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pObj) ); if ( iBox >= 0 ) // this is not a true PI { iTerm1 = Tim_ManBoxInputFirst( (Tim_Man_t *)p->pManTime, iBox ); nTerms = Tim_ManBoxInputNum( (Tim_Man_t *)p->pManTime, iBox ); for ( i = 0; i < nTerms; i++ ) { pNext = Aig_ManCo(p, iTerm1 + i); Aig_ManChoiceLevel_rec( p, pNext ); if ( LevelMax < Aig_ObjLevel(pNext) ) LevelMax = Aig_ObjLevel(pNext); } LevelMax++; } } // printf( "%d ", pObj->Level ); } else if ( Aig_ObjIsCo(pObj) ) { pNext = Aig_ObjFanin0(pObj); Aig_ManChoiceLevel_rec( p, pNext ); if ( LevelMax < Aig_ObjLevel(pNext) ) LevelMax = Aig_ObjLevel(pNext); } else if ( Aig_ObjIsNode(pObj) ) { // get the maximum level of the two fanins pNext = Aig_ObjFanin0(pObj); Aig_ManChoiceLevel_rec( p, pNext ); if ( LevelMax < Aig_ObjLevel(pNext) ) LevelMax = Aig_ObjLevel(pNext); pNext = Aig_ObjFanin1(pObj); Aig_ManChoiceLevel_rec( p, pNext ); if ( LevelMax < Aig_ObjLevel(pNext) ) LevelMax = Aig_ObjLevel(pNext); LevelMax++; // get the level of the nodes in the choice node if ( p->pEquivs && (pNext = Aig_ObjEquiv(p, pObj)) ) { Aig_ManChoiceLevel_rec( p, pNext ); if ( LevelMax < Aig_ObjLevel(pNext) ) LevelMax = Aig_ObjLevel(pNext); } } else if ( !Aig_ObjIsConst1(pObj) ) assert( 0 ); Aig_ObjSetLevel( pObj, LevelMax ); } /**Function************************************************************* Synopsis [Computes levels for AIG with choices and white boxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManChoiceLevel( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, LevelMax = 0; Aig_ManForEachObj( p, pObj, i ) Aig_ObjSetLevel( pObj, 0 ); Aig_ManSetCioIds( p ); Aig_ManIncrementTravId( p ); Aig_ManForEachCo( p, pObj, i ) { Aig_ManChoiceLevel_rec( p, pObj ); if ( LevelMax < Aig_ObjLevel(pObj) ) LevelMax = Aig_ObjLevel(pObj); } // account for dangling boxes Aig_ManForEachCi( p, pObj, i ) { Aig_ManChoiceLevel_rec( p, pObj ); if ( LevelMax < Aig_ObjLevel(pObj) ) LevelMax = Aig_ObjLevel(pObj); } Aig_ManCleanCioIds( p ); // Aig_ManForEachNode( p, pObj, i ) // assert( Aig_ObjLevel(pObj) > 0 ); return LevelMax; } //#endif /**Function************************************************************* Synopsis [Counts the number of AIG nodes rooted at this cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ConeMark_rec( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) return; Aig_ConeMark_rec( Aig_ObjFanin0(pObj) ); Aig_ConeMark_rec( Aig_ObjFanin1(pObj) ); assert( !Aig_ObjIsMarkA(pObj) ); // loop detection Aig_ObjSetMarkA( pObj ); } /**Function************************************************************* Synopsis [Counts the number of AIG nodes rooted at this cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ConeCleanAndMark_rec( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) return; Aig_ConeCleanAndMark_rec( Aig_ObjFanin0(pObj) ); Aig_ConeCleanAndMark_rec( Aig_ObjFanin1(pObj) ); assert( !Aig_ObjIsMarkA(pObj) ); // loop detection Aig_ObjSetMarkA( pObj ); pObj->pData = NULL; } /**Function************************************************************* Synopsis [Counts the number of AIG nodes rooted at this cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ConeCountAndMark_rec( Aig_Obj_t * pObj ) { int Counter; assert( !Aig_IsComplement(pObj) ); if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) return 0; Counter = 1 + Aig_ConeCountAndMark_rec( Aig_ObjFanin0(pObj) ) + Aig_ConeCountAndMark_rec( Aig_ObjFanin1(pObj) ); assert( !Aig_ObjIsMarkA(pObj) ); // loop detection Aig_ObjSetMarkA( pObj ); return Counter; } /**Function************************************************************* Synopsis [Counts the number of AIG nodes rooted at this cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ConeUnmark_rec( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); if ( !Aig_ObjIsNode(pObj) || !Aig_ObjIsMarkA(pObj) ) return; Aig_ConeUnmark_rec( Aig_ObjFanin0(pObj) ); Aig_ConeUnmark_rec( Aig_ObjFanin1(pObj) ); assert( Aig_ObjIsMarkA(pObj) ); // loop detection Aig_ObjClearMarkA( pObj ); } /**Function************************************************************* Synopsis [Counts the number of AIG nodes rooted at this cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_DagSize( Aig_Obj_t * pObj ) { int Counter; Counter = Aig_ConeCountAndMark_rec( Aig_Regular(pObj) ); Aig_ConeUnmark_rec( Aig_Regular(pObj) ); return Counter; } /**Function************************************************************* Synopsis [Counts the support size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_SupportSize_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int * pCounter ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); if ( Aig_ObjIsCi(pObj) ) { (*pCounter)++; return; } assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ); Aig_SupportSize_rec( p, Aig_ObjFanin0(pObj), pCounter ); if ( Aig_ObjFanin1(pObj) ) Aig_SupportSize_rec( p, Aig_ObjFanin1(pObj), pCounter ); } /**Function************************************************************* Synopsis [Counts the support size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_SupportSize( Aig_Man_t * p, Aig_Obj_t * pObj ) { int Counter = 0; assert( !Aig_IsComplement(pObj) ); assert( !Aig_ObjIsCo(pObj) ); Aig_ManIncrementTravId( p ); Aig_SupportSize_rec( p, pObj, &Counter ); return Counter; } /**Function************************************************************* Synopsis [Counts the support size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_SupportSizeTest( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, Counter = 0; abctime clk = Abc_Clock(); Aig_ManForEachObj( p, pObj, i ) if ( Aig_ObjIsNode(pObj) ) Counter += (Aig_SupportSize(p, pObj) <= 16); printf( "Nodes with small support %d (out of %d)\n", Counter, Aig_ManNodeNum(p) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return Counter; } /**Function************************************************************* Synopsis [Counts the support size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_Support_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); if ( Aig_ObjIsConst1(pObj) ) return; if ( Aig_ObjIsCi(pObj) ) { Vec_PtrPush( vSupp, pObj ); return; } assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ); Aig_Support_rec( p, Aig_ObjFanin0(pObj), vSupp ); if ( Aig_ObjFanin1(pObj) ) Aig_Support_rec( p, Aig_ObjFanin1(pObj), vSupp ); } /**Function************************************************************* Synopsis [Counts the support size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_Support( Aig_Man_t * p, Aig_Obj_t * pObj ) { Vec_Ptr_t * vSupp; assert( !Aig_IsComplement(pObj) ); assert( !Aig_ObjIsCo(pObj) ); Aig_ManIncrementTravId( p ); vSupp = Vec_PtrAlloc( 100 ); Aig_Support_rec( p, pObj, vSupp ); return vSupp; } /**Function************************************************************* Synopsis [Counts the support size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_SupportNodes( Aig_Man_t * p, Aig_Obj_t ** ppObjs, int nObjs, Vec_Ptr_t * vSupp ) { int i; Vec_PtrClear( vSupp ); Aig_ManIncrementTravId( p ); Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); for ( i = 0; i < nObjs; i++ ) { assert( !Aig_IsComplement(ppObjs[i]) ); if ( Aig_ObjIsCo(ppObjs[i]) ) Aig_Support_rec( p, Aig_ObjFanin0(ppObjs[i]), vSupp ); else Aig_Support_rec( p, ppObjs[i], vSupp ); } } /**Function************************************************************* Synopsis [Transfers the AIG from one manager into another.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_Transfer_rec( Aig_Man_t * pDest, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) return; Aig_Transfer_rec( pDest, Aig_ObjFanin0(pObj) ); Aig_Transfer_rec( pDest, Aig_ObjFanin1(pObj) ); pObj->pData = Aig_And( pDest, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); assert( !Aig_ObjIsMarkA(pObj) ); // loop detection Aig_ObjSetMarkA( pObj ); } /**Function************************************************************* Synopsis [Transfers the AIG from one manager into another.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pRoot, int nVars ) { Aig_Obj_t * pObj; int i; // solve simple cases if ( pSour == pDest ) return pRoot; if ( Aig_ObjIsConst1( Aig_Regular(pRoot) ) ) return Aig_NotCond( Aig_ManConst1(pDest), Aig_IsComplement(pRoot) ); // set the PI mapping Aig_ManForEachCi( pSour, pObj, i ) { if ( i == nVars ) break; pObj->pData = Aig_IthVar(pDest, i); } // transfer and set markings Aig_Transfer_rec( pDest, Aig_Regular(pRoot) ); // clear the markings Aig_ConeUnmark_rec( Aig_Regular(pRoot) ); return Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) ); } /**Function************************************************************* Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_Compose_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFunc, Aig_Obj_t * pVar ) { assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsMarkA(pObj) ) return; if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsCi(pObj) ) { pObj->pData = pObj == pVar ? pFunc : pObj; return; } Aig_Compose_rec( p, Aig_ObjFanin0(pObj), pFunc, pVar ); Aig_Compose_rec( p, Aig_ObjFanin1(pObj), pFunc, pVar ); pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); assert( !Aig_ObjIsMarkA(pObj) ); // loop detection Aig_ObjSetMarkA( pObj ); } /**Function************************************************************* Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar ) { // quit if the PI variable is not defined if ( iVar >= Aig_ManCiNum(p) ) { printf( "Aig_Compose(): The PI variable %d is not defined.\n", iVar ); return NULL; } // recursively perform composition Aig_Compose_rec( p, Aig_Regular(pRoot), pFunc, Aig_ManCi(p, iVar) ); // clear the markings Aig_ConeUnmark_rec( Aig_Regular(pRoot) ); return Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) ); } /**Function************************************************************* Synopsis [Computes the internal nodes of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjCollectCut_rec( Aig_Obj_t * pNode, Vec_Ptr_t * vNodes ) { // Aig_Obj_t * pFan0 = Aig_ObjFanin0(pNode); // Aig_Obj_t * pFan1 = Aig_ObjFanin1(pNode); if ( pNode->fMarkA ) return; pNode->fMarkA = 1; assert( Aig_ObjIsNode(pNode) ); Aig_ObjCollectCut_rec( Aig_ObjFanin0(pNode), vNodes ); Aig_ObjCollectCut_rec( Aig_ObjFanin1(pNode), vNodes ); Vec_PtrPush( vNodes, pNode ); //printf( "added %d ", pNode->Id ); } /**Function************************************************************* Synopsis [Computes the internal nodes of the cut.] Description [Does not include the leaves of the cut.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjCollectCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes ) { Aig_Obj_t * pObj; int i; // collect and mark the leaves Vec_PtrClear( vNodes ); Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) { assert( pObj->fMarkA == 0 ); pObj->fMarkA = 1; // printf( "%d " , pObj->Id ); } //printf( "\n" ); // collect and mark the nodes Aig_ObjCollectCut_rec( pRoot, vNodes ); // clean the nodes Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) pObj->fMarkA = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) pObj->fMarkA = 0; } /**Function************************************************************* Synopsis [Collects the nodes of the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjCollectSuper_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) { int RetValue1, RetValue2, i; // check if the node is visited if ( Aig_Regular(pObj)->fMarkA ) { // check if the node occurs in the same polarity for ( i = 0; i < vSuper->nSize; i++ ) if ( vSuper->pArray[i] == pObj ) return 1; // check if the node is present in the opposite polarity for ( i = 0; i < vSuper->nSize; i++ ) if ( vSuper->pArray[i] == Aig_Not(pObj) ) return -1; assert( 0 ); return 0; } // if the new node is complemented or a PI, another gate begins if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1) ) { Vec_PtrPush( vSuper, pObj ); Aig_Regular(pObj)->fMarkA = 1; return 0; } assert( !Aig_IsComplement(pObj) ); assert( Aig_ObjIsNode(pObj) ); // go through the branches RetValue1 = Aig_ObjCollectSuper_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper ); RetValue2 = Aig_ObjCollectSuper_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper ); if ( RetValue1 == -1 || RetValue2 == -1 ) return -1; // return 1 if at least one branch has a duplicate return RetValue1 || RetValue2; } /**Function************************************************************* Synopsis [Collects the nodes of the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjCollectSuper( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) { int RetValue, i; assert( !Aig_IsComplement(pObj) ); assert( Aig_ObjIsNode(pObj) ); // collect the nodes in the implication supergate Vec_PtrClear( vSuper ); RetValue = Aig_ObjCollectSuper_rec( pObj, pObj, vSuper ); assert( Vec_PtrSize(vSuper) > 1 ); // unmark the visited nodes Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i ) Aig_Regular(pObj)->fMarkA = 0; // if we found the node and its complement in the same implication supergate, // return empty set of nodes (meaning that we should use constant-0 node) if ( RetValue == -1 ) vSuper->nSize = 0; return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigDoms.c000066400000000000000000000767551477524141600160420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigDoms.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Computing multi-output dominators.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigDoms.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" #include "aig/saig/saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Aig_Sto_t_ Aig_Sto_t; typedef struct Aig_Dom_t_ Aig_Dom_t; struct Aig_Dom_t_ { int uSign; // signature int nNodes; // the number of nodes int pNodes[0]; // the nodes }; struct Aig_Sto_t_ { int Limit; Aig_Man_t * pAig; // user's AIG Aig_MmFixed_t * pMem; // memory manager for dominators Vec_Ptr_t * vDoms; // dominators Vec_Int_t * vFans; // temporary fanouts Vec_Int_t * vTimes; // the number of times each appears int nDomNodes; // nodes with dominators int nDomsTotal; // total dominators int nDomsFilter1; // filtered dominators int nDomsFilter2; // filtered dominators }; #define Aig_DomForEachNode( pAig, pDom, pNode, i ) \ for ( i = 0; (i < pDom->nNodes) && ((pNode) = Aig_ManObj(pAig, (pDom)->pNodes[i])); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates dominator manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Sto_t * Aig_ManDomStart( Aig_Man_t * pAig, int Limit ) { Aig_Sto_t * pSto; pSto = ABC_CALLOC( Aig_Sto_t, 1 ); pSto->pAig = pAig; pSto->Limit = Limit; pSto->pMem = Aig_MmFixedStart( sizeof(Aig_Dom_t) + sizeof(int) * Limit, 10000 ); pSto->vDoms = Vec_PtrStart( Aig_ManObjNumMax(pAig) ); pSto->vFans = Vec_IntAlloc( 100 ); pSto->vTimes = Vec_IntStart( Aig_ManObjNumMax(pAig) ); return pSto; } /**Function************************************************************* Synopsis [Adds trivial dominator.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjAddTriv( Aig_Sto_t * pSto, int Id, Vec_Ptr_t * vDoms ) { Aig_Dom_t * pDom; pDom = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem ); pDom->uSign = (1 << (Id % 63)); pDom->nNodes = 1; pDom->pNodes[0] = Id; Vec_PtrPushFirst( vDoms, pDom ); assert( Vec_PtrEntry( pSto->vDoms, Id ) == NULL ); Vec_PtrWriteEntry( pSto->vDoms, Id, vDoms ); } /**Function************************************************************* Synopsis [Duplicates vector of doms.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ObjDomVecDup( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms, int fSkip1 ) { Vec_Ptr_t * vDoms2; Aig_Dom_t * pDom, * pDom2; int i; vDoms2 = Vec_PtrAlloc( 0 ); Vec_PtrForEachEntryStart( Aig_Dom_t *, vDoms, pDom, i, fSkip1 ) { pDom2 = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem ); memcpy( pDom2, pDom, sizeof(Aig_Dom_t) + sizeof(int) * pSto->Limit ); Vec_PtrPush( vDoms2, pDom2 ); } return vDoms2; } /**Function************************************************************* Synopsis [Recycles vector of doms.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjDomVecRecycle( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms ) { Aig_Dom_t * pDom; int i; Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pDom, i ) Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pDom ); Vec_PtrFree( vDoms ); } /**Function************************************************************* Synopsis [Duplicates the vector of doms.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjDomPrint( Aig_Sto_t * pSto, Aig_Dom_t * pDom, int Num ) { int k; printf( "%4d : {", Num ); for ( k = 0; k < pDom->nNodes; k++ ) printf( " %4d", pDom->pNodes[k] ); for ( ; k < pSto->Limit; k++ ) printf( " " ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Duplicates the vector of doms.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjDomVecPrint( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms ) { Aig_Dom_t * pDom; int i; Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pDom, i ) Aig_ObjDomPrint( pSto, pDom, i ); } /**Function************************************************************* Synopsis [Computes multi-node dominators.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManDomPrint( Aig_Sto_t * pSto ) { Aig_Obj_t * pObj; int i; Saig_ManForEachPi( pSto->pAig, pObj, i ) { printf( "*** PI %4d %4d :\n", i, pObj->Id ); Aig_ObjDomVecPrint( pSto, (Vec_Ptr_t *)Vec_PtrEntry(pSto->vDoms, pObj->Id) ); } } /**Function************************************************************* Synopsis [Divides the circuit into well-balanced parts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManDomStop( Aig_Sto_t * pSto ) { Vec_Ptr_t * vDoms; int i; Vec_PtrForEachEntry( Vec_Ptr_t *, pSto->vDoms, vDoms, i ) if ( vDoms ) Aig_ObjDomVecRecycle( pSto, vDoms ); Vec_PtrFree( pSto->vDoms ); Vec_IntFree( pSto->vFans ); Vec_IntFree( pSto->vTimes ); Aig_MmFixedStop( pSto->pMem, 0 ); ABC_FREE( pSto ); } /**Function************************************************************* Synopsis [Checks correctness of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjDomCheck( Aig_Dom_t * pDom ) { int i; for ( i = 1; i < pDom->nNodes; i++ ) { if ( pDom->pNodes[i-1] >= pDom->pNodes[i] ) { Abc_Print( -1, "Aig_ObjDomCheck(): Cut has wrong ordering of inputs.\n" ); return 0; } assert( pDom->pNodes[i-1] < pDom->pNodes[i] ); } return 1; } /**Function************************************************************* Synopsis [Returns 1 if pDom is contained in pCut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_ObjDomCheckDominance( Aig_Dom_t * pDom, Aig_Dom_t * pCut ) { int i, k; for ( i = 0; i < pDom->nNodes; i++ ) { for ( k = 0; k < (int)pCut->nNodes; k++ ) if ( pDom->pNodes[i] == pCut->pNodes[k] ) break; if ( k == (int)pCut->nNodes ) // node i in pDom is not contained in pCut return 0; } // every node in pDom is contained in pCut return 1; } /**Function************************************************************* Synopsis [Returns 1 if the cut is contained.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjDomFilter( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms, Aig_Dom_t * pDom ) { Aig_Dom_t * pTemp; int i; Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pTemp, i ) { if ( pTemp->nNodes > pDom->nNodes ) { // do not fiter the first cut if ( i == 0 ) continue; // skip the non-contained cuts if ( (pTemp->uSign & pDom->uSign) != pDom->uSign ) continue; // check containment seriously if ( Aig_ObjDomCheckDominance( pDom, pTemp ) ) { Vec_PtrRemove( vDoms, pTemp ); Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pTemp ); i--; pSto->nDomsFilter1++; } } else { // skip the non-contained cuts if ( (pTemp->uSign & pDom->uSign) != pTemp->uSign ) continue; // check containment seriously if ( Aig_ObjDomCheckDominance( pTemp, pDom ) ) { pSto->nDomsFilter2++; return 1; } } } return 0; } /**Function************************************************************* Synopsis [Merges two cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_ObjDomMergeOrdered( Aig_Dom_t * pD0, Aig_Dom_t * pD1, Aig_Dom_t * pD, int Limit ) { int i, k, c; assert( pD0->nNodes >= pD1->nNodes ); // the case of the largest cut sizes if ( pD0->nNodes == Limit && pD1->nNodes == Limit ) { for ( i = 0; i < pD0->nNodes; i++ ) if ( pD0->pNodes[i] != pD1->pNodes[i] ) return 0; for ( i = 0; i < pD0->nNodes; i++ ) pD->pNodes[i] = pD0->pNodes[i]; pD->nNodes = pD0->nNodes; return 1; } // the case when one of the cuts is the largest if ( pD0->nNodes == Limit ) { for ( i = 0; i < pD1->nNodes; i++ ) { for ( k = pD0->nNodes - 1; k >= 0; k-- ) if ( pD0->pNodes[k] == pD1->pNodes[i] ) break; if ( k == -1 ) // did not find return 0; } for ( i = 0; i < pD0->nNodes; i++ ) pD->pNodes[i] = pD0->pNodes[i]; pD->nNodes = pD0->nNodes; return 1; } // compare two cuts with different numbers i = k = 0; for ( c = 0; c < (int)Limit; c++ ) { if ( k == pD1->nNodes ) { if ( i == pD0->nNodes ) { pD->nNodes = c; return 1; } pD->pNodes[c] = pD0->pNodes[i++]; continue; } if ( i == pD0->nNodes ) { if ( k == pD1->nNodes ) { pD->nNodes = c; return 1; } pD->pNodes[c] = pD1->pNodes[k++]; continue; } if ( pD0->pNodes[i] < pD1->pNodes[k] ) { pD->pNodes[c] = pD0->pNodes[i++]; continue; } if ( pD0->pNodes[i] > pD1->pNodes[k] ) { pD->pNodes[c] = pD1->pNodes[k++]; continue; } pD->pNodes[c] = pD0->pNodes[i++]; k++; } if ( i < pD0->nNodes || k < pD1->nNodes ) return 0; pD->nNodes = c; return 1; } /**Function************************************************************* Synopsis [Prepares the object for FPGA mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjDomMergeTwo( Aig_Dom_t * pDom0, Aig_Dom_t * pDom1, Aig_Dom_t * pDom, int Limit ) { assert( Limit > 0 ); if ( pDom0->nNodes < pDom1->nNodes ) { if ( !Aig_ObjDomMergeOrdered( pDom1, pDom0, pDom, Limit ) ) return 0; } else { if ( !Aig_ObjDomMergeOrdered( pDom0, pDom1, pDom, Limit ) ) return 0; } pDom->uSign = pDom0->uSign | pDom1->uSign; assert( pDom->nNodes <= Limit ); assert( Aig_ObjDomCheck( pDom ) ); return 1; } /**Function************************************************************* Synopsis [Merge two arrays of dominators.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ObjDomMerge( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms0, Vec_Ptr_t * vDoms1 ) { Vec_Ptr_t * vDoms; Aig_Dom_t * pDom0, * pDom1, * pDom; int i, k; vDoms = Vec_PtrAlloc( 16 ); Vec_PtrForEachEntry( Aig_Dom_t *, vDoms0, pDom0, i ) Vec_PtrForEachEntry( Aig_Dom_t *, vDoms1, pDom1, k ) { if ( Aig_WordCountOnes( pDom0->uSign | pDom1->uSign ) > pSto->Limit ) continue; // check if the cut exists pDom = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem ); if ( !Aig_ObjDomMergeTwo( pDom0, pDom1, pDom, pSto->Limit ) ) { Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pDom ); continue; } // check if this cut is contained in any of the available cuts if ( Aig_ObjDomFilter( pSto, vDoms, pDom ) ) { Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pDom ); continue; } Vec_PtrPush( vDoms, pDom ); } return vDoms; } /**Function************************************************************* Synopsis [Union two arrays of dominators.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjDomUnion( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms2, Vec_Ptr_t * vDoms1 ) { Aig_Dom_t * pDom1, * pDom2; int i; Vec_PtrForEachEntry( Aig_Dom_t *, vDoms1, pDom1, i ) { if ( i == 0 ) continue; if ( Aig_ObjDomFilter( pSto, vDoms2, pDom1 ) ) continue; pDom2 = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem ); memcpy( pDom2, pDom1, sizeof(Aig_Dom_t) + sizeof(int) * pSto->Limit ); Vec_PtrPush( vDoms2, pDom2 ); } } /**Function************************************************************* Synopsis [Computes multi-node dominators.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjDomCompute( Aig_Sto_t * pSto, Aig_Obj_t * pObj ) { Vec_Ptr_t * vDoms0, * vDoms1, * vDoms2, * vDomsT; Aig_Obj_t * pFanout; int i, iFanout; pSto->nDomNodes += Aig_ObjIsNode(pObj); Vec_IntClear( pSto->vFans ); Aig_ObjForEachFanout( pSto->pAig, pObj, pFanout, iFanout, i ) if ( Aig_ObjIsTravIdCurrent(pSto->pAig, pFanout) ) Vec_IntPush( pSto->vFans, iFanout>>1 ); if ( Vec_IntSize(pSto->vFans) == 0 ) return; vDoms0 = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, Vec_IntEntry(pSto->vFans, 0) ); vDoms2 = Aig_ObjDomVecDup( pSto, vDoms0, 0 ); Vec_IntForEachEntryStart( pSto->vFans, iFanout, i, 1 ) { vDoms1 = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, iFanout ); vDoms2 = Aig_ObjDomMerge( pSto, vDomsT = vDoms2, vDoms1 ); Aig_ObjDomVecRecycle( pSto, vDomsT ); } Aig_ObjAddTriv( pSto, pObj->Id, vDoms2 ); pSto->nDomsTotal += Vec_PtrSize(vDoms2); } /**Function************************************************************* Synopsis [Marks the flop TFI with the current traversal ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManMarkFlopTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { int Count; assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return 0; Aig_ObjSetTravIdCurrent(p, pObj); if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) return 1; Count = Aig_ManMarkFlopTfi_rec( p, Aig_ObjFanin0(pObj) ); if ( Aig_ObjIsNode(pObj) ) Count += Aig_ManMarkFlopTfi_rec( p, Aig_ObjFanin1(pObj) ); return Count; } /**Function************************************************************* Synopsis [Marks the flop TFI with the current traversal ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManMarkFlopTfi( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManIncrementTravId( p ); Saig_ManForEachLi( p, pObj, i ) Aig_ManMarkFlopTfi_rec( p, pObj ); } /**Function************************************************************* Synopsis [Computes multi-node dominators.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Sto_t * Aig_ManComputeDomsFlops( Aig_Man_t * pAig, int Limit ) { Aig_Sto_t * pSto; Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; abctime clk = Abc_Clock(); pSto = Aig_ManDomStart( pAig, Limit ); // initialize flop inputs Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjAddTriv( pSto, pObj->Id, Vec_PtrAlloc(1) ); // compute internal nodes vNodes = Aig_ManDfsReverse( pAig ); Aig_ManMarkFlopTfi( pAig ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) if ( Aig_ObjIsTravIdCurrent(pSto->pAig, pObj) ) Aig_ObjDomCompute( pSto, pObj ); Vec_PtrFree( vNodes ); // compute combinational inputs Aig_ManForEachCi( pAig, pObj, i ) Aig_ObjDomCompute( pSto, pObj ); // print statistics printf( "Nodes =%4d. Flops =%4d. Doms =%9d. Ave =%8.2f. ", pSto->nDomNodes, Aig_ManRegNum(pSto->pAig), pSto->nDomsTotal, // pSto->nDomsFilter1, pSto->nDomsFilter2, 1.0 * pSto->nDomsTotal / (pSto->nDomNodes + Aig_ManRegNum(pSto->pAig)) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return pSto; } /**Function************************************************************* Synopsis [Computes multi-node dominators.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Sto_t * Aig_ManComputeDomsPis( Aig_Man_t * pAig, int Limit ) { Aig_Sto_t * pSto; Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; abctime clk = Abc_Clock(); pSto = Aig_ManDomStart( pAig, Limit ); // initialize flop inputs Aig_ManForEachCo( pAig, pObj, i ) Aig_ObjAddTriv( pSto, pObj->Id, Vec_PtrAlloc(1) ); // compute internal nodes vNodes = Aig_ManDfsReverse( pAig ); Aig_ManMarkFlopTfi( pAig ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) if ( Aig_ObjIsTravIdCurrent(pSto->pAig, pObj) ) Aig_ObjDomCompute( pSto, pObj ); Vec_PtrFree( vNodes ); // compute combinational inputs Saig_ManForEachPi( pAig, pObj, i ) Aig_ObjDomCompute( pSto, pObj ); // print statistics printf( "Nodes =%4d. PIs =%4d. Doms =%9d. Ave =%8.2f. ", pSto->nDomNodes, Saig_ManPiNum(pSto->pAig), pSto->nDomsTotal, // pSto->nDomsFilter1, pSto->nDomsFilter2, 1.0 * pSto->nDomsTotal / (pSto->nDomNodes + Saig_ManPiNum(pSto->pAig)) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return pSto; } /**Function************************************************************* Synopsis [Computes multi-node dominators.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Sto_t * Aig_ManComputeDomsNodes( Aig_Man_t * pAig, int Limit ) { Aig_Sto_t * pSto; Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; abctime clk = Abc_Clock(); pSto = Aig_ManDomStart( pAig, Limit ); // initialize flop inputs Aig_ManForEachCo( pAig, pObj, i ) Aig_ObjAddTriv( pSto, pObj->Id, Vec_PtrAlloc(1) ); // compute internal nodes vNodes = Aig_ManDfsReverse( pAig ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) Aig_ObjDomCompute( pSto, pObj ); Vec_PtrFree( vNodes ); // compute combinational inputs Aig_ManForEachCi( pAig, pObj, i ) Aig_ObjDomCompute( pSto, pObj ); // print statistics printf( "Nodes =%6d. Doms =%9d. Ave =%8.2f. ", pSto->nDomNodes, pSto->nDomsTotal, // pSto->nDomsFilter1, pSto->nDomsFilter2, 1.0 * pSto->nDomsTotal / pSto->nDomNodes ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return pSto; } /**Function************************************************************* Synopsis [Collects dominators from the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ObjDomCollect( Aig_Sto_t * pSto, Vec_Int_t * vCut ) { Vec_Ptr_t * vDoms0, * vDoms1, * vDoms2; int i, ObjId; vDoms0 = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, Vec_IntEntry(vCut, 0) ); vDoms2 = Aig_ObjDomVecDup( pSto, vDoms0, 1 ); Vec_IntForEachEntryStart( vCut, ObjId, i, 1 ) { vDoms1 = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, ObjId ); if ( vDoms1 == NULL ) continue; Aig_ObjDomUnion( pSto, vDoms2, vDoms1 ); } return vDoms2; } /**Function************************************************************* Synopsis [Marks the flop TFI with the current traversal ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjDomVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { int Count; assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return 0; Aig_ObjSetTravIdCurrent(p, pObj); if ( pObj->fMarkA ) return 1; // assert( !Aig_ObjIsCi(pObj) && !Aig_ObjIsConst1(pObj) ); if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) return 1; Count = Aig_ObjDomVolume_rec( p, Aig_ObjFanin0(pObj) ); if ( Aig_ObjIsNode(pObj) ) Count += Aig_ObjDomVolume_rec( p, Aig_ObjFanin1(pObj) ); return Count; } /**Function************************************************************* Synopsis [Count the number of nodes in the dominator.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjDomVolume( Aig_Sto_t * pSto, Aig_Dom_t * pDom ) { Aig_Obj_t * pObj; int i, Counter = 0; Aig_ManIncrementTravId( pSto->pAig ); Aig_DomForEachNode( pSto->pAig, pDom, pObj, i ) Counter += Aig_ObjDomVolume_rec( pSto->pAig, pObj ); return Counter; } /**Function************************************************************* Synopsis [Dereferences the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjDomDeref_rec( Aig_Obj_t * pNode ) { int Counter = 0; assert( pNode->nRefs > 0 ); if ( --pNode->nRefs > 0 ) return 0; assert( pNode->nRefs == 0 ); if ( pNode->fMarkA ) return 1; if ( Aig_ObjIsCi(pNode) ) return 0; Counter += Aig_ObjDomDeref_rec( Aig_ObjFanin0(pNode) ); if ( Aig_ObjIsNode(pNode) ) Counter += Aig_ObjDomDeref_rec( Aig_ObjFanin1(pNode) ); return Counter; } /**Function************************************************************* Synopsis [References the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjDomRef_rec( Aig_Obj_t * pNode ) { int Counter = 0; assert( pNode->nRefs >= 0 ); if ( pNode->nRefs++ > 0 ) return 0; assert( pNode->nRefs == 1 ); if ( pNode->fMarkA ) return 1; if ( Aig_ObjIsCi(pNode) ) return 0; Counter += Aig_ObjDomRef_rec( Aig_ObjFanin0(pNode) ); if ( Aig_ObjIsNode(pNode) ) Counter += Aig_ObjDomRef_rec( Aig_ObjFanin1(pNode) ); return Counter; } /**Function************************************************************* Synopsis [Count the number of nodes in the dominator.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjDomDomed( Aig_Sto_t * pSto, Aig_Dom_t * pDom ) { Aig_Obj_t * pObj; int i, Counter0, Counter1; Counter0 = 0; Aig_DomForEachNode( pSto->pAig, pDom, pObj, i ) { assert( !Aig_ObjIsCi(pObj) ); Counter0 += Aig_ObjDomDeref_rec( Aig_ObjFanin0(pObj) ); if ( Aig_ObjIsNode(pObj) ) Counter0 += Aig_ObjDomDeref_rec( Aig_ObjFanin1(pObj) ); } Counter1 = 0; Aig_DomForEachNode( pSto->pAig, pDom, pObj, i ) { assert( !Aig_ObjIsCi(pObj) ); Counter1 += Aig_ObjDomRef_rec( Aig_ObjFanin0(pObj) ); if ( Aig_ObjIsNode(pObj) ) Counter1 += Aig_ObjDomRef_rec( Aig_ObjFanin1(pObj) ); } assert( Counter0 == Counter1 ); return Counter0; } /**Function************************************************************* Synopsis [Collects dominators from the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Aig_ObjDomCollectLos( Aig_Sto_t * pSto ) { Vec_Int_t * vCut; Aig_Obj_t * pObj; int i; vCut = Vec_IntAlloc( Aig_ManRegNum(pSto->pAig) ); Saig_ManForEachLo( pSto->pAig, pObj, i ) { Vec_IntPush( vCut, pObj->Id ); pObj->fMarkA = 1; } return vCut; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjPoLogicDeref( Aig_Sto_t * pSto ) { Aig_Obj_t * pObj; int i; Saig_ManForEachPo( pSto->pAig, pObj, i ) Aig_ObjDomDeref_rec( Aig_ObjFanin0(pObj) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjPoLogicRef( Aig_Sto_t * pSto ) { Aig_Obj_t * pObj; int i; Saig_ManForEachPo( pSto->pAig, pObj, i ) Aig_ObjDomRef_rec( Aig_ObjFanin0(pObj) ); } /**Function************************************************************* Synopsis [Collects dominators from the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjDomFindGood( Aig_Sto_t * pSto ) { Aig_Dom_t * pDom; Vec_Int_t * vCut; Vec_Ptr_t * vDoms; int i; vCut = Aig_ObjDomCollectLos( pSto ); vDoms = Aig_ObjDomCollect( pSto, vCut ); Vec_IntFree( vCut ); printf( "The cut has %d non-trivial %d-dominators.\n", Vec_PtrSize(vDoms), pSto->Limit ); Aig_ObjPoLogicDeref( pSto ); Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pDom, i ) { // if ( Aig_ObjDomDomed(pSto, pDom) <= 1 ) // continue; printf( "Vol =%3d. ", Aig_ObjDomVolume(pSto, pDom) ); printf( "Dom =%3d. ", Aig_ObjDomDomed(pSto, pDom) ); Aig_ObjDomPrint( pSto, pDom, i ); } Aig_ObjPoLogicRef( pSto ); Aig_ObjDomVecRecycle( pSto, vDoms ); Aig_ManCleanMarkA( pSto->pAig ); } /**Function************************************************************* Synopsis [Computes multi-node dominators.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManComputeDomsTest2( Aig_Man_t * pAig, int Num ) { Aig_Sto_t * pSto; // int i; //Aig_ManShow( pAig, 0, NULL ); Aig_ManFanoutStart( pAig ); // for ( i = 1; i < 9; i++ ) { printf( "ITERATION %d:\n", Num ); pSto = Aig_ManComputeDomsFlops( pAig, Num ); Aig_ObjDomFindGood( pSto ); // Aig_ManDomPrint( pSto ); Aig_ManDomStop( pSto ); } Aig_ManFanoutStop( pAig ); } /**Function************************************************************* Synopsis [Computes multi-node dominators.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManComputeDomsTest( Aig_Man_t * pAig ) { Aig_Sto_t * pSto; Aig_ManFanoutStart( pAig ); pSto = Aig_ManComputeDomsPis( pAig, 1 ); Aig_ManDomPrint( pSto ); Aig_ManDomStop( pSto ); Aig_ManFanoutStop( pAig ); } /**Function************************************************************* Synopsis [Collects dominators from the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjDomCount( Aig_Sto_t * pSto, Aig_Obj_t * pObj ) { Aig_Dom_t * pDom; Aig_Obj_t * pFanout; Vec_Int_t * vSingles; Vec_Ptr_t * vDoms; int i, k, Entry, iFanout, fPrint = 0; vSingles = Vec_IntAlloc( 100 ); // for each dominator of a fanout, count how many fanouts have it as a dominator Aig_ObjForEachFanout( pSto->pAig, pObj, pFanout, iFanout, i ) { vDoms = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, Aig_ObjId(pFanout) ); Vec_PtrForEachEntryStart( Aig_Dom_t *, vDoms, pDom, k, 1 ) { // printf( "Fanout %d Dominator %d\n", Aig_ObjId(pFanout), pDom->pNodes[0] ); Vec_IntAddToEntry( pSto->vTimes, pDom->pNodes[0], 1 ); Vec_IntPushUnique( vSingles, pDom->pNodes[0] ); } } // clear storage Vec_IntForEachEntry( vSingles, Entry, i ) { if ( Vec_IntEntry(pSto->vTimes, Entry) > 5 ) { if ( fPrint == 0 ) { printf( "%6d : Level =%4d. Fanout =%6d.\n", Aig_ObjId(pObj), Aig_ObjLevel(pObj), Aig_ObjRefs(pObj) ); } fPrint = 1; printf( "%d(%d) ", Entry, Vec_IntEntry(pSto->vTimes, Entry) ); } Vec_IntWriteEntry( pSto->vTimes, Entry, 0); } if ( fPrint ) printf( "\n" ); Vec_IntFree( vSingles ); } /**Function************************************************************* Synopsis [Computes multi-node dominators.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManComputeDomsForCofactoring( Aig_Man_t * pAig ) { Vec_Ptr_t * vDoms; Aig_Sto_t * pSto; Aig_Obj_t * pObj; int i; Aig_ManFanoutStart( pAig ); pSto = Aig_ManComputeDomsNodes( pAig, 1 ); Aig_ManForEachObj( pAig, pObj, i ) { if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) continue; if ( Aig_ObjRefs(pObj) < 10 ) continue; vDoms = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, Aig_ObjId(pObj) ); // printf( "%6d : Level =%4d. Fanout =%6d.\n", // Aig_ObjId(pObj), Aig_ObjLevel(pObj), Aig_ObjRefs(pObj) ); Aig_ObjDomCount( pSto, pObj ); } Aig_ManDomStop( pSto ); Aig_ManFanoutStop( pAig ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigDup.c000066400000000000000000001267751477524141600156660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigDup.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [AIG duplication (re-strashing).] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigDup.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig/saig/saig.h" #include "misc/tim/tim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [Orders nodes as follows: PIs, ANDs, POs.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupSimple( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew = NULL; int i; assert( p->pManTime == NULL ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; pNew->nBarBufs = p->nBarBufs; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) { pObjNew = Aig_ObjCreateCi( pNew ); pObjNew->Level = pObj->Level; pObj->pData = pObjNew; } // duplicate internal nodes Aig_ManForEachObj( p, pObj, i ) if ( Aig_ObjIsBuf(pObj) ) { pObjNew = Aig_ObjChild0Copy(pObj); pObj->pData = pObjNew; } else if ( Aig_ObjIsNode(pObj) ) { pObjNew = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); pObj->pData = pObjNew; } // add the POs Aig_ManForEachCo( p, pObj, i ) { pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); pObj->pData = pObjNew; } assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupSimple(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Derives AIG with hints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupSimpleWithHints( Aig_Man_t * p, Vec_Int_t * vHints ) { Aig_Man_t * pNew; Aig_Obj_t * pObj = NULL; int i, Entry; assert( p->nAsserts == 0 || p->nConstrs == 0 ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) { pObj->pData = Aig_ObjCreateCi( pNew ); Entry = Vec_IntEntry( vHints, Aig_ObjId(pObj) ); if ( Entry == 0 || Entry == 1 ) pObj->pData = Aig_NotCond( Aig_ManConst1(pNew), Entry ); // restrict to the complement of constraint!!! } // duplicate internal nodes Aig_ManForEachNode( p, pObj, i ) { pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); Entry = Vec_IntEntry( vHints, Aig_ObjId(pObj) ); if ( Entry == 0 || Entry == 1 ) pObj->pData = Aig_NotCond( Aig_ManConst1(pNew), Entry ); // restrict to the complement of constraint!!! } // add the POs Aig_ManForEachCo( p, pObj, i ) pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); Aig_ManCleanup( pNew ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Llb_ManDeriveAigWithHints(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG manager recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ManDupSimpleDfs_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( pObj->pData ) return (Aig_Obj_t *)pObj->pData; Aig_ManDupSimpleDfs_rec( pNew, p, Aig_ObjFanin0(pObj) ); if ( Aig_ObjIsBuf(pObj) ) return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj)); Aig_ManDupSimpleDfs_rec( pNew, p, Aig_ObjFanin1(pObj) ); pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); return (Aig_Obj_t *)pObj->pData; } /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [Orders nodes as follows: PIs, ANDs, POs.] SideEffects [This procedure assumes that buffers are not used during HAIG recording. This way, each HAIG node is in one-to-one correspondence with old HAIG node. There is no need to create new nodes, just reassign the pointers. If it were not the case, we would need to create HAIG nodes for each new node duplicated. ] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupSimpleDfs( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew = NULL; int i; assert( p->pManTime == NULL ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; pNew->nBarBufs = p->nBarBufs; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) { pObjNew = Aig_ObjCreateCi( pNew ); pObjNew->Level = pObj->Level; pObj->pData = pObjNew; } // duplicate internal nodes Aig_ManForEachObj( p, pObj, i ) if ( !Aig_ObjIsCo(pObj) ) { Aig_ManDupSimpleDfs_rec( pNew, p, pObj ); assert( pObj->Level == ((Aig_Obj_t*)pObj->pData)->Level ); } // add the POs Aig_ManForEachCo( p, pObj, i ) { pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); pObj->pData = pObjNew; } assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupSimple(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Duplicates part of the AIG manager.] Description [Orders nodes as follows: PIs, ANDs, POs.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupSimpleDfsPart( Aig_Man_t * p, Vec_Ptr_t * vPis, Vec_Ptr_t * vPos ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew = NULL; int i; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1( pNew ); Vec_PtrForEachEntry( Aig_Obj_t *, vPis, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); // duplicate internal nodes Vec_PtrForEachEntry( Aig_Obj_t *, vPos, pObj, i ) { pObjNew = Aig_ManDupSimpleDfs_rec( pNew, p, Aig_ObjFanin0(pObj) ); pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) ); Aig_ObjCreateCo( pNew, pObjNew ); } Aig_ManSetRegNum( pNew, 0 ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupSimple(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [Assumes topological ordering of the nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupOrdered( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew = NULL; int i, nNodes; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; pNew->nBarBufs = p->nBarBufs; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); // create the PIs Aig_ManCleanData( p ); // duplicate internal nodes Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjIsBuf(pObj) ) { pObjNew = Aig_ObjChild0Copy(pObj); } else if ( Aig_ObjIsNode(pObj) ) { pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); } else if ( Aig_ObjIsCi(pObj) ) { pObjNew = Aig_ObjCreateCi( pNew ); pObjNew->Level = pObj->Level; } else if ( Aig_ObjIsCo(pObj) ) { pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } else if ( Aig_ObjIsConst1(pObj) ) { pObjNew = Aig_ManConst1(pNew); } else assert( 0 ); pObj->pData = pObjNew; } assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); if ( (nNodes = Aig_ManCleanup( pNew )) ) printf( "Aig_ManDupOrdered(): Cleanup after AIG duplication removed %d nodes.\n", nNodes ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // duplicate the timing manager if ( p->pManTime ) pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupOrdered(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [Orders nodes as follows: PIs, ANDs, POs.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupCof( Aig_Man_t * p, int iInput, int Value ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew = NULL; int i; assert( p->pManTime == NULL ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; pNew->nBarBufs = p->nBarBufs; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) { if ( i == iInput ) pObjNew = Value ? Aig_ManConst1(pNew) : Aig_ManConst0(pNew); else { pObjNew = Aig_ObjCreateCi( pNew ); pObjNew->Level = pObj->Level; } pObj->pData = pObjNew; } // duplicate internal nodes Aig_ManForEachObj( p, pObj, i ) if ( Aig_ObjIsBuf(pObj) ) { pObjNew = Aig_ObjChild0Copy(pObj); pObj->pData = pObjNew; } else if ( Aig_ObjIsNode(pObj) ) { pObjNew = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); pObj->pData = pObjNew; } // add the POs Aig_ManForEachCo( p, pObj, i ) { pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); pObj->pData = pObjNew; } // assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); Aig_ManCleanup( pNew ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupSimple(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [Assumes topological ordering of the nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupTrim( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew = NULL; int i, nNodes; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; pNew->nBarBufs = p->nBarBufs; // create the PIs Aig_ManCleanData( p ); // duplicate internal nodes Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjIsNode(pObj) ) pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); else if ( Aig_ObjIsCi(pObj) ) pObjNew = (Aig_ObjRefs(pObj) > 0 || Saig_ObjIsLo(p, pObj)) ? Aig_ObjCreateCi(pNew) : NULL; else if ( Aig_ObjIsCo(pObj) ) pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); else if ( Aig_ObjIsConst1(pObj) ) pObjNew = Aig_ManConst1(pNew); else assert( 0 ); pObj->pData = pObjNew; } assert( Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); if ( (nNodes = Aig_ManCleanup( pNew )) ) printf( "Aig_ManDupTrim(): Cleanup after AIG duplication removed %d nodes.\n", nNodes ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupTrim(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG manager to have EXOR gates.] Description [Assumes topological ordering of the nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupExor( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew = NULL; int i; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->fCatchExor = 1; pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; pNew->nBarBufs = p->nBarBufs; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); // create the PIs Aig_ManCleanData( p ); // duplicate internal nodes Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjIsBuf(pObj) ) { pObjNew = Aig_ObjChild0Copy(pObj); } else if ( Aig_ObjIsNode(pObj) ) { pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); } else if ( Aig_ObjIsCi(pObj) ) { pObjNew = Aig_ObjCreateCi( pNew ); pObjNew->Level = pObj->Level; } else if ( Aig_ObjIsCo(pObj) ) { pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } else if ( Aig_ObjIsConst1(pObj) ) { pObjNew = Aig_ManConst1(pNew); } else assert( 0 ); pObj->pData = pObjNew; } Aig_ManCleanup( pNew ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // duplicate the timing manager if ( p->pManTime ) pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupExor(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG manager recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ManDupDfs_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pObjNew, * pEquivNew = NULL; if ( pObj->pData ) return (Aig_Obj_t *)pObj->pData; if ( p->pEquivs && Aig_ObjEquiv(p, pObj) ) pEquivNew = Aig_ManDupDfs_rec( pNew, p, Aig_ObjEquiv(p, pObj) ); Aig_ManDupDfs_rec( pNew, p, Aig_ObjFanin0(pObj) ); if ( Aig_ObjIsBuf(pObj) ) return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj)); Aig_ManDupDfs_rec( pNew, p, Aig_ObjFanin1(pObj) ); pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); if ( pEquivNew ) { assert( Aig_Regular(pEquivNew)->Id < Aig_Regular(pObjNew)->Id ); if ( pNew->pEquivs ) pNew->pEquivs[Aig_Regular(pObjNew)->Id] = Aig_Regular(pEquivNew); if ( pNew->pReprs ) pNew->pReprs[Aig_Regular(pEquivNew)->Id] = Aig_Regular(pObjNew); } return (Aig_Obj_t *)(pObj->pData = pObjNew); } /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [This duplicator works for AIGs with choices.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupDfs( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew = NULL; int i, nNodes; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; pNew->nBarBufs = p->nBarBufs; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); // duplicate representation of choice nodes if ( p->pEquivs ) pNew->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); if ( p->pReprs ) pNew->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); // create the PIs Aig_ManCleanData( p ); // duplicate internal nodes Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjIsCi(pObj) ) { pObjNew = Aig_ObjCreateCi( pNew ); pObjNew->Level = pObj->Level; pObj->pData = pObjNew; } else if ( Aig_ObjIsCo(pObj) ) { Aig_ManDupDfs_rec( pNew, p, Aig_ObjFanin0(pObj) ); // assert( pObj->Level == ((Aig_Obj_t*)pObj->pData)->Level ); pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); pObj->pData = pObjNew; } } assert( p->pEquivs != NULL || Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); if ( p->pEquivs == NULL && p->pReprs == NULL && (nNodes = Aig_ManCleanup( pNew )) ) printf( "Aig_ManDupDfs(): Cleanup after AIG duplication removed %d nodes.\n", nNodes ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // duplicate the timing manager if ( p->pManTime ) pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupDfs(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [This duplicator works for AIGs with choices.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManOrderPios( Aig_Man_t * p, Aig_Man_t * pOrder ) { Vec_Ptr_t * vPios; Aig_Obj_t * pObj = NULL; int i; assert( Aig_ManCiNum(p) == Aig_ManCiNum(pOrder) ); assert( Aig_ManCoNum(p) == Aig_ManCoNum(pOrder) ); Aig_ManSetCioIds( pOrder ); vPios = Vec_PtrAlloc( Aig_ManCiNum(p) + Aig_ManCoNum(p) ); Aig_ManForEachObj( pOrder, pObj, i ) { if ( Aig_ObjIsCi(pObj) ) Vec_PtrPush( vPios, Aig_ManCi(p, Aig_ObjCioId(pObj)) ); else if ( Aig_ObjIsCo(pObj) ) Vec_PtrPush( vPios, Aig_ManCo(p, Aig_ObjCioId(pObj)) ); } Aig_ManCleanCioIds( pOrder ); return vPios; } /**Function************************************************************* Synopsis [Duplicates the AIG manager recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ManDupDfsGuided_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pObjNew, * pEquivNew = NULL; if ( pObj->pData ) return (Aig_Obj_t *)pObj->pData; if ( Aig_ObjIsCi(pObj) ) return NULL; if ( p->pEquivs && Aig_ObjEquiv(p, pObj) ) pEquivNew = Aig_ManDupDfsGuided_rec( pNew, p, Aig_ObjEquiv(p, pObj) ); if ( !Aig_ManDupDfsGuided_rec( pNew, p, Aig_ObjFanin0(pObj) ) ) return NULL; if ( Aig_ObjIsBuf(pObj) ) return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj)); if ( !Aig_ManDupDfsGuided_rec( pNew, p, Aig_ObjFanin1(pObj) ) ) return NULL; pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); if ( pEquivNew ) { if ( pNew->pEquivs ) pNew->pEquivs[Aig_Regular(pObjNew)->Id] = Aig_Regular(pEquivNew); if ( pNew->pReprs ) pNew->pReprs[Aig_Regular(pEquivNew)->Id] = Aig_Regular(pObjNew); } return (Aig_Obj_t *)(pObj->pData = pObjNew); } /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [This duplicator works for AIGs with choices.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupDfsGuided( Aig_Man_t * p, Vec_Ptr_t * vPios ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew = NULL; int i, nNodes; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; pNew->nBarBufs = p->nBarBufs; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); // duplicate representation of choice nodes if ( p->pEquivs ) { pNew->pEquivs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); memset( pNew->pEquivs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) ); } if ( p->pReprs ) { pNew->pReprs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); memset( pNew->pReprs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) ); } // create the PIs Aig_ManCleanData( p ); // duplicate internal nodes Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Vec_PtrForEachEntry( Aig_Obj_t *, vPios, pObj, i ) { if ( Aig_ObjIsCi(pObj) ) { pObjNew = Aig_ObjCreateCi( pNew ); pObjNew->Level = pObj->Level; pObj->pData = pObjNew; } else if ( Aig_ObjIsCo(pObj) ) { Aig_ManDupDfsGuided_rec( pNew, p, Aig_ObjFanin0(pObj) ); // assert( pObj->Level == ((Aig_Obj_t*)pObj->pData)->Level ); pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); pObj->pData = pObjNew; } } // assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); if ( p->pEquivs == NULL && p->pReprs == NULL && (nNodes = Aig_ManCleanup( pNew )) ) printf( "Aig_ManDupDfs(): Cleanup after AIG duplication removed %d nodes.\n", nNodes ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // duplicate the timing manager if ( p->pManTime ) pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupDfs(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [This duplicator works for AIGs with choices.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupLevelized( Aig_Man_t * p ) { Vec_Vec_t * vLevels; Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew = NULL; int i, k; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; pNew->nBarBufs = p->nBarBufs; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); // duplicate representation of choice nodes if ( p->pEquivs ) { pNew->pEquivs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); memset( pNew->pEquivs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) ); } if ( p->pReprs ) { pNew->pReprs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); memset( pNew->pReprs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) ); } // create the PIs Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) { pObjNew = Aig_ObjCreateCi( pNew ); pObjNew->Level = pObj->Level; pObj->pData = pObjNew; } // duplicate internal nodes vLevels = Aig_ManLevelize( p ); Vec_VecForEachEntry( Aig_Obj_t *, vLevels, pObj, i, k ) { pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); pObj->pData = pObjNew; } Vec_VecFree( vLevels ); // duplicate POs Aig_ManForEachCo( p, pObj, i ) { pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); pObj->pData = pObjNew; } assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); // if ( (nNodes = Aig_ManCleanup( pNew )) ) // printf( "Aig_ManDupLevelized(): Cleanup after AIG duplication removed %d nodes.\n", nNodes ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // duplicate the timing manager if ( p->pManTime ) pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupLevelized(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [Assumes topological ordering of nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupWithoutPos( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj = NULL; int i; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); // duplicate internal nodes Aig_ManForEachObj( p, pObj, i ) { assert( !Aig_ObjIsBuf(pObj) ); if ( Aig_ObjIsNode(pObj) ) pObj->pData = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); } assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [Assumes topological ordering of nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupFlopsOnly( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj = NULL; int i; pNew = Aig_ManDupWithoutPos( p ); Saig_ManForEachLi( p, pObj, i ) pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); Aig_ManCleanup( pNew ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupFlopsOnly(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Returns representatives of fanin in approapriate polarity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Aig_Obj_t * Aig_ObjGetRepres( Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pRepr; if ( (pRepr = Aig_ObjRepr(p, pObj)) ) return Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pObj->fPhase ^ pRepr->fPhase ); return (Aig_Obj_t *)pObj->pData; } static inline Aig_Obj_t * Aig_ObjChild0Repres( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjGetRepres(p, Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); } static inline Aig_Obj_t * Aig_ObjChild1Repres( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjGetRepres(p, Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); } /**Function************************************************************* Synopsis [Duplicates AIG while substituting representatives.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupRepres( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj = NULL; int i; // start the HOP package pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; pNew->nBarBufs = p->nBarBufs; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); // map the const and primary inputs Aig_ManCleanData( p ); Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjIsNode(pObj) ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Repres(p, pObj), Aig_ObjChild1Repres(p, pObj) ); else if ( Aig_ObjIsCi(pObj) ) { pObj->pData = Aig_ObjCreateCi(pNew); pObj->pData = Aig_ObjGetRepres( p, pObj ); } else if ( Aig_ObjIsCo(pObj) ) pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Repres(p, pObj) ); else if ( Aig_ObjIsConst1(pObj) ) pObj->pData = Aig_ManConst1(pNew); else assert( 0 ); } Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // check the new manager if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupRepres: Check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG manager recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ManDupRepres_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pRepr; if ( pObj->pData ) return (Aig_Obj_t *)pObj->pData; if ( (pRepr = Aig_ObjRepr(p, pObj)) ) { Aig_ManDupRepres_rec( pNew, p, pRepr ); return (Aig_Obj_t *)(pObj->pData = Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pRepr->fPhase ^ pObj->fPhase )); } Aig_ManDupRepres_rec( pNew, p, Aig_ObjFanin0(pObj) ); Aig_ManDupRepres_rec( pNew, p, Aig_ObjFanin1(pObj) ); return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Repres(p, pObj), Aig_ObjChild1Repres(p, pObj) )); } /**Function************************************************************* Synopsis [Duplicates AIG while substituting representatives.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupRepresDfs( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj = NULL; int i; // start the HOP package pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; pNew->nBarBufs = p->nBarBufs; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); // map the const and primary inputs Aig_ManCleanData( p ); Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjIsNode(pObj) ) continue; if ( Aig_ObjIsCi(pObj) ) pObj->pData = Aig_ObjCreateCi(pNew); else if ( Aig_ObjIsCo(pObj) ) { Aig_ManDupRepres_rec( pNew, p, Aig_ObjFanin0(pObj) ); pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Repres(p, pObj) ); } else if ( Aig_ObjIsConst1(pObj) ) pObj->pData = Aig_ManConst1(pNew); else assert( 0 ); } Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // check the new manager if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupRepresDfs: Check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Creates the miter of the two AIG managers.] Description [Oper is the operation to perform on the outputs of the miter. Oper == 0 is XOR Oper == 1 is complemented implication (p1 => p2) Oper == 2 is OR Oper == 3 is AND ] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int Oper ) { Aig_Man_t * pNew; Aig_Obj_t * pObj = NULL; int i; assert( Aig_ManRegNum(p1) == 0 ); assert( Aig_ManRegNum(p2) == 0 ); assert( Aig_ManCoNum(p1) == 1 ); assert( Aig_ManCoNum(p2) == 1 ); assert( Aig_ManCiNum(p1) == Aig_ManCiNum(p2) ); pNew = Aig_ManStart( Aig_ManObjNumMax(p1) + Aig_ManObjNumMax(p2) ); // add first AIG Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p1, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); Aig_ManForEachNode( p1, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // add second AIG Aig_ManConst1(p2)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p2, pObj, i ) pObj->pData = Aig_ManCi( pNew, i ); Aig_ManForEachNode( p2, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // add the output if ( Oper == 0 ) // XOR pObj = Aig_Exor( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1,0)), Aig_ObjChild0Copy(Aig_ManCo(p2,0)) ); else if ( Oper == 1 ) // implication is PO(p1) -> PO(p2) ... complement is PO(p1) & !PO(p2) pObj = Aig_And( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1,0)), Aig_Not(Aig_ObjChild0Copy(Aig_ManCo(p2,0))) ); else if ( Oper == 2 ) // OR pObj = Aig_Or( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1,0)), Aig_ObjChild0Copy(Aig_ManCo(p2,0)) ); else if ( Oper == 3 ) // AND pObj = Aig_And( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1,0)), Aig_ObjChild0Copy(Aig_ManCo(p2,0)) ); else assert( 0 ); Aig_ObjCreateCo( pNew, pObj ); Aig_ManCleanup( pNew ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG with only one primary output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupOrpos( Aig_Man_t * p, int fAddRegs ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pMiter; int i; assert( Aig_ManRegNum(p) > 0 ); if ( p->nConstrs > 0 ) { printf( "The AIG manager should have no constraints.\n" ); return NULL; } // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); // set registers pNew->nRegs = fAddRegs? p->nRegs : 0; pNew->nTruePis = fAddRegs? p->nTruePis : p->nTruePis + p->nRegs; pNew->nTruePos = 1; // duplicate internal nodes Aig_ManForEachNode( p, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create the PO pMiter = Aig_ManConst0(pNew); Aig_ManForEachPoSeq( p, pObj, i ) pMiter = Aig_Or( pNew, pMiter, Aig_ObjChild0Copy(pObj) ); Aig_ObjCreateCo( pNew, pMiter ); // create register inputs with MUXes if ( fAddRegs ) { Aig_ManForEachLiSeq( p, pObj, i ) Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } Aig_ManCleanup( pNew ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG with only one primary output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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( iPoNum < Aig_ManCoNum(p)-Aig_ManRegNum(p) ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); // set registers pNew->nRegs = fAddRegs? p->nRegs : 0; pNew->nTruePis = fAddRegs? p->nTruePis : p->nTruePis + p->nRegs; pNew->nTruePos = 1; // duplicate internal nodes Aig_ManForEachNode( p, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create the PO pObj = Aig_ManCo( p, iPoNum ); Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); // create register inputs with MUXes if ( fAddRegs ) { Aig_ManForEachLiSeq( p, pObj, i ) Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } Aig_ManCleanup( pNew ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG with only one primary output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupUnsolvedOutputs( Aig_Man_t * p, int fAddRegs ) { Aig_Man_t * pNew; Aig_Obj_t * pObj = NULL; int i, nOuts = 0; assert( Aig_ManRegNum(p) > 0 ); if ( p->nConstrs > 0 ) { printf( "The AIG manager should have no constraints.\n" ); return NULL; } // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); // create the POs nOuts = 0; Aig_ManForEachPoSeq( p, pObj, i ) nOuts += ( Aig_ObjFanin0(pObj) != Aig_ManConst1(p) ); // set registers pNew->nRegs = fAddRegs? p->nRegs : 0; pNew->nTruePis = fAddRegs? p->nTruePis : p->nTruePis + p->nRegs; pNew->nTruePos = nOuts; // duplicate internal nodes Aig_ManForEachNode( p, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create the PO Aig_ManForEachPoSeq( p, pObj, i ) if ( Aig_ObjFanin0(pObj) != Aig_ManConst1(p) ) Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); // create register inputs with MUXes if ( fAddRegs ) { Aig_ManForEachLiSeq( p, pObj, i ) Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } Aig_ManCleanup( pNew ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG with only one primary output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupArray( Vec_Ptr_t * vArray ) { Aig_Man_t * p, * pNew; Aig_Obj_t * pObj = NULL; int i, k; if ( Vec_PtrSize(vArray) == 0 ) return NULL; p = (Aig_Man_t *)Vec_PtrEntry( vArray, 0 ); Vec_PtrForEachEntry( Aig_Man_t *, vArray, pNew, k ) { assert( Aig_ManRegNum(pNew) == 0 ); assert( Aig_ManCiNum(pNew) == Aig_ManCiNum(p) ); } // create the new manager pNew = Aig_ManStart( 10000 ); pNew->pName = Abc_UtilStrsav( p->pName ); Aig_ManForEachCi( p, pObj, i ) Aig_ObjCreateCi(pNew); // create the PIs Vec_PtrForEachEntry( Aig_Man_t *, vArray, p, k ) { Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) pObj->pData = Aig_ManCi( pNew, i ); Aig_ManForEachNode( p, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); Aig_ManForEachCo( p, pObj, i ) Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupSimple(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG with only one primary output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupNodes( Aig_Man_t * pMan, Vec_Ptr_t * vArray ) { Aig_Man_t * pNew; Vec_Ptr_t * vObjs; Aig_Obj_t * pObj = NULL; int i; if ( Vec_PtrSize(vArray) == 0 ) return NULL; vObjs = Aig_ManDfsNodes( pMan, (Aig_Obj_t **)Vec_PtrArray(vArray), Vec_PtrSize(vArray) ); // create the new manager pNew = Aig_ManStart( 10000 ); pNew->pName = Abc_UtilStrsav( pMan->pName ); Aig_ManConst1(pMan)->pData = Aig_ManConst1(pNew); Vec_PtrForEachEntry( Aig_Obj_t *, vObjs, pObj, i ) if ( Aig_ObjIsCi(pObj) ) pObj->pData = Aig_ObjCreateCi(pNew); Vec_PtrForEachEntry( Aig_Obj_t *, vObjs, pObj, i ) if ( Aig_ObjIsNode(pObj) ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); Vec_PtrForEachEntry( Aig_Obj_t *, vArray, pObj, i ) Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObj->pData ); Aig_ManSetRegNum( pNew, 0 ); Vec_PtrFree( vObjs ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigFact.c000066400000000000000000000565051477524141600160040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigFactor.c] SystemName [] PackageName [] Synopsis [] Author [Alan Mishchenko] Affiliation [] Date [Ver. 1.0. Started - April 17, 2009.] Revision [$Id: aigFactor.c,v 1.00 2009/04/17 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Detects multi-input AND gate rooted at this node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManFindImplications_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vImplics ) { if ( Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) ) { Vec_PtrPushUnique( vImplics, pObj ); return; } Aig_ManFindImplications_rec( Aig_ObjChild0(pObj), vImplics ); Aig_ManFindImplications_rec( Aig_ObjChild1(pObj), vImplics ); } /**Function************************************************************* Synopsis [Returns the nodes whose values are implied by pNode.] Description [Attention! Both pNode and results can be complemented! Also important: Currently, this procedure only does backward propagation. In general, it may find more implications if forward propagation is enabled.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManFindImplications( Aig_Man_t * p, Aig_Obj_t * pNode ) { Vec_Ptr_t * vImplics; vImplics = Vec_PtrAlloc( 100 ); Aig_ManFindImplications_rec( pNode, vImplics ); return vImplics; } /**Function************************************************************* Synopsis [Returns 1 if the cone of the node overlaps with the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManFindConeOverlap_rec( Aig_Man_t * p, Aig_Obj_t * pNode ) { if ( Aig_ObjIsTravIdPrevious( p, pNode ) ) return 1; if ( Aig_ObjIsTravIdCurrent( p, pNode ) ) return 0; Aig_ObjSetTravIdCurrent( p, pNode ); if ( Aig_ObjIsCi(pNode) ) return 0; if ( Aig_ManFindConeOverlap_rec( p, Aig_ObjFanin0(pNode) ) ) return 1; if ( Aig_ManFindConeOverlap_rec( p, Aig_ObjFanin1(pNode) ) ) return 1; return 0; } /**Function************************************************************* Synopsis [Returns 1 if the cone of the node overlaps with the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManFindConeOverlap( Aig_Man_t * p, Vec_Ptr_t * vImplics, Aig_Obj_t * pNode ) { Aig_Obj_t * pTemp; int i; assert( !Aig_IsComplement(pNode) ); assert( !Aig_ObjIsConst1(pNode) ); Aig_ManIncrementTravId( p ); Vec_PtrForEachEntry( Aig_Obj_t *, vImplics, pTemp, i ) Aig_ObjSetTravIdCurrent( p, Aig_Regular(pTemp) ); Aig_ManIncrementTravId( p ); return Aig_ManFindConeOverlap_rec( p, pNode ); } /**Function************************************************************* Synopsis [Returns 1 if the cone of the node overlaps with the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ManDeriveNewCone_rec( Aig_Man_t * p, Aig_Obj_t * pNode ) { if ( Aig_ObjIsTravIdCurrent( p, pNode ) ) return (Aig_Obj_t *)pNode->pData; Aig_ObjSetTravIdCurrent( p, pNode ); if ( Aig_ObjIsCi(pNode) ) return (Aig_Obj_t *)(pNode->pData = pNode); Aig_ManDeriveNewCone_rec( p, Aig_ObjFanin0(pNode) ); Aig_ManDeriveNewCone_rec( p, Aig_ObjFanin1(pNode) ); return (Aig_Obj_t *)(pNode->pData = Aig_And( p, Aig_ObjChild0Copy(pNode), Aig_ObjChild1Copy(pNode) )); } /**Function************************************************************* Synopsis [Returns 1 if the cone of the node overlaps with the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ManDeriveNewCone( Aig_Man_t * p, Vec_Ptr_t * vImplics, Aig_Obj_t * pNode ) { Aig_Obj_t * pTemp; int i; assert( !Aig_IsComplement(pNode) ); assert( !Aig_ObjIsConst1(pNode) ); Aig_ManIncrementTravId( p ); Vec_PtrForEachEntry( Aig_Obj_t *, vImplics, pTemp, i ) { Aig_ObjSetTravIdCurrent( p, Aig_Regular(pTemp) ); Aig_Regular(pTemp)->pData = Aig_NotCond( Aig_ManConst1(p), Aig_IsComplement(pTemp) ); } return Aig_ManDeriveNewCone_rec( p, pNode ); } /**Function************************************************************* Synopsis [Returns algebraic factoring of B in terms of A.] Description [Returns internal node C (an AND gate) that is equal to B under assignment A = 'Value', or NULL if there is no such node C. ] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ManFactorAlgebraic_int( Aig_Man_t * p, Aig_Obj_t * pPoA, Aig_Obj_t * pPoB, int Value ) { Aig_Obj_t * pNodeA, * pNodeC; Vec_Ptr_t * vImplics; int RetValue; if ( Aig_ObjIsConst1(Aig_ObjFanin0(pPoA)) || Aig_ObjIsConst1(Aig_ObjFanin0(pPoB)) ) return NULL; if ( Aig_ObjIsCi(Aig_ObjFanin0(pPoB)) ) return NULL; // get the internal node representing function of A under assignment A = 'Value' pNodeA = Aig_ObjChild0( pPoA ); pNodeA = Aig_NotCond( pNodeA, Value==0 ); // find implications of this signal (nodes whose value is fixed under assignment A = 'Value') vImplics = Aig_ManFindImplications( p, pNodeA ); // check if the TFI cone of B overlaps with the implied nodes RetValue = Aig_ManFindConeOverlap( p, vImplics, Aig_ObjFanin0(pPoB) ); if ( RetValue == 0 ) // no overlap { Vec_PtrFree( vImplics ); return NULL; } // there is overlap - derive node representing value of B under assignment A = 'Value' pNodeC = Aig_ManDeriveNewCone( p, vImplics, Aig_ObjFanin0(pPoB) ); pNodeC = Aig_NotCond( pNodeC, Aig_ObjFaninC0(pPoB) ); Vec_PtrFree( vImplics ); return pNodeC; } /**Function************************************************************* Synopsis [Returns algebraic factoring of B in terms of A.] Description [Returns internal node C (an AND gate) that is equal to B under assignment A = 'Value', or NULL if there is no such node C. ] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ManFactorAlgebraic( Aig_Man_t * p, int iPoA, int iPoB, int Value ) { assert( iPoA >= 0 && iPoA < Aig_ManCoNum(p) ); assert( iPoB >= 0 && iPoB < Aig_ManCoNum(p) ); assert( Value == 0 || Value == 1 ); return Aig_ManFactorAlgebraic_int( p, Aig_ManCo(p, iPoA), Aig_ManCo(p, iPoB), Value ); } /**Function************************************************************* Synopsis [Testing procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManFactorAlgebraicTest( Aig_Man_t * p ) { int iPoA = 0; int iPoB = 1; int Value = 0; Aig_Obj_t * pRes; // Aig_Obj_t * pObj; // int i; pRes = Aig_ManFactorAlgebraic( p, iPoA, iPoB, Value ); Aig_ManShow( p, 0, NULL ); Aig_ObjPrint( p, pRes ); printf( "\n" ); /* printf( "Results:\n" ); Aig_ManForEachObj( p, pObj, i ) { printf( "Object = %d.\n", i ); Aig_ObjPrint( p, pObj ); printf( "\n" ); Aig_ObjPrint( p, pObj->pData ); printf( "\n" ); } */ } /**Function************************************************************* Synopsis [Determines what support variables can be cofactored.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_SuppMinPerform( Aig_Man_t * p, Vec_Ptr_t * vOrGate, Vec_Ptr_t * vNodes, Vec_Ptr_t * vSupp ) { Aig_Obj_t * pObj; Vec_Ptr_t * vTrSupp, * vTrNode, * vCofs; unsigned * uFunc = NULL, * uCare, * uFunc0, * uFunc1; unsigned * uCof0, * uCof1, * uCare0, * uCare1; int i, nWords = Abc_TruthWordNum( Vec_PtrSize(vSupp) ); // assign support nodes vTrSupp = Vec_PtrAllocTruthTables( Vec_PtrSize(vSupp) ); Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i ) pObj->pData = Vec_PtrEntry( vTrSupp, i ); // compute internal nodes vTrNode = Vec_PtrAllocSimInfo( Vec_PtrSize(vNodes) + 5, nWords ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { pObj->pData = uFunc = (unsigned *)Vec_PtrEntry( vTrNode, i ); uFunc0 = (unsigned *)Aig_ObjFanin0(pObj)->pData; uFunc1 = (unsigned *)Aig_ObjFanin1(pObj)->pData; Kit_TruthAndPhase( uFunc, uFunc0, uFunc1, Vec_PtrSize(vSupp), Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) ); } // uFunc contains the result of computation // compute care set uCare = (unsigned *)Vec_PtrEntry( vTrNode, Vec_PtrSize(vNodes) ); Kit_TruthClear( uCare, Vec_PtrSize(vSupp) ); Vec_PtrForEachEntry( Aig_Obj_t *, vOrGate, pObj, i ) Kit_TruthOrPhase( uCare, uCare, (unsigned *)Aig_Regular(pObj)->pData, Vec_PtrSize(vSupp), 0, Aig_IsComplement(pObj) ); // try cofactoring each variable in both polarities vCofs = Vec_PtrAlloc( 10 ); uCof0 = (unsigned *)Vec_PtrEntry( vTrNode, Vec_PtrSize(vNodes)+1 ); uCof1 = (unsigned *)Vec_PtrEntry( vTrNode, Vec_PtrSize(vNodes)+2 ); uCare0 = (unsigned *)Vec_PtrEntry( vTrNode, Vec_PtrSize(vNodes)+3 ); uCare1 = (unsigned *)Vec_PtrEntry( vTrNode, Vec_PtrSize(vNodes)+4 ); Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i ) { Kit_TruthCofactor0New( uCof0, uFunc, Vec_PtrSize(vSupp), i ); Kit_TruthCofactor1New( uCof1, uFunc, Vec_PtrSize(vSupp), i ); Kit_TruthCofactor0New( uCare0, uCare, Vec_PtrSize(vSupp), i ); Kit_TruthCofactor1New( uCare1, uCare, Vec_PtrSize(vSupp), i ); if ( Kit_TruthIsEqualWithCare( uCof0, uCof1, uCare1, Vec_PtrSize(vSupp) ) ) Vec_PtrPush( vCofs, Aig_Not(pObj) ); else if ( Kit_TruthIsEqualWithCare( uCof0, uCof1, uCare0, Vec_PtrSize(vSupp) ) ) Vec_PtrPush( vCofs, pObj ); } Vec_PtrFree( vTrNode ); Vec_PtrFree( vTrSupp ); return vCofs; } /**Function************************************************************* Synopsis [Returns the new node after cofactoring.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_SuppMinReconstruct( Aig_Man_t * p, Vec_Ptr_t * vCofs, Vec_Ptr_t * vNodes, Vec_Ptr_t * vSupp ) { Aig_Obj_t * pObj = NULL; int i; // set the value of the support variables Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i ) assert( !Aig_IsComplement(pObj) ); Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i ) pObj->pData = pObj; // set the value of the cofactoring variables Vec_PtrForEachEntry( Aig_Obj_t *, vCofs, pObj, i ) Aig_Regular(pObj)->pData = Aig_NotCond( Aig_ManConst1(p), Aig_IsComplement(pObj) ); // reconstruct the node Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); return (Aig_Obj_t *)pObj->pData; } /**Function************************************************************* Synopsis [Returns 1 if all nodes of vOrGate are in vSupp.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_SuppMinGateIsInSupport( Aig_Man_t * p, Vec_Ptr_t * vOrGate, Vec_Ptr_t * vSupp ) { Aig_Obj_t * pObj; int i; Aig_ManIncrementTravId( p ); Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i ) Aig_ObjSetTravIdCurrent( p, pObj ); Vec_PtrForEachEntry( Aig_Obj_t *, vOrGate, pObj, i ) if ( !Aig_ObjIsTravIdCurrent( p, Aig_Regular(pObj) ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Collects fanins of the marked nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_SuppMinCollectSupport( Aig_Man_t * p, Vec_Ptr_t * vNodes ) { Vec_Ptr_t * vSupp; Aig_Obj_t * pObj, * pFanin; int i; vSupp = Vec_PtrAlloc( 4 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { assert( Aig_ObjIsTravIdCurrent(p, pObj) ); assert( Aig_ObjIsNode(pObj) ); pFanin = Aig_ObjFanin0( pObj ); if ( !Aig_ObjIsTravIdCurrent(p, pFanin) ) { Aig_ObjSetTravIdCurrent( p, pFanin ); Vec_PtrPush( vSupp, pFanin ); } pFanin = Aig_ObjFanin1( pObj ); if ( !Aig_ObjIsTravIdCurrent(p, pFanin) ) { Aig_ObjSetTravIdCurrent( p, pFanin ); Vec_PtrPush( vSupp, pFanin ); } } return vSupp; } /**Function************************************************************* Synopsis [Marks the nodes in the cone with current trav ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_SuppMinCollectCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) { if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) // visited return; if ( !Aig_ObjIsTravIdPrevious( p, pObj ) ) // not visited, but outside return; assert( Aig_ObjIsTravIdPrevious(p, pObj) ); // not visited, inside assert( Aig_ObjIsNode(pObj) ); Aig_ObjSetTravIdCurrent( p, pObj ); Aig_SuppMinCollectCone_rec( p, Aig_ObjFanin0(pObj), vNodes ); Aig_SuppMinCollectCone_rec( p, Aig_ObjFanin1(pObj), vNodes ); Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [Collects nodes with the current trav ID rooted in the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_SuppMinCollectCone( Aig_Man_t * p, Aig_Obj_t * pRoot ) { Vec_Ptr_t * vNodes; assert( !Aig_IsComplement(pRoot) ); // assert( Aig_ObjIsTravIdCurrent( p, pRoot ) ); vNodes = Vec_PtrAlloc( 4 ); Aig_ManIncrementTravId( p ); Aig_SuppMinCollectCone_rec( p, Aig_Regular(pRoot), vNodes ); return vNodes; } /**Function************************************************************* Synopsis [Marks the nodes in the cone with current trav ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_SuppMinHighlightCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { int RetValue; if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) // visited, marks there return 1; if ( Aig_ObjIsTravIdPrevious( p, pObj ) ) // visited, no marks there return 0; Aig_ObjSetTravIdPrevious( p, pObj ); if ( Aig_ObjIsCi(pObj) ) return 0; RetValue = Aig_SuppMinHighlightCone_rec( p, Aig_ObjFanin0(pObj) ) | Aig_SuppMinHighlightCone_rec( p, Aig_ObjFanin1(pObj) ); // printf( "%d %d\n", Aig_ObjId(pObj), RetValue ); if ( RetValue ) Aig_ObjSetTravIdCurrent( p, pObj ); return RetValue; } /**Function************************************************************* Synopsis [Marks the nodes in the cone with current trav ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_SuppMinHighlightCone( Aig_Man_t * p, Aig_Obj_t * pRoot, Vec_Ptr_t * vOrGate ) { Aig_Obj_t * pLeaf; int i, RetValue; assert( !Aig_IsComplement(pRoot) ); Aig_ManIncrementTravId( p ); Aig_ManIncrementTravId( p ); Vec_PtrForEachEntry( Aig_Obj_t *, vOrGate, pLeaf, i ) Aig_ObjSetTravIdCurrent( p, Aig_Regular(pLeaf) ); RetValue = Aig_SuppMinHighlightCone_rec( p, pRoot ); Vec_PtrForEachEntry( Aig_Obj_t *, vOrGate, pLeaf, i ) Aig_ObjSetTravIdPrevious( p, Aig_Regular(pLeaf) ); return RetValue; } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_SuppMinCollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) { // if the new node is complemented or a PI, another gate begins if ( Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) ) // || (Aig_ObjRefs(pObj) > 1) ) { Vec_PtrPushUnique( vSuper, Aig_Not(pObj) ); return; } // go through the branches Aig_SuppMinCollectSuper_rec( Aig_ObjChild0(pObj), vSuper ); Aig_SuppMinCollectSuper_rec( Aig_ObjChild1(pObj), vSuper ); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_SuppMinCollectSuper( Aig_Obj_t * pObj ) { Vec_Ptr_t * vSuper; assert( !Aig_IsComplement(pObj) ); assert( !Aig_ObjIsCi(pObj) ); vSuper = Vec_PtrAlloc( 4 ); Aig_SuppMinCollectSuper_rec( Aig_ObjChild0(pObj), vSuper ); Aig_SuppMinCollectSuper_rec( Aig_ObjChild1(pObj), vSuper ); return vSuper; } /**Function************************************************************* Synopsis [Returns the result of support minimization.] Description [Returns internal AIG node that is equal to pFunc under assignment pCond == 1, or NULL if there is no such node. status is -1 if condition is not OR; -2 if cone is too large or no cone; -3 if no support reduction is possible.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ManSupportMinimization( Aig_Man_t * p, Aig_Obj_t * pCond, Aig_Obj_t * pFunc, int * pStatus ) { int nSuppMax = 16; Vec_Ptr_t * vOrGate, * vNodes, * vSupp, * vCofs; Aig_Obj_t * pResult; int RetValue; *pStatus = 0; // if pCond is not OR if ( !Aig_IsComplement(pCond) || Aig_ObjIsCi(Aig_Regular(pCond)) || Aig_ObjIsConst1(Aig_Regular(pCond)) ) { *pStatus = -1; return NULL; } // if pFunc is not a node if ( !Aig_ObjIsNode(Aig_Regular(pFunc)) ) { *pStatus = -2; return NULL; } // collect the multi-input OR gate rooted in the condition vOrGate = Aig_SuppMinCollectSuper( Aig_Regular(pCond) ); if ( Vec_PtrSize(vOrGate) > nSuppMax ) { Vec_PtrFree( vOrGate ); *pStatus = -2; return NULL; } // highlight the cone limited by these gates RetValue = Aig_SuppMinHighlightCone( p, Aig_Regular(pFunc), vOrGate ); if ( RetValue == 0 ) // no overlap { Vec_PtrFree( vOrGate ); *pStatus = -2; return NULL; } // collect the cone rooted in pFunc limited by vOrGate vNodes = Aig_SuppMinCollectCone( p, Aig_Regular(pFunc) ); // collect the support nodes reachable from the cone vSupp = Aig_SuppMinCollectSupport( p, vNodes ); if ( Vec_PtrSize(vSupp) > nSuppMax ) { Vec_PtrFree( vOrGate ); Vec_PtrFree( vNodes ); Vec_PtrFree( vSupp ); *pStatus = -2; return NULL; } // check if all nodes belonging to OR gate are included in the support // (if this is not the case, don't-care minimization is not possible) if ( !Aig_SuppMinGateIsInSupport( p, vOrGate, vSupp ) ) { Vec_PtrFree( vOrGate ); Vec_PtrFree( vNodes ); Vec_PtrFree( vSupp ); *pStatus = -3; return NULL; } // create truth tables of all nodes and find the maximal number // of support varialbles that can be replaced by constants vCofs = Aig_SuppMinPerform( p, vOrGate, vNodes, vSupp ); if ( Vec_PtrSize(vCofs) == 0 ) { Vec_PtrFree( vCofs ); Vec_PtrFree( vOrGate ); Vec_PtrFree( vNodes ); Vec_PtrFree( vSupp ); *pStatus = -3; return NULL; } // reconstruct the cone pResult = Aig_SuppMinReconstruct( p, vCofs, vNodes, vSupp ); pResult = Aig_NotCond( pResult, Aig_IsComplement(pFunc) ); Vec_PtrFree( vCofs ); Vec_PtrFree( vOrGate ); Vec_PtrFree( vNodes ); Vec_PtrFree( vSupp ); return pResult; } /**Function************************************************************* Synopsis [Testing procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManSupportMinimizationTest() { Aig_Man_t * p; Aig_Obj_t * pFunc, * pCond, * pRes; int i, Status; p = Aig_ManStart( 100 ); for ( i = 0; i < 5; i++ ) Aig_IthVar(p,i); pFunc = Aig_Mux( p, Aig_IthVar(p,3), Aig_IthVar(p,1), Aig_IthVar(p,0) ); pFunc = Aig_Mux( p, Aig_IthVar(p,4), Aig_IthVar(p,2), pFunc ); pCond = Aig_Or( p, Aig_IthVar(p,3), Aig_IthVar(p,4) ); pRes = Aig_ManSupportMinimization( p, pCond, pFunc, &Status ); assert( Status == 0 ); Aig_ObjPrint( p, Aig_Regular(pRes) ); printf( "\n" ); Aig_ObjPrint( p, Aig_ObjFanin0(Aig_Regular(pRes)) ); printf( "\n" ); Aig_ObjPrint( p, Aig_ObjFanin1(Aig_Regular(pRes)) ); printf( "\n" ); Aig_ManStop( p ); } void Aig_ManSupportMinimizationTest2() { Aig_Man_t * p; Aig_Obj_t * node09, * node10, * node11, * node12, * node13, * pRes; int i, Status; p = Aig_ManStart( 100 ); for ( i = 0; i < 3; i++ ) Aig_IthVar(p,i); node09 = Aig_And( p, Aig_IthVar(p,0), Aig_Not(Aig_IthVar(p,1)) ); node10 = Aig_And( p, Aig_Not(node09), Aig_Not(Aig_IthVar(p,2)) ); node11 = Aig_And( p, node10, Aig_IthVar(p,1) ); node12 = Aig_Or( p, Aig_IthVar(p,1), Aig_IthVar(p,2) ); node13 = Aig_Or( p, node12, Aig_IthVar(p,0) ); pRes = Aig_ManSupportMinimization( p, node13, node11, &Status ); assert( Status == 0 ); printf( "Compl = %d ", Aig_IsComplement(pRes) ); Aig_ObjPrint( p, Aig_Regular(pRes) ); printf( "\n" ); if ( Aig_ObjIsNode(Aig_Regular(pRes)) ) { Aig_ObjPrint( p, Aig_ObjFanin0(Aig_Regular(pRes)) ); printf( "\n" ); Aig_ObjPrint( p, Aig_ObjFanin1(Aig_Regular(pRes)) ); printf( "\n" ); } Aig_ManStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigFanout.c000066400000000000000000000137441477524141600163610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigFanout.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Fanout manipulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigFanout.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START // 0: first iFan // 1: prev iFan0 // 2: prev iFan1 // 3: next iFan0 // 4: next iFan1 //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Aig_FanoutCreate( int FanId, int Num ) { assert( Num < 2 ); return (FanId << 1) | Num; } static inline int * Aig_FanoutObj( int * pData, int ObjId ) { return pData + 5*ObjId; } static inline int * Aig_FanoutPrev( int * pData, int iFan ) { return pData + 5*(iFan >> 1) + 1 + (iFan & 1); } static inline int * Aig_FanoutNext( int * pData, int iFan ) { return pData + 5*(iFan >> 1) + 3 + (iFan & 1); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Create fanout for all objects in the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManFanoutStart( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; assert( Aig_ManBufNum(p) == 0 ); // allocate fanout datastructure assert( p->pFanData == NULL ); p->nFansAlloc = 2 * Aig_ManObjNumMax(p); if ( p->nFansAlloc < (1<<12) ) p->nFansAlloc = (1<<12); p->pFanData = ABC_ALLOC( int, 5 * p->nFansAlloc ); memset( p->pFanData, 0, sizeof(int) * 5 * p->nFansAlloc ); // add fanouts for all objects Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjChild0(pObj) ) Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj ); if ( Aig_ObjChild1(pObj) ) Aig_ObjAddFanout( p, Aig_ObjFanin1(pObj), pObj ); } } /**Function************************************************************* Synopsis [Deletes fanout for all objects in the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManFanoutStop( Aig_Man_t * p ) { assert( p->pFanData != NULL ); ABC_FREE( p->pFanData ); p->nFansAlloc = 0; } /**Function************************************************************* Synopsis [Adds fanout (pFanout) of node (pObj).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjAddFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ) { int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext; assert( p->pFanData ); assert( !Aig_IsComplement(pObj) && !Aig_IsComplement(pFanout) ); assert( pFanout->Id > 0 ); if ( pObj->Id >= p->nFansAlloc || pFanout->Id >= p->nFansAlloc ) { int nFansAlloc = 2 * Abc_MaxInt( pObj->Id, pFanout->Id ); p->pFanData = ABC_REALLOC( int, p->pFanData, 5 * nFansAlloc ); memset( p->pFanData + 5 * p->nFansAlloc, 0, sizeof(int) * 5 * (nFansAlloc - p->nFansAlloc) ); p->nFansAlloc = nFansAlloc; } assert( pObj->Id < p->nFansAlloc && pFanout->Id < p->nFansAlloc ); iFan = Aig_FanoutCreate( pFanout->Id, Aig_ObjWhatFanin(pFanout, pObj) ); pPrevC = Aig_FanoutPrev( p->pFanData, iFan ); pNextC = Aig_FanoutNext( p->pFanData, iFan ); pFirst = Aig_FanoutObj( p->pFanData, pObj->Id ); if ( *pFirst == 0 ) { *pFirst = iFan; *pPrevC = iFan; *pNextC = iFan; } else { pPrev = Aig_FanoutPrev( p->pFanData, *pFirst ); pNext = Aig_FanoutNext( p->pFanData, *pPrev ); assert( *pNext == *pFirst ); *pPrevC = *pPrev; *pNextC = *pFirst; *pPrev = iFan; *pNext = iFan; } } /**Function************************************************************* Synopsis [Removes fanout (pFanout) of node (pObj).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjRemoveFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ) { int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext; assert( p->pFanData && pObj->Id < p->nFansAlloc && pFanout->Id < p->nFansAlloc ); assert( !Aig_IsComplement(pObj) && !Aig_IsComplement(pFanout) ); assert( pFanout->Id > 0 ); iFan = Aig_FanoutCreate( pFanout->Id, Aig_ObjWhatFanin(pFanout, pObj) ); pPrevC = Aig_FanoutPrev( p->pFanData, iFan ); pNextC = Aig_FanoutNext( p->pFanData, iFan ); pPrev = Aig_FanoutPrev( p->pFanData, *pNextC ); pNext = Aig_FanoutNext( p->pFanData, *pPrevC ); assert( *pPrev == iFan ); assert( *pNext == iFan ); pFirst = Aig_FanoutObj( p->pFanData, pObj->Id ); assert( *pFirst > 0 ); if ( *pFirst == iFan ) { if ( *pNextC == iFan ) { *pFirst = 0; *pPrev = 0; *pNext = 0; *pPrevC = 0; *pNextC = 0; return; } *pFirst = *pNextC; } *pPrev = *pPrevC; *pNext = *pNextC; *pPrevC = 0; *pNextC = 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigFrames.c000066400000000000000000000125721477524141600163400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigFrames.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Performs timeframe expansion of the AIG.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigFrames.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline Aig_Obj_t * Aig_ObjFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return pObjMap[nFs*pObj->Id + i]; } static inline void Aig_ObjSetFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { pObjMap[nFs*pObj->Id + i] = pNode; } static inline Aig_Obj_t * Aig_ObjChild0Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin0(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } static inline Aig_Obj_t * Aig_ObjChild1Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin1(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs timeframe expansion of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManFrames( Aig_Man_t * pAig, int nFs, int fInit, int fOuts, int fRegs, int fEnlarge, Aig_Obj_t *** ppObjMap ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; Aig_Obj_t ** pObjMap; int i, f; // create mapping for the frames nodes pObjMap = ABC_ALLOC( Aig_Obj_t *, nFs * Aig_ManObjNumMax(pAig) ); memset( pObjMap, 0, sizeof(Aig_Obj_t *) * nFs * Aig_ManObjNumMax(pAig) ); // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFs ); pFrames->pName = Abc_UtilStrsav( pAig->pName ); pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); // map constant nodes for ( f = 0; f < nFs; f++ ) Aig_ObjSetFrames( pObjMap, nFs, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); // create PI nodes for the frames for ( f = 0; f < nFs; f++ ) Aig_ManForEachPiSeq( pAig, pObj, i ) Aig_ObjSetFrames( pObjMap, nFs, pObj, f, Aig_ObjCreateCi(pFrames) ); // set initial state for the latches if ( fInit ) { Aig_ManForEachLoSeq( pAig, pObj, i ) Aig_ObjSetFrames( pObjMap, nFs, pObj, 0, Aig_ManConst0(pFrames) ); } else { Aig_ManForEachLoSeq( pAig, pObj, i ) Aig_ObjSetFrames( pObjMap, nFs, pObj, 0, Aig_ObjCreateCi(pFrames) ); } // add timeframes for ( f = 0; f < nFs; f++ ) { // printf( "Frame = %d.\n", f ); // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) { // Aig_Obj_t * pFanin0 = Aig_ObjChild0Frames(pObjMap,nFs,pObj,f); // Aig_Obj_t * pFanin1 = Aig_ObjChild1Frames(pObjMap,nFs,pObj,f); // printf( "Node = %3d. Fanin0 = %3d. Fanin1 = %3d.\n", pObj->Id, Aig_Regular(pFanin0)->Id, Aig_Regular(pFanin1)->Id ); pObjNew = Aig_And( pFrames, Aig_ObjChild0Frames(pObjMap,nFs,pObj,f), Aig_ObjChild1Frames(pObjMap,nFs,pObj,f) ); Aig_ObjSetFrames( pObjMap, nFs, pObj, f, pObjNew ); } // set the latch inputs and copy them into the latch outputs of the next frame Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i ) { pObjNew = Aig_ObjChild0Frames(pObjMap,nFs,pObjLi,f); if ( f < nFs - 1 ) Aig_ObjSetFrames( pObjMap, nFs, pObjLo, f+1, pObjNew ); } } if ( fOuts ) { for ( f = fEnlarge?nFs-1:0; f < nFs; f++ ) Aig_ManForEachPoSeq( pAig, pObj, i ) { pObjNew = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Frames(pObjMap,nFs,pObj,f) ); Aig_ObjSetFrames( pObjMap, nFs, pObj, f, pObjNew ); } } if ( fRegs ) { pFrames->nRegs = pAig->nRegs; Aig_ManForEachLiSeq( pAig, pObj, i ) { pObjNew = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Frames(pObjMap,nFs,pObj,fEnlarge?0:nFs-1) ); Aig_ObjSetFrames( pObjMap, nFs, pObj, nFs-1, pObjNew ); } Aig_ManSetRegNum( pFrames, Aig_ManRegNum(pAig) ); } Aig_ManCleanup( pFrames ); // return the new manager if ( ppObjMap ) *ppObjMap = pObjMap; else ABC_FREE( pObjMap ); return pFrames; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigInter.c000066400000000000000000000211751477524141600162030ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigInter.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Interpolate two AIGs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigInter.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern abctime timeCnf; extern abctime timeSat; extern abctime timeInt; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManInterFast( Aig_Man_t * pManOn, Aig_Man_t * pManOff, int fVerbose ) { sat_solver * pSat; Cnf_Dat_t * pCnfOn, * pCnfOff; Aig_Obj_t * pObj, * pObj2; int Lits[3], status, i; // abctime clk = Abc_Clock(); assert( Aig_ManCiNum(pManOn) == Aig_ManCiNum(pManOff) ); assert( Aig_ManCoNum(pManOn) == Aig_ManCoNum(pManOff) ); // derive CNFs pManOn->nRegs = Aig_ManCoNum(pManOn); pCnfOn = Cnf_Derive( pManOn, Aig_ManCoNum(pManOn) ); pManOn->nRegs = 0; pManOff->nRegs = Aig_ManCoNum(pManOn); pCnfOff = Cnf_Derive( pManOff, Aig_ManCoNum(pManOff) ); pManOff->nRegs = 0; // pCnfOn = Cnf_DeriveSimple( pManOn, Aig_ManCoNum(pManOn) ); // pCnfOff = Cnf_DeriveSimple( pManOff, Aig_ManCoNum(pManOn) ); Cnf_DataLift( pCnfOff, pCnfOn->nVars ); // start the solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, pCnfOn->nVars + pCnfOff->nVars ); // add clauses of A for ( i = 0; i < pCnfOn->nClauses; i++ ) { if ( !sat_solver_addclause( pSat, pCnfOn->pClauses[i], pCnfOn->pClauses[i+1] ) ) { Cnf_DataFree( pCnfOn ); Cnf_DataFree( pCnfOff ); sat_solver_delete( pSat ); return; } } // add clauses of B for ( i = 0; i < pCnfOff->nClauses; i++ ) { if ( !sat_solver_addclause( pSat, pCnfOff->pClauses[i], pCnfOff->pClauses[i+1] ) ) { Cnf_DataFree( pCnfOn ); Cnf_DataFree( pCnfOff ); sat_solver_delete( pSat ); return; } } // add PI clauses // collect the common variables Aig_ManForEachCi( pManOn, pObj, i ) { pObj2 = Aig_ManCi( pManOff, i ); Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 0 ); Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 1 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 1 ); Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 0 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); } status = sat_solver_simplify( pSat ); assert( status != 0 ); // solve incremental SAT problems Aig_ManForEachCo( pManOn, pObj, i ) { pObj2 = Aig_ManCo( pManOff, i ); Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 0 ); Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 0 ); status = sat_solver_solve( pSat, Lits, Lits+2, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status != l_False ) printf( "The incremental SAT problem is not UNSAT.\n" ); } Cnf_DataFree( pCnfOn ); Cnf_DataFree( pCnfOff ); sat_solver_delete( pSat ); // ABC_PRT( "Fast interpolation time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManInter( Aig_Man_t * pManOn, Aig_Man_t * pManOff, int fRelation, int fVerbose ) { void * pSatCnf = NULL; Inta_Man_t * pManInter; Aig_Man_t * pRes; sat_solver * pSat; Cnf_Dat_t * pCnfOn, * pCnfOff; Vec_Int_t * vVarsAB; Aig_Obj_t * pObj, * pObj2; int Lits[3], status, i; abctime clk; int iLast = -1; // Suppress "might be used uninitialized" assert( Aig_ManCiNum(pManOn) == Aig_ManCiNum(pManOff) ); clk = Abc_Clock(); // derive CNFs // pCnfOn = Cnf_Derive( pManOn, 0 ); // pCnfOff = Cnf_Derive( pManOff, 0 ); pCnfOn = Cnf_DeriveSimple( pManOn, 0 ); pCnfOff = Cnf_DeriveSimple( pManOff, 0 ); Cnf_DataLift( pCnfOff, pCnfOn->nVars ); timeCnf += Abc_Clock() - clk; clk = Abc_Clock(); // start the solver pSat = sat_solver_new(); sat_solver_store_alloc( pSat ); sat_solver_setnvars( pSat, pCnfOn->nVars + pCnfOff->nVars ); // add clauses of A for ( i = 0; i < pCnfOn->nClauses; i++ ) { if ( !sat_solver_addclause( pSat, pCnfOn->pClauses[i], pCnfOn->pClauses[i+1] ) ) { Cnf_DataFree( pCnfOn ); Cnf_DataFree( pCnfOff ); sat_solver_delete( pSat ); return NULL; } } sat_solver_store_mark_clauses_a( pSat ); // update the last clause if ( fRelation ) { extern int sat_solver_store_change_last( sat_solver * pSat ); iLast = sat_solver_store_change_last( pSat ); } // add clauses of B for ( i = 0; i < pCnfOff->nClauses; i++ ) { if ( !sat_solver_addclause( pSat, pCnfOff->pClauses[i], pCnfOff->pClauses[i+1] ) ) { Cnf_DataFree( pCnfOn ); Cnf_DataFree( pCnfOff ); sat_solver_delete( pSat ); return NULL; } } // add PI clauses // collect the common variables vVarsAB = Vec_IntAlloc( Aig_ManCiNum(pManOn) ); if ( fRelation ) Vec_IntPush( vVarsAB, iLast ); Aig_ManForEachCi( pManOn, pObj, i ) { Vec_IntPush( vVarsAB, pCnfOn->pVarNums[pObj->Id] ); pObj2 = Aig_ManCi( pManOff, i ); Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 0 ); Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 1 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 1 ); Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 0 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); } Cnf_DataFree( pCnfOn ); Cnf_DataFree( pCnfOff ); sat_solver_store_mark_roots( pSat ); /* status = sat_solver_simplify(pSat); if ( status == 0 ) { Vec_IntFree( vVarsAB ); Cnf_DataFree( pCnfOn ); Cnf_DataFree( pCnfOff ); sat_solver_delete( pSat ); return NULL; } */ // solve the problem status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); timeSat += Abc_Clock() - clk; if ( status == l_False ) { pSatCnf = sat_solver_store_release( pSat ); // printf( "unsat\n" ); } else if ( status == l_True ) { // printf( "sat\n" ); } else { // printf( "undef\n" ); } sat_solver_delete( pSat ); if ( pSatCnf == NULL ) { printf( "The SAT problem is not unsat.\n" ); Vec_IntFree( vVarsAB ); return NULL; } // create the resulting manager clk = Abc_Clock(); pManInter = Inta_ManAlloc(); pRes = (Aig_Man_t *)Inta_ManInterpolate( pManInter, (Sto_Man_t *)pSatCnf, 0, vVarsAB, fVerbose ); Inta_ManFree( pManInter ); timeInt += Abc_Clock() - clk; /* // test UNSAT core computation { Intp_Man_t * pManProof; Vec_Int_t * vCore; pManProof = Intp_ManAlloc(); vCore = Intp_ManUnsatCore( pManProof, pSatCnf, 0 ); Intp_ManFree( pManProof ); Vec_IntFree( vCore ); } */ Vec_IntFree( vVarsAB ); Sto_ManFree( (Sto_Man_t *)pSatCnf ); // Ioa_WriteAiger( pRes, "inter2.aig", 0, 0 ); return pRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigJust.c000066400000000000000000000236241477524141600160500ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigJust.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Justification of node values.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigJust.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define AIG_VAL0 1 #define AIG_VAL1 2 #define AIG_VALX 3 // storing ternary values static inline int Aig_ObjSetTerValue( Aig_Obj_t * pNode, int Value ) { assert( Value ); pNode->fMarkA = (Value & 1); pNode->fMarkB = ((Value >> 1) & 1); return Value; } static inline int Aig_ObjGetTerValue( Aig_Obj_t * pNode ) { return (pNode->fMarkB << 1) | pNode->fMarkA; } // working with ternary values static inline int Aig_ObjNotTerValue( int Value ) { if ( Value == AIG_VAL1 ) return AIG_VAL0; if ( Value == AIG_VAL0 ) return AIG_VAL1; return AIG_VALX; } static inline int Aig_ObjAndTerValue( int Value0, int Value1 ) { if ( Value0 == AIG_VAL0 || Value1 == AIG_VAL0 ) return AIG_VAL0; if ( Value0 == AIG_VAL1 && Value1 == AIG_VAL1 ) return AIG_VAL1; return AIG_VALX; } static inline int Aig_ObjNotCondTerValue( int Value, int Cond ) { return Cond ? Aig_ObjNotTerValue( Value ) : Value; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns value (0 or 1) or X if unassigned.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_ObjSatValue( Aig_Man_t * pAig, Aig_Obj_t * pNode, int fCompl ) { if ( Aig_ObjIsTravIdCurrent(pAig, pNode) ) return (pNode->fMarkA ^ fCompl) ? AIG_VAL1 : AIG_VAL0; return AIG_VALX; } /**Function************************************************************* Synopsis [Recursively searched for a satisfying assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NtkFindSatAssign_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode, int Value, Vec_Int_t * vSuppLits, int Heur ) { int Value0, Value1; // ++Heur; if ( Aig_ObjIsConst1(pNode) ) return 1; if ( Aig_ObjIsTravIdCurrent(pAig, pNode) ) return ((int)pNode->fMarkA == Value); Aig_ObjSetTravIdCurrent(pAig, pNode); pNode->fMarkA = Value; if ( Aig_ObjIsCi(pNode) ) { // if ( Aig_ObjId(pNode) % 1000 == 0 ) // Value ^= 1; if ( vSuppLits ) Vec_IntPush( vSuppLits, Abc_Var2Lit( Aig_ObjCioId(pNode), !Value ) ); return 1; } assert( Aig_ObjIsNode(pNode) ); // propagation if ( Value ) { if ( !Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), !Aig_ObjFaninC0(pNode), vSuppLits, Heur) ) return 0; return Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), !Aig_ObjFaninC1(pNode), vSuppLits, Heur); } // justification Value0 = Aig_ObjSatValue( pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode) ); if ( Value0 == AIG_VAL0 ) return 1; Value1 = Aig_ObjSatValue( pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode) ); if ( Value1 == AIG_VAL0 ) return 1; if ( Value0 == AIG_VAL1 && Value1 == AIG_VAL1 ) return 0; if ( Value0 == AIG_VAL1 ) return Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), vSuppLits, Heur); if ( Value1 == AIG_VAL1 ) return Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), vSuppLits, Heur); assert( Value0 == AIG_VALX && Value1 == AIG_VALX ); // decision making // if ( rand() % 10 == Heur ) // if ( Aig_ObjId(pNode) % 8 == Heur ) if ( ++Heur % 8 == 0 ) return Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), vSuppLits, Heur); else return Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), vSuppLits, Heur); } /**Function************************************************************* Synopsis [Returns 1 if SAT assignment is found; 0 otherwise.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjFindSatAssign( Aig_Man_t * pAig, Aig_Obj_t * pNode, int Value, Vec_Int_t * vSuppLits ) { int i; if ( Aig_ObjIsCo(pNode) ) return Aig_ObjFindSatAssign( pAig, Aig_ObjFanin0(pNode), Value ^ Aig_ObjFaninC0(pNode), vSuppLits ); for ( i = 0; i < 8; i++ ) { Vec_IntClear( vSuppLits ); Aig_ManIncrementTravId( pAig ); if ( Aig_NtkFindSatAssign_rec( pAig, pNode, Value, vSuppLits, i ) ) return 1; } return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjTerSimulate_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode ) { int Value0, Value1; if ( Aig_ObjIsConst1(pNode) ) return AIG_VAL1; if ( Aig_ObjIsTravIdCurrent(pAig, pNode) ) return Aig_ObjGetTerValue( pNode ); Aig_ObjSetTravIdCurrent( pAig, pNode ); if ( Aig_ObjIsCi(pNode) ) return Aig_ObjSetTerValue( pNode, AIG_VALX ); Value0 = Aig_ObjNotCondTerValue( Aig_ObjTerSimulate_rec(pAig, Aig_ObjFanin0(pNode)), Aig_ObjFaninC0(pNode) ); if ( Aig_ObjIsCo(pNode) || Value0 == AIG_VAL0 ) return Aig_ObjSetTerValue( pNode, Value0 ); assert( Aig_ObjIsNode(pNode) ); Value1 = Aig_ObjNotCondTerValue( Aig_ObjTerSimulate_rec(pAig, Aig_ObjFanin1(pNode)), Aig_ObjFaninC1(pNode) ); return Aig_ObjSetTerValue( pNode, Aig_ObjAndTerValue(Value0, Value1) ); } /**Function************************************************************* Synopsis [Returns value of the object under input assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjTerSimulate( Aig_Man_t * pAig, Aig_Obj_t * pNode, Vec_Int_t * vSuppLits ) { Aig_Obj_t * pObj; int i, Entry; Aig_ManIncrementTravId( pAig ); Vec_IntForEachEntry( vSuppLits, Entry, i ) { pObj = Aig_ManCi( pAig, Abc_Lit2Var(Entry) ); Aig_ObjSetTerValue( pObj, Abc_LitIsCompl(Entry) ? AIG_VAL0 : AIG_VAL1 ); Aig_ObjSetTravIdCurrent( pAig, pObj ); //printf( "%d ", Entry ); } //printf( "\n" ); return Aig_ObjTerSimulate_rec( pAig, pNode ); } typedef struct Aig_ManPack_t_ Aig_ManPack_t; extern Aig_ManPack_t * Aig_ManPackStart( Aig_Man_t * pAig ); extern void Aig_ManPackStop( Aig_ManPack_t * p ); extern void Aig_ManPackAddPattern( Aig_ManPack_t * p, Vec_Int_t * vLits ); extern Vec_Int_t * Aig_ManPackConstNodes( Aig_ManPack_t * p ); /**Function************************************************************* Synopsis [Testing of the framework.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManJustExperiment( Aig_Man_t * pAig ) { Aig_ManPack_t * pPack; Vec_Int_t * vSuppLits, * vNodes; Aig_Obj_t * pObj; int i; abctime clk = Abc_Clock(); int Count0 = 0, Count0f = 0, Count1 = 0, Count1f = 0; int nTotalLits = 0; vSuppLits = Vec_IntAlloc( 100 ); pPack = Aig_ManPackStart( pAig ); vNodes = Aig_ManPackConstNodes( pPack ); // Aig_ManForEachCo( pAig, pObj, i ) Aig_ManForEachObjVec( vNodes, pAig, pObj, i ) { if ( pObj->fPhase ) // const 1 { if ( Aig_ObjFindSatAssign(pAig, pObj, 0, vSuppLits) ) { // assert( Aig_ObjTerSimulate(pAig, pObj, vSuppLits) == AIG_VAL0 ); // if ( Aig_ObjTerSimulate(pAig, pObj, vSuppLits) != AIG_VAL0 ) // printf( "Justification error!\n" ); Count0++; nTotalLits += Vec_IntSize(vSuppLits); Aig_ManPackAddPattern( pPack, vSuppLits ); } else Count0f++; } else { if ( Aig_ObjFindSatAssign(pAig, pObj, 1, vSuppLits) ) { // assert( Aig_ObjTerSimulate(pAig, pObj, vSuppLits) == AIG_VAL1 ); // if ( Aig_ObjTerSimulate(pAig, pObj, vSuppLits) != AIG_VAL1 ) // printf( "Justification error!\n" ); Count1++; nTotalLits += Vec_IntSize(vSuppLits); Aig_ManPackAddPattern( pPack, vSuppLits ); } else Count1f++; } } Vec_IntFree( vSuppLits ); printf( "PO =%6d. C0 =%6d. C0f =%6d. C1 =%6d. C1f =%6d. (%6.2f %%) Ave =%4.1f ", Aig_ManCoNum(pAig), Count0, Count0f, Count1, Count1f, 100.0*(Count0+Count1)/Aig_ManCoNum(pAig), 1.0*nTotalLits/(Count0+Count1) ); Abc_PrintTime( 1, "T", Abc_Clock() - clk ); Aig_ManCleanMarkAB( pAig ); Aig_ManPackStop( pPack ); Vec_IntFree( vNodes ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigMan.c000066400000000000000000000341301477524141600156300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [AIG manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" #include "misc/tim/tim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the AIG manager.] Description [The argument of this procedure is a soft limit on the the number of nodes, or 0 if the limit is unknown.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManStart( int nNodesMax ) { Aig_Man_t * p; if ( nNodesMax <= 0 ) nNodesMax = 10007; // start the manager p = ABC_ALLOC( Aig_Man_t, 1 ); memset( p, 0, sizeof(Aig_Man_t) ); // perform initializations p->nTravIds = 1; p->fCatchExor = 0; // allocate arrays for nodes p->vCis = Vec_PtrAlloc( 100 ); p->vCos = Vec_PtrAlloc( 100 ); p->vObjs = Vec_PtrAlloc( 1000 ); p->vBufs = Vec_PtrAlloc( 100 ); //--jlong -- begin p->unfold2_type_I = Vec_PtrAlloc( 4); p->unfold2_type_II = Vec_PtrAlloc( 4); //--jlong -- end // prepare the internal memory manager p->pMemObjs = Aig_MmFixedStart( sizeof(Aig_Obj_t), nNodesMax ); // create the constant node p->pConst1 = Aig_ManFetchMemory( p ); p->pConst1->Type = AIG_OBJ_CONST1; p->pConst1->fPhase = 1; p->nObjs[AIG_OBJ_CONST1]++; // start the table p->nTableSize = Abc_PrimeCudd( nNodesMax ); p->pTable = ABC_ALLOC( Aig_Obj_t *, p->nTableSize ); memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); return p; } /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManStartFrom( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew; int i; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) { pObjNew = Aig_ObjCreateCi( pNew ); pObjNew->Level = pObj->Level; pObj->pData = pObjNew; } return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG manager recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ManDup_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pObjNew; if ( pObj->pData ) return (Aig_Obj_t *)pObj->pData; Aig_ManDup_rec( pNew, p, Aig_ObjFanin0(pObj) ); if ( Aig_ObjIsBuf(pObj) ) return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj)); Aig_ManDup_rec( pNew, p, Aig_ObjFanin1(pObj) ); pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); return (Aig_Obj_t *)(pObj->pData = pObjNew); } /**Function************************************************************* Synopsis [Extracts the miter composed of XOR of the two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManExtractMiter( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) pObj->pData = Aig_ObjCreateCi(pNew); // dump the nodes Aig_ManDup_rec( pNew, p, pNode1 ); Aig_ManDup_rec( pNew, p, pNode2 ); // construct the EXOR pObj = Aig_Exor( pNew, (Aig_Obj_t *)pNode1->pData, (Aig_Obj_t *)pNode2->pData ); pObj = Aig_NotCond( pObj, Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) ); // add the PO Aig_ObjCreateCo( pNew, pObj ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManExtractMiter(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Stops the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManStop( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; if ( p->time1 ) { ABC_PRT( "time1", p->time1 ); } if ( p->time2 ) { ABC_PRT( "time2", p->time2 ); } // make sure the nodes have clean marks Aig_ManForEachObj( p, pObj, i ) assert( !pObj->fMarkA && !pObj->fMarkB ); Tim_ManStopP( (Tim_Man_t **)&p->pManTime ); if ( p->pFanData ) Aig_ManFanoutStop( p ); if ( p->pManExdc ) Aig_ManStop( p->pManExdc ); // Aig_TableProfile( p ); Aig_MmFixedStop( p->pMemObjs, 0 ); Vec_PtrFreeP( &p->vCis ); Vec_PtrFreeP( &p->vCos ); Vec_PtrFreeP( &p->vObjs ); Vec_PtrFreeP( &p->vBufs ); //--jlong -- begin Vec_PtrFreeP( &p->unfold2_type_I ); Vec_PtrFreeP( &p->unfold2_type_II ); //--jlong -- end Vec_IntFreeP( &p->vLevelR ); Vec_VecFreeP( &p->vLevels ); Vec_IntFreeP( &p->vFlopNums ); Vec_IntFreeP( &p->vFlopReprs ); Vec_VecFreeP( (Vec_Vec_t **)&p->vOnehots ); Vec_VecFreeP( &p->vClockDoms ); Vec_IntFreeP( &p->vProbs ); Vec_IntFreeP( &p->vCiNumsOrig ); Vec_PtrFreeP( &p->vMapped ); if ( p->vSeqModelVec ) Vec_PtrFreeFree( p->vSeqModelVec ); ABC_FREE( p->pTerSimData ); ABC_FREE( p->pFastSim ); ABC_FREE( p->pData ); ABC_FREE( p->pSeqModel ); ABC_FREE( p->pName ); ABC_FREE( p->pSpec ); ABC_FREE( p->pObjCopies ); ABC_FREE( p->pReprs ); ABC_FREE( p->pEquivs ); ABC_FREE( p->pTable ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Stops the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManStopP( Aig_Man_t ** p ) { if ( *p == NULL ) return; Aig_ManStop( *p ); *p = NULL; } /**Function************************************************************* Synopsis [Removes combinational logic that does not feed into POs.] Description [Returns the number of dangling nodes removed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManCleanup( Aig_Man_t * p ) { Vec_Ptr_t * vObjs; Aig_Obj_t * pNode; int i, nNodesOld = Aig_ManNodeNum(p); // collect roots of dangling nodes vObjs = Vec_PtrAlloc( 100 ); Aig_ManForEachObj( p, pNode, i ) if ( Aig_ObjIsNode(pNode) && Aig_ObjRefs(pNode) == 0 ) Vec_PtrPush( vObjs, pNode ); // recursively remove dangling nodes Vec_PtrForEachEntry( Aig_Obj_t *, vObjs, pNode, i ) Aig_ObjDelete_rec( p, pNode, 1 ); Vec_PtrFree( vObjs ); return nNodesOld - Aig_ManNodeNum(p); } /**Function************************************************************* Synopsis [Adds POs for the nodes that otherwise would be dangling.] Description [Returns the number of POs added.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManAntiCleanup( Aig_Man_t * p ) { Aig_Obj_t * pNode; int i, nNodesOld = Aig_ManCoNum(p); Aig_ManForEachObj( p, pNode, i ) if ( Aig_ObjIsNode(pNode) && Aig_ObjRefs(pNode) == 0 ) Aig_ObjCreateCo( p, pNode ); return nNodesOld - Aig_ManCoNum(p); } /**Function************************************************************* Synopsis [Removes PIs without fanouts.] Description [Returns the number of PIs removed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManCiCleanup( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, k = 0, nPisOld = Aig_ManCiNum(p); Vec_PtrForEachEntry( Aig_Obj_t *, p->vCis, pObj, i ) { if ( i >= Aig_ManCiNum(p) - Aig_ManRegNum(p) ) Vec_PtrWriteEntry( p->vCis, k++, pObj ); else if ( Aig_ObjRefs(pObj) > 0 ) Vec_PtrWriteEntry( p->vCis, k++, pObj ); else Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); } Vec_PtrShrink( p->vCis, k ); p->nObjs[AIG_OBJ_CI] = Vec_PtrSize( p->vCis ); if ( Aig_ManRegNum(p) ) p->nTruePis = Aig_ManCiNum(p) - Aig_ManRegNum(p); return nPisOld - Aig_ManCiNum(p); } /**Function************************************************************* Synopsis [Removes POs with constant input.] Description [Returns the number of POs removed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManCoCleanup( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, k = 0, nPosOld = Aig_ManCoNum(p); Vec_PtrForEachEntry( Aig_Obj_t *, p->vCos, pObj, i ) { if ( i >= Aig_ManCoNum(p) - Aig_ManRegNum(p) ) Vec_PtrWriteEntry( p->vCos, k++, pObj ); else if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) || !Aig_ObjFaninC0(pObj) ) // non-const or const1 Vec_PtrWriteEntry( p->vCos, k++, pObj ); else { Aig_ObjDisconnect( p, pObj ); Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); } } Vec_PtrShrink( p->vCos, k ); p->nObjs[AIG_OBJ_CO] = Vec_PtrSize( p->vCos ); if ( Aig_ManRegNum(p) ) p->nTruePos = Aig_ManCoNum(p) - Aig_ManRegNum(p); return nPosOld - Aig_ManCoNum(p); } /**Function************************************************************* Synopsis [Stops the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPrintStats( Aig_Man_t * p ) { int nChoices = Aig_ManChoiceNum(p); printf( "%-15s : ", p->pName ); printf( "pi = %5d ", Aig_ManCiNum(p)-Aig_ManRegNum(p) ); printf( "po = %5d ", Aig_ManCoNum(p)-Aig_ManRegNum(p) ); if ( Aig_ManRegNum(p) ) printf( "lat = %5d ", Aig_ManRegNum(p) ); printf( "and = %7d ", Aig_ManAndNum(p) ); // printf( "Eq = %7d ", Aig_ManHaigCounter(p) ); if ( Aig_ManExorNum(p) ) printf( "xor = %5d ", Aig_ManExorNum(p) ); if ( nChoices ) printf( "ch = %5d ", nChoices ); if ( Aig_ManBufNum(p) ) printf( "buf = %5d ", Aig_ManBufNum(p) ); // printf( "Cre = %6d ", p->nCreated ); // printf( "Del = %6d ", p->nDeleted ); // printf( "Lev = %3d ", Aig_ManLevelNum(p) ); // printf( "Max = %7d ", Aig_ManObjNumMax(p) ); printf( "lev = %3d", Aig_ManLevels(p) ); printf( "\n" ); fflush( stdout ); } /**Function************************************************************* Synopsis [Reports the reduction of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManReportImprovement( Aig_Man_t * p, Aig_Man_t * pNew ) { printf( "REG: Beg = %5d. End = %5d. (R =%5.1f %%) ", Aig_ManRegNum(p), Aig_ManRegNum(pNew), Aig_ManRegNum(p)? 100.0*(Aig_ManRegNum(p)-Aig_ManRegNum(pNew))/Aig_ManRegNum(p) : 0.0 ); printf( "AND: Beg = %6d. End = %6d. (R =%5.1f %%)", Aig_ManNodeNum(p), Aig_ManNodeNum(pNew), Aig_ManNodeNum(p)? 100.0*(Aig_ManNodeNum(p)-Aig_ManNodeNum(pNew))/Aig_ManNodeNum(p) : 0.0 ); printf( "\n" ); } /**Function************************************************************* Synopsis [Sets the number of registers in the AIG manager.] Description [This procedure should be called after the manager is fully constructed.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManSetRegNum( Aig_Man_t * p, int nRegs ) { p->nRegs = nRegs; p->nTruePis = Aig_ManCiNum(p) - nRegs; p->nTruePos = Aig_ManCoNum(p) - nRegs; Aig_ManSetCioIds( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManFlipFirstPo( Aig_Man_t * p ) { Aig_ObjChild0Flip( Aig_ManCo(p, 0) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Aig_ManReleaseData( Aig_Man_t * p ) { void * pD = p->pData; p->pData = NULL; return pD; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigMem.c000066400000000000000000000423211477524141600156340ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigMem.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Memory managers.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigMem.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// struct Aig_MmFixed_t_ { // information about individual entries int nEntrySize; // the size of one entry int nEntriesAlloc; // the total number of entries allocated int nEntriesUsed; // the number of entries in use int nEntriesMax; // the max number of entries in use char * pEntriesFree; // the linked list of free entries // this is where the memory is stored int nChunkSize; // the size of one chunk int nChunksAlloc; // the maximum number of memory chunks int nChunks; // the current number of memory chunks char ** pChunks; // the allocated memory // statistics int nMemoryUsed; // memory used in the allocated entries int nMemoryAlloc; // memory allocated }; struct Aig_MmFlex_t_ { // information about individual entries int nEntriesUsed; // the number of entries allocated char * pCurrent; // the current pointer to free memory char * pEnd; // the first entry outside the free memory // this is where the memory is stored int nChunkSize; // the size of one chunk int nChunksAlloc; // the maximum number of memory chunks int nChunks; // the current number of memory chunks char ** pChunks; // the allocated memory // statistics int nMemoryUsed; // memory used in the allocated entries int nMemoryAlloc; // memory allocated }; struct Aig_MmStep_t_ { int nMems; // the number of fixed memory managers employed Aig_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc int nMapSize; // the size of the memory array Aig_MmFixed_t ** pMap; // maps the number of bytes into its memory manager // additional memory chunks int nChunksAlloc; // the maximum number of memory chunks int nChunks; // the current number of memory chunks char ** pChunks; // the allocated memory }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates memory pieces of fixed size.] Description [The size of the chunk is computed as the minimum of 1024 entries and 64K. Can only work with entry size at least 4 byte long.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_MmFixed_t * Aig_MmFixedStart( int nEntrySize, int nEntriesMax ) { Aig_MmFixed_t * p; p = ABC_ALLOC( Aig_MmFixed_t, 1 ); memset( p, 0, sizeof(Aig_MmFixed_t) ); p->nEntrySize = nEntrySize; p->nEntriesAlloc = 0; p->nEntriesUsed = 0; p->pEntriesFree = NULL; p->nChunkSize = nEntriesMax / 8; if ( p->nChunkSize < 8 ) p->nChunkSize = 8; p->nChunksAlloc = 64; p->nChunks = 0; p->pChunks = ABC_ALLOC( char *, p->nChunksAlloc ); p->nMemoryUsed = 0; p->nMemoryAlloc = 0; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_MmFixedStop( Aig_MmFixed_t * p, int fVerbose ) { int i; if ( p == NULL ) return; if ( fVerbose ) { printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", p->nEntrySize, p->nChunkSize, p->nChunks ); printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); } for ( i = 0; i < p->nChunks; i++ ) ABC_FREE( p->pChunks[i] ); ABC_FREE( p->pChunks ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p ) { char * pTemp; int i; // check if there are still free entries if ( p->nEntriesUsed == p->nEntriesAlloc ) { // need to allocate more entries assert( p->pEntriesFree == NULL ); if ( p->nChunks == p->nChunksAlloc ) { p->nChunksAlloc *= 2; p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); } p->pEntriesFree = ABC_ALLOC( char, p->nEntrySize * p->nChunkSize ); p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; // transform these entries into a linked list pTemp = p->pEntriesFree; for ( i = 1; i < p->nChunkSize; i++ ) { *((char **)pTemp) = pTemp + p->nEntrySize; pTemp += p->nEntrySize; } // set the last link *((char **)pTemp) = NULL; // add the chunk to the chunk storage p->pChunks[ p->nChunks++ ] = p->pEntriesFree; // add to the number of entries allocated p->nEntriesAlloc += p->nChunkSize; } // incrememt the counter of used entries p->nEntriesUsed++; if ( p->nEntriesMax < p->nEntriesUsed ) p->nEntriesMax = p->nEntriesUsed; // return the first entry in the free entry list pTemp = p->pEntriesFree; p->pEntriesFree = *((char **)pTemp); return pTemp; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry ) { // decrement the counter of used entries p->nEntriesUsed--; // add the entry to the linked list of free entries *((char **)pEntry) = p->pEntriesFree; p->pEntriesFree = pEntry; } /**Function************************************************************* Synopsis [] Description [Relocates all the memory except the first chunk.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_MmFixedRestart( Aig_MmFixed_t * p ) { int i; char * pTemp; if ( p->nChunks == 0 ) return; // deallocate all chunks except the first one for ( i = 1; i < p->nChunks; i++ ) ABC_FREE( p->pChunks[i] ); p->nChunks = 1; // transform these entries into a linked list pTemp = p->pChunks[0]; for ( i = 1; i < p->nChunkSize; i++ ) { *((char **)pTemp) = pTemp + p->nEntrySize; pTemp += p->nEntrySize; } // set the last link *((char **)pTemp) = NULL; // set the free entry list p->pEntriesFree = p->pChunks[0]; // set the correct statistics p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; p->nMemoryUsed = 0; p->nEntriesAlloc = p->nChunkSize; p->nEntriesUsed = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_MmFixedReadMemUsage( Aig_MmFixed_t * p ) { return p->nMemoryAlloc; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_MmFixedReadMaxEntriesUsed( Aig_MmFixed_t * p ) { return p->nEntriesMax; } /**Function************************************************************* Synopsis [Allocates entries of flexible size.] Description [Can only work with entry size at least 4 byte long.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_MmFlex_t * Aig_MmFlexStart() { Aig_MmFlex_t * p; p = ABC_ALLOC( Aig_MmFlex_t, 1 ); memset( p, 0, sizeof(Aig_MmFlex_t) ); p->nEntriesUsed = 0; p->pCurrent = NULL; p->pEnd = NULL; p->nChunkSize = (1 << 18); p->nChunksAlloc = 64; p->nChunks = 0; p->pChunks = ABC_ALLOC( char *, p->nChunksAlloc ); p->nMemoryUsed = 0; p->nMemoryAlloc = 0; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_MmFlexStop( Aig_MmFlex_t * p, int fVerbose ) { int i; if ( p == NULL ) return; if ( fVerbose ) { printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", p->nChunkSize, p->nChunks ); printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); } for ( i = 0; i < p->nChunks; i++ ) ABC_FREE( p->pChunks[i] ); ABC_FREE( p->pChunks ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Aig_MmFlexEntryFetch( Aig_MmFlex_t * p, int nBytes ) { char * pTemp; #ifdef ABC_MEMALIGN // extend size to max alignment nBytes += (ABC_MEMALIGN - nBytes % ABC_MEMALIGN) % ABC_MEMALIGN; #endif // check if there are still free entries if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) { // need to allocate more entries if ( p->nChunks == p->nChunksAlloc ) { p->nChunksAlloc *= 2; p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); } if ( nBytes > p->nChunkSize ) { // resize the chunk size if more memory is requested than it can give // (ideally, this should never happen) p->nChunkSize = 2 * nBytes; } p->pCurrent = ABC_ALLOC( char, p->nChunkSize ); p->pEnd = p->pCurrent + p->nChunkSize; p->nMemoryAlloc += p->nChunkSize; // add the chunk to the chunk storage p->pChunks[ p->nChunks++ ] = p->pCurrent; } assert( p->pCurrent + nBytes <= p->pEnd ); // increment the counter of used entries p->nEntriesUsed++; // keep track of the memory used p->nMemoryUsed += nBytes; // return the next entry pTemp = p->pCurrent; p->pCurrent += nBytes; return pTemp; } /**Function************************************************************* Synopsis [] Description [Relocates all the memory except the first chunk.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_MmFlexRestart( Aig_MmFlex_t * p ) { int i; if ( p->nChunks == 0 ) return; // deallocate all chunks except the first one for ( i = 1; i < p->nChunks; i++ ) ABC_FREE( p->pChunks[i] ); p->nChunks = 1; p->nMemoryAlloc = p->nChunkSize; // transform these entries into a linked list p->pCurrent = p->pChunks[0]; p->pEnd = p->pCurrent + p->nChunkSize; p->nEntriesUsed = 0; p->nMemoryUsed = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_MmFlexReadMemUsage( Aig_MmFlex_t * p ) { return p->nMemoryUsed; } /**Function************************************************************* Synopsis [Starts the hierarchical memory manager.] Description [This manager can allocate entries of any size. Iternally they are mapped into the entries with the number of bytes equal to the power of 2. The smallest entry size is 8 bytes. The next one is 16 bytes etc. So, if the user requests 6 bytes, he gets 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. The input parameters "nSteps" says how many fixed memory managers are employed internally. Calling this procedure with nSteps equal to 10 results in 10 hierarchically arranged internal memory managers, which can allocate up to 4096 (1Kb) entries. Requests for larger entries are handed over to malloc() and then ABC_FREE()ed.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_MmStep_t * Aig_MmStepStart( int nSteps ) { Aig_MmStep_t * p; int i, k; p = ABC_ALLOC( Aig_MmStep_t, 1 ); memset( p, 0, sizeof(Aig_MmStep_t) ); p->nMems = nSteps; // start the fixed memory managers p->pMems = ABC_ALLOC( Aig_MmFixed_t *, p->nMems ); for ( i = 0; i < p->nMems; i++ ) p->pMems[i] = Aig_MmFixedStart( (8<nMapSize = (4<nMems); p->pMap = ABC_ALLOC( Aig_MmFixed_t *, p->nMapSize+1 ); p->pMap[0] = NULL; for ( k = 1; k <= 4; k++ ) p->pMap[k] = p->pMems[0]; for ( i = 0; i < p->nMems; i++ ) for ( k = (4<pMap[k] = p->pMems[i]; //for ( i = 1; i < 100; i ++ ) //printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); p->nChunksAlloc = 64; p->nChunks = 0; p->pChunks = ABC_ALLOC( char *, p->nChunksAlloc ); return p; } /**Function************************************************************* Synopsis [Stops the memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_MmStepStop( Aig_MmStep_t * p, int fVerbose ) { int i; for ( i = 0; i < p->nMems; i++ ) Aig_MmFixedStop( p->pMems[i], fVerbose ); if ( p->nChunksAlloc ) { for ( i = 0; i < p->nChunks; i++ ) ABC_FREE( p->pChunks[i] ); ABC_FREE( p->pChunks ); } ABC_FREE( p->pMems ); ABC_FREE( p->pMap ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates the entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Aig_MmStepEntryFetch( Aig_MmStep_t * p, int nBytes ) { if ( nBytes == 0 ) return NULL; #ifdef ABC_MEMALIGN // extend size to max alignment nBytes += (ABC_MEMALIGN - nBytes % ABC_MEMALIGN) % ABC_MEMALIGN; #endif if ( nBytes > p->nMapSize ) { if ( p->nChunks == p->nChunksAlloc ) { p->nChunksAlloc *= 2; p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); } p->pChunks[ p->nChunks++ ] = ABC_ALLOC( char, nBytes ); return p->pChunks[p->nChunks-1]; } return Aig_MmFixedEntryFetch( p->pMap[nBytes] ); } /**Function************************************************************* Synopsis [Recycles the entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_MmStepEntryRecycle( Aig_MmStep_t * p, char * pEntry, int nBytes ) { if ( nBytes == 0 ) return; #ifdef ABC_MEMALIGN // extend size to max alignment nBytes += (ABC_MEMALIGN - nBytes % ABC_MEMALIGN) % ABC_MEMALIGN; #endif if ( nBytes > p->nMapSize ) { // ABC_FREE( pEntry ); return; } Aig_MmFixedEntryRecycle( p->pMap[nBytes], pEntry ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_MmStepReadMemUsage( Aig_MmStep_t * p ) { int i, nMemTotal = 0; for ( i = 0; i < p->nMems; i++ ) nMemTotal += p->pMems[i]->nMemoryAlloc; return nMemTotal; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigMffc.c000066400000000000000000000237731477524141600160030ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigMffc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Computation of MFFCs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigMffc.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Dereferences the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin, float * pPower, float * pProbs ) { float Power0 = 0.0, Power1 = 0.0; Aig_Obj_t * pFanin; int Counter = 0; if ( pProbs ) *pPower = 0.0; if ( Aig_ObjIsCi(pNode) ) return 0; // consider the first fanin pFanin = Aig_ObjFanin0(pNode); assert( pFanin->nRefs > 0 ); if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) ) Counter += Aig_NodeDeref_rec( pFanin, LevelMin, &Power0, pProbs ); if ( pProbs ) *pPower += Power0 + 2.0 * pProbs[pFanin->Id] * (1.0 - pProbs[pFanin->Id]); // skip the buffer if ( Aig_ObjIsBuf(pNode) ) return Counter; assert( Aig_ObjIsNode(pNode) ); // consider the second fanin pFanin = Aig_ObjFanin1(pNode); assert( pFanin->nRefs > 0 ); if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) ) Counter += Aig_NodeDeref_rec( pFanin, LevelMin, &Power1, pProbs ); if ( pProbs ) *pPower += Power1 + 2.0 * pProbs[pFanin->Id] * (1.0 - pProbs[pFanin->Id]); return Counter + 1; } /**Function************************************************************* Synopsis [References the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeRef_rec( Aig_Obj_t * pNode, unsigned LevelMin ) { Aig_Obj_t * pFanin; int Counter = 0; if ( Aig_ObjIsCi(pNode) ) return 0; // consider the first fanin pFanin = Aig_ObjFanin0(pNode); if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) Counter += Aig_NodeRef_rec( pFanin, LevelMin ); // skip the buffer if ( Aig_ObjIsBuf(pNode) ) return Counter; assert( Aig_ObjIsNode(pNode) ); // consider the second fanin pFanin = Aig_ObjFanin1(pNode); if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) Counter += Aig_NodeRef_rec( pFanin, LevelMin ); return Counter + 1; } /**Function************************************************************* Synopsis [References the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeRefLabel_rec( Aig_Man_t * p, Aig_Obj_t * pNode, unsigned LevelMin ) { Aig_Obj_t * pFanin; int Counter = 0; if ( Aig_ObjIsCi(pNode) ) return 0; Aig_ObjSetTravIdCurrent( p, pNode ); // consider the first fanin pFanin = Aig_ObjFanin0(pNode); if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) Counter += Aig_NodeRefLabel_rec( p, pFanin, LevelMin ); if ( Aig_ObjIsBuf(pNode) ) return Counter; assert( Aig_ObjIsNode(pNode) ); // consider the second fanin pFanin = Aig_ObjFanin1(pNode); if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) Counter += Aig_NodeRefLabel_rec( p, pFanin, LevelMin ); return Counter + 1; } /**Function************************************************************* Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_NodeMffcSupp_rec( Aig_Man_t * p, Aig_Obj_t * pNode, unsigned LevelMin, Vec_Ptr_t * vSupp, int fTopmost, Aig_Obj_t * pObjSkip ) { // skip visited nodes if ( Aig_ObjIsTravIdCurrent(p, pNode) ) return; Aig_ObjSetTravIdCurrent(p, pNode); // add to the new support nodes if ( !fTopmost && pNode != pObjSkip && (Aig_ObjIsCi(pNode) || pNode->nRefs > 0 || pNode->Level <= LevelMin) ) { if ( vSupp ) Vec_PtrPush( vSupp, pNode ); return; } assert( Aig_ObjIsNode(pNode) ); // recur on the children Aig_NodeMffcSupp_rec( p, Aig_ObjFanin0(pNode), LevelMin, vSupp, 0, pObjSkip ); Aig_NodeMffcSupp_rec( p, Aig_ObjFanin1(pNode), LevelMin, vSupp, 0, pObjSkip ); } /**Function************************************************************* Synopsis [Collects the support of depth-limited MFFC.] Description [Returns the number of internal nodes in the MFFC.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeMffcSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp ) { int ConeSize1, ConeSize2; if ( vSupp ) Vec_PtrClear( vSupp ); if ( !Aig_ObjIsNode(pNode) ) { if ( Aig_ObjIsCi(pNode) && vSupp ) Vec_PtrPush( vSupp, pNode ); return 0; } assert( !Aig_IsComplement(pNode) ); assert( Aig_ObjIsNode(pNode) ); Aig_ManIncrementTravId( p ); ConeSize1 = Aig_NodeDeref_rec( pNode, LevelMin, NULL, NULL ); Aig_NodeMffcSupp_rec( p, pNode, LevelMin, vSupp, 1, NULL ); ConeSize2 = Aig_NodeRef_rec( pNode, LevelMin ); assert( ConeSize1 == ConeSize2 ); assert( ConeSize1 > 0 ); return ConeSize1; } /**Function************************************************************* Synopsis [Labels the nodes in the MFFC.] Description [Returns the number of internal nodes in the MFFC.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeMffcLabel( Aig_Man_t * p, Aig_Obj_t * pNode, float * pPower ) { int ConeSize1, ConeSize2; assert( (pPower != NULL) == (p->vProbs != NULL) ); assert( !Aig_IsComplement(pNode) ); assert( Aig_ObjIsNode(pNode) ); Aig_ManIncrementTravId( p ); ConeSize1 = Aig_NodeDeref_rec( pNode, 0, pPower, p->vProbs? (float *)p->vProbs->pArray : NULL ); ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 ); assert( ConeSize1 == ConeSize2 ); assert( ConeSize1 > 0 ); return ConeSize1; } /**Function************************************************************* Synopsis [Labels the nodes in the MFFC.] Description [Returns the number of internal nodes in the MFFC.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeMffcLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves ) { Aig_Obj_t * pObj; int i, ConeSize1, ConeSize2; assert( !Aig_IsComplement(pNode) ); assert( Aig_ObjIsNode(pNode) ); Aig_ManIncrementTravId( p ); Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) pObj->nRefs++; ConeSize1 = Aig_NodeDeref_rec( pNode, 0, NULL, NULL ); ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 ); Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) pObj->nRefs--; assert( ConeSize1 == ConeSize2 ); assert( ConeSize1 > 0 ); return ConeSize1; } /**Function************************************************************* Synopsis [Expands the cut by adding the most closely related node.] Description [Returns 1 if the cut exists.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_NodeMffcExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult ) { Aig_Obj_t * pObj, * pLeafBest; int i, LevelMax, ConeSize1, ConeSize2, ConeCur1, ConeCur2, ConeBest; // dereference the current cut LevelMax = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) LevelMax = Abc_MaxInt( LevelMax, (int)pObj->Level ); if ( LevelMax == 0 ) return 0; // dereference the cut ConeSize1 = Aig_NodeDeref_rec( pNode, 0, NULL, NULL ); // try expanding each node in the boundary ConeBest = ABC_INFINITY; pLeafBest = NULL; Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) { if ( (int)pObj->Level != LevelMax ) continue; ConeCur1 = Aig_NodeDeref_rec( pObj, 0, NULL, NULL ); if ( ConeBest > ConeCur1 ) { ConeBest = ConeCur1; pLeafBest = pObj; } ConeCur2 = Aig_NodeRef_rec( pObj, 0 ); assert( ConeCur1 == ConeCur2 ); } assert( pLeafBest != NULL ); assert( Aig_ObjIsNode(pLeafBest) ); // deref the best leaf ConeCur1 = Aig_NodeDeref_rec( pLeafBest, 0, NULL, NULL ); // collect the cut nodes Vec_PtrClear( vResult ); Aig_ManIncrementTravId( p ); Aig_NodeMffcSupp_rec( p, pNode, 0, vResult, 1, pLeafBest ); // ref the nodes ConeCur2 = Aig_NodeRef_rec( pLeafBest, 0 ); assert( ConeCur1 == ConeCur2 ); // ref the original node ConeSize2 = Aig_NodeRef_rec( pNode, 0 ); assert( ConeSize1 == ConeSize2 ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigObj.c000066400000000000000000000415541477524141600156370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigObj.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Adding/removing objects.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigObj.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates primary input.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ObjCreateCi( Aig_Man_t * p ) { Aig_Obj_t * pObj; pObj = Aig_ManFetchMemory( p ); pObj->Type = AIG_OBJ_CI; Vec_PtrPush( p->vCis, pObj ); p->nObjs[AIG_OBJ_CI]++; return pObj; } /**Function************************************************************* Synopsis [Creates primary output with the given driver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ObjCreateCo( Aig_Man_t * p, Aig_Obj_t * pDriver ) { Aig_Obj_t * pObj; pObj = Aig_ManFetchMemory( p ); pObj->Type = AIG_OBJ_CO; Vec_PtrPush( p->vCos, pObj ); Aig_ObjConnect( p, pObj, pDriver, NULL ); p->nObjs[AIG_OBJ_CO]++; return pObj; } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost ) { Aig_Obj_t * pObj; assert( !Aig_IsComplement(pGhost) ); assert( Aig_ObjIsHash(pGhost) ); // assert( pGhost == &p->Ghost ); // get memory for the new object pObj = Aig_ManFetchMemory( p ); pObj->Type = pGhost->Type; // add connections Aig_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); // update node counters of the manager p->nObjs[Aig_ObjType(pObj)]++; assert( pObj->pData == NULL ); // create the power counter if ( p->vProbs ) { float Prob0 = Abc_Int2Float( Vec_IntEntry( p->vProbs, Aig_ObjFaninId0(pObj) ) ); float Prob1 = Abc_Int2Float( Vec_IntEntry( p->vProbs, Aig_ObjFaninId1(pObj) ) ); Prob0 = Aig_ObjFaninC0(pObj)? 1.0 - Prob0 : Prob0; Prob1 = Aig_ObjFaninC1(pObj)? 1.0 - Prob1 : Prob1; Vec_IntSetEntry( p->vProbs, pObj->Id, Abc_Float2Int(Prob0 * Prob1) ); } return pObj; } /**Function************************************************************* Synopsis [Connect the object to the fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 ) { assert( !Aig_IsComplement(pObj) ); assert( !Aig_ObjIsCi(pObj) ); // add the first fanin pObj->pFanin0 = pFan0; pObj->pFanin1 = pFan1; // increment references of the fanins and add their fanouts if ( pFan0 != NULL ) { assert( Aig_ObjFanin0(pObj)->Type > 0 ); Aig_ObjRef( Aig_ObjFanin0(pObj) ); if ( p->pFanData ) Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj ); } if ( pFan1 != NULL ) { assert( Aig_ObjFanin1(pObj)->Type > 0 ); Aig_ObjRef( Aig_ObjFanin1(pObj) ); if ( p->pFanData ) Aig_ObjAddFanout( p, Aig_ObjFanin1(pObj), pObj ); } // set level and phase pObj->Level = Aig_ObjLevelNew( pObj ); pObj->fPhase = Aig_ObjPhaseReal(pFan0) & Aig_ObjPhaseReal(pFan1); // add the node to the structural hash table if ( p->pTable && Aig_ObjIsHash(pObj) ) Aig_TableInsert( p, pObj ); // add the node to the dynamically updated topological order // if ( p->pOrderData && Aig_ObjIsNode(pObj) ) // Aig_ObjOrderInsert( p, pObj->Id ); assert( !Aig_ObjIsNode(pObj) || pObj->Level > 0 ); } /**Function************************************************************* Synopsis [Disconnects the object from the fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); // remove connections if ( pObj->pFanin0 != NULL ) { if ( p->pFanData ) Aig_ObjRemoveFanout( p, Aig_ObjFanin0(pObj), pObj ); Aig_ObjDeref(Aig_ObjFanin0(pObj)); } if ( pObj->pFanin1 != NULL ) { if ( p->pFanData ) Aig_ObjRemoveFanout( p, Aig_ObjFanin1(pObj), pObj ); Aig_ObjDeref(Aig_ObjFanin1(pObj)); } // remove the node from the structural hash table if ( p->pTable && Aig_ObjIsHash(pObj) ) Aig_TableDelete( p, pObj ); // add the first fanin pObj->pFanin0 = NULL; pObj->pFanin1 = NULL; // remove the node from the dynamically updated topological order // if ( p->pOrderData && Aig_ObjIsNode(pObj) ) // Aig_ObjOrderRemove( p, pObj->Id ); } /**Function************************************************************* Synopsis [Deletes the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); assert( !Aig_ObjIsTerm(pObj) ); assert( Aig_ObjRefs(pObj) == 0 ); if ( p->pFanData && Aig_ObjIsBuf(pObj) ) Vec_PtrRemove( p->vBufs, pObj ); p->nObjs[pObj->Type]--; Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); Aig_ManRecycleMemory( p, pObj ); } /**Function************************************************************* Synopsis [Deletes the MFFC of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fFreeTop ) { Aig_Obj_t * pFanin0, * pFanin1; assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsCi(pObj) ) return; assert( !Aig_ObjIsCo(pObj) ); pFanin0 = Aig_ObjFanin0(pObj); pFanin1 = Aig_ObjFanin1(pObj); Aig_ObjDisconnect( p, pObj ); if ( fFreeTop ) Aig_ObjDelete( p, pObj ); if ( pFanin0 && !Aig_ObjIsNone(pFanin0) && Aig_ObjRefs(pFanin0) == 0 ) Aig_ObjDelete_rec( p, pFanin0, 1 ); if ( pFanin1 && !Aig_ObjIsNone(pFanin1) && Aig_ObjRefs(pFanin1) == 0 ) Aig_ObjDelete_rec( p, pFanin1, 1 ); } /**Function************************************************************* Synopsis [Deletes the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjDeletePo( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert( Aig_ObjIsCo(pObj) ); Aig_ObjDeref(Aig_ObjFanin0(pObj)); pObj->pFanin0 = NULL; p->nObjs[pObj->Type]--; Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); Aig_ManRecycleMemory( p, pObj ); } /**Function************************************************************* Synopsis [Replaces the first fanin of the node by the new fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjPatchFanin0( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFaninNew ) { Aig_Obj_t * pFaninOld; assert( !Aig_IsComplement(pObj) ); assert( Aig_ObjIsCo(pObj) ); pFaninOld = Aig_ObjFanin0(pObj); // decrement ref and remove fanout if ( p->pFanData ) Aig_ObjRemoveFanout( p, pFaninOld, pObj ); Aig_ObjDeref( pFaninOld ); // update the fanin pObj->pFanin0 = pFaninNew; pObj->Level = Aig_ObjLevelNew( pObj ); pObj->fPhase = Aig_ObjPhaseReal(pObj->pFanin0); // increment ref and add fanout if ( p->pFanData ) Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj ); Aig_ObjRef( Aig_ObjFanin0(pObj) ); // get rid of old fanin if ( !Aig_ObjIsCi(pFaninOld) && !Aig_ObjIsConst1(pFaninOld) && Aig_ObjRefs(pFaninOld) == 0 ) Aig_ObjDelete_rec( p, pFaninOld, 1 ); } /**Function************************************************************* Synopsis [Verbose printing of the AIG node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjPrint( Aig_Man_t * p, Aig_Obj_t * pObj ) { int fShowFanouts = 0; Aig_Obj_t * pTemp; if ( pObj == NULL ) { printf( "Object is NULL." ); return; } if ( Aig_IsComplement(pObj) ) { printf( "Compl " ); pObj = Aig_Not(pObj); } assert( !Aig_IsComplement(pObj) ); printf( "Node %4d : ", Aig_ObjId(pObj) ); if ( Aig_ObjIsConst1(pObj) ) printf( "constant 1" ); else if ( Aig_ObjIsCi(pObj) ) printf( "PI" ); else if ( Aig_ObjIsCo(pObj) ) printf( "PO( %4d%s )", Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " ") ); else if ( Aig_ObjIsBuf(pObj) ) printf( "BUF( %d%s )", Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " ") ); else printf( "AND( %4d%s, %4d%s )", Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " "), Aig_ObjFanin1(pObj)->Id, (Aig_ObjFaninC1(pObj)? "\'" : " ") ); printf( " (refs = %3d)", Aig_ObjRefs(pObj) ); if ( fShowFanouts && p->pFanData ) { Aig_Obj_t * pFanout; int i; int iFan = -1; // Suppress "might be used uninitialized" printf( "\nFanouts:\n" ); Aig_ObjForEachFanout( p, pObj, pFanout, iFan, i ) { printf( " " ); printf( "Node %4d : ", Aig_ObjId(pFanout) ); if ( Aig_ObjIsCo(pFanout) ) printf( "PO( %4d%s )", Aig_ObjFanin0(pFanout)->Id, (Aig_ObjFaninC0(pFanout)? "\'" : " ") ); else if ( Aig_ObjIsBuf(pFanout) ) printf( "BUF( %d%s )", Aig_ObjFanin0(pFanout)->Id, (Aig_ObjFaninC0(pFanout)? "\'" : " ") ); else printf( "AND( %4d%s, %4d%s )", Aig_ObjFanin0(pFanout)->Id, (Aig_ObjFaninC0(pFanout)? "\'" : " "), Aig_ObjFanin1(pFanout)->Id, (Aig_ObjFaninC1(pFanout)? "\'" : " ") ); printf( "\n" ); } return; } // there are choices if ( p->pEquivs && p->pEquivs[pObj->Id] ) { // print equivalence class printf( " { %4d ", pObj->Id ); for ( pTemp = p->pEquivs[pObj->Id]; pTemp; pTemp = p->pEquivs[pTemp->Id] ) printf( " %4d%s", pTemp->Id, (pTemp->fPhase != pObj->fPhase)? "\'" : " " ); printf( " }" ); return; } // this is a secondary node if ( p->pReprs && p->pReprs[pObj->Id] ) printf( " class of %d", pObj->Id ); } /**Function************************************************************* Synopsis [Replaces node with a buffer fanin by a node without them.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_NodeFixBufferFanins( Aig_Man_t * p, Aig_Obj_t * pObj, int fUpdateLevel ) { Aig_Obj_t * pFanReal0, * pFanReal1, * pResult = NULL; p->nBufFixes++; if ( Aig_ObjIsCo(pObj) ) { assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) ); pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); assert( Aig_ObjPhaseReal(Aig_ObjChild0(pObj)) == Aig_ObjPhaseReal(pFanReal0) ); Aig_ObjPatchFanin0( p, pObj, pFanReal0 ); return; } assert( Aig_ObjIsNode(pObj) ); assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) || Aig_ObjIsBuf(Aig_ObjFanin1(pObj)) ); // get the real fanins pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); pFanReal1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); // get the new node if ( Aig_ObjIsNode(pObj) ) pResult = Aig_Oper( p, pFanReal0, pFanReal1, Aig_ObjType(pObj) ); // else if ( Aig_ObjIsLatch(pObj) ) // pResult = Aig_Latch( p, pFanReal0, Aig_ObjInit(pObj) ); else assert( 0 ); // replace the node with buffer by the node without buffer Aig_ObjReplace( p, pObj, pResult, fUpdateLevel ); } /**Function************************************************************* Synopsis [Returns the number of dangling nodes removed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManPropagateBuffers( Aig_Man_t * p, int fUpdateLevel ) { Aig_Obj_t * pObj; int nSteps; assert( p->pFanData ); for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ ) { // get the node with a buffer fanin for ( pObj = (Aig_Obj_t *)Vec_PtrEntryLast(p->vBufs); Aig_ObjIsBuf(pObj); pObj = Aig_ObjFanout0(p, pObj) ); // replace this node by a node without buffer Aig_NodeFixBufferFanins( p, pObj, fUpdateLevel ); // stop if a cycle occured if ( nSteps > 1000000 ) { printf( "Error: A cycle is encountered while propagating buffers.\n" ); break; } } return nSteps; } /**Function************************************************************* Synopsis [Replaces one object by another.] Description [The new object (pObjNew) should be used instead of the old object (pObjOld). If the new object is complemented or used, the buffer is added and the new object remains in the manager; otherwise, the new object is deleted.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjReplace( Aig_Man_t * p, Aig_Obj_t * pObjOld, Aig_Obj_t * pObjNew, int fUpdateLevel ) { Aig_Obj_t * pObjNewR = Aig_Regular(pObjNew); // the object to be replaced cannot be complemented assert( !Aig_IsComplement(pObjOld) ); // the object to be replaced cannot be a terminal assert( !Aig_ObjIsCi(pObjOld) && !Aig_ObjIsCo(pObjOld) ); // the object to be used cannot be a buffer or a PO assert( !Aig_ObjIsBuf(pObjNewR) && !Aig_ObjIsCo(pObjNewR) ); // the object cannot be the same assert( pObjOld != pObjNewR ); // make sure object is not pointing to itself assert( pObjOld != Aig_ObjFanin0(pObjNewR) ); assert( pObjOld != Aig_ObjFanin1(pObjNewR) ); if ( pObjOld == Aig_ObjFanin0(pObjNewR) || pObjOld == Aig_ObjFanin1(pObjNewR) ) { printf( "Aig_ObjReplace(): Internal error!\n" ); exit(1); } // recursively delete the old node - but leave the object there pObjNewR->nRefs++; Aig_ObjDelete_rec( p, pObjOld, 0 ); pObjNewR->nRefs--; // if the new object is complemented or already used, create a buffer p->nObjs[pObjOld->Type]--; if ( Aig_IsComplement(pObjNew) || Aig_ObjRefs(pObjNew) > 0 || !Aig_ObjIsNode(pObjNew) ) { pObjOld->Type = AIG_OBJ_BUF; Aig_ObjConnect( p, pObjOld, pObjNew, NULL ); p->nBufReplaces++; } else { Aig_Obj_t * pFanin0 = pObjNew->pFanin0; Aig_Obj_t * pFanin1 = pObjNew->pFanin1; int LevelOld = pObjOld->Level; pObjOld->Type = pObjNew->Type; Aig_ObjDisconnect( p, pObjNew ); Aig_ObjConnect( p, pObjOld, pFanin0, pFanin1 ); // delete the new object Aig_ObjDelete( p, pObjNew ); // update levels if ( p->pFanData ) { pObjOld->Level = LevelOld; Aig_ManUpdateLevel( p, pObjOld ); } if ( fUpdateLevel ) { Aig_ObjClearReverseLevel( p, pObjOld ); Aig_ManUpdateReverseLevel( p, pObjOld ); } } p->nObjs[pObjOld->Type]++; // store buffers if fanout is allocated if ( p->pFanData && Aig_ObjIsBuf(pObjOld) ) { Vec_PtrPush( p->vBufs, pObjOld ); p->nBufMax = Abc_MaxInt( p->nBufMax, Vec_PtrSize(p->vBufs) ); Aig_ManPropagateBuffers( p, fUpdateLevel ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigOper.c000066400000000000000000000461311477524141600160260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigOper.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [AIG operations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigOper.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // procedure to detect an EXOR gate static inline int Aig_ObjIsExorType( Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ) { if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) ) return 0; p0 = Aig_Regular(p0); p1 = Aig_Regular(p1); if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) ) return 0; if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) ) return 0; if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) ) return 0; *ppFan0 = Aig_ObjChild0(p0); *ppFan1 = Aig_ObjChild1(p0); return 1; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns i-th elementary variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_IthVar( Aig_Man_t * p, int i ) { int v; for ( v = Aig_ManCiNum(p); v <= i; v++ ) Aig_ObjCreateCi( p ); assert( i < Vec_PtrSize(p->vCis) ); return Aig_ManCi( p, i ); } /**Function************************************************************* Synopsis [Perform one operation.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ) { if ( Type == AIG_OBJ_AND ) return Aig_And( p, p0, p1 ); if ( Type == AIG_OBJ_EXOR ) return Aig_Exor( p, p0, p1 ); assert( 0 ); return NULL; } /**Function************************************************************* Synopsis [Performs canonicization step.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) { Aig_Obj_t * pGhost, * pResult; Aig_Obj_t * pFan0, * pFan1; // check trivial cases if ( p0 == p1 ) return p0; if ( p0 == Aig_Not(p1) ) return Aig_Not(p->pConst1); if ( Aig_Regular(p0) == p->pConst1 ) return p0 == p->pConst1 ? p1 : Aig_Not(p->pConst1); if ( Aig_Regular(p1) == p->pConst1 ) return p1 == p->pConst1 ? p0 : Aig_Not(p->pConst1); // check not so trivial cases if ( p->fAddStrash && (Aig_ObjIsNode(Aig_Regular(p0)) || Aig_ObjIsNode(Aig_Regular(p1))) ) { // http://fmv.jku.at/papers/BrummayerBiere-MEMICS06.pdf Aig_Obj_t * pFanA, * pFanB, * pFanC, * pFanD; pFanA = Aig_ObjChild0(Aig_Regular(p0)); pFanB = Aig_ObjChild1(Aig_Regular(p0)); pFanC = Aig_ObjChild0(Aig_Regular(p1)); pFanD = Aig_ObjChild1(Aig_Regular(p1)); if ( Aig_IsComplement(p0) ) { if ( pFanA == Aig_Not(p1) || pFanB == Aig_Not(p1) ) return p1; if ( pFanB == p1 ) return Aig_And( p, Aig_Not(pFanA), pFanB ); if ( pFanA == p1 ) return Aig_And( p, Aig_Not(pFanB), pFanA ); } else { if ( pFanA == Aig_Not(p1) || pFanB == Aig_Not(p1) ) return Aig_Not(p->pConst1); if ( pFanA == p1 || pFanB == p1 ) return p0; } if ( Aig_IsComplement(p1) ) { if ( pFanC == Aig_Not(p0) || pFanD == Aig_Not(p0) ) return p0; if ( pFanD == p0 ) return Aig_And( p, Aig_Not(pFanC), pFanD ); if ( pFanC == p0 ) return Aig_And( p, Aig_Not(pFanD), pFanC ); } else { if ( pFanC == Aig_Not(p0) || pFanD == Aig_Not(p0) ) return Aig_Not(p->pConst1); if ( pFanC == p0 || pFanD == p0 ) return p1; } if ( !Aig_IsComplement(p0) && !Aig_IsComplement(p1) ) { if ( pFanA == Aig_Not(pFanC) || pFanA == Aig_Not(pFanD) || pFanB == Aig_Not(pFanC) || pFanB == Aig_Not(pFanD) ) return Aig_Not(p->pConst1); if ( pFanA == pFanC || pFanB == pFanC ) return Aig_And( p, p0, pFanD ); if ( pFanB == pFanC || pFanB == pFanD ) return Aig_And( p, pFanA, p1 ); if ( pFanA == pFanD || pFanB == pFanD ) return Aig_And( p, p0, pFanC ); if ( pFanA == pFanC || pFanA == pFanD ) return Aig_And( p, pFanB, p1 ); } else if ( Aig_IsComplement(p0) && !Aig_IsComplement(p1) ) { if ( pFanA == Aig_Not(pFanC) || pFanA == Aig_Not(pFanD) || pFanB == Aig_Not(pFanC) || pFanB == Aig_Not(pFanD) ) return p1; if ( pFanB == pFanC || pFanB == pFanD ) return Aig_And( p, Aig_Not(pFanA), p1 ); if ( pFanA == pFanC || pFanA == pFanD ) return Aig_And( p, Aig_Not(pFanB), p1 ); } else if ( !Aig_IsComplement(p0) && Aig_IsComplement(p1) ) { if ( pFanC == Aig_Not(pFanA) || pFanC == Aig_Not(pFanB) || pFanD == Aig_Not(pFanA) || pFanD == Aig_Not(pFanB) ) return p0; if ( pFanD == pFanA || pFanD == pFanB ) return Aig_And( p, Aig_Not(pFanC), p0 ); if ( pFanC == pFanA || pFanC == pFanB ) return Aig_And( p, Aig_Not(pFanD), p0 ); } else // if ( Aig_IsComplement(p0) && Aig_IsComplement(p1) ) { if ( pFanA == pFanD && pFanB == Aig_Not(pFanC) ) return Aig_Not(pFanA); if ( pFanB == pFanC && pFanA == Aig_Not(pFanD) ) return Aig_Not(pFanB); if ( pFanA == pFanC && pFanB == Aig_Not(pFanD) ) return Aig_Not(pFanA); if ( pFanB == pFanD && pFanA == Aig_Not(pFanC) ) return Aig_Not(pFanB); } } // check if it can be an EXOR gate if ( p->fCatchExor && Aig_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) return Aig_Exor( p, pFan0, pFan1 ); pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_OBJ_AND ); if ( (pResult = Aig_TableLookup( p, pGhost )) ) return pResult; return Aig_ObjCreate( p, pGhost ); } /**Function************************************************************* Synopsis [Performs canonicization step.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) { Aig_Obj_t * pGhost, * pResult; int fCompl; // check trivial cases if ( p0 == p1 ) return Aig_Not(p->pConst1); if ( p0 == Aig_Not(p1) ) return p->pConst1; if ( Aig_Regular(p0) == p->pConst1 ) return Aig_NotCond( p1, p0 == p->pConst1 ); if ( Aig_Regular(p1) == p->pConst1 ) return Aig_NotCond( p0, p1 == p->pConst1 ); // when there is no special XOR gates if ( !p->fCatchExor ) return Aig_Or( p, Aig_And(p, p0, Aig_Not(p1)), Aig_And(p, Aig_Not(p0), p1) ); // canonicize fCompl = Aig_IsComplement(p0) ^ Aig_IsComplement(p1); p0 = Aig_Regular(p0); p1 = Aig_Regular(p1); pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_OBJ_EXOR ); // check the table if ( (pResult = Aig_TableLookup( p, pGhost )) ) return Aig_NotCond( pResult, fCompl ); pResult = Aig_ObjCreate( p, pGhost ); return Aig_NotCond( pResult, fCompl ); } /**Function************************************************************* Synopsis [Implements Boolean OR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) { return Aig_Not( Aig_And( p, Aig_Not(p0), Aig_Not(p1) ) ); } /**Function************************************************************* Synopsis [Implements ITE operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_TableLookupInt( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) { if ( p0 == p1 ) return p0; if ( p0 == Aig_ManConst0(p) || p1 == Aig_ManConst0(p) || p0 == Aig_Not(p1) ) return Aig_ManConst0(p); if ( p0 == Aig_ManConst1(p) ) return p1; if ( p1 == Aig_ManConst1(p) ) return p0; if ( Aig_Regular(p0)->Id < Aig_Regular(p1)->Id ) return Aig_TableLookup( p, Aig_ObjCreateGhost(p, p0, p1, AIG_OBJ_AND) ); return Aig_TableLookup( p, Aig_ObjCreateGhost(p, p1, p0, AIG_OBJ_AND) ); } /**Function************************************************************* Synopsis [Implements ITE operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_Mux2( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 ) { return Aig_Or( p, Aig_And(p, pC, p1), Aig_And(p, Aig_Not(pC), p0) ); } /**Function************************************************************* Synopsis [Implements ITE operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 ) { int fUseMuxCanon = 0; Aig_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; int Count0, Count1; if ( !fUseMuxCanon ) return Aig_Mux2( p, pC, p1, p0 ); if ( p0 == p1 ) return p0; if ( p1 == Aig_Not(p0) ) return Aig_Exor( p, pC, p0 ); if ( pC == Aig_ManConst0(p) ) return p0; if ( pC == Aig_ManConst1(p) ) return p1; if ( p0 == Aig_ManConst0(p) ) return Aig_And( p, pC, p1 ); if ( p0 == Aig_ManConst1(p) ) return Aig_Or( p, Aig_Not(pC), p1 ); if ( p1 == Aig_ManConst0(p) ) return Aig_And( p, Aig_Not(pC), p0 ); if ( p1 == Aig_ManConst1(p) ) return Aig_Or( p, pC, p0 ); // implement the first MUX (F = C * x1 + C' * x0) pTempA1 = Aig_TableLookupInt( p, pC, p1 ); pTempA2 = Aig_TableLookupInt( p, Aig_Not(pC), p0 ); if ( pTempA1 && pTempA2 ) { pTemp = Aig_TableLookupInt( p, Aig_Not(pTempA1), Aig_Not(pTempA2) ); if ( pTemp ) return Aig_Not(pTemp); } Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); // implement the second MUX (F' = C * x1' + C' * x0') pTempB1 = Aig_TableLookupInt( p, pC, Aig_Not(p1) ); pTempB2 = Aig_TableLookupInt( p, Aig_Not(pC), Aig_Not(p0) ); if ( pTempB1 && pTempB2 ) { pTemp = Aig_TableLookupInt( p, Aig_Not(pTempB1), Aig_Not(pTempB2) ); if ( pTemp ) return pTemp; } Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); // compare and decide which one to implement if ( Count0 >= Count1 ) return Aig_Or( p, Aig_And(p, pC, p1), Aig_And(p, Aig_Not(pC), p0) ); return Aig_Not( Aig_Or( p, Aig_And(p, pC, Aig_Not(p1)), Aig_And(p, Aig_Not(pC), Aig_Not(p0)) ) ); // return Aig_Or( p, Aig_And(p, pC, p1), Aig_And(p, Aig_Not(pC), p0) ); } /**Function************************************************************* Synopsis [Implements ITE operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC ) { return Aig_Or( p, Aig_Or(p, Aig_And(p, pA, pB), Aig_And(p, pA, pC)), Aig_And(p, pB, pC) ); } /**Function************************************************************* Synopsis [Constructs the well-balanced tree of gates.] Description [Disregards levels and possible logic sharing.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_Multi_rec( Aig_Man_t * p, Aig_Obj_t ** ppObjs, int nObjs, Aig_Type_t Type ) { Aig_Obj_t * pObj1, * pObj2; if ( nObjs == 1 ) return ppObjs[0]; pObj1 = Aig_Multi_rec( p, ppObjs, nObjs/2, Type ); pObj2 = Aig_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); return Aig_Oper( p, pObj1, pObj2, Type ); } /**Function************************************************************* Synopsis [Old code.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_Multi( Aig_Man_t * p, Aig_Obj_t ** pArgs, int nArgs, Aig_Type_t Type ) { assert( Type == AIG_OBJ_AND || Type == AIG_OBJ_EXOR ); assert( nArgs > 0 ); return Aig_Multi_rec( p, pArgs, nArgs, Type ); } /**Function************************************************************* Synopsis [Implements the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs ) { int i; assert( vPairs->nSize > 0 ); assert( vPairs->nSize % 2 == 0 ); for ( i = 0; i < vPairs->nSize; i += 2 ) vPairs->pArray[i/2] = Aig_Not( Aig_Exor( p, (Aig_Obj_t *)vPairs->pArray[i], (Aig_Obj_t *)vPairs->pArray[i+1] ) ); vPairs->nSize = vPairs->nSize/2; return Aig_Not( Aig_Multi_rec( p, (Aig_Obj_t **)vPairs->pArray, vPairs->nSize, AIG_OBJ_AND ) ); } /**Function************************************************************* Synopsis [Implements the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_MiterTwo( Aig_Man_t * p, Vec_Ptr_t * vNodes1, Vec_Ptr_t * vNodes2 ) { int i; assert( vNodes1->nSize > 0 && vNodes2->nSize > 0 ); assert( vNodes1->nSize == vNodes2->nSize ); for ( i = 0; i < vNodes1->nSize; i++ ) vNodes1->pArray[i] = Aig_Not( Aig_Exor( p, (Aig_Obj_t *)vNodes1->pArray[i], (Aig_Obj_t *)vNodes2->pArray[i] ) ); return Aig_Not( Aig_Multi_rec( p, (Aig_Obj_t **)vNodes1->pArray, vNodes1->nSize, AIG_OBJ_AND ) ); } /**Function************************************************************* Synopsis [Creates AND function with nVars inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_CreateAnd( Aig_Man_t * p, int nVars ) { Aig_Obj_t * pFunc; int i; pFunc = Aig_ManConst1( p ); for ( i = 0; i < nVars; i++ ) pFunc = Aig_And( p, pFunc, Aig_IthVar(p, i) ); return pFunc; } /**Function************************************************************* Synopsis [Creates AND function with nVars inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_CreateOr( Aig_Man_t * p, int nVars ) { Aig_Obj_t * pFunc; int i; pFunc = Aig_ManConst0( p ); for ( i = 0; i < nVars; i++ ) pFunc = Aig_Or( p, pFunc, Aig_IthVar(p, i) ); return pFunc; } /**Function************************************************************* Synopsis [Creates AND function with nVars inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_CreateExor( Aig_Man_t * p, int nVars ) { Aig_Obj_t * pFunc; int i; pFunc = Aig_ManConst0( p ); for ( i = 0; i < nVars; i++ ) pFunc = Aig_Exor( p, pFunc, Aig_IthVar(p, i) ); return pFunc; } /**Function************************************************************* Synopsis [Implements ITE operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_MuxTest() { Vec_Ptr_t * vNodes; Aig_Man_t * p; Aig_Obj_t * pObj, * pFanin0, * pFanin1, * pCtrl; int nNodes = 2000; int i,nPIs = 20; // srand( time(NULL) ); srand( 321 ); vNodes = Vec_PtrAlloc( 100 ); // create a bunch of random MUXes p = Aig_ManStart( 10000 ); for ( i = 0; i < nPIs; i++ ) Aig_IthVar(p,i); for ( i = 0; i < nNodes; i++ ) { if ( rand() % 10 == 0 ) pCtrl = Aig_ManConst0(p); else if ( rand() % 10 == 0 ) pCtrl = Aig_ManConst1(p); else if ( rand() % 3 == 0 || i < nPIs ) pCtrl = Aig_IthVar( p, rand() % nPIs ); else pCtrl = (Aig_Obj_t *)Vec_PtrEntry(vNodes, rand() % i); if ( rand() % 2 == 0 ) pCtrl = Aig_Not( pCtrl ); if ( rand() % 10 == 0 ) pFanin1 = Aig_ManConst0(p); else if ( rand() % 10 == 0 ) pFanin1 = Aig_ManConst1(p); else if ( rand() % 3 == 0 || i < nPIs ) pFanin1 = Aig_IthVar( p, rand() % nPIs ); else pFanin1 = (Aig_Obj_t *)Vec_PtrEntry(vNodes, rand() % i); if ( rand() % 2 == 0 ) pFanin1 = Aig_Not( pFanin1 ); if ( rand() % 10 == 0 ) pFanin0 = Aig_ManConst0(p); else if ( rand() % 10 == 0 ) pFanin0 = Aig_ManConst1(p); else if ( rand() % 3 == 0 || i < nPIs ) pFanin0 = Aig_IthVar( p, rand() % nPIs ); else pFanin0 = (Aig_Obj_t *)Vec_PtrEntry(vNodes, rand() % i); if ( rand() % 2 == 0 ) pFanin0 = Aig_Not( pFanin0 ); pObj = Aig_Mux( p, pCtrl, pFanin1, pFanin0 ); Vec_PtrPush( vNodes, pObj ); } Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) Aig_ObjCreateCo( p, pObj ); Vec_PtrFree( vNodes ); printf( "Number of nodes = %6d.\n", Aig_ManObjNum(p) ); Aig_ManCleanup( p ); printf( "Number of nodes = %6d.\n", Aig_ManObjNum(p) ); Aig_ManDumpBlif( p, "test1.blif", NULL, NULL ); Aig_ManStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigOrder.c000066400000000000000000000117051477524141600161730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigOrder.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Dynamically updated topological order.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigOrder.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Initializes the order datastructure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManOrderStart( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; assert( Aig_ManBufNum(p) == 0 ); // allocate order datastructure assert( p->pOrderData == NULL ); p->nOrderAlloc = 2 * Aig_ManObjNumMax(p); if ( p->nOrderAlloc < (1<<12) ) p->nOrderAlloc = (1<<12); p->pOrderData = ABC_ALLOC( unsigned, 2 * p->nOrderAlloc ); memset( p->pOrderData, 0xFF, sizeof(unsigned) * 2 * p->nOrderAlloc ); // add the constant node p->pOrderData[0] = p->pOrderData[1] = 0; p->iPrev = p->iNext = 0; // add the internal nodes Aig_ManForEachNode( p, pObj, i ) Aig_ObjOrderInsert( p, pObj->Id ); } /**Function************************************************************* Synopsis [Deletes the order datastructure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManOrderStop( Aig_Man_t * p ) { assert( p->pOrderData ); ABC_FREE( p->pOrderData ); p->nOrderAlloc = 0; p->iPrev = p->iNext = 0; } /**Function************************************************************* Synopsis [Inserts an entry before iNext.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjOrderInsert( Aig_Man_t * p, int ObjId ) { int iPrev; assert( ObjId != 0 ); assert( Aig_ObjIsNode( Aig_ManObj(p, ObjId) ) ); if ( ObjId >= p->nOrderAlloc ) { int nOrderAlloc = 2 * ObjId; p->pOrderData = ABC_REALLOC( unsigned, p->pOrderData, 2 * nOrderAlloc ); memset( p->pOrderData + 2 * p->nOrderAlloc, 0xFF, sizeof(unsigned) * 2 * (nOrderAlloc - p->nOrderAlloc) ); p->nOrderAlloc = nOrderAlloc; } assert( p->pOrderData[2*ObjId] == 0xFFFFFFFF ); // prev assert( p->pOrderData[2*ObjId+1] == 0xFFFFFFFF ); // next iPrev = p->pOrderData[2*p->iNext]; assert( p->pOrderData[2*iPrev+1] == (unsigned)p->iNext ); p->pOrderData[2*ObjId] = iPrev; p->pOrderData[2*iPrev+1] = ObjId; p->pOrderData[2*p->iNext] = ObjId; p->pOrderData[2*ObjId+1] = p->iNext; p->nAndTotal++; } /**Function************************************************************* Synopsis [Removes the entry.] Description [If iPrev is removed, it slides backward. If iNext is removed, it slides forward.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjOrderRemove( Aig_Man_t * p, int ObjId ) { int iPrev, iNext; assert( ObjId != 0 ); assert( Aig_ObjIsNode( Aig_ManObj(p, ObjId) ) ); iPrev = p->pOrderData[2*ObjId]; iNext = p->pOrderData[2*ObjId+1]; p->pOrderData[2*ObjId] = 0xFFFFFFFF; p->pOrderData[2*ObjId+1] = 0xFFFFFFFF; p->pOrderData[2*iNext] = iPrev; p->pOrderData[2*iPrev+1] = iNext; if ( p->iPrev == ObjId ) { p->nAndPrev--; p->iPrev = iPrev; } if ( p->iNext == ObjId ) p->iNext = iNext; p->nAndTotal--; } /**Function************************************************************* Synopsis [Advances the order forward.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjOrderAdvance( Aig_Man_t * p ) { assert( p->pOrderData ); assert( p->pOrderData[2*p->iPrev+1] == (unsigned)p->iNext ); p->iPrev = p->iNext; p->nAndPrev++; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigPack.c000066400000000000000000000255101477524141600157750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigPack.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Bit-packing code.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigPack.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // resubstitution manager typedef struct Aig_ManPack_t_ Aig_ManPack_t; struct Aig_ManPack_t_ { Aig_Man_t * pAig; // working manager Vec_Wrd_t * vSigns; // object signatures Vec_Wrd_t * vPiPats; // PI assignments Vec_Wrd_t * vPiCare; // PI care set int iPatCur; // current pattern int fVerbose; // verbosiness flag // statistics int nPatTotal; // number of all patterns int nPatSkip; // number of skipped patterns int nPatRepeat; // number of repeated patterns }; static inline int Aig_Word6CountOnes( word t ) { return Aig_WordCountOnes( (unsigned)(t >> 32) ) + Aig_WordCountOnes( (unsigned)(t & 0xFFFFFFFF) ); } static inline int Aig_Word6HasOneBit( word t ) { return (t & (t-1)) == 0; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_ManPack_t * Aig_ManPackAlloc( Aig_Man_t * pAig ) { Aig_ManPack_t * p; p = ABC_CALLOC( Aig_ManPack_t, 1 ); p->pAig = pAig; p->vSigns = Vec_WrdStart( Aig_ManObjNumMax(pAig) ); p->vPiPats = Vec_WrdStart( Aig_ManCiNum(pAig) ); p->vPiCare = Vec_WrdStart( Aig_ManCiNum(pAig) ); p->iPatCur = 1; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManPackCountCares( Aig_ManPack_t * p ) { Aig_Obj_t * pObj; int i, Total = 0; Aig_ManForEachCi( p->pAig, pObj, i ) Total += Aig_Word6CountOnes( Vec_WrdEntry(p->vPiCare, i) ); return Total; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPackPrintCare( Aig_ManPack_t * p ) { Aig_Obj_t * pObj; word Sign; int i; Aig_ManForEachCi( p->pAig, pObj, i ) { Sign = Vec_WrdEntry( p->vPiCare, i ); // Extra_PrintBinary( stdout, (unsigned *)&Sign, 64 ); // printf( "\n" ); } // printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPackFree( Aig_ManPack_t * p ) { // Aig_ManPackPrintCare( p ); printf( "Patterns: " ); printf( "Total = %6d. ", p->nPatTotal ); printf( "Skipped = %6d. ", p->nPatSkip ); printf( "Cares = %6.2f %% ", 100.0*Aig_ManPackCountCares(p)/Aig_ManCiNum(p->pAig)/64 ); printf( "\n" ); Vec_WrdFree( p->vSigns ); Vec_WrdFree( p->vPiPats ); Vec_WrdFree( p->vPiCare ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPackSetRandom( Aig_ManPack_t * p ) { Aig_Obj_t * pObj; word Sign; int i; Aig_ManForEachCi( p->pAig, pObj, i ) { Sign = (((word)Aig_ManRandom(0)) << 32) | ((word)Aig_ManRandom(0)); Vec_WrdWriteEntry( p->vPiPats, i, Sign << 1 ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPackSimulate( Aig_ManPack_t * p ) { Aig_Obj_t * pObj; word Sign, Sign0, Sign1; int i; // set the constant Vec_WrdWriteEntry( p->vSigns, 0, ~(word)0 ); // transfer into the array Aig_ManForEachCi( p->pAig, pObj, i ) Vec_WrdWriteEntry( p->vSigns, Aig_ObjId(pObj), Vec_WrdEntry(p->vPiPats, i) ); // simulate internal nodes Aig_ManForEachNode( p->pAig, pObj, i ) { Sign0 = Vec_WrdEntry( p->vSigns, Aig_ObjFaninId0(pObj) ); Sign1 = Vec_WrdEntry( p->vSigns, Aig_ObjFaninId1(pObj) ); if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) Sign = ~(Sign0 | Sign1); else if ( Aig_ObjFaninC0(pObj) ) Sign = ~Sign0 & Sign1; else if ( Aig_ObjFaninC1(pObj) ) Sign = Sign0 & ~Sign1; else Sign = Sign0 & Sign1; Vec_WrdWriteEntry( p->vSigns, Aig_ObjId(pObj), Sign ); } // set the outputs Aig_ManForEachCo( p->pAig, pObj, i ) { Sign0 = Vec_WrdEntry( p->vSigns, Aig_ObjFaninId0(pObj) ); Sign = Aig_ObjFaninC0(pObj) ? ~Sign0 : Sign0; Vec_WrdWriteEntry( p->vSigns, Aig_ObjId(pObj), Sign ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPackPrintStats( Aig_ManPack_t * p ) { word Sign; Aig_Obj_t * pObj; int i, Total, Count, Counts[33] = {0}; // the number of nodes having that many patterns Aig_ManForEachNode( p->pAig, pObj, i ) { Sign = Vec_WrdEntry( p->vSigns, Aig_ObjId(pObj) ); Count = Aig_Word6CountOnes( Sign ); if ( Count > 32 ) Count = 64 - Count; Counts[Count]++; } // print statistics Total = 0; for ( i = 0; i <= 32; i++ ) { Total += Counts[i]; printf( "%2d : ", i ); printf( "%6d ", Counts[i] ); printf( "%6.1f %%", 100.0*Counts[i]/Aig_ManNodeNum(p->pAig) ); printf( "%6.1f %%", 100.0*Total/Aig_ManNodeNum(p->pAig) ); printf( "\n" ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Aig_ManPackConstNodes( Aig_ManPack_t * p ) { Vec_Int_t * vNodes; Aig_Obj_t * pObj; word Sign; int i; vNodes = Vec_IntAlloc( 1000 ); Aig_ManForEachNode( p->pAig, pObj, i ) { Sign = Vec_WrdEntry( p->vSigns, Aig_ObjId(pObj) ); if ( Sign == 0 || ~Sign == 0 || Aig_Word6HasOneBit(Sign) || Aig_Word6HasOneBit(~Sign) ) Vec_IntPush( vNodes, Aig_ObjId(pObj) ); } return vNodes; } /**Function************************************************************* Synopsis [Packs patterns into array of simulation info.] Description [] SideEffects [] SeeAlso [] *************************************`**********************************/ int Aig_ManPackAddPatternTry( Aig_ManPack_t * p, int iBit, Vec_Int_t * vLits ) { word * pInfo, * pPres; int i, Lit; Vec_IntForEachEntry( vLits, Lit, i ) { pInfo = Vec_WrdEntryP( p->vPiPats, Abc_Lit2Var(Lit) ); pPres = Vec_WrdEntryP( p->vPiCare, Abc_Lit2Var(Lit) ); if ( Abc_InfoHasBit( (unsigned *)pPres, iBit ) && Abc_InfoHasBit( (unsigned *)pInfo, iBit ) == Abc_LitIsCompl(Lit) ) return 0; } Vec_IntForEachEntry( vLits, Lit, i ) { pInfo = Vec_WrdEntryP( p->vPiPats, Abc_Lit2Var(Lit) ); pPres = Vec_WrdEntryP( p->vPiCare, Abc_Lit2Var(Lit) ); Abc_InfoSetBit( (unsigned *)pPres, iBit ); if ( Abc_InfoHasBit( (unsigned *)pInfo, iBit ) == Abc_LitIsCompl(Lit) ) Abc_InfoXorBit( (unsigned *)pInfo, iBit ); } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPackAddPattern( Aig_ManPack_t * p, Vec_Int_t * vLits ) { int k; for ( k = 1; k < 64; k++ ) if ( Aig_ManPackAddPatternTry( p, k, vLits ) ) break; if ( k == 64 ) { /* word * pInfo, * pPres; int i, Lit; Vec_IntForEachEntry( vLits, Lit, i ) printf( "%d", Abc_LitIsCompl(Lit) ); printf( "\n\n" ); for ( k = 1; k < 64; k++ ) { Vec_IntForEachEntry( vLits, Lit, i ) { pInfo = Vec_WrdEntryP( p->vPiPats, Abc_Lit2Var(Lit) ); pPres = Vec_WrdEntryP( p->vPiCare, Abc_Lit2Var(Lit) ); if ( Abc_InfoHasBit( (unsigned *)pPres, k ) ) printf( "%d", Abc_InfoHasBit( (unsigned *)pInfo, k ) ); else printf( "-" ); } printf( "\n" ); } */ p->nPatSkip++; } p->nPatTotal++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_ManPack_t * Aig_ManPackStart( Aig_Man_t * pAig ) { Aig_ManPack_t * p; p = Aig_ManPackAlloc( pAig ); Aig_ManPackSetRandom( p ); Aig_ManPackSimulate( p ); Aig_ManPackPrintStats( p ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPackStop( Aig_ManPack_t * p ) { Aig_ManPackSimulate( p ); Aig_ManPackPrintStats( p ); Aig_ManPackFree( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigPart.c000066400000000000000000001450021477524141600160240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigPart.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [AIG partitioning package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigPart.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" #include "misc/tim/tim.h" #include "proof/fra/fra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Part_Man_t_ Part_Man_t; struct Part_Man_t_ { int nChunkSize; // the size of one chunk of memory (~1 MB) int nStepSize; // the step size in saving memory (~64 bytes) char * pFreeBuf; // the pointer to free memory int nFreeSize; // the size of remaining free memory Vec_Ptr_t * vMemory; // the memory allocated Vec_Ptr_t * vFree; // the vector of free pieces of memory }; typedef struct Part_One_t_ Part_One_t; struct Part_One_t_ { int nRefs; // the number of references int nOuts; // the number of outputs int nOutsAlloc; // the array size int pOuts[0]; // the array of outputs }; static inline int Part_SizeType( int nSize, int nStepSize ) { return nSize / nStepSize + ((nSize % nStepSize) > 0); } static inline char * Part_OneNext( char * pPart ) { return *((char **)pPart); } static inline void Part_OneSetNext( char * pPart, char * pNext ) { *((char **)pPart) = pNext; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Start the memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Part_Man_t * Part_ManStart( int nChunkSize, int nStepSize ) { Part_Man_t * p; p = ABC_ALLOC( Part_Man_t, 1 ); memset( p, 0, sizeof(Part_Man_t) ); p->nChunkSize = nChunkSize; p->nStepSize = nStepSize; p->vMemory = Vec_PtrAlloc( 1000 ); p->vFree = Vec_PtrAlloc( 1000 ); return p; } /**Function************************************************************* Synopsis [Stops the memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Part_ManStop( Part_Man_t * p ) { void * pMemory; int i; Vec_PtrForEachEntry( void *, p->vMemory, pMemory, i ) ABC_FREE( pMemory ); Vec_PtrFree( p->vMemory ); Vec_PtrFree( p->vFree ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Fetches the memory entry of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Part_ManFetch( Part_Man_t * p, int nSize ) { int Type, nSizeReal; char * pMemory; assert( nSize > 0 ); Type = Part_SizeType( nSize, p->nStepSize ); Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); if ( (pMemory = (char *)Vec_PtrEntry( p->vFree, Type )) ) { Vec_PtrWriteEntry( p->vFree, Type, Part_OneNext(pMemory) ); return pMemory; } nSizeReal = p->nStepSize * Type; if ( p->nFreeSize < nSizeReal ) { p->pFreeBuf = ABC_ALLOC( char, p->nChunkSize ); p->nFreeSize = p->nChunkSize; Vec_PtrPush( p->vMemory, p->pFreeBuf ); } assert( p->nFreeSize >= nSizeReal ); pMemory = p->pFreeBuf; p->pFreeBuf += nSizeReal; p->nFreeSize -= nSizeReal; return pMemory; } /**Function************************************************************* Synopsis [Recycles the memory entry of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Part_ManRecycle( Part_Man_t * p, char * pMemory, int nSize ) { int Type; Type = Part_SizeType( nSize, p->nStepSize ); Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); Part_OneSetNext( pMemory, (char *)Vec_PtrEntry(p->vFree, Type) ); Vec_PtrWriteEntry( p->vFree, Type, pMemory ); } /**Function************************************************************* Synopsis [Fetches the memory entry of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Part_One_t * Part_ManFetchEntry( Part_Man_t * p, int nWords, int nRefs ) { Part_One_t * pPart; pPart = (Part_One_t *)Part_ManFetch( p, sizeof(Part_One_t) + sizeof(int) * nWords ); pPart->nRefs = nRefs; pPart->nOuts = 0; pPart->nOutsAlloc = nWords; return pPart; } /**Function************************************************************* Synopsis [Recycles the memory entry of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Part_ManRecycleEntry( Part_Man_t * p, Part_One_t * pEntry ) { assert( pEntry->nOuts <= pEntry->nOutsAlloc ); assert( pEntry->nOuts >= pEntry->nOutsAlloc/2 ); Part_ManRecycle( p, (char *)pEntry, sizeof(Part_One_t) + sizeof(int) * pEntry->nOutsAlloc ); } /**Function************************************************************* Synopsis [Merges two entries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Part_One_t * Part_ManMergeEntry( Part_Man_t * pMan, Part_One_t * p1, Part_One_t * p2, int nRefs ) { Part_One_t * p = Part_ManFetchEntry( pMan, p1->nOuts + p2->nOuts, nRefs ); int * pBeg1 = p1->pOuts; int * pBeg2 = p2->pOuts; int * pBeg = p->pOuts; int * pEnd1 = p1->pOuts + p1->nOuts; int * pEnd2 = p2->pOuts + p2->nOuts; while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) { if ( *pBeg1 == *pBeg2 ) *pBeg++ = *pBeg1++, pBeg2++; else if ( *pBeg1 < *pBeg2 ) *pBeg++ = *pBeg1++; else *pBeg++ = *pBeg2++; } while ( pBeg1 < pEnd1 ) *pBeg++ = *pBeg1++; while ( pBeg2 < pEnd2 ) *pBeg++ = *pBeg2++; p->nOuts = pBeg - p->pOuts; assert( p->nOuts <= p->nOutsAlloc ); assert( p->nOuts >= p1->nOuts ); assert( p->nOuts >= p2->nOuts ); return p; } /**Function************************************************************* Synopsis [Tranfers the entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Part_ManTransferEntry( Part_One_t * p ) { Vec_Int_t * vSupp; int i; vSupp = Vec_IntAlloc( p->nOuts ); for ( i = 0; i < p->nOuts; i++ ) Vec_IntPush( vSupp, p->pOuts[i] ); return vSupp; } /**Function************************************************************* Synopsis [Computes supports of the POs in the multi-output AIG.] Description [Returns the array of integer arrays containing indices of the primary inputs for each primary output.] SideEffects [Adds the integer PO number at end of each array.] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManSupports( Aig_Man_t * pMan ) { Vec_Ptr_t * vSupports; Vec_Int_t * vSupp; Part_Man_t * p; Part_One_t * pPart0, * pPart1; Aig_Obj_t * pObj; int i, Counter = 0; // set the number of PIs/POs Aig_ManForEachCi( pMan, pObj, i ) pObj->pNext = (Aig_Obj_t *)(long)i; Aig_ManForEachCo( pMan, pObj, i ) pObj->pNext = (Aig_Obj_t *)(long)i; // start the support computation manager p = Part_ManStart( 1 << 20, 1 << 6 ); // consider objects in the topological order vSupports = Vec_PtrAlloc( Aig_ManCoNum(pMan) ); Aig_ManCleanData(pMan); Aig_ManForEachObj( pMan, pObj, i ) { if ( Aig_ObjIsNode(pObj) ) { pPart0 = (Part_One_t *)Aig_ObjFanin0(pObj)->pData; pPart1 = (Part_One_t *)Aig_ObjFanin1(pObj)->pData; pObj->pData = Part_ManMergeEntry( p, pPart0, pPart1, pObj->nRefs ); assert( pPart0->nRefs > 0 ); if ( --pPart0->nRefs == 0 ) Part_ManRecycleEntry( p, pPart0 ); assert( pPart1->nRefs > 0 ); if ( --pPart1->nRefs == 0 ) Part_ManRecycleEntry( p, pPart1 ); if ( ((Part_One_t *)pObj->pData)->nOuts <= 16 ) Counter++; continue; } if ( Aig_ObjIsCo(pObj) ) { pPart0 = (Part_One_t *)Aig_ObjFanin0(pObj)->pData; vSupp = Part_ManTransferEntry(pPart0); Vec_IntPush( vSupp, (int)(long)pObj->pNext ); Vec_PtrPush( vSupports, vSupp ); assert( pPart0->nRefs > 0 ); if ( --pPart0->nRefs == 0 ) Part_ManRecycleEntry( p, pPart0 ); continue; } if ( Aig_ObjIsCi(pObj) ) { if ( pObj->nRefs ) { pPart0 = Part_ManFetchEntry( p, 1, pObj->nRefs ); pPart0->pOuts[ pPart0->nOuts++ ] = (int)(long)pObj->pNext; pObj->pData = pPart0; } continue; } if ( Aig_ObjIsConst1(pObj) ) { if ( pObj->nRefs ) pObj->pData = Part_ManFetchEntry( p, 0, pObj->nRefs ); continue; } assert( 0 ); } //printf( "Memory usage = %d MB.\n", Vec_PtrSize(p->vMemory) * p->nChunkSize / (1<<20) ); Part_ManStop( p ); // sort supports by size Vec_VecSort( (Vec_Vec_t *)vSupports, 1 ); // clear the number of PIs/POs Aig_ManForEachCi( pMan, pObj, i ) pObj->pNext = NULL; Aig_ManForEachCo( pMan, pObj, i ) pObj->pNext = NULL; /* Aig_ManForEachCo( pMan, pObj, i ) printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vSupports, i) ) ); printf( "\n" ); */ // printf( "%d \n", Counter ); return vSupports; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManSupportsTest( Aig_Man_t * pMan ) { Vec_Ptr_t * vSupps; vSupps = Aig_ManSupports( pMan ); Vec_VecFree( (Vec_Vec_t *)vSupps ); } /**Function************************************************************* Synopsis [Computes the set of outputs for each input.] Description [Returns the array of integer arrays containing indices of the primary outputsf for each primary input.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManSupportsInverse( Aig_Man_t * p ) { Vec_Ptr_t * vSupps, * vSuppsInv; Vec_Int_t * vSupp; int i, k, iIn, iOut; // get structural supports for each output vSupps = Aig_ManSupports( p ); // start the inverse supports vSuppsInv = Vec_PtrAlloc( Aig_ManCiNum(p) ); for ( i = 0; i < Aig_ManCiNum(p); i++ ) Vec_PtrPush( vSuppsInv, Vec_IntAlloc(8) ); // transforms the supports into the inverse supports Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vSupp, i ) { iOut = Vec_IntPop( vSupp ); Vec_IntForEachEntry( vSupp, iIn, k ) Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vSuppsInv, iIn), iOut ); } Vec_VecFree( (Vec_Vec_t *)vSupps ); return vSuppsInv; } /**Function************************************************************* Synopsis [Returns the register dependency matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManSupportsRegisters( Aig_Man_t * p ) { Vec_Ptr_t * vSupports, * vMatrix; Vec_Int_t * vSupp; int iOut, iIn, k, m, i; // get structural supports for each output vSupports = Aig_ManSupports( p ); // transforms the supports into the latch dependency matrix vMatrix = Vec_PtrStart( Aig_ManRegNum(p) ); Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vSupp, i ) { // skip true POs iOut = Vec_IntPop( vSupp ); iOut -= Aig_ManCoNum(p) - Aig_ManRegNum(p); if ( iOut < 0 ) { Vec_IntFree( vSupp ); continue; } // remove PIs m = 0; Vec_IntForEachEntry( vSupp, iIn, k ) { iIn -= Aig_ManCiNum(p) - Aig_ManRegNum(p); if ( iIn < 0 ) continue; assert( iIn < Aig_ManRegNum(p) ); Vec_IntWriteEntry( vSupp, m++, iIn ); } Vec_IntShrink( vSupp, m ); // store support in the matrix assert( iOut < Aig_ManRegNum(p) ); Vec_PtrWriteEntry( vMatrix, iOut, vSupp ); } Vec_PtrFree( vSupports ); // check that all supports are used Vec_PtrForEachEntry( Vec_Int_t *, vMatrix, vSupp, i ) assert( vSupp != NULL ); return vMatrix; } /**Function************************************************************* Synopsis [Start char-bases support representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Aig_ManSuppCharStart( Vec_Int_t * vOne, int nPis ) { unsigned * pBuffer; int i, Entry; int nWords = Abc_BitWordNum(nPis); pBuffer = ABC_ALLOC( unsigned, nWords ); memset( pBuffer, 0, sizeof(unsigned) * nWords ); Vec_IntForEachEntry( vOne, Entry, i ) { assert( Entry < nPis ); Abc_InfoSetBit( pBuffer, Entry ); } return pBuffer; } /**Function************************************************************* Synopsis [Add to char-bases support representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManSuppCharAdd( unsigned * pBuffer, Vec_Int_t * vOne, int nPis ) { int i, Entry; Vec_IntForEachEntry( vOne, Entry, i ) { assert( Entry < nPis ); Abc_InfoSetBit( pBuffer, Entry ); } } /**Function************************************************************* Synopsis [Find the common variables using char-bases support representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManSuppCharCommon( unsigned * pBuffer, Vec_Int_t * vOne ) { int i, Entry, nCommon = 0; Vec_IntForEachEntry( vOne, Entry, i ) nCommon += Abc_InfoHasBit(pBuffer, Entry); return nCommon; } /**Function************************************************************* Synopsis [Find the best partition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsBit, int nSuppSizeLimit, Vec_Int_t * vOne ) { Vec_Int_t * vPartSupp;//, * vPart; int Attract, Repulse, Value, ValueBest; int i, nCommon, iBest; iBest = -1; ValueBest = 0; Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vPartSupp, i ) { // vPart = Vec_PtrEntry( vPartsAll, i ); // if ( nSuppSizeLimit > 0 && Vec_IntSize(vPart) >= nSuppSizeLimit ) // continue; // nCommon = Vec_IntTwoCountCommon( vPartSupp, vOne ); nCommon = Aig_ManSuppCharCommon( (unsigned *)Vec_PtrEntry(vPartSuppsBit, i), vOne ); if ( nCommon == 0 ) continue; if ( nCommon == Vec_IntSize(vOne) ) return i; // skip partitions whose size exceeds the limit if ( nSuppSizeLimit > 0 && Vec_IntSize(vPartSupp) >= 2 * nSuppSizeLimit ) continue; Attract = 1000 * nCommon / Vec_IntSize(vOne); if ( Vec_IntSize(vPartSupp) < 100 ) Repulse = 1; else Repulse = 1+Abc_Base2Log(Vec_IntSize(vPartSupp)-100); Value = Attract/Repulse; if ( ValueBest < Value ) { ValueBest = Value; iBest = i; } } if ( ValueBest < 75 ) return -1; return iBest; } /**Function************************************************************* Synopsis [Perform the smart partitioning.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPartitionPrint( Aig_Man_t * p, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll ) { Vec_Int_t * vOne; int i, nOutputs, Counter; Counter = 0; Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i ) { nOutputs = Vec_IntSize((Vec_Int_t *)Vec_PtrEntry(vPartsAll, i)); printf( "%d=(%d,%d) ", i, Vec_IntSize(vOne), nOutputs ); Counter += nOutputs; if ( i == Vec_PtrSize(vPartsAll) - 1 ) break; } assert( Counter == Aig_ManCoNum(p) ); // printf( "\nTotal = %d. Outputs = %d.\n", Counter, Aig_ManCoNum(p) ); } /**Function************************************************************* Synopsis [Perform the smart partitioning.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nSuppSizeLimit ) { Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; int i, iPart; if ( nSuppSizeLimit == 0 ) nSuppSizeLimit = 200; // pack smaller partitions into larger blocks iPart = 0; vPart = vPartSupp = NULL; Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i ) { if ( Vec_IntSize(vOne) < nSuppSizeLimit ) { if ( vPartSupp == NULL ) { assert( vPart == NULL ); vPartSupp = Vec_IntDup(vOne); vPart = (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i); } else { vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); Vec_IntFree( vTemp ); vPart = Vec_IntTwoMerge( vTemp = vPart, (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i) ); Vec_IntFree( vTemp ); Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i) ); } if ( Vec_IntSize(vPartSupp) < nSuppSizeLimit ) continue; } else vPart = (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i); // add the partition Vec_PtrWriteEntry( vPartsAll, iPart, vPart ); vPart = NULL; if ( vPartSupp ) { Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vPartSuppsAll, iPart) ); Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); vPartSupp = NULL; } iPart++; } // add the last one if ( vPart ) { Vec_PtrWriteEntry( vPartsAll, iPart, vPart ); vPart = NULL; assert( vPartSupp != NULL ); Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vPartSuppsAll, iPart) ); Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); vPartSupp = NULL; iPart++; } Vec_PtrShrink( vPartsAll, iPart ); Vec_PtrShrink( vPartsAll, iPart ); } /**Function************************************************************* Synopsis [Perform the smart partitioning.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManPartitionSmart( Aig_Man_t * p, int nSuppSizeLimit, int fVerbose, Vec_Ptr_t ** pvPartSupps ) { Vec_Ptr_t * vPartSuppsBit; Vec_Ptr_t * vSupports, * vPartsAll, * vPartsAll2, * vPartSuppsAll;//, * vPartPtr; Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; int i, iPart, iOut; abctime clk; // compute the supports for all outputs clk = Abc_Clock(); vSupports = Aig_ManSupports( p ); if ( fVerbose ) { ABC_PRT( "Supps", Abc_Clock() - clk ); } // start char-based support representation vPartSuppsBit = Vec_PtrAlloc( 1000 ); // create partitions clk = Abc_Clock(); vPartsAll = Vec_PtrAlloc( 256 ); vPartSuppsAll = Vec_PtrAlloc( 256 ); Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vOne, i ) { // get the output number iOut = Vec_IntPop(vOne); // find closely matching part iPart = Aig_ManPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsBit, nSuppSizeLimit, vOne ); if ( iPart == -1 ) { // create new partition vPart = Vec_IntAlloc( 32 ); Vec_IntPush( vPart, iOut ); // create new partition support vPartSupp = Vec_IntDup( vOne ); // add this partition and its support Vec_PtrPush( vPartsAll, vPart ); Vec_PtrPush( vPartSuppsAll, vPartSupp ); Vec_PtrPush( vPartSuppsBit, Aig_ManSuppCharStart(vOne, Aig_ManCiNum(p)) ); } else { // add output to this partition vPart = (Vec_Int_t *)Vec_PtrEntry( vPartsAll, iPart ); Vec_IntPush( vPart, iOut ); // merge supports vPartSupp = (Vec_Int_t *)Vec_PtrEntry( vPartSuppsAll, iPart ); vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); Vec_IntFree( vTemp ); // reinsert new support Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); Aig_ManSuppCharAdd( (unsigned *)Vec_PtrEntry(vPartSuppsBit, iPart), vOne, Aig_ManCiNum(p) ); } } // stop char-based support representation Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsBit, vTemp, i ) ABC_FREE( vTemp ); Vec_PtrFree( vPartSuppsBit ); //printf( "\n" ); if ( fVerbose ) { ABC_PRT( "Parts", Abc_Clock() - clk ); } clk = Abc_Clock(); // reorder partitions in the decreasing order of support sizes // remember partition number in each partition support Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i ) Vec_IntPush( vOne, i ); // sort the supports in the decreasing order Vec_VecSort( (Vec_Vec_t *)vPartSuppsAll, 1 ); // reproduce partitions vPartsAll2 = Vec_PtrAlloc( 256 ); Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i ) Vec_PtrPush( vPartsAll2, Vec_PtrEntry(vPartsAll, Vec_IntPop(vOne)) ); Vec_PtrFree( vPartsAll ); vPartsAll = vPartsAll2; // compact small partitions // Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll ); Aig_ManPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit ); if ( fVerbose ) // Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll ); printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) ); if ( fVerbose ) { //ABC_PRT( "Comps", Abc_Clock() - clk ); } // cleanup Vec_VecFree( (Vec_Vec_t *)vSupports ); if ( pvPartSupps == NULL ) Vec_VecFree( (Vec_Vec_t *)vPartSuppsAll ); else *pvPartSupps = vPartSuppsAll; /* // converts from intergers to nodes Vec_PtrForEachEntry( Vec_Int_t *, vPartsAll, vPart, iPart ) { vPartPtr = Vec_PtrAlloc( Vec_IntSize(vPart) ); Vec_IntForEachEntry( vPart, iOut, i ) Vec_PtrPush( vPartPtr, Aig_ManCo(p, iOut) ); Vec_IntFree( vPart ); Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr ); } */ return vPartsAll; } /**Function************************************************************* Synopsis [Perform the smart partitioning.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManPartitionSmartRegisters( Aig_Man_t * pAig, int nSuppSizeLimit, int fVerbose ) { Vec_Ptr_t * vPartSuppsBit; Vec_Ptr_t * vSupports, * vPartsAll, * vPartsAll2, * vPartSuppsAll; Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; int i, iPart, iOut; abctime clk; // add output number to each clk = Abc_Clock(); vSupports = Aig_ManSupportsRegisters( pAig ); assert( Vec_PtrSize(vSupports) == Aig_ManRegNum(pAig) ); Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vOne, i ) Vec_IntPush( vOne, i ); if ( fVerbose ) { ABC_PRT( "Supps", Abc_Clock() - clk ); } // start char-based support representation vPartSuppsBit = Vec_PtrAlloc( 1000 ); // create partitions clk = Abc_Clock(); vPartsAll = Vec_PtrAlloc( 256 ); vPartSuppsAll = Vec_PtrAlloc( 256 ); Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vOne, i ) { // get the output number iOut = Vec_IntPop(vOne); // find closely matching part iPart = Aig_ManPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsBit, nSuppSizeLimit, vOne ); if ( iPart == -1 ) { // create new partition vPart = Vec_IntAlloc( 32 ); Vec_IntPush( vPart, iOut ); // create new partition support vPartSupp = Vec_IntDup( vOne ); // add this partition and its support Vec_PtrPush( vPartsAll, vPart ); Vec_PtrPush( vPartSuppsAll, vPartSupp ); Vec_PtrPush( vPartSuppsBit, Aig_ManSuppCharStart(vOne, Vec_PtrSize(vSupports)) ); } else { // add output to this partition vPart = (Vec_Int_t *)Vec_PtrEntry( vPartsAll, iPart ); Vec_IntPush( vPart, iOut ); // merge supports vPartSupp = (Vec_Int_t *)Vec_PtrEntry( vPartSuppsAll, iPart ); vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); Vec_IntFree( vTemp ); // reinsert new support Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); Aig_ManSuppCharAdd( (unsigned *)Vec_PtrEntry(vPartSuppsBit, iPart), vOne, Vec_PtrSize(vSupports) ); } } // stop char-based support representation Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsBit, vTemp, i ) ABC_FREE( vTemp ); Vec_PtrFree( vPartSuppsBit ); //printf( "\n" ); if ( fVerbose ) { ABC_PRT( "Parts", Abc_Clock() - clk ); } clk = Abc_Clock(); // reorder partitions in the decreasing order of support sizes // remember partition number in each partition support Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i ) Vec_IntPush( vOne, i ); // sort the supports in the decreasing order Vec_VecSort( (Vec_Vec_t *)vPartSuppsAll, 1 ); // reproduce partitions vPartsAll2 = Vec_PtrAlloc( 256 ); Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i ) Vec_PtrPush( vPartsAll2, Vec_PtrEntry(vPartsAll, Vec_IntPop(vOne)) ); Vec_PtrFree( vPartsAll ); vPartsAll = vPartsAll2; // compact small partitions // Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll ); Aig_ManPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit ); if ( fVerbose ) // Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll ); printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) ); if ( fVerbose ) { //ABC_PRT( "Comps", Abc_Clock() - clk ); } // cleanup Vec_VecFree( (Vec_Vec_t *)vSupports ); // if ( pvPartSupps == NULL ) Vec_VecFree( (Vec_Vec_t *)vPartSuppsAll ); // else // *pvPartSupps = vPartSuppsAll; /* // converts from intergers to nodes Vec_PtrForEachEntry( Vec_Int_t *, vPartsAll, vPart, iPart ) { vPartPtr = Vec_PtrAlloc( Vec_IntSize(vPart) ); Vec_IntForEachEntry( vPart, iOut, i ) Vec_PtrPush( vPartPtr, Aig_ManCo(p, iOut) ); Vec_IntFree( vPart ); Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr ); } */ return vPartsAll; } /**Function************************************************************* Synopsis [Perform the naive partitioning.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManPartitionNaive( Aig_Man_t * p, int nPartSize ) { Vec_Ptr_t * vParts; Aig_Obj_t * pObj; int nParts, i; nParts = (Aig_ManCoNum(p) / nPartSize) + ((Aig_ManCoNum(p) % nPartSize) > 0); vParts = (Vec_Ptr_t *)Vec_VecStart( nParts ); Aig_ManForEachCo( p, pObj, i ) Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vParts, i / nPartSize), i ); return vParts; } /**Function************************************************************* Synopsis [Adds internal nodes in the topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ManDupPart_rec( Aig_Man_t * pNew, Aig_Man_t * pOld, Aig_Obj_t * pObj, Vec_Int_t * vSuppMap ) { assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsTravIdCurrent(pOld, pObj) ) return (Aig_Obj_t *)pObj->pData; Aig_ObjSetTravIdCurrent(pOld, pObj); if ( Aig_ObjIsCi(pObj) ) { assert( Vec_IntSize(vSuppMap) == Aig_ManCiNum(pNew) ); Vec_IntPush( vSuppMap, (int)(long)pObj->pNext ); return (Aig_Obj_t *)(pObj->pData = Aig_ObjCreateCi(pNew)); } assert( Aig_ObjIsNode(pObj) ); Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin0(pObj), vSuppMap ); Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin1(pObj), vSuppMap ); return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) )); } /**Function************************************************************* Synopsis [Adds internal nodes in the topological order.] Description [Returns the array of new outputs.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManDupPart( Aig_Man_t * pNew, Aig_Man_t * pOld, Vec_Int_t * vPart, Vec_Int_t * vSuppMap, int fInverse ) { Vec_Ptr_t * vOutsTotal; Aig_Obj_t * pObj; int Entry, i; // create the PIs Aig_ManIncrementTravId( pOld ); Aig_ManConst1(pOld)->pData = Aig_ManConst1(pNew); Aig_ObjSetTravIdCurrent( pOld, Aig_ManConst1(pOld) ); if ( !fInverse ) { Vec_IntForEachEntry( vSuppMap, Entry, i ) { pObj = Aig_ManCi( pOld, Entry ); pObj->pData = Aig_ManCi( pNew, i ); Aig_ObjSetTravIdCurrent( pOld, pObj ); } } else { Vec_IntForEachEntry( vSuppMap, Entry, i ) { pObj = Aig_ManCi( pOld, i ); pObj->pData = Aig_ManCi( pNew, Entry ); Aig_ObjSetTravIdCurrent( pOld, pObj ); } vSuppMap = NULL; // should not be useful } // create the internal nodes vOutsTotal = Vec_PtrAlloc( Vec_IntSize(vPart) ); if ( !fInverse ) { Vec_IntForEachEntry( vPart, Entry, i ) { pObj = Aig_ManCo( pOld, Entry ); Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin0(pObj), vSuppMap ); Vec_PtrPush( vOutsTotal, Aig_ObjChild0Copy(pObj) ); } } else { Aig_ManForEachObj( pOld, pObj, i ) { if ( Aig_ObjIsCo(pObj) ) { Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin0(pObj), vSuppMap ); Vec_PtrPush( vOutsTotal, Aig_ObjChild0Copy(pObj) ); } else if ( Aig_ObjIsNode(pObj) && pObj->nRefs == 0 ) Aig_ManDupPart_rec( pNew, pOld, pObj, vSuppMap ); } } return vOutsTotal; } /**Function************************************************************* Synopsis [Adds internal nodes in the topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManDupPartAll_rec( Aig_Man_t * pNew, Aig_Man_t * pOld, Aig_Obj_t * pObj ) { Aig_Obj_t * pObjNew; assert( !Aig_IsComplement(pObj) ); if ( Aig_ObjIsTravIdCurrent(pOld, pObj) ) return; Aig_ObjSetTravIdCurrent(pOld, pObj); if ( Aig_ObjIsCi(pObj) ) pObjNew = Aig_ObjCreateCi(pNew); else if ( Aig_ObjIsCo(pObj) ) { Aig_ManDupPartAll_rec( pNew, pOld, Aig_ObjFanin0(pObj) ); pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } else { assert( Aig_ObjIsNode(pObj) ); Aig_ManDupPartAll_rec( pNew, pOld, Aig_ObjFanin0(pObj) ); Aig_ManDupPartAll_rec( pNew, pOld, Aig_ObjFanin1(pObj) ); pObjNew = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } pObj->pData = pObjNew; pObjNew->pData = pObj; } /**Function************************************************************* Synopsis [Adds internal nodes in the topological order.] Description [Returns the array of new outputs.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupPartAll( Aig_Man_t * pOld, Vec_Int_t * vPart ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew; int i, Entry; Aig_ManIncrementTravId( pOld ); pNew = Aig_ManStart( 5000 ); // map constant nodes pObj = Aig_ManConst1(pOld); pObjNew = Aig_ManConst1(pNew); pObj->pData = pObjNew; pObjNew->pData = pObj; Aig_ObjSetTravIdCurrent(pOld, pObj); // map all other nodes Vec_IntForEachEntry( vPart, Entry, i ) { pObj = Aig_ManCo( pOld, Entry ); Aig_ManDupPartAll_rec( pNew, pOld, pObj ); } return pNew; } /**Function************************************************************* Synopsis [Collects internal nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManSupportNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vSupport ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); if ( Aig_ObjIsCi(pObj) ) { Vec_IntPush( vSupport, Aig_ObjCioId(pObj) ); return; } Aig_ManSupportNodes_rec( p, Aig_ObjFanin0(pObj), vSupport ); Aig_ManSupportNodes_rec( p, Aig_ObjFanin1(pObj), vSupport ); } /**Function************************************************************* Synopsis [Collects internal nodes and PIs in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManSupportNodes( Aig_Man_t * p, Vec_Ptr_t * vParts ) { Vec_Ptr_t * vPartSupps; Vec_Int_t * vPart, * vSupport; int i, k, iOut; Aig_ManSetCioIds( p ); vPartSupps = Vec_PtrAlloc( Vec_PtrSize(vParts) ); Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i ) { vSupport = Vec_IntAlloc( 100 ); Aig_ManIncrementTravId( p ); Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); Vec_IntForEachEntry( vPart, iOut, k ) Aig_ManSupportNodes_rec( p, Aig_ObjFanin0(Aig_ManCo(p, iOut)), vSupport ); // Vec_IntSort( vSupport, 0 ); Vec_PtrPush( vPartSupps, vSupport ); } Aig_ManCleanCioIds( p ); return vPartSupps; } /**Function************************************************************* Synopsis [Create partitioned miter of the two AIGs.] Description [Assumes that each output in the second AIG cannot have more supp vars than the same output in the first AIG.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManMiterPartitioned( Aig_Man_t * p1, Aig_Man_t * p2, int nPartSize, int fSmart ) { Aig_Man_t * pNew; Aig_Obj_t * pMiter; Vec_Ptr_t * vMiters, * vNodes1, * vNodes2; Vec_Ptr_t * vParts, * vPartSupps; Vec_Int_t * vPart, * vPartSupp; int i, k; // partition the first manager if ( fSmart ) vParts = Aig_ManPartitionSmart( p1, nPartSize, 0, &vPartSupps ); else { vParts = Aig_ManPartitionNaive( p1, nPartSize ); vPartSupps = Aig_ManSupportNodes( p1, vParts ); } // derive miters vMiters = Vec_PtrAlloc( Vec_PtrSize(vParts) ); for ( i = 0; i < Vec_PtrSize(vParts); i++ ) { // get partition and its support vPart = (Vec_Int_t *)Vec_PtrEntry( vParts, i ); vPartSupp = (Vec_Int_t *)Vec_PtrEntry( vPartSupps, i ); // create the new miter pNew = Aig_ManStart( 1000 ); // create the PIs for ( k = 0; k < Vec_IntSize(vPartSupp); k++ ) Aig_ObjCreateCi( pNew ); // copy the components vNodes1 = Aig_ManDupPart( pNew, p1, vPart, vPartSupp, 0 ); vNodes2 = Aig_ManDupPart( pNew, p2, vPart, vPartSupp, 0 ); // create the miter pMiter = Aig_MiterTwo( pNew, vNodes1, vNodes2 ); Vec_PtrFree( vNodes1 ); Vec_PtrFree( vNodes2 ); // create the output Aig_ObjCreateCo( pNew, pMiter ); // clean up Aig_ManCleanup( pNew ); Vec_PtrPush( vMiters, pNew ); } Vec_VecFree( (Vec_Vec_t *)vParts ); Vec_VecFree( (Vec_Vec_t *)vPartSupps ); return vMiters; } /**Function************************************************************* Synopsis [Performs partitioned choice computation.] Description [Assumes that each output in the second AIG cannot have more supp vars than the same output in the first AIG.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManChoicePartitioned( Vec_Ptr_t * vAigs, int nPartSize, int nConfMax, int nLevelMax, int fVerbose ) { // extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); // extern void * Abc_FrameGetGlobalFrame(); // extern Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax, int nLevelMax ); Vec_Ptr_t * vPios; Vec_Ptr_t * vOutsTotal, * vOuts; Aig_Man_t * pAigTotal, * pAigPart, * pAig, * pTemp; Vec_Int_t * vPart, * vPartSupp; Vec_Ptr_t * vParts; Aig_Obj_t * pObj; void ** ppData; int i, k, m, nIdMax; assert( Vec_PtrSize(vAigs) > 1 ); // compute the total number of IDs nIdMax = 0; Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, i ) nIdMax += Aig_ManObjNumMax(pAig); // partition the first AIG in the array pAig = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 ); vParts = Aig_ManPartitionSmart( pAig, nPartSize, 0, NULL ); // start the total fraiged AIG pAigTotal = Aig_ManStartFrom( pAig ); Aig_ManReprStart( pAigTotal, nIdMax ); vOutsTotal = Vec_PtrStart( Aig_ManCoNum(pAig) ); // set the PI numbers Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, i ) Aig_ManForEachCi( pAig, pObj, k ) pObj->pNext = (Aig_Obj_t *)(long)k; // Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); // create the total fraiged AIG vPartSupp = Vec_IntAlloc( 100 ); // maps part PI num into total PI num Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i ) { // derive the partition AIG pAigPart = Aig_ManStart( 5000 ); // pAigPart->pName = Extra_UtilStrsav( pAigPart->pName ); Vec_IntClear( vPartSupp ); Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, k ) { vOuts = Aig_ManDupPart( pAigPart, pAig, vPart, vPartSupp, 0 ); if ( k == 0 ) { Vec_PtrForEachEntry( Aig_Obj_t *, vOuts, pObj, m ) Aig_ObjCreateCo( pAigPart, pObj ); } Vec_PtrFree( vOuts ); } // derive the total AIG from the partitioned AIG vOuts = Aig_ManDupPart( pAigTotal, pAigPart, vPart, vPartSupp, 1 ); // add to the outputs Vec_PtrForEachEntry( Aig_Obj_t *, vOuts, pObj, k ) { assert( Vec_PtrEntry( vOutsTotal, Vec_IntEntry(vPart,k) ) == NULL ); Vec_PtrWriteEntry( vOutsTotal, Vec_IntEntry(vPart,k), pObj ); } Vec_PtrFree( vOuts ); // store contents of pData pointers ppData = ABC_ALLOC( void *, Aig_ManObjNumMax(pAigPart) ); Aig_ManForEachObj( pAigPart, pObj, k ) ppData[k] = pObj->pData; // report the process if ( fVerbose ) printf( "Part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", i+1, Vec_PtrSize(vParts), Aig_ManCiNum(pAigPart), Aig_ManCoNum(pAigPart), Aig_ManNodeNum(pAigPart), Aig_ManLevelNum(pAigPart) ); // compute equivalence classes (to be stored in pNew->pReprs) pAig = Fra_FraigChoice( pAigPart, nConfMax, nLevelMax ); Aig_ManStop( pAig ); // reset the pData pointers Aig_ManForEachObj( pAigPart, pObj, k ) pObj->pData = ppData[k]; ABC_FREE( ppData ); // transfer representatives to the total AIG if ( pAigPart->pReprs ) Aig_ManTransferRepr( pAigTotal, pAigPart ); Aig_ManStop( pAigPart ); } if ( fVerbose ) printf( " \r" ); Vec_VecFree( (Vec_Vec_t *)vParts ); Vec_IntFree( vPartSupp ); // Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); // clear the PI numbers Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, i ) Aig_ManForEachCi( pAig, pObj, k ) pObj->pNext = NULL; // add the outputs in the same order Vec_PtrForEachEntry( Aig_Obj_t *, vOutsTotal, pObj, i ) Aig_ObjCreateCo( pAigTotal, pObj ); Vec_PtrFree( vOutsTotal ); // derive the result of choicing pAig = Aig_ManRehash( pAigTotal ); // create the equivalent nodes lists Aig_ManMarkValidChoices( pAig ); // reconstruct the network vPios = Aig_ManOrderPios( pAig, (Aig_Man_t *)Vec_PtrEntry(vAigs,0) ); pAig = Aig_ManDupDfsGuided( pTemp = pAig, vPios ); Aig_ManStop( pTemp ); Vec_PtrFree( vPios ); // duplicate the timing manager pTemp = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 ); if ( pTemp->pManTime ) pAig->pManTime = Tim_ManDup( (Tim_Man_t *)pTemp->pManTime, 0 ); // reset levels Aig_ManChoiceLevel( pAig ); return pAig; } /**Function************************************************************* Synopsis [Performs partitioned choice computation.] Description [Assumes that each output in the second AIG cannot have more supp vars than the same output in the first AIG.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManFraigPartitioned( Aig_Man_t * pAig, int nPartSize, int nConfMax, int nLevelMax, int fVerbose ) { // extern Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax, int nLevelMax ); Aig_Man_t * pAigPart, * pAigTemp; Vec_Int_t * vPart; Vec_Ptr_t * vParts; Aig_Obj_t * pObj; void ** ppData; int i, k; // partition the outputs of the AIG vParts = Aig_ManPartitionNaive( pAig, nPartSize ); // start the equivalence classes Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); // set the PI numbers Aig_ManSetCioIds( pAig ); // create the total fraiged AIG Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i ) { // derive the partition AIG pAigPart = Aig_ManDupPartAll( pAig, vPart ); // store contents of pData pointers ppData = ABC_ALLOC( void *, Aig_ManObjNumMax(pAigPart) ); Aig_ManForEachObj( pAigPart, pObj, k ) ppData[k] = pObj->pData; // report the process if ( fVerbose ) printf( "Part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", i+1, Vec_PtrSize(vParts), Aig_ManCiNum(pAigPart), Aig_ManCoNum(pAigPart), Aig_ManNodeNum(pAigPart), Aig_ManLevelNum(pAigPart) ); // compute equivalence classes (to be stored in pNew->pReprs) pAigTemp = Fra_FraigChoice( pAigPart, nConfMax, nLevelMax ); Aig_ManStop( pAigTemp ); // reset the pData pointers Aig_ManForEachObj( pAigPart, pObj, k ) pObj->pData = ppData[k]; ABC_FREE( ppData ); // transfer representatives to the total AIG if ( pAigPart->pReprs ) Aig_ManTransferRepr( pAig, pAigPart ); Aig_ManStop( pAigPart ); } if ( fVerbose ) printf( " \r" ); Vec_VecFree( (Vec_Vec_t *)vParts ); // clear the PI numbers Aig_ManCleanCioIds( pAig ); // derive the result of choicing return Aig_ManDupRepr( pAig, 0 ); } /**Function************************************************************* Synopsis [Set the representative.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Aig_ObjSetRepr_( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ) { assert( p->pReprs != NULL ); assert( !Aig_IsComplement(pNode1) ); assert( !Aig_IsComplement(pNode2) ); assert( pNode1->Id < p->nReprsAlloc ); assert( pNode2->Id < p->nReprsAlloc ); if ( pNode1 == pNode2 ) return; if ( pNode1->Id < pNode2->Id ) p->pReprs[pNode2->Id] = pNode1; else p->pReprs[pNode1->Id] = pNode2; } /**Function************************************************************* Synopsis [Constructively accumulates choices.] Description [pNew is a new AIG with choices under construction. pPrev is the AIG preceding pThis in the order of deriving choices. pThis is the current AIG to be added to pNew while creating choices.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManChoiceConstructiveOne( Aig_Man_t * pNew, Aig_Man_t * pPrev, Aig_Man_t * pThis ) { Aig_Obj_t * pObj, * pObjNew; int i; assert( Aig_ManCiNum(pNew) == Aig_ManCiNum(pPrev) ); assert( Aig_ManCiNum(pNew) == Aig_ManCiNum(pThis) ); assert( Aig_ManCoNum(pNew) == Aig_ManCoNum(pPrev) ); assert( Aig_ManCoNum(pNew) == Aig_ManCoNum(pThis) ); // make sure the nodes of pPrev point to pNew Aig_ManForEachObj( pNew, pObj, i ) pObj->fMarkB = 1; Aig_ManForEachObj( pPrev, pObj, i ) assert( Aig_Regular((Aig_Obj_t *)pObj->pData)->fMarkB ); Aig_ManForEachObj( pNew, pObj, i ) pObj->fMarkB = 0; // make sure the nodes of pThis point to pPrev Aig_ManForEachObj( pPrev, pObj, i ) pObj->fMarkB = 1; Aig_ManForEachObj( pPrev, pObj, i ) pObj->fMarkB = 0; // remap nodes of pThis on top of pNew using pPrev pObj = Aig_ManConst1(pThis); pObj->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( pThis, pObj, i ) pObj->pData = Aig_ManCi(pNew, i); Aig_ManForEachCo( pThis, pObj, i ) pObj->pData = Aig_ManCo(pNew, i); // go through the nodes in the topological order Aig_ManForEachNode( pThis, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // set the inputs of POs as equivalent Aig_ManForEachCo( pThis, pObj, i ) { pObjNew = Aig_ObjFanin0( Aig_ManCo(pNew,i) ); // pObjNew and Aig_ObjFanin0(pObj)->pData are equivalent Aig_ObjSetRepr_( pNew, pObjNew, Aig_Regular((Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData) ); } } /**Function************************************************************* Synopsis [Constructively accumulates choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManChoiceEval( Aig_Man_t * p ) { Vec_Ptr_t * vSupp; Aig_Obj_t * pNode, * pTemp; int i, Counter; vSupp = Vec_PtrAlloc( 100 ); Aig_ManForEachNode( p, pNode, i ) { if ( !Aig_ObjIsChoice(p, pNode) ) continue; Counter = 0; for ( pTemp = pNode; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) ) Counter++; printf( "Choice node = %5d. Level = %2d. Choices = %d. { ", pNode->Id, pNode->Level, Counter ); for ( pTemp = pNode; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) ) { Counter = Aig_NodeMffcSupp( p, pTemp, 0, vSupp ); printf( "S=%d N=%d L=%d ", Vec_PtrSize(vSupp), Counter, pTemp->Level ); } printf( "}\n" ); } Vec_PtrFree( vSupp ); } /**Function************************************************************* Synopsis [Constructively accumulates choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManChoiceConstructive( Vec_Ptr_t * vAigs, int fVerbose ) { Vec_Ptr_t * vPios; Aig_Man_t * pNew, * pThis, * pPrev, * pTemp; int i; // start AIG with choices pPrev = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 ); pNew = Aig_ManDupOrdered( pPrev ); // create room for equivalent nodes and representatives assert( pNew->pReprs == NULL ); pNew->nReprsAlloc = Vec_PtrSize(vAigs) * Aig_ManObjNumMax(pNew); pNew->pReprs = ABC_ALLOC( Aig_Obj_t *, pNew->nReprsAlloc ); memset( pNew->pReprs, 0, sizeof(Aig_Obj_t *) * pNew->nReprsAlloc ); // add other AIGs one by one Vec_PtrForEachEntryStart( Aig_Man_t *, vAigs, pThis, i, 1 ) { Aig_ManChoiceConstructiveOne( pNew, pPrev, pThis ); pPrev = pThis; } // derive the result of choicing pNew = Aig_ManRehash( pNew ); // create the equivalent nodes lists Aig_ManMarkValidChoices( pNew ); // reconstruct the network vPios = Aig_ManOrderPios( pNew, (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 ) ); pNew = Aig_ManDupDfsGuided( pTemp = pNew, vPios ); Aig_ManStop( pTemp ); Vec_PtrFree( vPios ); // duplicate the timing manager pTemp = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 ); if ( pTemp->pManTime ) pNew->pManTime = Tim_ManDup( (Tim_Man_t *)pTemp->pManTime, 0 ); // reset levels Aig_ManChoiceLevel( pNew ); return pNew; } /* Vec_Ptr_t * vPios; vPios = Aig_ManOrderPios( pMan, pAig ); Vec_PtrFree( vPios ); */ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigPartReg.c000066400000000000000000000475161477524141600164750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigPartReg.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Register partitioning algorithm.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigPartReg.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" //#include "fra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Aig_ManPre_t_ Aig_ManPre_t; struct Aig_ManPre_t_ { // input data Aig_Man_t * pAig; // seq AIG manager Vec_Ptr_t * vMatrix; // register dependency int nRegsMax; // the max number of registers in the cluster // information about partitions Vec_Ptr_t * vParts; // the partitions char * pfUsedRegs; // the registers already included in the partitions // info about the current partition Vec_Int_t * vRegs; // registers of this partition Vec_Int_t * vUniques; // unique registers of this partition Vec_Int_t * vFreeVars; // free variables of this partition Vec_Flt_t * vPartCost; // costs of adding each variable char * pfPartVars; // input/output registers of the partition }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes partitioning of registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_ManPre_t * Aig_ManRegManStart( Aig_Man_t * pAig, int nPartSize ) { Aig_ManPre_t * p; p = ABC_ALLOC( Aig_ManPre_t, 1 ); memset( p, 0, sizeof(Aig_ManPre_t) ); p->pAig = pAig; p->vMatrix = Aig_ManSupportsRegisters( pAig ); p->nRegsMax = nPartSize; p->vParts = Vec_PtrAlloc(256); p->vRegs = Vec_IntAlloc(256); p->vUniques = Vec_IntAlloc(256); p->vFreeVars = Vec_IntAlloc(256); p->vPartCost = Vec_FltAlloc(256); p->pfUsedRegs = ABC_ALLOC( char, Aig_ManRegNum(p->pAig) ); memset( p->pfUsedRegs, 0, sizeof(char) * Aig_ManRegNum(p->pAig) ); p->pfPartVars = ABC_ALLOC( char, Aig_ManRegNum(p->pAig) ); return p; } /**Function************************************************************* Synopsis [Computes partitioning of registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManRegManStop( Aig_ManPre_t * p ) { Vec_VecFree( (Vec_Vec_t *)p->vMatrix ); if ( p->vParts ) Vec_VecFree( (Vec_Vec_t *)p->vParts ); Vec_IntFree( p->vRegs ); Vec_IntFree( p->vUniques ); Vec_IntFree( p->vFreeVars ); Vec_FltFree( p->vPartCost ); ABC_FREE( p->pfUsedRegs ); ABC_FREE( p->pfPartVars ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Determines what register to use as the seed.] Description [The register is selected as the one having the largest number of non-taken registers in its support.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManRegFindSeed( Aig_ManPre_t * p ) { Vec_Int_t * vRegs; int i, k, iReg; int iMax = -1; // Suppress "might be used uninitialized" int nRegsCur, nRegsMax = -1; for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) { if ( p->pfUsedRegs[i] ) continue; nRegsCur = 0; vRegs = (Vec_Int_t *)Vec_PtrEntry( p->vMatrix, i ); Vec_IntForEachEntry( vRegs, iReg, k ) nRegsCur += !p->pfUsedRegs[iReg]; if ( nRegsMax < nRegsCur ) { nRegsMax = nRegsCur; iMax = i; } } return iMax; } /**Function************************************************************* Synopsis [Computes the next register to be added to the set.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManRegFindBestVar( Aig_ManPre_t * p ) { Vec_Int_t * vSupp; int nNewVars, nNewVarsBest = ABC_INFINITY; int iVarFree, iVarSupp, iVarBest = -1, i, k; // go through the free variables Vec_IntForEachEntry( p->vFreeVars, iVarFree, i ) { // if ( p->pfUsedRegs[iVarFree] ) // continue; // get support of this variable vSupp = (Vec_Int_t *)Vec_PtrEntry( p->vMatrix, iVarFree ); // count the number of new vars nNewVars = 0; Vec_IntForEachEntry( vSupp, iVarSupp, k ) { if ( p->pfPartVars[iVarSupp] ) continue; nNewVars += 1 + 3 * p->pfUsedRegs[iVarSupp]; } // quit if there is no new variables if ( nNewVars == 0 ) return iVarFree; // compare the cost of this if ( nNewVarsBest > nNewVars ) { nNewVarsBest = nNewVars; iVarBest = iVarFree; } } return iVarBest; } /**Function************************************************************* Synopsis [Computes partitioning of registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManRegPartitionAdd( Aig_ManPre_t * p, int iReg ) { Vec_Int_t * vSupp; int RetValue, iVar, i; // make sure this is a new variable // assert( !p->pfUsedRegs[iReg] ); if ( !p->pfUsedRegs[iReg] ) { p->pfUsedRegs[iReg] = 1; Vec_IntPush( p->vUniques, iReg ); } // remove it from the free variables if ( Vec_IntSize(p->vFreeVars) > 0 ) { assert( p->pfPartVars[iReg] ); RetValue = Vec_IntRemove( p->vFreeVars, iReg ); assert( RetValue ); } else assert( !p->pfPartVars[iReg] ); // add it to the partition p->pfPartVars[iReg] = 1; Vec_IntPush( p->vRegs, iReg ); // add new variables vSupp = (Vec_Int_t *)Vec_PtrEntry( p->vMatrix, iReg ); Vec_IntForEachEntry( vSupp, iVar, i ) { if ( p->pfPartVars[iVar] ) continue; p->pfPartVars[iVar] = 1; Vec_IntPush( p->vFreeVars, iVar ); } // add it to the cost Vec_FltPush( p->vPartCost, 1.0*Vec_IntSize(p->vFreeVars)/Vec_IntSize(p->vRegs) ); } /**Function************************************************************* Synopsis [Creates projection of 1-hot registers onto the given partition.] Description [Assumes that the relevant register outputs are labeled with the current traversal ID.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManRegProjectOnehots( Aig_Man_t * pAig, Aig_Man_t * pPart, Vec_Ptr_t * vOnehots, int fVerbose ) { Vec_Ptr_t * vOnehotsPart = NULL; Vec_Int_t * vGroup, * vGroupNew; Aig_Obj_t * pObj, * pObjNew; int nOffset, iReg, i, k; // set the PI numbers Aig_ManForEachCi( pPart, pObj, i ) pObj->iData = i; // go through each group and check if registers are involved in this one nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig); Vec_PtrForEachEntry( Vec_Int_t *, vOnehots, vGroup, i ) { vGroupNew = NULL; Vec_IntForEachEntry( vGroup, iReg, k ) { pObj = Aig_ManCi( pAig, nOffset+iReg ); if ( !Aig_ObjIsTravIdCurrent(pAig, pObj) ) continue; if ( vGroupNew == NULL ) vGroupNew = Vec_IntAlloc( Vec_IntSize(vGroup) ); pObjNew = (Aig_Obj_t *)pObj->pData; Vec_IntPush( vGroupNew, pObjNew->iData ); } if ( vGroupNew == NULL ) continue; if ( Vec_IntSize(vGroupNew) > 1 ) { if ( vOnehotsPart == NULL ) vOnehotsPart = Vec_PtrAlloc( 100 ); Vec_PtrPush( vOnehotsPart, vGroupNew ); } else Vec_IntFree( vGroupNew ); } // clear the PI numbers Aig_ManForEachCi( pPart, pObj, i ) pObj->iData = 0; // print out if ( vOnehotsPart && fVerbose ) { printf( "Partition contains %d groups of 1-hot registers: { ", Vec_PtrSize(vOnehotsPart) ); Vec_PtrForEachEntry( Vec_Int_t *, vOnehotsPart, vGroup, k ) printf( "%d ", Vec_IntSize(vGroup) ); printf( "}\n" ); } return vOnehotsPart; } /**Function************************************************************* Synopsis [Computes partitioning of registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManRegCreatePart( Aig_Man_t * pAig, Vec_Int_t * vPart, int * pnCountPis, int * pnCountRegs, int ** ppMapBack ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjNew; Vec_Ptr_t * vNodes; Vec_Ptr_t * vRoots; int nOffset, iOut, i; int nCountPis, nCountRegs; int * pMapBack; // collect roots vRoots = Vec_PtrAlloc( Vec_IntSize(vPart) ); nOffset = Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig); Vec_IntForEachEntry( vPart, iOut, i ) { pObj = Aig_ManCo(pAig, nOffset+iOut); Vec_PtrPush( vRoots, Aig_ObjFanin0(pObj) ); } // collect/mark nodes/PIs in the DFS order vNodes = Aig_ManDfsNodes( pAig, (Aig_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) ); Vec_PtrFree( vRoots ); // unmark register outputs nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig); Vec_IntForEachEntry( vPart, iOut, i ) { pObj = Aig_ManCi(pAig, nOffset+iOut); Aig_ObjSetTravIdPrevious( pAig, pObj ); } // count pure PIs nCountPis = nCountRegs = 0; Aig_ManForEachPiSeq( pAig, pObj, i ) nCountPis += Aig_ObjIsTravIdCurrent(pAig, pObj); // count outputs of other registers Aig_ManForEachLoSeq( pAig, pObj, i ) nCountRegs += Aig_ObjIsTravIdCurrent(pAig, pObj); if ( pnCountPis ) *pnCountPis = nCountPis; if ( pnCountRegs ) *pnCountRegs = nCountRegs; // create the new manager pNew = Aig_ManStart( Vec_PtrSize(vNodes) ); Aig_ManConst1(pAig)->pData = Aig_ManConst1(pNew); // create the PIs Aig_ManForEachCi( pAig, pObj, i ) if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) pObj->pData = Aig_ObjCreateCi(pNew); // add variables for the register outputs // create fake POs to hold the register outputs nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig); Vec_IntForEachEntry( vPart, iOut, i ) { pObj = Aig_ManCi(pAig, nOffset+iOut); pObj->pData = Aig_ObjCreateCi(pNew); Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObj->pData ); Aig_ObjSetTravIdCurrent( pAig, pObj ); // added } // create the nodes Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) if ( Aig_ObjIsNode(pObj) ) pObj->pData = Aig_And(pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // add real POs for the registers nOffset = Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig); Vec_IntForEachEntry( vPart, iOut, i ) { pObj = Aig_ManCo( pAig, nOffset+iOut ); Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } pNew->nRegs = Vec_IntSize(vPart); // create map if ( ppMapBack ) { pMapBack = ABC_ALLOC( int, Aig_ManObjNumMax(pNew) ); memset( pMapBack, 0xff, sizeof(int) * Aig_ManObjNumMax(pNew) ); // map constant nodes pMapBack[0] = 0; // logic cones of register outputs Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { pObjNew = Aig_Regular((Aig_Obj_t *)pObj->pData); pMapBack[pObjNew->Id] = pObj->Id; } // map register outputs nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig); Vec_IntForEachEntry( vPart, iOut, i ) { pObj = Aig_ManCi(pAig, nOffset+iOut); pObjNew = (Aig_Obj_t *)pObj->pData; pMapBack[pObjNew->Id] = pObj->Id; } *ppMapBack = pMapBack; } Vec_PtrFree( vNodes ); return pNew; } /**Function************************************************************* Synopsis [Computes partitioning of registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManRegPartitionSmart( Aig_Man_t * pAig, int nPartSize ) { extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); Aig_ManPre_t * p; Vec_Ptr_t * vResult; int iSeed, iNext, i, k; // create the manager p = Aig_ManRegManStart( pAig, nPartSize ); // add partitions as long as registers remain for ( i = 0; (iSeed = Aig_ManRegFindSeed(p)) >= 0; i++ ) { //printf( "Seed variable = %d.\n", iSeed ); // clean the current partition information Vec_IntClear( p->vRegs ); Vec_IntClear( p->vUniques ); Vec_IntClear( p->vFreeVars ); Vec_FltClear( p->vPartCost ); memset( p->pfPartVars, 0, sizeof(char) * Aig_ManRegNum(p->pAig) ); // add the register and its partition support Aig_ManRegPartitionAdd( p, iSeed ); // select the best var to add for ( k = 0; Vec_IntSize(p->vRegs) < p->nRegsMax; k++ ) { // get the next best variable iNext = Aig_ManRegFindBestVar( p ); if ( iNext == -1 ) break; // add the register to the support of the partition Aig_ManRegPartitionAdd( p, iNext ); // report the result //printf( "Part %3d Reg %3d : Free = %4d. Total = %4d. Ratio = %6.2f. Unique = %4d.\n", i, k, // Vec_IntSize(p->vFreeVars), Vec_IntSize(p->vRegs), // 1.0*Vec_IntSize(p->vFreeVars)/Vec_IntSize(p->vRegs), Vec_IntSize(p->vUniques) ); // quit if there are not free variables if ( Vec_IntSize(p->vFreeVars) == 0 ) break; } // add this partition to the set Vec_PtrPush( p->vParts, Vec_IntDup(p->vRegs) ); printf( "Part %3d SUMMARY: Free = %4d. Total = %4d. Ratio = %6.2f. Unique = %4d.\n", i, Vec_IntSize(p->vFreeVars), Vec_IntSize(p->vRegs), 1.0*Vec_IntSize(p->vFreeVars)/Vec_IntSize(p->vRegs), Vec_IntSize(p->vUniques) ); //printf( "\n" ); } vResult = p->vParts; p->vParts = NULL; Aig_ManRegManStop( p ); return vResult; } /**Function************************************************************* Synopsis [Computes partitioning of registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManRegPartitionSimple( Aig_Man_t * pAig, int nPartSize, int nOverSize ) { Vec_Ptr_t * vResult; Vec_Int_t * vPart; int i, Counter; if ( nOverSize >= nPartSize ) { printf( "Overlap size (%d) is more or equal than the partition size (%d).\n", nOverSize, nPartSize ); printf( "Adjusting it to be equal to half of the partition size.\n" ); nOverSize = nPartSize/2; } assert( nOverSize < nPartSize ); vResult = Vec_PtrAlloc( 100 ); for ( Counter = 0; Counter < Aig_ManRegNum(pAig); Counter -= nOverSize ) { vPart = Vec_IntAlloc( nPartSize ); for ( i = 0; i < nPartSize; i++, Counter++ ) if ( Counter < Aig_ManRegNum(pAig) ) Vec_IntPush( vPart, Counter ); if ( Vec_IntSize(vPart) <= nOverSize ) Vec_IntFree(vPart); else Vec_PtrPush( vResult, vPart ); } return vResult; } /**Function************************************************************* Synopsis [Divides a large partition into several ones.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPartDivide( Vec_Ptr_t * vResult, Vec_Int_t * vDomain, int nPartSize, int nOverSize ) { Vec_Int_t * vPart; int i, Counter; assert( nPartSize && Vec_IntSize(vDomain) > nPartSize ); if ( nOverSize >= nPartSize ) { printf( "Overlap size (%d) is more or equal than the partition size (%d).\n", nOverSize, nPartSize ); printf( "Adjusting it to be equal to half of the partition size.\n" ); nOverSize = nPartSize/2; } assert( nOverSize < nPartSize ); for ( Counter = 0; Counter < Vec_IntSize(vDomain); Counter -= nOverSize ) { vPart = Vec_IntAlloc( nPartSize ); for ( i = 0; i < nPartSize; i++, Counter++ ) if ( Counter < Vec_IntSize(vDomain) ) Vec_IntPush( vPart, Vec_IntEntry(vDomain, Counter) ); if ( Vec_IntSize(vPart) <= nOverSize ) Vec_IntFree(vPart); else Vec_PtrPush( vResult, vPart ); } } /**Function************************************************************* Synopsis [Computes partitioning of registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManRegPartitionTraverse_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vLos ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent( p, pObj ); if ( Aig_ObjIsCi(pObj) ) { if ( pObj->iData >= Aig_ManCiNum(p) - Aig_ManRegNum(p) ) { Vec_PtrPush( vLos, pObj ); printf( "%d ", pObj->iData - (Aig_ManCiNum(p) - Aig_ManRegNum(p)) ); } return; } Aig_ManRegPartitionTraverse_rec( p, Aig_ObjFanin0(pObj), vLos ); Aig_ManRegPartitionTraverse_rec( p, Aig_ObjFanin1(pObj), vLos ); } /**Function************************************************************* Synopsis [Computes partitioning of registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManRegPartitionTraverse( Aig_Man_t * p ) { Vec_Ptr_t * vLos; Aig_Obj_t * pObj; int i, nPrev, Counter; // mark the registers Aig_ManForEachCi( p, pObj, i ) pObj->iData = i; // collect registers vLos = Vec_PtrAlloc( Aig_ManRegNum(p) ); nPrev = 0; Counter = 0; Aig_ManIncrementTravId( p ); Aig_ManForEachLiSeq( p, pObj, i ) { ++Counter; printf( "Latch %d: ", Counter ); Aig_ManRegPartitionTraverse_rec( p, Aig_ObjFanin0(pObj), vLos ); printf( "%d=%d \n", Counter, Vec_PtrSize(vLos)-nPrev ); nPrev = Vec_PtrSize(vLos); } printf( "Total collected = %d. Total regs = %d.\n", Vec_PtrSize(vLos), Aig_ManRegNum(p) ); return vLos; } /**Function************************************************************* Synopsis [Computes partitioning of registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManRegPartitionLinear( Aig_Man_t * pAig, int nPartSize ) { Vec_Ptr_t * vLos; vLos = Aig_ManRegPartitionTraverse( pAig ); Vec_PtrFree( vLos ); return NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigPartSat.c000066400000000000000000000501071477524141600164750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigPartSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Partitioning for SAT solving.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigPartSat.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" #include "sat/bsat/satSolver.h" #include "sat/cnf/cnf.h" ABC_NAMESPACE_IMPL_START /* The node partitioners defined in this file return array of intergers mapping each AND node's ID into the 0-based number of its partition. The mapping of PIs/POs will be derived automatically in Aig_ManPartSplit(). The partitions can be ordered in any way, but the recommended ordering is to first include partitions whose nodes are closer to the outputs. */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [No partitioning.] Description [The partitioner ] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Aig_ManPartitionMonolithic( Aig_Man_t * p ) { Vec_Int_t * vId2Part; vId2Part = Vec_IntStart( Aig_ManObjNumMax(p) ); return vId2Part; } /**Function************************************************************* Synopsis [Partitioning using levelized order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Aig_ManPartitionLevelized( Aig_Man_t * p, int nPartSize ) { Vec_Int_t * vId2Part; Vec_Vec_t * vNodes; Aig_Obj_t * pObj; int i, k, Counter = 0; vNodes = Aig_ManLevelize( p ); vId2Part = Vec_IntStart( Aig_ManObjNumMax(p) ); Vec_VecForEachEntryReverseReverse( Aig_Obj_t *, vNodes, pObj, i, k ) Vec_IntWriteEntry( vId2Part, Aig_ObjId(pObj), Counter++/nPartSize ); Vec_VecFree( vNodes ); return vId2Part; } /**Function************************************************************* Synopsis [Partitioning using DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Aig_ManPartitionDfs( Aig_Man_t * p, int nPartSize, int fPreorder ) { Vec_Int_t * vId2Part; Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i, Counter = 0; vId2Part = Vec_IntStart( Aig_ManObjNumMax(p) ); if ( fPreorder ) { vNodes = Aig_ManDfsPreorder( p, 1 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) Vec_IntWriteEntry( vId2Part, Aig_ObjId(pObj), Counter++/nPartSize ); } else { vNodes = Aig_ManDfs( p, 1 ); Vec_PtrForEachEntryReverse( Aig_Obj_t *, vNodes, pObj, i ) Vec_IntWriteEntry( vId2Part, Aig_ObjId(pObj), Counter++/nPartSize ); } Vec_PtrFree( vNodes ); return vId2Part; } /**Function************************************************************* Synopsis [Recursively constructs the partition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPartSplitOne_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vPio2Id ) { if ( !Aig_ObjIsTravIdCurrent( p, pObj ) ) { // new PI Aig_ObjSetTravIdCurrent( p, pObj ); /* if ( pObj->fMarkA ) // const0 pObj->pData = Aig_ManConst0( pNew ); else if ( pObj->fMarkB ) // const1 pObj->pData = Aig_ManConst1( pNew ); else */ { pObj->pData = Aig_ObjCreateCi( pNew ); if ( pObj->fMarkA ) // const0 ((Aig_Obj_t *)pObj->pData)->fMarkA = 1; else if ( pObj->fMarkB ) // const1 ((Aig_Obj_t *)pObj->pData)->fMarkB = 1; Vec_IntPush( vPio2Id, Aig_ObjId(pObj) ); } return; } if ( pObj->pData ) return; Aig_ManPartSplitOne_rec( pNew, p, Aig_ObjFanin0(pObj), vPio2Id ); Aig_ManPartSplitOne_rec( pNew, p, Aig_ObjFanin1(pObj), vPio2Id ); pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } /**Function************************************************************* Synopsis [Carves out one partition of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManPartSplitOne( Aig_Man_t * p, Vec_Ptr_t * vNodes, Vec_Int_t ** pvPio2Id ) { Vec_Int_t * vPio2Id; Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; // mark these nodes Aig_ManIncrementTravId( p ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { Aig_ObjSetTravIdCurrent( p, pObj ); pObj->pData = NULL; } // add these nodes in a DFS order pNew = Aig_ManStart( Vec_PtrSize(vNodes) ); vPio2Id = Vec_IntAlloc( 100 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) Aig_ManPartSplitOne_rec( pNew, p, pObj, vPio2Id ); // add the POs Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) if ( Aig_ObjRefs((Aig_Obj_t *)pObj->pData) != Aig_ObjRefs(pObj) ) { assert( Aig_ObjRefs((Aig_Obj_t *)pObj->pData) < Aig_ObjRefs(pObj) ); Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObj->pData ); Vec_IntPush( vPio2Id, Aig_ObjId(pObj) ); } assert( Aig_ManNodeNum(pNew) == Vec_PtrSize(vNodes) ); *pvPio2Id = vPio2Id; return pNew; } /**Function************************************************************* Synopsis [Derives AIGs for each partition.] Description [The first argument is a original AIG. The second argument is the array mapping each AND-node's ID into the 0-based number of its partition. The last argument is the array of arrays (one for each new AIG) mapping the index of each terminal in the new AIG (the index of each terminal is derived by ordering PIs followed by POs in their natural order) into the ID of the corresponding node in the original AIG. The returned value is the array of AIGs representing the partitions.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManPartSplit( Aig_Man_t * p, Vec_Int_t * vNode2Part, Vec_Ptr_t ** pvPio2Id, Vec_Ptr_t ** pvPart2Pos ) { Vec_Vec_t * vGroups, * vPart2Pos; Vec_Ptr_t * vAigs, * vPio2Id, * vNodes; Vec_Int_t * vPio2IdOne; Aig_Man_t * pAig; Aig_Obj_t * pObj, * pDriver; int i, nodePart, nParts; vAigs = Vec_PtrAlloc( 100 ); vPio2Id = Vec_PtrAlloc( 100 ); // put all nodes into levels according to their partition nParts = Vec_IntFindMax(vNode2Part) + 1; assert( nParts > 0 ); vGroups = Vec_VecAlloc( nParts ); Vec_IntForEachEntry( vNode2Part, nodePart, i ) { pObj = Aig_ManObj( p, i ); if ( Aig_ObjIsNode(pObj) ) Vec_VecPush( vGroups, nodePart, pObj ); } // label PIs that should be restricted to some values Aig_ManForEachCo( p, pObj, i ) { pDriver = Aig_ObjFanin0(pObj); if ( Aig_ObjIsCi(pDriver) ) { if ( Aig_ObjFaninC0(pObj) ) pDriver->fMarkA = 1; // const0 PI else pDriver->fMarkB = 1; // const1 PI } } // create partitions Vec_VecForEachLevel( vGroups, vNodes, i ) { if ( Vec_PtrSize(vNodes) == 0 ) { printf( "Aig_ManPartSplit(): Skipping partition # %d without nodes (warning).\n", i ); continue; } pAig = Aig_ManPartSplitOne( p, vNodes, &vPio2IdOne ); Vec_PtrPush( vPio2Id, vPio2IdOne ); Vec_PtrPush( vAigs, pAig ); } Vec_VecFree( vGroups ); // divide POs according to their partitions vPart2Pos = Vec_VecStart( Vec_PtrSize(vAigs) ); Aig_ManForEachCo( p, pObj, i ) { pDriver = Aig_ObjFanin0(pObj); if ( Aig_ObjIsCi(pDriver) ) pDriver->fMarkA = pDriver->fMarkB = 0; else Vec_VecPush( vPart2Pos, Vec_IntEntry(vNode2Part, Aig_ObjFaninId0(pObj)), pObj ); } *pvPio2Id = vPio2Id; *pvPart2Pos = (Vec_Ptr_t *)vPart2Pos; return vAigs; } /**Function************************************************************* Synopsis [Resets node polarity to unbias the polarity of CNF variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPartResetNodePolarity( Aig_Man_t * pPart ) { Aig_Obj_t * pObj; int i; Aig_ManForEachObj( pPart, pObj, i ) pObj->fPhase = 0; } /**Function************************************************************* Synopsis [Sets polarity according to the original nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPartSetNodePolarity( Aig_Man_t * p, Aig_Man_t * pPart, Vec_Int_t * vPio2Id ) { Aig_Obj_t * pObj, * pObjInit; int i; Aig_ManConst1(pPart)->fPhase = 1; Aig_ManForEachCi( pPart, pObj, i ) { pObjInit = Aig_ManObj( p, Vec_IntEntry(vPio2Id, i) ); pObj->fPhase = pObjInit->fPhase; } Aig_ManForEachNode( pPart, pObj, i ) pObj->fPhase = (Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj)) & (Aig_ObjFanin1(pObj)->fPhase ^ Aig_ObjFaninC1(pObj)); Aig_ManForEachCo( pPart, pObj, i ) { pObjInit = Aig_ManObj( p, Vec_IntEntry(vPio2Id, Aig_ManCiNum(pPart) + i) ); pObj->fPhase = (Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj)); assert( pObj->fPhase == pObjInit->fPhase ); } } /**Function************************************************************* Synopsis [Sets polarity according to the original nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManDeriveCounterExample( Aig_Man_t * p, Vec_Int_t * vNode2Var, sat_solver * pSat ) { Vec_Int_t * vPisIds; Aig_Obj_t * pObj; int i; // collect IDs of PI variables // (fanoutless PIs have SAT var 0, which is an unused in the SAT solver -> has value 0) vPisIds = Vec_IntAlloc( Aig_ManCiNum(p) ); Aig_ManForEachCi( p, pObj, i ) Vec_IntPush( vPisIds, Vec_IntEntry(vNode2Var, Aig_ObjId(pObj)) ); // derive the SAT assignment p->pData = Sat_SolverGetModel( pSat, vPisIds->pArray, vPisIds->nSize ); Vec_IntFree( vPisIds ); } /**Function************************************************************* Synopsis [Derives CNF for the partition (pAig) and adds it to solver.] Description [Array vPio2Id contains mapping of the PI/PO terminal of pAig into the IDs of the corresponding original nodes. Array vNode2Var contains mapping of the original nodes into their SAT variable numbers.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManAddNewCnfToSolver( sat_solver * pSat, Aig_Man_t * pAig, Vec_Int_t * vNode2Var, Vec_Int_t * vPioIds, Vec_Ptr_t * vPartPos, int fAlignPol ) { Cnf_Dat_t * pCnf; Aig_Obj_t * pObj; int * pBeg, * pEnd; int i, Lits[2], iSatVarOld, iNodeIdOld; // derive CNF and express it using new SAT variables pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); Cnf_DataTranformPolarity( pCnf, 1 ); Cnf_DataLift( pCnf, sat_solver_nvars(pSat) ); // create new variables in the SAT solver sat_solver_setnvars( pSat, sat_solver_nvars(pSat) + pCnf->nVars ); // add clauses for this CNF Cnf_CnfForClause( pCnf, pBeg, pEnd, i ) if ( !sat_solver_addclause( pSat, pBeg, pEnd ) ) { assert( 0 ); // if it happens, can return 1 (unsatisfiable) return 1; } // derive the connector clauses Aig_ManForEachCi( pAig, pObj, i ) { iNodeIdOld = Vec_IntEntry( vPioIds, i ); iSatVarOld = Vec_IntEntry( vNode2Var, iNodeIdOld ); if ( iSatVarOld == 0 ) // iNodeIdOld in the original AIG has no SAT var { // map the corresponding original AIG node into this SAT var Vec_IntWriteEntry( vNode2Var, iNodeIdOld, pCnf->pVarNums[Aig_ObjId(pObj)] ); continue; } // add connector clauses Lits[0] = toLitCond( iSatVarOld, 0 ); Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); Lits[0] = toLitCond( iSatVarOld, 1 ); Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); } // derive the connector clauses Aig_ManForEachCo( pAig, pObj, i ) { iNodeIdOld = Vec_IntEntry( vPioIds, Aig_ManCiNum(pAig) + i ); iSatVarOld = Vec_IntEntry( vNode2Var, iNodeIdOld ); if ( iSatVarOld == 0 ) // iNodeIdOld in the original AIG has no SAT var { // map the corresponding original AIG node into this SAT var Vec_IntWriteEntry( vNode2Var, iNodeIdOld, pCnf->pVarNums[Aig_ObjId(pObj)] ); continue; } // add connector clauses Lits[0] = toLitCond( iSatVarOld, 0 ); Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); Lits[0] = toLitCond( iSatVarOld, 1 ); Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); } // transfer the ID of constant 1 node if ( Vec_IntEntry( vNode2Var, 0 ) == 0 ) Vec_IntWriteEntry( vNode2Var, 0, pCnf->pVarNums[0] ); // remove the CNF Cnf_DataFree( pCnf ); // constrain the solver with the literals corresponding to the original POs Vec_PtrForEachEntry( Aig_Obj_t *, vPartPos, pObj, i ) { iNodeIdOld = Aig_ObjFaninId0( pObj ); iSatVarOld = Vec_IntEntry( vNode2Var, iNodeIdOld ); assert( iSatVarOld != 0 ); // assert the original PO to be 1 Lits[0] = toLitCond( iSatVarOld, Aig_ObjFaninC0(pObj) ); // correct the polarity if polarity alignment is enabled if ( fAlignPol && Aig_ObjFanin0(pObj)->fPhase ) Lits[0] = lit_neg( Lits[0] ); if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) ) { assert( 0 ); // if it happens, can return 1 (unsatisfiable) return 1; } } // constrain some the primary inputs to constant values Aig_ManForEachCi( pAig, pObj, i ) { if ( !pObj->fMarkA && !pObj->fMarkB ) continue; iNodeIdOld = Vec_IntEntry( vPioIds, i ); iSatVarOld = Vec_IntEntry( vNode2Var, iNodeIdOld ); Lits[0] = toLitCond( iSatVarOld, pObj->fMarkA ); if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) ) { assert( 0 ); // if it happens, can return 1 (unsatisfiable) return 1; } pObj->fMarkA = pObj->fMarkB = 0; } return 0; } /**Function************************************************************* Synopsis [Performs partitioned SAT solving.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManPartitionedSat( Aig_Man_t * p, int nAlgo, int nPartSize, int nConfPart, int nConfTotal, int fAlignPol, int fSynthesize, int fVerbose ) { sat_solver * pSat; Vec_Ptr_t * vAigs; Vec_Vec_t * vPio2Id, * vPart2Pos; Aig_Man_t * pAig, * pTemp; Vec_Int_t * vNode2Part, * vNode2Var; int nConfRemaining = nConfTotal, nNodes = 0; int i, status, RetValue = -1; abctime clk; // perform partitioning according to the selected algorithm clk = Abc_Clock(); switch ( nAlgo ) { case 0: vNode2Part = Aig_ManPartitionMonolithic( p ); break; case 1: vNode2Part = Aig_ManPartitionLevelized( p, nPartSize ); break; case 2: vNode2Part = Aig_ManPartitionDfs( p, nPartSize, 0 ); break; case 3: vNode2Part = Aig_ManPartitionDfs( p, nPartSize, 1 ); break; default: printf( "Unknown partitioning algorithm.\n" ); return -1; } if ( fVerbose ) { printf( "Partitioning derived %d partitions. ", Vec_IntFindMax(vNode2Part) + 1 ); ABC_PRT( "Time", Abc_Clock() - clk ); } // split the original AIG into partition AIGs (vAigs) // also, derives mapping of PIs/POs of partition AIGs into original nodes // also, derives mapping of POs of the original AIG into partitions vAigs = Aig_ManPartSplit( p, vNode2Part, (Vec_Ptr_t **)&vPio2Id, (Vec_Ptr_t **)&vPart2Pos ); Vec_IntFree( vNode2Part ); if ( fVerbose ) { printf( "Partions were transformed into AIGs. " ); ABC_PRT( "Time", Abc_Clock() - clk ); } // synthesize partitions if ( fSynthesize ) Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, i ) { pAig = Dar_ManRwsat( pTemp = pAig, 0, 0 ); Vec_PtrWriteEntry( vAigs, i, pAig ); Aig_ManStop( pTemp ); } // start the SAT solver pSat = sat_solver_new(); // pSat->verbosity = fVerbose; // start mapping of the original AIG IDs into their SAT variable numbers vNode2Var = Vec_IntStart( Aig_ManObjNumMax(p) ); // add partitions, one at a time, and run the SAT solver Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, i ) { clk = Abc_Clock(); // transform polarity of the AIG if ( fAlignPol ) Aig_ManPartSetNodePolarity( p, pAig, Vec_VecEntryInt(vPio2Id,i) ); else Aig_ManPartResetNodePolarity( pAig ); // add CNF of this partition to the SAT solver if ( Aig_ManAddNewCnfToSolver( pSat, pAig, vNode2Var, Vec_VecEntryInt(vPio2Id,i), Vec_VecEntry(vPart2Pos,i), fAlignPol ) ) { RetValue = 1; break; } // call the SAT solver status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfRemaining, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( fVerbose ) { printf( "%4d : Aig = %6d. Vs = %7d. RootCs = %7d. LearnCs = %6d. ", i, nNodes += Aig_ManNodeNum(pAig), sat_solver_nvars(pSat), (int)pSat->stats.clauses, (int)pSat->stats.learnts ); ABC_PRT( "Time", Abc_Clock() - clk ); } // analize the result if ( status == l_False ) { RetValue = 1; break; } else if ( status == l_True ) RetValue = 0; else RetValue = -1; nConfRemaining -= pSat->stats.conflicts; if ( nConfRemaining <= 0 ) { printf( "Exceeded the limit on the total number of conflicts (%d).\n", nConfTotal ); break; } } if ( RetValue == 0 ) Aig_ManDeriveCounterExample( p, vNode2Var, pSat ); // cleanup sat_solver_delete( pSat ); Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i ) Aig_ManStop( pTemp ); Vec_PtrFree( vAigs ); Vec_VecFree( vPio2Id ); Vec_VecFree( vPart2Pos ); Vec_IntFree( vNode2Var ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigRepar.c000066400000000000000000000316021477524141600161670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigRepar.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Interpolation-based reparametrization.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigRepar.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver2.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Adds buffer to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Aig_ManInterAddBuffer( sat_solver2 * pSat, int iVarA, int iVarB, int fCompl, int fMark ) { lit Lits[2]; int Cid; assert( iVarA >= 0 && iVarB >= 0 ); Lits[0] = toLitCond( iVarA, 0 ); Lits[1] = toLitCond( iVarB, !fCompl ); Cid = sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ); if ( fMark ) clause2_set_partA( pSat, Cid, 1 ); Lits[0] = toLitCond( iVarA, 1 ); Lits[1] = toLitCond( iVarB, fCompl ); Cid = sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ); if ( fMark ) clause2_set_partA( pSat, Cid, 1 ); } /**Function************************************************************* Synopsis [Adds constraints for the two-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Aig_ManInterAddXor( sat_solver2 * pSat, int iVarA, int iVarB, int iVarC, int fCompl, int fMark ) { lit Lits[3]; int Cid; assert( iVarA >= 0 && iVarB >= 0 && iVarC >= 0 ); Lits[0] = toLitCond( iVarA, !fCompl ); Lits[1] = toLitCond( iVarB, 1 ); Lits[2] = toLitCond( iVarC, 1 ); Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 ); if ( fMark ) clause2_set_partA( pSat, Cid, 1 ); Lits[0] = toLitCond( iVarA, !fCompl ); Lits[1] = toLitCond( iVarB, 0 ); Lits[2] = toLitCond( iVarC, 0 ); Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 ); if ( fMark ) clause2_set_partA( pSat, Cid, 1 ); Lits[0] = toLitCond( iVarA, fCompl ); Lits[1] = toLitCond( iVarB, 1 ); Lits[2] = toLitCond( iVarC, 0 ); Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 ); if ( fMark ) clause2_set_partA( pSat, Cid, 1 ); Lits[0] = toLitCond( iVarA, fCompl ); Lits[1] = toLitCond( iVarB, 0 ); Lits[2] = toLitCond( iVarC, 1 ); Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 ); if ( fMark ) clause2_set_partA( pSat, Cid, 1 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManInterTest( Aig_Man_t * pMan, int fVerbose ) { sat_solver2 * pSat; // Aig_Man_t * pInter; word * pInter; Vec_Int_t * vVars; Cnf_Dat_t * pCnf; Aig_Obj_t * pObj; int Lit, Cid, Var, status, i; clock_t clk = clock(); assert( Aig_ManRegNum(pMan) == 0 ); assert( Aig_ManCoNum(pMan) == 1 ); // derive CNFs pCnf = Cnf_Derive( pMan, 1 ); // start the solver pSat = sat_solver2_new(); sat_solver2_setnvars( pSat, 2*pCnf->nVars+1 ); // set A-variables (all used except PI/PO) Aig_ManForEachObj( pMan, pObj, i ) { if ( pCnf->pVarNums[pObj->Id] < 0 ) continue; if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsCo(pObj) ) var_set_partA( pSat, pCnf->pVarNums[pObj->Id], 1 ); } // add clauses of A for ( i = 0; i < pCnf->nClauses; i++ ) { Cid = sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 ); clause2_set_partA( pSat, Cid, 1 ); } // add clauses of B Cnf_DataLift( pCnf, pCnf->nVars ); for ( i = 0; i < pCnf->nClauses; i++ ) sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 ); Cnf_DataLift( pCnf, -pCnf->nVars ); // add PI equality clauses vVars = Vec_IntAlloc( Aig_ManCoNum(pMan)+1 ); Aig_ManForEachCi( pMan, pObj, i ) { if ( Aig_ObjRefs(pObj) == 0 ) continue; Var = pCnf->pVarNums[pObj->Id]; Aig_ManInterAddBuffer( pSat, Var, pCnf->nVars + Var, 0, 0 ); Vec_IntPush( vVars, Var ); } // add an XOR clause in the end Var = pCnf->pVarNums[Aig_ManCo(pMan,0)->Id]; Aig_ManInterAddXor( pSat, Var, pCnf->nVars + Var, 2*pCnf->nVars, 0, 0 ); Vec_IntPush( vVars, Var ); // solve the problem Lit = toLitCond( 2*pCnf->nVars, 0 ); status = sat_solver2_solve( pSat, &Lit, &Lit + 1, 0, 0, 0, 0 ); assert( status == l_False ); Sat_Solver2PrintStats( stdout, pSat ); // derive interpolant // pInter = Sat_ProofInterpolant( pSat, vVars ); // Aig_ManPrintStats( pInter ); // Aig_ManDumpBlif( pInter, "int.blif", NULL, NULL ); //pInter = Sat_ProofInterpolantTruth( pSat, vVars ); pInter = NULL; // Extra_PrintHex( stdout, pInter, Vec_IntSize(vVars) ); printf( "\n" ); // clean up // Aig_ManStop( pInter ); ABC_FREE( pInter ); Vec_IntFree( vVars ); Cnf_DataFree( pCnf ); sat_solver2_delete( pSat ); ABC_PRT( "Total interpolation time", clock() - clk ); } /**Function************************************************************* Synopsis [Duplicates AIG while mapping PIs into the given array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManAppend( Aig_Man_t * pBase, Aig_Man_t * pNew ) { Aig_Obj_t * pObj; int i; assert( Aig_ManCoNum(pNew) == 1 ); assert( Aig_ManCiNum(pNew) == Aig_ManCiNum(pBase) ); // create the PIs Aig_ManCleanData( pNew ); Aig_ManConst1(pNew)->pData = Aig_ManConst1(pBase); Aig_ManForEachCi( pNew, pObj, i ) pObj->pData = Aig_IthVar(pBase, i); // duplicate internal nodes Aig_ManForEachNode( pNew, pObj, i ) pObj->pData = Aig_And( pBase, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // add one PO to base pObj = Aig_ManCo( pNew, 0 ); Aig_ObjCreateCo( pBase, Aig_ObjChild0Copy(pObj) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManInterRepar( Aig_Man_t * pMan, int fVerbose ) { Aig_Man_t * pAigTemp, * pInter, * pBase = NULL; sat_solver2 * pSat; Vec_Int_t * vVars; Cnf_Dat_t * pCnf, * pCnfInter; Aig_Obj_t * pObj; int nOuts = Aig_ManCoNum(pMan); int ShiftP[2], ShiftCnf[2], ShiftOr[2], ShiftAssume; int Cid, Lit, status, i, k, c; clock_t clk = clock(); assert( Aig_ManRegNum(pMan) == 0 ); // derive CNFs pCnf = Cnf_Derive( pMan, nOuts ); // start the solver pSat = sat_solver2_new(); sat_solver2_setnvars( pSat, 4*pCnf->nVars + 6*nOuts ); // vars: pGlobal + (p0 + A1 + A2 + or0) + (p1 + B1 + B2 + or1) + pAssume; ShiftP[0] = nOuts; ShiftP[1] = 2*pCnf->nVars + 3*nOuts; ShiftCnf[0] = ShiftP[0] + nOuts; ShiftCnf[1] = ShiftP[1] + nOuts; ShiftOr[0] = ShiftCnf[0] + 2*pCnf->nVars; ShiftOr[1] = ShiftCnf[1] + 2*pCnf->nVars; ShiftAssume = ShiftOr[1] + nOuts; assert( ShiftAssume + nOuts == pSat->size ); // mark variables of A for ( i = ShiftCnf[0]; i < ShiftP[1]; i++ ) var_set_partA( pSat, i, 1 ); // add clauses of A, then B vVars = Vec_IntAlloc( 2*nOuts ); for ( k = 0; k < 2; k++ ) { // copy A1 Cnf_DataLift( pCnf, ShiftCnf[k] ); for ( i = 0; i < pCnf->nClauses; i++ ) { Cid = sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 ); clause2_set_partA( pSat, Cid, k==0 ); } // add equality p[k] == A1/B1 Aig_ManForEachCo( pMan, pObj, i ) Aig_ManInterAddBuffer( pSat, ShiftP[k] + i, pCnf->pVarNums[pObj->Id], k==1, k==0 ); // copy A2 Cnf_DataLift( pCnf, pCnf->nVars ); for ( i = 0; i < pCnf->nClauses; i++ ) { Cid = sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 ); clause2_set_partA( pSat, Cid, k==0 ); } // add comparator (!p[k] ^ A2/B2) == or[k] Vec_IntClear( vVars ); Aig_ManForEachCo( pMan, pObj, i ) { Aig_ManInterAddXor( pSat, ShiftP[k] + i, pCnf->pVarNums[pObj->Id], ShiftOr[k] + i, k==1, k==0 ); Vec_IntPush( vVars, toLitCond(ShiftOr[k] + i, 1) ); } Cid = sat_solver2_addclause( pSat, Vec_IntArray(vVars), Vec_IntArray(vVars) + Vec_IntSize(vVars), 0 ); clause2_set_partA( pSat, Cid, k==0 ); // return to normal Cnf_DataLift( pCnf, -ShiftCnf[k]-pCnf->nVars ); } // add clauses to constrain p[0] and p[1] for ( k = 0; k < nOuts; k++ ) Aig_ManInterAddXor( pSat, ShiftP[0] + k, ShiftP[1] + k, ShiftAssume + k, 0, 0 ); // start the interpolant pBase = Aig_ManStart( 1000 ); pBase->pName = Abc_UtilStrsav( "repar" ); for ( k = 0; k < 2*nOuts; k++ ) Aig_IthVar(pBase, i); // start global variables (pGlobal and p[0]) Vec_IntClear( vVars ); for ( k = 0; k < 2*nOuts; k++ ) Vec_IntPush( vVars, k ); // perform iterative solving // vars: pGlobal + (p0 + A1 + A2 + or0) + (p1 + B1 + B2 + or1) + pAssume; for ( k = 0; k < nOuts; k++ ) { // swap k-th variables int Temp = Vec_IntEntry( vVars, k ); Vec_IntWriteEntry( vVars, k, Vec_IntEntry(vVars, nOuts+k) ); Vec_IntWriteEntry( vVars, nOuts+k, Temp ); // solve incrementally Lit = toLitCond( ShiftAssume + k, 1 ); // XOR output is 0 ==> p1 == p2 status = sat_solver2_solve( pSat, &Lit, &Lit + 1, 0, 0, 0, 0 ); assert( status == l_False ); Sat_Solver2PrintStats( stdout, pSat ); // derive interpolant pInter = (Aig_Man_t *)Sat_ProofInterpolant( pSat, vVars ); Aig_ManPrintStats( pInter ); // make sure interpolant does not depend on useless vars Aig_ManForEachCi( pInter, pObj, i ) assert( i <= k || Aig_ObjRefs(pObj) == 0 ); // simplify pInter = Dar_ManRwsat( pAigTemp = pInter, 1, 0 ); Aig_ManStop( pAigTemp ); // add interpolant to the solver pCnfInter = Cnf_Derive( pInter, 1 ); Cnf_DataLift( pCnfInter, pSat->size ); sat_solver2_setnvars( pSat, pSat->size + 2*pCnfInter->nVars ); for ( i = 0; i < pCnfInter->nVars; i++ ) var_set_partA( pSat, pSat->size-2*pCnfInter->nVars + i, 1 ); for ( c = 0; c < 2; c++ ) { if ( c == 1 ) Cnf_DataLift( pCnfInter, pCnfInter->nVars ); // add to A for ( i = 0; i < pCnfInter->nClauses; i++ ) { Cid = sat_solver2_addclause( pSat, pCnfInter->pClauses[i], pCnfInter->pClauses[i+1], 0 ); clause2_set_partA( pSat, Cid, c==0 ); } // connect to the inputs Aig_ManForEachCi( pInter, pObj, i ) if ( i <= k ) Aig_ManInterAddBuffer( pSat, i, pCnf->pVarNums[pObj->Id], 0, c==0 ); // connect to the outputs pObj = Aig_ManCo(pInter, 0); Aig_ManInterAddBuffer( pSat, ShiftP[c] + k, pCnf->pVarNums[pObj->Id], 0, c==0 ); if ( c == 1 ) Cnf_DataLift( pCnfInter, -pCnfInter->nVars ); } Cnf_DataFree( pCnfInter ); // accumulate Aig_ManAppend( pBase, pInter ); Aig_ManStop( pInter ); // update global variables Temp = Vec_IntEntry( vVars, k ); Vec_IntWriteEntry( vVars, k, Vec_IntEntry(vVars, nOuts+k) ); Vec_IntWriteEntry( vVars, nOuts+k, Temp ); } Vec_IntFree( vVars ); Cnf_DataFree( pCnf ); sat_solver2_delete( pSat ); ABC_PRT( "Reparameterization time", clock() - clk ); return pBase; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigRepr.c000066400000000000000000000401621477524141600160270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigRepr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Handing node representatives.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigRepr.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the array of representatives.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManReprStart( Aig_Man_t * p, int nIdMax ) { assert( Aig_ManBufNum(p) == 0 ); assert( p->pReprs == NULL ); p->nReprsAlloc = nIdMax; p->pReprs = ABC_ALLOC( Aig_Obj_t *, p->nReprsAlloc ); memset( p->pReprs, 0, sizeof(Aig_Obj_t *) * p->nReprsAlloc ); } /**Function************************************************************* Synopsis [Stop the array of representatives.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManReprStop( Aig_Man_t * p ) { assert( p->pReprs != NULL ); ABC_FREE( p->pReprs ); p->nReprsAlloc = 0; } /**Function************************************************************* Synopsis [Set the representative.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjCreateRepr( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ) { assert( p->pReprs != NULL ); assert( !Aig_IsComplement(pNode1) ); assert( !Aig_IsComplement(pNode2) ); assert( pNode1->Id < p->nReprsAlloc ); assert( pNode2->Id < p->nReprsAlloc ); assert( pNode1->Id < pNode2->Id ); p->pReprs[pNode2->Id] = pNode1; } /**Function************************************************************* Synopsis [Set the representative.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Aig_ObjSetRepr_( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ) { assert( p->pReprs != NULL ); assert( !Aig_IsComplement(pNode1) ); assert( !Aig_IsComplement(pNode2) ); assert( pNode1->Id < p->nReprsAlloc ); assert( pNode2->Id < p->nReprsAlloc ); if ( pNode1 == pNode2 ) return; if ( pNode1->Id < pNode2->Id ) p->pReprs[pNode2->Id] = pNode1; else p->pReprs[pNode1->Id] = pNode2; } /**Function************************************************************* Synopsis [Find representative.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Aig_Obj_t * Aig_ObjFindRepr( Aig_Man_t * p, Aig_Obj_t * pNode ) { assert( p->pReprs != NULL ); assert( !Aig_IsComplement(pNode) ); assert( pNode->Id < p->nReprsAlloc ); // assert( !p->pReprs[pNode->Id] || p->pReprs[pNode->Id]->Id < pNode->Id ); return p->pReprs[pNode->Id]; } /**Function************************************************************* Synopsis [Clears the representative.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Aig_ObjClearRepr( Aig_Man_t * p, Aig_Obj_t * pNode ) { assert( p->pReprs != NULL ); assert( !Aig_IsComplement(pNode) ); assert( pNode->Id < p->nReprsAlloc ); p->pReprs[pNode->Id] = NULL; } /**Function************************************************************* Synopsis [Find representative transitively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Aig_Obj_t * Aig_ObjFindReprTransitive( Aig_Man_t * p, Aig_Obj_t * pNode ) { Aig_Obj_t * pNext, * pRepr; if ( (pRepr = Aig_ObjFindRepr(p, pNode)) ) while ( (pNext = Aig_ObjFindRepr(p, pRepr)) ) pRepr = pNext; return pRepr; } /**Function************************************************************* Synopsis [Returns representatives of fanin in approapriate polarity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Aig_Obj_t * Aig_ObjGetRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pRepr; if ( (pRepr = Aig_ObjFindRepr(p, pObj)) ) return Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pObj->fPhase ^ pRepr->fPhase ); return (Aig_Obj_t *)pObj->pData; } static inline Aig_Obj_t * Aig_ObjChild0Repr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjGetRepr(p, Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); } static inline Aig_Obj_t * Aig_ObjChild1Repr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjGetRepr(p, Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); } /**Function************************************************************* Synopsis [Duplicates AIG while substituting representatives.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManTransferRepr( Aig_Man_t * pNew, Aig_Man_t * pOld ) { Aig_Obj_t * pObj, * pRepr; int k; assert( pNew->pReprs != NULL ); // extend storage to fix pNew if ( pNew->nReprsAlloc < Aig_ManObjNumMax(pNew) ) { int nReprsAllocNew = 2 * Aig_ManObjNumMax(pNew); pNew->pReprs = ABC_REALLOC( Aig_Obj_t *, pNew->pReprs, nReprsAllocNew ); memset( pNew->pReprs + pNew->nReprsAlloc, 0, sizeof(Aig_Obj_t *) * (nReprsAllocNew-pNew->nReprsAlloc) ); pNew->nReprsAlloc = nReprsAllocNew; } // go through the nodes which have representatives Aig_ManForEachObj( pOld, pObj, k ) if ( (pRepr = Aig_ObjFindRepr(pOld, pObj)) ) Aig_ObjSetRepr_( pNew, Aig_Regular((Aig_Obj_t *)pRepr->pData), Aig_Regular((Aig_Obj_t *)pObj->pData) ); } /**Function************************************************************* Synopsis [Duplicates the AIG manager recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ManDupRepr_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pRepr; if ( pObj->pData ) return (Aig_Obj_t *)pObj->pData; if ( (pRepr = Aig_ObjFindRepr(p, pObj)) ) { Aig_ManDupRepr_rec( pNew, p, pRepr ); return (Aig_Obj_t *)(pObj->pData = Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pRepr->fPhase ^ pObj->fPhase )); } Aig_ManDupRepr_rec( pNew, p, Aig_ObjFanin0(pObj) ); Aig_ManDupRepr_rec( pNew, p, Aig_ObjFanin1(pObj) ); return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Repr(p, pObj), Aig_ObjChild1Repr(p, pObj) )); } /**Function************************************************************* Synopsis [Duplicates AIG while substituting representatives.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupRepr( Aig_Man_t * p, int fOrdered ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; // start the HOP package pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; pNew->nBarBufs = p->nBarBufs; if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); // map the const and primary inputs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) pObj->pData = Aig_ObjCreateCi(pNew); // Aig_ManForEachCi( p, pObj, i ) // pObj->pData = Aig_ObjGetRepr( p, pObj ); // map the internal nodes if ( fOrdered ) { Aig_ManForEachNode( p, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Repr(p, pObj), Aig_ObjChild1Repr(p, pObj) ); } else { // Aig_ManForEachObj( p, pObj, i ) // if ( p->pReprs[i] ) // printf( "Substituting %d for %d.\n", p->pReprs[i]->Id, pObj->Id ); Aig_ManForEachCo( p, pObj, i ) Aig_ManDupRepr_rec( pNew, p, Aig_ObjFanin0(pObj) ); } // transfer the POs Aig_ManForEachCo( p, pObj, i ) Aig_ObjCreateCo( pNew, Aig_ObjChild0Repr(p, pObj) ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // check the new manager if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupRepr: Check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG with representatives without removing registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupReprBasic( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; assert( p->pReprs != NULL ); // reconstruct AIG with representatives pNew = Aig_ManDupRepr( p, 0 ); // perfrom sequential cleanup but do not remove registers Aig_ManSeqCleanupBasic( pNew ); // remove pointers to the dead nodes Aig_ManForEachObj( p, pObj, i ) if ( pObj->pData && Aig_ObjIsNone((Aig_Obj_t *)pObj->pData) ) pObj->pData = NULL; return pNew; } /**Function************************************************************* Synopsis [Transfer representatives and return the number of critical fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManRemapRepr( Aig_Man_t * p ) { Aig_Obj_t * pObj, * pRepr; int i, nFanouts = 0; Aig_ManForEachNode( p, pObj, i ) { pRepr = Aig_ObjFindReprTransitive( p, pObj ); if ( pRepr == NULL ) continue; assert( pRepr->Id < pObj->Id ); Aig_ObjSetRepr_( p, pObj, pRepr ); nFanouts += (pObj->nRefs > 0); } return nFanouts; } /**Function************************************************************* Synopsis [Transfer representatives and return the number of critical fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManCountReprs( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, Counter = 0; if ( p->pReprs == NULL ) return 0; Aig_ManForEachObj( p, pObj, i ) Counter += (p->pReprs[i] != NULL); return Counter; } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjCheckTfi_rec( Aig_Man_t * p, Aig_Obj_t * pNode, Aig_Obj_t * pOld ) { // check the trivial cases if ( pNode == NULL ) return 0; if ( Aig_ObjIsCi(pNode) ) return 0; // if ( pNode->Id < pOld->Id ) // cannot use because of choices of pNode // return 0; if ( pNode == pOld ) return 1; // skip the visited node if ( Aig_ObjIsTravIdCurrent( p, pNode ) ) return 0; Aig_ObjSetTravIdCurrent( p, pNode ); // check the children if ( Aig_ObjCheckTfi_rec( p, Aig_ObjFanin0(pNode), pOld ) ) return 1; if ( Aig_ObjCheckTfi_rec( p, Aig_ObjFanin1(pNode), pOld ) ) return 1; // check equivalent nodes return Aig_ObjCheckTfi_rec( p, Aig_ObjEquiv(p, pNode), pOld ); } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pNew, Aig_Obj_t * pOld ) { assert( !Aig_IsComplement(pNew) ); assert( !Aig_IsComplement(pOld) ); Aig_ManIncrementTravId( p ); return Aig_ObjCheckTfi_rec( p, pNew, pOld ); } /**Function************************************************************* Synopsis [Iteratively rehashes the AIG.] Description [The input AIG is assumed to have representatives assigned.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManRehash( Aig_Man_t * p ) { Aig_Man_t * pTemp; int i, nFanouts; assert( p->pReprs != NULL ); for ( i = 0; (nFanouts = Aig_ManRemapRepr( p )); i++ ) { // printf( "Iter = %3d. Fanouts = %6d. Nodes = %7d.\n", i+1, nFanouts, Aig_ManNodeNum(p) ); p = Aig_ManDupRepr( pTemp = p, 1 ); Aig_ManReprStart( p, Aig_ManObjNumMax(p) ); Aig_ManTransferRepr( p, pTemp ); Aig_ManStop( pTemp ); } return p; } /**Function************************************************************* Synopsis [Marks the nodes that are Creates choices.] Description [The input AIG is assumed to have representatives assigned.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManMarkValidChoices( Aig_Man_t * p ) { Aig_Obj_t * pObj, * pRepr; int i; assert( p->pReprs != NULL ); // create equivalent nodes in the manager assert( p->pEquivs == NULL ); p->pEquivs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); memset( p->pEquivs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) ); // make the choice nodes Aig_ManForEachNode( p, pObj, i ) { pRepr = Aig_ObjFindRepr( p, pObj ); if ( pRepr == NULL ) continue; // skip constant and PI classes if ( !Aig_ObjIsNode(pRepr) ) { Aig_ObjClearRepr( p, pObj ); continue; } // skip choices with combinatinal loops if ( Aig_ObjCheckTfi( p, pObj, pRepr ) ) { Aig_ObjClearRepr( p, pObj ); continue; } //printf( "Node %d is represented by node %d.\n", pObj->Id, pRepr->Id ); // add choice to the choice node if ( pObj->nRefs > 0 ) { Aig_ObjClearRepr( p, pObj ); continue; } assert( pObj->nRefs == 0 ); p->pEquivs[pObj->Id] = p->pEquivs[pRepr->Id]; p->pEquivs[pRepr->Id] = pObj; } } /**Function************************************************************* Synopsis [Transfers the classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_TransferMappedClasses( Aig_Man_t * pAig, Aig_Man_t * pPart, int * pMapBack ) { Aig_Obj_t * pObj; int nClasses, k; nClasses = 0; if ( pPart->pReprs ) { Aig_ManForEachObj( pPart, pObj, k ) { if ( pPart->pReprs[pObj->Id] == NULL ) continue; nClasses++; Aig_ObjSetRepr_( pAig, Aig_ManObj(pAig, pMapBack[pObj->Id]), Aig_ManObj(pAig, pMapBack[pPart->pReprs[pObj->Id]->Id]) ); } } return nClasses; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigRet.c000066400000000000000000001027231477524141600156530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigRet.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Retiming of AIGs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigRet.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // init values typedef enum { RTM_VAL_NONE, // 0: non-existent value RTM_VAL_ZERO, // 1: initial value 0 RTM_VAL_ONE, // 2: initial value 1 RTM_VAL_VOID // 3: unused value } Rtm_Init_t; typedef struct Rtm_Man_t_ Rtm_Man_t; struct Rtm_Man_t_ { // network representation Vec_Ptr_t * vObjs; // retiming objects Vec_Ptr_t * vPis; // PIs only Vec_Ptr_t * vPos; // POs only Aig_MmFlex_t * pMem; // the memory manager // autonomous components after cutting off // storage for overflow latches unsigned * pExtra; int nExtraCur; int nExtraAlloc; }; typedef struct Rtm_Edg_t_ Rtm_Edg_t; struct Rtm_Edg_t_ { unsigned long nLats : 12; // the number of latches unsigned long LData : 20; // the latches themselves }; typedef struct Rtm_Obj_t_ Rtm_Obj_t; struct Rtm_Obj_t_ { void * pCopy; // the copy of this object unsigned long Type : 3; // object type unsigned long fMark : 1; // multipurpose mark unsigned long fAuto : 1; // this object belongs to an autonomous component unsigned long fCompl0 : 1; // complemented attribute of the first edge unsigned long fCompl1 : 1; // complemented attribute of the second edge unsigned long nFanins : 8; // the number of fanins unsigned Num : 17; // the retiming number of this node int Id; // ID of this object int Temp; // temporary usage int nFanouts; // the number of fanouts void * pFanio[0]; // fanins and their edges (followed by fanouts and pointers to their edges) }; static inline Rtm_Obj_t * Rtm_ObjFanin( Rtm_Obj_t * pObj, int i ) { return (Rtm_Obj_t *)pObj->pFanio[2*i]; } static inline Rtm_Obj_t * Rtm_ObjFanout( Rtm_Obj_t * pObj, int i ) { return (Rtm_Obj_t *)pObj->pFanio[2*(pObj->nFanins+i)]; } static inline Rtm_Edg_t * Rtm_ObjEdge( Rtm_Obj_t * pObj, int i ) { return (Rtm_Edg_t *)(pObj->pFanio + 2*i + 1); } static inline Rtm_Edg_t * Rtm_ObjFanoutEdge( Rtm_Obj_t * pObj, int i ) { return (Rtm_Edg_t *)pObj->pFanio[2*(pObj->nFanins+i) + 1]; } static inline Rtm_Init_t Rtm_InitNot( Rtm_Init_t Val ) { if ( Val == RTM_VAL_ZERO ) return (Rtm_Init_t)RTM_VAL_ONE; if ( Val == RTM_VAL_ONE ) return (Rtm_Init_t)RTM_VAL_ZERO; assert( 0 ); return (Rtm_Init_t)-1; } static inline Rtm_Init_t Rtm_InitNotCond( Rtm_Init_t Val, int c ) { return c ? Rtm_InitNot(Val) : Val; } static inline Rtm_Init_t Rtm_InitAnd(Rtm_Init_t ValA, Rtm_Init_t ValB ) { if ( ValA == RTM_VAL_ONE && ValB == RTM_VAL_ONE ) return (Rtm_Init_t)RTM_VAL_ONE; if ( ValA == RTM_VAL_ZERO || ValB == RTM_VAL_ZERO ) return (Rtm_Init_t)RTM_VAL_ZERO; assert( 0 ); return (Rtm_Init_t)-1; } static inline int Rtm_InitWordsNum( int nLats ) { return (nLats >> 4) + ((nLats & 15) > 0); } static inline int Rtm_InitGetTwo( unsigned * p, int i ) { return (p[i>>4] >> ((i & 15)<<1)) & 3; } static inline void Rtm_InitSetTwo( unsigned * p, int i, int val ) { p[i>>4] |= (val << ((i & 15)<<1)); } static inline void Rtm_InitXorTwo( unsigned * p, int i, int val ) { p[i>>4] ^= (val << ((i & 15)<<1)); } static inline Rtm_Init_t Rtm_ObjGetFirst1( Rtm_Edg_t * pEdge ) { return (Rtm_Init_t)(pEdge->LData & 3); } static inline Rtm_Init_t Rtm_ObjGetLast1( Rtm_Edg_t * pEdge ) { return (Rtm_Init_t)((pEdge->LData >> ((pEdge->nLats-1)<<1)) & 3); } static inline Rtm_Init_t Rtm_ObjGetOne1( Rtm_Edg_t * pEdge, int i ) { assert( i < (int)pEdge->nLats ); return (Rtm_Init_t)((pEdge->LData >> (i << 1)) & 3); } static inline Rtm_Init_t Rtm_ObjRemFirst1( Rtm_Edg_t * pEdge ) { int Val = pEdge->LData & 3; pEdge->LData >>= 2; assert(pEdge->nLats > 0); pEdge->nLats--; return (Rtm_Init_t)Val; } static inline Rtm_Init_t Rtm_ObjRemLast1( Rtm_Edg_t * pEdge ) { int Val = (pEdge->LData >> ((pEdge->nLats-1)<<1)) & 3; pEdge->LData ^= Val << ((pEdge->nLats-1)<<1); assert(pEdge->nLats > 0); pEdge->nLats--; return (Rtm_Init_t)Val; } static inline void Rtm_ObjAddFirst1( Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { assert( Val > 0 ); pEdge->LData = (pEdge->LData << 2) | Val; pEdge->nLats++; } static inline void Rtm_ObjAddLast1( Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { assert( Val > 0 ); pEdge->LData |= Val << (pEdge->nLats<<1); pEdge->nLats++; } static inline Rtm_Init_t Rtm_ObjGetFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return (Rtm_Init_t)Rtm_InitGetTwo( p->pExtra + pEdge->LData, 0 ); } static inline Rtm_Init_t Rtm_ObjGetLast2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return (Rtm_Init_t)Rtm_InitGetTwo( p->pExtra + pEdge->LData, pEdge->nLats - 1 ); } static inline Rtm_Init_t Rtm_ObjGetOne2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, int i ) { return (Rtm_Init_t)Rtm_InitGetTwo( p->pExtra + pEdge->LData, i ); } static Rtm_Init_t Rtm_ObjRemFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); static inline Rtm_Init_t Rtm_ObjRemLast2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { Rtm_Init_t Val = Rtm_ObjGetLast2( p, pEdge ); Rtm_InitXorTwo( p->pExtra + pEdge->LData, pEdge->nLats - 1, Val ); pEdge->nLats--; return (Rtm_Init_t)Val; } static void Rtm_ObjAddFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ); static inline void Rtm_ObjAddLast2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { Rtm_InitSetTwo( p->pExtra + pEdge->LData, pEdge->nLats, Val ); pEdge->nLats++; } static void Rtm_ObjTransferToSmall( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); static void Rtm_ObjTransferToBig( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); static void Rtm_ObjTransferToBigger( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); static inline Rtm_Init_t Rtm_ObjGetFirst( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return pEdge->nLats > 10? Rtm_ObjGetFirst2(p, pEdge) : Rtm_ObjGetFirst1(pEdge); } static inline Rtm_Init_t Rtm_ObjGetLast( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return pEdge->nLats > 10? Rtm_ObjGetLast2(p, pEdge) : Rtm_ObjGetLast1(pEdge); } static inline Rtm_Init_t Rtm_ObjGetOne( Rtm_Man_t * p, Rtm_Edg_t * pEdge, int i ) { return pEdge->nLats > 10? Rtm_ObjGetOne2(p, pEdge, i) : Rtm_ObjGetOne1(pEdge, i); } static Rtm_Init_t Rtm_ObjRemFirst( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { Rtm_Init_t Res = pEdge->nLats > 10 ? Rtm_ObjRemFirst2(p, pEdge) : Rtm_ObjRemFirst1(pEdge); if ( pEdge->nLats == 10 ) Rtm_ObjTransferToSmall(p, pEdge); return Res; } static Rtm_Init_t Rtm_ObjRemLast( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { Rtm_Init_t Res = pEdge->nLats > 10 ? Rtm_ObjRemLast2(p, pEdge) : Rtm_ObjRemLast1(pEdge); if ( pEdge->nLats == 10 ) Rtm_ObjTransferToSmall(p, pEdge); return Res; } static void Rtm_ObjAddFirst( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { if ( pEdge->nLats == 10 ) Rtm_ObjTransferToBig(p, pEdge); else if ( (pEdge->nLats & 15) == 15 ) Rtm_ObjTransferToBigger(p, pEdge); if ( pEdge->nLats >= 10 ) Rtm_ObjAddFirst2(p, pEdge, Val); else Rtm_ObjAddFirst1(pEdge, Val); } static void Rtm_ObjAddLast( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { if ( pEdge->nLats == 10 ) Rtm_ObjTransferToBig(p, pEdge); else if ( (pEdge->nLats & 15) == 15 ) Rtm_ObjTransferToBigger(p, pEdge); if ( pEdge->nLats >= 10 ) Rtm_ObjAddLast2(p, pEdge, Val); else Rtm_ObjAddLast1(pEdge, Val); } // iterator over the primary inputs #define Rtm_ManForEachPi( p, pObj, i ) \ Vec_PtrForEachEntry( Rtm_Obj_t *, p->vPis, pObj, i ) // iterator over the primary outputs #define Rtm_ManForEachPo( p, pObj, i ) \ Vec_PtrForEachEntry( Rtm_Obj_t *, p->vPos, pObj, i ) // iterator over all objects, including those currently not used #define Rtm_ManForEachObj( p, pObj, i ) \ Vec_PtrForEachEntry( Rtm_Obj_t *, p->vObjs, pObj, i ) // iterate through the fanins #define Rtm_ObjForEachFanin( pObj, pFanin, i ) \ for ( i = 0; i < (int)(pObj)->nFanins && ((pFanin = Rtm_ObjFanin(pObj, i)), 1); i++ ) // iterate through the fanouts #define Rtm_ObjForEachFanout( pObj, pFanout, i ) \ for ( i = 0; i < (int)(pObj)->nFanouts && ((pFanout = Rtm_ObjFanout(pObj, i)), 1); i++ ) // iterate through the fanin edges #define Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) \ for ( i = 0; i < (int)(pObj)->nFanins && ((pEdge = Rtm_ObjEdge(pObj, i)), 1); i++ ) // iterate through the fanout edges #define Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) \ for ( i = 0; i < (int)(pObj)->nFanouts && ((pEdge = Rtm_ObjFanoutEdge(pObj, i)), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Transfers from big to small storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rtm_ObjTransferToSmall( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { assert( pEdge->nLats == 10 ); pEdge->LData = p->pExtra[pEdge->LData]; } /**Function************************************************************* Synopsis [Transfers from small to big storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rtm_ObjTransferToBig( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { assert( pEdge->nLats == 10 ); if ( p->nExtraCur + 1 > p->nExtraAlloc ) { int nExtraAllocNew = Abc_MaxInt( 2 * p->nExtraAlloc, 1024 ); p->pExtra = ABC_REALLOC( unsigned, p->pExtra, nExtraAllocNew ); p->nExtraAlloc = nExtraAllocNew; } p->pExtra[p->nExtraCur] = pEdge->LData; pEdge->LData = p->nExtraCur++; } /**Function************************************************************* Synopsis [Transfers to bigger storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rtm_ObjTransferToBigger( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { int nWords; assert( (pEdge->nLats & 15) == 15 ); nWords = (pEdge->nLats + 1) >> 4; if ( p->nExtraCur + nWords + 1 > p->nExtraAlloc ) { int nExtraAllocNew = Abc_MaxInt( 2 * p->nExtraAlloc, 1024 ); p->pExtra = ABC_REALLOC( unsigned, p->pExtra, nExtraAllocNew ); p->nExtraAlloc = nExtraAllocNew; } memcpy( p->pExtra + p->nExtraCur, p->pExtra + pEdge->LData, sizeof(unsigned) * nWords ); p->pExtra[p->nExtraCur + nWords] = 0; pEdge->LData = p->nExtraCur; p->nExtraCur += nWords + 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rtm_Init_t Rtm_ObjRemFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { Rtm_Init_t Val = (Rtm_Init_t)0, Temp; unsigned * pB = p->pExtra + pEdge->LData, * pE = pB + Rtm_InitWordsNum( pEdge->nLats-- ) - 1; while ( pE >= pB ) { Temp = (Rtm_Init_t)(*pE & 3); *pE = (*pE >> 2) | (Val << 30); Val = Temp; pE--; } assert( Val != 0 ); return Val; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rtm_ObjAddFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { unsigned * pB = p->pExtra + pEdge->LData, * pE = pB + Rtm_InitWordsNum( ++pEdge->nLats ); Rtm_Init_t Temp; assert( Val != 0 ); while ( pB < pE ) { Temp = (Rtm_Init_t)(*pB >> 30); *pB = (*pB << 2) | Val; Val = Temp; pB++; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rtm_PrintEdge( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { // unsigned LData = pEdge->LData; printf( "%d : ", (int)pEdge->nLats ); /* if ( pEdge->nLats > 10 ) Extra_PrintBinary( stdout, p->pExtra + pEdge->LData, 2*(pEdge->nLats+1) ); else Extra_PrintBinary( stdout, &LData, 2*(pEdge->nLats+1) ); */ printf( "\n" ); } /**Function************************************************************* Synopsis [Allocates the retiming manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rtm_Man_t * Rtm_ManAlloc( Aig_Man_t * p ) { Rtm_Man_t * pRtm; // start the manager pRtm = ABC_ALLOC( Rtm_Man_t, 1 ); memset( pRtm, 0, sizeof(Rtm_Man_t) ); // perform initializations pRtm->vObjs = Vec_PtrAlloc( Aig_ManObjNum(p) ); pRtm->vPis = Vec_PtrAlloc( Aig_ManCiNum(p) ); pRtm->vPos = Vec_PtrAlloc( Aig_ManCoNum(p) ); pRtm->pMem = Aig_MmFlexStart(); return pRtm; } /**Function************************************************************* Synopsis [Allocates the retiming manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rtm_ManFree( Rtm_Man_t * p ) { Vec_PtrFree( p->vObjs ); Vec_PtrFree( p->vPis ); Vec_PtrFree( p->vPos ); Aig_MmFlexStop( p->pMem, 0 ); ABC_FREE( p->pExtra ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Counts the maximum number of latches on an edge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rtm_ManLatchMax( Rtm_Man_t * p ) { Rtm_Obj_t * pObj; Rtm_Edg_t * pEdge; int nLatchMax = 0, i, k;//, c, Val; Rtm_ManForEachObj( p, pObj, i ) Rtm_ObjForEachFaninEdge( pObj, pEdge, k ) { /* for ( c = 0; c < (int)pEdge->nLats; c++ ) { Val = Rtm_ObjGetOne( p, pEdge, c ); assert( Val == 1 || Val == 2 ); } */ nLatchMax = Abc_MaxInt( nLatchMax, (int)pEdge->nLats ); } return nLatchMax; } /**Function************************************************************* Synopsis [Allocates the retiming object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rtm_Obj_t * Rtm_ObjAlloc( Rtm_Man_t * pRtm, int nFanins, int nFanouts ) { Rtm_Obj_t * pObj; int Size = sizeof(Rtm_Obj_t) + sizeof(Rtm_Obj_t *) * (nFanins + nFanouts) * 2; pObj = (Rtm_Obj_t *)Aig_MmFlexEntryFetch( pRtm->pMem, Size ); memset( pObj, 0, sizeof(Rtm_Obj_t) ); pObj->Type = (int)(nFanins == 1 && nFanouts == 0); // mark PO pObj->Num = nFanins; // temporary pObj->Temp = nFanouts; pObj->Id = Vec_PtrSize(pRtm->vObjs); Vec_PtrPush( pRtm->vObjs, pObj ); return pObj; } /**Function************************************************************* Synopsis [Allocates the retiming object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rtm_ObjAddFanin( Rtm_Obj_t * pObj, Rtm_Obj_t * pFanin, int fCompl ) { pObj->pFanio[ 2*pObj->nFanins ] = pFanin; pObj->pFanio[ 2*pObj->nFanins + 1 ] = NULL; pFanin->pFanio[ 2*(pFanin->Num + pFanin->nFanouts) ] = pObj; pFanin->pFanio[ 2*(pFanin->Num + pFanin->nFanouts) + 1 ] = pObj->pFanio + 2*pObj->nFanins + 1; if ( pObj->nFanins == 0 ) pObj->fCompl0 = fCompl; else if ( pObj->nFanins == 1 ) pObj->fCompl1 = fCompl; else assert( 0 ); pObj->nFanins++; pFanin->nFanouts++; assert( pObj->nFanins <= pObj->Num ); assert( pFanin->nFanouts <= pFanin->Temp ); } /**Function************************************************************* Synopsis [Check the possibility of forward retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rtm_ObjCheckRetimeFwd( Rtm_Obj_t * pObj ) { Rtm_Edg_t * pEdge; int i; Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) if ( pEdge->nLats == 0 ) return 0; return 1; } /**Function************************************************************* Synopsis [Check the possibility of forward retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rtm_ObjCheckRetimeBwd( Rtm_Obj_t * pObj ) { Rtm_Edg_t * pEdge; int i; Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) if ( pEdge->nLats == 0 ) return 0; return 1; } /**Function************************************************************* Synopsis [Check the possibility of forward retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rtm_ObjGetDegreeFwd( Rtm_Obj_t * pObj ) { Rtm_Obj_t * pFanin; int i, Degree = 0; Rtm_ObjForEachFanin( pObj, pFanin, i ) Degree = Abc_MaxInt( Degree, (int)pFanin->Num ); return Degree + 1; } /**Function************************************************************* Synopsis [Check the possibility of forward retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rtm_ObjGetDegreeBwd( Rtm_Obj_t * pObj ) { Rtm_Obj_t * pFanout; int i, Degree = 0; Rtm_ObjForEachFanout( pObj, pFanout, i ) Degree = Abc_MaxInt( Degree, (int)pFanout->Num ); return Degree + 1; } /**Function************************************************************* Synopsis [Performs forward retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rtm_ObjRetimeFwd( Rtm_Man_t * pRtm, Rtm_Obj_t * pObj ) { Rtm_Init_t ValTotal, ValCur; Rtm_Edg_t * pEdge; int i; assert( Rtm_ObjCheckRetimeFwd(pObj) ); // extract values and compute the result ValTotal = RTM_VAL_ONE; Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) { ValCur = Rtm_ObjRemFirst( pRtm, pEdge ); ValCur = Rtm_InitNotCond( ValCur, i? pObj->fCompl1 : pObj->fCompl0 ); ValTotal = Rtm_InitAnd( ValTotal, ValCur ); } // insert the result in the fanout values Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) Rtm_ObjAddLast( pRtm, pEdge, ValTotal ); } /**Function************************************************************* Synopsis [Performs forward retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rtm_ObjRetimeBwd( Rtm_Man_t * pRtm, Rtm_Obj_t * pObj ) { Rtm_Edg_t * pEdge; int i; assert( Rtm_ObjCheckRetimeBwd(pObj) ); // extract values and compute the result Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) Rtm_ObjRemLast( pRtm, pEdge ); // insert the result in the fanout values Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) Rtm_ObjAddFirst( pRtm, pEdge, RTM_VAL_VOID ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rtm_ObjMarkAutoFwd_rec( Rtm_Obj_t * pObj ) { Rtm_Obj_t * pFanout; int i; if ( pObj->fAuto ) return; pObj->fAuto = 1; Rtm_ObjForEachFanout( pObj, pFanout, i ) Rtm_ObjMarkAutoFwd_rec( pFanout ); } /**Function************************************************************* Synopsis [Marks the nodes unreachable from the PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rtm_ManMarkAutoFwd( Rtm_Man_t * pRtm ) { Rtm_Obj_t * pObjRtm; int i, Counter = 0; // mark nodes reachable from the PIs pObjRtm = (Rtm_Obj_t *)Vec_PtrEntry( pRtm->vObjs, 0 ); Rtm_ObjMarkAutoFwd_rec( pObjRtm ); Rtm_ManForEachPi( pRtm, pObjRtm, i ) Rtm_ObjMarkAutoFwd_rec( pObjRtm ); // count the number of autonomous nodes Rtm_ManForEachObj( pRtm, pObjRtm, i ) { pObjRtm->fAuto = !pObjRtm->fAuto; Counter += pObjRtm->fAuto; } // mark the fanins of the autonomous nodes return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Rtm_ObjMarkAutoBwd_rec( Rtm_Obj_t * pObj ) { Rtm_Obj_t * pFanin; int i; if ( pObj->fAuto ) return; pObj->fAuto = 1; Rtm_ObjForEachFanin( pObj, pFanin, i ) Rtm_ObjMarkAutoBwd_rec( pFanin ); } /**Function************************************************************* Synopsis [Marks the nodes unreachable from the POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rtm_ManMarkAutoBwd( Rtm_Man_t * pRtm ) { Rtm_Obj_t * pObjRtm; int i, Counter = 0; // mark nodes reachable from the PIs pObjRtm = (Rtm_Obj_t *)Vec_PtrEntry( pRtm->vObjs, 0 ); pObjRtm->fAuto = 1; Rtm_ManForEachPi( pRtm, pObjRtm, i ) pObjRtm->fAuto = 1; Rtm_ManForEachPo( pRtm, pObjRtm, i ) Rtm_ObjMarkAutoBwd_rec( pObjRtm ); // count the number of autonomous nodes Rtm_ManForEachObj( pRtm, pObjRtm, i ) { pObjRtm->fAuto = !pObjRtm->fAuto; Counter += pObjRtm->fAuto; } // mark the fanins of the autonomous nodes return Counter; } /**Function************************************************************* Synopsis [Derive retiming manager from the given AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rtm_Man_t * Rtm_ManFromAig( Aig_Man_t * p ) { Rtm_Man_t * pRtm; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i; assert( Aig_ManRegNum(p) > 0 ); assert( Aig_ManBufNum(p) == 0 ); // allocate the manager pRtm = Rtm_ManAlloc( p ); // allocate objects pObj = Aig_ManConst1(p); pObj->pData = Rtm_ObjAlloc( pRtm, 0, pObj->nRefs ); Aig_ManForEachPiSeq( p, pObj, i ) { pObj->pData = Rtm_ObjAlloc( pRtm, 0, pObj->nRefs ); Vec_PtrPush( pRtm->vPis, pObj->pData ); } Aig_ManForEachPoSeq( p, pObj, i ) { pObj->pData = Rtm_ObjAlloc( pRtm, 1, 0 ); Vec_PtrPush( pRtm->vPos, pObj->pData ); } Aig_ManForEachLoSeq( p, pObj, i ) pObj->pData = Rtm_ObjAlloc( pRtm, 1, pObj->nRefs ); Aig_ManForEachLiSeq( p, pObj, i ) pObj->pData = Rtm_ObjAlloc( pRtm, 1, 1 ); Aig_ManForEachNode( p, pObj, i ) pObj->pData = Rtm_ObjAlloc( pRtm, 2, pObj->nRefs ); // connect objects Aig_ManForEachPoSeq( p, pObj, i ) Rtm_ObjAddFanin( (Rtm_Obj_t *)pObj->pData, (Rtm_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); Aig_ManForEachLiSeq( p, pObj, i ) Rtm_ObjAddFanin( (Rtm_Obj_t *)pObj->pData, (Rtm_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) Rtm_ObjAddFanin( (Rtm_Obj_t *)pObjLo->pData, (Rtm_Obj_t *)pObjLi->pData, 0 ); Aig_ManForEachNode( p, pObj, i ) { Rtm_ObjAddFanin( (Rtm_Obj_t *)pObj->pData, (Rtm_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); Rtm_ObjAddFanin( (Rtm_Obj_t *)pObj->pData, (Rtm_Obj_t *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); } return pRtm; } /**Function************************************************************* Synopsis [Derive AIG manager after retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Rtm_ManToAig_rec( Aig_Man_t * pNew, Rtm_Man_t * pRtm, Rtm_Obj_t * pObjRtm, int * pLatches ) { Rtm_Edg_t * pEdge; Aig_Obj_t * pRes, * pFanin; int k, Val; if ( pObjRtm->pCopy ) return (Aig_Obj_t *)pObjRtm->pCopy; // get the inputs pRes = Aig_ManConst1( pNew ); Rtm_ObjForEachFaninEdge( pObjRtm, pEdge, k ) { if ( pEdge->nLats == 0 ) pFanin = Rtm_ManToAig_rec( pNew, pRtm, Rtm_ObjFanin(pObjRtm, k), pLatches ); else { Val = Rtm_ObjGetFirst( pRtm, pEdge ); pFanin = Aig_ManCi( pNew, pLatches[2*pObjRtm->Id + k] + pEdge->nLats - 1 ); pFanin = Aig_NotCond( pFanin, Val == RTM_VAL_ONE ); } pFanin = Aig_NotCond( pFanin, k ? pObjRtm->fCompl1 : pObjRtm->fCompl0 ); pRes = Aig_And( pNew, pRes, pFanin ); } return (Aig_Obj_t *)(pObjRtm->pCopy = pRes); } /**Function************************************************************* Synopsis [Derive AIG manager after retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Rtm_ManToAig( Rtm_Man_t * pRtm ) { Aig_Man_t * pNew; Aig_Obj_t * pObjNew; Rtm_Obj_t * pObjRtm; Rtm_Edg_t * pEdge; int i, k, m, Val, nLatches, * pLatches; // count latches and mark the first latch on each edge pLatches = ABC_ALLOC( int, 2 * Vec_PtrSize(pRtm->vObjs) ); nLatches = 0; Rtm_ManForEachObj( pRtm, pObjRtm, i ) Rtm_ObjForEachFaninEdge( pObjRtm, pEdge, k ) { pLatches[2*pObjRtm->Id + k] = Vec_PtrSize(pRtm->vPis) + nLatches; nLatches += pEdge->nLats; } // create the new manager pNew = Aig_ManStart( Vec_PtrSize(pRtm->vObjs) + nLatches ); // create PIs/POs and latches pObjRtm = (Rtm_Obj_t *)Vec_PtrEntry( pRtm->vObjs, 0 ); pObjRtm->pCopy = Aig_ManConst1(pNew); Rtm_ManForEachPi( pRtm, pObjRtm, i ) pObjRtm->pCopy = Aig_ObjCreateCi(pNew); for ( i = 0; i < nLatches; i++ ) Aig_ObjCreateCi(pNew); // create internal nodes Rtm_ManForEachObj( pRtm, pObjRtm, i ) Rtm_ManToAig_rec( pNew, pRtm, pObjRtm, pLatches ); // create POs Rtm_ManForEachPo( pRtm, pObjRtm, i ) Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObjRtm->pCopy ); // connect latches Rtm_ManForEachObj( pRtm, pObjRtm, i ) Rtm_ObjForEachFaninEdge( pObjRtm, pEdge, k ) { if ( pEdge->nLats == 0 ) continue; pObjNew = (Aig_Obj_t *)Rtm_ObjFanin( pObjRtm, k )->pCopy; for ( m = 0; m < (int)pEdge->nLats; m++ ) { Val = Rtm_ObjGetOne( pRtm, pEdge, pEdge->nLats - 1 - m ); assert( Val == RTM_VAL_ZERO || Val == RTM_VAL_ONE || Val == RTM_VAL_VOID ); pObjNew = Aig_NotCond( pObjNew, Val == RTM_VAL_ONE ); Aig_ObjCreateCo( pNew, pObjNew ); pObjNew = Aig_ManCi( pNew, pLatches[2*pObjRtm->Id + k] + m ); pObjNew = Aig_NotCond( pObjNew, Val == RTM_VAL_ONE ); } // assert( Aig_Regular(pObjNew)->nRefs > 0 ); } ABC_FREE( pLatches ); Aig_ManSetRegNum( pNew, nLatches ); // remove useless nodes Aig_ManCleanup( pNew ); if ( !Aig_ManCheck( pNew ) ) printf( "Rtm_ManToAig: The network check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Performs forward retiming with the given limit on depth.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Rtm_ManRetime( Aig_Man_t * p, int fForward, int nStepsMax, int fVerbose ) { Vec_Ptr_t * vQueue; Aig_Man_t * pNew; Rtm_Man_t * pRtm; Rtm_Obj_t * pObj, * pNext; Aig_Obj_t * pObjAig; int i, k, nAutos, Degree, DegreeMax = 0; abctime clk; // create the retiming manager clk = Abc_Clock(); pRtm = Rtm_ManFromAig( p ); // set registers Aig_ManForEachLoSeq( p, pObjAig, i ) Rtm_ObjAddFirst( pRtm, Rtm_ObjEdge((Rtm_Obj_t *)pObjAig->pData, 0), fForward? RTM_VAL_ZERO : RTM_VAL_VOID ); // detect and mark the autonomous components if ( fForward ) nAutos = Rtm_ManMarkAutoFwd( pRtm ); else nAutos = Rtm_ManMarkAutoBwd( pRtm ); if ( fVerbose ) { printf( "Detected %d autonomous objects. ", nAutos ); ABC_PRT( "Time", Abc_Clock() - clk ); } // set the current retiming number Rtm_ManForEachObj( pRtm, pObj, i ) { assert( pObj->nFanins == pObj->Num ); assert( pObj->nFanouts == pObj->Temp ); pObj->Num = 0; } clk = Abc_Clock(); // put the LOs on the queue vQueue = Vec_PtrAlloc( 1000 ); if ( fForward ) { Aig_ManForEachLoSeq( p, pObjAig, i ) { pObj = (Rtm_Obj_t *)pObjAig->pData; if ( pObj->fAuto ) continue; pObj->fMark = 1; Vec_PtrPush( vQueue, pObj ); } } else { Aig_ManForEachLiSeq( p, pObjAig, i ) { pObj = (Rtm_Obj_t *)pObjAig->pData; if ( pObj->fAuto ) continue; pObj->fMark = 1; Vec_PtrPush( vQueue, pObj ); } } // perform retiming DegreeMax = 0; Vec_PtrForEachEntry( Rtm_Obj_t *, vQueue, pObj, i ) { pObj->fMark = 0; // retime the node if ( fForward ) { Rtm_ObjRetimeFwd( pRtm, pObj ); // check if its fanouts should be retimed Rtm_ObjForEachFanout( pObj, pNext, k ) { if ( pNext->fMark ) // skip aleady scheduled continue; if ( pNext->Type ) // skip POs continue; if ( !Rtm_ObjCheckRetimeFwd( pNext ) ) // skip non-retimable continue; Degree = Rtm_ObjGetDegreeFwd( pNext ); DegreeMax = Abc_MaxInt( DegreeMax, Degree ); if ( Degree > nStepsMax ) // skip nodes with high degree continue; pNext->fMark = 1; pNext->Num = Degree; Vec_PtrPush( vQueue, pNext ); } } else { Rtm_ObjRetimeBwd( pRtm, pObj ); // check if its fanouts should be retimed Rtm_ObjForEachFanin( pObj, pNext, k ) { if ( pNext->fMark ) // skip aleady scheduled continue; if ( pNext->nFanins == 0 ) // skip PIs continue; if ( !Rtm_ObjCheckRetimeBwd( pNext ) ) // skip non-retimable continue; Degree = Rtm_ObjGetDegreeBwd( pNext ); DegreeMax = Abc_MaxInt( DegreeMax, Degree ); if ( Degree > nStepsMax ) // skip nodes with high degree continue; pNext->fMark = 1; pNext->Num = Degree; Vec_PtrPush( vQueue, pNext ); } } } if ( fVerbose ) { printf( "Performed %d %s latch moves of max depth %d and max latch count %d.\n", Vec_PtrSize(vQueue), fForward? "fwd":"bwd", DegreeMax, Rtm_ManLatchMax(pRtm) ); printf( "Memory usage = %d. ", pRtm->nExtraCur ); ABC_PRT( "Time", Abc_Clock() - clk ); } Vec_PtrFree( vQueue ); // get the new manager pNew = Rtm_ManToAig( pRtm ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Rtm_ManFree( pRtm ); // group the registers clk = Abc_Clock(); pNew = Aig_ManReduceLaches( pNew, fVerbose ); if ( fVerbose ) { ABC_PRT( "Register sharing time", Abc_Clock() - clk ); } return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigRetF.c000066400000000000000000000152251477524141600157610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigRetF.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Retiming frontier.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigRetF.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Mark the nodes reachable from the PIs in the reverse order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManRetimeMark_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( pObj->fMarkB ) return 1; if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) return 0; if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return pObj->fMarkB; Aig_ObjSetTravIdCurrent(p, pObj); if ( Aig_ManRetimeMark_rec( p, Aig_ObjFanin0(pObj) ) ) return pObj->fMarkB = 1; if ( Aig_ObjIsNode(pObj) && Aig_ManRetimeMark_rec( p, Aig_ObjFanin1(pObj) ) ) return pObj->fMarkB = 1; assert( pObj->fMarkB == 0 ); return 0; } /**Function************************************************************* Synopsis [Mark the nodes reachable from the true PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManRetimeMark( Aig_Man_t * p ) { Aig_Obj_t * pObj, * pObjLi, * pObjLo; int fChange, i; // mark the PIs Aig_ManForEachObj( p, pObj, i ) assert( pObj->fMarkB == 0 ); Aig_ManForEachPiSeq( p, pObj, i ) pObj->fMarkB = 1; // map registers into each other Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) { assert( pObjLo->pNext == NULL ); assert( pObjLi->pNext == NULL ); pObjLo->pNext = pObjLi; pObjLi->pNext = pObjLo; } // iterativively mark the logic reachable from PIs fChange = 1; while ( fChange ) { fChange = 0; Aig_ManIncrementTravId( p ); Aig_ManForEachCo( p, pObj, i ) { if ( pObj->fMarkB ) continue; if ( Aig_ManRetimeMark_rec( p, pObj ) ) { if ( pObj->pNext ) pObj->pNext->fMarkB = 1; fChange = 1; } } } // clean register mapping Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) pObjLo->pNext = pObjLi->pNext = NULL; } /**Function************************************************************* Synopsis [Performs forward retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManRetimeFrontier( Aig_Man_t * p, int nStepsMax ) { Aig_Obj_t * pObj, * pObjNew, * pObjLo, * pObjLo0, * pObjLo1, * pObjLi, * pObjLi0, * pObjLi1;//, * pObjLi0_, * pObjLi1_, * pObjLi0__, * pObjLi1__; int i, Counter, fCompl, fChange; assert( Aig_ManRegNum(p) > 0 ); // remove structural hashing table Aig_TableClear( p ); // mark the retimable nodes Aig_ManRetimeMark( p ); // mark the register outputs Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) { pObjLo->fMarkA = 1; pObjLo->pNext = pObjLi; pObjLi->pNext = pObjLo; } // go through the nodes and find retimable ones Counter = 0; fChange = 1; while ( fChange ) { fChange = 0; Aig_ManForEachNode( p, pObj, i ) { if ( !pObj->fMarkB ) continue; if ( Aig_ObjIsBuf(pObj) ) continue; // get the real inputs of the node (skipping the buffers) pObjLo0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); pObjLo1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); if ( !Aig_Regular(pObjLo0)->fMarkA || !Aig_Regular(pObjLo1)->fMarkA ) continue; // remember complemented attribute fCompl = Aig_IsComplement(pObjLo0) & Aig_IsComplement(pObjLo1); // get the register inputs // pObjLi0_ = Aig_Regular(pObjLo0)->pNext; // pObjLi1_ = Aig_Regular(pObjLo1)->pNext; // pObjLi0__ = Aig_ObjChild0(Aig_Regular(pObjLo0)->pNext); // pObjLi1__ = Aig_ObjChild0(Aig_Regular(pObjLo1)->pNext); pObjLi0 = Aig_NotCond( Aig_ObjChild0(Aig_Regular(pObjLo0)->pNext), Aig_IsComplement(pObjLo0) ); pObjLi1 = Aig_NotCond( Aig_ObjChild0(Aig_Regular(pObjLo1)->pNext), Aig_IsComplement(pObjLo1) ); // create new node pObjNew = Aig_And( p, pObjLi0, pObjLi1 ); pObjNew->fMarkB = 1; // create new register pObjLo = Aig_ObjCreateCi(p); pObjLo->fMarkA = 1; pObjLi = Aig_ObjCreateCo( p, Aig_NotCond(pObjNew, fCompl) ); p->nRegs++; pObjLo->pNext = pObjLi; pObjLi->pNext = pObjLo; // add the buffer Aig_ObjDisconnect( p, pObj ); pObj->Type = AIG_OBJ_BUF; p->nObjs[AIG_OBJ_AND]--; p->nObjs[AIG_OBJ_BUF]++; Aig_ObjConnect( p, pObj, Aig_NotCond(pObjLo, fCompl), NULL ); // create HAIG if defined // mark the change fChange = 1; // check the limit if ( ++Counter >= nStepsMax ) { fChange = 0; break; } } } // clean the markings Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) { pObjLo->fMarkA = 0; pObjLo->pNext = pObjLi->pNext = NULL; } Aig_ManForEachObj( p, pObj, i ) pObj->fMarkB = 0; // remove useless registers Aig_ManSeqCleanup( p ); // rehash the nodes return Aig_ManDupOrdered( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigScl.c000066400000000000000000000547111477524141600156450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigScl.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Sequential cleanup.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigScl.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Remaps the manager.] Description [Map in the array specifies for each CI node the node that should be used after remapping.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManRemap( Aig_Man_t * p, Vec_Ptr_t * vMap ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjMapped; int i, nTruePis; // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nAsserts = p->nAsserts; pNew->nConstrs = p->nConstrs; pNew->nBarBufs = p->nBarBufs; assert( p->vFlopNums == NULL || Vec_IntSize(p->vFlopNums) == p->nRegs ); if ( p->vFlopNums ) pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); if ( p->vFlopReprs ) pNew->vFlopReprs = Vec_IntDup( p->vFlopReprs ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) pObj->pData = Aig_ObjCreateCi(pNew); // implement the mapping nTruePis = Aig_ManCiNum(p)-Aig_ManRegNum(p); if ( p->vFlopReprs ) { Aig_ManForEachLoSeq( p, pObj, i ) pObj->pNext = (Aig_Obj_t *)(long)Vec_IntEntry( p->vFlopNums, i-nTruePis ); } Aig_ManForEachCi( p, pObj, i ) { pObjMapped = (Aig_Obj_t *)Vec_PtrEntry( vMap, i ); pObj->pData = Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pObjMapped)->pData, Aig_IsComplement(pObjMapped) ); if ( pNew->vFlopReprs && i >= nTruePis && pObj != pObjMapped ) { Vec_IntPush( pNew->vFlopReprs, Aig_ObjCioId(pObj) ); if ( Aig_ObjIsConst1( Aig_Regular(pObjMapped) ) ) Vec_IntPush( pNew->vFlopReprs, -1 ); else { assert( !Aig_IsComplement(pObjMapped) ); assert( Aig_ObjIsCi(pObjMapped) ); assert( Aig_ObjCioId(pObj) != Aig_ObjCioId(pObjMapped) ); Vec_IntPush( pNew->vFlopReprs, Aig_ObjCioId(pObjMapped) ); } } } if ( p->vFlopReprs ) { Aig_ManForEachLoSeq( p, pObj, i ) pObj->pNext = NULL; } // duplicate internal nodes Aig_ManForEachObj( p, pObj, i ) if ( Aig_ObjIsBuf(pObj) ) pObj->pData = Aig_ObjChild0Copy(pObj); else if ( Aig_ObjIsNode(pObj) ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // add the POs Aig_ManForEachCo( p, pObj, i ) Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); assert( Aig_ManNodeNum(p) >= Aig_ManNodeNum(pNew) ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManRemap(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Returns the number of dangling nodes removed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManSeqCleanup_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); // collect latch input corresponding to unmarked PI (latch output) if ( Aig_ObjIsCi(pObj) ) { Vec_PtrPush( vNodes, pObj->pNext ); return; } if ( Aig_ObjIsCo(pObj) || Aig_ObjIsBuf(pObj) ) { Aig_ManSeqCleanup_rec( p, Aig_ObjFanin0(pObj), vNodes ); return; } assert( Aig_ObjIsNode(pObj) ); Aig_ManSeqCleanup_rec( p, Aig_ObjFanin0(pObj), vNodes ); Aig_ManSeqCleanup_rec( p, Aig_ObjFanin1(pObj), vNodes ); } /**Function************************************************************* Synopsis [Returns the number of dangling nodes removed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManSeqCleanup( Aig_Man_t * p ) { Vec_Ptr_t * vNodes, * vCis, * vCos; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, nTruePis, nTruePos; // assert( Aig_ManBufNum(p) == 0 ); // mark the PIs Aig_ManIncrementTravId( p ); Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); Aig_ManForEachPiSeq( p, pObj, i ) Aig_ObjSetTravIdCurrent( p, pObj ); // prepare to collect nodes reachable from POs vNodes = Vec_PtrAlloc( 100 ); Aig_ManForEachPoSeq( p, pObj, i ) Vec_PtrPush( vNodes, pObj ); // remember latch inputs in latch outputs Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) pObjLo->pNext = pObjLi; // mark the nodes reachable from these nodes Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) Aig_ManSeqCleanup_rec( p, pObj, vNodes ); assert( Vec_PtrSize(vNodes) <= Aig_ManCoNum(p) ); // clean latch output pointers Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) pObjLo->pNext = NULL; // if some latches are removed, update PIs/POs if ( Vec_PtrSize(vNodes) < Aig_ManCoNum(p) ) { if ( p->vFlopNums ) { int nTruePos = Aig_ManCoNum(p)-Aig_ManRegNum(p); int iNum, k = 0; Aig_ManForEachCo( p, pObj, i ) if ( i >= nTruePos && Aig_ObjIsTravIdCurrent(p, pObj) ) { iNum = Vec_IntEntry( p->vFlopNums, i - nTruePos ); Vec_IntWriteEntry( p->vFlopNums, k++, iNum ); } assert( k == Vec_PtrSize(vNodes) - nTruePos ); Vec_IntShrink( p->vFlopNums, k ); } // collect new CIs/COs vCis = Vec_PtrAlloc( Aig_ManCiNum(p) ); Aig_ManForEachCi( p, pObj, i ) if ( Aig_ObjIsTravIdCurrent(p, pObj) ) Vec_PtrPush( vCis, pObj ); else { Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); // Aig_ManRecycleMemory( p, pObj ); } vCos = Vec_PtrAlloc( Aig_ManCoNum(p) ); Aig_ManForEachCo( p, pObj, i ) if ( Aig_ObjIsTravIdCurrent(p, pObj) ) Vec_PtrPush( vCos, pObj ); else { Aig_ObjDisconnect( p, pObj ); Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); // Aig_ManRecycleMemory( p, pObj ); } // remember the number of true PIs/POs nTruePis = Aig_ManCiNum(p) - Aig_ManRegNum(p); nTruePos = Aig_ManCoNum(p) - Aig_ManRegNum(p); // set the new number of registers p->nRegs -= Aig_ManCoNum(p) - Vec_PtrSize(vNodes); // create new PIs/POs assert( Vec_PtrSize(vCis) == nTruePis + p->nRegs ); assert( Vec_PtrSize(vCos) == nTruePos + p->nRegs ); Vec_PtrFree( p->vCis ); p->vCis = vCis; Vec_PtrFree( p->vCos ); p->vCos = vCos; p->nObjs[AIG_OBJ_CI] = Vec_PtrSize( p->vCis ); p->nObjs[AIG_OBJ_CO] = Vec_PtrSize( p->vCos ); } Vec_PtrFree( vNodes ); p->nTruePis = Aig_ManCiNum(p) - Aig_ManRegNum(p); p->nTruePos = Aig_ManCoNum(p) - Aig_ManRegNum(p); Aig_ManSetCioIds( p ); // remove dangling nodes return Aig_ManCleanup( p ); } /**Function************************************************************* Synopsis [Returns the number of dangling nodes removed.] Description [This cleanup procedure is different in that it removes logic but does not remove the dangling latches.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManSeqCleanupBasic( Aig_Man_t * p ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i; // assert( Aig_ManBufNum(p) == 0 ); // mark the PIs Aig_ManIncrementTravId( p ); Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); Aig_ManForEachPiSeq( p, pObj, i ) Aig_ObjSetTravIdCurrent( p, pObj ); // prepare to collect nodes reachable from POs vNodes = Vec_PtrAlloc( 100 ); Aig_ManForEachPoSeq( p, pObj, i ) Vec_PtrPush( vNodes, pObj ); // remember latch inputs in latch outputs Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) pObjLo->pNext = pObjLi; // mark the nodes reachable from these nodes Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) Aig_ManSeqCleanup_rec( p, pObj, vNodes ); assert( Vec_PtrSize(vNodes) <= Aig_ManCoNum(p) ); // clean latch output pointers Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) pObjLo->pNext = NULL; // if some latches are removed, update PIs/POs if ( Vec_PtrSize(vNodes) < Aig_ManCoNum(p) ) { // add constant drivers to the dangling latches Aig_ManForEachCo( p, pObj, i ) if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) Aig_ObjPatchFanin0( p, pObj, Aig_ManConst0(p) ); } Vec_PtrFree( vNodes ); // remove dangling nodes return Aig_ManCleanup( p ); } /**Function************************************************************* Synopsis [Returns the number of dangling nodes removed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManCountMergeRegs( Aig_Man_t * p ) { Aig_Obj_t * pObj, * pFanin; int i, Counter = 0, Const0 = 0, Const1 = 0; Aig_ManIncrementTravId( p ); Aig_ManForEachLiSeq( p, pObj, i ) { pFanin = Aig_ObjFanin0(pObj); if ( Aig_ObjIsConst1(pFanin) ) { if ( Aig_ObjFaninC0(pObj) ) Const0++; else Const1++; } if ( Aig_ObjIsTravIdCurrent(p, pFanin) ) continue; Aig_ObjSetTravIdCurrent(p, pFanin); Counter++; } printf( "Regs = %d. Fanins = %d. Const0 = %d. Const1 = %d.\n", Aig_ManRegNum(p), Counter, Const0, Const1 ); return 0; } /**Function************************************************************* Synopsis [Checks how many latches can be reduced.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManReduceLachesCount( Aig_Man_t * p ) { Aig_Obj_t * pObj, * pFanin; int i, Counter = 0, Diffs = 0; assert( Aig_ManRegNum(p) > 0 ); Aig_ManForEachObj( p, pObj, i ) assert( !pObj->fMarkA && !pObj->fMarkB ); Aig_ManForEachLiSeq( p, pObj, i ) { pFanin = Aig_ObjFanin0(pObj); if ( Aig_ObjFaninC0(pObj) ) { if ( pFanin->fMarkB ) Counter++; else pFanin->fMarkB = 1; } else { if ( pFanin->fMarkA ) Counter++; else pFanin->fMarkA = 1; } } // count fanins that have both attributes Aig_ManForEachLiSeq( p, pObj, i ) { pFanin = Aig_ObjFanin0(pObj); Diffs += pFanin->fMarkA && pFanin->fMarkB; pFanin->fMarkA = pFanin->fMarkB = 0; } // printf( "Diffs = %d.\n", Diffs ); return Counter; } /**Function************************************************************* Synopsis [Reduces the latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManReduceLachesOnce( Aig_Man_t * p ) { Vec_Ptr_t * vMap; Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pFanin; int * pMapping, i; // start mapping by adding the true PIs vMap = Vec_PtrAlloc( Aig_ManCiNum(p) ); Aig_ManForEachPiSeq( p, pObj, i ) Vec_PtrPush( vMap, pObj ); // create mapping of fanin nodes into the corresponding latch outputs pMapping = ABC_FALLOC( int, 2 * Aig_ManObjNumMax(p) ); Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) { pFanin = Aig_ObjFanin0(pObjLi); if ( Aig_ObjFaninC0(pObjLi) ) { if ( pFanin->fMarkB ) { Vec_PtrPush( vMap, Aig_ManLo(p, pMapping[2*pFanin->Id + 1]) ); } else { pFanin->fMarkB = 1; pMapping[2*pFanin->Id + 1] = i; Vec_PtrPush( vMap, pObjLo ); } } else { if ( pFanin->fMarkA ) { Vec_PtrPush( vMap, Aig_ManLo(p, pMapping[2*pFanin->Id]) ); } else { pFanin->fMarkA = 1; pMapping[2*pFanin->Id] = i; Vec_PtrPush( vMap, pObjLo ); } } } ABC_FREE( pMapping ); Aig_ManForEachLiSeq( p, pObj, i ) { pFanin = Aig_ObjFanin0(pObj); pFanin->fMarkA = pFanin->fMarkB = 0; } return vMap; } /**Function************************************************************* Synopsis [Reduces the latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManReduceLaches( Aig_Man_t * p, int fVerbose ) { Aig_Man_t * pTemp; Vec_Ptr_t * vMap; int nSaved, nCur; if ( fVerbose ) printf( "Performing combinational register sweep:\n" ); for ( nSaved = 0; (nCur = Aig_ManReduceLachesCount(p)); nSaved += nCur ) { // printf( "Reducible = %d\n", nCur ); vMap = Aig_ManReduceLachesOnce( p ); p = Aig_ManRemap( pTemp = p, vMap ); Vec_PtrFree( vMap ); Aig_ManSeqCleanup( p ); if ( fVerbose ) Aig_ManReportImprovement( pTemp, p ); Aig_ManStop( pTemp ); if ( p->nRegs == 0 ) break; } return p; } /**Function************************************************************* Synopsis [Computes strongly connected components of registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManComputeSccs( Aig_Man_t * p ) { Vec_Ptr_t * vSupports, * vMatrix, * vMatrix2; Vec_Int_t * vSupp, * vSupp2, * vComp; char * pVarsTot; int i, k, m, iOut, iIn, nComps; if ( Aig_ManRegNum(p) == 0 ) { printf( "The network is combinational.\n" ); return; } // get structural supports for each output vSupports = Aig_ManSupports( p ); // transforms the supports into the latch dependency matrix vMatrix = Vec_PtrStart( Aig_ManRegNum(p) ); Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vSupp, i ) { // skip true POs iOut = Vec_IntPop( vSupp ); iOut -= Aig_ManCoNum(p) - Aig_ManRegNum(p); if ( iOut < 0 ) continue; // remove PIs m = 0; Vec_IntForEachEntry( vSupp, iIn, k ) { iIn -= Aig_ManCiNum(p) - Aig_ManRegNum(p); if ( iIn < 0 ) continue; assert( iIn < Aig_ManRegNum(p) ); Vec_IntWriteEntry( vSupp, m++, iIn ); } Vec_IntShrink( vSupp, m ); // store support in the matrix assert( iOut < Aig_ManRegNum(p) ); Vec_PtrWriteEntry( vMatrix, iOut, vSupp ); } // create the reverse matrix vMatrix2 = Vec_PtrAlloc( Aig_ManRegNum(p) ); for ( i = 0; i < Aig_ManRegNum(p); i++ ) Vec_PtrPush( vMatrix2, Vec_IntAlloc(8) ); Vec_PtrForEachEntry( Vec_Int_t *, vMatrix, vSupp, i ) { Vec_IntForEachEntry( vSupp, iIn, k ) { vSupp2 = (Vec_Int_t *)Vec_PtrEntry( vMatrix2, iIn ); Vec_IntPush( vSupp2, i ); } } // detect strongly connected components vComp = Vec_IntAlloc( Aig_ManRegNum(p) ); pVarsTot = ABC_ALLOC( char, Aig_ManRegNum(p) ); memset( pVarsTot, 0, Aig_ManRegNum(p) * sizeof(char) ); for ( nComps = 0; ; nComps++ ) { Vec_IntClear( vComp ); // get the first support for ( iOut = 0; iOut < Aig_ManRegNum(p); iOut++ ) if ( pVarsTot[iOut] == 0 ) break; if ( iOut == Aig_ManRegNum(p) ) break; pVarsTot[iOut] = 1; Vec_IntPush( vComp, iOut ); Vec_IntForEachEntry( vComp, iOut, i ) { vSupp = (Vec_Int_t *)Vec_PtrEntry( vMatrix, iOut ); Vec_IntForEachEntry( vSupp, iIn, k ) { if ( pVarsTot[iIn] ) continue; pVarsTot[iIn] = 1; Vec_IntPush( vComp, iIn ); } vSupp2 = (Vec_Int_t *)Vec_PtrEntry( vMatrix2, iOut ); Vec_IntForEachEntry( vSupp2, iIn, k ) { if ( pVarsTot[iIn] ) continue; pVarsTot[iIn] = 1; Vec_IntPush( vComp, iIn ); } } if ( Vec_IntSize(vComp) == Aig_ManRegNum(p) ) { printf( "There is only one SCC of registers in this network.\n" ); break; } printf( "SCC #%d contains %5d registers.\n", nComps+1, Vec_IntSize(vComp) ); } ABC_FREE( pVarsTot ); Vec_IntFree( vComp ); Vec_PtrFree( vMatrix ); Vec_VecFree( (Vec_Vec_t *)vMatrix2 ); Vec_VecFree( (Vec_Vec_t *)vSupports ); } /**Function************************************************************* Synopsis [Performs partitioned register sweep.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManSclPart( Aig_Man_t * pAig, int fLatchConst, int fLatchEqual, int fVerbose ) { Vec_Ptr_t * vResult; Vec_Int_t * vPart; int i, nCountPis, nCountRegs; int * pMapBack; Aig_Man_t * pTemp, * pNew; int nClasses; if ( pAig->vClockDoms ) { vResult = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Vec_Int_t *, (Vec_Ptr_t *)pAig->vClockDoms, vPart, i ) Vec_PtrPush( vResult, Vec_IntDup(vPart) ); } else vResult = Aig_ManRegPartitionSimple( pAig, 0, 0 ); Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i ) { pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, &pMapBack ); Aig_ManSetRegNum( pTemp, pTemp->nRegs ); if (nCountPis>0) { pNew = Aig_ManScl( pTemp, fLatchConst, fLatchEqual, 0, -1, -1, fVerbose, 0 ); nClasses = Aig_TransferMappedClasses( pAig, pTemp, pMapBack ); if ( fVerbose ) printf( "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. It = %3d. Cl = %5d\n", i, Vec_IntSize(vPart), Aig_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp), 0, nClasses ); Aig_ManStop( pNew ); } Aig_ManStop( pTemp ); ABC_FREE( pMapBack ); } pNew = Aig_ManDupRepr( pAig, 0 ); Aig_ManSeqCleanup( pNew ); Vec_VecFree( (Vec_Vec_t*)vResult ); return pNew; } /**Function************************************************************* Synopsis [Gives the current ABC network to AIG manager for processing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManScl( Aig_Man_t * pAig, int fLatchConst, int fLatchEqual, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose ) { extern void Saig_ManReportUselessRegisters( Aig_Man_t * pAig ); extern int Saig_ManReportComplements( Aig_Man_t * p ); Aig_Man_t * pAigInit, * pAigNew; Aig_Obj_t * pFlop1, * pFlop2; int i, Entry1, Entry2, nTruePis;//, nRegs; if ( pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0 ) return Aig_ManSclPart( pAig, fLatchConst, fLatchEqual, fVerbose); // store the original AIG assert( pAig->vFlopNums == NULL ); pAigInit = pAig; pAig = Aig_ManDupSimple( pAig ); // create storage for latch numbers pAig->vFlopNums = Vec_IntStartNatural( pAig->nRegs ); pAig->vFlopReprs = Vec_IntAlloc( 100 ); Aig_ManSeqCleanup( pAig ); if ( fLatchConst && pAig->nRegs ) pAig = Aig_ManConstReduce( pAig, fUseMvSweep, nFramesSymb, nFramesSatur, fVerbose, fVeryVerbose ); if ( fLatchEqual && pAig->nRegs ) pAig = Aig_ManReduceLaches( pAig, fVerbose ); // translate pairs into reprs nTruePis = Aig_ManCiNum(pAigInit)-Aig_ManRegNum(pAigInit); Aig_ManReprStart( pAigInit, Aig_ManObjNumMax(pAigInit) ); Vec_IntForEachEntry( pAig->vFlopReprs, Entry1, i ) { Entry2 = Vec_IntEntry( pAig->vFlopReprs, ++i ); pFlop1 = Aig_ManCi( pAigInit, nTruePis + Entry1 ); pFlop2 = (Entry2 == -1)? Aig_ManConst1(pAigInit) : Aig_ManCi( pAigInit, nTruePis + Entry2 ); assert( pFlop1 != pFlop2 ); if ( pFlop1->Id > pFlop2->Id ) pAigInit->pReprs[pFlop1->Id] = pFlop2; else pAigInit->pReprs[pFlop2->Id] = pFlop1; } Aig_ManStop( pAig ); // Aig_ManSeqCleanup( pAigInit ); pAigNew = Aig_ManDupRepr( pAigInit, 0 ); Aig_ManSeqCleanup( pAigNew ); // Saig_ManReportUselessRegisters( pAigNew ); if ( Aig_ManRegNum(pAigNew) == 0 ) return pAigNew; // nRegs = Saig_ManReportComplements( pAigNew ); // if ( nRegs ) // printf( "The number of complemented registers = %d.\n", nRegs ); return pAigNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigShow.c000066400000000000000000000316361477524141600160450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyShow.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Visualization of HAIG.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" #include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Writes the graph structure of AIG for DOT.] Description [Useful for graph visualization using tools such as GraphViz: http://www.graphviz.org/] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_WriteDotAig( Aig_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ) { FILE * pFile; Aig_Obj_t * pNode;//, * pTemp, * pPrev; int LevelMax, Prev, Level, i; if ( Aig_ManNodeNum(pMan) > 200 ) { fprintf( stdout, "Cannot visualize AIG with more than 200 nodes.\n" ); return; } if ( (pFile = fopen( pFileName, "w" )) == NULL ) { fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); return; } // mark the nodes if ( vBold ) Vec_PtrForEachEntry( Aig_Obj_t *, vBold, pNode, i ) pNode->fMarkB = 1; // compute levels // LevelMax = 1 + Aig_ManSetLevels( pMan, fHaig ); LevelMax = 1 + Aig_ManLevels( pMan ); Aig_ManForEachCo( pMan, pNode, i ) pNode->Level = LevelMax; // write the DOT header fprintf( pFile, "# %s\n", "AIG structure generated by IVY package" ); fprintf( pFile, "\n" ); fprintf( pFile, "digraph AIG {\n" ); fprintf( pFile, "size = \"7.5,10\";\n" ); // fprintf( pFile, "ranksep = 0.5;\n" ); // fprintf( pFile, "nodesep = 0.5;\n" ); fprintf( pFile, "center = true;\n" ); // fprintf( pFile, "orientation = landscape;\n" ); // fprintf( pFile, "edge [fontsize = 10];\n" ); // fprintf( pFile, "edge [dir = none];\n" ); fprintf( pFile, "edge [dir = back];\n" ); fprintf( pFile, "\n" ); // labels on the left of the picture fprintf( pFile, "{\n" ); fprintf( pFile, " node [shape = plaintext];\n" ); fprintf( pFile, " edge [style = invis];\n" ); fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); // generate node names with labels for ( Level = LevelMax; Level >= 0; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); fprintf( pFile, " [label = " ); // label name fprintf( pFile, "\"" ); fprintf( pFile, "\"" ); fprintf( pFile, "];\n" ); } // genetate the sequence of visible/invisible nodes to mark levels fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); for ( Level = LevelMax; Level >= 0; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); // the connector if ( Level != 0 ) fprintf( pFile, " ->" ); else fprintf( pFile, ";" ); } fprintf( pFile, "\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate title box on top fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); fprintf( pFile, " LevelTitle1;\n" ); fprintf( pFile, " title1 [shape=plaintext,\n" ); fprintf( pFile, " fontsize=20,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); fprintf( pFile, "%s", "AIG structure visualized by ABC" ); fprintf( pFile, "\\n" ); fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); // fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate statistics box fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); fprintf( pFile, " LevelTitle2;\n" ); fprintf( pFile, " title2 [shape=plaintext,\n" ); fprintf( pFile, " fontsize=18,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Aig_ManNodeNum(pMan), LevelMax ); fprintf( pFile, "\\n" ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate the COs fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMax ); // generate the CO nodes Aig_ManForEachCo( pMan, pNode, i ) { /* if ( fHaig || pNode->pEquiv == NULL ) fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":"") ); else fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":""), Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" ); */ fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); fprintf( pFile, ", shape = %s", "invtriangle" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate nodes of each rank for ( Level = LevelMax - 1; Level > 0; Level-- ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", Level ); Aig_ManForEachObj( pMan, pNode, i ) { if ( (int)pNode->Level != Level ) continue; /* if ( fHaig || pNode->pEquiv == NULL ) fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); else fprintf( pFile, " Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id, Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" ); */ fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); fprintf( pFile, ", shape = ellipse" ); if ( vBold && pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); } // generate the CI nodes fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", 0 ); // generate constant node if ( Aig_ObjRefs(Aig_ManConst1(pMan)) > 0 ) { pNode = Aig_ManConst1(pMan); // check if the costant node is present fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id ); fprintf( pFile, ", shape = ellipse" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } // generate the CI nodes Aig_ManForEachCi( pMan, pNode, i ) { /* if ( fHaig || pNode->pEquiv == NULL ) fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, (Aig_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_out":"") ); else fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, (Aig_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_out":""), Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" ); */ fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); fprintf( pFile, ", shape = %s", "triangle" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate invisible edges from the square down fprintf( pFile, "title1 -> title2 [style = invis];\n" ); Aig_ManForEachCo( pMan, pNode, i ) fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); // generate invisible edges among the COs Prev = -1; Aig_ManForEachCo( pMan, pNode, i ) { if ( i > 0 ) fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, pNode->Id ); Prev = pNode->Id; } // generate edges Aig_ManForEachObj( pMan, pNode, i ) { if ( !Aig_ObjIsNode(pNode) && !Aig_ObjIsCo(pNode) && !Aig_ObjIsBuf(pNode) ) continue; // generate the edge from this node to the next fprintf( pFile, "Node%d", pNode->Id ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", Aig_ObjFaninId0(pNode) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", Aig_ObjFaninC0(pNode)? "dotted" : "bold" ); // if ( Aig_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 ) // fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); if ( !Aig_ObjIsNode(pNode) ) continue; // generate the edge from this node to the next fprintf( pFile, "Node%d", pNode->Id ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", Aig_ObjFaninId1(pNode) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", Aig_ObjFaninC1(pNode)? "dotted" : "bold" ); // if ( Aig_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 ) // fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); /* // generate the edges between the equivalent nodes if ( fHaig && pNode->pEquiv && Aig_ObjRefs(pNode) > 0 ) { pPrev = pNode; for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Aig_Regular(pTemp->pEquiv) ) { fprintf( pFile, "Node%d", pPrev->Id ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", pTemp->Id ); fprintf( pFile, " [style = %s]", Aig_IsComplement(pTemp->pEquiv)? "dotted" : "bold" ); fprintf( pFile, ";\n" ); pPrev = pTemp; } // connect the last node with the first fprintf( pFile, "Node%d", pPrev->Id ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", pNode->Id ); fprintf( pFile, " [style = %s]", Aig_IsComplement(pPrev->pEquiv)? "dotted" : "bold" ); fprintf( pFile, ";\n" ); } */ } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); fclose( pFile ); // unmark nodes if ( vBold ) Vec_PtrForEachEntry( Aig_Obj_t *, vBold, pNode, i ) pNode->fMarkB = 0; Aig_ManForEachCo( pMan, pNode, i ) pNode->Level = Aig_ObjFanin0(pNode)->Level; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) { extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); char FileNameDot[200]; FILE * pFile; // create the file name sprintf( FileNameDot, "%s", Extra_FileNameGenericAppend(pMan->pName ? pMan->pName : (char *)"unknown", ".dot") ); // check that the file can be opened if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) { fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); return; } fclose( pFile ); // generate the file Aig_WriteDotAig( pMan, FileNameDot, fHaig, vBold ); // visualize the file Abc_ShowFile( FileNameDot, 0 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigSplit.c000066400000000000000000000243201477524141600162100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigSplit.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Splits the property output cone into a set of cofactor properties.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigSplit.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" #include "aig/saig/saig.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD /**Function************************************************************* Synopsis [Converts the node to MUXes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Aig_Man_t * pNew, st__table * tBdd2Node ) { Aig_Obj_t * pNode, * pNode0, * pNode1, * pNodeC; assert( !Cudd_IsComplement(bFunc) ); if ( st__lookup( tBdd2Node, (char *)bFunc, (char **)&pNode ) ) return pNode; // solve for the children nodes pNode0 = Aig_NodeBddToMuxes_rec( dd, Cudd_Regular(cuddE(bFunc)), pNew, tBdd2Node ); pNode0 = Aig_NotCond( pNode0, Cudd_IsComplement(cuddE(bFunc)) ); pNode1 = Aig_NodeBddToMuxes_rec( dd, cuddT(bFunc), pNew, tBdd2Node ); if ( ! st__lookup( tBdd2Node, (char *)Cudd_bddIthVar(dd, bFunc->index), (char **)&pNodeC ) ) assert( 0 ); // create the MUX node pNode = Aig_Mux( pNew, pNodeC, pNode1, pNode0 ); st__insert( tBdd2Node, (char *)bFunc, (char *)pNode ); return pNode; } /**Function************************************************************* Synopsis [Derives AIG for the BDDs of the cofactors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManConvertBddsToAigs( Aig_Man_t * p, DdManager * dd, Vec_Ptr_t * vCofs ) { DdNode * bFunc; st__table * tBdd2Node; Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; Aig_ManCleanData( p ); // generate AIG for BDD pNew = Aig_ManStart( Aig_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); // create the table mapping BDD nodes into the ABC nodes tBdd2Node = st__init_table( st__ptrcmp, st__ptrhash ); // add the constant and the elementary vars st__insert( tBdd2Node, (char *)Cudd_ReadOne(dd), (char *)Aig_ManConst1(pNew) ); Aig_ManForEachCi( p, pObj, i ) st__insert( tBdd2Node, (char *)Cudd_bddIthVar(dd, i), (char *)pObj->pData ); // build primary outputs for the cofactors Vec_PtrForEachEntry( DdNode *, vCofs, bFunc, i ) { if ( bFunc == Cudd_ReadLogicZero(dd) ) continue; pObj = Aig_NodeBddToMuxes_rec( dd, Cudd_Regular(bFunc), pNew, tBdd2Node ); pObj = Aig_NotCond( pObj, Cudd_IsComplement(bFunc) ); Aig_ObjCreateCo( pNew, pObj ); } st__free_table( tBdd2Node ); // duplicate the rest of the AIG // add the POs Aig_ManForEachCo( p, pObj, i ) { if ( i == 0 ) continue; Aig_ManDupSimpleDfs_rec( pNew, p, Aig_ObjFanin0(pObj) ); pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } Aig_ManCleanup( pNew ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManConvertBddsToAigs(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Returns the array of constraint candidates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Aig_ManBuildPoBdd_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd ) { DdNode * bBdd0, * bBdd1; if ( pObj->pData != NULL ) return (DdNode *)pObj->pData; assert( Aig_ObjIsNode(pObj) ); bBdd0 = Aig_ManBuildPoBdd_rec( p, Aig_ObjFanin0(pObj), dd ); bBdd1 = Aig_ManBuildPoBdd_rec( p, Aig_ObjFanin1(pObj), dd ); bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) ); bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) ); pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); return (DdNode *)pObj->pData; } /**Function************************************************************* Synopsis [Derive BDDs for the cofactors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManCofactorBdds( Aig_Man_t * p, Vec_Ptr_t * vSubset, DdManager * dd, DdNode * bFunc ) { Vec_Ptr_t * vCofs; DdNode * bCube, * bTemp, * bCof, ** pbVars; int i; vCofs = Vec_PtrAlloc( 100 ); pbVars = (DdNode **)Vec_PtrArray(vSubset); for ( i = 0; i < (1 << Vec_PtrSize(vSubset)); i++ ) { bCube = Extra_bddBitsToCube( dd, i, Vec_PtrSize(vSubset), pbVars, 1 ); Cudd_Ref( bCube ); bCof = Cudd_Cofactor( dd, bFunc, bCube ); Cudd_Ref( bCof ); bCof = Cudd_bddAnd( dd, bTemp = bCof, bCube ); Cudd_Ref( bCof ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bCube ); Vec_PtrPush( vCofs, bCof ); } return vCofs; } /**Function************************************************************* Synopsis [Construct BDDs for the primary output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdManager * Aig_ManBuildPoBdd( Aig_Man_t * p, DdNode ** pbFunc ) { DdManager * dd; Aig_Obj_t * pObj; int i; assert( Saig_ManPoNum(p) == 1 ); Aig_ManCleanData( p ); dd = Cudd_Init( Aig_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); pObj = Aig_ManConst1(p); pObj->pData = Cudd_ReadOne(dd); Cudd_Ref( (DdNode *)pObj->pData ); Aig_ManForEachCi( p, pObj, i ) { pObj->pData = Cudd_bddIthVar(dd, i); Cudd_Ref( (DdNode *)pObj->pData ); } pObj = Aig_ManCo( p, 0 ); *pbFunc = Aig_ManBuildPoBdd_rec( p, Aig_ObjFanin0(pObj), dd ); Cudd_Ref( *pbFunc ); *pbFunc = Cudd_NotCond( *pbFunc, Aig_ObjFaninC0(pObj) ); Aig_ManForEachObj( p, pObj, i ) { if ( pObj->pData ) Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); } Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); return dd; } /**Function************************************************************* Synopsis [Randomly selects a random subset of inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManVecRandSubset( Vec_Ptr_t * vVec, int nVars ) { Vec_Ptr_t * vRes; void * pEntry; unsigned Rand; vRes = Vec_PtrDup(vVec); while ( Vec_PtrSize(vRes) > nVars ) { Rand = Aig_ManRandom( 0 ); pEntry = Vec_PtrEntry( vRes, Rand % Vec_PtrSize(vRes) ); Vec_PtrRemove( vRes, pEntry ); } return vRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManSplit( Aig_Man_t * p, int nVars, int fVerbose ) { Aig_Man_t * pRes; Aig_Obj_t * pNode; DdNode * bFunc; DdManager * dd; Vec_Ptr_t * vSupp, * vSubs, * vCofs; int i; abctime clk = Abc_Clock(); if ( Saig_ManPoNum(p) != 1 ) { printf( "Currently works only for one primary output.\n" ); return NULL; } if ( nVars < 1 ) { printf( "The number of cofactoring variables should be a positive number.\n" ); return NULL; } if ( nVars > 16 ) { printf( "The number of cofactoring variables should be less than 17.\n" ); return NULL; } vSupp = Aig_Support( p, Aig_ObjFanin0(Aig_ManCo(p,0)) ); if ( Vec_PtrSize(vSupp) == 0 ) { printf( "Property output function is a constant.\n" ); Vec_PtrFree( vSupp ); return NULL; } dd = Aig_ManBuildPoBdd( p, &bFunc ); // bFunc is referenced if ( fVerbose ) printf( "Support =%5d. BDD size =%6d. ", Vec_PtrSize(vSupp), Cudd_DagSize(bFunc) ); vSubs = Aig_ManVecRandSubset( vSupp, nVars ); // replace nodes by their BDD variables Vec_PtrForEachEntry( Aig_Obj_t *, vSubs, pNode, i ) Vec_PtrWriteEntry( vSubs, i, pNode->pData ); // derive cofactors and functions vCofs = Aig_ManCofactorBdds( p, vSubs, dd, bFunc ); pRes = Aig_ManConvertBddsToAigs( p, dd, vCofs ); Vec_PtrFree( vSupp ); Vec_PtrFree( vSubs ); if ( fVerbose ) printf( "Created %d cofactors (out of %d). ", Saig_ManPoNum(pRes), Vec_PtrSize(vCofs) ); if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // dereference Cudd_RecursiveDeref( dd, bFunc ); Vec_PtrForEachEntry( DdNode *, vCofs, bFunc, i ) Cudd_RecursiveDeref( dd, bFunc ); Vec_PtrFree( vCofs ); Extra_StopManager( dd ); return pRes; } #else Aig_Man_t * Aig_ManSplit( Aig_Man_t * p, int nVars, int fVerbose ) { return NULL; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigTable.c000066400000000000000000000203651477524141600161510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigTable.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Structural hashing table.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigTable.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // hashing the node static unsigned long Aig_Hash( Aig_Obj_t * pObj, int TableSize ) { unsigned long Key = Aig_ObjIsExor(pObj) * 1699; Key ^= Aig_ObjFanin0(pObj)->Id * 7937; Key ^= Aig_ObjFanin1(pObj)->Id * 2971; Key ^= Aig_ObjFaninC0(pObj) * 911; Key ^= Aig_ObjFaninC1(pObj) * 353; return Key % TableSize; } // returns the place where this node is stored (or should be stored) static Aig_Obj_t ** Aig_TableFind( Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t ** ppEntry; assert( Aig_ObjChild0(pObj) && Aig_ObjChild1(pObj) ); assert( Aig_ObjFanin0(pObj)->Id < Aig_ObjFanin1(pObj)->Id ); for ( ppEntry = p->pTable + Aig_Hash(pObj, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext ) if ( *ppEntry == pObj ) return ppEntry; assert( *ppEntry == NULL ); return ppEntry; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Resizes the table.] Description [Typically this procedure should not be called.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_TableResize( Aig_Man_t * p ) { Aig_Obj_t * pEntry, * pNext; Aig_Obj_t ** pTableOld, ** ppPlace; int nTableSizeOld, Counter, i; abctime clk; assert( p->pTable != NULL ); clk = Abc_Clock(); // save the old table pTableOld = p->pTable; nTableSizeOld = p->nTableSize; // get the new table p->nTableSize = Abc_PrimeCudd( 2 * Aig_ManNodeNum(p) ); p->pTable = ABC_ALLOC( Aig_Obj_t *, p->nTableSize ); memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); // rehash the entries from the old table Counter = 0; for ( i = 0; i < nTableSizeOld; i++ ) for ( pEntry = pTableOld[i], pNext = pEntry? pEntry->pNext : NULL; pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL ) { // get the place where this entry goes in the table ppPlace = Aig_TableFind( p, pEntry ); assert( *ppPlace == NULL ); // should not be there // add the entry to the list *ppPlace = pEntry; pEntry->pNext = NULL; Counter++; } assert( Counter == Aig_ManNodeNum(p) ); // printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); // ABC_PRT( "Time", Abc_Clock() - clk ); // replace the table and the parameters ABC_FREE( pTableOld ); } /**Function************************************************************* Synopsis [Checks if node with the given attributes is in the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost ) { Aig_Obj_t * pEntry; assert( !Aig_IsComplement(pGhost) ); assert( Aig_ObjIsNode(pGhost) ); assert( Aig_ObjChild0(pGhost) && Aig_ObjChild1(pGhost) ); assert( Aig_ObjFanin0(pGhost)->Id < Aig_ObjFanin1(pGhost)->Id ); if ( p->pTable == NULL || !Aig_ObjRefs(Aig_ObjFanin0(pGhost)) || !Aig_ObjRefs(Aig_ObjFanin1(pGhost)) ) return NULL; for ( pEntry = p->pTable[Aig_Hash(pGhost, p->nTableSize)]; pEntry; pEntry = pEntry->pNext ) { if ( Aig_ObjChild0(pEntry) == Aig_ObjChild0(pGhost) && Aig_ObjChild1(pEntry) == Aig_ObjChild1(pGhost) && Aig_ObjType(pEntry) == Aig_ObjType(pGhost) ) return pEntry; } return NULL; } /**Function************************************************************* Synopsis [Checks if node with the given attributes is in the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_TableLookupTwo( Aig_Man_t * p, Aig_Obj_t * pFanin0, Aig_Obj_t * pFanin1 ) { Aig_Obj_t * pGhost; // consider simple cases if ( pFanin0 == pFanin1 ) return pFanin0; if ( pFanin0 == Aig_Not(pFanin1) ) return Aig_ManConst0(p); if ( Aig_Regular(pFanin0) == Aig_ManConst1(p) ) return pFanin0 == Aig_ManConst1(p) ? pFanin1 : Aig_ManConst0(p); if ( Aig_Regular(pFanin1) == Aig_ManConst1(p) ) return pFanin1 == Aig_ManConst1(p) ? pFanin0 : Aig_ManConst0(p); pGhost = Aig_ObjCreateGhost( p, pFanin0, pFanin1, AIG_OBJ_AND ); return Aig_TableLookup( p, pGhost ); } /**Function************************************************************* Synopsis [Adds the new node to the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t ** ppPlace; assert( !Aig_IsComplement(pObj) ); assert( Aig_TableLookup(p, pObj) == NULL ); if ( (pObj->Id & 0xFF) == 0 && 2 * p->nTableSize < Aig_ManNodeNum(p) ) Aig_TableResize( p ); ppPlace = Aig_TableFind( p, pObj ); assert( *ppPlace == NULL ); *ppPlace = pObj; } /**Function************************************************************* Synopsis [Deletes the node from the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t ** ppPlace; assert( !Aig_IsComplement(pObj) ); ppPlace = Aig_TableFind( p, pObj ); assert( *ppPlace == pObj ); // node should be in the table // remove the node *ppPlace = pObj->pNext; pObj->pNext = NULL; } /**Function************************************************************* Synopsis [Count the number of nodes in the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_TableCountEntries( Aig_Man_t * p ) { Aig_Obj_t * pEntry; int i, Counter = 0; for ( i = 0; i < p->nTableSize; i++ ) for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) Counter++; return Counter; } /**Function******************************************************************** Synopsis [Profiles the hash table.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Aig_TableProfile( Aig_Man_t * p ) { Aig_Obj_t * pEntry; int i, Counter; printf( "Table size = %d. Entries = %d.\n", p->nTableSize, Aig_ManNodeNum(p) ); for ( i = 0; i < p->nTableSize; i++ ) { Counter = 0; for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) Counter++; if ( Counter ) printf( "%d ", Counter ); } } /**Function******************************************************************** Synopsis [Profiles the hash table.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Aig_TableClear( Aig_Man_t * p ) { ABC_FREE( p->pTable ); p->nTableSize = 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigTest.c000066400000000000000000000012511477524141600160320ustar00rootroot00000000000000 #include "aig.h" ABC_NAMESPACE_IMPL_START void Aig_ProcedureTest() { Aig_Man_t * p; Aig_Obj_t * pA, * pB, * pC; Aig_Obj_t * pFunc; Aig_Obj_t * pFunc2; p = Aig_ManStart( 1000 ); pA = Aig_IthVar( p, 0 ); pB = Aig_IthVar( p, 1 ); pC = Aig_IthVar( p, 2 ); pFunc = Aig_Mux( p, pA, pB, pC ); pFunc2 = Aig_And( p, pA, pB ); Aig_ObjCreatePo( p, pFunc ); Aig_ObjCreatePo( p, pFunc2 ); Aig_ManSetRegNum( p, 1 ); Aig_ManCleanup( p ); if ( !Aig_ManCheck( p ) ) { printf( "Check has failed\n" ); } Aig_ManDumpBlif( p, "aig_test_file.blif", NULL, NULL ); Aig_ManStop( p ); }ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigTiming.c000066400000000000000000000257161477524141600163560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigTiming.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Incremental updating of direct/reverse AIG levels.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigTiming.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the reverse level of the node.] Description [The reverse level is the level of the node in reverse topological order, starting from the COs.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_ObjReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert( p->vLevelR ); Vec_IntFillExtra( p->vLevelR, pObj->Id + 1, 0 ); return Vec_IntEntry(p->vLevelR, pObj->Id); } /**Function************************************************************* Synopsis [Sets the reverse level of the node.] Description [The reverse level is the level of the node in reverse topological order, starting from the COs.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Aig_ObjSetReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj, int LevelR ) { assert( p->vLevelR ); Vec_IntFillExtra( p->vLevelR, pObj->Id + 1, 0 ); Vec_IntWriteEntry( p->vLevelR, pObj->Id, LevelR ); } /**Function************************************************************* Synopsis [Resets reverse level of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjClearReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_ObjSetReverseLevel( p, pObj, 0 ); } /**Function************************************************************* Synopsis [Returns required level of the node.] Description [Converts the reverse levels of the node into its required level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjRequiredLevel( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert( p->vLevelR ); return p->nLevelMax + 1 - Aig_ObjReverseLevel(p, pObj); } /**Function************************************************************* Synopsis [Computes the reverse level of the node using its fanout levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjReverseLevelNew( Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pFanout; int i, iFanout = -1, LevelCur, Level = 0; Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) { LevelCur = Aig_ObjReverseLevel( p, pFanout ); Level = Abc_MaxInt( Level, LevelCur ); } return Level + 1; } /**Function************************************************************* Synopsis [Prepares for the computation of required levels.] Description [This procedure should be called before the required times are used. It starts internal data structures, which records the level from the COs of the network nodes in reverse topologogical order.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManStartReverseLevels( Aig_Man_t * p, int nMaxLevelIncrease ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; assert( p->pFanData != NULL ); assert( p->vLevelR == NULL ); // remember the maximum number of direct levels p->nLevelMax = Aig_ManLevels(p) + nMaxLevelIncrease; // start the reverse levels p->vLevelR = Vec_IntAlloc( 0 ); Vec_IntFill( p->vLevelR, Aig_ManObjNumMax(p), 0 ); // compute levels in reverse topological order vNodes = Aig_ManDfsReverse( p ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { assert( pObj->fMarkA == 0 ); Aig_ObjSetReverseLevel( p, pObj, Aig_ObjReverseLevelNew(p, pObj) ); } Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Cleans the data structures used to compute required levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManStopReverseLevels( Aig_Man_t * p ) { assert( p->vLevelR != NULL ); Vec_IntFree( p->vLevelR ); p->vLevelR = NULL; p->nLevelMax = 0; } /**Function************************************************************* Synopsis [Incrementally updates level of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManUpdateLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ) { Aig_Obj_t * pFanout, * pTemp; int iFanout = -1, LevelOld, Lev, k, m; assert( p->pFanData != NULL ); assert( Aig_ObjIsNode(pObjNew) ); // allocate level if needed if ( p->vLevels == NULL ) p->vLevels = Vec_VecAlloc( Aig_ManLevels(p) + 8 ); // check if level has changed LevelOld = Aig_ObjLevel(pObjNew); if ( LevelOld == Aig_ObjLevelNew(pObjNew) ) return; // start the data structure for level update // we cannot fail to visit a node when using this structure because the // nodes are stored by their _old_ levels, which are assumed to be correct Vec_VecClear( p->vLevels ); Vec_VecPush( p->vLevels, LevelOld, pObjNew ); pObjNew->fMarkA = 1; // recursively update level Vec_VecForEachEntryStart( Aig_Obj_t *, p->vLevels, pTemp, Lev, k, LevelOld ) { pTemp->fMarkA = 0; assert( Aig_ObjLevel(pTemp) == Lev ); pTemp->Level = Aig_ObjLevelNew(pTemp); // if the level did not change, no need to check the fanout levels if ( Aig_ObjLevel(pTemp) == Lev ) continue; // schedule fanout for level update Aig_ObjForEachFanout( p, pTemp, pFanout, iFanout, m ) { if ( Aig_ObjIsNode(pFanout) && !pFanout->fMarkA ) { assert( Aig_ObjLevel(pFanout) >= Lev ); Vec_VecPush( p->vLevels, Aig_ObjLevel(pFanout), pFanout ); pFanout->fMarkA = 1; } } } } /**Function************************************************************* Synopsis [Incrementally updates level of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManUpdateReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ) { Aig_Obj_t * pFanin, * pTemp; int LevelOld, LevFanin, Lev, k; assert( p->vLevelR != NULL ); assert( Aig_ObjIsNode(pObjNew) ); // allocate level if needed if ( p->vLevels == NULL ) p->vLevels = Vec_VecAlloc( Aig_ManLevels(p) + 8 ); // check if level has changed LevelOld = Aig_ObjReverseLevel(p, pObjNew); if ( LevelOld == Aig_ObjReverseLevelNew(p, pObjNew) ) return; // start the data structure for level update // we cannot fail to visit a node when using this structure because the // nodes are stored by their _old_ levels, which are assumed to be correct Vec_VecClear( p->vLevels ); Vec_VecPush( p->vLevels, LevelOld, pObjNew ); pObjNew->fMarkA = 1; // recursively update level Vec_VecForEachEntryStart( Aig_Obj_t *, p->vLevels, pTemp, Lev, k, LevelOld ) { pTemp->fMarkA = 0; LevelOld = Aig_ObjReverseLevel(p, pTemp); assert( LevelOld == Lev ); Aig_ObjSetReverseLevel( p, pTemp, Aig_ObjReverseLevelNew(p, pTemp) ); // if the level did not change, to need to check the fanout levels if ( Aig_ObjReverseLevel(p, pTemp) == Lev ) continue; // schedule fanins for level update pFanin = Aig_ObjFanin0(pTemp); if ( Aig_ObjIsNode(pFanin) && !pFanin->fMarkA ) { LevFanin = Aig_ObjReverseLevel( p, pFanin ); assert( LevFanin >= Lev ); Vec_VecPush( p->vLevels, LevFanin, pFanin ); pFanin->fMarkA = 1; } pFanin = Aig_ObjFanin1(pTemp); if ( Aig_ObjIsNode(pFanin) && !pFanin->fMarkA ) { LevFanin = Aig_ObjReverseLevel( p, pFanin ); assert( LevFanin >= Lev ); Vec_VecPush( p->vLevels, LevFanin, pFanin ); pFanin->fMarkA = 1; } } } /**Function************************************************************* Synopsis [Verifies direct level of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManVerifyLevel( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, Counter = 0; assert( p->pFanData ); Aig_ManForEachNode( p, pObj, i ) if ( Aig_ObjLevel(pObj) != Aig_ObjLevelNew(pObj) ) { printf( "Level of node %6d should be %4d instead of %4d.\n", pObj->Id, Aig_ObjLevelNew(pObj), Aig_ObjLevel(pObj) ); Counter++; } if ( Counter ) printf( "Levels of %d nodes are incorrect.\n", Counter ); } /**Function************************************************************* Synopsis [Verifies reverse level of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManVerifyReverseLevel( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, Counter = 0; assert( p->vLevelR ); Aig_ManForEachNode( p, pObj, i ) if ( Aig_ObjLevel(pObj) != Aig_ObjLevelNew(pObj) ) { printf( "Reverse level of node %6d should be %4d instead of %4d.\n", pObj->Id, Aig_ObjReverseLevelNew(p, pObj), Aig_ObjReverseLevel(p, pObj) ); Counter++; } if ( Counter ) printf( "Reverse levels of %d nodes are incorrect.\n", Counter ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigTruth.c000066400000000000000000000070701477524141600162260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigTruth.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Computes truth table for the cut.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigTruth.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes truth table of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Aig_ManCutTruthOne( Aig_Obj_t * pNode, unsigned * pTruth, int nWords ) { unsigned * pTruth0, * pTruth1; int i; pTruth0 = (unsigned *)Aig_ObjFanin0(pNode)->pData; pTruth1 = (unsigned *)Aig_ObjFanin1(pNode)->pData; if ( Aig_ObjIsExor(pNode) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] ^ pTruth1[i]; else if ( !Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] & pTruth1[i]; else if ( !Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] & ~pTruth1[i]; else if ( Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = ~pTruth0[i] & pTruth1[i]; else // if ( Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; return pTruth; } /**Function************************************************************* Synopsis [Computes truth table of the cut.] Description [The returned pointer should be used immediately.] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Aig_ManCutTruth( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore ) { Aig_Obj_t * pObj; int i, nWords; assert( Vec_PtrSize(vLeaves) <= Vec_PtrSize(vTruthElem) ); assert( Vec_PtrSize(vNodes) <= Vec_PtrSize(vTruthStore) ); assert( Vec_PtrSize(vNodes) == 0 || pRoot == Vec_PtrEntryLast(vNodes) ); // assign elementary truth tables Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) pObj->pData = Vec_PtrEntry( vTruthElem, i ); // compute truths for other nodes nWords = Abc_TruthWordNum( Vec_PtrSize(vLeaves) ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) pObj->pData = Aig_ManCutTruthOne( pObj, (unsigned *)Vec_PtrEntry(vTruthStore, i), nWords ); return (unsigned *)pRoot->pData; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigTsim.c000066400000000000000000000377231477524141600160440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigTsim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Ternary simulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigTsim.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" #include "aig/saig/saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define TSI_MAX_ROUNDS 1000 #define TSI_ONE_SERIES 300 #define AIG_XVS0 1 #define AIG_XVS1 2 #define AIG_XVSX 3 static inline void Aig_ObjSetXsim( Aig_Obj_t * pObj, int Value ) { pObj->nCuts = Value; } static inline int Aig_ObjGetXsim( Aig_Obj_t * pObj ) { return pObj->nCuts; } static inline int Aig_XsimInv( int Value ) { if ( Value == AIG_XVS0 ) return AIG_XVS1; if ( Value == AIG_XVS1 ) return AIG_XVS0; assert( Value == AIG_XVSX ); return AIG_XVSX; } static inline int Aig_XsimAnd( int Value0, int Value1 ) { if ( Value0 == AIG_XVS0 || Value1 == AIG_XVS0 ) return AIG_XVS0; if ( Value0 == AIG_XVSX || Value1 == AIG_XVSX ) return AIG_XVSX; assert( Value0 == AIG_XVS1 && Value1 == AIG_XVS1 ); return AIG_XVS1; } static inline int Aig_XsimRand2() { return (Aig_ManRandom(0) & 1) ? AIG_XVS1 : AIG_XVS0; } static inline int Aig_XsimRand3() { int RetValue; do { RetValue = Aig_ManRandom(0) & 3; } while ( RetValue == 0 ); return RetValue; } static inline int Aig_ObjGetXsimFanin0( Aig_Obj_t * pObj ) { int RetValue; RetValue = Aig_ObjGetXsim(Aig_ObjFanin0(pObj)); return Aig_ObjFaninC0(pObj)? Aig_XsimInv(RetValue) : RetValue; } static inline int Aig_ObjGetXsimFanin1( Aig_Obj_t * pObj ) { int RetValue; RetValue = Aig_ObjGetXsim(Aig_ObjFanin1(pObj)); return Aig_ObjFaninC1(pObj)? Aig_XsimInv(RetValue) : RetValue; } static inline void Aig_XsimPrint( FILE * pFile, int Value ) { if ( Value == AIG_XVS0 ) { fprintf( pFile, "0" ); return; } if ( Value == AIG_XVS1 ) { fprintf( pFile, "1" ); return; } assert( Value == AIG_XVSX ); fprintf( pFile, "x" ); } // simulation manager typedef struct Aig_Tsi_t_ Aig_Tsi_t; struct Aig_Tsi_t_ { Aig_Man_t * pAig; // the original AIG manager // ternary state representation int nWords; // the number of words in the states Vec_Ptr_t * vStates; // the collection of ternary states Aig_MmFixed_t * pMem; // memory for ternary states // hash table for terminary states unsigned ** pBins; int nBins; }; static inline unsigned * Aig_TsiNext( unsigned * pState, int nWords ) { return *((unsigned **)(pState + nWords)); } static inline void Aig_TsiSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Tsi_t * Aig_TsiStart( Aig_Man_t * pAig ) { Aig_Tsi_t * p; p = ABC_ALLOC( Aig_Tsi_t, 1 ); memset( p, 0, sizeof(Aig_Tsi_t) ); p->pAig = pAig; p->nWords = Abc_BitWordNum( 2*Aig_ManRegNum(pAig) ); p->vStates = Vec_PtrAlloc( 1000 ); p->pMem = Aig_MmFixedStart( sizeof(unsigned) * p->nWords + sizeof(unsigned *), 10000 ); p->nBins = Abc_PrimeCudd(TSI_MAX_ROUNDS/2); p->pBins = ABC_ALLOC( unsigned *, p->nBins ); memset( p->pBins, 0, sizeof(unsigned *) * p->nBins ); return p; } /**Function************************************************************* Synopsis [Deallocates simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_TsiStop( Aig_Tsi_t * p ) { Aig_MmFixedStop( p->pMem, 0 ); Vec_PtrFree( p->vStates ); ABC_FREE( p->pBins ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Computes hash value of the node using its simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_TsiStateHash( unsigned * pState, int nWords, int nTableSize ) { static int s_FPrimes[128] = { 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 }; unsigned uHash; int i; uHash = 0; for ( i = 0; i < nWords; i++ ) uHash ^= pState[i] * s_FPrimes[i & 0x7F]; return uHash % nTableSize; } /**Function************************************************************* Synopsis [Inserts value into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_TsiStateLookup( Aig_Tsi_t * p, unsigned * pState, int nWords ) { unsigned * pEntry; int Hash; Hash = Aig_TsiStateHash( pState, nWords, p->nBins ); for ( pEntry = p->pBins[Hash]; pEntry; pEntry = Aig_TsiNext(pEntry, nWords) ) if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) ) return 1; return 0; } /**Function************************************************************* Synopsis [Inserts value into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_TsiStateInsert( Aig_Tsi_t * p, unsigned * pState, int nWords ) { int Hash = Aig_TsiStateHash( pState, nWords, p->nBins ); assert( !Aig_TsiStateLookup( p, pState, nWords ) ); Aig_TsiSetNext( pState, nWords, p->pBins[Hash] ); p->pBins[Hash] = pState; } /**Function************************************************************* Synopsis [Inserts value into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Aig_TsiStateNew( Aig_Tsi_t * p ) { unsigned * pState; pState = (unsigned *)Aig_MmFixedEntryFetch( p->pMem ); memset( pState, 0, sizeof(unsigned) * p->nWords ); Vec_PtrPush( p->vStates, pState ); return pState; } /**Function************************************************************* Synopsis [Inserts value into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_TsiStatePrint( Aig_Tsi_t * p, unsigned * pState ) { int i, Value, nZeros = 0, nOnes = 0, nDcs = 0; for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) { Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); if ( Value == 1 ) printf( "0" ), nZeros++; else if ( Value == 2 ) printf( "1" ), nOnes++; else if ( Value == 3 ) printf( "x" ), nDcs++; else assert( 0 ); } printf( " (0=%5d, 1=%5d, x=%5d)\n", nZeros, nOnes, nDcs ); } /**Function************************************************************* Synopsis [Count constant values in the state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_TsiStateCount( Aig_Tsi_t * p, unsigned * pState ) { Aig_Obj_t * pObjLi, * pObjLo; int i, Value, nCounter = 0; Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i ) { Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); nCounter += (Value == 1 || Value == 2); } return nCounter; } /**Function************************************************************* Synopsis [Count constant values in the state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_TsiStateOrAll( Aig_Tsi_t * pTsi, unsigned * pState ) { unsigned * pPrev; int i, k; Vec_PtrForEachEntry( unsigned *, pTsi->vStates, pPrev, i ) { for ( k = 0; k < pTsi->nWords; k++ ) pState[k] |= pPrev[k]; } } /**Function************************************************************* Synopsis [Cycles the circuit to create a new initial state.] Description [Simulates the circuit with random input for the given number of timeframes to get a better initial state.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManTernarySimulate( Aig_Man_t * p, int fVerbose, int fVeryVerbose ) { Aig_Tsi_t * pTsi; Vec_Ptr_t * vMap; Aig_Obj_t * pObj, * pObjLi, * pObjLo; unsigned * pState;//, * pPrev; int i, f, fConstants, Value, nCounter, nRetired; // allocate the simulation manager pTsi = Aig_TsiStart( p ); // initialize the values Aig_ObjSetXsim( Aig_ManConst1(p), AIG_XVS1 ); Aig_ManForEachPiSeq( p, pObj, i ) Aig_ObjSetXsim( pObj, AIG_XVSX ); Aig_ManForEachLoSeq( p, pObj, i ) Aig_ObjSetXsim( pObj, AIG_XVS0 ); // simulate for the given number of timeframes for ( f = 0; f < TSI_MAX_ROUNDS; f++ ) { // collect this state pState = Aig_TsiStateNew( pTsi ); Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) { Value = Aig_ObjGetXsim(pObjLo); if ( Value & 1 ) Abc_InfoSetBit( pState, 2 * i ); if ( Value & 2 ) Abc_InfoSetBit( pState, 2 * i + 1 ); } // printf( "%d ", Aig_TsiStateCount(pTsi, pState) ); if ( fVeryVerbose ) { printf( "%3d : ", f ); Aig_TsiStatePrint( pTsi, pState ); } // check if this state exists if ( Aig_TsiStateLookup( pTsi, pState, pTsi->nWords ) ) break; // nCounter = 0; // Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) // nCounter += (Aig_ObjGetXsim(pObjLo) == AIG_XVS0); //printf( "%d -> ", nCounter ); // insert this state Aig_TsiStateInsert( pTsi, pState, pTsi->nWords ); // simulate internal nodes Aig_ManForEachNode( p, pObj, i ) { Aig_ObjSetXsim( pObj, Aig_XsimAnd(Aig_ObjGetXsimFanin0(pObj), Aig_ObjGetXsimFanin1(pObj)) ); // printf( "%d %d Id = %2d. Value = %d.\n", // Aig_ObjGetXsimFanin0(pObj), Aig_ObjGetXsimFanin1(pObj), // i, Aig_XsimAnd(Aig_ObjGetXsimFanin0(pObj), Aig_ObjGetXsimFanin1(pObj)) ); } // transfer the latch values Aig_ManForEachLiSeq( p, pObj, i ) Aig_ObjSetXsim( pObj, Aig_ObjGetXsimFanin0(pObj) ); nCounter = 0; nRetired = 0; Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) { if ( f < TSI_ONE_SERIES ) Aig_ObjSetXsim( pObjLo, Aig_ObjGetXsim(pObjLi) ); else { if ( Aig_ObjGetXsim(pObjLi) != Aig_ObjGetXsim(pObjLo) ) { Aig_ObjSetXsim( pObjLo, AIG_XVSX ); nRetired++; } } nCounter += (Aig_ObjGetXsim(pObjLo) == AIG_XVS0); } // if ( nRetired ) // printf( "Retired %d registers.\n", nRetired ); // if ( f && (f % 1000 == 0) ) // printf( "%d \n", f ); //printf( "%d ", nCounter ); } //printf( "\n" ); if ( f == TSI_MAX_ROUNDS ) { printf( "Aig_ManTernarySimulate(): Did not reach a fixed point after %d iterations (not a bug).\n", TSI_MAX_ROUNDS ); Aig_TsiStop( pTsi ); return NULL; } // OR all the states pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, 0 ); Aig_TsiStateOrAll( pTsi, pState ); // check if there are constants fConstants = 0; if ( 2*Aig_ManRegNum(p) == 32*pTsi->nWords ) { for ( i = 0; i < pTsi->nWords; i++ ) if ( pState[i] != ~0 ) fConstants = 1; } else { for ( i = 0; i < pTsi->nWords - 1; i++ ) if ( pState[i] != ~0 ) fConstants = 1; if ( pState[i] != Abc_InfoMask( 2*Aig_ManRegNum(p) - 32*(pTsi->nWords-1) ) ) fConstants = 1; } if ( fConstants == 0 ) { if ( fVerbose ) printf( "Detected 0 constants after %d iterations of ternary simulation.\n", f ); Aig_TsiStop( pTsi ); return NULL; } // start mapping by adding the true PIs vMap = Vec_PtrAlloc( Aig_ManCiNum(p) ); Aig_ManForEachPiSeq( p, pObj, i ) Vec_PtrPush( vMap, pObj ); // find constant registers nCounter = 0; Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) { Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); nCounter += (Value == 1 || Value == 2); if ( Value == 1 ) Vec_PtrPush( vMap, Aig_ManConst0(p) ); else if ( Value == 2 ) Vec_PtrPush( vMap, Aig_ManConst1(p) ); else if ( Value == 3 ) Vec_PtrPush( vMap, pObjLo ); else assert( 0 ); // Aig_XsimPrint( stdout, Value ); } // printf( "\n" ); Aig_TsiStop( pTsi ); if ( fVerbose ) printf( "Detected %d constants after %d iterations of ternary simulation.\n", nCounter, f ); return vMap; } /**Function************************************************************* Synopsis [Reduces the circuit using ternary simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManConstReduce( Aig_Man_t * p, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose ) { Aig_Man_t * pTemp; Vec_Ptr_t * vMap; while ( Aig_ManRegNum(p) > 0 ) { if ( fUseMvSweep ) vMap = Saig_MvManSimulate( p, nFramesSymb, nFramesSatur, fVerbose, fVeryVerbose ); else vMap = Aig_ManTernarySimulate( p, fVerbose, fVeryVerbose ); if ( vMap == NULL ) break; p = Aig_ManRemap( pTemp = p, vMap ); Vec_PtrFree( vMap ); Aig_ManSeqCleanup( p ); if ( fVerbose ) Aig_ManReportImprovement( pTemp, p ); Aig_ManStop( pTemp ); } return p; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigUtil.c000066400000000000000000001376221477524141600160440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Various procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Increments the current traversal ID of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManIncrementTravId( Aig_Man_t * p ) { if ( p->nTravIds >= (1<<30)-1 ) Aig_ManCleanData( p ); p->nTravIds++; } /**Function************************************************************* Synopsis [Returns the time stamp.] Description [The file should be closed.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Aig_TimeStamp() { static char Buffer[100]; char * TimeStamp; time_t ltime; // get the current time time( <ime ); TimeStamp = asctime( localtime( <ime ) ); TimeStamp[ strlen(TimeStamp) - 1 ] = 0; strcpy( Buffer, TimeStamp ); return Buffer; } /**Function************************************************************* Synopsis [Make sure AIG has not gaps in the numeric order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManHasNoGaps( Aig_Man_t * p ) { return (int)(Aig_ManObjNum(p) == Aig_ManCiNum(p) + Aig_ManCoNum(p) + Aig_ManNodeNum(p) + 1); } /**Function************************************************************* Synopsis [Collect the latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManLevels( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, LevelMax = 0; Aig_ManForEachCo( p, pObj, i ) LevelMax = Abc_MaxInt( LevelMax, (int)Aig_ObjFanin0(pObj)->Level ); return LevelMax; } /**Function************************************************************* Synopsis [Reset reference counters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManResetRefs( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManForEachObj( p, pObj, i ) pObj->nRefs = 0; Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjFanin0(pObj) ) Aig_ObjFanin0(pObj)->nRefs++; if ( Aig_ObjFanin1(pObj) ) Aig_ObjFanin1(pObj)->nRefs++; } } /**Function************************************************************* Synopsis [Cleans fMarkA.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManCleanMarkA( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManForEachObj( p, pObj, i ) pObj->fMarkA = 0; } /**Function************************************************************* Synopsis [Cleans fMarkB.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManCleanMarkB( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManForEachObj( p, pObj, i ) pObj->fMarkB = 0; } /**Function************************************************************* Synopsis [Cleans fMarkB.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManCleanMarkAB( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManForEachObj( p, pObj, i ) pObj->fMarkA = pObj->fMarkB = 0; } /**Function************************************************************* Synopsis [Cleans the data pointers for the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManCleanData( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManForEachObj( p, pObj, i ) pObj->pData = NULL; } /**Function************************************************************* Synopsis [Cleans the data pointers for the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManCleanNext( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManForEachObj( p, pObj, i ) pObj->pNext = NULL; } /**Function************************************************************* Synopsis [Recursively cleans the data pointers in the cone of the node.] Description [Applicable to small AIGs only because no caching is performed.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjCleanData_rec( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); assert( !Aig_ObjIsCo(pObj) ); if ( Aig_ObjIsAnd(pObj) ) { Aig_ObjCleanData_rec( Aig_ObjFanin0(pObj) ); Aig_ObjCleanData_rec( Aig_ObjFanin1(pObj) ); } pObj->pData = NULL; } /**Function************************************************************* Synopsis [Detects multi-input gate rooted at this node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjCollectMulti_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) { if ( pRoot != pObj && (Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) || Aig_ObjType(pRoot) != Aig_ObjType(pObj)) ) { Vec_PtrPushUnique(vSuper, pObj); return; } Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild0(pObj), vSuper ); Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild1(pObj), vSuper ); } /**Function************************************************************* Synopsis [Detects multi-input gate rooted at this node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjCollectMulti( Aig_Obj_t * pRoot, Vec_Ptr_t * vSuper ) { assert( !Aig_IsComplement(pRoot) ); Vec_PtrClear( vSuper ); Aig_ObjCollectMulti_rec( pRoot, pRoot, vSuper ); } /**Function************************************************************* Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjIsMuxType( Aig_Obj_t * pNode ) { Aig_Obj_t * pNode0, * pNode1; // check that the node is regular assert( !Aig_IsComplement(pNode) ); // if the node is not AND, this is not MUX if ( !Aig_ObjIsAnd(pNode) ) return 0; // if the children are not complemented, this is not MUX if ( !Aig_ObjFaninC0(pNode) || !Aig_ObjFaninC1(pNode) ) return 0; // get children pNode0 = Aig_ObjFanin0(pNode); pNode1 = Aig_ObjFanin1(pNode); // if the children are not ANDs, this is not MUX if ( !Aig_ObjIsAnd(pNode0) || !Aig_ObjIsAnd(pNode1) ) return 0; // otherwise the node is MUX iff it has a pair of equal grandchildren return (Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1))) || (Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1))) || (Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1))) || (Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1))); } /**Function************************************************************* Synopsis [Recognizes what nodes are inputs of the EXOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ) { Aig_Obj_t * p0, * p1; assert( !Aig_IsComplement(pObj) ); if ( !Aig_ObjIsNode(pObj) ) return 0; if ( Aig_ObjIsExor(pObj) ) { *ppFan0 = Aig_ObjChild0(pObj); *ppFan1 = Aig_ObjChild1(pObj); return 1; } assert( Aig_ObjIsAnd(pObj) ); p0 = Aig_ObjChild0(pObj); p1 = Aig_ObjChild1(pObj); if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) ) return 0; p0 = Aig_Regular(p0); p1 = Aig_Regular(p1); if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) ) return 0; if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) ) return 0; if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) ) return 0; *ppFan0 = Aig_ObjChild0(p0); *ppFan1 = Aig_ObjChild1(p0); return 1; } /**Function************************************************************* Synopsis [Recognizes what nodes are control and data inputs of a MUX.] Description [If the node is a MUX, returns the control variable C. Assigns nodes T and E to be the then and else variables of the MUX. Node C is never complemented. Nodes T and E can be complemented. This function also recognizes EXOR/NEXOR gates as MUXes.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ObjRecognizeMux( Aig_Obj_t * pNode, Aig_Obj_t ** ppNodeT, Aig_Obj_t ** ppNodeE ) { Aig_Obj_t * pNode0, * pNode1; assert( !Aig_IsComplement(pNode) ); assert( Aig_ObjIsMuxType(pNode) ); // get children pNode0 = Aig_ObjFanin0(pNode); pNode1 = Aig_ObjFanin1(pNode); // find the control variable if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p2) ) if ( Aig_ObjFaninC1(pNode0) ) { // pNode2->p2 is positive phase of C *ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); *ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); return Aig_ObjChild1(pNode1);//pNode2->p2; } else { // pNode1->p2 is positive phase of C *ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); *ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); return Aig_ObjChild1(pNode0);//pNode1->p2; } } else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p1) ) if ( Aig_ObjFaninC0(pNode0) ) { // pNode2->p1 is positive phase of C *ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); *ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); return Aig_ObjChild0(pNode1);//pNode2->p1; } else { // pNode1->p1 is positive phase of C *ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); *ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); return Aig_ObjChild0(pNode0);//pNode1->p1; } } else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p1) ) if ( Aig_ObjFaninC0(pNode0) ) { // pNode2->p2 is positive phase of C *ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); *ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); return Aig_ObjChild1(pNode1);//pNode2->p2; } else { // pNode1->p1 is positive phase of C *ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); *ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); return Aig_ObjChild0(pNode0);//pNode1->p1; } } else if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p2) ) if ( Aig_ObjFaninC1(pNode0) ) { // pNode2->p1 is positive phase of C *ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); *ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); return Aig_ObjChild0(pNode1);//pNode2->p1; } else { // pNode1->p2 is positive phase of C *ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); *ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); return Aig_ObjChild1(pNode0);//pNode1->p2; } } assert( 0 ); // this is not MUX return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Aig_ObjReal_rec( Aig_Obj_t * pObj ) { Aig_Obj_t * pObjNew, * pObjR = Aig_Regular(pObj); if ( !Aig_ObjIsBuf(pObjR) ) return pObj; pObjNew = Aig_ObjReal_rec( Aig_ObjChild0(pObjR) ); return Aig_NotCond( pObjNew, Aig_IsComplement(pObj) ); } /**Function************************************************************* Synopsis [Procedure used for sorting the nodes in increasing order of IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ObjCompareIdIncrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ) { int Diff = Aig_ObjId(*pp1) - Aig_ObjId(*pp2); if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; return 0; } /**Function************************************************************* Synopsis [Prints Eqn formula for the AIG rooted at this node.] Description [The formula is in terms of PIs, which should have their names assigned in pObj->pData fields.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjPrintEqn( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) { Vec_Ptr_t * vSuper; Aig_Obj_t * pFanin; int fCompl, i; // store the complemented attribute fCompl = Aig_IsComplement(pObj); pObj = Aig_Regular(pObj); // constant case if ( Aig_ObjIsConst1(pObj) ) { fprintf( pFile, "%d", !fCompl ); return; } // PI case if ( Aig_ObjIsCi(pObj) ) { fprintf( pFile, "%s%s", fCompl? "!" : "", (char*)pObj->pData ); return; } // AND case Vec_VecExpand( vLevels, Level ); vSuper = Vec_VecEntry(vLevels, Level); Aig_ObjCollectMulti( pObj, vSuper ); fprintf( pFile, "%s", (Level==0? "" : "(") ); Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) { Aig_ObjPrintEqn( pFile, Aig_NotCond(pFanin, fCompl), vLevels, Level+1 ); if ( i < Vec_PtrSize(vSuper) - 1 ) fprintf( pFile, " %s ", fCompl? "+" : "*" ); } fprintf( pFile, "%s", (Level==0? "" : ")") ); return; } /**Function************************************************************* Synopsis [Prints Verilog formula for the AIG rooted at this node.] Description [The formula is in terms of PIs, which should have their names assigned in pObj->pData fields.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) { Vec_Ptr_t * vSuper; Aig_Obj_t * pFanin, * pFanin0, * pFanin1, * pFaninC; int fCompl, i; // store the complemented attribute fCompl = Aig_IsComplement(pObj); pObj = Aig_Regular(pObj); // constant case if ( Aig_ObjIsConst1(pObj) ) { fprintf( pFile, "1\'b%d", !fCompl ); return; } // PI case if ( Aig_ObjIsCi(pObj) ) { fprintf( pFile, "%s%s", fCompl? "~" : "", (char*)pObj->pData ); return; } // EXOR case if ( Aig_ObjIsExor(pObj) ) { Vec_VecExpand( vLevels, Level ); vSuper = Vec_VecEntry( vLevels, Level ); Aig_ObjCollectMulti( pObj, vSuper ); fprintf( pFile, "%s", (Level==0? "" : "(") ); Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) { Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, (fCompl && i==0)), vLevels, Level+1 ); if ( i < Vec_PtrSize(vSuper) - 1 ) fprintf( pFile, " ^ " ); } fprintf( pFile, "%s", (Level==0? "" : ")") ); return; } // MUX case if ( Aig_ObjIsMuxType(pObj) ) { if ( Aig_ObjRecognizeExor( pObj, &pFanin0, &pFanin1 ) ) { fprintf( pFile, "%s", (Level==0? "" : "(") ); Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 ); fprintf( pFile, " ^ " ); Aig_ObjPrintVerilog( pFile, pFanin1, vLevels, Level+1 ); fprintf( pFile, "%s", (Level==0? "" : ")") ); } else { pFaninC = Aig_ObjRecognizeMux( pObj, &pFanin1, &pFanin0 ); fprintf( pFile, "%s", (Level==0? "" : "(") ); Aig_ObjPrintVerilog( pFile, pFaninC, vLevels, Level+1 ); fprintf( pFile, " ? " ); Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin1, fCompl), vLevels, Level+1 ); fprintf( pFile, " : " ); Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 ); fprintf( pFile, "%s", (Level==0? "" : ")") ); } return; } // AND case Vec_VecExpand( vLevels, Level ); vSuper = Vec_VecEntry(vLevels, Level); Aig_ObjCollectMulti( pObj, vSuper ); fprintf( pFile, "%s", (Level==0? "" : "(") ); Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) { Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, fCompl), vLevels, Level+1 ); if ( i < Vec_PtrSize(vSuper) - 1 ) fprintf( pFile, " %s ", fCompl? "|" : "&" ); } fprintf( pFile, "%s", (Level==0? "" : ")") ); return; } /**Function************************************************************* Synopsis [Prints node in HAIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig ) { assert( !Aig_IsComplement(pObj) ); printf( "Node %d : ", pObj->Id ); if ( Aig_ObjIsConst1(pObj) ) printf( "constant 1" ); else if ( Aig_ObjIsCi(pObj) ) printf( "CI" ); else if ( Aig_ObjIsCo(pObj) ) { printf( "CO( " ); printf( "%d%s )", Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " ") ); } else printf( "AND( %d%s, %d%s )", Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " "), Aig_ObjFanin1(pObj)->Id, (Aig_ObjFaninC1(pObj)? "\'" : " ") ); printf( " (refs = %3d)", Aig_ObjRefs(pObj) ); } void Aig_ObjPrintVerboseCone( Aig_Man_t * p, Aig_Obj_t * pRoot, int fHaig ) { extern Vec_Ptr_t * Aig_ManDfsArray( Aig_Man_t * p, Aig_Obj_t ** pNodes, int nNodes ); Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; vNodes = Aig_ManDfsArray( p, &pRoot, 1 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) Aig_ObjPrintVerbose( pObj, fHaig ), printf( "\n" ); printf( "\n" ); Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Prints node in HAIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj; int i; printf( "PIs: " ); Aig_ManForEachCi( p, pObj, i ) printf( " %p", pObj ); printf( "\n" ); vNodes = Aig_ManDfs( p, 0 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) Aig_ObjPrintVerbose( pObj, fHaig ), printf( "\n" ); printf( "\n" ); Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Write speculative miter for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManDump( Aig_Man_t * p ) { static int Counter = 0; char FileName[200]; // dump the logic into a file sprintf( FileName, "aigbug\\%03d.blif", ++Counter ); Aig_ManDumpBlif( p, FileName, NULL, NULL ); printf( "Intermediate AIG with %d nodes was written into file \"%s\".\n", Aig_ManNodeNum(p), FileName ); } /**Function************************************************************* Synopsis [Writes the AIG into a BLIF file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames ) { FILE * pFile; Vec_Ptr_t * vNodes; Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pConst1 = NULL; int i, nDigits, Counter = 0; if ( Aig_ManCoNum(p) == 0 ) { printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" ); return; } // check if constant is used Aig_ManForEachCo( p, pObj, i ) if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) pConst1 = Aig_ManConst1(p); // collect nodes in the DFS order vNodes = Aig_ManDfs( p, 1 ); // assign IDs to objects Aig_ManConst1(p)->iData = Counter++; Aig_ManForEachCi( p, pObj, i ) pObj->iData = Counter++; Aig_ManForEachCo( p, pObj, i ) pObj->iData = Counter++; Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) pObj->iData = Counter++; nDigits = Abc_Base10Log( Counter ); // write the file pFile = fopen( pFileName, "w" ); fprintf( pFile, "# BLIF file written by procedure Aig_ManDumpBlif()\n" ); // fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); fprintf( pFile, ".model %s\n", p->pName ); // write PIs fprintf( pFile, ".inputs" ); Aig_ManForEachPiSeq( p, pObj, i ) if ( vPiNames ) fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, i) ); else fprintf( pFile, " n%0*d", nDigits, pObj->iData ); fprintf( pFile, "\n" ); // write POs fprintf( pFile, ".outputs" ); Aig_ManForEachPoSeq( p, pObj, i ) if ( vPoNames ) fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPoNames, i) ); else fprintf( pFile, " n%0*d", nDigits, pObj->iData ); fprintf( pFile, "\n" ); // write latches if ( Aig_ManRegNum(p) ) { fprintf( pFile, "\n" ); Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) { fprintf( pFile, ".latch" ); if ( vPoNames ) fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPoNames, Aig_ManCoNum(p)-Aig_ManRegNum(p)+i) ); else fprintf( pFile, " n%0*d", nDigits, pObjLi->iData ); if ( vPiNames ) fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Aig_ManCiNum(p)-Aig_ManRegNum(p)+i) ); else fprintf( pFile, " n%0*d", nDigits, pObjLo->iData ); fprintf( pFile, " 0\n" ); } fprintf( pFile, "\n" ); } // write nodes if ( pConst1 ) fprintf( pFile, ".names n%0*d\n 1\n", nDigits, pConst1->iData ); Aig_ManSetCioIds( p ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { fprintf( pFile, ".names" ); if ( vPiNames && Aig_ObjIsCi(Aig_ObjFanin0(pObj)) ) fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Aig_ObjCioId(Aig_ObjFanin0(pObj))) ); else fprintf( pFile, " n%0*d", nDigits, Aig_ObjFanin0(pObj)->iData ); if ( vPiNames && Aig_ObjIsCi(Aig_ObjFanin1(pObj)) ) fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Aig_ObjCioId(Aig_ObjFanin1(pObj))) ); else fprintf( pFile, " n%0*d", nDigits, Aig_ObjFanin1(pObj)->iData ); fprintf( pFile, " n%0*d\n", nDigits, pObj->iData ); fprintf( pFile, "%d%d 1\n", !Aig_ObjFaninC0(pObj), !Aig_ObjFaninC1(pObj) ); } // write POs Aig_ManForEachCo( p, pObj, i ) { fprintf( pFile, ".names" ); if ( vPiNames && Aig_ObjIsCi(Aig_ObjFanin0(pObj)) ) fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Aig_ObjCioId(Aig_ObjFanin0(pObj))) ); else fprintf( pFile, " n%0*d", nDigits, Aig_ObjFanin0(pObj)->iData ); if ( vPoNames ) fprintf( pFile, " %s\n", (char*)Vec_PtrEntry(vPoNames, Aig_ObjCioId(pObj)) ); else fprintf( pFile, " n%0*d\n", nDigits, pObj->iData ); fprintf( pFile, "%d 1\n", !Aig_ObjFaninC0(pObj) ); } Aig_ManCleanCioIds( p ); fprintf( pFile, ".end\n\n" ); fclose( pFile ); Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Writes the AIG into a Verilog file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManDumpVerilog( Aig_Man_t * p, char * pFileName ) { FILE * pFile; Vec_Ptr_t * vNodes; Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pConst1 = NULL; int i, nDigits, Counter = 0; if ( Aig_ManCoNum(p) == 0 ) { printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" ); return; } // check if constant is used Aig_ManForEachCo( p, pObj, i ) if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) pConst1 = Aig_ManConst1(p); // collect nodes in the DFS order vNodes = Aig_ManDfs( p, 1 ); // assign IDs to objects Aig_ManConst1(p)->iData = Counter++; Aig_ManForEachCi( p, pObj, i ) pObj->iData = Counter++; Aig_ManForEachCo( p, pObj, i ) pObj->iData = Counter++; Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) pObj->iData = Counter++; nDigits = Abc_Base10Log( Counter ); // write the file pFile = fopen( pFileName, "w" ); fprintf( pFile, "// Verilog file written by procedure Aig_ManDumpVerilog()\n" ); // fprintf( pFile, "// http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); if ( Aig_ManRegNum(p) ) fprintf( pFile, "module %s ( clock", p->pName? p->pName: "test" ); else fprintf( pFile, "module %s (", p->pName? p->pName: "test" ); Aig_ManForEachPiSeq( p, pObj, i ) fprintf( pFile, "%s n%0*d", ((Aig_ManRegNum(p) || i)? ",":""), nDigits, pObj->iData ); Aig_ManForEachPoSeq( p, pObj, i ) fprintf( pFile, ", n%0*d", nDigits, pObj->iData ); fprintf( pFile, " );\n" ); // write PIs if ( Aig_ManRegNum(p) ) fprintf( pFile, "input clock;\n" ); Aig_ManForEachPiSeq( p, pObj, i ) fprintf( pFile, "input n%0*d;\n", nDigits, pObj->iData ); // write POs Aig_ManForEachPoSeq( p, pObj, i ) fprintf( pFile, "output n%0*d;\n", nDigits, pObj->iData ); // write latches if ( Aig_ManRegNum(p) ) { Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) fprintf( pFile, "reg n%0*d;\n", nDigits, pObjLo->iData ); Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) fprintf( pFile, "wire n%0*d;\n", nDigits, pObjLi->iData ); } // write nodes Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) fprintf( pFile, "wire n%0*d;\n", nDigits, pObj->iData ); if ( pConst1 ) fprintf( pFile, "wire n%0*d;\n", nDigits, pConst1->iData ); // write nodes if ( pConst1 ) fprintf( pFile, "assign n%0*d = 1\'b1;\n", nDigits, pConst1->iData ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { fprintf( pFile, "assign n%0*d = %sn%0*d & %sn%0*d;\n", nDigits, pObj->iData, !Aig_ObjFaninC0(pObj) ? " " : "~", nDigits, Aig_ObjFanin0(pObj)->iData, !Aig_ObjFaninC1(pObj) ? " " : "~", nDigits, Aig_ObjFanin1(pObj)->iData ); } // write POs Aig_ManForEachPoSeq( p, pObj, i ) { fprintf( pFile, "assign n%0*d = %sn%0*d;\n", nDigits, pObj->iData, !Aig_ObjFaninC0(pObj) ? " " : "~", nDigits, Aig_ObjFanin0(pObj)->iData ); } if ( Aig_ManRegNum(p) ) { Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) { fprintf( pFile, "assign n%0*d = %sn%0*d;\n", nDigits, pObjLi->iData, !Aig_ObjFaninC0(pObjLi) ? " " : "~", nDigits, Aig_ObjFanin0(pObjLi)->iData ); } } // write initial state if ( Aig_ManRegNum(p) ) { Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) fprintf( pFile, "always @ (posedge clock) begin n%0*d <= n%0*d; end\n", nDigits, pObjLo->iData, nDigits, pObjLi->iData ); Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) fprintf( pFile, "initial begin n%0*d <= 1\'b0; end\n", nDigits, pObjLo->iData ); } fprintf( pFile, "endmodule\n\n" ); fclose( pFile ); Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Sets the PI/PO numbers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManSetCioIds( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManForEachCi( p, pObj, i ) pObj->CioId = i; Aig_ManForEachCo( p, pObj, i ) pObj->CioId = i; } /**Function************************************************************* Synopsis [Sets the PI/PO numbers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManCleanCioIds( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManForEachCi( p, pObj, i ) pObj->pNext = NULL; Aig_ManForEachCo( p, pObj, i ) pObj->pNext = NULL; } /**Function************************************************************* Synopsis [Sets the PI/PO numbers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManChoiceNum( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, Counter = 0; Aig_ManForEachNode( p, pObj, i ) Counter += Aig_ObjIsChoice( p, pObj ); return Counter; } /**Function************************************************************* Synopsis [Prints the fanouts of the control register.] Description [Useful only for Intel MC benchmarks.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManPrintControlFanouts( Aig_Man_t * p ) { Aig_Obj_t * pObj, * pFanin0, * pFanin1, * pCtrl; int i; pCtrl = Aig_ManCi( p, Aig_ManCiNum(p) - 1 ); printf( "Control signal:\n" ); Aig_ObjPrint( p, pCtrl ); printf( "\n\n" ); Aig_ManForEachObj( p, pObj, i ) { if ( !Aig_ObjIsNode(pObj) ) continue; assert( pObj != pCtrl ); pFanin0 = Aig_ObjFanin0(pObj); pFanin1 = Aig_ObjFanin1(pObj); if ( pFanin0 == pCtrl && Aig_ObjIsCi(pFanin1) ) { Aig_ObjPrint( p, pObj ); printf( "\n" ); Aig_ObjPrint( p, pFanin1 ); printf( "\n" ); printf( "\n" ); } if ( pFanin1 == pCtrl && Aig_ObjIsCi(pFanin0) ) { Aig_ObjPrint( p, pObj ); printf( "\n" ); Aig_ObjPrint( p, pFanin0 ); printf( "\n" ); printf( "\n" ); } } } /**Function************************************************************* Synopsis [Returns the composite name of the file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Aig_FileNameGenericAppend( char * pBase, char * pSuffix ) { static char Buffer[1000]; char * pDot; strcpy( Buffer, pBase ); if ( (pDot = strrchr( Buffer, '.' )) ) *pDot = 0; strcat( Buffer, pSuffix ); if ( (pDot = strrchr( Buffer, '\\' )) || (pDot = strrchr( Buffer, '/' )) ) return pDot+1; return Buffer; } /**Function************************************************************* Synopsis [Creates a sequence of random numbers.] Description [] SideEffects [] SeeAlso [http://en.wikipedia.org/wiki/LFSR] ***********************************************************************/ void Aig_ManRandomTest2() { FILE * pFile; unsigned int lfsr = 1; unsigned int period = 0; pFile = fopen( "rand.txt", "w" ); do { // lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u); // taps 32 31 29 1 lfsr = 1; // to prevent the warning ++period; fprintf( pFile, "%10d : %10d ", period, lfsr ); // Extra_PrintBinary( pFile, &lfsr, 32 ); fprintf( pFile, "\n" ); if ( period == 20000 ) break; } while(lfsr != 1u); fclose( pFile ); } /**Function************************************************************* Synopsis [Creates a sequence of random numbers.] Description [] SideEffects [] SeeAlso [http://www.codeproject.com/KB/recipes/SimpleRNG.aspx] ***********************************************************************/ void Aig_ManRandomTest1() { FILE * pFile; unsigned int lfsr; unsigned int period = 0; pFile = fopen( "rand.txt", "w" ); do { lfsr = Aig_ManRandom( 0 ); ++period; fprintf( pFile, "%10d : %10d ", period, lfsr ); // Extra_PrintBinary( pFile, &lfsr, 32 ); fprintf( pFile, "\n" ); if ( period == 20000 ) break; } while(lfsr != 1u); fclose( pFile ); } #define NUMBER1 3716960521u #define NUMBER2 2174103536u /**Function************************************************************* Synopsis [Creates a sequence of random numbers.] Description [] SideEffects [] SeeAlso [http://www.codeproject.com/KB/recipes/SimpleRNG.aspx] ***********************************************************************/ unsigned Aig_ManRandom( int fReset ) { #ifdef _MSC_VER static unsigned int m_z = NUMBER1; static unsigned int m_w = NUMBER2; #else static __thread unsigned int m_z = NUMBER1; static __thread unsigned int m_w = NUMBER2; #endif if ( fReset ) { m_z = NUMBER1; m_w = NUMBER2; } m_z = 36969 * (m_z & 65535) + (m_z >> 16); m_w = 18000 * (m_w & 65535) + (m_w >> 16); return (m_z << 16) + m_w; } /**Function************************************************************* Synopsis [Creates a sequence of random numbers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word Aig_ManRandom64( int fReset ) { word Res = (word)Aig_ManRandom(fReset); return Res | ((word)Aig_ManRandom(0) << 32); } /**Function************************************************************* Synopsis [Creates random info for the primary inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int iWordStop ) { unsigned * pInfo; int i, w; Vec_PtrForEachEntryStart( unsigned *, vInfo, pInfo, i, iInputStart ) for ( w = iWordStart; w < iWordStop; w++ ) pInfo[w] = Aig_ManRandom(0); } /**Function************************************************************* Synopsis [Returns the result of merging the two vectors.] Description [Assumes that the vectors are sorted in the increasing order.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_NodeUnionLists( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * vArr ) { Aig_Obj_t ** pBeg = (Aig_Obj_t **)vArr->pArray; Aig_Obj_t ** pBeg1 = (Aig_Obj_t **)vArr1->pArray; Aig_Obj_t ** pBeg2 = (Aig_Obj_t **)vArr2->pArray; Aig_Obj_t ** pEnd1 = (Aig_Obj_t **)vArr1->pArray + vArr1->nSize; Aig_Obj_t ** pEnd2 = (Aig_Obj_t **)vArr2->pArray + vArr2->nSize; Vec_PtrGrow( vArr, Vec_PtrSize(vArr1) + Vec_PtrSize(vArr2) ); pBeg = (Aig_Obj_t **)vArr->pArray; while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) { if ( (*pBeg1)->Id == (*pBeg2)->Id ) *pBeg++ = *pBeg1++, pBeg2++; else if ( (*pBeg1)->Id < (*pBeg2)->Id ) *pBeg++ = *pBeg1++; else *pBeg++ = *pBeg2++; } while ( pBeg1 < pEnd1 ) *pBeg++ = *pBeg1++; while ( pBeg2 < pEnd2 ) *pBeg++ = *pBeg2++; vArr->nSize = pBeg - (Aig_Obj_t **)vArr->pArray; assert( vArr->nSize <= vArr->nCap ); assert( vArr->nSize >= vArr1->nSize ); assert( vArr->nSize >= vArr2->nSize ); } /**Function************************************************************* Synopsis [Returns the result of intersecting the two vectors.] Description [Assumes that the vectors are sorted in the increasing order.] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_NodeIntersectLists( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * vArr ) { Aig_Obj_t ** pBeg = (Aig_Obj_t **)vArr->pArray; Aig_Obj_t ** pBeg1 = (Aig_Obj_t **)vArr1->pArray; Aig_Obj_t ** pBeg2 = (Aig_Obj_t **)vArr2->pArray; Aig_Obj_t ** pEnd1 = (Aig_Obj_t **)vArr1->pArray + vArr1->nSize; Aig_Obj_t ** pEnd2 = (Aig_Obj_t **)vArr2->pArray + vArr2->nSize; Vec_PtrGrow( vArr, Abc_MaxInt( Vec_PtrSize(vArr1), Vec_PtrSize(vArr2) ) ); pBeg = (Aig_Obj_t **)vArr->pArray; while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) { if ( (*pBeg1)->Id == (*pBeg2)->Id ) *pBeg++ = *pBeg1++, pBeg2++; else if ( (*pBeg1)->Id < (*pBeg2)->Id ) // *pBeg++ = *pBeg1++; pBeg1++; else // *pBeg++ = *pBeg2++; pBeg2++; } // while ( pBeg1 < pEnd1 ) // *pBeg++ = *pBeg1++; // while ( pBeg2 < pEnd2 ) // *pBeg++ = *pBeg2++; vArr->nSize = pBeg - (Aig_Obj_t **)vArr->pArray; assert( vArr->nSize <= vArr->nCap ); assert( vArr->nSize <= vArr1->nSize ); assert( vArr->nSize <= vArr2->nSize ); } ABC_NAMESPACE_IMPL_END #include "proof/fra/fra.h" #include "aig/saig/saig.h" ABC_NAMESPACE_IMPL_START extern void Aig_ManCounterExampleValueStart( Aig_Man_t * pAig, Abc_Cex_t * pCex ); extern void Aig_ManCounterExampleValueStop( Aig_Man_t * pAig ); extern int Aig_ManCounterExampleValueLookup( Aig_Man_t * pAig, int Id, int iFrame ); /**Function************************************************************* Synopsis [Starts the process of retuning values for internal nodes.] Description [Should be called when pCex is available, before probing any object for its value using Aig_ManCounterExampleValueLookup().] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManCounterExampleValueStart( Aig_Man_t * pAig, Abc_Cex_t * pCex ) { Aig_Obj_t * pObj, * pObjRi, * pObjRo; int Val0, Val1, nObjs, i, k, iBit = 0; assert( Aig_ManRegNum(pAig) > 0 ); // makes sense only for sequential AIGs assert( pAig->pData2 == NULL ); // if this fail, there may be a memory leak // allocate memory to store simulation bits for internal nodes 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 ), iBit++; // iterate through the timeframes nObjs = Aig_ManObjNumMax(pAig); for ( i = 0; i <= pCex->iFrame; i++ ) { // set constant 1 node Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + 0 ); // set primary inputs according to the counter-example Saig_ManForEachPi( pAig, pObj, k ) if ( Abc_InfoHasBit(pCex->pData, iBit++) ) Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObj) ); // compute values for each node Aig_ManForEachNode( pAig, pObj, k ) { Val0 = Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjFaninId0(pObj) ); Val1 = Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjFaninId1(pObj) ); if ( (Val0 ^ Aig_ObjFaninC0(pObj)) & (Val1 ^ Aig_ObjFaninC1(pObj)) ) Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObj) ); } // derive values for combinational outputs Aig_ManForEachCo( pAig, pObj, k ) { Val0 = Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjFaninId0(pObj) ); if ( Val0 ^ Aig_ObjFaninC0(pObj) ) Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObj) ); } if ( i == pCex->iFrame ) continue; // transfer values to the register output of the next frame Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) if ( Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObjRi) ) ) Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * (i+1) + Aig_ObjId(pObjRo) ); } assert( iBit == pCex->nBits ); // check that the counter-example is correct, that is, the corresponding output is asserted assert( Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * pCex->iFrame + Aig_ObjId(Aig_ManCo(pAig, pCex->iPo)) ) ); } /**Function************************************************************* Synopsis [Stops the process of retuning values for internal nodes.] Description [Should be called when probing is no longer needed] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManCounterExampleValueStop( Aig_Man_t * pAig ) { assert( pAig->pData2 != NULL ); // if this fail, we try to call this procedure more than once free( pAig->pData2 ); pAig->pData2 = NULL; } /**Function************************************************************* Synopsis [Returns the value of the given object in the given timeframe.] Description [Should be called to probe the value of an object with the given ID (iFrame is a 0-based number of a time frame - should not exceed the number of timeframes in the original counter-example).] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManCounterExampleValueLookup( Aig_Man_t * pAig, int Id, int iFrame ) { assert( Id >= 0 && Id < Aig_ManObjNumMax(pAig) ); return Abc_InfoHasBit( (unsigned *)pAig->pData2, Aig_ManObjNumMax(pAig) * iFrame + Id ); } /**Function************************************************************* Synopsis [Procedure to test the above code.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManCounterExampleValueTest( Aig_Man_t * pAig, Abc_Cex_t * pCex ) { Aig_Obj_t * pObj = Aig_ManObj( pAig, Aig_ManObjNumMax(pAig)/2 ); int iFrame = Abc_MaxInt( 0, pCex->iFrame - 1 ); printf( "\nUsing counter-example, which asserts output %d in frame %d.\n", pCex->iPo, pCex->iFrame ); Aig_ManCounterExampleValueStart( pAig, pCex ); printf( "Value of object %d in frame %d is %d.\n", Aig_ObjId(pObj), iFrame, Aig_ManCounterExampleValueLookup(pAig, Aig_ObjId(pObj), iFrame) ); Aig_ManCounterExampleValueStop( pAig ); } /**Function************************************************************* Synopsis [Handle the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManSetPhase( Aig_Man_t * pAig ) { Aig_Obj_t * pObj; int i; // set the PI simulation information Aig_ManConst1( pAig )->fPhase = 1; Aig_ManForEachCi( pAig, pObj, i ) pObj->fPhase = 0; // simulate internal nodes Aig_ManForEachNode( pAig, pObj, i ) pObj->fPhase = ( Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj) ) & ( Aig_ObjFanin1(pObj)->fPhase ^ Aig_ObjFaninC1(pObj) ); // simulate PO nodes Aig_ManForEachCo( pAig, pObj, i ) pObj->fPhase = Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj); } /**Function************************************************************* Synopsis [Collects muxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Aig_ManMuxesCollect( Aig_Man_t * pAig ) { Vec_Ptr_t * vMuxes; Aig_Obj_t * pObj; int i; vMuxes = Vec_PtrAlloc( 100 ); Aig_ManForEachNode( pAig, pObj, i ) if ( Aig_ObjIsMuxType(pObj) ) Vec_PtrPush( vMuxes, pObj ); return vMuxes; } /**Function************************************************************* Synopsis [Dereferences muxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManMuxesDeref( Aig_Man_t * pAig, Vec_Ptr_t * vMuxes ) { Aig_Obj_t * pObj, * pNodeT, * pNodeE, * pNodeC; int i; Vec_PtrForEachEntry( Aig_Obj_t *, vMuxes, pObj, i ) { if ( Aig_ObjRecognizeExor( pObj, &pNodeT, &pNodeE ) ) { pNodeT->nRefs--; pNodeE->nRefs--; } else { pNodeC = Aig_ObjRecognizeMux( pObj, &pNodeT, &pNodeE ); pNodeC->nRefs--; } } } /**Function************************************************************* Synopsis [References muxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManMuxesRef( Aig_Man_t * pAig, Vec_Ptr_t * vMuxes ) { Aig_Obj_t * pObj, * pNodeT, * pNodeE, * pNodeC; int i; Vec_PtrForEachEntry( Aig_Obj_t *, vMuxes, pObj, i ) { if ( Aig_ObjRecognizeExor( pObj, &pNodeT, &pNodeE ) ) { pNodeT->nRefs++; pNodeE->nRefs++; } else { pNodeC = Aig_ObjRecognizeMux( pObj, &pNodeT, &pNodeE ); pNodeC->nRefs++; } } } /**Function************************************************************* Synopsis [Complements the constraint outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManInvertConstraints( Aig_Man_t * pAig ) { Aig_Obj_t * pObj; int i; if ( Aig_ManConstrNum(pAig) == 0 ) return; Saig_ManForEachPo( pAig, pObj, i ) { if ( i >= Saig_ManPoNum(pAig) - Aig_ManConstrNum(pAig) ) Aig_ObjChild0Flip( pObj ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aigWin.c000066400000000000000000000137251477524141600156610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigWin.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Window computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigWin.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Evaluate the cost of removing the node from the set of leaves.] Description [Returns the number of new leaves that will be brought in. Returns large number if the node cannot be removed from the set of leaves.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_NodeGetLeafCostOne( Aig_Obj_t * pNode, int nFanoutLimit ) { int Cost; // make sure the node is in the construction zone assert( pNode->fMarkA ); // cannot expand over the PI node if ( Aig_ObjIsCi(pNode) ) return 999; // get the cost of the cone Cost = (!Aig_ObjFanin0(pNode)->fMarkA) + (!Aig_ObjFanin1(pNode)->fMarkA); // always accept if the number of leaves does not increase if ( Cost < 2 ) return Cost; // skip nodes with many fanouts if ( (int)pNode->nRefs > nFanoutLimit ) return 999; // return the number of nodes that will be on the leaves if this node is removed return Cost; } /**Function************************************************************* Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] Description [This procedure looks at the current leaves and tries to change one leaf at a time in such a way that the cut grows as little as possible. In evaluating the fanins, this procedure looks only at their immediate predecessors (this is why it is called a one-level construction procedure).] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_ManFindCut_int( Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit ) { Aig_Obj_t * pNode, * pFaninBest, * pNext; int CostBest, CostCur, i; // find the best fanin CostBest = 100; pFaninBest = NULL; //printf( "Evaluating fanins of the cut:\n" ); Vec_PtrForEachEntry( Aig_Obj_t *, vFront, pNode, i ) { CostCur = Aig_NodeGetLeafCostOne( pNode, nFanoutLimit ); //printf( " Fanin %s has cost %d.\n", Aig_ObjName(pNode), CostCur ); if ( CostBest > CostCur || (CostBest == CostCur && pNode->Level > pFaninBest->Level) ) { CostBest = CostCur; pFaninBest = pNode; } if ( CostBest == 0 ) break; } if ( pFaninBest == NULL ) return 0; assert( CostBest < 3 ); if ( Vec_PtrSize(vFront) - 1 + CostBest > nSizeLimit ) return 0; assert( Aig_ObjIsNode(pFaninBest) ); // remove the node from the array Vec_PtrRemove( vFront, pFaninBest ); //printf( "Removing fanin %s.\n", Aig_ObjName(pFaninBest) ); // add the left child to the fanins pNext = Aig_ObjFanin0(pFaninBest); if ( !pNext->fMarkA ) { //printf( "Adding fanin %s.\n", Aig_ObjName(pNext) ); pNext->fMarkA = 1; Vec_PtrPush( vFront, pNext ); Vec_PtrPush( vVisited, pNext ); } // add the right child to the fanins pNext = Aig_ObjFanin1(pFaninBest); if ( !pNext->fMarkA ) { //printf( "Adding fanin %s.\n", Aig_ObjName(pNext) ); pNext->fMarkA = 1; Vec_PtrPush( vFront, pNext ); Vec_PtrPush( vVisited, pNext ); } assert( Vec_PtrSize(vFront) <= nSizeLimit ); // keep doing this return 1; } /**Function************************************************************* Synopsis [Computes one sequential cut of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManFindCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit ) { Aig_Obj_t * pNode; int i; assert( !Aig_IsComplement(pRoot) ); assert( Aig_ObjIsNode(pRoot) ); assert( Aig_ObjChild0(pRoot) ); assert( Aig_ObjChild1(pRoot) ); // start the cut Vec_PtrClear( vFront ); Vec_PtrPush( vFront, Aig_ObjFanin0(pRoot) ); Vec_PtrPush( vFront, Aig_ObjFanin1(pRoot) ); // start the visited nodes Vec_PtrClear( vVisited ); Vec_PtrPush( vVisited, pRoot ); Vec_PtrPush( vVisited, Aig_ObjFanin0(pRoot) ); Vec_PtrPush( vVisited, Aig_ObjFanin1(pRoot) ); // mark these nodes assert( !pRoot->fMarkA ); assert( !Aig_ObjFanin0(pRoot)->fMarkA ); assert( !Aig_ObjFanin1(pRoot)->fMarkA ); pRoot->fMarkA = 1; Aig_ObjFanin0(pRoot)->fMarkA = 1; Aig_ObjFanin1(pRoot)->fMarkA = 1; // compute the cut while ( Aig_ManFindCut_int( vFront, vVisited, nSizeLimit, nFanoutLimit ) ); assert( Vec_PtrSize(vFront) <= nSizeLimit ); // clean the visit markings Vec_PtrForEachEntry( Aig_Obj_t *, vVisited, pNode, i ) pNode->fMarkA = 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/aig_.c000066400000000000000000000026331477524141600153360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aig_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aig_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/aig/module.make000066400000000000000000000015621477524141600164170ustar00rootroot00000000000000SRC += src/aig/aig/aigCheck.c \ src/aig/aig/aigCanon.c \ src/aig/aig/aigCuts.c \ src/aig/aig/aigDfs.c \ src/aig/aig/aigDup.c \ src/aig/aig/aigFanout.c \ src/aig/aig/aigFrames.c \ src/aig/aig/aigInter.c \ src/aig/aig/aigJust.c \ src/aig/aig/aigMan.c \ src/aig/aig/aigMem.c \ src/aig/aig/aigMffc.c \ src/aig/aig/aigObj.c \ src/aig/aig/aigOper.c \ src/aig/aig/aigOrder.c \ src/aig/aig/aigPack.c \ src/aig/aig/aigPart.c \ src/aig/aig/aigPartReg.c \ src/aig/aig/aigPartSat.c \ src/aig/aig/aigRepr.c \ src/aig/aig/aigRet.c \ src/aig/aig/aigRetF.c \ src/aig/aig/aigScl.c \ src/aig/aig/aigShow.c \ src/aig/aig/aigSplit.c \ src/aig/aig/aigTable.c \ src/aig/aig/aigTiming.c \ src/aig/aig/aigTruth.c \ src/aig/aig/aigTsim.c \ src/aig/aig/aigUtil.c \ src/aig/aig/aigWin.cabc-0.52/src/aig/gia/000077500000000000000000000000001477524141600142675ustar00rootroot00000000000000abc-0.52/src/aig/gia/gia.c000066400000000000000000000325431477524141600152020ustar00rootroot00000000000000/**CFile**************************************************************** FileName [gia.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" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Slv_Man_t_ Slv_Man_t; struct Slv_Man_t_ { Vec_Int_t vCis; Vec_Int_t vCos; Vec_Int_t vFanins; Vec_Int_t vFanoutN; Vec_Int_t vFanout0; Vec_Str_t vValues; Vec_Int_t vCopies; }; static inline int Slv_ManObjNum ( Slv_Man_t * p ) { return Vec_IntSize(&p->vFanins)/2; } static inline int Slv_ObjFaninLit ( Slv_Man_t * p, int iObj, int f ) { return Vec_IntEntry(&p->vFanins, Abc_Var2Lit(iObj, f)); } static inline int Slv_ObjFanin ( Slv_Man_t * p, int iObj, int f ) { return Abc_Lit2Var(Slv_ObjFaninLit(p, iObj, f)); } static inline int Slv_ObjFaninC ( Slv_Man_t * p, int iObj, int f ) { return Abc_LitIsCompl(Slv_ObjFaninLit(p, iObj, f)); } static inline int Slv_ObjIsCi ( Slv_Man_t * p, int iObj ) { return !Slv_ObjFaninLit(p, iObj, 0) && Slv_ObjFaninLit(p, iObj, 1); } static inline int Slv_ObjIsCo ( Slv_Man_t * p, int iObj ) { return Slv_ObjFaninLit(p, iObj, 0) && !Slv_ObjFaninLit(p, iObj, 1); } static inline int Slv_ObjIsAnd ( Slv_Man_t * p, int iObj ) { return Slv_ObjFaninLit(p, iObj, 0) && Slv_ObjFaninLit(p, iObj, 1); } static inline int Slv_ObjFanout0 ( Slv_Man_t * p, int iObj ) { return Vec_IntEntry(&p->vFanout0, iObj); } static inline void Slv_ObjSetFanout0 ( Slv_Man_t * p, int iObj, int iLit ) { Vec_IntWriteEntry(&p->vFanout0, iObj, iLit); } static inline int Slv_ObjNextFanout ( Slv_Man_t * p, int iLit ) { return Vec_IntEntry(&p->vFanoutN, iLit); } static inline void Slv_ObjSetNextFanout( Slv_Man_t * p, int iLit, int iLitF ) { Vec_IntWriteEntry(&p->vFanoutN, iLit, iLitF); } static inline int Slv_ObjCopyLit ( Slv_Man_t * p, int iObj ) { return Vec_IntEntry(&p->vCopies, iObj); } static inline void Slv_ObjSetCopyLit ( Slv_Man_t * p, int iObj, int iLit ) { Vec_IntWriteEntry(&p->vCopies, iObj, iLit); } #define Slv_ManForEachObj( p, iObj ) \ for ( iObj = 1; iObj < Slv_ManObjNum(p); iObj++ ) #define Slv_ObjForEachFanout( p, iObj, iFanLit ) \ for ( iFanLit = Slv_ObjFanout0(p, iObj); iFanLit; iFanLit = Slv_ObjNextFanout(p, iFanLit) ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Slv_Man_t * Slv_ManAlloc( int nObjs ) { Slv_Man_t * p = ABC_CALLOC( Slv_Man_t, 1 ); Vec_IntGrow( &p->vCis, 100 ); Vec_IntGrow( &p->vCos, 100 ); Vec_IntGrow( &p->vFanins, 2*nObjs ); Vec_IntGrow( &p->vFanoutN, 2*nObjs ); Vec_IntGrow( &p->vFanout0, nObjs ); Vec_StrGrow( &p->vValues, nObjs ); // constant node Vec_IntFill( &p->vFanins, 2, 0 ); Vec_IntFill( &p->vFanoutN, 2, 0 ); Vec_IntFill( &p->vFanout0, 1, 0 ); return p; } void Slv_ManFree( Slv_Man_t * p ) { Vec_IntErase( &p->vCis ); Vec_IntErase( &p->vCos ); Vec_IntErase( &p->vFanins ); Vec_IntErase( &p->vFanoutN ); Vec_IntErase( &p->vFanout0 ); Vec_StrErase( &p->vValues ); Vec_IntErase( &p->vCopies ); ABC_FREE( p ); } void Slv_ManPrintFanouts( Slv_Man_t * p ) { int iObj, iFanLit; Slv_ManForEachObj( p, iObj ) { printf( "Fanouts of node %d: ", iObj ); Slv_ObjForEachFanout( p, iObj, iFanLit ) printf( "%d ", Abc_Lit2Var(iFanLit) ); printf( "\n" ); } } static inline int Slv_ManAppendObj( Slv_Man_t * p, int iLit0, int iLit1 ) { int iObj = Slv_ManObjNum(p); Vec_StrPush( &p->vValues, 0 ); Vec_IntPush( &p->vFanout0, 0 ); Vec_IntPushTwo( &p->vFanoutN, 0, 0 ); if ( !iLit0 ) // primary input assert(!iLit1), iLit1 = Vec_IntSize(&p->vCis)+1, Vec_IntPush(&p->vCis, iObj); else if ( !iLit1 ) // primary output assert(iLit0), Vec_IntPush(&p->vCos, iObj); else { Slv_ObjSetNextFanout( p, Abc_Var2Lit(iObj, 0), Slv_ObjFanout0(p, Abc_Lit2Var(iLit0)) ); Slv_ObjSetNextFanout( p, Abc_Var2Lit(iObj, 1), Slv_ObjFanout0(p, Abc_Lit2Var(iLit1)) ); Slv_ObjSetFanout0( p, Abc_Lit2Var(iLit0), Abc_Var2Lit(iObj, 0) ); Slv_ObjSetFanout0( p, Abc_Lit2Var(iLit1), Abc_Var2Lit(iObj, 1) ); } Vec_IntPushTwo( &p->vFanins, iLit0, iLit1 ); return Abc_Var2Lit( iObj, 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Slv_Man_t * Slv_ManFromGia( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Slv_Man_t * pNew = Slv_ManAlloc( Gia_ManObjNum(p) ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Slv_ManAppendObj( pNew, Abc_LitNotCond(Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj)), Abc_LitNotCond(Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj)) ); else if ( Gia_ObjIsCo(pObj) ) pObj->Value = Slv_ManAppendObj( pNew, Abc_LitNotCond(Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj)), 0 ); else if ( Gia_ObjIsCi(pObj) ) pObj->Value = Slv_ManAppendObj( pNew, 0, 0 ); else assert( 0 ); } assert( Gia_ManObjNum(p) == Slv_ManObjNum(pNew) ); return pNew; } Gia_Man_t * Slv_ManToGia( Slv_Man_t * p ) { int iObj; Gia_Man_t * pNew = Gia_ManStart( Slv_ManObjNum(p) ); Vec_IntFill( &p->vCopies, Slv_ManObjNum(p), 0 ); Slv_ManForEachObj( p, iObj ) if ( Slv_ObjIsCi(p, iObj) ) Slv_ObjSetCopyLit( p, iObj, Gia_ManAppendCi(pNew) ); else if ( Slv_ObjIsCo(p, iObj) ) { int iLit0 = Abc_LitNotCond( Slv_ObjCopyLit(p, Slv_ObjFanin(p, iObj, 0)), Slv_ObjFaninC(p, iObj, 0) ); Slv_ObjSetCopyLit( p, iObj, Gia_ManAppendCo(pNew, iLit0) ); } else if ( Slv_ObjIsAnd(p, iObj) ) { int iLit0 = Abc_LitNotCond( Slv_ObjCopyLit(p, Slv_ObjFanin(p, iObj, 0)), Slv_ObjFaninC(p, iObj, 0) ); int iLit1 = Abc_LitNotCond( Slv_ObjCopyLit(p, Slv_ObjFanin(p, iObj, 1)), Slv_ObjFaninC(p, iObj, 1) ); Slv_ObjSetCopyLit( p, iObj, Gia_ManAppendAnd(pNew, iLit0, iLit1) ); } else assert(0); assert( Gia_ManObjNum(pNew) == Slv_ManObjNum(p) ); return pNew; } Gia_Man_t * Slv_ManToAig( Gia_Man_t * pGia ) { Slv_Man_t * p = Slv_ManFromGia( pGia ); Gia_Man_t * pNew = Slv_ManToGia( p ); pNew->pName = Abc_UtilStrsav( pGia->pName ); pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); Slv_ManPrintFanouts( p ); Slv_ManFree( p ); 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 /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/gia.h000066400000000000000000004057571477524141600152220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [gia.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: gia.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__gia__gia_h #define ABC__aig__gia__gia_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "misc/vec/vec.h" #include "misc/vec/vecWec.h" #include "misc/util/utilCex.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START #define GIA_NONE 0x1FFFFFFF #define GIA_VOID 0x0FFFFFFF //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// 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_ { unsigned iRepr : 28; // representative node unsigned fProved : 1; // marks the proved equivalence unsigned fFailed : 1; // marks the failed equivalence unsigned fColorA : 1; // marks cone of A unsigned fColorB : 1; // marks cone of B }; typedef struct Gia_Plc_t_ Gia_Plc_t; struct Gia_Plc_t_ { unsigned fFixed : 1; // the placement of this object is fixed unsigned xCoord : 15; // x-ooordinate of the placement unsigned fUndef : 1; // the placement of this object is not assigned unsigned yCoord : 15; // y-ooordinate of the placement }; typedef struct Gia_Obj_t_ Gia_Obj_t; struct Gia_Obj_t_ { unsigned iDiff0 : 29; // the diff of the first fanin unsigned fCompl0: 1; // the complemented attribute unsigned fMark0 : 1; // first user-controlled mark unsigned fTerm : 1; // terminal node (CI/CO) unsigned iDiff1 : 29; // the diff of the second fanin unsigned fCompl1: 1; // the complemented attribute unsigned fMark1 : 1; // second user-controlled mark unsigned fPhase : 1; // value under 000 pattern unsigned Value; // application-specific value }; // Value is currently used to store several types of information // - pointer to the next node in the hash table during structural hashing // - pointer to the node copy during duplication // new AIG manager typedef struct Gia_Man_t_ Gia_Man_t; struct Gia_Man_t_ { char * pName; // name of the AIG char * pSpec; // name of the input file int nRegs; // number of registers int nRegsAlloc; // number of allocated registers int nObjs; // number of objects int nObjsAlloc; // number of allocated objects Gia_Obj_t * pObjs; // the array of objects unsigned * pMuxes; // control signals of MUXes int nXors; // the number of XORs int nMuxes; // the number of MUXes int nBufs; // the number of buffers Vec_Int_t * vCis; // the vector of CIs (PIs + LOs) Vec_Int_t * vCos; // the vector of COs (POs + LIs) Vec_Int_t vHash; // hash links Vec_Int_t vHTable; // hash table int fAddStrash; // performs additional structural hashing int fSweeper; // sweeper is running int fGiaSimple; // simple mode (no const-propagation and strashing) Vec_Int_t vRefs; // the reference count int * pRefs; // the reference count int * pLutRefs; // the reference count Vec_Int_t * vLevels; // levels of the nodes int nLevels; // the mamixum level int nConstrs; // the number of constraints int nTravIds; // the current traversal ID int nFront; // frontier size int * pReprsOld; // representatives (for CIs and ANDs) Gia_Rpr_t * pReprs; // representatives (for CIs and ANDs) int * pNexts; // next nodes in the equivalence classes int * pSibls; // next nodes in the choice nodes int * pIso; // pairs of structurally isomorphic nodes int nTerLoop; // the state where loop begins int nTerStates; // the total number of ternary states int * pFanData; // the database to store fanout information int nFansAlloc; // the size of fanout representation Vec_Int_t * vFanoutNums; // static fanout Vec_Int_t * vFanout; // static fanout Vec_Int_t * vMapping; // mapping for each node Vec_Wec_t * vMapping2; // mapping for each node Vec_Wec_t * vFanouts2; // mapping fanouts Vec_Int_t * vCellMapping; // mapping for each node void * pSatlutWinman; // windowing for SAT-based mapping Vec_Int_t * vPacking; // packing information Vec_Int_t * vConfigs; // cell configurations char * pCellStr; // cell description Vec_Int_t * vLutConfigs; // LUT configurations Vec_Int_t * vEdgeDelay; // special edge information Vec_Int_t * vEdgeDelayR; // special edge information Vec_Int_t * vEdge1; // special edge information Vec_Int_t * vEdge2; // special edge information Abc_Cex_t * pCexComb; // combinational counter-example Abc_Cex_t * pCexSeq; // sequential counter-example Vec_Ptr_t * vSeqModelVec; // sequential counter-examples Vec_Int_t vCopies; // intermediate copies Vec_Int_t vCopies2; // intermediate copies Vec_Int_t * vVar2Obj; // mapping of variables into objects Vec_Int_t * vTruths; // used for truth table computation Vec_Int_t * vFlopClasses; // classes of flops for retiming/merging/etc Vec_Int_t * vGateClasses; // classes of gates for abstraction Vec_Int_t * vObjClasses; // classes of objects for abstraction Vec_Int_t * vInitClasses; // classes of flops for retiming/merging/etc Vec_Int_t * vRegClasses; // classes of registers for sequential synthesis Vec_Int_t * vRegInits; // initial state Vec_Int_t * vDoms; // dominators Vec_Int_t * vBarBufs; // barrier buffers Vec_Int_t * vXors; // temporary XORs unsigned char* pSwitching; // switching activity for each object Gia_Plc_t * pPlacement; // placement of the objects Gia_Man_t * pAigExtra; // combinational logic of holes Vec_Flt_t * vInArrs; // PI arrival times Vec_Flt_t * vOutReqs; // PO required times Vec_Int_t * vCiArrs; // CI arrival times 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 Vec_Int_t * vSwitching; // switching activity int * pTravIds; // separate traversal ID representation 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 Vec_Int_t * vCiNumsOrig; // original CI names Vec_Int_t * vCoNumsOrig; // original CO names Vec_Int_t * vIdsOrig; // original object IDs Vec_Int_t * vIdsEquiv; // original object IDs proved equivalent Vec_Int_t * vCofVars; // cofactoring variables Vec_Vec_t * vClockDoms; // clock domains Vec_Flt_t * vTiming; // arrival/required/slack void * pManTime; // the timing manager void * pLutLib; // LUT library word nHashHit; // hash table hit word nHashMiss; // hash table miss void * pData; // various user data unsigned * pData2; // various user data int iData; // various user data int iData2; // various user data int nAnd2Delay; // AND2 delay scaled to match delay numbers used int fVerbose; // verbose reports int MappedArea; // area after mapping int MappedDelay; // delay after mapping // bit-parallel simulation 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; int iTimeStamp; Vec_Int_t * vTimeStamps; // truth table computation for small functions int nTtVars; // truth table variables int nTtWords; // truth table words Vec_Int_t * vTtNums; // object numbers Vec_Int_t * vTtNodes; // internal nodes Vec_Ptr_t * vTtInputs; // truth tables for constant and primary inputs Vec_Wrd_t * vTtMemory; // truth tables for internal nodes // balancing Vec_Int_t * vSuper; // supergate Vec_Int_t * vStore; // node storage // existential quantification int iSuppPi; // the number of support variables int nSuppWords; // the number of support words 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; // retiming data Vec_Str_t * vStopsF; Vec_Str_t * vStopsB; // iteration with boxes int iFirstNonPiId; int iFirstPoId; int iFirstAndObj; int iFirstPoObj; Vec_Str_t * vTTISOPs; // truth tables from ISOP computation Vec_Int_t * vTTLut; // truth tables from ISOP computation Vec_Int_t * vMFFCsInfo; // MFFC information Vec_Int_t * vMFFCsLuts; // MFFCs for each lut Vec_Ptr_t * vLutsRankings; // LUTs rankings of inputs }; typedef struct Gps_Par_t_ Gps_Par_t; struct Gps_Par_t_ { int fTents; int fSwitch; int fCut; int fNpn; int fLutProf; int fMuxXor; int fMiter; int fSkipMap; int fSlacks; int fNoColor; char * pDumpFile; }; typedef struct Emb_Par_t_ Emb_Par_t; struct Emb_Par_t_ { int nDims; // the number of dimension int nSols; // the number of solutions (typically, 2) int nIters; // the number of iterations of FORCE int fRefine; // use refinement by FORCE int fCluster; // use clustered representation int fDump; // dump Gnuplot file int fDumpLarge; // dump Gnuplot file for large benchmarks int fShowImage; // shows image if Gnuplot is installed int fVerbose; // verbose flag }; // frames parameters typedef struct Gia_ParFra_t_ Gia_ParFra_t; struct Gia_ParFra_t_ { int nFrames; // the number of frames to unroll int fInit; // initialize the timeframes int fSaveLastLit; // adds POs for outputs of each frame int fDisableSt; // disables strashing int fOrPos; // ORs respective POs in each timeframe int fVerbose; // enables verbose output }; // simulation parameters typedef struct Gia_ParSim_t_ Gia_ParSim_t; struct Gia_ParSim_t_ { // user-controlled parameters int nWords; // the number of machine words int nIters; // the number of timeframes int RandSeed; // seed to generate random numbers int TimeLimit; // time limit in seconds int fCheckMiter; // check if miter outputs are non-zero int fVerbose; // enables verbose output int iOutFail; // index of the failed output }; typedef struct Gia_ManSim_t_ Gia_ManSim_t; struct Gia_ManSim_t_ { Gia_Man_t * pAig; Gia_ParSim_t * pPars; int nWords; Vec_Int_t * vCis2Ids; Vec_Int_t * vConsts; // simulation information unsigned * pDataSim; // simulation data unsigned * pDataSimCis; // simulation data for CIs unsigned * pDataSimCos; // simulation data for COs }; typedef struct Jf_Par_t_ Jf_Par_t; struct Jf_Par_t_ { int nLutSize; int nCutNum; int nProcNum; int nRounds; int nRoundsEla; int nRelaxRatio; int nCoarseLimit; int nAreaTuner; int nReqTimeFlex; int nVerbLimit; int nDelayLut1; int nDelayLut2; int nFastEdges; int DelayTarget; int fAreaOnly; int fPinPerm; int fPinQuick; int fPinFilter; int fOptEdge; int fUseMux7; int fPower; int fCoarsen; int fCutMin; int fFuncDsd; int fGenCnf; int fGenLit; int fCnfObjIds; int fAddOrCla; int fCnfMapping; int fPureAig; int fDoAverage; int fCutHashing; int fCutSimple; int fCutGroup; int fVerbose; int fVeryVerbose; int nLutSizeMax; int nCutNumMax; int nProcNumMax; int nLutSizeMux; word Delay; word Area; word Edge; word Clause; word Mux7; word WordMapDelay; word WordMapArea; word WordMapDelayTarget; int MapDelay; float MapArea; float MapAreaF; float MapDelayTarget; float Epsilon; float * pTimesArr; float * pTimesReq; }; static inline unsigned Gia_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId & 31)); } static inline int Gia_WordHasOneBit( unsigned uWord ) { return (uWord & (uWord-1)) == 0; } static inline int Gia_WordHasOnePair( unsigned uWord ) { return Gia_WordHasOneBit(uWord & (uWord>>1) & 0x55555555); } static inline int Gia_WordCountOnes( unsigned uWord ) { uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); return (uWord & 0x0000FFFF) + (uWord>>16); } static inline int Gia_WordFindFirstBit( unsigned uWord ) { int i; for ( i = 0; i < 32; i++ ) if ( uWord & (1 << i) ) return i; return -1; } static inline int Gia_ManTruthIsConst0( unsigned * pIn, int nVars ) { int w; for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn[w] ) return 0; return 1; } static inline int Gia_ManTruthIsConst1( unsigned * pIn, int nVars ) { int w; for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) if ( pIn[w] != ~(unsigned)0 ) return 0; return 1; } static inline void Gia_ManTruthCopy( unsigned * pOut, unsigned * pIn, int nVars ) { int w; for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn[w]; } static inline void Gia_ManTruthClear( unsigned * pOut, int nVars ) { int w; for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = 0; } static inline void Gia_ManTruthFill( unsigned * pOut, int nVars ) { int w; for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~(unsigned)0; } static inline void Gia_ManTruthNot( unsigned * pOut, unsigned * pIn, int nVars ) { int w; for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~pIn[w]; } static inline int Gia_ManConst0Lit() { return 0; } static inline int Gia_ManConst1Lit() { return 1; } static inline int Gia_ManIsConst0Lit( int iLit ) { return (iLit == 0); } static inline int Gia_ManIsConst1Lit( int iLit ) { return (iLit == 1); } static inline int Gia_ManIsConstLit( int iLit ) { return (iLit <= 1); } static inline Gia_Obj_t * Gia_Regular( Gia_Obj_t * p ) { return (Gia_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } static inline Gia_Obj_t * Gia_Not( Gia_Obj_t * p ) { return (Gia_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } static inline Gia_Obj_t * Gia_NotCond( Gia_Obj_t * p, int c ) { return (Gia_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } static inline int Gia_IsComplement( Gia_Obj_t * p ) { return (int)((ABC_PTRUINT_T)(p) & 01); } static inline char * Gia_ManName( Gia_Man_t * p ) { return p->pName; } static inline int Gia_ManCiNum( Gia_Man_t * p ) { return Vec_IntSize(p->vCis); } static inline int Gia_ManCoNum( Gia_Man_t * p ) { return Vec_IntSize(p->vCos); } static inline int Gia_ManPiNum( Gia_Man_t * p ) { return Vec_IntSize(p->vCis) - p->nRegs; } static inline int Gia_ManPoNum( Gia_Man_t * p ) { return Vec_IntSize(p->vCos) - p->nRegs; } static inline int Gia_ManRegNum( Gia_Man_t * p ) { return p->nRegs; } static inline int Gia_ManObjNum( Gia_Man_t * p ) { return p->nObjs; } static inline int Gia_ManAndNum( Gia_Man_t * p ) { return p->nObjs - Vec_IntSize(p->vCis) - Vec_IntSize(p->vCos) - 1; } static inline int Gia_ManXorNum( Gia_Man_t * p ) { return p->nXors; } static inline int Gia_ManMuxNum( Gia_Man_t * p ) { return p->nMuxes; } static inline int Gia_ManBufNum( Gia_Man_t * p ) { return p->nBufs; } static inline int Gia_ManAndNotBufNum( Gia_Man_t * p ){ return Gia_ManAndNum(p) - Gia_ManBufNum(p); } static inline int Gia_ManCandNum( Gia_Man_t * p ) { return Gia_ManCiNum(p) + Gia_ManAndNum(p); } static inline int Gia_ManConstrNum( Gia_Man_t * p ) { return p->nConstrs; } static inline void Gia_ManFlipVerbose( Gia_Man_t * p ) { p->fVerbose ^= 1; } static inline int Gia_ManHasChoices( Gia_Man_t * p ) { return p->pSibls != NULL; } static inline int Gia_ManChoiceNum( Gia_Man_t * p ) { int c = 0; if (p->pSibls) { int i; for (i = 0; i < p->nObjs; i++) c += (int)(p->pSibls[i] > 0); } return c; } static inline Gia_Obj_t * Gia_ManConst0( Gia_Man_t * p ) { return p->pObjs; } static inline Gia_Obj_t * Gia_ManConst1( Gia_Man_t * p ) { return Gia_Not(Gia_ManConst0(p)); } static inline Gia_Obj_t * Gia_ManObj( Gia_Man_t * p, int v ) { assert( v >= 0 && v < p->nObjs ); return p->pObjs + v; } static inline Gia_Obj_t * Gia_ManCi( Gia_Man_t * p, int v ) { return Gia_ManObj( p, Vec_IntEntry(p->vCis,v) ); } static inline Gia_Obj_t * Gia_ManCo( Gia_Man_t * p, int v ) { return Gia_ManObj( p, Vec_IntEntry(p->vCos,v) ); } static inline Gia_Obj_t * Gia_ManPi( Gia_Man_t * p, int v ) { assert( v < Gia_ManPiNum(p) ); return Gia_ManCi( p, v ); } static inline Gia_Obj_t * Gia_ManPo( Gia_Man_t * p, int v ) { assert( v < Gia_ManPoNum(p) ); return Gia_ManCo( p, v ); } static inline Gia_Obj_t * Gia_ManRo( Gia_Man_t * p, int v ) { assert( v < Gia_ManRegNum(p) ); return Gia_ManCi( p, Gia_ManPiNum(p)+v ); } static inline Gia_Obj_t * Gia_ManRi( Gia_Man_t * p, int v ) { assert( v < Gia_ManRegNum(p) ); return Gia_ManCo( p, Gia_ManPoNum(p)+v ); } static inline int Gia_ObjId( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( p->pObjs <= pObj && pObj < p->pObjs + p->nObjs ); return pObj - p->pObjs; } static inline int Gia_ObjCioId( Gia_Obj_t * pObj ) { assert( pObj->fTerm ); return pObj->iDiff1; } static inline void Gia_ObjSetCioId( Gia_Obj_t * pObj, int v ) { assert( pObj->fTerm ); pObj->iDiff1 = v; } static inline int Gia_ObjValue( Gia_Obj_t * pObj ) { return pObj->Value; } 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; } static inline int Gia_ObjIsCi( Gia_Obj_t * pObj ) { return pObj->fTerm && pObj->iDiff0 == GIA_NONE; } static inline int Gia_ObjIsCo( Gia_Obj_t * pObj ) { return pObj->fTerm && pObj->iDiff0 != GIA_NONE; } static inline int Gia_ObjIsAnd( Gia_Obj_t * pObj ) { return!pObj->fTerm && pObj->iDiff0 != GIA_NONE; } static inline int Gia_ObjIsXor( Gia_Obj_t * pObj ) { return Gia_ObjIsAnd(pObj) && pObj->iDiff0 < pObj->iDiff1; } static inline int Gia_ObjIsMuxId( Gia_Man_t * p, int iObj ) { return p->pMuxes && p->pMuxes[iObj] > 0; } static inline int Gia_ObjIsMux( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjIsMuxId( p, Gia_ObjId(p, pObj) ); } static inline int Gia_ObjIsAndReal( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjIsAnd(pObj) && pObj->iDiff0 > pObj->iDiff1 && !Gia_ObjIsMux(p, pObj); } static inline int Gia_ObjIsBuf( Gia_Obj_t * pObj ) { return pObj->iDiff0 == pObj->iDiff1 && pObj->iDiff0 != GIA_NONE && !pObj->fTerm; } static inline int Gia_ObjIsAndNotBuf( Gia_Obj_t * pObj ) { return Gia_ObjIsAnd(pObj) && pObj->iDiff0 != pObj->iDiff1; } static inline int Gia_ObjIsCand( Gia_Obj_t * pObj ) { return Gia_ObjIsAnd(pObj) || Gia_ObjIsCi(pObj); } static inline int Gia_ObjIsConst0( Gia_Obj_t * pObj ) { return pObj->iDiff0 == GIA_NONE && pObj->iDiff1 == GIA_NONE; } static inline int Gia_ManObjIsConst0( Gia_Man_t * p, Gia_Obj_t * pObj){ return pObj == p->pObjs; } static inline int Gia_Obj2Lit( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Abc_Var2Lit(Gia_ObjId(p, Gia_Regular(pObj)), Gia_IsComplement(pObj)); } static inline Gia_Obj_t * Gia_Lit2Obj( Gia_Man_t * p, int iLit ) { return Gia_NotCond(Gia_ManObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit)); } static inline int Gia_ManCiLit( Gia_Man_t * p, int CiId ) { return Gia_Obj2Lit( p, Gia_ManCi(p, CiId) ); } static inline int Gia_ManIdToCioId( Gia_Man_t * p, int Id ) { return Gia_ObjCioId( Gia_ManObj(p, Id) ); } static inline int Gia_ManCiIdToId( Gia_Man_t * p, int CiId ) { return Gia_ObjId( p, Gia_ManCi(p, CiId) ); } static inline int Gia_ManCoIdToId( Gia_Man_t * p, int CoId ) { return Gia_ObjId( p, Gia_ManCo(p, CoId) ); } static inline int Gia_ObjIsPi( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjIsCi(pObj) && Gia_ObjCioId(pObj) < Gia_ManPiNum(p); } static inline int Gia_ObjIsPo( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjIsCo(pObj) && Gia_ObjCioId(pObj) < Gia_ManPoNum(p); } static inline int Gia_ObjIsRo( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjIsCi(pObj) && Gia_ObjCioId(pObj) >= Gia_ManPiNum(p); } static inline int Gia_ObjIsRi( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjIsCo(pObj) && Gia_ObjCioId(pObj) >= Gia_ManPoNum(p); } static inline Gia_Obj_t * Gia_ObjRoToRi( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsRo(p, pObj) ); return Gia_ManCo(p, Gia_ManCoNum(p) - Gia_ManCiNum(p) + Gia_ObjCioId(pObj)); } static inline Gia_Obj_t * Gia_ObjRiToRo( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsRi(p, pObj) ); return Gia_ManCi(p, Gia_ManCiNum(p) - Gia_ManCoNum(p) + Gia_ObjCioId(pObj)); } static inline int Gia_ObjRoToRiId( Gia_Man_t * p, int ObjId ) { return Gia_ObjId( p, Gia_ObjRoToRi( p, Gia_ManObj(p, ObjId) ) ); } static inline int Gia_ObjRiToRoId( Gia_Man_t * p, int ObjId ) { return Gia_ObjId( p, Gia_ObjRiToRo( p, Gia_ManObj(p, ObjId) ) ); } static inline int Gia_ObjDiff0( Gia_Obj_t * pObj ) { return pObj->iDiff0; } static inline int Gia_ObjDiff1( Gia_Obj_t * pObj ) { return pObj->iDiff1; } 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; } static inline int Gia_ObjFaninLit( Gia_Obj_t * pObj, int ObjId, int n ){ return n ? Gia_ObjFaninLit1(pObj, ObjId) : Gia_ObjFaninLit0(pObj, ObjId);} static inline int Gia_ObjFaninLit0p( Gia_Man_t * p, Gia_Obj_t * pObj) { return Abc_Var2Lit( Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj) ); } static inline int Gia_ObjFaninLit1p( Gia_Man_t * p, Gia_Obj_t * pObj) { return Abc_Var2Lit( Gia_ObjFaninId1p(p, pObj), Gia_ObjFaninC1(pObj) ); } static inline int Gia_ObjFaninLit2p( Gia_Man_t * p, Gia_Obj_t * pObj) { return (p->pMuxes && p->pMuxes[Gia_ObjId(p, pObj)]) ? p->pMuxes[Gia_ObjId(p, pObj)] : -1; } static inline int Gia_ObjFaninLitp( Gia_Man_t * p, Gia_Obj_t * pObj, int n ){ return n ? Gia_ObjFaninLit1p(p, pObj) : Gia_ObjFaninLit0p(p, pObj);} static inline void Gia_ObjFlipFaninC0( Gia_Obj_t * pObj ) { assert( Gia_ObjIsCo(pObj) ); pObj->fCompl0 ^= 1; } static inline int Gia_ObjFaninNum( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsMux(p, pObj) ) return 3; if ( Gia_ObjIsAnd(pObj) ) return 2; if ( Gia_ObjIsCo(pObj) ) return 1; return 0; } static inline int Gia_ObjWhatFanin( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanin ) { if ( Gia_ObjFanin0(pObj) == pFanin ) return 0; if ( Gia_ObjFanin1(pObj) == pFanin ) return 1; if ( Gia_ObjFanin2(p, pObj) == pFanin ) return 2; assert(0); return -1; } 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)) ); } static inline Gia_Obj_t * Gia_ObjCopy( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ManObj( p, Abc_Lit2Var(pObj->Value) ); } static inline int Gia_ObjLitCopy( Gia_Man_t * p, int iLit ) { return Abc_LitNotCond( Gia_ManObj(p, Abc_Lit2Var(iLit))->Value, Abc_LitIsCompl(iLit)); } static inline int Gia_ObjFanin0Copy( Gia_Obj_t * pObj ) { return Abc_LitNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); } static inline int Gia_ObjFanin1Copy( Gia_Obj_t * pObj ) { return Abc_LitNotCond( Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj) ); } static inline int Gia_ObjFanin2Copy( Gia_Man_t * p, Gia_Obj_t * pObj ){ return Abc_LitNotCond(Gia_ObjFanin2(p, pObj)->Value, Gia_ObjFaninC2(p, pObj)); } static inline int Gia_ObjCopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj ) { return Vec_IntEntry(&p->vCopies, Gia_ManObjNum(p) * f + Gia_ObjId(p,pObj)); } static inline void Gia_ObjSetCopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj, int iLit ) { Vec_IntWriteEntry(&p->vCopies, Gia_ManObjNum(p) * f + Gia_ObjId(p,pObj), iLit); } static inline int Gia_ObjCopyArray( Gia_Man_t * p, int iObj ) { return Vec_IntEntry(&p->vCopies, iObj); } static inline void Gia_ObjSetCopyArray( Gia_Man_t * p, int iObj, int iLit ) { Vec_IntWriteEntry(&p->vCopies, iObj, iLit); } static inline void Gia_ManCleanCopyArray( Gia_Man_t * p ) { Vec_IntFill( &p->vCopies, Gia_ManObjNum(p), -1 ); } static inline int Gia_ObjCopy2Array( Gia_Man_t * p, int iObj ) { return Vec_IntEntry(&p->vCopies2, iObj); } static inline void Gia_ObjSetCopy2Array( Gia_Man_t * p, int iObj, int iLit ) { Vec_IntWriteEntry(&p->vCopies2, iObj, iLit); } static inline void Gia_ManCleanCopy2Array( Gia_Man_t * p ) { Vec_IntFill( &p->vCopies2, Gia_ManObjNum(p), -1 ); } static inline int Gia_ObjFanin0CopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj ) { return Abc_LitNotCond(Gia_ObjCopyF(p, f, Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj)); } static inline int Gia_ObjFanin1CopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj ) { return Abc_LitNotCond(Gia_ObjCopyF(p, f, Gia_ObjFanin1(pObj)), Gia_ObjFaninC1(pObj)); } static inline int Gia_ObjFanin0CopyArray( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Abc_LitNotCond(Gia_ObjCopyArray(p, Gia_ObjFaninId0p(p,pObj)), Gia_ObjFaninC0(pObj)); } static inline int Gia_ObjFanin1CopyArray( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Abc_LitNotCond(Gia_ObjCopyArray(p, Gia_ObjFaninId1p(p,pObj)), Gia_ObjFaninC1(pObj)); } static inline Gia_Obj_t * Gia_ObjFromLit( Gia_Man_t * p, int iLit ) { return Gia_NotCond( Gia_ManObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit) ); } static inline int Gia_ObjToLit( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Abc_Var2Lit( Gia_ObjId(p, Gia_Regular(pObj)), Gia_IsComplement(pObj) ); } static inline int Gia_ObjPhaseRealLit( Gia_Man_t * p, int iLit ) { return Gia_ObjPhaseReal( Gia_ObjFromLit(p, 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)) ); } static inline void Gia_ObjSetBufLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsAnd(pObj) ); Gia_ObjSetLevel( p, pObj, Gia_ObjLevel(p,Gia_ObjFanin0(pObj)) ); } static inline void Gia_ObjSetAndLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsAnd(pObj) ); Gia_ObjSetLevel( p, pObj, 1+Abc_MaxInt(Gia_ObjLevel(p,Gia_ObjFanin0(pObj)),Gia_ObjLevel(p,Gia_ObjFanin1(pObj))) ); } static inline void Gia_ObjSetXorLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsXor(pObj) ); Gia_ObjSetLevel( p, pObj, 2+Abc_MaxInt(Gia_ObjLevel(p,Gia_ObjFanin0(pObj)),Gia_ObjLevel(p,Gia_ObjFanin1(pObj))) ); } static inline void Gia_ObjSetMuxLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsMux(p,pObj) ); Gia_ObjSetLevel( p, pObj, 2+Abc_MaxInt( Abc_MaxInt(Gia_ObjLevel(p,Gia_ObjFanin0(pObj)),Gia_ObjLevel(p,Gia_ObjFanin1(pObj))), Gia_ObjLevel(p,Gia_ObjFanin2(p,pObj))) ); } static inline void Gia_ObjSetGateLevel( Gia_Man_t * p, Gia_Obj_t * pObj ){ if ( !p->fGiaSimple && Gia_ObjIsBuf(pObj) ) Gia_ObjSetBufLevel(p, pObj); else if ( Gia_ObjIsMux(p,pObj) ) Gia_ObjSetMuxLevel(p, pObj); else if ( Gia_ObjIsXor(pObj) ) Gia_ObjSetXorLevel(p, pObj); else if ( Gia_ObjIsAnd(pObj) ) Gia_ObjSetAndLevel(p, pObj); } static inline int Gia_ObjHasNumId( Gia_Man_t * p, int Id ) { return Vec_IntEntry(p->vTtNums, Id) > -ABC_INFINITY; } static inline int Gia_ObjNumId( Gia_Man_t * p, int Id ) { return Vec_IntEntry(p->vTtNums, Id); } static inline int Gia_ObjNum( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Vec_IntEntry(p->vTtNums, Gia_ObjId(p,pObj)); } static inline void Gia_ObjSetNumId( Gia_Man_t * p, int Id, int n ) { Vec_IntWriteEntry(p->vTtNums, Id, n); } static inline void Gia_ObjSetNum( Gia_Man_t * p, Gia_Obj_t * pObj, int n ) { Vec_IntWriteEntry(p->vTtNums, Gia_ObjId(p,pObj), n); } static inline void Gia_ObjResetNumId( Gia_Man_t * p, int Id ) { Vec_IntWriteEntry(p->vTtNums, Id, -ABC_INFINITY); } static inline int Gia_ObjRefNumId( Gia_Man_t * p, int Id ) { return p->pRefs[Id]; } static inline int Gia_ObjRefIncId( Gia_Man_t * p, int Id ) { return p->pRefs[Id]++; } static inline int Gia_ObjRefDecId( Gia_Man_t * p, int Id ) { return --p->pRefs[Id]; } static inline int Gia_ObjRefNum( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjRefNumId( p, Gia_ObjId(p, pObj) ); } static inline int Gia_ObjRefInc( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjRefIncId( p, Gia_ObjId(p, pObj) ); } static inline int Gia_ObjRefDec( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjRefDecId( p, Gia_ObjId(p, pObj) ); } static inline void Gia_ObjRefFanin0Inc(Gia_Man_t * p, Gia_Obj_t * pObj) { Gia_ObjRefInc(p, Gia_ObjFanin0(pObj)); } static inline void Gia_ObjRefFanin1Inc(Gia_Man_t * p, Gia_Obj_t * pObj) { Gia_ObjRefInc(p, Gia_ObjFanin1(pObj)); } static inline void Gia_ObjRefFanin2Inc(Gia_Man_t * p, Gia_Obj_t * pObj) { Gia_ObjRefInc(p, Gia_ObjFanin2(p, pObj)); } static inline void Gia_ObjRefFanin0Dec(Gia_Man_t * p, Gia_Obj_t * pObj) { Gia_ObjRefDec(p, Gia_ObjFanin0(pObj)); } static inline void Gia_ObjRefFanin1Dec(Gia_Man_t * p, Gia_Obj_t * pObj) { Gia_ObjRefDec(p, Gia_ObjFanin1(pObj)); } static inline void Gia_ObjRefFanin2Dec(Gia_Man_t * p, Gia_Obj_t * pObj) { Gia_ObjRefDec(p, Gia_ObjFanin2(p, pObj)); } static inline int Gia_ObjLutRefNumId( Gia_Man_t * p, int Id ) { assert(p->pLutRefs); return p->pLutRefs[Id]; } static inline int Gia_ObjLutRefIncId( Gia_Man_t * p, int Id ) { assert(p->pLutRefs); return p->pLutRefs[Id]++; } static inline int Gia_ObjLutRefDecId( Gia_Man_t * p, int Id ) { assert(p->pLutRefs); return --p->pLutRefs[Id]; } static inline int Gia_ObjLutRefNum( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert(p->pLutRefs); return p->pLutRefs[Gia_ObjId(p, pObj)]; } static inline int Gia_ObjLutRefInc( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert(p->pLutRefs); return p->pLutRefs[Gia_ObjId(p, pObj)]++; } static inline int Gia_ObjLutRefDec( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert(p->pLutRefs); return --p->pLutRefs[Gia_ObjId(p, pObj)]; } static inline void Gia_ObjSetTravIdCurrent( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjId(p, pObj) < p->nTravIdsAlloc ); p->pTravIds[Gia_ObjId(p, pObj)] = p->nTravIds; } 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 ); } static inline void Gia_ManTimeStop( Gia_Man_t * p ) { assert( p->vTiming != NULL ); Vec_FltFreeP(&p->vTiming); } static inline float Gia_ObjTimeArrival( Gia_Man_t * p, int Id ) { return Vec_FltEntry(p->vTiming, 3*Id+0); } static inline float Gia_ObjTimeRequired( Gia_Man_t * p, int Id ) { return Vec_FltEntry(p->vTiming, 3*Id+1); } static inline float Gia_ObjTimeSlack( Gia_Man_t * p, int Id ) { return Vec_FltEntry(p->vTiming, 3*Id+2); } static inline float Gia_ObjTimeArrivalObj( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjTimeArrival( p, Gia_ObjId(p, pObj) ); } static inline float Gia_ObjTimeRequiredObj( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjTimeRequired( p, Gia_ObjId(p, pObj) ); } static inline float Gia_ObjTimeSlackObj( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjTimeSlack( p, Gia_ObjId(p, pObj) ); } static inline void Gia_ObjSetTimeArrival( Gia_Man_t * p, int Id, float t ) { Vec_FltWriteEntry( p->vTiming, 3*Id+0, t ); } static inline void Gia_ObjSetTimeRequired( Gia_Man_t * p, int Id, float t ) { Vec_FltWriteEntry( p->vTiming, 3*Id+1, t ); } static inline void Gia_ObjSetTimeSlack( Gia_Man_t * p, int Id, float t ) { Vec_FltWriteEntry( p->vTiming, 3*Id+2, t ); } static inline void Gia_ObjSetTimeArrivalObj( Gia_Man_t * p, Gia_Obj_t * pObj, float t ) { Gia_ObjSetTimeArrival( p, Gia_ObjId(p, pObj), t ); } static inline void Gia_ObjSetTimeRequiredObj( Gia_Man_t * p, Gia_Obj_t * pObj, float t ) { Gia_ObjSetTimeRequired( p, Gia_ObjId(p, pObj), t ); } static inline void Gia_ObjSetTimeSlackObj( Gia_Man_t * p, Gia_Obj_t * pObj, float t ) { Gia_ObjSetTimeSlack( p, Gia_ObjId(p, pObj), t ); } static inline int Gia_ObjSimWords( Gia_Man_t * p ) { return Vec_WrdSize( p->vSimsPi ) / Gia_ManPiNum( p ); } static inline word * Gia_ObjSimPi( Gia_Man_t * p, int PiId ) { return Vec_WrdEntryP( p->vSimsPi, PiId * Gia_ObjSimWords(p) ); } static inline word * Gia_ObjSim( Gia_Man_t * p, int Id ) { return Vec_WrdEntryP( p->vSims, Id * Gia_ObjSimWords(p) ); } static inline word * Gia_ObjSimObj( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjSim( p, Gia_ObjId(p, pObj) ); } // AIG construction extern void Gia_ObjAddFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout ); static inline Gia_Obj_t * Gia_ManAppendObj( Gia_Man_t * p ) { if ( p->nObjs == p->nObjsAlloc ) { int nObjNew = Abc_MinInt( 2 * p->nObjsAlloc, (1 << 29) ); if ( p->nObjs == (1 << 29) ) printf( "Hard limit on the number of nodes (2^29) is reached. Quitting...\n" ), exit(1); assert( p->nObjs < nObjNew ); if ( p->fVerbose ) printf("Extending GIA object storage: %d -> %d.\n", p->nObjsAlloc, nObjNew ); assert( p->nObjsAlloc > 0 ); p->pObjs = ABC_REALLOC( Gia_Obj_t, p->pObjs, nObjNew ); memset( p->pObjs + p->nObjsAlloc, 0, sizeof(Gia_Obj_t) * (nObjNew - p->nObjsAlloc) ); if ( p->pMuxes ) { p->pMuxes = ABC_REALLOC( unsigned, p->pMuxes, nObjNew ); memset( p->pMuxes + p->nObjsAlloc, 0, sizeof(unsigned) * (nObjNew - p->nObjsAlloc) ); } p->nObjsAlloc = nObjNew; } if ( Vec_IntSize(&p->vHTable) ) Vec_IntPush( &p->vHash, 0 ); return Gia_ManObj( p, p->nObjs++ ); } static inline int Gia_ManAppendCi( Gia_Man_t * p ) { Gia_Obj_t * pObj = Gia_ManAppendObj( p ); pObj->fTerm = 1; pObj->iDiff0 = GIA_NONE; pObj->iDiff1 = Vec_IntSize( p->vCis ); Vec_IntPush( p->vCis, Gia_ObjId(p, pObj) ); return Gia_ObjId( p, pObj ) << 1; } extern void Gia_ManQuantSetSuppAnd( Gia_Man_t * p, Gia_Obj_t * pObj ); extern void Gia_ManBuiltInSimPerform( Gia_Man_t * p, int iObj ); static inline int Gia_ManAppendAnd( Gia_Man_t * p, int iLit0, int iLit1 ) { Gia_Obj_t * pObj = Gia_ManAppendObj( p ); assert( iLit0 >= 0 && Abc_Lit2Var(iLit0) < Gia_ManObjNum(p) ); assert( iLit1 >= 0 && Abc_Lit2Var(iLit1) < Gia_ManObjNum(p) ); assert( p->fGiaSimple || Abc_Lit2Var(iLit0) != Abc_Lit2Var(iLit1) ); if ( iLit0 < 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 = (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 ) { Gia_ObjAddFanout( p, Gia_ObjFanin0(pObj), pObj ); Gia_ObjAddFanout( p, Gia_ObjFanin1(pObj), pObj ); } if ( p->fSweeper ) { Gia_Obj_t * pFan0 = Gia_ObjFanin0(pObj); Gia_Obj_t * pFan1 = Gia_ObjFanin1(pObj); if ( pFan0->fMark0 ) pFan0->fMark1 = 1; else pFan0->fMark0 = 1; if ( pFan1->fMark0 ) pFan1->fMark1 = 1; else pFan1->fMark0 = 1; pObj->fPhase = (Gia_ObjPhase(pFan0) ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjPhase(pFan1) ^ Gia_ObjFaninC1(pObj)); } if ( p->fBuiltInSim ) { Gia_Obj_t * pFan0 = Gia_ObjFanin0(pObj); Gia_Obj_t * pFan1 = Gia_ObjFanin1(pObj); pObj->fPhase = (Gia_ObjPhase(pFan0) ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjPhase(pFan1) ^ Gia_ObjFaninC1(pObj)); Gia_ManBuiltInSimPerform( p, Gia_ObjId( p, pObj ) ); } if ( p->vSuppWords ) Gia_ManQuantSetSuppAnd( p, pObj ); return Gia_ObjId( p, pObj ) << 1; } static inline int Gia_ManAppendXorReal( Gia_Man_t * p, int iLit0, int iLit1 ) { Gia_Obj_t * pObj = Gia_ManAppendObj( p ); 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) ); if ( Abc_Lit2Var(iLit0) > Abc_Lit2Var(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 = (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; } static inline int Gia_ManAppendMuxReal( Gia_Man_t * p, int iLitC, int iLit1, int iLit0 ) { Gia_Obj_t * pObj = Gia_ManAppendObj( p ); assert( p->pMuxes != NULL ); assert( iLit0 >= 0 && Abc_Lit2Var(iLit0) < Gia_ManObjNum(p) ); assert( iLit1 >= 0 && Abc_Lit2Var(iLit1) < Gia_ManObjNum(p) ); assert( iLitC >= 0 && Abc_Lit2Var(iLitC) < Gia_ManObjNum(p) ); assert( Abc_Lit2Var(iLit0) != Abc_Lit2Var(iLit1) ); assert( Abc_Lit2Var(iLitC) != Abc_Lit2Var(iLit0) ); assert( Abc_Lit2Var(iLitC) != Abc_Lit2Var(iLit1) ); assert( !Vec_IntSize(&p->vHTable) || !Abc_LitIsCompl(iLit1) ); if ( Abc_Lit2Var(iLit0) < Abc_Lit2Var(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 = (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++; return Gia_ObjId( p, pObj ) << 1; } static inline int Gia_ManAppendBuf( Gia_Man_t * p, int iLit ) { Gia_Obj_t * pObj = Gia_ManAppendObj( p ); assert( iLit >= 0 && Abc_Lit2Var(iLit) < Gia_ManObjNum(p) ); pObj->iDiff0 = pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit); pObj->fCompl0 = pObj->fCompl1 = Abc_LitIsCompl(iLit); p->nBufs++; return Gia_ObjId( p, pObj ) << 1; } static inline int Gia_ManAppendCo( Gia_Man_t * p, int iLit0 ) { Gia_Obj_t * pObj; assert( iLit0 >= 0 && Abc_Lit2Var(iLit0) < Gia_ManObjNum(p) ); assert( !Gia_ObjIsCo(Gia_ManObj(p, Abc_Lit2Var(iLit0))) ); pObj = Gia_ManAppendObj( p ); pObj->fTerm = 1; pObj->iDiff0 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); pObj->fCompl0 = Abc_LitIsCompl(iLit0); pObj->iDiff1 = Vec_IntSize( p->vCos ); Vec_IntPush( p->vCos, Gia_ObjId(p, pObj) ); if ( p->pFanData ) Gia_ObjAddFanout( p, Gia_ObjFanin0(pObj), pObj ); return Gia_ObjId( p, pObj ) << 1; } static inline int Gia_ManAppendOr( Gia_Man_t * p, int iLit0, int iLit1 ) { return Abc_LitNot(Gia_ManAppendAnd( p, Abc_LitNot(iLit0), Abc_LitNot(iLit1) )); } static inline int Gia_ManAppendMux( Gia_Man_t * p, int iCtrl, int iData1, int iData0 ) { int iTemp0 = Gia_ManAppendAnd( p, Abc_LitNot(iCtrl), iData0 ); int iTemp1 = Gia_ManAppendAnd( p, iCtrl, iData1 ); return Abc_LitNotCond( Gia_ManAppendAnd( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), 1 ); } static inline int Gia_ManAppendMaj( Gia_Man_t * p, int iData0, int iData1, int iData2 ) { int iTemp0 = Gia_ManAppendOr( p, iData1, iData2 ); int iTemp1 = Gia_ManAppendAnd( p, iData0, iTemp0 ); int iTemp2 = Gia_ManAppendAnd( p, iData1, iData2 ); return Gia_ManAppendOr( p, iTemp1, iTemp2 ); } static inline int Gia_ManAppendXor( Gia_Man_t * p, int iLit0, int iLit1 ) { return Gia_ManAppendMux( p, iLit0, Abc_LitNot(iLit1), iLit1 ); } static inline int Gia_ManAppendAnd2( Gia_Man_t * p, int iLit0, int iLit1 ) { if ( !p->fGiaSimple ) { if ( iLit0 < 2 ) return iLit0 ? iLit1 : 0; if ( iLit1 < 2 ) return iLit1 ? iLit0 : 0; if ( iLit0 == iLit1 ) return iLit1; if ( iLit0 == Abc_LitNot(iLit1) ) return 0; } return Gia_ManAppendAnd( p, iLit0, iLit1 ); } static inline int Gia_ManAppendOr2( Gia_Man_t * p, int iLit0, int iLit1 ) { return Abc_LitNot(Gia_ManAppendAnd2( p, Abc_LitNot(iLit0), Abc_LitNot(iLit1) )); } static inline int Gia_ManAppendMux2( Gia_Man_t * p, int iCtrl, int iData1, int iData0 ) { int iTemp0 = Gia_ManAppendAnd2( p, Abc_LitNot(iCtrl), iData0 ); int iTemp1 = Gia_ManAppendAnd2( p, iCtrl, iData1 ); return Abc_LitNotCond( Gia_ManAppendAnd2( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), 1 ); } static inline int Gia_ManAppendMaj2( Gia_Man_t * p, int iData0, int iData1, int iData2 ) { int iTemp0 = Gia_ManAppendOr2( p, iData1, iData2 ); int iTemp1 = Gia_ManAppendAnd2( p, iData0, iTemp0 ); int iTemp2 = Gia_ManAppendAnd2( p, iData1, iData2 ); return Gia_ManAppendOr2( p, iTemp1, iTemp2 ); } 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 ); assert( Gia_ObjId(p, pObjCo) > Abc_Lit2Var(iLit0) ); pObjCo->iDiff0 = Gia_ObjId(p, pObjCo) - Abc_Lit2Var(iLit0); pObjCo->fCompl0 = Abc_LitIsCompl(iLit0); } #define GIA_ZER 1 #define GIA_ONE 2 #define GIA_UND 3 static inline int Gia_XsimNotCond( int Value, int fCompl ) { if ( Value == GIA_UND ) return GIA_UND; if ( Value == GIA_ZER + fCompl ) return GIA_ZER; return GIA_ONE; } static inline int Gia_XsimAndCond( int Value0, int fCompl0, int Value1, int fCompl1 ) { if ( Value0 == GIA_ZER + fCompl0 || Value1 == GIA_ZER + fCompl1 ) return GIA_ZER; if ( Value0 == GIA_UND || Value1 == GIA_UND ) return GIA_UND; return GIA_ONE; } static inline void Gia_ObjTerSimSetC( Gia_Obj_t * pObj ) { pObj->fMark0 = 0; pObj->fMark1 = 0; } static inline void Gia_ObjTerSimSet0( Gia_Obj_t * pObj ) { pObj->fMark0 = 1; pObj->fMark1 = 0; } static inline void Gia_ObjTerSimSet1( Gia_Obj_t * pObj ) { pObj->fMark0 = 0; pObj->fMark1 = 1; } static inline void Gia_ObjTerSimSetX( Gia_Obj_t * pObj ) { pObj->fMark0 = 1; pObj->fMark1 = 1; } static inline int Gia_ObjTerSimGetC( Gia_Obj_t * pObj ) { return !pObj->fMark0 && !pObj->fMark1; } static inline int Gia_ObjTerSimGet0( Gia_Obj_t * pObj ) { return pObj->fMark0 && !pObj->fMark1; } static inline int Gia_ObjTerSimGet1( Gia_Obj_t * pObj ) { return !pObj->fMark0 && pObj->fMark1; } static inline int Gia_ObjTerSimGetX( Gia_Obj_t * pObj ) { return pObj->fMark0 && pObj->fMark1; } static inline int Gia_ObjTerSimGet0Fanin0( Gia_Obj_t * pObj ) { return (Gia_ObjTerSimGet1(Gia_ObjFanin0(pObj)) && Gia_ObjFaninC0(pObj)) || (Gia_ObjTerSimGet0(Gia_ObjFanin0(pObj)) && !Gia_ObjFaninC0(pObj)); } static inline int Gia_ObjTerSimGet1Fanin0( Gia_Obj_t * pObj ) { return (Gia_ObjTerSimGet0(Gia_ObjFanin0(pObj)) && Gia_ObjFaninC0(pObj)) || (Gia_ObjTerSimGet1(Gia_ObjFanin0(pObj)) && !Gia_ObjFaninC0(pObj)); } static inline int Gia_ObjTerSimGet0Fanin1( Gia_Obj_t * pObj ) { return (Gia_ObjTerSimGet1(Gia_ObjFanin1(pObj)) && Gia_ObjFaninC1(pObj)) || (Gia_ObjTerSimGet0(Gia_ObjFanin1(pObj)) && !Gia_ObjFaninC1(pObj)); } static inline int Gia_ObjTerSimGet1Fanin1( Gia_Obj_t * pObj ) { return (Gia_ObjTerSimGet0(Gia_ObjFanin1(pObj)) && Gia_ObjFaninC1(pObj)) || (Gia_ObjTerSimGet1(Gia_ObjFanin1(pObj)) && !Gia_ObjFaninC1(pObj)); } static inline void Gia_ObjTerSimAnd( Gia_Obj_t * pObj ) { assert( Gia_ObjIsAnd(pObj) ); assert( !Gia_ObjTerSimGetC( Gia_ObjFanin0(pObj) ) ); assert( !Gia_ObjTerSimGetC( Gia_ObjFanin1(pObj) ) ); if ( Gia_ObjTerSimGet0Fanin0(pObj) || Gia_ObjTerSimGet0Fanin1(pObj) ) Gia_ObjTerSimSet0( pObj ); else if ( Gia_ObjTerSimGet1Fanin0(pObj) && Gia_ObjTerSimGet1Fanin1(pObj) ) Gia_ObjTerSimSet1( pObj ); else Gia_ObjTerSimSetX( pObj ); } static inline void Gia_ObjTerSimCo( Gia_Obj_t * pObj ) { assert( Gia_ObjIsCo(pObj) ); assert( !Gia_ObjTerSimGetC( Gia_ObjFanin0(pObj) ) ); if ( Gia_ObjTerSimGet0Fanin0(pObj) ) Gia_ObjTerSimSet0( pObj ); else if ( Gia_ObjTerSimGet1Fanin0(pObj) ) Gia_ObjTerSimSet1( pObj ); else Gia_ObjTerSimSetX( pObj ); } static inline void Gia_ObjTerSimRo( Gia_Man_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pTemp = Gia_ObjRoToRi(p, pObj); assert( Gia_ObjIsRo(p, pObj) ); assert( !Gia_ObjTerSimGetC( pTemp ) ); pObj->fMark0 = pTemp->fMark0; pObj->fMark1 = pTemp->fMark1; } static inline void Gia_ObjTerSimPrint( Gia_Obj_t * pObj ) { if ( Gia_ObjTerSimGet0(pObj) ) printf( "0" ); else if ( Gia_ObjTerSimGet1(pObj) ) printf( "1" ); else if ( Gia_ObjTerSimGetX(pObj) ) printf( "X" ); } static inline int Gia_AigerReadInt( unsigned char * pPos ) { int i, Value = 0; for ( i = 0; i < 4; i++ ) Value = (Value << 8) | *pPos++; return Value; } static inline void Gia_AigerWriteInt( unsigned char * pPos, int Value ) { int i; for ( i = 3; i >= 0; i-- ) *pPos++ = (Value >> (8*i)) & 255; } static inline unsigned Gia_AigerReadUnsigned( unsigned char ** ppPos ) { unsigned x = 0, i = 0; unsigned char ch; while ((ch = *(*ppPos)++) & 0x80) x |= (ch & 0x7f) << (7 * i++); return x | (ch << (7 * i)); } static inline void Gia_AigerWriteUnsigned( Vec_Str_t * vStr, unsigned x ) { unsigned char ch; while (x & ~0x7f) { ch = (x & 0x7f) | 0x80; Vec_StrPush( vStr, ch ); x >>= 7; } ch = x; Vec_StrPush( vStr, ch ); } static inline void Gia_AigerWriteUnsignedFile( 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 inline int Gia_AigerWriteUnsignedBuffer( unsigned char * pBuffer, int Pos, unsigned x ) { unsigned char ch; while (x & ~0x7f) { ch = (x & 0x7f) | 0x80; pBuffer[Pos++] = ch; x >>= 7; } ch = x; pBuffer[Pos++] = ch; return Pos; } static inline Gia_Obj_t * Gia_ObjReprObj( Gia_Man_t * p, int Id ) { return p->pReprs[Id].iRepr == GIA_VOID ? NULL : Gia_ManObj( p, p->pReprs[Id].iRepr ); } static inline int Gia_ObjRepr( Gia_Man_t * p, int Id ) { return p->pReprs[Id].iRepr; } static inline void Gia_ObjSetRepr( Gia_Man_t * p, int Id, int Num ) { assert( Num == GIA_VOID || Num < Id ); p->pReprs[Id].iRepr = Num; } static inline void Gia_ObjSetReprRev( Gia_Man_t * p, int Id, int Num ){ assert( Num == GIA_VOID || Num > Id ); p->pReprs[Id].iRepr = Num; } static inline void Gia_ObjUnsetRepr( Gia_Man_t * p, int Id ) { p->pReprs[Id].iRepr = GIA_VOID; } static inline int Gia_ObjHasRepr( Gia_Man_t * p, int Id ) { return p->pReprs[Id].iRepr != GIA_VOID; } static inline int Gia_ObjReprSelf( Gia_Man_t * p, int Id ) { return Gia_ObjHasRepr(p, Id) ? Gia_ObjRepr(p, Id) : Id; } static inline int Gia_ObjSibl( Gia_Man_t * p, int Id ) { return p->pSibls ? p->pSibls[Id] : 0; } static inline Gia_Obj_t * Gia_ObjSiblObj( Gia_Man_t * p, int Id ) { return (p->pSibls && p->pSibls[Id]) ? Gia_ManObj(p, p->pSibls[Id]) : NULL; } static inline int Gia_ObjProved( Gia_Man_t * p, int Id ) { return p->pReprs[Id].fProved; } static inline void Gia_ObjSetProved( Gia_Man_t * p, int Id ) { p->pReprs[Id].fProved = 1; } static inline void Gia_ObjUnsetProved( Gia_Man_t * p, int Id ) { p->pReprs[Id].fProved = 0; } static inline int Gia_ObjFailed( Gia_Man_t * p, int Id ) { return p->pReprs[Id].fFailed; } static inline void Gia_ObjSetFailed( Gia_Man_t * p, int Id ) { p->pReprs[Id].fFailed = 1; } static inline int Gia_ObjColor( Gia_Man_t * p, int Id, int c ) { return c? p->pReprs[Id].fColorB : p->pReprs[Id].fColorA; } static inline int Gia_ObjColors( Gia_Man_t * p, int Id ) { return p->pReprs[Id].fColorB * 2 + p->pReprs[Id].fColorA; } static inline void Gia_ObjSetColor( Gia_Man_t * p, int Id, int c ) { if (c) p->pReprs[Id].fColorB = 1; else p->pReprs[Id].fColorA = 1; } static inline void Gia_ObjSetColors( Gia_Man_t * p, int Id ) { p->pReprs[Id].fColorB = p->pReprs[Id].fColorA = 1; } static inline int Gia_ObjVisitColor( Gia_Man_t * p, int Id, int c ) { int x; if (c) { x = p->pReprs[Id].fColorB; p->pReprs[Id].fColorB = 1; } else { x = p->pReprs[Id].fColorA; p->pReprs[Id].fColorA = 1; } return x; } static inline int Gia_ObjDiffColors( Gia_Man_t * p, int i, int j ) { return (p->pReprs[i].fColorA ^ p->pReprs[j].fColorA) && (p->pReprs[i].fColorB ^ p->pReprs[j].fColorB); } static inline int Gia_ObjDiffColors2( Gia_Man_t * p, int i, int j ) { return (p->pReprs[i].fColorA ^ p->pReprs[j].fColorA) || (p->pReprs[i].fColorB ^ p->pReprs[j].fColorB); } static inline Gia_Obj_t * Gia_ObjNextObj( Gia_Man_t * p, int Id ) { return p->pNexts[Id] == 0 ? NULL : Gia_ManObj( p, p->pNexts[Id] );} static inline int Gia_ObjNext( Gia_Man_t * p, int Id ) { return p->pNexts[Id]; } static inline void Gia_ObjSetNext( Gia_Man_t * p, int Id, int Num ) { p->pNexts[Id] = Num; } static inline int Gia_ObjIsConst( Gia_Man_t * p, int Id ) { return Gia_ObjRepr(p, Id) == 0; } static inline int Gia_ObjIsHead( Gia_Man_t * p, int Id ) { return Gia_ObjRepr(p, Id) == GIA_VOID && Gia_ObjNext(p, Id) > 0; } static inline int Gia_ObjIsNone( Gia_Man_t * p, int Id ) { return Gia_ObjRepr(p, Id) == GIA_VOID && Gia_ObjNext(p, Id) <= 0; } static inline int Gia_ObjIsTail( Gia_Man_t * p, int Id ) { return (Gia_ObjRepr(p, Id) > 0 && Gia_ObjRepr(p, Id) != GIA_VOID) && Gia_ObjNext(p, Id) <= 0; } static inline int Gia_ObjIsClass( Gia_Man_t * p, int Id ) { return (Gia_ObjRepr(p, Id) > 0 && Gia_ObjRepr(p, Id) != GIA_VOID) || Gia_ObjNext(p, Id) > 0; } static inline int Gia_ObjHasSameRepr( Gia_Man_t * p, int i, int k ) { assert( k ); return i? (Gia_ObjRepr(p, i) == Gia_ObjRepr(p, k) && Gia_ObjRepr(p, i) != GIA_VOID) : Gia_ObjRepr(p, k) == 0; } static inline int Gia_ObjIsFailedPair( Gia_Man_t * p, int i, int k ) { assert( k ); return i? (Gia_ObjFailed(p, i) || Gia_ObjFailed(p, k)) : Gia_ObjFailed(p, k); } static inline int Gia_ClassIsPair( Gia_Man_t * p, int i ) { assert( Gia_ObjIsHead(p, i) ); assert( Gia_ObjNext(p, i) ); return Gia_ObjNext(p, Gia_ObjNext(p, i)) <= 0; } static inline void Gia_ClassUndoPair( Gia_Man_t * p, int i ) { assert( Gia_ClassIsPair(p,i) ); Gia_ObjSetRepr(p, Gia_ObjNext(p, i), GIA_VOID); Gia_ObjSetNext(p, i, 0); } #define Gia_ManForEachConst( p, i ) \ for ( i = 1; i < Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsConst(p, i) ) {} else #define Gia_ManForEachClass( p, i ) \ for ( i = 1; i < Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsHead(p, i) ) {} else #define Gia_ManForEachClass0( p, i ) \ for ( i = 0; i < Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsHead(p, i) ) {} else #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) && 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 ); } static inline int Gia_ObjFoffset( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjFoffsetId( p, Gia_ObjId(p, pObj) ); } static inline int Gia_ObjFanoutNumId( Gia_Man_t * p, int Id ) { return Vec_IntEntry( p->vFanoutNums, Id ); } static inline int Gia_ObjFanoutNum( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjFanoutNumId( p, Gia_ObjId(p, pObj) ); } static inline int Gia_ObjFanoutId( Gia_Man_t * p, int Id, int i ) { return Vec_IntEntry( p->vFanout, Gia_ObjFoffsetId(p, Id) + i ); } static inline Gia_Obj_t * Gia_ObjFanout0( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ManObj( p, Gia_ObjFanoutId(p, Gia_ObjId(p, pObj), 0) ); } static inline Gia_Obj_t * Gia_ObjFanout( Gia_Man_t * p, Gia_Obj_t * pObj, int i ) { return Gia_ManObj( p, Gia_ObjFanoutId(p, Gia_ObjId(p, pObj), 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_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; } static inline int Gia_ObjLutSize( Gia_Man_t * p, int Id ) { return Vec_IntEntry(p->vMapping, Vec_IntEntry(p->vMapping, Id)); } static inline int * Gia_ObjLutFanins( Gia_Man_t * p, int Id ) { return Vec_IntEntryP(p->vMapping, Vec_IntEntry(p->vMapping, Id)) + 1; } static inline int Gia_ObjLutFanin( Gia_Man_t * p, int Id, int i ) { return Gia_ObjLutFanins(p, Id)[i]; } static inline int Gia_ObjLutMuxId( Gia_Man_t * p, int Id ) { return Gia_ObjLutFanins(p, Id)[Gia_ObjLutSize(p, Id)]; } static inline int Gia_ObjLutIsMux( Gia_Man_t * p, int Id ) { return (int)(Gia_ObjLutMuxId(p, Id) < 0); } static inline int Gia_ManHasMapping2( Gia_Man_t * p ) { return p->vMapping2 != NULL; } static inline int Gia_ObjIsLut2( Gia_Man_t * p, int Id ) { return Vec_IntSize(Vec_WecEntry(p->vMapping2, Id)) != 0; } static inline int Gia_ObjLutSize2( Gia_Man_t * p, int Id ) { return Vec_IntSize(Vec_WecEntry(p->vMapping2, Id)); } static inline Vec_Int_t * Gia_ObjLutFanins2( Gia_Man_t * p, int Id ) { return Vec_WecEntry(p->vMapping2, Id); } static inline int Gia_ObjLutFanin2( Gia_Man_t * p, int Id, int i ) { return Vec_IntEntry(Vec_WecEntry(p->vMapping2, Id), i); } static inline int Gia_ObjLutFanoutNum2( Gia_Man_t * p, int Id ) { return Vec_IntSize(Vec_WecEntry(p->vFanouts2, Id)); } static inline int Gia_ObjLutFanout2( Gia_Man_t * p, int Id, int i ) { return Vec_IntEntry(Vec_WecEntry(p->vFanouts2, Id), i); } static inline int Gia_ManHasCellMapping( Gia_Man_t * p ) { return p->vCellMapping != NULL; } static inline int Gia_ObjIsCell( Gia_Man_t * p, int iLit ) { return Vec_IntEntry(p->vCellMapping, iLit) != 0; } static inline int Gia_ObjIsCellInv( Gia_Man_t * p, int iLit ) { return Vec_IntEntry(p->vCellMapping, iLit) == -1; } static inline int Gia_ObjIsCellBuf( Gia_Man_t * p, int iLit ) { return Vec_IntEntry(p->vCellMapping, iLit) == -2; } static inline int Gia_ObjCellSize( Gia_Man_t * p, int iLit ) { return Vec_IntEntry(p->vCellMapping, Vec_IntEntry(p->vCellMapping, iLit)); } static inline int * Gia_ObjCellFanins( Gia_Man_t * p, int iLit ) { return Vec_IntEntryP(p->vCellMapping, Vec_IntEntry(p->vCellMapping, iLit))+1; } static inline int Gia_ObjCellFanin( Gia_Man_t * p, int iLit, int i ){ return Gia_ObjCellFanins(p, iLit)[i]; } static inline int Gia_ObjCellId( Gia_Man_t * p, int iLit ) { return Gia_ObjCellFanins(p, iLit)[Gia_ObjCellSize(p, iLit)]; } #define Gia_ManForEachLut( p, i ) \ for ( i = 1; i < Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsLut(p, i) ) {} else #define Gia_ManForEachLutReverse( p, i ) \ 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++ ) #define Gia_ManForEachLut2( p, i ) \ for ( i = 1; i < Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsLut2(p, i) ) {} else #define Gia_ManForEachLut2Reverse( p, i ) \ for ( i = Gia_ManObjNum(p) - 1; i > 0; i-- ) if ( !Gia_ObjIsLut2(p, i) ) {} else #define Gia_ManForEachLut2Vec( vIds, p, vVec, iObj, i ) \ for ( i = 0; i < Vec_IntSize(vIds) && (vVec = Vec_WecEntry(p->vMapping2, (iObj = Vec_IntEntry(vIds, i)))); i++ ) #define Gia_ManForEachLut2VecReverse( vIds, p, vVec, iObj, i ) \ for ( i = Vec_IntSize(vIds)-1; i >= 0 && (vVec = Vec_WecEntry(p->vMapping2, (iObj = Vec_IntEntry(vIds, i)))); i-- ) #define Gia_LutForEachFanin2( p, i, iFan, k ) \ for ( k = 0; k < Gia_ObjLutSize2(p,i) && ((iFan = Gia_ObjLutFanin2(p,i,k)),1); k++ ) #define Gia_LutForEachFanout2( p, i, iFan, k ) \ for ( k = 0; k < Gia_ObjLutFanoutNum2(p,i) && ((iFan = Gia_ObjLutFanout2(p,i,k)),1); k++ ) #define Gia_ManForEachCell( p, i ) \ for ( i = 2; i < 2*Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsCell(p, i) ) {} else #define Gia_CellForEachFanin( p, i, iFanLit, k ) \ for ( k = 0; k < Gia_ObjCellSize(p,i) && ((iFanLit = Gia_ObjCellFanins(p,i)[k]),1); k++ ) //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define Gia_ManForEachObj( p, pObj, i ) \ for ( i = 0; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ ) #define Gia_ManForEachObj1( p, pObj, i ) \ 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_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++ ) #define Gia_ManForEachObjReverse( p, pObj, i ) \ for ( i = p->nObjs - 1; (i >= 0) && ((pObj) = Gia_ManObj(p, i)); i-- ) #define Gia_ManForEachObjReverse1( p, pObj, i ) \ for ( i = p->nObjs - 1; (i > 0) && ((pObj) = Gia_ManObj(p, i)); i-- ) #define Gia_ManForEachBuf( p, pObj, i ) \ for ( i = Gia_ManBufNum(p) ? 0 : p->nObjs; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ ) if ( !Gia_ObjIsBuf(pObj) ) {} else #define Gia_ManForEachBufId( p, i ) \ for ( i = 0; (i < p->nObjs); i++ ) if ( !Gia_ObjIsBuf(Gia_ManObj(p, i)) ) {} else #define Gia_ManForEachAnd( p, pObj, i ) \ for ( i = 0; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ ) if ( !Gia_ObjIsAnd(pObj) ) {} else #define Gia_ManForEachAndId( p, i ) \ for ( i = 0; (i < p->nObjs); i++ ) if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) ) {} else #define Gia_ManForEachMuxId( p, i ) \ for ( i = 0; (i < p->nObjs); i++ ) if ( !Gia_ObjIsMuxId(p, i) ) {} else #define Gia_ManForEachCand( p, pObj, i ) \ for ( i = 0; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ ) if ( !Gia_ObjIsCand(pObj) ) {} else #define Gia_ManForEachAndReverse( p, pObj, i ) \ for ( i = p->nObjs - 1; (i > 0) && ((pObj) = Gia_ManObj(p, i)); i-- ) if ( !Gia_ObjIsAnd(pObj) ) {} else #define Gia_ManForEachAndReverseId( p, i ) \ for ( i = p->nObjs - 1; (i > 0); i-- ) if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) ) {} else #define Gia_ManForEachMux( p, pObj, i ) \ for ( i = 0; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ ) if ( !Gia_ObjIsMuxId(p, i) ) {} else #define Gia_ManForEachCi( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(p->vCis)) && ((pObj) = Gia_ManCi(p, i)); i++ ) #define Gia_ManForEachCiId( p, Id, i ) \ for ( i = 0; (i < Vec_IntSize(p->vCis)) && ((Id) = Gia_ObjId(p, Gia_ManCi(p, i))); i++ ) #define Gia_ManForEachCiVec( vVec, p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManCi(p, Vec_IntEntry(vVec,i))); i++ ) #define Gia_ManForEachCiReverse( p, pObj, i ) \ for ( i = Vec_IntSize(p->vCis) - 1; (i >= 0) && ((pObj) = Gia_ManCi(p, i)); i-- ) #define Gia_ManForEachCo( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(p->vCos)) && ((pObj) = Gia_ManCo(p, i)); i++ ) #define Gia_ManForEachCoVec( vVec, p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManCo(p, Vec_IntEntry(vVec,i))); i++ ) #define Gia_ManForEachCoId( p, Id, i ) \ for ( i = 0; (i < Vec_IntSize(p->vCos)) && ((Id) = Gia_ObjId(p, Gia_ManCo(p, i))); i++ ) #define Gia_ManForEachCoReverse( p, pObj, i ) \ for ( i = Vec_IntSize(p->vCos) - 1; (i >= 0) && ((pObj) = Gia_ManCo(p, i)); i-- ) #define Gia_ManForEachCoDriver( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(p->vCos)) && ((pObj) = Gia_ObjFanin0(Gia_ManCo(p, i))); i++ ) #define Gia_ManForEachCoDriverId( p, DriverId, i ) \ for ( i = 0; (i < Vec_IntSize(p->vCos)) && (((DriverId) = Gia_ObjFaninId0p(p, Gia_ManCo(p, i))), 1); i++ ) #define Gia_ManForEachPi( p, pObj, i ) \ for ( i = 0; (i < Gia_ManPiNum(p)) && ((pObj) = Gia_ManCi(p, i)); i++ ) #define Gia_ManForEachPo( p, pObj, i ) \ for ( i = 0; (i < Gia_ManPoNum(p)) && ((pObj) = Gia_ManCo(p, i)); i++ ) #define Gia_ManForEachRo( p, pObj, i ) \ for ( i = 0; (i < Gia_ManRegNum(p)) && ((pObj) = Gia_ManCi(p, Gia_ManPiNum(p)+i)); i++ ) #define Gia_ManForEachRi( p, pObj, i ) \ 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++ ) #define Gia_ManForEachObjWithBoxes( p, pObj, i ) \ for ( i = p->iFirstAndObj; (i < p->iFirstPoObj) && ((pObj) = Gia_ManObj(p, i)); i++ ) #define Gia_ManForEachObjReverseWithBoxes( p, pObj, i ) \ for ( i = p->iFirstPoObj - 1; (i >= p->iFirstAndObj) && ((pObj) = Gia_ManObj(p, i)); i-- ) #define Gia_ManForEachCiIdWithBoxes( p, Id, i ) \ for ( i = 0; (i < p->iFirstNonPiId) && ((Id) = Gia_ObjId(p, Gia_ManCi(p, i))); i++ ) #define Gia_ManForEachCoWithBoxes( p, pObj, i ) \ for ( i = p->iFirstPoId; (i < Vec_IntSize(p->vCos)) && ((pObj) = Gia_ManCo(p, i)); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== giaAiger.c ===========================================================*/ 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, int fWriteNewLine ); extern void Gia_AigerWriteS( Gia_Man_t * p, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine, int fSkipComment ); 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 ); extern void Gia_AigerWriteSimple( Gia_Man_t * pInit, char * pFileName ); /*=== giaBalance.c ===========================================================*/ extern Gia_Man_t * Gia_ManBalance( Gia_Man_t * p, int fSimpleAnd, int fStrict, int fVerbose ); extern Gia_Man_t * Gia_ManAreaBalance( Gia_Man_t * p, int fSimpleAnd, int nNewNodesMax, int fVerbose, int fVeryVerbose ); extern Gia_Man_t * Gia_ManAigSyn2( Gia_Man_t * p, int fOldAlgo, int fCoarsen, int fCutMin, int nRelaxRatio, int fDelayMin, int fVerbose, int fVeryVerbose ); extern Gia_Man_t * Gia_ManAigSyn3( Gia_Man_t * p, int fVerbose, int fVeryVerbose ); extern Gia_Man_t * Gia_ManAigSyn4( Gia_Man_t * p, int fVerbose, int fVeryVerbose ); /*=== giaBidec.c ===========================================================*/ extern unsigned * Gia_ManConvertAigToTruth( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vTruth, Vec_Int_t * vVisited ); extern Gia_Man_t * Gia_ManPerformBidec( Gia_Man_t * p, int fVerbose ); /*=== giaCex.c ============================================================*/ extern int Gia_ManVerifyCex( Gia_Man_t * pAig, Abc_Cex_t * p, int fDualOut ); extern int Gia_ManFindFailedPoCex( Gia_Man_t * pAig, Abc_Cex_t * p, int nOutputs ); extern int Gia_ManSetFailedPoCex( Gia_Man_t * pAig, Abc_Cex_t * p ); extern void Gia_ManCounterExampleValueStart( Gia_Man_t * pGia, Abc_Cex_t * pCex ); extern void Gia_ManCounterExampleValueStop( Gia_Man_t * pGia ); extern int Gia_ManCounterExampleValueLookup( Gia_Man_t * pGia, int Id, int iFrame ); extern Abc_Cex_t * Gia_ManCexExtendToIncludeCurrentStates( Gia_Man_t * p, Abc_Cex_t * pCex ); extern Abc_Cex_t * Gia_ManCexExtendToIncludeAllObjects( Gia_Man_t * p, Abc_Cex_t * pCex ); /*=== giaCsatOld.c ============================================================*/ extern Vec_Int_t * Cbs_ManSolveMiter( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ); /*=== giaCsat.c ============================================================*/ typedef struct Cbs_Man_t_ Cbs_Man_t; 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 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 ============================================================*/ extern Vec_Int_t * Tas_ManSolveMiterNc( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ); /*=== giaCof.c =============================================================*/ 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 ); /*=== giaDup.c ============================================================*/ extern void Gia_ManDupRemapLiterals( Vec_Int_t * vLits, Gia_Man_t * p ); 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, 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 ); extern Gia_Man_t * Gia_ManDupOrderAiger( Gia_Man_t * p ); 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 ); extern Gia_Man_t * Gia_ManDupZero( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupPerm( Gia_Man_t * p, Vec_Int_t * vPiPerm ); extern Gia_Man_t * Gia_ManDupPermFlop( Gia_Man_t * p, Vec_Int_t * vFfPerm ); extern Gia_Man_t * Gia_ManDupPermFlopGap( Gia_Man_t * p, Vec_Int_t * vFfPerm ); extern void Gia_ManDupAppend( Gia_Man_t * p, Gia_Man_t * pTwo ); extern void Gia_ManDupAppendShare( Gia_Man_t * p, Gia_Man_t * pTwo ); extern Gia_Man_t * Gia_ManDupAppendNew( Gia_Man_t * pOne, Gia_Man_t * pTwo ); extern Gia_Man_t * Gia_ManDupAppendCones( Gia_Man_t * p, Gia_Man_t ** ppCones, int nCones, int fOnlyRegs ); extern Gia_Man_t * Gia_ManDupSelf( Gia_Man_t * p ); 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 ); extern Gia_Man_t * Gia_ManDupBlock( Gia_Man_t * p, int nBlock ); extern Gia_Man_t * Gia_ManDupExist( Gia_Man_t * p, int iVar ); extern Gia_Man_t * Gia_ManDupUniv( Gia_Man_t * p, int iVar ); extern Gia_Man_t * Gia_ManDupDfsSkip( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupDfsCone( Gia_Man_t * p, Gia_Obj_t * pObj ); extern Gia_Man_t * Gia_ManDupConeSupp( Gia_Man_t * p, int iLit, Vec_Int_t * vCiIds ); extern int Gia_ManDupConeBack( Gia_Man_t * p, Gia_Man_t * pNew, Vec_Int_t * vCiIds ); extern int Gia_ManDupConeBackObjs( Gia_Man_t * p, Gia_Man_t * pNew, Vec_Int_t * vObjs ); extern Gia_Man_t * Gia_ManDupDfsNode( Gia_Man_t * p, Gia_Obj_t * pObj ); extern Gia_Man_t * Gia_ManDupDfsLitArray( Gia_Man_t * p, Vec_Int_t * vLits ); extern Gia_Man_t * Gia_ManDupTrimmed( Gia_Man_t * p, int fTrimCis, int fTrimCos, int fDualOut, int OutValue ); extern Gia_Man_t * Gia_ManDupOntop( Gia_Man_t * p, Gia_Man_t * p2 ); extern Gia_Man_t * Gia_ManDupWithNewPo( Gia_Man_t * p1, Gia_Man_t * p2 ); extern Gia_Man_t * Gia_ManDupDfsCiMap( Gia_Man_t * p, int * pCi2Lit, Vec_Int_t * vLits ); extern Gia_Man_t * Gia_ManPermuteInputs( Gia_Man_t * p, int nPpis, int nExtra ); 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 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 ); extern Gia_Man_t * Gia_ManTransformToDual( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManTransformTwoWord2DualOutput( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManChoiceMiter( Vec_Ptr_t * vGias ); extern Gia_Man_t * Gia_ManDupWithConstraints( Gia_Man_t * p, Vec_Int_t * vPoTypes ); extern Gia_Man_t * Gia_ManDupCones( Gia_Man_t * p, int * pPos, int nPos, int fTrimPis ); extern Gia_Man_t * Gia_ManDupAndCones( Gia_Man_t * p, int * pAnds, int nAnds, int fTrimPis ); extern Gia_Man_t * Gia_ManDupAndConesLimit( Gia_Man_t * p, int * pAnds, int nAnds, int Level ); extern Gia_Man_t * Gia_ManDupAndConesLimit2( Gia_Man_t * p, int * pAnds, int nAnds, int Level ); extern Gia_Man_t * Gia_ManDupOneHot( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupLevelized( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupFromVecs( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs ); extern Gia_Man_t * Gia_ManDupSliced( Gia_Man_t * p, int nSuppMax ); 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 ); extern void Gia_ManConvertPackingToEdges( Gia_Man_t * p ); extern int Gia_ObjCheckEdge( Gia_Man_t * p, int iObj, int iNext ); extern int Gia_ManEvalEdgeDelay( Gia_Man_t * p ); extern int Gia_ManEvalEdgeCount( Gia_Man_t * p ); extern int Gia_ManComputeEdgeDelay( Gia_Man_t * p, int fUseTwo ); extern int Gia_ManComputeEdgeDelay2( Gia_Man_t * p ); extern void Gia_ManUpdateMapping( Gia_Man_t * p, Vec_Int_t * vNodes, Vec_Wec_t * vWin ); extern int Gia_ManEvalWindow( Gia_Man_t * p, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Wec_t * vWin, Vec_Int_t * vTemp, int fUseTwo ); /*=== giaEnable.c ==========================================================*/ extern void Gia_ManDetectSeqSignals( Gia_Man_t * p, int fSetReset, int fVerbose ); extern Gia_Man_t * Gia_ManUnrollAndCofactor( Gia_Man_t * p, int nFrames, int nFanMax, int fVerbose ); extern Gia_Man_t * Gia_ManRemoveEnables( Gia_Man_t * p ); /*=== giaEquiv.c ==========================================================*/ extern void Gia_ManOrigIdsInit( Gia_Man_t * p ); extern void Gia_ManOrigIdsStart( Gia_Man_t * p ); extern void Gia_ManOrigIdsRemap( Gia_Man_t * p, Gia_Man_t * pNew ); extern Gia_Man_t * Gia_ManOrigIdsReduce( Gia_Man_t * p, Vec_Int_t * vPairs ); extern Gia_Man_t * Gia_ManComputeGiaEquivs( Gia_Man_t * pGia, int nConfs, int fVerbose ); extern void Gia_ManEquivFixOutputPairs( Gia_Man_t * p ); extern int Gia_ManCheckTopoOrder( Gia_Man_t * p ); extern int * Gia_ManDeriveNexts( Gia_Man_t * p ); extern void Gia_ManDeriveReprs( Gia_Man_t * p ); extern void Gia_ManDeriveReprsFromSibls( Gia_Man_t *p ); extern int Gia_ManEquivCountLits( Gia_Man_t * p ); extern int Gia_ManEquivCountLitsAll( Gia_Man_t * p ); extern int Gia_ManEquivCountClasses( Gia_Man_t * p ); extern void Gia_ManEquivPrintOne( Gia_Man_t * p, int i, int Counter ); extern void Gia_ManEquivPrintClasses( Gia_Man_t * p, int fVerbose, float Mem ); extern Gia_Man_t * Gia_ManEquivReduce( Gia_Man_t * p, int fUseAll, int fDualOut, int fSkipPhase, int fVerbose ); extern Gia_Man_t * Gia_ManEquivReduceAndRemap( Gia_Man_t * p, int fSeq, int fMiterPairs ); extern int Gia_ManEquivSetColors( Gia_Man_t * p, int fVerbose ); extern Gia_Man_t * Gia_ManSpecReduce( Gia_Man_t * p, int fDualOut, int fSynthesis, int fReduce, int fSkipSome, int fVerbose ); extern Gia_Man_t * Gia_ManSpecReduceInit( Gia_Man_t * p, Abc_Cex_t * pInit, int nFrames, int fDualOut ); extern Gia_Man_t * Gia_ManSpecReduceInitFrames( Gia_Man_t * p, Abc_Cex_t * pInit, int nFramesMax, int * pnFrames, int fDualOut, int nMinOutputs ); extern void Gia_ManEquivTransform( Gia_Man_t * p, int fVerbose ); extern void Gia_ManEquivImprove( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManEquivToChoices( Gia_Man_t * p, int nSnapshots ); extern int Gia_ManCountChoiceNodes( Gia_Man_t * p ); extern int Gia_ManCountChoices( Gia_Man_t * p ); extern int Gia_ManFilterEquivsForSpeculation( Gia_Man_t * pGia, char * pName1, char * pName2, int fLatchA, int fLatchB ); extern int Gia_ManFilterEquivsUsingParts( Gia_Man_t * pGia, char * pName1, char * pName2 ); extern void Gia_ManFilterEquivsUsingLatches( Gia_Man_t * pGia, int fFlopsOnly, int fFlopsWith, int fUseRiDrivers ); /*=== giaExist.c =========================================================*/ extern void Gia_ManQuantSetSuppStart( Gia_Man_t * p ); extern void Gia_ManQuantSetSuppZero( Gia_Man_t * p ); extern void Gia_ManQuantSetSuppCi( Gia_Man_t * p, Gia_Obj_t * pObj ); extern void Gia_ManQuantUpdateCiSupp( Gia_Man_t * p, int iObj ); extern int Gia_ManQuantExist( Gia_Man_t * p, int iLit, int(*pFuncCiToKeep)(void *, int), void * pData ); /*=== giaFanout.c =========================================================*/ extern void Gia_ObjAddFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout ); extern void Gia_ObjRemoveFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout ); 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 =========================================================*/ extern Gia_Man_t * Gia_ManUnrollDup( Gia_Man_t * p, Vec_Int_t * vLimit ); extern Vec_Ptr_t * Gia_ManUnrollAbs( Gia_Man_t * p, int nFrames ); extern void * Gia_ManUnrollStart( Gia_Man_t * pAig, Gia_ParFra_t * pPars ); extern void * Gia_ManUnrollAdd( void * pMan, int fMax ); extern void Gia_ManUnrollStop( void * pMan ); extern int Gia_ManUnrollLastLit( void * pMan ); extern void Gia_ManFraSetDefaultParams( Gia_ParFra_t * p ); extern Gia_Man_t * Gia_ManFrames( Gia_Man_t * pAig, Gia_ParFra_t * pPars ); extern Gia_Man_t * Gia_ManFramesInitSpecial( Gia_Man_t * pAig, int nFrames, int fVerbose ); /*=== giaFront.c ==========================================================*/ extern Gia_Man_t * Gia_ManFront( Gia_Man_t * p ); extern void Gia_ManFrontTest( Gia_Man_t * p ); /*=== giaFx.c ==========================================================*/ extern Gia_Man_t * Gia_ManPerformFx( Gia_Man_t * p, int nNewNodesMax, int LitCountMax, int fReverse, int fVerbose, int fVeryVerbose ); /*=== giaHash.c ===========================================================*/ extern void Gia_ManHashAlloc( Gia_Man_t * p ); extern void Gia_ManHashStart( Gia_Man_t * p ); extern void Gia_ManHashStop( Gia_Man_t * p ); extern int Gia_ManHashXorReal( Gia_Man_t * p, int iLit0, int iLit1 ); extern int Gia_ManHashMuxReal( Gia_Man_t * p, int iLitC, int iLit1, int iLit0 ); extern int Gia_ManHashAnd( Gia_Man_t * p, int iLit0, int iLit1 ); extern int Gia_ManHashOr( Gia_Man_t * p, int iLit0, int iLit1 ); extern int Gia_ManHashXor( Gia_Man_t * p, int iLit0, int iLit1 ); extern int Gia_ManHashMux( Gia_Man_t * p, int iCtrl, int iData1, int iData0 ); extern int Gia_ManHashMaj( Gia_Man_t * p, int iData0, int iData1, int iData2 ); extern int Gia_ManHashAndTry( Gia_Man_t * p, int iLit0, int iLit1 ); extern Gia_Man_t * Gia_ManRehash( Gia_Man_t * p, int fAddStrash ); extern void Gia_ManHashProfile( Gia_Man_t * p ); extern int Gia_ManHashLookupInt( Gia_Man_t * p, int iLit0, int iLit1 ); 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 ); extern void Gia_ManPrintLutStats( Gia_Man_t * p ); extern int Gia_ManLutFaninCount( Gia_Man_t * p ); extern int Gia_ManLutSizeMax( Gia_Man_t * p ); extern int Gia_ManLutNum( Gia_Man_t * p ); extern int Gia_ManLutLevel( Gia_Man_t * p, int ** ppLevels ); extern void Gia_ManLutParams( Gia_Man_t * p, int * pnCurLuts, int * pnCurEdges, int * pnCurLevels ); extern void Gia_ManSetRefsMapped( Gia_Man_t * p ); extern void Gia_ManSetLutRefs( Gia_Man_t * p ); extern void Gia_ManSetIfParsDefault( void * pIfPars ); extern void Gia_ManMappingVerify( Gia_Man_t * p ); extern void Gia_ManTransferMapping( Gia_Man_t * p, Gia_Man_t * pGia ); extern void Gia_ManTransferPacking( Gia_Man_t * p, Gia_Man_t * pGia ); extern void Gia_ManTransferTiming( Gia_Man_t * p, Gia_Man_t * pGia ); extern Gia_Man_t * Gia_ManPerformMapping( Gia_Man_t * p, void * pIfPars ); extern Gia_Man_t * Gia_ManPerformSopBalance( Gia_Man_t * p, int nCutNum, int nRelaxRatio, int fVerbose ); extern Gia_Man_t * Gia_ManPerformDsdBalance( Gia_Man_t * p, int nLutSize, int nCutNum, int nRelaxRatio, int fVerbose ); extern Gia_Man_t * Gia_ManDupHashMapping( Gia_Man_t * p ); /*=== giaJf.c ===========================================================*/ extern void Jf_ManSetDefaultPars( Jf_Par_t * pPars ); extern Gia_Man_t * Jf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ); extern Gia_Man_t * Jf_ManDeriveCnf( Gia_Man_t * p, int fCnfObjIds ); /*=== giaIso.c ===========================================================*/ extern Gia_Man_t * Gia_ManIsoCanonicize( Gia_Man_t * p, int fVerbose ); extern Gia_Man_t * Gia_ManIsoReduce( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, Vec_Ptr_t ** pvPiPerms, int fEstimate, int fDualOut, int fVerbose, int fVeryVerbose ); extern Gia_Man_t * Gia_ManIsoReduce2( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, Vec_Ptr_t ** pvPiPerms, int fEstimate, int fBetterQual, int fDualOut, int fVerbose, int fVeryVerbose ); /*=== giaLf.c ===========================================================*/ extern void Lf_ManSetDefaultPars( Jf_Par_t * pPars ); extern Gia_Man_t * Lf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ); extern Gia_Man_t * Gia_ManPerformLfMapping( Gia_Man_t * p, Jf_Par_t * pPars, int fNormalized ); /*=== giaLogic.c ===========================================================*/ extern void Gia_ManTestDistance( Gia_Man_t * p ); extern void Gia_ManSolveProblem( Gia_Man_t * pGia, Emb_Par_t * pPars ); /*=== giaMan.c ===========================================================*/ extern Gia_Man_t * Gia_ManStart( int nObjsMax ); extern void Gia_ManStop( Gia_Man_t * p ); extern void Gia_ManStopP( Gia_Man_t ** p ); extern double Gia_ManMemory( Gia_Man_t * p ); extern void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars ); extern void Gia_ManPrintStatsShort( Gia_Man_t * p ); extern void Gia_ManPrintMiterStatus( Gia_Man_t * p ); 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, int fInterComb, int fAssign, int fReverse ); extern void Gia_ManDumpVerilogNand( Gia_Man_t * p, char * pFileName ); /*=== giaMem.c ===========================================================*/ extern Gia_MmFixed_t * Gia_MmFixedStart( int nEntrySize, int nEntriesMax ); extern void Gia_MmFixedStop( Gia_MmFixed_t * p, int fVerbose ); extern char * Gia_MmFixedEntryFetch( Gia_MmFixed_t * p ); extern void Gia_MmFixedEntryRecycle( Gia_MmFixed_t * p, char * pEntry ); extern void Gia_MmFixedRestart( Gia_MmFixed_t * p ); extern int Gia_MmFixedReadMemUsage( Gia_MmFixed_t * p ); extern int Gia_MmFixedReadMaxEntriesUsed( Gia_MmFixed_t * p ); extern Gia_MmFlex_t * Gia_MmFlexStart(); extern void Gia_MmFlexStop( Gia_MmFlex_t * p, int fVerbose ); extern char * Gia_MmFlexEntryFetch( Gia_MmFlex_t * p, int nBytes ); extern void Gia_MmFlexRestart( Gia_MmFlex_t * p ); extern int Gia_MmFlexReadMemUsage( Gia_MmFlex_t * p ); extern Gia_MmStep_t * Gia_MmStepStart( int nSteps ); extern void Gia_MmStepStop( Gia_MmStep_t * p, int fVerbose ); extern char * Gia_MmStepEntryFetch( Gia_MmStep_t * p, int nBytes ); extern void Gia_MmStepEntryRecycle( Gia_MmStep_t * p, char * pEntry, int nBytes ); extern int Gia_MmStepReadMemUsage( Gia_MmStep_t * p ); /*=== giaMf.c ===========================================================*/ 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, 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, 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 ===========================================================*/ extern Gia_Man_t * Gia_ManRetimeForward( Gia_Man_t * p, int nMaxIters, int fVerbose ); /*=== giaSat.c ============================================================*/ extern int Sat_ManTest( Gia_Man_t * pGia, Gia_Obj_t * pObj, int nConfsMax ); /*=== giaScl.c ============================================================*/ extern int Gia_ManSeqMarkUsed( Gia_Man_t * p ); extern int Gia_ManCombMarkUsed( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManCleanup( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManCleanupOutputs( Gia_Man_t * p, int nOutputs ); extern Gia_Man_t * Gia_ManSeqCleanup( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManSeqStructSweep( Gia_Man_t * p, int fConst, int fEquiv, int fVerbose ); /*=== giaShow.c ===========================================================*/ extern void Gia_ManShow( Gia_Man_t * pMan, Vec_Int_t * vBold, int fAdders, int fFadds, int fPath ); /*=== giaShrink.c ===========================================================*/ extern Gia_Man_t * Gia_ManMapShrink4( Gia_Man_t * p, int fKeepLevel, int fVerbose ); extern Gia_Man_t * Gia_ManMapShrink6( Gia_Man_t * p, int nFanoutMax, int fKeepLevel, int fVerbose ); /*=== giaSopb.c ============================================================*/ extern Gia_Man_t * Gia_ManExtractWindow( Gia_Man_t * p, int LevelMax, int nTimeWindow, int fVerbose ); extern Gia_Man_t * Gia_ManPerformSopBalanceWin( Gia_Man_t * p, int LevelMax, int nTimeWindow, int nCutNum, int nRelaxRatio, int fVerbose ); extern Gia_Man_t * Gia_ManPerformDsdBalanceWin( Gia_Man_t * p, int LevelMax, int nTimeWindow, int nLutSize, int nCutNum, int nRelaxRatio, int fVerbose ); /*=== giaSort.c ============================================================*/ extern int * Gia_SortFloats( float * pArray, int * pPerm, int nSize ); /*=== giaSim.c ============================================================*/ extern void Gia_ManSimSetDefaultParams( Gia_ParSim_t * p ); extern int Gia_ManSimSimulate( Gia_Man_t * pAig, Gia_ParSim_t * pPars ); extern unsigned * Gia_SimDataExt( Gia_ManSim_t * p, int i ); extern unsigned * Gia_SimDataCiExt( Gia_ManSim_t * p, int i ); extern unsigned * Gia_SimDataCoExt( Gia_ManSim_t * p, int i ); extern void Gia_ManSimInfoInit( Gia_ManSim_t * p ); extern void Gia_ManSimInfoTransfer( Gia_ManSim_t * p ); extern void Gia_ManSimulateRound( Gia_ManSim_t * p ); extern void Gia_ManBuiltInSimStart( Gia_Man_t * p, int nWords, int nObjs ); extern void Gia_ManBuiltInSimPerform( Gia_Man_t * p, int iObj ); extern int Gia_ManBuiltInSimCheckOver( Gia_Man_t * p, int iLit0, int iLit1 ); extern int Gia_ManBuiltInSimCheckEqual( Gia_Man_t * p, int iLit0, int iLit1 ); extern void Gia_ManBuiltInSimResimulateCone( Gia_Man_t * p, int iLit0, int iLit1 ); extern void Gia_ManBuiltInSimResimulate( Gia_Man_t * p ); extern int Gia_ManBuiltInSimAddPat( Gia_Man_t * p, Vec_Int_t * vPat ); extern void Gia_ManIncrSimStart( Gia_Man_t * p, int nWords, int nObjs ); 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 ); extern Gia_Man_t * Gia_ManSpeedup( Gia_Man_t * p, int Percentage, int Degree, int fVerbose, int fVeryVerbose ); /*=== giaSplit.c ============================================================*/ extern void Gia_ManComputeOneWinStart( Gia_Man_t * p, int nAnds, int fReverse ); extern int Gia_ManComputeOneWin( Gia_Man_t * p, int iPivot, Vec_Int_t ** pvRoots, Vec_Int_t ** pvNodes, Vec_Int_t ** pvLeaves, Vec_Int_t ** pvAnds ); /*=== giaStg.c ============================================================*/ extern void Gia_ManStgPrint( FILE * pFile, Vec_Int_t * vLines, int nIns, int nOuts, int nStates ); extern Gia_Man_t * Gia_ManStgRead( char * pFileName, int kHot, int fVerbose ); /*=== giaSupp.c ============================================================*/ typedef struct Gia_ManMin_t_ Gia_ManMin_t; extern Gia_ManMin_t * Gia_ManSuppStart( Gia_Man_t * pGia ); extern void Gia_ManSuppStop( Gia_ManMin_t * p ); extern int Gia_ManSupportAnd( Gia_ManMin_t * p, int iLit0, int iLit1 ); typedef struct Gia_Man2Min_t_ Gia_Man2Min_t; extern Gia_Man2Min_t * Gia_Man2SuppStart( Gia_Man_t * pGia ); extern void Gia_Man2SuppStop( Gia_Man2Min_t * p ); extern int Gia_Man2SupportAnd( Gia_Man2Min_t * p, int iLit0, int iLit1 ); /*=== giaSweep.c ============================================================*/ extern Gia_Man_t * Gia_ManFraigSweepSimple( Gia_Man_t * p, void * pPars ); extern Gia_Man_t * Gia_ManSweepWithBoxes( Gia_Man_t * p, void * pParsC, void * pParsS, int fConst, int fEquiv, int fVerbose, int fVerbEquivs ); extern void Gia_ManCheckIntegrityWithBoxes( Gia_Man_t * p ); /*=== giaSweeper.c ============================================================*/ extern Gia_Man_t * Gia_SweeperStart( Gia_Man_t * p ); extern void Gia_SweeperStop( Gia_Man_t * p ); extern int Gia_SweeperIsRunning( Gia_Man_t * p ); extern void Gia_SweeperPrintStats( Gia_Man_t * p ); extern void Gia_SweeperSetConflictLimit( Gia_Man_t * p, int nConfMax ); extern void Gia_SweeperSetRuntimeLimit( Gia_Man_t * p, int nSeconds ); extern Vec_Int_t * Gia_SweeperGetCex( Gia_Man_t * p ); extern int Gia_SweeperProbeCreate( Gia_Man_t * p, int iLit ); extern int Gia_SweeperProbeDelete( Gia_Man_t * p, int ProbeId ); extern int Gia_SweeperProbeUpdate( Gia_Man_t * p, int ProbeId, int iLitNew ); extern int Gia_SweeperProbeLit( Gia_Man_t * p, int ProbeId ); extern Vec_Int_t * Gia_SweeperCollectValidProbeIds( Gia_Man_t * p ); extern int Gia_SweeperCondPop( Gia_Man_t * p ); extern void Gia_SweeperCondPush( Gia_Man_t * p, int ProbeId ); extern Vec_Int_t * Gia_SweeperCondVector( Gia_Man_t * p ); extern int Gia_SweeperCondCheckUnsat( Gia_Man_t * p ); extern int Gia_SweeperCheckEquiv( Gia_Man_t * p, int ProbeId1, int ProbeId2 ); extern Gia_Man_t * Gia_SweeperExtractUserLogic( Gia_Man_t * p, Vec_Int_t * vProbeIds, Vec_Ptr_t * vInNames, Vec_Ptr_t * vOutNames ); extern void Gia_SweeperLogicDump( Gia_Man_t * p, Vec_Int_t * vProbeIds, int fDumpConds, char * pFileName ); extern Gia_Man_t * Gia_SweeperCleanup( Gia_Man_t * p, char * pCommLime ); extern Vec_Int_t * Gia_SweeperGraft( Gia_Man_t * pDst, Vec_Int_t * vProbes, Gia_Man_t * pSrc ); extern int Gia_SweeperFraig( Gia_Man_t * p, Vec_Int_t * vProbeIds, char * pCommLime, int nWords, int nConfs, int fVerify, int fVerbose ); extern int Gia_SweeperRun( Gia_Man_t * p, Vec_Int_t * vProbeIds, char * pCommLime, int fVerbose ); /*=== giaSwitch.c ============================================================*/ extern float Gia_ManEvaluateSwitching( Gia_Man_t * p ); extern float Gia_ManComputeSwitching( Gia_Man_t * p, int nFrames, int nPref, int fProbOne ); extern Vec_Int_t * Gia_ManComputeSwitchProbs( Gia_Man_t * pGia, int nFrames, int nPref, int fProbOne ); extern Vec_Int_t * Gia_ManComputeSwitchProbs2( Gia_Man_t * pGia, int nFrames, int nPref, int fProbOne, int nRandPiFactor ); extern Vec_Flt_t * Gia_ManPrintOutputProb( Gia_Man_t * p ); /*=== giaTim.c ===========================================================*/ extern int Gia_ManBoxNum( Gia_Man_t * p ); extern int Gia_ManRegBoxNum( Gia_Man_t * p ); extern int Gia_ManNonRegBoxNum( Gia_Man_t * p ); extern int Gia_ManBlackBoxNum( Gia_Man_t * p ); extern int Gia_ManBoxCiNum( Gia_Man_t * p ); extern int Gia_ManBoxCoNum( Gia_Man_t * p ); extern int Gia_ManClockDomainNum( Gia_Man_t * p ); extern int Gia_ManIsSeqWithBoxes( Gia_Man_t * p ); extern int Gia_ManIsNormalized( Gia_Man_t * p ); extern Vec_Int_t * Gia_ManOrderWithBoxes( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupNormalize( Gia_Man_t * p, int fHashMapping ); extern Gia_Man_t * Gia_ManDupUnnormalize( Gia_Man_t * p ); extern Gia_Man_t * Gia_ManDupUnshuffleInputs( Gia_Man_t * p ); extern int Gia_ManLevelWithBoxes( Gia_Man_t * p ); extern int Gia_ManLutLevelWithBoxes( Gia_Man_t * p ); extern void * Gia_ManUpdateTimMan( Gia_Man_t * p, Vec_Int_t * vBoxPres ); extern void * Gia_ManUpdateTimMan2( Gia_Man_t * p, Vec_Int_t * vBoxesLeft, int nTermsDiff ); extern Gia_Man_t * Gia_ManUpdateExtraAig( void * pTime, Gia_Man_t * pAig, Vec_Int_t * vBoxPres ); extern Gia_Man_t * Gia_ManUpdateExtraAig2( void * pTime, Gia_Man_t * pAig, Vec_Int_t * vBoxesLeft ); extern Gia_Man_t * Gia_ManDupCollapse( Gia_Man_t * p, Gia_Man_t * pBoxes, Vec_Int_t * vBoxPres, int fSeq ); extern int Gia_ManVerifyWithBoxes( Gia_Man_t * pGia, int nBTLimit, int nTimeLim, int fSeq, int fDumpFiles, int fVerbose, char * pFileSpec ); /*=== giaTruth.c ===========================================================*/ extern word Gia_LutComputeTruth6( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTruths ); extern word Gia_ObjComputeTruthTable6Lut( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTemp ); extern word Gia_ObjComputeTruthTable6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp, Vec_Wrd_t * vTruths ); extern word Gia_ObjComputeTruth6Cis( Gia_Man_t * p, int iLit, Vec_Int_t * vSupp, Vec_Wrd_t * vTemp ); extern void Gia_ObjCollectInternal( Gia_Man_t * p, Gia_Obj_t * pObj ); extern word * Gia_ObjComputeTruthTable( Gia_Man_t * p, Gia_Obj_t * pObj ); extern void Gia_ObjComputeTruthTableStart( Gia_Man_t * p, int nVarsMax ); extern void Gia_ObjComputeTruthTableStop( Gia_Man_t * p ); extern word * Gia_ObjComputeTruthTableCut( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves ); /*=== giaTsim.c ============================================================*/ extern Gia_Man_t * Gia_ManReduceConst( Gia_Man_t * pAig, int fVerbose ); /*=== giaUtil.c ===========================================================*/ extern unsigned Gia_ManRandom( int fReset ); extern word Gia_ManRandomW( int fReset ); extern void Gia_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int iWordStop ); extern char * Gia_TimeStamp(); extern char * Gia_FileNameGenericAppend( char * pBase, char * pSuffix ); extern Vec_Ptr_t * Gia_GetFakeNames( int nNames, int fCaps ); extern void Gia_ManIncrementTravId( Gia_Man_t * p ); extern void Gia_ManCleanMark01( Gia_Man_t * p ); extern void Gia_ManSetMark0( Gia_Man_t * p ); extern void Gia_ManCleanMark0( Gia_Man_t * p ); extern void Gia_ManCheckMark0( Gia_Man_t * p ); extern void Gia_ManSetMark1( Gia_Man_t * p ); extern void Gia_ManCleanMark1( Gia_Man_t * p ); extern void Gia_ManCheckMark1( Gia_Man_t * p ); extern void Gia_ManCleanValue( Gia_Man_t * p ); extern void Gia_ManCleanLevels( Gia_Man_t * p, int Size ); extern void Gia_ManCleanTruth( Gia_Man_t * p ); extern void Gia_ManFillValue( Gia_Man_t * p ); extern void Gia_ObjSetPhase( Gia_Man_t * p, Gia_Obj_t * pObj ); extern void Gia_ManSetPhase( Gia_Man_t * p ); extern void Gia_ManSetPhasePattern( Gia_Man_t * p, Vec_Int_t * vCiValues ); 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 ); extern Vec_Int_t * Gia_ManRequiredLevel( Gia_Man_t * p ); extern void Gia_ManCreateValueRefs( Gia_Man_t * p ); extern void Gia_ManCreateRefs( Gia_Man_t * p ); extern void Gia_ManCreateLitRefs( Gia_Man_t * p ); extern int * Gia_ManCreateMuxRefs( Gia_Man_t * p ); extern int Gia_ManCrossCut( Gia_Man_t * p, int fReverse ); extern Vec_Int_t * Gia_ManCollectPoIds( Gia_Man_t * p ); extern int Gia_ObjIsMuxType( Gia_Obj_t * pNode ); extern int Gia_ObjRecognizeExor( Gia_Obj_t * pObj, Gia_Obj_t ** ppFan0, Gia_Obj_t ** ppFan1 ); 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 ); extern void Gia_ObjPrint( Gia_Man_t * p, Gia_Obj_t * pObj ); extern void Gia_ManPrint( Gia_Man_t * p ); extern void Gia_ManPrintCo( Gia_Man_t * p, Gia_Obj_t * pObj ); extern void Gia_ManPrintCone( Gia_Man_t * p, Gia_Obj_t * pObj, int * pLeaves, int nLeaves, Vec_Int_t * vNodes ); extern void Gia_ManPrintConeMulti( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ); extern void Gia_ManPrintCone2( Gia_Man_t * p, Gia_Obj_t * pObj ); extern void Gia_ManInvertConstraints( Gia_Man_t * pAig ); extern void Gia_ManInvertPos( Gia_Man_t * pAig ); extern int Gia_ManCompare( Gia_Man_t * p1, Gia_Man_t * p2 ); extern void Gia_ManMarkFanoutDrivers( Gia_Man_t * p ); extern void Gia_ManSwapPos( Gia_Man_t * p, int i ); 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 ); /*=== giaRrr.cpp ===========================================================*/ extern Gia_Man_t * Gia_ManRrr( Gia_Man_t *pGia, int iSeed, int nWords, int nTimeout, int nSchedulerVerbose, int nPartitionerVerbose, int nOptimizerVerbose, int nAnalyzerVerbose, int nSimulatorVerbose, int nSatSolverVerbose, int fUseBddCspf, int fUseBddMspf, int nConflictLimit, int nSortType, int nOptimizerFlow, int nSchedulerFlow, int nPartitionType, int nDistance, int nJobs, int nThreads, int nPartitionSize, int nPartitionSizeMin, int fDeterministic, int nParallelPartitions, int fOptOnInsert, int fGreedy ); /*=== giaCTas.c ===========================================================*/ typedef struct Tas_Man_t_ Tas_Man_t; extern Tas_Man_t * Tas_ManAlloc( Gia_Man_t * pAig, int nBTLimit ); extern void Tas_ManStop( Tas_Man_t * p ); extern Vec_Int_t * Tas_ReadModel( Tas_Man_t * p ); 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 ); /*=== giaBound.c ===========================================================*/ typedef struct Bnd_Man_t_ Bnd_Man_t; extern Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl, int fVerbose ); extern void Bnd_ManStop(); // getter extern int Bnd_ManGetNInternal(); extern int Bnd_ManGetNExtra(); //for fraig extern void Bnd_ManMap( int iLit, int id, int spec ); extern void Bnd_ManMerge( int id1, int id2, int phaseDiff ); extern void Bnd_ManFinalizeMappings(); extern void Bnd_ManPrintMappings(); extern Gia_Man_t* Bnd_ManStackGias( Gia_Man_t *pSpec, Gia_Man_t *pImpl ); extern int Bnd_ManCheckCoMerged( Gia_Man_t *p ); // for eco extern int Bnd_ManCheckBound( Gia_Man_t *p, int fVerbose ); extern void Bnd_ManFindBound( Gia_Man_t *p, Gia_Man_t *pImpl ); extern Gia_Man_t* Bnd_ManGenSpecOut( Gia_Man_t *p ); extern Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t *p ); extern Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPatch ); extern Gia_Man_t* Bnd_ManGenPatched1( Gia_Man_t *pOut, Gia_Man_t *pSpec ); extern Gia_Man_t* Bnd_ManGenPatched2( Gia_Man_t *pImpl, Gia_Man_t *pPatch, int fSkiptStrash, int fVerbose ); extern void Bnd_ManSetEqOut( int eq ); extern void Bnd_ManSetEqRes( int eq ); extern void Bnd_ManPrintStats(); // util extern Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec_Bit_t* vEI_phase, Vec_Bit_t* vEO_phase ); extern int Gia_ObjCheckMffc( Gia_Man_t * p, Gia_Obj_t * pRoot, int Limit, Vec_Int_t * vNodes, Vec_Int_t * vLeaves, Vec_Int_t * vInners ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/aig/gia/giaAgi.c000066400000000000000000000234711477524141600156230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaAig.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: giaAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define AGI_PI ABC_CONST(0xFFFFFFFF00000000) #define AGI_RO ABC_CONST(0xFFFFFFFE00000000) #define AGI_PO ABC_CONST(0xFFFFFFFD00000000) #define AGI_RI ABC_CONST(0xFFFFFFFC00000000) #define AGI_C0 ABC_CONST(0xFFFFFFFBFFFFFFFA) #define AGI_M0 ABC_CONST(0x00000000FFFFFFFF) #define AGI_M1 ABC_CONST(0xFFFFFFFF00000000) typedef struct Agi_Man_t_ Agi_Man_t; struct Agi_Man_t_ { char * pName; // name of the AIG char * pSpec; // name of the input file int nCap; // number of objects int nObjs; // number of objects int nNodes; // number of objects int nRegs; // number of registers unsigned nTravIds; // number of objects Vec_Int_t vCis; // comb inputs Vec_Int_t vCos; // comb outputs word * pObjs; // objects unsigned * pThird; // third input unsigned * pTravIds; // traversal IDs unsigned * pNext; // next values unsigned * pTable; // hash table unsigned * pCopy; // hash table }; static inline int Agi_ManObjNum( Agi_Man_t * p ) { return p->nObjs; } static inline int Agi_ManCiNum( Agi_Man_t * p ) { return Vec_IntSize( &p->vCis ); } static inline int Agi_ManCoNum( Agi_Man_t * p ) { return Vec_IntSize( &p->vCos ); } static inline int Agi_ManNodeNum( Agi_Man_t * p ) { return p->nNodes; } static inline unsigned Agi_ObjLit0( Agi_Man_t * p, int i ) { return (unsigned)(p->pObjs[i]); } static inline unsigned Agi_ObjLit1( Agi_Man_t * p, int i ) { return (unsigned)(p->pObjs[i] >> 32); } static inline unsigned Agi_ObjLit2( Agi_Man_t * p, int i ) { return p->pThird[i]; } static inline int Agi_ObjVar0( Agi_Man_t * p, int i ) { return Agi_ObjLit0(p, i) >> 1; } static inline int Agi_ObjVar1( Agi_Man_t * p, int i ) { return Agi_ObjLit1(p, i) >> 1; } static inline int Agi_ObjVar2( Agi_Man_t * p, int i ) { return Agi_ObjLit2(p, i) >> 1; } static inline void Agi_ObjSetLit0( Agi_Man_t * p, int i, unsigned l ) { p->pObjs[i] = (p->pObjs[i] & AGI_M1) | (word)l; } static inline void Agi_ObjSetLit1( Agi_Man_t * p, int i, unsigned l ) { p->pObjs[i] = (p->pObjs[i] & AGI_M0) | ((word)l << 32); } static inline void Agi_ObjSetLit2( Agi_Man_t * p, int i, unsigned l ) { p->pThird[i] = l; } static inline int Agi_ObjIsC0( Agi_Man_t * p, int i ) { return (i == 0); } static inline int Agi_ObjIsPi( Agi_Man_t * p, int i ) { return (p->pObjs[i] & AGI_PI) == AGI_PI; } static inline int Agi_ObjIsRo( Agi_Man_t * p, int i ) { return (p->pObjs[i] & AGI_PI) == AGI_RO; } 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_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); } static inline int Agi_ObjIsXor( Agi_Man_t * p, int i ) { return Agi_ObjIsNode(p, i) && Agi_ObjLit0(p, i) > Agi_ObjLit1(p, i); } static inline int Agi_ObjIsMux( Agi_Man_t * p, int i ) { return Agi_ObjIsAnd(p, i) && ~Agi_ObjLit2(p, i); } static inline int Agi_ObjIsMaj( Agi_Man_t * p, int i ) { return Agi_ObjIsXor(p, i) && ~Agi_ObjLit2(p, i); } static inline int Agi_ManAppendObj( Agi_Man_t * p ) { assert( p->nObjs < p->nCap ); return p->nObjs++; // return var } static inline int Agi_ManAppendCi( Agi_Man_t * p ) { int iObj = Agi_ManAppendObj( p ); p->pObjs[iObj] = AGI_PI | (word)Vec_IntSize(&p->vCis); Vec_IntPush( &p->vCis, iObj ); return Abc_Var2Lit( iObj, 0 ); // return lit } static inline int Agi_ManAppendCo( Agi_Man_t * p, int iLit0 ) { int iObj = Agi_ManAppendObj( p ); p->pObjs[iObj] = AGI_PO | (word)iLit0; Vec_IntPush( &p->vCos, iObj ); return Abc_Var2Lit( iObj, 0 ); // return lit } static inline int Agi_ManAppendAnd( Agi_Man_t * p, int iLit0, int iLit1 ) { int iObj = Agi_ManAppendObj( p ); assert( iLit0 < iLit1 ); p->pObjs[iObj] = ((word)iLit1 << 32) | (word)iLit0; p->nNodes++; return Abc_Var2Lit( iObj, 0 ); // return lit } #define Agi_ManForEachCi( p, iCi, i ) Vec_IntForEachEntry( &p->vCis, iCi, i ) #define Agi_ManForEachCo( p, iCo, i ) Vec_IntForEachEntry( &p->vCos, iCo, i ) #define Agi_ManForEachObj( p, i ) for ( i = 0; i < Agi_ManObjNum(p); i++ ) #define Agi_ManForEachObj1( p, i ) for ( i = 1; i < Agi_ManObjNum(p); i++ ) #define Agi_ManForEachNode( p, i ) for ( i = 1; i < Agi_ManObjNum(p); i++ ) if ( !Agi_ObjIsNode(p, i) ) {} else //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Agi_Man_t * Agi_ManAlloc( int nCap ) { Agi_Man_t * p; nCap = Abc_MaxInt( nCap, 16 ); p = ABC_CALLOC( Agi_Man_t, 1 ); p->nCap = nCap; p->pObjs = ABC_CALLOC( word, nCap ); p->pTravIds = ABC_CALLOC( unsigned, nCap ); p->pObjs[0] = AGI_C0; p->nObjs = 1; return p; } void Agi_ManFree( Agi_Man_t * p ) { ABC_FREE( p->pObjs ); ABC_FREE( p->pTravIds ); ABC_FREE( p->vCis.pArray ); ABC_FREE( p->vCos.pArray ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Agi_Man_t * Agi_ManFromGia( Gia_Man_t * p ) { Agi_Man_t * pNew; Gia_Obj_t * pObj; int i; pNew = Agi_ManAlloc( Gia_ManObjNum(p) ); Gia_ManForEachObj1( p, pObj, i ) if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Agi_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsCo(pObj) ) pObj->Value = Agi_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); else if ( Gia_ObjIsCi(pObj) ) pObj->Value = Agi_ManAppendCi( pNew ); else assert( 0 ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Agi_ManSuppSize_rec( Agi_Man_t * p, int i ) { if ( p->pTravIds[i] == p->nTravIds ) return 0; p->pTravIds[i] = p->nTravIds; if ( Agi_ObjIsCi(p, i) ) return 1; assert( Agi_ObjIsAnd(p, i) ); return Agi_ManSuppSize_rec( p, Agi_ObjVar0(p, i) ) + Agi_ManSuppSize_rec( p, Agi_ObjVar1(p, i) ); } int Agi_ManSuppSizeOne( Agi_Man_t * p, int i ) { p->nTravIds++; return Agi_ManSuppSize_rec( p, i ); } int Agi_ManSuppSizeTest( Agi_Man_t * p ) { abctime clk = Abc_Clock(); int i, Counter = 0; Agi_ManForEachNode( p, i ) Counter += (Agi_ManSuppSizeOne(p, i) <= 16); printf( "Nodes with small support %d (out of %d)\n", Counter, Agi_ManNodeNum(p) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return Counter; } void Agi_ManTest( Gia_Man_t * pGia ) { extern int Gia_ManSuppSizeTest( Gia_Man_t * p ); Agi_Man_t * p; Gia_ManSuppSizeTest( pGia ); p = Agi_ManFromGia( pGia ); Agi_ManSuppSizeTest( p ); Agi_ManFree( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaAig.c000066400000000000000000000576671477524141600156410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaAig.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Transformation between AIG manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "giaAig.h" #include "aig/gia/gia.h" #include "proof/fra/fra.h" #include "proof/dch/dch.h" #include "opt/dar/dar.h" #include "opt/dau/dau.h" #include ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Gia_ObjChild0Copy( Aig_Obj_t * pObj ) { return Abc_LitNotCond( Aig_ObjFanin0(pObj)->iData, Aig_ObjFaninC0(pObj) ); } static inline int Gia_ObjChild1Copy( Aig_Obj_t * pObj ) { return Abc_LitNotCond( Aig_ObjFanin1(pObj)->iData, Aig_ObjFaninC1(pObj) ); } static inline Aig_Obj_t * Gia_ObjChild0Copy2( Aig_Obj_t ** ppNodes, Gia_Obj_t * pObj, int Id ) { return Aig_NotCond( ppNodes[Gia_ObjFaninId0(pObj, Id)], Gia_ObjFaninC0(pObj) ); } static inline Aig_Obj_t * Gia_ObjChild1Copy2( Aig_Obj_t ** ppNodes, Gia_Obj_t * pObj, int Id ) { return Aig_NotCond( ppNodes[Gia_ObjFaninId1(pObj, Id)], Gia_ObjFaninC1(pObj) ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFromAig_rec( Gia_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pNext; if ( pObj->iData ) return; assert( Aig_ObjIsNode(pObj) ); Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin0(pObj) ); Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin1(pObj) ); pObj->iData = Gia_ManAppendAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) ); if ( p->pEquivs && (pNext = Aig_ObjEquiv(p, pObj)) ) { int iObjNew, iNextNew; Gia_ManFromAig_rec( pNew, p, pNext ); iObjNew = Abc_Lit2Var(pObj->iData); iNextNew = Abc_Lit2Var(pNext->iData); if ( pNew->pNexts ) pNew->pNexts[iObjNew] = iNextNew; } } Gia_Man_t * Gia_ManFromAig( Aig_Man_t * p ) { Gia_Man_t * pNew; Aig_Obj_t * pObj; int i; // create the new manager pNew = Gia_ManStart( Aig_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; // create room to store equivalences if ( p->pEquivs ) pNew->pNexts = ABC_CALLOC( int, Aig_ManObjNum(p) ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->iData = 1; Aig_ManForEachCi( p, pObj, i ) pObj->iData = Gia_ManAppendCi( pNew ); // add logic for the POs Aig_ManForEachCo( p, pObj, i ) Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin0(pObj) ); Aig_ManForEachCo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) ); Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) ); if ( pNew->pNexts ) Gia_ManDeriveReprs( pNew ); 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFromAigChoices_rec( Gia_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( pObj == NULL || pObj->iData ) return; assert( Aig_ObjIsNode(pObj) ); Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjFanin0(pObj) ); Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjFanin1(pObj) ); Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjEquiv(p, pObj) ); pObj->iData = Gia_ManAppendAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) ); if ( Aig_ObjEquiv(p, pObj) ) { int iObjNew, iNextNew; iObjNew = Abc_Lit2Var(pObj->iData); iNextNew = Abc_Lit2Var(Aig_ObjEquiv(p, pObj)->iData); assert( iObjNew > iNextNew ); assert( Gia_ObjIsAnd(Gia_ManObj(pNew, iNextNew)) ); pNew->pSibls[iObjNew] = iNextNew; } } Gia_Man_t * Gia_ManFromAigChoices( Aig_Man_t * p ) { Gia_Man_t * pNew; Aig_Obj_t * pObj; int i; assert( p->pEquivs != NULL ); // create the new manager pNew = Gia_ManStart( Aig_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; // create room to store equivalences pNew->pSibls = ABC_CALLOC( int, Aig_ManObjNum(p) ); // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->iData = 1; Aig_ManForEachCi( p, pObj, i ) pObj->iData = Gia_ManAppendCi( pNew ); // add logic for the POs Aig_ManForEachCo( p, pObj, i ) Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjFanin0(pObj) ); Aig_ManForEachCo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) ); Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) ); //assert( Gia_ManObjNum(pNew) == Aig_ManObjNum(p) ); //Gia_ManCheckChoices( pNew ); if ( pNew->pSibls ) Gia_ManDeriveReprsFromSibls( pNew ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFromAigSimple( Aig_Man_t * p ) { Gia_Man_t * pNew; Aig_Obj_t * pObj; int i; // create the new manager pNew = Gia_ManStart( Aig_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; // create the PIs Aig_ManCleanData( p ); Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjIsAnd(pObj) ) pObj->iData = Gia_ManAppendAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) ); else if ( Aig_ObjIsCi(pObj) ) pObj->iData = Gia_ManAppendCi( pNew ); else if ( Aig_ObjIsCo(pObj) ) pObj->iData = Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) ); else if ( Aig_ObjIsConst1(pObj) ) pObj->iData = 1; else assert( 0 ); } Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Handles choices as additional combinational outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFromAigSwitch( Aig_Man_t * p ) { Gia_Man_t * pNew; Aig_Obj_t * pObj; int i; // create the new manager pNew = Gia_ManStart( Aig_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; // create the PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->iData = 1; Aig_ManForEachCi( p, pObj, i ) pObj->iData = Gia_ManAppendCi( pNew ); // add POs corresponding to the nodes with choices Aig_ManForEachNode( p, pObj, i ) if ( Aig_ObjRefs(pObj) == 0 ) { Gia_ManFromAig_rec( pNew, p, pObj ); Gia_ManAppendCo( pNew, pObj->iData ); } // add logic for the POs Aig_ManForEachCo( p, pObj, i ) Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin0(pObj) ); Aig_ManForEachCo( p, pObj, i ) pObj->iData = Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) ); Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManToAig_rec( Aig_Man_t * pNew, Aig_Obj_t ** ppNodes, Gia_Man_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pNext; if ( ppNodes[Gia_ObjId(p, pObj)] ) return; if ( Gia_ObjIsCi(pObj) ) ppNodes[Gia_ObjId(p, pObj)] = Aig_ObjCreateCi( pNew ); else { assert( Gia_ObjIsAnd(pObj) ); Gia_ManToAig_rec( pNew, ppNodes, p, Gia_ObjFanin0(pObj) ); Gia_ManToAig_rec( pNew, ppNodes, p, Gia_ObjFanin1(pObj) ); ppNodes[Gia_ObjId(p, pObj)] = Aig_And( pNew, Gia_ObjChild0Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)), Gia_ObjChild1Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)) ); } if ( pNew->pEquivs && (pNext = Gia_ObjNextObj(p, Gia_ObjId(p, pObj))) ) { Aig_Obj_t * pObjNew, * pNextNew; Gia_ManToAig_rec( pNew, ppNodes, p, pNext ); pObjNew = ppNodes[Gia_ObjId(p, pObj)]; pNextNew = ppNodes[Gia_ObjId(p, pNext)]; if ( pNew->pEquivs ) pNew->pEquivs[Aig_Regular(pObjNew)->Id] = Aig_Regular(pNextNew); } } Aig_Man_t * Gia_ManToAig( Gia_Man_t * p, int fChoices ) { Aig_Man_t * pNew; Aig_Obj_t ** ppNodes; Gia_Obj_t * pObj; int i; assert( !fChoices || (p->pNexts && p->pReprs) ); // create the new manager pNew = Aig_ManStart( Gia_ManAndNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; // pNew->pSpec = Abc_UtilStrsav( p->pName ); // duplicate representation of choice nodes if ( fChoices ) pNew->pEquivs = ABC_CALLOC( Aig_Obj_t *, Gia_ManObjNum(p) ); // create the PIs ppNodes = ABC_CALLOC( Aig_Obj_t *, Gia_ManObjNum(p) ); ppNodes[0] = Aig_ManConst0(pNew); Gia_ManForEachCi( p, pObj, i ) ppNodes[Gia_ObjId(p, pObj)] = Aig_ObjCreateCi( pNew ); // transfer level if ( p->vLevels ) Gia_ManForEachCi( p, pObj, i ) Aig_ObjSetLevel( ppNodes[Gia_ObjId(p, pObj)], Gia_ObjLevel(p, pObj) ); // add logic for the POs Gia_ManForEachCo( p, pObj, i ) { Gia_ManToAig_rec( pNew, ppNodes, p, Gia_ObjFanin0(pObj) ); ppNodes[Gia_ObjId(p, pObj)] = Aig_ObjCreateCo( pNew, Gia_ObjChild0Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)) ); } Aig_ManSetRegNum( pNew, Gia_ManRegNum(p) ); ABC_FREE( ppNodes ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Gia_ManToAigSkip( Gia_Man_t * p, int nOutDelta ) { Aig_Man_t * pNew; Aig_Obj_t ** ppNodes; Gia_Obj_t * pObj; int i; assert( p->pNexts == NULL && p->pReprs == NULL ); assert( nOutDelta > 0 && Gia_ManCoNum(p) % nOutDelta == 0 ); // create the new manager pNew = Aig_ManStart( Gia_ManAndNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; // pNew->pSpec = Abc_UtilStrsav( p->pName ); // create the PIs ppNodes = ABC_CALLOC( Aig_Obj_t *, Gia_ManObjNum(p) ); ppNodes[0] = Aig_ManConst0(pNew); Gia_ManForEachCi( p, pObj, i ) ppNodes[Gia_ObjId(p, pObj)] = Aig_ObjCreateCi( pNew ); // add logic for the POs Gia_ManForEachCo( p, pObj, i ) { Gia_ManToAig_rec( pNew, ppNodes, p, Gia_ObjFanin0(pObj) ); if ( i % nOutDelta != 0 ) continue; ppNodes[Gia_ObjId(p, pObj)] = Aig_ObjCreateCo( pNew, Gia_ObjChild0Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)) ); } Aig_ManSetRegNum( pNew, Gia_ManRegNum(p) ); ABC_FREE( ppNodes ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Gia_ManToAigSimple( Gia_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t ** ppNodes; Gia_Obj_t * pObj; int i; ppNodes = ABC_FALLOC( Aig_Obj_t *, Gia_ManObjNum(p) ); // create the new manager pNew = Aig_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nConstrs = p->nConstrs; // create the PIs Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) ppNodes[i] = Aig_And( pNew, Gia_ObjChild0Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)), Gia_ObjChild1Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)) ); else if ( Gia_ObjIsCi(pObj) ) ppNodes[i] = Aig_ObjCreateCi( pNew ); else if ( Gia_ObjIsCo(pObj) ) ppNodes[i] = Aig_ObjCreateCo( pNew, Gia_ObjChild0Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)) ); else if ( Gia_ObjIsConst0(pObj) ) ppNodes[i] = Aig_ManConst0(pNew); else assert( 0 ); pObj->Value = Abc_Var2Lit( Aig_ObjId(Aig_Regular(ppNodes[i])), Aig_IsComplement(ppNodes[i]) ); assert( i == 0 || Aig_ObjId(ppNodes[i]) == i ); } Aig_ManSetRegNum( pNew, Gia_ManRegNum(p) ); ABC_FREE( ppNodes ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Gia_ManCofactorAig( Aig_Man_t * p, int nFrames, int nCofFanLit ) { Aig_Man_t * pMan; Gia_Man_t * pGia, * pTemp; pGia = Gia_ManFromAig( p ); pGia = Gia_ManUnrollAndCofactor( pTemp = pGia, nFrames, nCofFanLit, 1 ); Gia_ManStop( pTemp ); pMan = Gia_ManToAig( pGia, 0 ); Gia_ManStop( pGia ); return pMan; } /**Function************************************************************* Synopsis [Transfers representatives from pGia to pAig.] Description [Assumes that pGia was created from pAig.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManReprToAigRepr( Aig_Man_t * pAig, Gia_Man_t * pGia ) { Aig_Obj_t * pObj; Gia_Obj_t * pGiaObj, * pGiaRepr; int i; assert( pAig->pReprs == NULL ); assert( pGia->pReprs != NULL ); // move pointers from AIG to GIA Aig_ManForEachObj( pAig, pObj, i ) { assert( i == 0 || !Abc_LitIsCompl(pObj->iData) ); pGiaObj = Gia_ManObj( pGia, Abc_Lit2Var(pObj->iData) ); pGiaObj->Value = i; } // set the pointers to the nodes in AIG Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); Gia_ManForEachObj( pGia, pGiaObj, i ) { pGiaRepr = Gia_ObjReprObj( pGia, i ); if ( pGiaRepr == NULL ) continue; Aig_ObjCreateRepr( pAig, Aig_ManObj(pAig, pGiaRepr->Value), Aig_ManObj(pAig, pGiaObj->Value) ); } } void Gia_ManReprToAigRepr2( Aig_Man_t * pAig, Gia_Man_t * pGia ) { Gia_Obj_t * pGiaObj, * pGiaRepr; int i; assert( pAig->pReprs == NULL ); assert( pGia->pReprs != NULL ); // set the pointers to the nodes in AIG Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); Gia_ManForEachObj( pGia, pGiaObj, i ) { pGiaRepr = Gia_ObjReprObj( pGia, i ); if ( pGiaRepr == NULL ) continue; Aig_ObjCreateRepr( pAig, Aig_ManObj(pAig, Abc_Lit2Var(pGiaRepr->Value)), Aig_ManObj(pAig, Abc_Lit2Var(pGiaObj->Value)) ); } } /**Function************************************************************* Synopsis [Transfers representatives from pAig to pGia.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManReprFromAigRepr( Aig_Man_t * pAig, Gia_Man_t * pGia ) { Gia_Obj_t * pObjGia; Aig_Obj_t * pObjAig, * pReprAig; int i; assert( pAig->pReprs != NULL ); assert( pGia->pReprs == NULL ); assert( Gia_ManObjNum(pGia) - Gia_ManCoNum(pGia) == Aig_ManObjNum(pAig) - Aig_ManCoNum(pAig) ); pGia->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pGia) ); for ( i = 0; i < Gia_ManObjNum(pGia); i++ ) Gia_ObjSetRepr( pGia, i, GIA_VOID ); // move pointers from GIA to AIG Gia_ManForEachObj( pGia, pObjGia, i ) { if ( Gia_ObjIsCo(pObjGia) ) continue; assert( i == 0 || !Abc_LitIsCompl(Gia_ObjValue(pObjGia)) ); pObjAig = Aig_ManObj( pAig, Abc_Lit2Var(Gia_ObjValue(pObjGia)) ); pObjAig->iData = i; } Aig_ManForEachObj( pAig, pObjAig, i ) { if ( Aig_ObjIsCo(pObjAig) ) continue; if ( pAig->pReprs[i] == NULL ) continue; pReprAig = pAig->pReprs[i]; Gia_ObjSetRepr( pGia, pObjAig->iData, pReprAig->iData ); } pGia->pNexts = Gia_ManDeriveNexts( pGia ); } void Gia_ManReprFromAigRepr2( Aig_Man_t * pAig, Gia_Man_t * pGia ) { Aig_Obj_t * pObjAig, * pReprAig; int i; assert( pAig->pReprs != NULL ); assert( pGia->pReprs == NULL ); assert( Gia_ManObjNum(pGia) - Gia_ManCoNum(pGia) == Aig_ManObjNum(pAig) - Aig_ManCoNum(pAig) ); pGia->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pGia) ); for ( i = 0; i < Gia_ManObjNum(pGia); i++ ) Gia_ObjSetRepr( pGia, i, GIA_VOID ); Aig_ManForEachObj( pAig, pObjAig, i ) { if ( Aig_ObjIsCo(pObjAig) ) continue; if ( pAig->pReprs[i] == NULL ) continue; pReprAig = pAig->pReprs[i]; Gia_ObjSetRepr( pGia, Abc_Lit2Var(pObjAig->iData), Abc_Lit2Var(pReprAig->iData) ); } pGia->pNexts = Gia_ManDeriveNexts( pGia ); } /**Function************************************************************* Synopsis [Applies DC2 to the GIA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManCompress2( Gia_Man_t * p, int fUpdateLevel, int fVerbose ) { Gia_Man_t * pGia; Aig_Man_t * pNew, * pTemp; if ( p->pManTime && p->vLevels == NULL ) Gia_ManLevelWithBoxes( p ); pNew = Gia_ManToAig( p, 0 ); pNew = Dar_ManCompress2( pTemp = pNew, 1, fUpdateLevel, 1, 0, fVerbose ); Aig_ManStop( pTemp ); pGia = Gia_ManFromAig( pNew ); Aig_ManStop( pNew ); Gia_ManTransferTiming( pGia, p ); return pGia; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] 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; Gia_Man_t * pGia, * pGia1; Aig_Man_t * pNew; if ( p->pManTime && p->vLevels == NULL ) Gia_ManLevelWithBoxes( p ); if ( fUseMapping && Gia_ManHasMapping(p) ) pGia1 = (Gia_Man_t *)Dsm_ManDeriveGia( p, 0 ); else pGia1 = Gia_ManDup( p ); pNew = Gia_ManToAig( pGia1, 0 ); Gia_ManStop( pGia1 ); pNew = Dar_ManChoiceNew( pNew, (Dch_Pars_t *)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; } /**Function************************************************************* Synopsis [Computes equivalences after structural sequential cleanup.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSeqCleanupClasses( Gia_Man_t * p, int fConst, int fEquiv, int fVerbose ) { Aig_Man_t * pNew, * pTemp; pNew = Gia_ManToAigSimple( p ); pTemp = Aig_ManScl( pNew, fConst, fEquiv, 0, -1, -1, fVerbose, 0 ); Gia_ManReprFromAigRepr( pNew, p ); Aig_ManStop( pTemp ); Aig_ManStop( pNew ); } /**Function************************************************************* Synopsis [Solves SAT problem.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSolveSat( Gia_Man_t * p ) { // extern int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose ); Aig_Man_t * pNew; int RetValue;//, clk = Abc_Clock(); pNew = Gia_ManToAig( p, 0 ); RetValue = Fra_FraigSat( pNew, 10000000, 0, 0, 0, 0, 1, 1, 0, 0 ); if ( RetValue == 0 ) { Gia_Obj_t * pObj; int i, * pInit = (int *)pNew->pData; Gia_ManConst0(p)->fMark0 = 0; Gia_ManForEachPi( p, pObj, i ) pObj->fMark0 = pInit[i]; Gia_ManForEachAnd( p, pObj, i ) pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); Gia_ManForEachPo( p, pObj, i ) pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)); Gia_ManForEachPo( p, pObj, i ) if ( pObj->fMark0 != 1 ) break; if ( i != Gia_ManPoNum(p) ) Abc_Print( 1, "Counter-example verification has failed. " ); // else // Abc_Print( 1, "Counter-example verification succeeded. " ); } /* else if ( RetValue == 1 ) Abc_Print( 1, "The SAT problem is unsatisfiable. " ); else if ( RetValue == -1 ) Abc_Print( 1, "The SAT problem is undecided. " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); */ Aig_ManStop( pNew ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaAig.h000066400000000000000000000064011477524141600156220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaAig.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaAig.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__gia__giaAig_h #define ABC__aig__gia__giaAig_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/aig/aig.h" #include "gia.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== giaAig.c =============================================================*/ extern Gia_Man_t * Gia_ManFromAig( Aig_Man_t * p ); extern Gia_Man_t * Gia_ManFromAigChoices( Aig_Man_t * p ); extern Gia_Man_t * Gia_ManFromAigSimple( Aig_Man_t * p ); extern Gia_Man_t * Gia_ManFromAigSwitch( Aig_Man_t * p ); extern Aig_Man_t * Gia_ManToAig( Gia_Man_t * p, int fChoices ); extern Aig_Man_t * Gia_ManToAigSkip( Gia_Man_t * p, int nOutDelta ); extern Aig_Man_t * Gia_ManToAigSimple( Gia_Man_t * p ); extern void Gia_ManReprToAigRepr( Aig_Man_t * pAig, Gia_Man_t * pGia ); extern void Gia_ManReprToAigRepr2( Aig_Man_t * pAig, Gia_Man_t * pGia ); extern void Gia_ManReprFromAigRepr( Aig_Man_t * pAig, Gia_Man_t * pGia ); extern void Gia_ManReprFromAigRepr2( Aig_Man_t * pAig, Gia_Man_t * pGia ); extern Gia_Man_t * Gia_ManCompress2( Gia_Man_t * p, int fUpdateLevel, int fVerbose ); extern Gia_Man_t * Gia_ManPerformDch( Gia_Man_t * p, void * pPars ); extern Gia_Man_t * Gia_ManAbstraction( Gia_Man_t * p, Vec_Int_t * vFlops ); extern void Gia_ManSeqCleanupClasses( Gia_Man_t * p, int fConst, int fEquiv, int fVerbose ); extern int Gia_ManSolveSat( Gia_Man_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/aig/gia/giaAiger.c000066400000000000000000002012451477524141600161470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaAiger.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Procedures to read/write binary AIGER format developed by Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaAiger.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/tim/tim.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START #define XAIG_VERBOSE 0 //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_FileFixName( char * pFileName ) { char * pName; for ( pName = pFileName; *pName; pName++ ) if ( *pName == '>' ) *pName = '\\'; } char * Gia_FileNameGeneric( char * FileName ) { char * pDot, * pRes; pRes = Abc_UtilStrsav( FileName ); if ( (pDot = strrchr( pRes, '.' )) ) *pDot = 0; return pRes; } int Gia_FileSize( char * pFileName ) { FILE * pFile; int nFileSize; pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { printf( "Gia_FileSize(): The file is unavailable (absent or open).\n" ); return 0; } fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); fclose( pFile ); return nFileSize; } void Gia_FileWriteBufferSize( FILE * pFile, int nSize ) { unsigned char Buffer[5]; Gia_AigerWriteInt( Buffer, nSize ); fwrite( Buffer, 1, 4, pFile ); } /**Function************************************************************* Synopsis [Create the array of literals to be written.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_AigerCollectLiterals( Gia_Man_t * p ) { Vec_Int_t * vLits; Gia_Obj_t * pObj; int i; vLits = Vec_IntAlloc( Gia_ManPoNum(p) ); Gia_ManForEachRi( p, pObj, i ) Vec_IntPush( vLits, Gia_ObjFaninLit0p(p, pObj) ); Gia_ManForEachPo( p, pObj, i ) Vec_IntPush( vLits, Gia_ObjFaninLit0p(p, pObj) ); return vLits; } Vec_Int_t * Gia_AigerReadLiterals( unsigned char ** ppPos, int nEntries ) { Vec_Int_t * vLits; int Lit, LitPrev, Diff, i; vLits = Vec_IntAlloc( nEntries ); LitPrev = Gia_AigerReadUnsigned( ppPos ); Vec_IntPush( vLits, LitPrev ); for ( i = 1; i < nEntries; i++ ) { // Diff = Lit - LitPrev; // Diff = (Lit < LitPrev)? -Diff : Diff; // Diff = ((2 * Diff) << 1) | (int)(Lit < LitPrev); Diff = Gia_AigerReadUnsigned( ppPos ); Diff = (Diff & 1)? -(Diff >> 1) : Diff >> 1; Lit = Diff + LitPrev; Vec_IntPush( vLits, Lit ); LitPrev = Lit; } return vLits; } Vec_Str_t * Gia_AigerWriteLiterals( Vec_Int_t * vLits ) { Vec_Str_t * vBinary; int Pos = 0, Lit, LitPrev, Diff, i; vBinary = Vec_StrAlloc( 2 * Vec_IntSize(vLits) ); LitPrev = Vec_IntEntry( vLits, 0 ); Pos = Gia_AigerWriteUnsignedBuffer( (unsigned char *)Vec_StrArray(vBinary), Pos, LitPrev ); Vec_IntForEachEntryStart( vLits, Lit, i, 1 ) { Diff = Lit - LitPrev; Diff = (Lit < LitPrev)? -Diff : Diff; Diff = (Diff << 1) | (int)(Lit < LitPrev); Pos = Gia_AigerWriteUnsignedBuffer( (unsigned char *)Vec_StrArray(vBinary), Pos, Diff ); LitPrev = Lit; if ( Pos + 10 > vBinary->nCap ) Vec_StrGrow( vBinary, vBinary->nCap+1 ); } vBinary->nSize = Pos; /* // verify { extern Vec_Int_t * Gia_AigerReadLiterals( char ** ppPos, int nEntries ); char * pPos = Vec_StrArray( vBinary ); Vec_Int_t * vTemp = Gia_AigerReadLiterals( &pPos, Vec_IntSize(vLits) ); for ( i = 0; i < Vec_IntSize(vLits); i++ ) { int Entry1 = Vec_IntEntry(vLits,i); int Entry2 = Vec_IntEntry(vTemp,i); assert( Entry1 == Entry2 ); } Vec_IntFree( vTemp ); } */ return vBinary; } /**Function************************************************************* Synopsis [Reads the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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; int nTotal, nInputs, nOutputs, nLatches, nAnds, i; int nBad = 0, nConstr = 0, nJust = 0, nFair = 0; unsigned char * pDrivers, * pSymbols, * pCur; unsigned uLit0, uLit1, uLit; // read the parameters (M I L O A + B C J F) pCur = (unsigned char *)pContents; while ( *pCur != ' ' ) pCur++; pCur++; // read the number of objects nTotal = atoi( (const char *)pCur ); while ( *pCur != ' ' ) pCur++; pCur++; // read the number of inputs nInputs = atoi( (const char *)pCur ); while ( *pCur != ' ' ) pCur++; pCur++; // read the number of latches nLatches = atoi( (const char *)pCur ); while ( *pCur != ' ' ) pCur++; pCur++; // read the number of outputs nOutputs = atoi( (const char *)pCur ); while ( *pCur != ' ' ) pCur++; pCur++; // read the number of nodes nAnds = atoi( (const char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; if ( *pCur == ' ' ) { // assert( nOutputs == 0 ); // read the number of properties pCur++; nBad = atoi( (const char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; nOutputs += nBad; } if ( *pCur == ' ' ) { // read the number of properties pCur++; nConstr = atoi( (const char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; nOutputs += nConstr; } if ( *pCur == ' ' ) { // read the number of properties pCur++; nJust = atoi( (const char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; nOutputs += nJust; } if ( *pCur == ' ' ) { // read the number of properties pCur++; nFair = atoi( (const char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; nOutputs += nFair; } if ( *pCur != '\n' ) { fprintf( stdout, "The parameter line is in a wrong format.\n" ); return NULL; } pCur++; // check the parameters if ( nTotal != nInputs + nLatches + nAnds ) { fprintf( stdout, "The number of objects does not match.\n" ); return NULL; } if ( nJust || nFair ) { fprintf( stdout, "Reading AIGER files with liveness properties is currently not supported.\n" ); return NULL; } if ( nConstr ) { if ( nConstr == 1 ) fprintf( stdout, "Warning: The last output is interpreted as a constraint.\n" ); else fprintf( stdout, "Warning: The last %d outputs are interpreted as constraints.\n", nConstr ); } // allocate the empty AIG pNew = Gia_ManStart( nTotal + nLatches + nOutputs + 1 ); pNew->nConstrs = nConstr; pNew->fGiaSimple = fGiaSimple; // prepare the array of nodes vNodes = Vec_IntAlloc( 1 + nTotal ); Vec_IntPush( vNodes, 0 ); // create the PIs for ( i = 0; i < nInputs + nLatches; i++ ) { iObj = Gia_ManAppendCi(pNew); Vec_IntPush( vNodes, iObj ); } // remember the beginning of latch/PO literals pDrivers = pCur; if ( pContents[3] == ' ' ) // standard AIGER { // scroll to the beginning of the binary data for ( i = 0; i < nLatches + nOutputs; ) if ( *pCur++ == '\n' ) i++; } else // modified AIGER { vLits = Gia_AigerReadLiterals( &pCur, nLatches + nOutputs ); } // create the AND gates if ( !fGiaSimple && !fSkipStrash ) Gia_ManHashAlloc( pNew ); for ( i = 0; i < nAnds; i++ ) { uLit = ((i + 1 + nInputs + nLatches) << 1); uLit1 = uLit - Gia_AigerReadUnsigned( &pCur ); uLit0 = uLit1 - Gia_AigerReadUnsigned( &pCur ); // assert( uLit1 > uLit0 ); iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); iNode1 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); assert( Vec_IntSize(vNodes) == i + 1 + nInputs + nLatches ); if ( !fGiaSimple && fSkipStrash ) { if ( iNode0 == iNode1 ) Vec_IntPush( vNodes, Gia_ManAppendBuf(pNew, iNode0) ); else Vec_IntPush( vNodes, Gia_ManAppendAnd(pNew, iNode0, iNode1) ); } else Vec_IntPush( vNodes, Gia_ManHashAnd(pNew, iNode0, iNode1) ); } if ( !fGiaSimple && !fSkipStrash ) Gia_ManHashStop( pNew ); // remember the place where symbols begin pSymbols = pCur; // read the latch driver literals vDrivers = Vec_IntAlloc( nLatches + nOutputs ); if ( pContents[3] == ' ' ) // standard AIGER { vInits = Vec_IntAlloc( nLatches ); pCur = pDrivers; for ( i = 0; i < nLatches; i++ ) { uLit0 = atoi( (char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; if ( *pCur == ' ' ) { pCur++; Vec_IntPush( vInits, atoi( (char *)pCur ) ); while ( *pCur++ != '\n' ); } else { pCur++; Vec_IntPush( vInits, 0 ); } iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Vec_IntPush( vDrivers, iNode0 ); } // read the PO driver literals for ( i = 0; i < nOutputs; i++ ) { uLit0 = atoi( (char *)pCur ); while ( *pCur++ != '\n' ); iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Vec_IntPush( vDrivers, iNode0 ); } } else { // read the latch driver literals for ( i = 0; i < nLatches; i++ ) { uLit0 = Vec_IntEntry( vLits, i ); iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Vec_IntPush( vDrivers, iNode0 ); } // read the PO driver literals for ( i = 0; i < nOutputs; i++ ) { uLit0 = Vec_IntEntry( vLits, i+nLatches ); iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); Vec_IntPush( vDrivers, iNode0 ); } Vec_IntFree( vLits ); } // create the POs for ( i = 0; i < nOutputs; i++ ) Gia_ManAppendCo( pNew, Vec_IntEntry(vDrivers, nLatches + i) ); for ( i = 0; i < nLatches; i++ ) Gia_ManAppendCo( pNew, Vec_IntEntry(vDrivers, i) ); Vec_IntFree( vDrivers ); // create the latches Gia_ManSetRegNum( pNew, nLatches ); // read signal names if they are of the special type 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_PtrStart( nInputs ); if ( Vec_PtrSize(vNamesIn) <= iTerm ) { fError = 1; break; } Vec_PtrWriteEntry( vNamesIn, iTerm, Abc_UtilStrsav(pName) ); } else if ( *pType == 'o' ) { if ( vNamesOut == NULL ) vNamesOut = Vec_PtrStart( nOutputs ); if ( Vec_PtrSize(vNamesOut) <= iTerm ) { fError = 1; break; } Vec_PtrWriteEntry( vNamesOut, iTerm, Abc_UtilStrsav(pName) ); } else if ( *pType == 'l' ) { char Buffer[1000]; assert( strlen(pName) < 995 ); sprintf( Buffer, "%s_in", pName ); if ( vNamesRegIn == NULL ) vNamesRegIn = Vec_PtrStart( nLatches ); if ( vNamesRegOut == NULL ) vNamesRegOut = Vec_PtrStart( nLatches ); if ( Vec_PtrSize(vNamesRegIn) <= iTerm ) { fError = 1; break; } Vec_PtrWriteEntry( vNamesRegIn, iTerm, Abc_UtilStrsav(Buffer) ); Vec_PtrWriteEntry( vNamesRegOut, iTerm, 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 ); pNew->vUserPoIds = Vec_IntStartFull( nOutputs ); pNew->vUserFfIds = Vec_IntStartFull( nLatches ); while ( pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' ) { int iTerm; char * pType = (char *)pCur; // check terminal type if ( *pCur != 'i' && *pCur != 'o' && *pCur != 'l' ) { // fprintf( stdout, "Wrong terminal type.\n" ); fBreakUsed = 1; break; } // get terminal number iTerm = atoi( (char *)++pCur ); while ( *pCur++ != ' ' ); // skip spaces while ( *pCur == ' ' ) pCur++; // decode the user numbers: // flops are named: @l // PIs are named: @i // POs are named: @o if ( *pCur++ != '@' ) { fBreakUsed = 1; break; } if ( *pCur == 'i' && *pType == 'i' ) Vec_IntWriteEntry( pNew->vUserPiIds, iTerm, atoi((char *)pCur+1) ); else if ( *pCur == 'o' && *pType == 'o' ) Vec_IntWriteEntry( pNew->vUserPoIds, iTerm, atoi((char *)pCur+1) ); else if ( *pCur == 'l' && *pType == 'l' ) Vec_IntWriteEntry( pNew->vUserFfIds, iTerm, atoi((char *)pCur+1) ); else { fprintf( stdout, "Wrong name format.\n" ); fBreakUsed = 1; break; } // skip digits while ( *pCur++ != '\n' ); } // in case of abnormal termination, remove the arrays if ( fBreakUsed ) { unsigned char * pName; int Entry, nInvars, nConstr, iTerm; Vec_Int_t * vPoNames = Vec_IntStartFull( nOutputs ); Vec_IntFreeP( &pNew->vUserPiIds ); Vec_IntFreeP( &pNew->vUserPoIds ); Vec_IntFreeP( &pNew->vUserFfIds ); // try to figure out signal names fBreakUsed = 0; pCur = (unsigned char *)pCurOld; while ( pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' ) { // get the terminal type if ( *pCur == 'i' || *pCur == 'l' ) { // skip till the end of the line while ( *pCur++ != '\n' ); *(pCur-1) = 0; continue; } if ( *pCur != 'o' ) { // fprintf( stdout, "Wrong terminal type.\n" ); fBreakUsed = 1; break; } // get the terminal number iTerm = atoi( (char *)++pCur ); while ( *pCur++ != ' ' ); // get the node if ( iTerm < 0 || iTerm >= nOutputs ) { fprintf( stdout, "The output number (%d) is out of range.\n", iTerm ); fBreakUsed = 1; break; } if ( Vec_IntEntry(vPoNames, iTerm) != ~0 ) { fprintf( stdout, "The output number (%d) is listed twice.\n", iTerm ); fBreakUsed = 1; break; } // get the name pName = pCur; while ( *pCur++ != '\n' ); *(pCur-1) = 0; // assign the name Vec_IntWriteEntry( vPoNames, iTerm, pName - (unsigned char *)pContents ); } // check that all names are assigned if ( !fBreakUsed ) { nInvars = nConstr = 0; vPoTypes = Vec_IntStart( Gia_ManPoNum(pNew) ); Vec_IntForEachEntry( vPoNames, Entry, i ) { if ( Entry == ~0 ) continue; if ( strncmp( pContents+Entry, "constraint:", 11 ) == 0 ) { Vec_IntWriteEntry( vPoTypes, i, 1 ); nConstr++; } if ( strncmp( pContents+Entry, "invariant:", 10 ) == 0 ) { Vec_IntWriteEntry( vPoTypes, i, 2 ); nInvars++; } } if ( nConstr ) fprintf( stdout, "Recognized and added %d constraints.\n", nConstr ); if ( nInvars ) fprintf( stdout, "Recognized and skipped %d invariants.\n", nInvars ); if ( nConstr == 0 && nInvars == 0 ) Vec_IntFreeP( &vPoTypes ); } Vec_IntFree( vPoNames ); } } } // check if there are other types of information to read if ( pCur + 1 < (unsigned char *)pContents + nFileSize && *pCur == 'c' ) { int fVerbose = XAIG_VERBOSE; Vec_Str_t * vStr; unsigned char * pCurTemp; pCur++; // skip new line if present // if ( *pCur == '\n' ) // pCur++; while ( pCur < (unsigned char *)pContents + nFileSize ) { // read extra AIG if ( *pCur == 'a' ) { pCur++; vStr = Vec_StrStart( Gia_AigerReadInt(pCur) ); pCur += 4; 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 ); if ( fVerbose ) printf( "Finished reading extension \"a\".\n" ); } // read number of constraints else if ( *pCur == 'c' ) { pCur++; assert( Gia_AigerReadInt(pCur) == 4 ); pCur += 4; pNew->nConstrs = Gia_AigerReadInt( pCur ); pCur += 4; if ( fVerbose ) printf( "Finished reading extension \"c\".\n" ); } // read delay information else if ( *pCur == 'd' ) { pCur++; assert( Gia_AigerReadInt(pCur) == 4 ); pCur += 4; pNew->nAnd2Delay = Gia_AigerReadInt(pCur); pCur += 4; if ( fVerbose ) printf( "Finished reading extension \"d\".\n" ); } else if ( *pCur == 'i' ) { pCur++; nInputs = Gia_AigerReadInt(pCur)/4; pCur += 4; pNew->vInArrs = Vec_FltStart( 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' ) { pCur++; nOutputs = Gia_AigerReadInt(pCur)/4; pCur += 4; pNew->vOutReqs = Vec_FltStart( 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 else if ( *pCur == 'e' ) { extern Gia_Rpr_t * Gia_AigerReadEquivClasses( unsigned char ** ppPos, int nSize ); pCur++; pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; pNew->pReprs = Gia_AigerReadEquivClasses( &pCur, Gia_ManObjNum(pNew) ); pNew->pNexts = Gia_ManDeriveNexts( pNew ); assert( pCur == pCurTemp ); if ( fVerbose ) printf( "Finished reading extension \"e\".\n" ); } // read flop classes else if ( *pCur == 'f' ) { pCur++; assert( Gia_AigerReadInt(pCur) == 4*Gia_ManRegNum(pNew) ); pCur += 4; pNew->vFlopClasses = Vec_IntStart( 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 else if ( *pCur == 'g' ) { pCur++; assert( Gia_AigerReadInt(pCur) == 4*Gia_ManObjNum(pNew) ); pCur += 4; pNew->vGateClasses = Vec_IntStart( 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 else if ( *pCur == 'h' ) { pCur++; vStr = Vec_StrStart( Gia_AigerReadInt(pCur) ); pCur += 4; memcpy( Vec_StrArray(vStr), pCur, (size_t)Vec_StrSize(vStr) ); pCur += Vec_StrSize(vStr); pNew->pManTime = Tim_ManLoad( vStr, 1 ); Vec_StrFree( vStr ); fHieOnly = 1; if ( fVerbose ) printf( "Finished reading extension \"h\".\n" ); } // read packing else if ( *pCur == 'k' ) { extern Vec_Int_t * Gia_AigerReadPacking( unsigned char ** ppPos, int nSize ); int nSize; pCur++; nSize = Gia_AigerReadInt(pCur); pCurTemp = pCur + nSize + 4; pCur += 4; pNew->vPacking = Gia_AigerReadPacking( &pCur, nSize ); assert( pCur == pCurTemp ); if ( fVerbose ) printf( "Finished reading extension \"k\".\n" ); } // read mapping else if ( *pCur == 'm' ) { extern int * Gia_AigerReadMapping( unsigned char ** ppPos, int nSize ); extern int * Gia_AigerReadMappingSimple( unsigned char ** ppPos, int nSize ); extern Vec_Int_t * Gia_AigerReadMappingDoc( unsigned char ** ppPos, int nObjs ); int nSize; pCur++; nSize = Gia_AigerReadInt(pCur); pCurTemp = pCur + nSize + 4; pCur += 4; pNew->vMapping = Gia_AigerReadMappingDoc( &pCur, Gia_ManObjNum(pNew) ); assert( pCur == pCurTemp ); if ( fVerbose ) printf( "Finished reading extension \"m\".\n" ); } // read model name else if ( *pCur == 'n' ) { 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 { pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; ABC_FREE( pNew->pName ); pNew->pName = Abc_UtilStrsav( (char *)pCur ); pCur += strlen(pNew->pName) + 1; assert( pCur == pCurTemp ); } } // read placement else if ( *pCur == 'p' ) { Gia_Plc_t * pPlacement; pCur++; pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; pPlacement = ABC_ALLOC( Gia_Plc_t, 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" ); } // read register classes else if ( *pCur == 'r' ) { int i, nRegs; pCur++; pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; nRegs = Gia_AigerReadInt(pCur); pCur += 4; //nRegs = (pCurTemp - pCur)/4; pNew->vRegClasses = Vec_IntAlloc( nRegs ); for ( i = 0; i < nRegs; i++ ) Vec_IntPush( pNew->vRegClasses, Gia_AigerReadInt(pCur) ), pCur += 4; assert( pCur == pCurTemp ); if ( fVerbose ) printf( "Finished reading extension \"r\".\n" ); } // read register inits else if ( *pCur == 's' ) { int i, nRegs; pCur++; pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; nRegs = Gia_AigerReadInt(pCur); pCur += 4; pNew->vRegInits = Vec_IntAlloc( nRegs ); for ( i = 0; i < nRegs; i++ ) Vec_IntPush( pNew->vRegInits, Gia_AigerReadInt(pCur) ), pCur += 4; assert( pCur == pCurTemp ); if ( fVerbose ) printf( "Finished reading extension \"s\".\n" ); } // read configuration data else if ( *pCur == 'b' ) { int nSize; pCur++; nSize = Gia_AigerReadInt(pCur); pCurTemp = pCur + nSize + 4; pCur += 4; pNew->pCellStr = Abc_UtilStrsav( (char*)pCur ); pCur += strlen((char*)pCur) + 1; nSize = nSize - strlen(pNew->pCellStr) - 1; assert( nSize % 4 == 0 ); pNew->vConfigs = Vec_IntAlloc(nSize / 4); // 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 ); if ( fVerbose ) printf( "Finished reading extension \"b\".\n" ); } // read choices else if ( *pCur == 'q' ) { int i, nPairs, iRepr, iNode; assert( !Gia_ManHasChoices(pNew) ); pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(pNew) ); pCur++; pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; nPairs = Gia_AigerReadInt(pCur); pCur += 4; for ( i = 0; i < nPairs; i++ ) { iRepr = Gia_AigerReadInt(pCur); pCur += 4; iNode = Gia_AigerReadInt(pCur); pCur += 4; pNew->pSibls[iRepr] = iNode; assert( iRepr > iNode ); } assert( pCur == pCurTemp ); if ( fVerbose ) printf( "Finished reading extension \"q\".\n" ); } // read switching activity else if ( *pCur == 'u' ) { unsigned char * pSwitching; pCur++; pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; pSwitching = ABC_ALLOC( unsigned char, 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" ); } // read timing manager else if ( *pCur == 't' ) { pCur++; vStr = Vec_StrStart( Gia_AigerReadInt(pCur) ); pCur += 4; 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" ); } // read object classes else if ( *pCur == 'v' ) { pCur++; pNew->vObjClasses = Vec_IntStart( Gia_AigerReadInt(pCur)/4 ); pCur += 4; 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" ); } // read edge information else if ( *pCur == 'w' ) { Vec_Int_t * vPairs; int i, nPairs; pCur++; pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; nPairs = Gia_AigerReadInt(pCur); pCur += 4; vPairs = Vec_IntAlloc( 2*nPairs ); for ( i = 0; i < 2*nPairs; i++ ) Vec_IntPush( vPairs, Gia_AigerReadInt(pCur) ), pCur += 4; assert( pCur == pCurTemp ); if ( fSkipStrash ) { Gia_ManEdgeFromArray( pNew, vPairs ); if ( fVerbose ) printf( "Finished reading extension \"w\".\n" ); } else printf( "Cannot read extension \"w\" because AIG is rehashed. Use \"&r -s \".\n" ); Vec_IntFree( vPairs ); } else break; } } // skipping the comments Vec_IntFree( vNodes ); // update polarity of the additional outputs if ( nBad || nConstr || nJust || nFair ) Gia_ManInvertConstraints( pNew ); // clean the PO drivers if ( vPoTypes ) { pNew = Gia_ManDupWithConstraints( pTemp = pNew, vPoTypes ); Gia_ManStop( pTemp ); Vec_IntFreeP( &vPoTypes ); } if ( !fGiaSimple && !fSkipStrash && Gia_ManHasDangling(pNew) ) { Tim_Man_t * pManTime; 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 ) { // Tim_ManPrint( (Tim_Man_t *)pNew->pManTime ); if ( Abc_FrameReadLibBox() == NULL ) printf( "Warning: Creating unit-delay box delay tables because box library is not available.\n" ); Tim_ManCreate( (Tim_Man_t *)pNew->pManTime, Abc_FrameReadLibBox(), pNew->vInArrs, pNew->vOutReqs ); } Vec_FltFreeP( &pNew->vInArrs ); Vec_FltFreeP( &pNew->vOutReqs ); /* // check the result if ( fCheck && !Gia_ManCheck( pNew ) ) { printf( "Gia_AigerRead: The network check has failed.\n" ); Gia_ManStop( pNew ); return NULL; } */ if ( vInits && Vec_IntSum(vInits) ) { char * pInit = ABC_ALLOC( char, Vec_IntSize(vInits) + 1 ); Gia_Obj_t * pObj; int i; assert( Vec_IntSize(vInits) == Gia_ManRegNum(pNew) ); Gia_ManForEachRo( pNew, pObj, i ) { if ( Vec_IntEntry(vInits, i) == 0 ) pInit[i] = '0'; else if ( Vec_IntEntry(vInits, i) == 1 ) pInit[i] = '1'; else { assert( Vec_IntEntry(vInits, i) == Abc_Var2Lit(Gia_ObjId(pNew, pObj), 0) ); // unitialized value of the latch is the latch literal according to http://fmv.jku.at/hwmcc11/beyond1.pdf pInit[i] = 'X'; } } pInit[i] = 0; 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 ); if ( !fGiaSimple && !fSkipStrash && pNew->vMapping ) { 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; } /**Function************************************************************* Synopsis [Reads the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_AigerRead( char * pFileName, int fGiaSimple, int fSkipStrash, int fCheck ) { FILE * pFile; Gia_Man_t * pNew; char * pName, * pContents; int nFileSize; int RetValue; // read the file into the buffer Gia_FileFixName( pFileName ); nFileSize = Gia_FileSize( pFileName ); pFile = fopen( pFileName, "rb" ); pContents = ABC_ALLOC( char, nFileSize ); RetValue = fread( pContents, nFileSize, 1, pFile ); fclose( pFile ); pNew = Gia_AigerReadFromMemory( pContents, nFileSize, fGiaSimple, fSkipStrash, fCheck ); ABC_FREE( pContents ); if ( pNew ) { ABC_FREE( pNew->pName ); pName = Gia_FileNameGeneric( pFileName ); pNew->pName = Abc_UtilStrsav( pName ); ABC_FREE( pName ); assert( pNew->pSpec == NULL ); pNew->pSpec = Abc_UtilStrsav( pFileName ); } return pNew; } /**Function************************************************************* Synopsis [Writes the AIG in into the memory buffer.] Description [The resulting buffer constains the AIG in AIGER format. The resulting buffer should be deallocated by the user.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Gia_AigerWriteIntoMemoryStr( Gia_Man_t * p ) { Vec_Str_t * vBuffer; Gia_Obj_t * pObj; int nNodes = 0, i, uLit, uLit0, uLit1; // set the node numbers to be used in the output file Gia_ManConst0(p)->Value = nNodes++; Gia_ManForEachCi( p, pObj, i ) pObj->Value = nNodes++; Gia_ManForEachAnd( p, pObj, i ) pObj->Value = nNodes++; // write the header "M I L O A" where M = I + L + A vBuffer = Vec_StrAlloc( 3*Gia_ManObjNum(p) ); Vec_StrPrintStr( vBuffer, "aig " ); Vec_StrPrintNum( vBuffer, Gia_ManCandNum(p) ); Vec_StrPrintStr( vBuffer, " " ); Vec_StrPrintNum( vBuffer, Gia_ManPiNum(p) ); Vec_StrPrintStr( vBuffer, " " ); Vec_StrPrintNum( vBuffer, Gia_ManRegNum(p) ); Vec_StrPrintStr( vBuffer, " " ); Vec_StrPrintNum( vBuffer, Gia_ManPoNum(p) ); Vec_StrPrintStr( vBuffer, " " ); Vec_StrPrintNum( vBuffer, Gia_ManAndNum(p) ); Vec_StrPrintStr( vBuffer, "\n" ); // write latch drivers Gia_ManForEachRi( p, pObj, i ) { uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) ); Vec_StrPrintNum( vBuffer, uLit ); Vec_StrPrintStr( vBuffer, "\n" ); } // write PO drivers Gia_ManForEachPo( p, pObj, i ) { uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) ); Vec_StrPrintNum( vBuffer, uLit ); Vec_StrPrintStr( vBuffer, "\n" ); } // write the nodes into the buffer Gia_ManForEachAnd( p, pObj, i ) { uLit = Abc_Var2Lit( Gia_ObjValue(pObj), 0 ); uLit0 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) ); uLit1 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin1(pObj)), Gia_ObjFaninC1(pObj) ); assert( uLit0 != uLit1 ); if ( uLit0 > uLit1 ) { int Temp = uLit0; uLit0 = uLit1; uLit1 = Temp; } Gia_AigerWriteUnsigned( vBuffer, uLit - uLit1 ); Gia_AigerWriteUnsigned( vBuffer, uLit1 - uLit0 ); } Vec_StrPrintStr( vBuffer, "c" ); return vBuffer; } /**Function************************************************************* Synopsis [Writes the AIG in into the memory buffer.] Description [The resulting buffer constains the AIG in AIGER format. The CI/CO/AND nodes are assumed to be ordered according to some rule. The resulting buffer should be deallocated by the user.] SideEffects [Note that in vCos, PIs are order first, followed by latches!] SeeAlso [] ***********************************************************************/ Vec_Str_t * Gia_AigerWriteIntoMemoryStrPart( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs ) { Vec_Str_t * vBuffer; Gia_Obj_t * pObj; int nNodes = 0, i, uLit, uLit0, uLit1; // set the node numbers to be used in the output file Gia_ManConst0(p)->Value = nNodes++; Gia_ManForEachObjVec( vCis, p, pObj, i ) { assert( Gia_ObjIsCi(pObj) ); pObj->Value = nNodes++; } Gia_ManForEachObjVec( vAnds, p, pObj, i ) { assert( Gia_ObjIsAnd(pObj) ); pObj->Value = nNodes++; } // write the header "M I L O A" where M = I + L + A vBuffer = Vec_StrAlloc( 3*Gia_ManObjNum(p) ); Vec_StrPrintStr( vBuffer, "aig " ); Vec_StrPrintNum( vBuffer, Vec_IntSize(vCis) + Vec_IntSize(vAnds) ); Vec_StrPrintStr( vBuffer, " " ); Vec_StrPrintNum( vBuffer, Vec_IntSize(vCis) - nRegs ); Vec_StrPrintStr( vBuffer, " " ); Vec_StrPrintNum( vBuffer, nRegs ); Vec_StrPrintStr( vBuffer, " " ); Vec_StrPrintNum( vBuffer, Vec_IntSize(vCos) - nRegs ); Vec_StrPrintStr( vBuffer, " " ); Vec_StrPrintNum( vBuffer, Vec_IntSize(vAnds) ); Vec_StrPrintStr( vBuffer, "\n" ); // write latch drivers Gia_ManForEachObjVec( vCos, p, pObj, i ) { assert( Gia_ObjIsCo(pObj) ); if ( i < Vec_IntSize(vCos) - nRegs ) continue; uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) ); Vec_StrPrintNum( vBuffer, uLit ); Vec_StrPrintStr( vBuffer, "\n" ); } // write output drivers Gia_ManForEachObjVec( vCos, p, pObj, i ) { assert( Gia_ObjIsCo(pObj) ); if ( i >= Vec_IntSize(vCos) - nRegs ) continue; uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) ); Vec_StrPrintNum( vBuffer, uLit ); Vec_StrPrintStr( vBuffer, "\n" ); } // write the nodes into the buffer Gia_ManForEachObjVec( vAnds, p, pObj, i ) { uLit = Abc_Var2Lit( Gia_ObjValue(pObj), 0 ); uLit0 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) ); uLit1 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin1(pObj)), Gia_ObjFaninC1(pObj) ); assert( uLit0 != uLit1 ); if ( uLit0 > uLit1 ) { int Temp = uLit0; uLit0 = uLit1; uLit1 = Temp; } Gia_AigerWriteUnsigned( vBuffer, uLit - uLit1 ); Gia_AigerWriteUnsigned( vBuffer, uLit1 - uLit0 ); } Vec_StrPrintStr( vBuffer, "c" ); return vBuffer; } /**Function************************************************************* Synopsis [Writes the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_AigerWriteS( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine, int fSkipComment ) { int fVerbose = XAIG_VERBOSE; FILE * pFile; Gia_Man_t * p; Gia_Obj_t * pObj; Vec_Str_t * vStrExt; int i, nBufferSize, Pos; unsigned char * pBuffer; unsigned uLit0, uLit1, uLit; assert( pInit->nXors == 0 && pInit->nMuxes == 0 ); if ( Gia_ManCoNum(pInit) == 0 ) { printf( "AIG cannot be written because it has no POs.\n" ); return; } // start the output stream pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { fprintf( stdout, "Gia_AigerWrite(): Cannot open the output file \"%s\".\n", pFileName ); return; } // create normalized AIG if ( !Gia_ManIsNormalized(pInit) ) { // printf( "Gia_AigerWrite(): Normalizing AIG for writing.\n" ); p = Gia_ManDupNormalize( pInit, 0 ); Gia_ManTransferMapping( p, pInit ); Gia_ManTransferPacking( p, pInit ); Gia_ManTransferTiming( p, pInit ); p->nConstrs = pInit->nConstrs; } else p = pInit; // write the header "M I L O A" where M = I + L + A fprintf( pFile, "aig%s %u %u %u %u %u", fCompact? "2" : "", Gia_ManCiNum(p) + Gia_ManAndNum(p), Gia_ManPiNum(p), Gia_ManRegNum(p), Gia_ManConstrNum(p) ? 0 : Gia_ManPoNum(p), Gia_ManAndNum(p) ); // write the extended header "B C J F" if ( Gia_ManConstrNum(p) ) fprintf( pFile, " %u %u", Gia_ManPoNum(p) - Gia_ManConstrNum(p), Gia_ManConstrNum(p) ); fprintf( pFile, "\n" ); Gia_ManInvertConstraints( p ); if ( !fCompact ) { // write latch drivers Gia_ManForEachRi( p, pObj, i ) fprintf( pFile, "%u\n", Gia_ObjFaninLit0p(p, pObj) ); // write PO drivers Gia_ManForEachPo( p, pObj, i ) fprintf( pFile, "%u\n", Gia_ObjFaninLit0p(p, pObj) ); } else { Vec_Int_t * vLits = Gia_AigerCollectLiterals( p ); Vec_Str_t * vBinary = Gia_AigerWriteLiterals( vLits ); fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), pFile ); Vec_StrFree( vBinary ); Vec_IntFree( vLits ); } Gia_ManInvertConstraints( p ); // write the nodes into the buffer Pos = 0; nBufferSize = 8 * Gia_ManAndNum(p) + 100; // skeptically assuming 3 chars per one AIG edge pBuffer = ABC_ALLOC( unsigned char, nBufferSize ); Gia_ManForEachAnd( p, pObj, i ) { uLit = Abc_Var2Lit( i, 0 ); uLit0 = Gia_ObjFaninLit0( pObj, i ); uLit1 = Gia_ObjFaninLit1( pObj, i ); assert( p->fGiaSimple || Gia_ManBufNum(p) || uLit0 < uLit1 ); Pos = Gia_AigerWriteUnsignedBuffer( pBuffer, Pos, uLit - uLit1 ); Pos = Gia_AigerWriteUnsignedBuffer( pBuffer, Pos, uLit1 - uLit0 ); if ( Pos > nBufferSize - 10 ) { printf( "Gia_AigerWrite(): AIGER generation has failed because the allocated buffer is too small.\n" ); fclose( pFile ); if ( p != pInit ) Gia_ManStop( p ); return; } } assert( Pos < nBufferSize ); // write the buffer fwrite( pBuffer, 1, Pos, pFile ); ABC_FREE( pBuffer ); // write the symbol table if ( p->vNamesIn && p->vNamesOut ) { assert( Vec_PtrSize(p->vNamesIn) == Gia_ManCiNum(p) ); assert( Vec_PtrSize(p->vNamesOut) == Gia_ManCoNum(p) ); // write PIs Gia_ManForEachPi( p, pObj, i ) fprintf( pFile, "i%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesIn, i) ); // write latches Gia_ManForEachRo( p, pObj, i ) fprintf( pFile, "l%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesIn, Gia_ManPiNum(p) + i) ); // write POs Gia_ManForEachPo( p, pObj, i ) fprintf( pFile, "o%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesOut, i) ); } if ( p->vNamesNode && Vec_PtrSize(p->vNamesNode) != Gia_ManObjNum(p) ) Abc_Print( 0, "The size of the node name array does not match the number of objects. Names are not written.\n" ); else if ( p->vNamesNode ) { Gia_ManForEachAnd( p, pObj, i ) if ( Vec_PtrEntry(p->vNamesNode, i) ) fprintf( pFile, "n%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesNode, i) ); } // write the comment if ( fWriteNewLine ) fprintf( pFile, "c\n" ); else fprintf( pFile, "c" ); // write additional AIG if ( p->pAigExtra ) { fprintf( pFile, "a" ); vStrExt = Gia_AigerWriteIntoMemoryStr( p->pAigExtra ); Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); Vec_StrFree( vStrExt ); if ( fVerbose ) printf( "Finished writing extension \"a\".\n" ); } // write constraints if ( p->nConstrs ) { fprintf( pFile, "c" ); Gia_FileWriteBufferSize( pFile, 4 ); Gia_FileWriteBufferSize( pFile, p->nConstrs ); } // write timing information if ( p->nAnd2Delay ) { fprintf( pFile, "d" ); Gia_FileWriteBufferSize( pFile, 4 ); Gia_FileWriteBufferSize( pFile, p->nAnd2Delay ); } if ( p->pManTime ) { float * pTimes; pTimes = Tim_ManGetArrTimes( (Tim_Man_t *)p->pManTime ); if ( pTimes ) { fprintf( pFile, "i" ); Gia_FileWriteBufferSize( pFile, 4*Tim_ManPiNum((Tim_Man_t *)p->pManTime) ); fwrite( pTimes, 1, 4*Tim_ManPiNum((Tim_Man_t *)p->pManTime), pFile ); ABC_FREE( pTimes ); if ( fVerbose ) printf( "Finished writing extension \"i\".\n" ); } pTimes = Tim_ManGetReqTimes( (Tim_Man_t *)p->pManTime ); if ( pTimes ) { fprintf( pFile, "o" ); Gia_FileWriteBufferSize( pFile, 4*Tim_ManPoNum((Tim_Man_t *)p->pManTime) ); fwrite( pTimes, 1, 4*Tim_ManPoNum((Tim_Man_t *)p->pManTime), pFile ); ABC_FREE( pTimes ); if ( fVerbose ) printf( "Finished writing extension \"o\".\n" ); } } // write equivalences if ( p->pReprs && p->pNexts ) { extern Vec_Str_t * Gia_WriteEquivClasses( Gia_Man_t * p ); fprintf( pFile, "e" ); vStrExt = Gia_WriteEquivClasses( p ); Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); Vec_StrFree( vStrExt ); } // write flop classes if ( p->vFlopClasses ) { fprintf( pFile, "f" ); Gia_FileWriteBufferSize( pFile, 4*Gia_ManRegNum(p) ); assert( Vec_IntSize(p->vFlopClasses) == Gia_ManRegNum(p) ); fwrite( Vec_IntArray(p->vFlopClasses), 1, 4*Gia_ManRegNum(p), pFile ); } // write gate classes if ( p->vGateClasses ) { fprintf( pFile, "g" ); Gia_FileWriteBufferSize( pFile, 4*Gia_ManObjNum(p) ); assert( Vec_IntSize(p->vGateClasses) == Gia_ManObjNum(p) ); fwrite( Vec_IntArray(p->vGateClasses), 1, 4*Gia_ManObjNum(p), pFile ); } // write hierarchy info if ( p->pManTime ) { fprintf( pFile, "h" ); vStrExt = Tim_ManSave( (Tim_Man_t *)p->pManTime, 1 ); Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); Vec_StrFree( vStrExt ); if ( fVerbose ) printf( "Finished writing extension \"h\".\n" ); } // write packing if ( p->vPacking ) { extern Vec_Str_t * Gia_WritePacking( Vec_Int_t * vPacking ); fprintf( pFile, "k" ); vStrExt = Gia_WritePacking( p->vPacking ); Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); Vec_StrFree( vStrExt ); if ( fVerbose ) printf( "Finished writing extension \"k\".\n" ); } // write edges if ( p->vEdge1 ) { Vec_Int_t * vPairs = Gia_ManEdgeToArray( p ); int i; fprintf( pFile, "w" ); Gia_FileWriteBufferSize( pFile, 4*(Vec_IntSize(vPairs)+1) ); Gia_FileWriteBufferSize( pFile, Vec_IntSize(vPairs)/2 ); for ( i = 0; i < Vec_IntSize(vPairs); i++ ) Gia_FileWriteBufferSize( pFile, Vec_IntEntry(vPairs, i) ); Vec_IntFree( vPairs ); } // write mapping if ( Gia_ManHasMapping(p) ) { extern Vec_Str_t * Gia_AigerWriteMapping( Gia_Man_t * p ); extern Vec_Str_t * Gia_AigerWriteMappingSimple( Gia_Man_t * p ); extern Vec_Str_t * Gia_AigerWriteMappingDoc( Gia_Man_t * p ); fprintf( pFile, "m" ); vStrExt = Gia_AigerWriteMappingDoc( p ); Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); Vec_StrFree( vStrExt ); if ( fVerbose ) printf( "Finished writing extension \"m\".\n" ); } // write cell mapping if ( Gia_ManHasCellMapping(p) ) { extern Vec_Str_t * Gia_AigerWriteCellMappingDoc( Gia_Man_t * p ); fprintf( pFile, "M" ); vStrExt = Gia_AigerWriteCellMappingDoc( p ); Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); Vec_StrFree( vStrExt ); if ( fVerbose ) printf( "Finished writing extension \"M\".\n" ); } // write placement if ( p->pPlacement ) { fprintf( pFile, "p" ); Gia_FileWriteBufferSize( pFile, 4*Gia_ManObjNum(p) ); fwrite( p->pPlacement, 1, 4*Gia_ManObjNum(p), pFile ); } // write register classes if ( p->vRegClasses ) { int i; fprintf( pFile, "r" ); Gia_FileWriteBufferSize( pFile, 4*(Vec_IntSize(p->vRegClasses)+1) ); Gia_FileWriteBufferSize( pFile, Vec_IntSize(p->vRegClasses) ); for ( i = 0; i < Vec_IntSize(p->vRegClasses); i++ ) Gia_FileWriteBufferSize( pFile, Vec_IntEntry(p->vRegClasses, i) ); } // write register inits if ( p->vRegInits ) { int i; fprintf( pFile, "s" ); Gia_FileWriteBufferSize( pFile, 4*(Vec_IntSize(p->vRegInits)+1) ); Gia_FileWriteBufferSize( pFile, Vec_IntSize(p->vRegInits) ); for ( i = 0; i < Vec_IntSize(p->vRegInits); i++ ) Gia_FileWriteBufferSize( pFile, Vec_IntEntry(p->vRegInits, i) ); } // write configuration data if ( p->vConfigs ) { fprintf( pFile, "b" ); assert( p->pCellStr != NULL ); Gia_FileWriteBufferSize( pFile, 4*Vec_IntSize(p->vConfigs) + strlen(p->pCellStr) + 1 ); fwrite( p->pCellStr, 1, strlen(p->pCellStr) + 1, pFile ); // fwrite( Vec_IntArray(p->vConfigs), 1, 4*Vec_IntSize(p->vConfigs), pFile ); for ( i = 0; i < Vec_IntSize(p->vConfigs); i++ ) Gia_FileWriteBufferSize( pFile, Vec_IntEntry(p->vConfigs, i) ); } // write choices if ( Gia_ManHasChoices(p) ) { int i, nPairs = 0; fprintf( pFile, "q" ); for ( i = 0; i < Gia_ManObjNum(p); i++ ) nPairs += (Gia_ObjSibl(p, i) > 0); Gia_FileWriteBufferSize( pFile, 4*(nPairs * 2 + 1) ); Gia_FileWriteBufferSize( pFile, nPairs ); for ( i = 0; i < Gia_ManObjNum(p); i++ ) if ( Gia_ObjSibl(p, i) ) { assert( i > Gia_ObjSibl(p, i) ); Gia_FileWriteBufferSize( pFile, i ); Gia_FileWriteBufferSize( pFile, Gia_ObjSibl(p, i) ); } if ( fVerbose ) printf( "Finished writing extension \"q\".\n" ); } // write switching activity if ( p->pSwitching ) { fprintf( pFile, "u" ); Gia_FileWriteBufferSize( pFile, Gia_ManObjNum(p) ); fwrite( p->pSwitching, 1, Gia_ManObjNum(p), pFile ); } /* // write timing information if ( p->pManTime ) { fprintf( pFile, "t" ); vStrExt = Tim_ManSave( (Tim_Man_t *)p->pManTime, 0 ); Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); Vec_StrFree( vStrExt ); } */ // write object classes if ( p->vObjClasses ) { fprintf( pFile, "v" ); Gia_FileWriteBufferSize( pFile, 4*Gia_ManObjNum(p) ); assert( Vec_IntSize(p->vObjClasses) == Gia_ManObjNum(p) ); fwrite( Vec_IntArray(p->vObjClasses), 1, 4*Gia_ManObjNum(p), pFile ); } // write name if ( p->pName ) { fprintf( pFile, "n" ); Gia_FileWriteBufferSize( pFile, strlen(p->pName)+1 ); fwrite( p->pName, 1, strlen(p->pName), pFile ); fprintf( pFile, "%c", '\0' ); } // write comments if ( fWriteNewLine ) fprintf( pFile, "c\n" ); if ( !fSkipComment ) { 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 ) { Gia_ManTransferTiming( pInit, p ); Gia_ManStop( p ); } } /**Function************************************************************* Synopsis [Writes the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine ) { Gia_AigerWriteS( pInit, pFileName, fWriteSymbols, fCompact, fWriteNewLine, 0 ); } /**Function************************************************************* Synopsis [Writes the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_DumpAiger( Gia_Man_t * p, char * pFilePrefix, int iFileNum, int nFileNumDigits ) { char Buffer[100]; sprintf( Buffer, "%s%0*d.aig", pFilePrefix, nFileNumDigits, iFileNum ); Gia_AigerWrite( p, Buffer, 0, 0, 0 ); } /**Function************************************************************* Synopsis [Writes the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_AigerWriteSimple( Gia_Man_t * pInit, char * pFileName ) { FILE * pFile; Vec_Str_t * vStr; if ( Gia_ManPoNum(pInit) == 0 ) { printf( "Gia_AigerWriteSimple(): AIG cannot be written because it has no POs.\n" ); return; } // start the output stream pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { fprintf( stdout, "Gia_AigerWriteSimple(): Cannot open the output file \"%s\".\n", pFileName ); return; } // write the buffer vStr = Gia_AigerWriteIntoMemoryStr( pInit ); fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile ); Vec_StrFree( vStr ); 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 /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaAigerExt.c000066400000000000000000000327111477524141600166300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaAigerExt.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Custom AIGER extensions.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaAigerExt.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/st/st.h" #include "map/mio/mio.h" #include "map/mio/mioInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Read/write equivalence classes information.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Rpr_t * Gia_AigerReadEquivClasses( unsigned char ** ppPos, int nSize ) { Gia_Rpr_t * pReprs; unsigned char * pStop; int i, Item, fProved, iRepr, iNode; pStop = *ppPos; pStop += Gia_AigerReadInt( *ppPos ); *ppPos += 4; pReprs = ABC_CALLOC( Gia_Rpr_t, nSize ); for ( i = 0; i < nSize; i++ ) pReprs[i].iRepr = GIA_VOID; iRepr = iNode = 0; while ( *ppPos < pStop ) { Item = Gia_AigerReadUnsigned( ppPos ); if ( Item & 1 ) { iRepr += (Item >> 1); iNode = iRepr; continue; } Item >>= 1; fProved = (Item & 1); Item >>= 1; iNode += Item; pReprs[iNode].fProved = fProved; pReprs[iNode].iRepr = iRepr; assert( iRepr < iNode ); } return pReprs; } unsigned char * Gia_WriteEquivClassesInt( Gia_Man_t * p, int * pEquivSize ) { unsigned char * pBuffer; int iRepr, iNode, iPrevRepr, iPrevNode, iLit, nItems, iPos; assert( p->pReprs && p->pNexts ); // count the number of entries to be written nItems = 0; for ( iRepr = 1; iRepr < Gia_ManObjNum(p); iRepr++ ) { nItems += Gia_ObjIsConst( p, iRepr ); if ( !Gia_ObjIsHead(p, iRepr) ) continue; Gia_ClassForEachObj( p, iRepr, iNode ) nItems++; } pBuffer = ABC_ALLOC( unsigned char, sizeof(int) * (nItems + 10) ); // write constant class iPos = Gia_AigerWriteUnsignedBuffer( pBuffer, 4, Abc_Var2Lit(0, 1) ); iPrevNode = 0; for ( iNode = 1; iNode < Gia_ManObjNum(p); iNode++ ) if ( Gia_ObjIsConst(p, iNode) ) { iLit = Abc_Var2Lit( iNode - iPrevNode, Gia_ObjProved(p, iNode) ); iPrevNode = iNode; iPos = Gia_AigerWriteUnsignedBuffer( pBuffer, iPos, Abc_Var2Lit(iLit, 0) ); } // write non-constant classes iPrevRepr = 0; Gia_ManForEachClass( p, iRepr ) { iPos = Gia_AigerWriteUnsignedBuffer( pBuffer, iPos, Abc_Var2Lit(iRepr - iPrevRepr, 1) ); iPrevRepr = iPrevNode = iRepr; Gia_ClassForEachObj1( p, iRepr, iNode ) { iLit = Abc_Var2Lit( iNode - iPrevNode, Gia_ObjProved(p, iNode) ); iPrevNode = iNode; iPos = Gia_AigerWriteUnsignedBuffer( pBuffer, iPos, Abc_Var2Lit(iLit, 0) ); } } Gia_AigerWriteInt( pBuffer, iPos ); *pEquivSize = iPos; return pBuffer; } Vec_Str_t * Gia_WriteEquivClasses( Gia_Man_t * p ) { int nEquivSize; unsigned char * pBuffer = Gia_WriteEquivClassesInt( p, &nEquivSize ); return Vec_StrAllocArray( (char *)pBuffer, nEquivSize ); } /**Function************************************************************* Synopsis [Read/write mapping information.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Gia_AigerReadDiffValue( unsigned char ** ppPos, int iPrev ) { int Item = Gia_AigerReadUnsigned( ppPos ); if ( Item & 1 ) return iPrev + (Item >> 1); return iPrev - (Item >> 1); } int * Gia_AigerReadMapping( unsigned char ** ppPos, int nSize ) { int * pMapping; unsigned char * pStop; int k, j, nFanins, nAlloc, iNode = 0, iOffset = nSize; pStop = *ppPos; pStop += Gia_AigerReadInt( *ppPos ); *ppPos += 4; nAlloc = nSize + pStop - *ppPos; pMapping = ABC_CALLOC( int, nAlloc ); while ( *ppPos < pStop ) { k = iOffset; pMapping[k++] = nFanins = Gia_AigerReadUnsigned( ppPos ); for ( j = 0; j <= nFanins; j++ ) pMapping[k++] = iNode = Gia_AigerReadDiffValue( ppPos, iNode ); pMapping[iNode] = iOffset; iOffset = k; } assert( iOffset <= nAlloc ); return pMapping; } static inline int Gia_AigerWriteDiffValue( unsigned char * pPos, int iPos, int iPrev, int iThis ) { if ( iPrev < iThis ) return Gia_AigerWriteUnsignedBuffer( pPos, iPos, Abc_Var2Lit(iThis - iPrev, 1) ); return Gia_AigerWriteUnsignedBuffer( pPos, iPos, Abc_Var2Lit(iPrev - iThis, 0) ); } unsigned char * Gia_AigerWriteMappingInt( Gia_Man_t * p, int * pMapSize ) { unsigned char * pBuffer; int i, k, iPrev, iFan, nItems, iPos = 4; assert( Gia_ManHasMapping(p) ); // count the number of entries to be written nItems = 0; Gia_ManForEachLut( p, i ) nItems += 2 + Gia_ObjLutSize( p, i ); pBuffer = ABC_ALLOC( unsigned char, sizeof(int) * (nItems + 1) ); // write non-constant classes iPrev = 0; Gia_ManForEachLut( p, i ) { //printf( "\nSize = %d ", Gia_ObjLutSize(p, i) ); iPos = Gia_AigerWriteUnsignedBuffer( pBuffer, iPos, Gia_ObjLutSize(p, i) ); Gia_LutForEachFanin( p, i, iFan, k ) { //printf( "Fan = %d ", iFan ); iPos = Gia_AigerWriteDiffValue( pBuffer, iPos, iPrev, iFan ); iPrev = iFan; } iPos = Gia_AigerWriteDiffValue( pBuffer, iPos, iPrev, i ); iPrev = i; //printf( "Node = %d ", i ); } //printf( "\n" ); Gia_AigerWriteInt( pBuffer, iPos ); *pMapSize = iPos; return pBuffer; } Vec_Str_t * Gia_AigerWriteMapping( Gia_Man_t * p ) { int nMapSize; unsigned char * pBuffer = Gia_AigerWriteMappingInt( p, &nMapSize ); return Vec_StrAllocArray( (char *)pBuffer, nMapSize ); } /**Function************************************************************* Synopsis [Read/write mapping information.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Gia_AigerReadMappingSimple( unsigned char ** ppPos, int nSize ) { int * pMapping = ABC_ALLOC( int, (size_t)nSize/4 ); memcpy( pMapping, *ppPos, nSize ); assert( nSize % 4 == 0 ); return pMapping; } 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), (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) ); } /**Function************************************************************* Synopsis [Read/write mapping information.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_AigerReadMappingDoc( unsigned char ** ppPos, int nObjs ) { int * pMapping, nLuts, LutSize, iRoot, nFanins, i, k, nOffset; nLuts = Gia_AigerReadInt( *ppPos ); *ppPos += 4; LutSize = Gia_AigerReadInt( *ppPos ); *ppPos += 4; pMapping = ABC_CALLOC( int, nObjs + (LutSize + 2) * nLuts ); nOffset = nObjs; for ( i = 0; i < nLuts; i++ ) { iRoot = Gia_AigerReadInt( *ppPos ); *ppPos += 4; nFanins = Gia_AigerReadInt( *ppPos ); *ppPos += 4; pMapping[iRoot] = nOffset; // write one pMapping[ nOffset++ ] = nFanins; for ( k = 0; k < nFanins; k++ ) { pMapping[ nOffset++ ] = Gia_AigerReadInt( *ppPos ); *ppPos += 4; } pMapping[ nOffset++ ] = iRoot; } return Vec_IntAllocArray( pMapping, nOffset ); } Vec_Str_t * Gia_AigerWriteMappingDoc( Gia_Man_t * p ) { unsigned char * pBuffer; int i, k, iFan, nLuts = 0, LutSize = 0, nSize = 2, nSize2 = 0; Gia_ManForEachLut( p, i ) { nLuts++; nSize += Gia_ObjLutSize(p, i) + 2; LutSize = Abc_MaxInt( LutSize, Gia_ObjLutSize(p, i) ); } pBuffer = ABC_ALLOC( unsigned char, 4 * nSize ); Gia_AigerWriteInt( pBuffer + 4 * nSize2++, nLuts ); Gia_AigerWriteInt( pBuffer + 4 * nSize2++, LutSize ); Gia_ManForEachLut( p, i ) { Gia_AigerWriteInt( pBuffer + 4 * nSize2++, i ); Gia_AigerWriteInt( pBuffer + 4 * nSize2++, Gia_ObjLutSize(p, i) ); Gia_LutForEachFanin( p, i, iFan, k ) Gia_AigerWriteInt( pBuffer + 4 * nSize2++, iFan ); } assert( nSize2 == nSize ); return Vec_StrAllocArray( (char *)pBuffer, 4*nSize ); } int Gia_AigerWriteCellMappingInstance( Gia_Man_t * p, unsigned char * pBuffer, int nSize2, int i ) { int k, iFan; if ( !Gia_ObjIsCellInv(p, i) ) { Gia_AigerWriteInt( pBuffer + nSize2, Gia_ObjCellId(p, i) ); nSize2 += 4; Gia_AigerWriteInt( pBuffer + nSize2, i ); nSize2 += 4; Gia_CellForEachFanin( p, i, iFan, k ) { Gia_AigerWriteInt( pBuffer + nSize2, iFan ); nSize2 += 4; } } else { Gia_AigerWriteInt( pBuffer + nSize2, 3 ); nSize2 += 4; Gia_AigerWriteInt( pBuffer + nSize2, i ); nSize2 += 4; Gia_AigerWriteInt( pBuffer + nSize2, Abc_LitNot(i) ); nSize2 += 4; } return nSize2; } Vec_Str_t * Gia_AigerWriteCellMappingDoc( Gia_Man_t * p ) { unsigned char * pBuffer; int i, nCells = 0, nInstances = 0, nSize = 8, nSize2 = 0; Mio_Cell2_t * pCells = Mio_CollectRootsNewDefault2( 6, &nCells, 0 ); assert( pCells ); for (int i = 0; i < nCells; i++) { Mio_Gate_t *pGate = (Mio_Gate_t *) pCells[i].pMioGate; Mio_Pin_t *pPin; nSize += strlen(Mio_GateReadName(pGate)) + 1; nSize += strlen(Mio_GateReadOutName(pGate)) + 1 + 4; Mio_GateForEachPin( pGate, pPin ) nSize += strlen(Mio_PinReadName(pPin)) + 1; } Gia_ManForEachCell( p, i ) { assert ( !Gia_ObjIsCellBuf(p, i) ); // not implemented nInstances++; if ( Gia_ObjIsCellInv(p, i) ) nSize += 12; else nSize += Gia_ObjCellSize(p, i) * 4 + 8; } pBuffer = ABC_ALLOC( unsigned char, nSize ); Gia_AigerWriteInt( pBuffer + nSize2, nCells ); nSize2 += 4; Gia_AigerWriteInt( pBuffer + nSize2, nInstances ); nSize2 += 4; for (int i = 0; i < nCells; i++) { int nPins = 0; Mio_Gate_t *pGate = (Mio_Gate_t *) pCells[i].pMioGate; Mio_Pin_t *pPin; strcpy((char *) pBuffer + nSize2, Mio_GateReadName(pGate)); nSize2 += strlen(Mio_GateReadName(pGate)) + 1; strcpy((char *) pBuffer + nSize2, Mio_GateReadOutName(pGate)); nSize2 += strlen(Mio_GateReadOutName(pGate)) + 1; Mio_GateForEachPin( pGate, pPin ) nPins++; Gia_AigerWriteInt( pBuffer + nSize2, nPins ); nSize2 += 4; Mio_GateForEachPin( pGate, pPin ) { strcpy((char *) pBuffer + nSize2, Mio_PinReadName(pPin)); nSize2 += strlen(Mio_PinReadName(pPin)) + 1; } } Gia_ManForEachCell( p, i ) { if ( Gia_ObjIsCellBuf(p, i) ) continue; if ( Gia_ObjIsCellInv(p, i) && !Abc_LitIsCompl(i) ) { // swap the order so that the inverter is after the driver // of the inverter's input nSize2 = Gia_AigerWriteCellMappingInstance(p, pBuffer, nSize2, Abc_LitNot(i) ); nSize2 = Gia_AigerWriteCellMappingInstance(p, pBuffer, nSize2, i ); i += 1; continue; } nSize2 = Gia_AigerWriteCellMappingInstance(p, pBuffer, nSize2, i ); } assert( nSize2 == nSize ); ABC_FREE( pCells ); return Vec_StrAllocArray( (char *)pBuffer, nSize ); } /**Function************************************************************* Synopsis [Read/write packing information.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_AigerReadPacking( unsigned char ** ppPos, int nSize ) { Vec_Int_t * vPacking = Vec_IntAlloc( nSize/4 ); int i; assert( nSize % 4 == 0 ); for ( i = 0; i < nSize/4; i++, *ppPos += 4 ) Vec_IntPush( vPacking, Gia_AigerReadInt( *ppPos ) ); return vPacking; } Vec_Str_t * Gia_WritePacking( Vec_Int_t * vPacking ) { unsigned char * pBuffer = ABC_ALLOC( unsigned char, 4*Vec_IntSize(vPacking) ); int i, Entry, nSize = 0; Vec_IntForEachEntry( vPacking, Entry, i ) Gia_AigerWriteInt( pBuffer + 4 * nSize++, Entry ); return Vec_StrAllocArray( (char *)pBuffer, 4*Vec_IntSize(vPacking) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaBalAig.c000066400000000000000000001175101477524141600162400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaBalance.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [AIG balancing.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaBalance.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/vec/vecHash.h" #include "misc/vec/vecQue.h" #include "opt/dau/dau.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // operation manager typedef struct Dam_Man_t_ Dam_Man_t; struct Dam_Man_t_ { Gia_Man_t * pGia; // user's AIG Vec_Int_t * vNod2Set; // node ID into fanin set Vec_Int_t * vDiv2Nod; // div ID into root node set Vec_Int_t * vSetStore; // fanin set storage Vec_Int_t * vNodStore; // root node set storage Vec_Flt_t * vCounts; // occur counts Vec_Int_t * vNodLevR; // node reverse level Vec_Int_t * vDivLevR; // divisor reverse level Vec_Int_t * vVisit; // visited MUXes Vec_Que_t * vQue; // pairs by their weight Hash_IntMan_t * vHash; // pair hash table abctime clkStart; // starting the clock int nLevelMax; // maximum level int nDivs; // extracted divisor count int nAnds; // total AND node count int nGain; // total gain in AND nodes int nGainX; // gain from XOR nodes }; static inline int Dam_ObjHand( Dam_Man_t * p, int i ) { return i < Vec_IntSize(p->vNod2Set) ? Vec_IntEntry(p->vNod2Set, i) : 0; } static inline int * Dam_ObjSet( Dam_Man_t * p, int i ) { int h = Dam_ObjHand(p, i); if ( h == 0 ) return NULL; return Vec_IntEntryP(p->vSetStore, h); } static inline int Dam_DivHand( Dam_Man_t * p, int d ) { return d < Vec_IntSize(p->vDiv2Nod) ? Vec_IntEntry(p->vDiv2Nod, d) : 0; } static inline int * Dam_DivSet( Dam_Man_t * p, int d ) { int h = Dam_DivHand(p, d); if ( h == 0 ) return NULL; return Vec_IntEntryP(p->vNodStore, h); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Simplify multi-input AND/XOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSimplifyXor( Vec_Int_t * vSuper ) { int i, k = 0, Prev = -1, This, fCompl = 0; Vec_IntForEachEntry( vSuper, This, i ) { if ( This == 0 ) continue; if ( This == 1 ) fCompl ^= 1; else if ( Prev != This ) Vec_IntWriteEntry( vSuper, k++, This ), Prev = This; else Prev = -1, k--; } Vec_IntShrink( vSuper, k ); if ( Vec_IntSize( vSuper ) == 0 ) Vec_IntPush( vSuper, fCompl ); else if ( fCompl ) Vec_IntWriteEntry( vSuper, 0, Abc_LitNot(Vec_IntEntry(vSuper, 0)) ); } void Gia_ManSimplifyAnd( Vec_Int_t * vSuper ) { int i, k = 0, Prev = -1, This; Vec_IntForEachEntry( vSuper, This, i ) { if ( This == 0 ) { Vec_IntFill(vSuper, 1, 0); return; } if ( This == 1 ) continue; if ( Prev == -1 || Abc_Lit2Var(Prev) != Abc_Lit2Var(This) ) Vec_IntWriteEntry( vSuper, k++, This ), Prev = This; else if ( Prev != This ) { Vec_IntFill(vSuper, 1, 0); return; } } Vec_IntShrink( vSuper, k ); if ( Vec_IntSize( vSuper ) == 0 ) Vec_IntPush( vSuper, 1 ); } /**Function************************************************************* Synopsis [Collect multi-input AND/XOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSuperCollectXor_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int fStrict ) { assert( !Gia_IsComplement(pObj) ); if ( !Gia_ObjIsXor(pObj) || (fStrict && Gia_ObjRefNum(p, pObj) > 1) || Gia_ObjRefNum(p, pObj) > 2 || (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || Vec_IntSize(p->vSuper) > 50 ) { Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) ); return; } assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ); Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj), fStrict ); Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj), fStrict ); } void Gia_ManSuperCollectAnd_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int fStrict ) { if ( Gia_IsComplement(pObj) || !Gia_ObjIsAndReal(p, pObj) || (fStrict && Gia_ObjRefNum(p, pObj) > 1) || Gia_ObjRefNum(p, pObj) > 2 || (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || Vec_IntSize(p->vSuper) > 50 ) { Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) ); return; } Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj), fStrict ); Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj), fStrict ); } void Gia_ManSuperCollect( Gia_Man_t * p, Gia_Obj_t * pObj, int fStrict ) { // int nSize; if ( p->vSuper == NULL ) p->vSuper = Vec_IntAlloc( 1000 ); else Vec_IntClear( p->vSuper ); if ( Gia_ObjIsXor(pObj) ) { assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ); Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj), fStrict ); Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj), fStrict ); // nSize = Vec_IntSize(vSuper); Vec_IntSort( p->vSuper, 0 ); Gia_ManSimplifyXor( p->vSuper ); // if ( nSize != Vec_IntSize(vSuper) ) // printf( "X %d->%d ", nSize, Vec_IntSize(vSuper) ); } else if ( Gia_ObjIsAndReal(p, pObj) ) { Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj), fStrict ); Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj), fStrict ); // nSize = Vec_IntSize(vSuper); Vec_IntSort( p->vSuper, 0 ); Gia_ManSimplifyAnd( p->vSuper ); // if ( nSize != Vec_IntSize(vSuper) ) // printf( "A %d->%d ", nSize, Vec_IntSize(vSuper) ); } else assert( 0 ); // if ( nSize > 10 ) // printf( "%d ", nSize ); assert( Vec_IntSize(p->vSuper) > 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFindSharedNode( Gia_Man_t * pNew, Vec_Int_t * vSuper, int iLit0 ) { int i, iLit1 = Vec_IntEntryLast(vSuper); // iterate through the nodes whose level is equal to that of the last one int iLit1Level = Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit1)); for ( i = Vec_IntSize(vSuper)-1; i >= 0; i-- ) { int iLit2 = Vec_IntEntry(vSuper, i); if ( iLit1Level != Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit2)) ) break; if ( Abc_Lit2Var(iLit0) != Abc_Lit2Var(iLit2) && !Gia_ManHashLookupInt(pNew, iLit0, iLit2) ) // new node continue; // swap iLit2 and iLit1 if ( iLit2 != iLit1 ) { Vec_IntWriteEntry( vSuper, i, iLit1 ); Vec_IntWriteEntry( vSuper, Vec_IntSize(vSuper)-1, iLit2 ); } break; } return Vec_IntPop(vSuper); } void Gia_ManPrepareLastTwo( Gia_Man_t * pNew, Vec_Int_t * vSuper ) { int i, k, Stop, Lit1, Lit2, Level1, Level2, * pArray; int nSize = Vec_IntSize(vSuper); if ( nSize == 2 ) return; assert( nSize > 2 ); Level1 = Gia_ObjLevelId( pNew, Abc_Lit2Var(Vec_IntEntry(vSuper, nSize-2)) ); // find the first one with Level1 for ( Stop = nSize-3; Stop >= 0; Stop-- ) { Level2 = Gia_ObjLevelId( pNew, Abc_Lit2Var(Vec_IntEntry(vSuper, Stop)) ); if ( Level1 != Level2 ) break; } if ( Stop == nSize-3 ) return; // avoid worst-case quadratic behavior by looking at the last 8 nodes Stop = Abc_MaxInt( Stop, nSize - 9 ); for ( i = nSize - 1; i > Stop; i-- ) for ( k = i - 1; k > Stop; k-- ) { Lit1 = Vec_IntEntry(vSuper, i); Lit2 = Vec_IntEntry(vSuper, k); if ( Abc_Lit2Var(Lit1) != Abc_Lit2Var(Lit2) && !Gia_ManHashLookupInt(pNew, Lit1, Lit2) ) // new node continue; // move Lit1 to be last and Lit2 to be the one before pArray = Vec_IntArray( vSuper ); if ( i != nSize-1 ) ABC_SWAP( int, pArray[i], pArray[nSize-1] ); if ( k != nSize-2 ) ABC_SWAP( int, pArray[k], pArray[nSize-2] ); } } void Gia_ManCreateGate( Gia_Man_t * pNew, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) { int iLit0 = Vec_IntPop(vSuper); int iLit1 = Vec_IntPop(vSuper); // int iLit1 = Gia_ManFindSharedNode(pNew, vSuper, iLit0); int iLit, i; if ( !Gia_ObjIsXor(pObj) ) iLit = Gia_ManHashAnd( pNew, iLit0, iLit1 ); else if ( pNew->pMuxes ) iLit = Gia_ManHashXorReal( pNew, iLit0, iLit1 ); else iLit = Gia_ManHashXor( pNew, iLit0, iLit1 ); Vec_IntPush( vSuper, iLit ); Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(iLit)) ); // shift to the corrent location for ( i = Vec_IntSize(vSuper)-1; i > 0; i-- ) { int iLit1 = Vec_IntEntry(vSuper, i); int iLit2 = Vec_IntEntry(vSuper, i-1); if ( Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit1)) <= Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit2)) ) break; Vec_IntWriteEntry( vSuper, i, iLit2 ); Vec_IntWriteEntry( vSuper, i-1, iLit1 ); } } int Gia_ManBalanceGate( Gia_Man_t * pNew, Gia_Obj_t * pObj, Vec_Int_t * vSuper, int * pLits, int nLits ) { assert( !Gia_ObjIsBuf(pObj) ); Vec_IntClear( vSuper ); if ( nLits == 1 ) Vec_IntPush( vSuper, pLits[0] ); else if ( nLits == 2 ) { Vec_IntPush( vSuper, pLits[0] ); Vec_IntPush( vSuper, pLits[1] ); Gia_ManCreateGate( pNew, pObj, vSuper ); } else if ( nLits > 2 ) { // collect levels int i, * pArray, * pPerm; //int iLit; for ( i = 0; i < nLits; i++ ) Vec_IntPush( vSuper, Gia_ObjLevelId(pNew, Abc_Lit2Var(pLits[i])) ); // sort by level Vec_IntGrow( vSuper, 4 * nLits ); pArray = Vec_IntArray( vSuper ); pPerm = pArray + nLits; Abc_QuickSortCostData( pArray, nLits, 1, (word *)(pArray + 2 * nLits), pPerm ); // collect in the increasing order of level for ( i = 0; i < nLits; i++ ) Vec_IntWriteEntry( vSuper, i, pLits[pPerm[i]] ); Vec_IntShrink( vSuper, nLits ); /* Vec_IntForEachEntry( vSuper, iLit, i ) printf( "%d ", Gia_ObjLevel(pNew, Gia_ManObj( pNew, Abc_Lit2Var(iLit) )) ); printf( "\n" ); */ // perform incremental extraction while ( Vec_IntSize(vSuper) > 1 ) { if ( !Gia_ObjIsXor(pObj) ) Gia_ManPrepareLastTwo( pNew, vSuper ); Gia_ManCreateGate( pNew, pObj, vSuper ); } } // consider trivial case assert( Vec_IntSize(vSuper) == 1 ); return Vec_IntEntry(vSuper, 0); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManBalance_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int fStrict ) { int i, iLit, iBeg, iEnd; if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); assert( !Gia_ObjIsBuf(pObj) ); // handle MUX if ( Gia_ObjIsMux(p, pObj) ) { Gia_ManBalance_rec( pNew, p, Gia_ObjFanin0(pObj), fStrict ); Gia_ManBalance_rec( pNew, p, Gia_ObjFanin1(pObj), fStrict ); Gia_ManBalance_rec( pNew, p, Gia_ObjFanin2(p, pObj), fStrict ); pObj->Value = Gia_ManHashMuxReal( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value)) ); return; } // find supergate Gia_ManSuperCollect( p, pObj, fStrict ); // save entries if ( p->vStore == NULL ) p->vStore = Vec_IntAlloc( 1000 ); iBeg = Vec_IntSize( p->vStore ); Vec_IntAppend( p->vStore, p->vSuper ); iEnd = Vec_IntSize( p->vStore ); // call recursively Vec_IntForEachEntryStartStop( p->vStore, iLit, i, iBeg, iEnd ) { Gia_Obj_t * pTemp = Gia_ManObj( p, Abc_Lit2Var(iLit) ); Gia_ManBalance_rec( pNew, p, pTemp, fStrict ); Vec_IntWriteEntry( p->vStore, i, Abc_LitNotCond(pTemp->Value, Abc_LitIsCompl(iLit)) ); } assert( Vec_IntSize(p->vStore) == iEnd ); // consider general case pObj->Value = Gia_ManBalanceGate( pNew, pObj, p->vSuper, Vec_IntEntryP(p->vStore, iBeg), iEnd-iBeg ); Vec_IntShrink( p->vStore, iBeg ); } Gia_Man_t * Gia_ManBalanceInt( Gia_Man_t * p, int fStrict ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; Gia_ManFillValue( p ); 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 ); pNew->vLevels = Vec_IntStart( pNew->nObjsAlloc ); // create constant and inputs Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); // set arrival times for the input of the new AIG if ( p->vCiArrs ) { int Id, And2Delay = p->And2Delay ? p->And2Delay : 1; 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 ) { Gia_ManBalance_rec( pNew, p, Gia_ObjFanin0(pObj), fStrict ); pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value)) ); } Gia_ManForEachCo( p, pObj, i ) { Gia_ManBalance_rec( pNew, p, Gia_ObjFanin0(pObj), fStrict ); pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } assert( !fStrict || Gia_ManObjNum(pNew) <= Gia_ManObjNum(p) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // perform cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManBalance( Gia_Man_t * p, int fSimpleAnd, int fStrict, int fVerbose ) { Gia_Man_t * pNew, * pNew1, * pNew2; if ( fVerbose ) Gia_ManPrintStats( p, NULL ); pNew = fSimpleAnd ? Gia_ManDup( p ) : Gia_ManDupMuxes( p, 2 ); Gia_ManTransferTiming( pNew, p ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); pNew1 = Gia_ManBalanceInt( pNew, fStrict ); Gia_ManTransferTiming( pNew1, pNew ); if ( fVerbose ) Gia_ManPrintStats( pNew1, NULL ); Gia_ManStop( pNew ); pNew2 = Gia_ManDupNoMuxes( pNew1, 0 ); Gia_ManTransferTiming( pNew2, pNew1 ); if ( fVerbose ) Gia_ManPrintStats( pNew2, NULL ); Gia_ManStop( pNew1 ); return pNew2; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dam_Man_t * Dam_ManAlloc( Gia_Man_t * pGia ) { Dam_Man_t * p; p = ABC_CALLOC( Dam_Man_t, 1 ); p->clkStart = Abc_Clock(); p->vVisit = Vec_IntAlloc( 1000 ); p->pGia = pGia; return p; } void Dam_ManFree( Dam_Man_t * p ) { Vec_IntFreeP( &p->vVisit ); Vec_IntFreeP( &p->vDivLevR ); Vec_IntFreeP( &p->vNodLevR ); Vec_IntFreeP( &p->vNod2Set ); Vec_IntFreeP( &p->vDiv2Nod ); Vec_IntFreeP( &p->vSetStore ); Vec_IntFreeP( &p->vNodStore ); Vec_FltFreeP( &p->vCounts ); Vec_QueFreeP( &p->vQue ); Hash_IntManStop( p->vHash ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Collect initial multi-input gates.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dam_ManCollectSets_rec( Dam_Man_t * p, int Id ) { Gia_Obj_t * pObj; int i, iBeg, iEnd, iLit; if ( Dam_ObjHand(p, Id) || Id == 0 ) return; pObj = Gia_ManObj(p->pGia, Id); if ( Gia_ObjIsCi(pObj) ) return; if ( Gia_ObjIsBuf(pObj) ) { Dam_ManCollectSets_rec( p, Gia_ObjFaninId0(pObj, Id) ); return; } if ( Gia_ObjIsMux(p->pGia, pObj) ) { if ( pObj->fMark0 ) return; pObj->fMark0 = 1; Vec_IntPush( p->vVisit, Id ); Dam_ManCollectSets_rec( p, Gia_ObjFaninId0(pObj, Id) ); Dam_ManCollectSets_rec( p, Gia_ObjFaninId1(pObj, Id) ); Dam_ManCollectSets_rec( p, Gia_ObjFaninId2(p->pGia, Id) ); p->nAnds += 3; return; } Gia_ManSuperCollect( p->pGia, pObj, 0 ); Vec_IntWriteEntry( p->vNod2Set, Id, Vec_IntSize(p->vSetStore) ); Vec_IntPush( p->vSetStore, Vec_IntSize(p->pGia->vSuper) ); p->nAnds += (1 + 2 * Gia_ObjIsXor(pObj)) * (Vec_IntSize(p->pGia->vSuper) - 1); // save entries iBeg = Vec_IntSize( p->vSetStore ); Vec_IntAppend( p->vSetStore, p->pGia->vSuper ); iEnd = Vec_IntSize( p->vSetStore ); // call recursively Vec_IntForEachEntryStartStop( p->vSetStore, iLit, i, iBeg, iEnd ) Dam_ManCollectSets_rec( p, Abc_Lit2Var(iLit) ); } void Dam_ManCollectSets( Dam_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManCreateRefs( p->pGia ); p->vNod2Set = Vec_IntStart( Gia_ManObjNum(p->pGia) ); p->vSetStore = Vec_IntAlloc( Gia_ManObjNum(p->pGia) ); Vec_IntPush( p->vSetStore, -1 ); Vec_IntClear( p->vVisit ); Gia_ManForEachCo( p->pGia, pObj, i ) Dam_ManCollectSets_rec( p, Gia_ObjFaninId0p(p->pGia, pObj) ); ABC_FREE( p->pGia->pRefs ); Gia_ManForEachObjVec( p->vVisit, p->pGia, pObj, i ) pObj->fMark0 = 0; } /**Function************************************************************* Synopsis [Create divisors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Dam_ManDivSlack( Dam_Man_t * p, int iLit0, int iLit1, int LevR ) { int Lev0 = Gia_ObjLevel(p->pGia, Gia_ManObj(p->pGia, Abc_Lit2Var(iLit0))); int Lev1 = Gia_ObjLevel(p->pGia, Gia_ManObj(p->pGia, Abc_Lit2Var(iLit1))); int Slack = p->nLevelMax - LevR - Abc_MaxInt(Lev0, Lev1) - 1 - (int)(iLit0 > iLit1); return Abc_MinInt( Slack, 100 ); } void Dam_ManCreateMultiRefs( Dam_Man_t * p, Vec_Int_t ** pvRefsAnd, Vec_Int_t ** pvRefsXor ) { Vec_Int_t * vRefsAnd, * vRefsXor; Gia_Obj_t * pObj; int i, k, * pSet; vRefsAnd = Vec_IntStart( 2 * Gia_ManObjNum(p->pGia) ); vRefsXor = Vec_IntStart( Gia_ManObjNum(p->pGia) ); Gia_ManForEachAnd( p->pGia, pObj, i ) { if ( !Dam_ObjHand(p, i) ) continue; pSet = Dam_ObjSet(p, i); if ( Gia_ObjIsXor(pObj) ) for ( k = 1; k <= pSet[0]; k++ ) { assert( !Abc_LitIsCompl(pSet[k]) ); Vec_IntAddToEntry( vRefsXor, Abc_Lit2Var(pSet[k]), 1 ); } else if ( Gia_ObjIsAndReal(p->pGia, pObj) ) for ( k = 1; k <= pSet[0]; k++ ) Vec_IntAddToEntry( vRefsAnd, pSet[k], 1 ); else assert( 0 ); } *pvRefsAnd = vRefsAnd; *pvRefsXor = vRefsXor; } void Dam_ManCreatePairs( Dam_Man_t * p, int fVerbose ) { Gia_Obj_t * pObj; Hash_IntMan_t * vHash; Vec_Int_t * vRefsAnd, * vRefsXor, * vSuper, * vDivs, * vRemap, * vLevRMax; int i, j, k, Num, FanK, FanJ, nRefs, iNode, iDiv, * pSet; int nPairsAll = 0, nPairsTried = 0, nPairsUsed = 0, nPairsXor = 0; int nDivsAll = 0, nDivsUsed = 0, nDivsXor = 0; Dam_ManCollectSets( p ); vSuper = p->pGia->vSuper; vDivs = Vec_IntAlloc( Gia_ManObjNum(p->pGia) ); vHash = Hash_IntManStart( Gia_ManObjNum(p->pGia)/2 ); vLevRMax = Vec_IntStart( 1000 ); Dam_ManCreateMultiRefs( p, &vRefsAnd, &vRefsXor ); Gia_ManForEachAnd( p->pGia, pObj, i ) { if ( !Dam_ObjHand(p, i) ) continue; pSet = Dam_ObjSet(p, i); nPairsAll += pSet[0] * (pSet[0] - 1) / 2; Vec_IntClear(vSuper); if ( Gia_ObjIsXor(pObj) ) { for ( k = 1; k <= pSet[0]; k++ ) if ( Vec_IntEntry(vRefsXor, Abc_Lit2Var(pSet[k])) > 1 ) Vec_IntPush( vSuper, pSet[k] ); } else if ( Gia_ObjIsAndReal(p->pGia, pObj) ) { for ( k = 1; k <= pSet[0]; k++ ) if ( Vec_IntEntry(vRefsAnd, pSet[k]) > 1 ) Vec_IntPush( vSuper, pSet[k] ); } else assert( 0 ); if ( Vec_IntSize(vSuper) < 2 ) continue; // enumerate pairs nPairsTried += Vec_IntSize(vSuper) * (Vec_IntSize(vSuper) - 1) / 2; Vec_IntPush( vDivs, -i ); // remember node Vec_IntForEachEntry( vSuper, FanK, k ) Vec_IntForEachEntryStart( vSuper, FanJ, j, k+1 ) { if ( (FanK > FanJ) ^ Gia_ObjIsXor(pObj) ) Num = Hash_Int2ManInsert( vHash, FanJ, FanK, 0 ); else Num = Hash_Int2ManInsert( vHash, FanK, FanJ, 0 ); if ( Hash_Int2ObjInc( vHash, Num ) == 1 ) { nDivsUsed++; nDivsXor += Gia_ObjIsXor(pObj); } Vec_IntPush( vDivs, Num ); // remember devisor // update reverse level if ( Num >= Vec_IntSize(vLevRMax) ) Vec_IntFillExtra( vLevRMax, 3 * Vec_IntSize(vLevRMax) / 2, 0 ); Vec_IntUpdateEntry( vLevRMax, Num, Vec_IntEntry(p->vNodLevR, i) ); } } Vec_IntFree( vRefsAnd ); Vec_IntFree( vRefsXor ); // Hash_IntManProfile( vHash ); // remove entries that appear only once p->vHash = Hash_IntManStart( 3 * nDivsUsed /2 ); p->vCounts = Vec_FltAlloc( 2 * nDivsUsed ); Vec_FltPush( p->vCounts, ABC_INFINITY ); p->vQue = Vec_QueAlloc( Vec_FltCap(p->vCounts) ); Vec_QueSetPriority( p->vQue, Vec_FltArrayP(p->vCounts) ); // mapping div to node p->vDiv2Nod = Vec_IntAlloc( 2 * nDivsUsed ); Vec_IntPush( p->vDiv2Nod, ABC_INFINITY ); p->vNodStore = Vec_IntAlloc( Gia_ManObjNum(p->pGia) ); Vec_IntPush( p->vNodStore, -1 ); nDivsAll = Hash_IntManEntryNum(vHash); vRemap = Vec_IntStartFull( nDivsAll+1 ); for ( i = 1; i <= nDivsAll; i++ ) { nRefs = Hash_IntObjData2(vHash, i); if ( nRefs < 2 ) continue; nPairsUsed += nRefs; if ( Hash_IntObjData0(vHash, i) > Hash_IntObjData1(vHash, i) ) nPairsXor += nRefs; Num = Hash_Int2ManInsert( p->vHash, Hash_IntObjData0(vHash, i), Hash_IntObjData1(vHash, i), 0 ); assert( Num == Hash_IntManEntryNum(p->vHash) ); assert( Num == Vec_FltSize(p->vCounts) ); Vec_FltPush( p->vCounts, nRefs + 0.005*Dam_ManDivSlack(p, Hash_IntObjData0(vHash, i), Hash_IntObjData1(vHash, i), Vec_IntEntry(vLevRMax, i)) ); Vec_QuePush( p->vQue, Num ); // remember divisors assert( Num == Vec_IntSize(p->vDiv2Nod) ); Vec_IntPush( p->vDiv2Nod, Vec_IntSize(p->vNodStore) ); Vec_IntPush( p->vNodStore, 0 ); Vec_IntFillExtra( p->vNodStore, Vec_IntSize(p->vNodStore) + nRefs, -1 ); // remember entry Vec_IntWriteEntry( vRemap, i, Num ); } assert( Vec_FltSize(p->vCounts) == Hash_IntManEntryNum(p->vHash)+1 ); assert( Vec_IntSize(p->vDiv2Nod) == nDivsUsed+1 ); Hash_IntManStop( vHash ); Vec_IntFree( vLevRMax ); // fill in the divisors iNode = -1; Vec_IntForEachEntry( vDivs, iDiv, i ) { if ( iDiv < 0 ) { iNode = -iDiv; continue; } Num = Vec_IntEntry( vRemap, iDiv ); if ( Num == -1 ) continue; pSet = Dam_DivSet( p, Num ); pSet[++pSet[0]] = iNode; } Vec_IntFree( vRemap ); Vec_IntFree( vDivs ); // create storage for reverse level of divisor during update p->vDivLevR = Vec_IntStart( 2 * nDivsUsed ); // make sure divisors are added correctly // for ( i = 1; i <= nDivsUsed; i++ ) // assert( Dam_DivSet(p, i)[0] == Vec_FltEntry(p->vCounts, i)+1 ); if ( !fVerbose ) return; // print stats printf( "Pairs:" ); printf( " Total =%9d (%6.2f %%)", nPairsAll, 100.0 * nPairsAll / Abc_MaxInt(nPairsAll, 1) ); printf( " Tried =%9d (%6.2f %%)", nPairsTried, 100.0 * nPairsTried / Abc_MaxInt(nPairsAll, 1) ); printf( " Used =%9d (%6.2f %%)", nPairsUsed, 100.0 * nPairsUsed / Abc_MaxInt(nPairsAll, 1) ); printf( " Xor =%9d (%6.2f %%)", nPairsXor, 100.0 * nPairsXor / Abc_MaxInt(nPairsAll, 1) ); printf( "\n" ); printf( "Div: " ); printf( " Total =%9d (%6.2f %%)", nDivsAll, 100.0 * nDivsAll / Abc_MaxInt(nDivsAll, 1) ); printf( " Tried =%9d (%6.2f %%)", nDivsAll, 100.0 * nDivsAll / Abc_MaxInt(nDivsAll, 1) ); printf( " Used =%9d (%6.2f %%)", nDivsUsed, 100.0 * nDivsUsed / Abc_MaxInt(nDivsAll, 1) ); printf( " Xor =%9d (%6.2f %%)", nDivsXor, 100.0 * nDivsXor / Abc_MaxInt(nDivsAll, 1) ); printf( "\n" ); } /**Function************************************************************* Synopsis [Derives new AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dam_ManMultiAig_rec( Dam_Man_t * pMan, Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { int i, * pSet; if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); pSet = Dam_ObjSet(pMan, Gia_ObjId(p, pObj)); if ( pSet == NULL ) { Dam_ManMultiAig_rec( pMan, pNew, p, Gia_ObjFanin0(pObj) ); Dam_ManMultiAig_rec( pMan, pNew, p, Gia_ObjFanin1(pObj) ); if ( Gia_ObjIsMux(p, pObj) ) { Dam_ManMultiAig_rec( pMan, pNew, p, Gia_ObjFanin2(p, pObj) ); pObj->Value = Gia_ManHashMuxReal( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); } else if ( Gia_ObjIsXor(pObj) ) pObj->Value = Gia_ManHashXorReal( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value)) ); return; } assert( Gia_ObjIsXor(pObj) || Gia_ObjIsAndReal(p, pObj) ); // call recursively for ( i = 1; i <= pSet[0]; i++ ) { Gia_Obj_t * pTemp = Gia_ManObj( p, Abc_Lit2Var(pSet[i]) ); Dam_ManMultiAig_rec( pMan, pNew, p, pTemp ); pSet[i] = Abc_LitNotCond( pTemp->Value, Abc_LitIsCompl(pSet[i]) ); } // create balanced gate pObj->Value = Gia_ManBalanceGate( pNew, pObj, p->vSuper, pSet + 1, pSet[0] ); } Gia_Man_t * Dam_ManMultiAig( Dam_Man_t * pMan ) { Gia_Man_t * p = pMan->pGia; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; // start the new manager pNew = Gia_ManStart( 2*Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); pNew->vLevels = Vec_IntStart( pNew->nObjsAlloc ); // create constant and inputs Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) { pObj->Value = Gia_ManAppendCi( pNew ); Vec_IntWriteEntry( pNew->vLevels, Abc_Lit2Var(pObj->Value), Gia_ObjLevel(p, pObj) ); } // create internal nodes Gia_ManHashStart( pNew ); Gia_ManForEachBuf( p, pObj, i ) { Dam_ManMultiAig_rec( pMan, pNew, p, Gia_ObjFanin0(pObj) ); pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value)) ); } Gia_ManForEachCo( p, pObj, i ) { Dam_ManMultiAig_rec( pMan, pNew, p, Gia_ObjFanin0(pObj) ); pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } // assert( Gia_ManObjNum(pNew) <= Gia_ManObjNum(p) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // perform cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Updates the data-structure after extracting one divisor.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Dam_PrintDiv( Dam_Man_t * p, int iDiv ) { if ( iDiv == 0 ) printf( "Final statistics after extracting %6d divisors: ", p->nDivs ); else { char Buffer[100]; int iData0 = Hash_IntObjData0(p->vHash, iDiv); int iData1 = Hash_IntObjData1(p->vHash, iDiv); printf( "Div%5d : ", p->nDivs+1 ); printf( "D%-8d = ", iDiv ); sprintf( Buffer, "%c%d", Abc_LitIsCompl(iData0)? '!':' ', Abc_Lit2Var(iData0) ); printf( "%8s ", Buffer ); printf( "%c ", (iData0 < iData1) ? '*' : '+' ); sprintf( Buffer, "%c%d", Abc_LitIsCompl(iData1)? '!':' ', Abc_Lit2Var(iData1) ); printf( "%8s ", Buffer ); printf( "Weight %9.2f ", Vec_FltEntry(p->vCounts, iDiv) ); } printf( "Divs =%8d ", Hash_IntManEntryNum(p->vHash) ); printf( "Ands =%8d ", p->nAnds - p->nGain ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); } void Dam_PrintQue( Dam_Man_t * p ) { int i; printf( "Divisor queue: \n" ); for ( i = 1; i <= Hash_IntManEntryNum(p->vHash); i++ ) { int iLit0 = Hash_IntObjData0(p->vHash, i); int iLit1 = Hash_IntObjData1(p->vHash, i); printf( "Div %7d : ", i ); printf( "Weight %9.2f ", Vec_FltEntry(p->vCounts, i) ); printf( "F = %c%c ", Abc_LitIsCompl(iLit0) ? '!': ' ', 'a' + Abc_Lit2Var(iLit0)-1 ); printf( "%c ", (Hash_IntObjData0(p->vHash, i) < Hash_IntObjData1(p->vHash, i)) ? '*':'+' ); printf( "%c%c ", Abc_LitIsCompl(iLit1) ? '!': ' ', 'a' + Abc_Lit2Var(iLit1)-1 ); printf( "\n" ); } } int Dam_ManUpdateNode( Dam_Man_t * p, int iObj, int iLit0, int iLit1, int iLitNew, Vec_Int_t * vDivs ) { int * pSet = Dam_ObjSet( p, iObj ); int i, k, c, Num, iLit, iLit2, fPres; // check if literal can be found for ( i = 1; i <= pSet[0]; i++ ) if ( pSet[i] == iLit0 ) break; if ( i > pSet[0] ) return 0; // check if literal can be found for ( i = 1; i <= pSet[0]; i++ ) if ( pSet[i] == iLit1 ) break; if ( i > pSet[0] ) return 0; // compact literals Vec_IntPush( vDivs, -iObj ); for ( k = i = 1; i <= pSet[0]; i++ ) { if ( iLit0 == pSet[i] || iLit1 == pSet[i] ) continue; pSet[k++] = iLit = pSet[i]; // reduce weights of the divisors fPres = 0; for ( c = 0; c < 2; c++ ) { iLit2 = c ? iLit1 : iLit0; if ( (iLit > iLit2) ^ (iLit0 > iLit1) ) Num = *Hash_Int2ManLookup( p->vHash, iLit2, iLit ); else Num = *Hash_Int2ManLookup( p->vHash, iLit, iLit2 ); if ( Num > 0 ) { Vec_FltAddToEntry( p->vCounts, Num, -1 ); if ( Vec_QueIsMember(p->vQue, Num) ) { Vec_QueUpdate( p->vQue, Num ); fPres |= (1 << c); } } } if ( fPres != 3 ) continue; if ( (iLit > iLitNew) ^ (iLit0 > iLit1) ) Num = Hash_Int2ManInsert( p->vHash, iLitNew, iLit, 0 ); else Num = Hash_Int2ManInsert( p->vHash, iLit, iLitNew, 0 ); Hash_Int2ObjInc( p->vHash, Num ); Vec_IntPush( vDivs, Num ); // update reverse level if ( Num >= Vec_IntSize(p->vDivLevR) ) Vec_IntFillExtra( p->vDivLevR, 3 * Vec_IntSize(p->vDivLevR) / 2, 0 ); Vec_IntUpdateEntry( p->vDivLevR, Num, Vec_IntEntry(p->vNodLevR, iObj) ); } pSet[k] = iLitNew; pSet[0] = k; return 1; } void Dam_ManUpdate( Dam_Man_t * p, int iDiv ) { Vec_Int_t * vDivs = p->pGia->vSuper; int iLit0 = Hash_IntObjData0(p->vHash, iDiv); int iLit1 = Hash_IntObjData1(p->vHash, iDiv); int i, iLitNew, * pSet, * pNods = Dam_DivSet( p, iDiv ); int nPresent = 0, nPairsStart, nPairsStop, pPairsNew, nRefs; int fThisIsXor = (iLit0 > iLit1), iDivTemp, iNode; // Dam_PrintQue( p ); if ( fThisIsXor ) iLitNew = Gia_ManAppendXorReal( p->pGia, iLit0, iLit1 ); else iLitNew = Gia_ManAppendAnd( p->pGia, iLit0, iLit1 ); Gia_ObjSetGateLevel( p->pGia, Gia_ManObj(p->pGia, Abc_Lit2Var(iLitNew)) ); // printf( "%d ", Gia_ObjLevel(p->pGia, Gia_ManObj(p->pGia, Abc_Lit2Var(iLitNew))) ); // replace entries assert( pNods[0] >= 2 ); nPairsStart = Hash_IntManEntryNum(p->vHash) + 1; Vec_IntClear( vDivs ); for ( i = 1; i <= pNods[0]; i++ ) nPresent += Dam_ManUpdateNode( p, pNods[i], iLit0, iLit1, iLitNew, vDivs ); nPairsStop = Hash_IntManEntryNum(p->vHash) + 1; // extend arrayvs pPairsNew = 0; Vec_FltFillExtra( p->vCounts, nPairsStop, 0 ); Vec_IntFillExtra( p->vDiv2Nod, nPairsStop, -1 ); for ( i = nPairsStart; i < nPairsStop; i++ ) { nRefs = Hash_IntObjData2(p->vHash, i); if ( nRefs < 2 ) continue; Vec_FltWriteEntry( p->vCounts, i, nRefs + 0.001*Dam_ManDivSlack(p, Hash_IntObjData0(p->vHash, i), Hash_IntObjData1(p->vHash, i), Vec_IntEntry(p->vDivLevR, i)) ); Vec_QuePush( p->vQue, i ); // remember divisors Vec_IntWriteEntry( p->vDiv2Nod, i, Vec_IntSize(p->vNodStore) ); Vec_IntPush( p->vNodStore, 0 ); Vec_IntFillExtra( p->vNodStore, Vec_IntSize(p->vNodStore) + nRefs, -1 ); pPairsNew++; } // printf( "Added %d new pairs\n", pPairsNew ); // fill in the divisors iNode = -1; Vec_IntForEachEntry( vDivs, iDivTemp, i ) { if ( iDivTemp < 0 ) { iNode = -iDivTemp; continue; } if ( Vec_IntEntry(p->vDiv2Nod, iDivTemp) == -1 ) continue; pSet = Dam_DivSet( p, iDivTemp ); pSet[++pSet[0]] = iNode; } // make sure divisors are added correctly for ( i = nPairsStart; i < nPairsStop; i++ ) if ( Vec_IntEntry(p->vDiv2Nod, i) > 0 ) assert( Dam_DivSet(p, i)[0] == Hash_IntObjData2(p->vHash, i) ); // update costs Vec_FltWriteEntry( p->vCounts, iDiv, 0 ); p->nGain += (1 + 2 * fThisIsXor) * (nPresent - 1); p->nGainX += 3 * fThisIsXor * (nPresent - 1); p->nDivs++; } /**Function************************************************************* Synopsis [Perform extraction for multi-input AND/XOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Dam_ManAreaBalanceInt( Gia_Man_t * pGia, Vec_Int_t * vCiLevels, int nNewNodesMax, int fVerbose, int fVeryVerbose ) { Gia_Man_t * pNew; Dam_Man_t * p; int i, iDiv; p = Dam_ManAlloc( pGia ); p->nLevelMax = Gia_ManSetLevels( p->pGia, vCiLevels ); p->vNodLevR = Gia_ManReverseLevel( p->pGia ); Vec_IntFillExtra( p->pGia->vLevels, 3*Gia_ManObjNum(p->pGia)/2, 0 ); Dam_ManCreatePairs( p, fVerbose ); for ( i = 0; i < nNewNodesMax && Vec_QueTopPriority(p->vQue) >= 2; i++ ) { iDiv = Vec_QuePop(p->vQue); if ( fVeryVerbose ) Dam_PrintDiv( p, iDiv ); Dam_ManUpdate( p, iDiv ); } if ( fVeryVerbose ) Dam_PrintDiv( p, 0 ); pNew = Dam_ManMultiAig( p ); if ( fVerbose ) { int nDivsAll = Hash_IntManEntryNum(p->vHash); int nDivsUsed = p->nDivs; printf( "Div: " ); printf( " Total =%9d (%6.2f %%) ", nDivsAll, 100.0 * nDivsAll / Abc_MaxInt(nDivsAll, 1) ); printf( " Used =%9d (%6.2f %%)", nDivsUsed, 100.0 * nDivsUsed / Abc_MaxInt(nDivsAll, 1) ); printf( " Gain =%6d (%6.2f %%)", p->nGain, 100.0 * p->nGain / Abc_MaxInt(p->nAnds, 1) ); printf( " GainX = %d ", p->nGainX ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); } Dam_ManFree( p ); return pNew; } Gia_Man_t * Gia_ManAreaBalance( Gia_Man_t * p, int fSimpleAnd, int nNewNodesMax, int fVerbose, int fVeryVerbose ) { Gia_Man_t * pNew0, * pNew, * pNew1, * pNew2; Vec_Int_t * vCiLevels; // set arrival times for the input of the new AIG if ( p->vCiArrs ) { int i, Id, And2Delay = p->And2Delay ? p->And2Delay : 1; Vec_IntFreeP( &p->vLevels ); p->vLevels = Vec_IntStart( Gia_ManObjNum(p) ); 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 ); vCiLevels = Gia_ManGetCiLevels( p ); // get the starting manager pNew0 = Gia_ManHasMapping(p) ? (Gia_Man_t *)Dsm_ManDeriveGia(p, 0) : Gia_ManDup(p); Gia_ManTransferTiming( pNew0, p ); if ( fVerbose ) Gia_ManPrintStats( pNew0, NULL ); // derive internal manager pNew = fSimpleAnd ? Gia_ManDup( pNew0 ) : Gia_ManDupMuxes( pNew0, 2 ); Gia_ManTransferTiming( pNew, pNew0 ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); if ( pNew0 != p ) Gia_ManStop( pNew0 ); // perform the operation pNew1 = Dam_ManAreaBalanceInt( pNew, vCiLevels, nNewNodesMax, fVerbose, fVeryVerbose ); Gia_ManTransferTiming( pNew1, pNew ); if ( fVerbose ) Gia_ManPrintStats( pNew1, NULL ); Gia_ManStop( pNew ); Vec_IntFreeP( &vCiLevels ); // derive the final result pNew2 = Gia_ManDupNoMuxes( pNew1, 0 ); Gia_ManTransferTiming( pNew2, pNew1 ); if ( fVerbose ) Gia_ManPrintStats( pNew2, NULL ); Gia_ManStop( pNew1 ); // normalize if needed if ( !Gia_ManIsNormalized(pNew2) ) { pNew2 = Gia_ManDupNormalize( pNew1 = pNew2, 0 ); Gia_ManTransferTiming( pNew2, pNew1 ); Gia_ManStop( pNew1 ); } //Gia_ManTransferTiming( pNew2, p ); return pNew2; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaBalLut.c000066400000000000000000001012401477524141600162750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaBalance.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [AIG balancing.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaBalance.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/vec/vecHash.h" #include "misc/vec/vecQue.h" #include "opt/dau/dau.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define BAL_LEAF_MAX 6 #define BAL_CUT_MAX 8 #define BAL_SUPER 50 #define BAL_NO_LEAF 31 #define BAL_NO_FUNC 134217727 // (1<<27)-1 typedef struct Bal_Cut_t_ Bal_Cut_t; struct Bal_Cut_t_ { word Sign; // signature int Delay; // delay unsigned iFunc : 27; // function (BAL_NO_FUNC) unsigned nLeaves : 5; // leaf number (Bal_NO_LEAF) int pLeaves[BAL_LEAF_MAX]; // leaves }; // operation manager typedef struct Bal_Man_t_ Bal_Man_t; struct Bal_Man_t_ { Gia_Man_t * pGia; // user AIG int nLutSize; // LUT size int nCutNum; // cut number int fCutMin; // cut minimization int fVerbose; // verbose Gia_Man_t * pNew; // derived AIG Vec_Int_t * vCosts; // cost of supergate nodes Vec_Ptr_t * vCutSets; // object cutsets abctime clkStart; // starting the clock }; static inline Bal_Man_t * Bal_GiaMan( Gia_Man_t * p ) { return (Bal_Man_t *)p->pData; } static inline int Bal_ObjCost( Bal_Man_t * p, int i ) { return Vec_IntEntry(p->vCosts, i); } static inline int Bal_LitCost( Bal_Man_t * p, int i ) { return Bal_ObjCost(p, Abc_Lit2Var(i)); } static inline int Bal_ObjDelay( Bal_Man_t * p, int i ) { return Bal_ObjCost(p, i) >> 4; } static inline int Bal_LitDelay( Bal_Man_t * p, int i ) { return Bal_ObjDelay(p, Abc_Lit2Var(i)); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bal_Man_t * Bal_ManAlloc( Gia_Man_t * pGia, Gia_Man_t * pNew, int nLutSize, int nCutNum, int fVerbose ) { Bal_Man_t * p; p = ABC_CALLOC( Bal_Man_t, 1 ); p->clkStart = Abc_Clock(); p->pGia = pGia; p->pNew = pNew; p->nLutSize = nLutSize; p->nCutNum = nCutNum; p->fVerbose = fVerbose; p->vCosts = Vec_IntAlloc( 3 * Gia_ManObjNum(pGia) / 2 ); p->vCutSets = Vec_PtrAlloc( 3 * Gia_ManObjNum(pGia) / 2 ); Vec_IntFill( p->vCosts, Gia_ManObjNum(pNew), 0 ); Vec_PtrFill( p->vCutSets, Gia_ManObjNum(pNew), NULL ); pNew->pData = p; return p; } void Bal_ManFree( Bal_Man_t * p ) { Vec_PtrFreeFree( p->vCutSets ); Vec_IntFree( p->vCosts ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Bal_CutCountBits( word i ) { i = i - ((i >> 1) & 0x5555555555555555); i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); return (i*(0x0101010101010101))>>56; } static inline word Bal_CutGetSign( int * pLeaves, int nLeaves ) { word Sign = 0; int i; for ( i = 0; i < nLeaves; i++ ) Sign |= ((word)1) << (pLeaves[i] & 0x3F); return Sign; } static inline int Bal_CutCreateUnit( Bal_Cut_t * p, int i, int Delay ) { p->iFunc = 2; p->Delay = Delay; p->nLeaves = 1; p->pLeaves[0] = i; p->Sign = ((word)1) << (i & 0x3F); return 1; } static inline int Bal_ManPrepareSet( Bal_Man_t * p, int iObj, int Index, int fUnit, Bal_Cut_t ** ppCutSet ) { static Bal_Cut_t CutTemp[3]; int i; if ( Vec_PtrEntry(p->vCutSets, iObj) == NULL || fUnit ) return Bal_CutCreateUnit( (*ppCutSet = CutTemp + Index), iObj, Bal_ObjDelay(p, iObj)+1 ); *ppCutSet = (Bal_Cut_t *)Vec_PtrEntry(p->vCutSets, iObj); for ( i = 0; i < p->nCutNum; i++ ) if ( (*ppCutSet)[i].nLeaves == BAL_NO_LEAF ) return i; return i; } /**Function************************************************************* Synopsis [Check correctness of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Bal_CutCheck( Bal_Cut_t * pBase, Bal_Cut_t * pCut ) // check if pCut is contained in pBase { int nSizeB = pBase->nLeaves; int nSizeC = pCut->nLeaves; int i, * pB = pBase->pLeaves; int k, * pC = pCut->pLeaves; for ( i = 0; i < nSizeC; i++ ) { for ( k = 0; k < nSizeB; k++ ) if ( pC[i] == pB[k] ) break; if ( k == nSizeB ) return 0; } return 1; } static inline int Bal_SetCheckArray( Bal_Cut_t ** ppCuts, int nCuts ) { Bal_Cut_t * pCut0, * pCut1; int i, k, m, n, Value; assert( nCuts > 0 ); for ( i = 0; i < nCuts; i++ ) { pCut0 = ppCuts[i]; assert( pCut0->nLeaves <= BAL_LEAF_MAX ); assert( pCut0->Sign == Bal_CutGetSign(pCut0->pLeaves, pCut0->nLeaves) ); // check duplicates for ( m = 0; m < (int)pCut0->nLeaves; m++ ) for ( n = m + 1; n < (int)pCut0->nLeaves; n++ ) assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] ); // check pairs for ( k = 0; k < nCuts; k++ ) { pCut1 = ppCuts[k]; if ( pCut0 == pCut1 ) continue; // check containments Value = Bal_CutCheck( pCut0, pCut1 ); assert( Value == 0 ); } } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Bal_CutMergeOrder( Bal_Cut_t * pCut0, Bal_Cut_t * pCut1, Bal_Cut_t * pCut, int nLutSize ) { int nSize0 = pCut0->nLeaves; int nSize1 = pCut1->nLeaves; int i, * pC0 = pCut0->pLeaves; int k, * pC1 = pCut1->pLeaves; int c, * pC = pCut->pLeaves; // the case of the largest cut sizes if ( nSize0 == nLutSize && nSize1 == nLutSize ) { for ( i = 0; i < nSize0; i++ ) { if ( pC0[i] != pC1[i] ) return 0; pC[i] = pC0[i]; } pCut->nLeaves = nLutSize; pCut->iFunc = BAL_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign; pCut->Delay = Abc_MaxInt( pCut0->Delay, pCut1->Delay ); return 1; } // compare two cuts with different numbers i = k = c = 0; while ( 1 ) { if ( c == nLutSize ) return 0; if ( pC0[i] < pC1[k] ) { pC[c++] = pC0[i++]; if ( i >= nSize0 ) goto FlushCut1; } else if ( pC0[i] > pC1[k] ) { pC[c++] = pC1[k++]; if ( k >= nSize1 ) goto FlushCut0; } else { pC[c++] = pC0[i++]; k++; if ( i >= nSize0 ) goto FlushCut1; if ( k >= nSize1 ) goto FlushCut0; } } FlushCut0: if ( c + nSize0 > nLutSize + i ) return 0; while ( i < nSize0 ) pC[c++] = pC0[i++]; pCut->nLeaves = c; pCut->iFunc = BAL_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign; pCut->Delay = Abc_MaxInt( pCut0->Delay, pCut1->Delay ); return 1; FlushCut1: if ( c + nSize1 > nLutSize + k ) return 0; while ( k < nSize1 ) pC[c++] = pC1[k++]; pCut->nLeaves = c; pCut->iFunc = BAL_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign; pCut->Delay = Abc_MaxInt( pCut0->Delay, pCut1->Delay ); return 1; } static inline int Bal_CutMergeOrderMux( Bal_Cut_t * pCut0, Bal_Cut_t * pCut1, Bal_Cut_t * pCut2, Bal_Cut_t * pCut, int nLutSize ) { int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; int x2, i2 = 0, nSize2 = pCut2->nLeaves, * pC2 = pCut2->pLeaves; int xMin, c = 0, * pC = pCut->pLeaves; while ( 1 ) { x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; x2 = (i2 == nSize2) ? ABC_INFINITY : pC2[i2]; xMin = Abc_MinInt( Abc_MinInt(x0, x1), x2 ); if ( xMin == ABC_INFINITY ) break; if ( c == nLutSize ) return 0; pC[c++] = xMin; if (x0 == xMin) i0++; if (x1 == xMin) i1++; if (x2 == xMin) i2++; } pCut->nLeaves = c; pCut->iFunc = BAL_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign | pCut2->Sign; pCut->Delay = Abc_MaxInt( pCut0->Delay, Abc_MaxInt(pCut1->Delay, pCut2->Delay) ); return 1; } static inline int Bal_SetCutIsContainedOrder( Bal_Cut_t * pBase, Bal_Cut_t * pCut ) // check if pCut is contained in pBase { int i, nSizeB = pBase->nLeaves; int k, nSizeC = pCut->nLeaves; if ( nSizeB == nSizeC ) { for ( i = 0; i < nSizeB; i++ ) if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) return 0; return 1; } assert( nSizeB > nSizeC ); if ( nSizeC == 0 ) return 1; for ( i = k = 0; i < nSizeB; i++ ) { if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) return 0; if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) { if ( ++k == nSizeC ) return 1; } } return 0; } static inline int Bal_SetLastCutIsContained( Bal_Cut_t ** pCuts, int nCuts ) { int i; for ( i = 0; i < nCuts; i++ ) if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Bal_SetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) ) return 1; return 0; } static inline int Bal_SetLastCutContains( Bal_Cut_t ** pCuts, int nCuts ) { int i, k, fChanges = 0; for ( i = 0; i < nCuts; i++ ) if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Bal_SetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) ) pCuts[i]->nLeaves = BAL_NO_LEAF, fChanges = 1; if ( !fChanges ) return nCuts; for ( i = k = 0; i <= nCuts; i++ ) { if ( pCuts[i]->nLeaves == BAL_NO_LEAF ) continue; if ( k < i ) ABC_SWAP( Bal_Cut_t *, pCuts[k], pCuts[i] ); k++; } return k - 1; } static inline int Bal_CutCompareArea( Bal_Cut_t * pCut0, Bal_Cut_t * pCut1 ) { if ( pCut0->Delay < pCut1->Delay ) return -1; if ( pCut0->Delay > pCut1->Delay ) return 1; if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; return 0; } static inline void Bal_SetSortByDelay( Bal_Cut_t ** pCuts, int nCuts ) { int i; for ( i = nCuts; i > 0; i-- ) { if ( Bal_CutCompareArea(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 ) return; ABC_SWAP( Bal_Cut_t *, pCuts[i - 1], pCuts[i] ); } } static inline int Bal_SetAddCut( Bal_Cut_t ** pCuts, int nCuts, int nCutNum ) { if ( nCuts == 0 ) return 1; nCuts = Bal_SetLastCutContains(pCuts, nCuts); Bal_SetSortByDelay( pCuts, nCuts ); return Abc_MinInt( nCuts + 1, nCutNum - 1 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bal_ManDeriveCuts( Bal_Man_t * p, int iFan0, int iFan1, int iFan2, int fCompl0, int fCompl1, int fCompl2, int fUnit0, int fUnit1, int fUnit2, int fIsXor, int Target, int fSave ) { Bal_Cut_t pCutSet[BAL_CUT_MAX], * pCutsR[BAL_CUT_MAX]; Bal_Cut_t * pCutSet0, * pCutSet1, * pCutSet2; int nCuts0 = Bal_ManPrepareSet( p, iFan0, 0, fUnit0, &pCutSet0 ); int nCuts1 = Bal_ManPrepareSet( p, iFan1, 1, fUnit1, &pCutSet1 ); Bal_Cut_t * pCut0, * pCut0Lim = pCutSet0 + nCuts0; Bal_Cut_t * pCut1, * pCut1Lim = pCutSet1 + nCuts1; int i, Cost, nCutsR = 0; memset( pCutSet, 0, sizeof(Bal_Cut_t) * p->nCutNum ); for ( i = 0; i < p->nCutNum; i++ ) pCutsR[i] = pCutSet + i; // enumerate cuts if ( iFan2 > 0 ) { int nCuts2 = Bal_ManPrepareSet( p, iFan2, 2, fUnit2, &pCutSet2 ); Bal_Cut_t * pCut2, * pCut2Lim = pCutSet2 + nCuts2; for ( pCut0 = pCutSet0; pCut0 < pCut0Lim; pCut0++ ) for ( pCut1 = pCutSet1; pCut1 < pCut1Lim; pCut1++ ) for ( pCut2 = pCutSet2; pCut2 < pCut2Lim; pCut2++ ) { if ( Bal_CutCountBits(pCut0->Sign | pCut1->Sign | pCut2->Sign) > p->nLutSize ) continue; if ( !Bal_CutMergeOrderMux(pCut0, pCut1, pCut2, pCutsR[nCutsR], p->nLutSize) ) continue; assert( pCutsR[nCutsR]->Delay == Target ); if ( Bal_SetLastCutIsContained(pCutsR, nCutsR) ) continue; // if ( p->fCutMin && Bal_CutComputeTruthMux(p, pCut0, pCut1, pCut2, fCompl0, fCompl1, fCompl2, pCutsR[nCutsR]) ) // pCutsR[nCutsR]->Sign = Bal_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); nCutsR = Bal_SetAddCut( pCutsR, nCutsR, p->nCutNum ); } } else { for ( pCut0 = pCutSet0; pCut0 < pCut0Lim; pCut0++ ) for ( pCut1 = pCutSet1; pCut1 < pCut1Lim; pCut1++ ) { if ( Bal_CutCountBits(pCut0->Sign | pCut1->Sign) > p->nLutSize ) continue; if ( !Bal_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], p->nLutSize) ) continue; assert( pCutsR[nCutsR]->Delay == Target ); if ( Bal_SetLastCutIsContained(pCutsR, nCutsR) ) continue; // if ( p->fCutMin && Bal_CutComputeTruth(p, pCut0, pCut1, fCompl0, fCompl1, pCutsR[nCutsR], fIsXor) ) // pCutsR[nCutsR]->Sign = Bal_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); nCutsR = Bal_SetAddCut( pCutsR, nCutsR, p->nCutNum ); } } if ( nCutsR == 0 ) return -1; //printf( "%d ", nCutsR ); Cost = ((pCutsR[0]->Delay << 4) | pCutsR[0]->nLeaves); // verify assert( nCutsR > 0 && nCutsR < p->nCutNum ); assert( Bal_SetCheckArray(pCutsR, nCutsR) ); // save cuts if ( fSave && Cost >= 0 ) { pCutSet0 = ABC_CALLOC( Bal_Cut_t, p->nCutNum ); Vec_PtrPush( p->vCutSets, pCutSet0 ); assert( Vec_PtrSize(p->vCutSets) == Gia_ManObjNum(p->pNew) ); for ( i = 0; i < nCutsR; i++ ) pCutSet0[i] = *pCutsR[i]; for ( ; i < p->nCutNum; i++ ) pCutSet0[i].nLeaves = BAL_NO_LEAF; Vec_IntPush( p->vCosts, Cost ); assert( Vec_IntSize(p->vCosts) == Gia_ManObjNum(p->pNew) ); } return Cost; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bal_ManSetGateLevel( Bal_Man_t * p, Gia_Obj_t * pObjOld, int iLitNew ) { int iFan0, iFan1, iFan2, Cost; int fCompl0, fCompl1, fCompl2; int fUnit0, fUnit1, fUnit2; int Delay0, Delay1, Delay2, DelayMax; int iObjNew = Abc_Lit2Var(iLitNew); Gia_Obj_t * pObjNew = Gia_ManObj( p->pNew, iObjNew ); int fMux = Gia_ObjIsMux(p->pNew, pObjNew); if ( iObjNew < Vec_PtrSize(p->vCutSets) ) return -1; iFan0 = Gia_ObjFaninId0( pObjNew, iObjNew ); iFan1 = Gia_ObjFaninId1( pObjNew, iObjNew ); iFan2 = fMux ? Gia_ObjFaninId2(p->pNew, iObjNew) : 0; fCompl0 = Gia_ObjFaninC0( pObjNew ); fCompl1 = Gia_ObjFaninC1( pObjNew ); fCompl2 = fMux ? Gia_ObjFaninC2(p->pNew, pObjNew) : 0; Delay0 = Bal_ObjDelay( p, iFan0 ); Delay1 = Bal_ObjDelay( p, iFan1 ); Delay2 = Bal_ObjDelay( p, iFan2 ); DelayMax = Abc_MaxInt( Delay0, Abc_MaxInt(Delay1, Delay2) ); fUnit0 = (int)(Delay0 != DelayMax); fUnit1 = (int)(Delay1 != DelayMax); fUnit2 = (int)(Delay2 != DelayMax); if ( DelayMax > 0 ) { //printf( "A" ); Cost = Bal_ManDeriveCuts(p, iFan0, iFan1, iFan2, fCompl0, fCompl1, fCompl2, fUnit0, fUnit1, fUnit2, Gia_ObjIsXor(pObjNew), DelayMax, 1 ); //printf( "B" ); if ( Cost >= 0 ) return Cost; } DelayMax++; fUnit0 = fUnit1 = fUnit2 = 1; //printf( "A" ); Cost = Bal_ManDeriveCuts(p, iFan0, iFan1, iFan2, fCompl0, fCompl1, fCompl2, fUnit0, fUnit1, fUnit2, Gia_ObjIsXor(pObjNew), DelayMax, 1 ); //printf( "B" ); assert( Cost >= 0 ); return Cost; } int Bal_ManEvalTwo( Bal_Man_t * p, int iLitNew0, int iLitNew1, int iLitNew2, int fIsXor ) { int iFan0 = Abc_Lit2Var( iLitNew0 ); int iFan1 = Abc_Lit2Var( iLitNew1 ); int iFan2 = Abc_Lit2Var( iLitNew2 ); int fCompl0 = Abc_LitIsCompl( iLitNew0 ); int fCompl1 = Abc_LitIsCompl( iLitNew1 ); int fCompl2 = Abc_LitIsCompl( iLitNew2 ); int Delay0 = Bal_ObjDelay( p, iFan0 ); int Delay1 = Bal_ObjDelay( p, iFan1 ); int Delay2 = Bal_ObjDelay( p, iFan2 ); int DelayMax = Abc_MaxInt( Delay0, Abc_MaxInt(Delay1, Delay2) ); int fUnit0 = (int)(Delay0 != DelayMax); int fUnit1 = (int)(Delay1 != DelayMax); int fUnit2 = (int)(Delay2 != DelayMax); if ( DelayMax == 0 ) return -1; return Bal_ManDeriveCuts(p, iFan0, iFan1, iFan2, fCompl0, fCompl1, fCompl2, fUnit0, fUnit1, fUnit2, fIsXor, DelayMax, 0 ); } /**Function************************************************************* Synopsis [Sort literals by their cost.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntSelectSortCostLit( Vec_Int_t * vSuper, Vec_Int_t * vCosts ) { int * pArray = Vec_IntArray(vSuper); int nSize = Vec_IntSize(vSuper); int i, j, best_i; for ( i = 0; i < nSize-1; i++ ) { best_i = i; for ( j = i+1; j < nSize; j++ ) if ( Vec_IntEntry(vCosts, Abc_Lit2Var(pArray[j])) > Vec_IntEntry(vCosts, Abc_Lit2Var(pArray[best_i])) ) best_i = j; ABC_SWAP( int, pArray[i], pArray[best_i] ); } } static inline void Vec_IntPushOrderCost2( Vec_Int_t * vSuper, Vec_Int_t * vCosts, int iLit ) { int i, nSize, * pArray; Vec_IntPush( vSuper, iLit ); pArray = Vec_IntArray(vSuper); nSize = Vec_IntSize(vSuper); for ( i = nSize-1; i > 0; i-- ) { if ( Vec_IntEntry(vCosts, Abc_Lit2Var(pArray[i])) <= Vec_IntEntry(vCosts, Abc_Lit2Var(pArray[i - 1])) ) return; ABC_SWAP( int, pArray[i], pArray[i - 1] ); } } static inline int Vec_IntFindFirstSameDelayAsLast( Bal_Man_t * p, Vec_Int_t * vSuper ) { int i, DelayCur, Delay = Bal_LitDelay( p, Vec_IntEntryLast(vSuper) ); assert( Vec_IntSize(vSuper) > 1 ); for ( i = Vec_IntSize(vSuper)-1; i > 0; i-- ) { DelayCur = Bal_LitDelay( p, Vec_IntEntry(vSuper, i-1) ); assert( DelayCur >= Delay ); if ( DelayCur > Delay ) return i; } return i; } /**Function************************************************************* Synopsis [Select the best pair to merge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Bal_ManFindBestPair( Bal_Man_t * p, Vec_Int_t * vSuper, Gia_Obj_t * pObj ) { int * pSuper = Vec_IntArray(vSuper); int iBeg = Vec_IntFindFirstSameDelayAsLast( p, vSuper ); int iEnd = Vec_IntSize(vSuper)-1; int i, k, iBest = -1, kBest = -1, BestCost = ABC_INFINITY, Cost; assert( iBeg <= iEnd ); // check if we can add to the higher levels without increasing cost for ( k = iBeg-1; k >= 0; k-- ) for ( i = iEnd; i >= iBeg; i-- ) { Cost = Bal_ManEvalTwo( p, pSuper[i], pSuper[k], 0, Gia_ObjIsXor(pObj) ); if ( Cost == -1 ) continue; if ( Cost == Bal_LitCost(p, pSuper[k]) ) { // printf( "A" ); return (k << 16)|i; } if ( BestCost > Cost ) BestCost = Cost, iBest = i, kBest = k; } if ( BestCost != ABC_INFINITY && (BestCost >> 4) == Bal_LitDelay(p, pSuper[kBest]) ) { // printf( "B" ); return (kBest << 16)|iBest; } // check if some can be added to lowest level without increasing cost BestCost = ABC_INFINITY; for ( i = iBeg; i <= iEnd; i++ ) for ( k = i+1; k <= iEnd; k++ ) { Cost = Bal_ManEvalTwo( p, pSuper[i], pSuper[k], 0, Gia_ObjIsXor(pObj) ); if ( Cost == -1 ) continue; if ( Cost == Abc_MaxInt(Bal_LitCost(p, pSuper[i]), Bal_LitCost(p, pSuper[k])) ) { // printf( "C" ); return (k << 16)|i; } if ( BestCost > Cost ) BestCost = Cost, iBest = i, kBest = k; } if ( BestCost != ABC_INFINITY ) { // printf( "D" ); return (kBest << 16)|iBest; } // printf( "E" ); // group pairs from lowest level based on proximity return (iEnd << 16)|(iEnd-1); } /**Function************************************************************* Synopsis [Simplify multi-input AND/XOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSimplifyXor( Vec_Int_t * vSuper ) { int i, k = 0, Prev = -1, This, fCompl = 0; Vec_IntForEachEntry( vSuper, This, i ) { if ( This == 0 ) continue; if ( This == 1 ) fCompl ^= 1; else if ( Prev != This ) Vec_IntWriteEntry( vSuper, k++, This ), Prev = This; else Prev = -1, k--; } Vec_IntShrink( vSuper, k ); if ( Vec_IntSize( vSuper ) == 0 ) Vec_IntPush( vSuper, fCompl ); else if ( fCompl ) Vec_IntWriteEntry( vSuper, 0, Abc_LitNot(Vec_IntEntry(vSuper, 0)) ); } static inline void Gia_ManSimplifyAnd( Vec_Int_t * vSuper ) { int i, k = 0, Prev = -1, This; Vec_IntForEachEntry( vSuper, This, i ) { if ( This == 0 ) { Vec_IntFill(vSuper, 1, 0); return; } if ( This == 1 ) continue; if ( Prev == -1 || Abc_Lit2Var(Prev) != Abc_Lit2Var(This) ) Vec_IntWriteEntry( vSuper, k++, This ), Prev = This; else if ( Prev != This ) { Vec_IntFill(vSuper, 1, 0); return; } } Vec_IntShrink( vSuper, k ); if ( Vec_IntSize( vSuper ) == 0 ) Vec_IntPush( vSuper, 1 ); } /**Function************************************************************* Synopsis [Collect multi-input AND/XOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSuperCollectXor_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( !Gia_IsComplement(pObj) ); if ( !Gia_ObjIsXor(pObj) || // Gia_ObjRefNum(p, pObj) > 1 || Gia_ObjRefNum(p, pObj) > 3 || // (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || Vec_IntSize(p->vSuper) > BAL_SUPER ) { Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) ); return; } assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ); Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj) ); Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj) ); } static inline void Gia_ManSuperCollectAnd_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_IsComplement(pObj) || !Gia_ObjIsAndReal(p, pObj) || // Gia_ObjRefNum(p, pObj) > 1 || Gia_ObjRefNum(p, pObj) > 3 || // (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || Vec_IntSize(p->vSuper) > BAL_SUPER ) { Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) ); return; } Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj) ); Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj) ); } static inline void Gia_ManSuperCollect( Gia_Man_t * p, Gia_Obj_t * pObj ) { // int nSize; if ( p->vSuper == NULL ) p->vSuper = Vec_IntAlloc( 1000 ); else Vec_IntClear( p->vSuper ); if ( Gia_ObjIsXor(pObj) ) { assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ); Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj) ); Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj) ); // nSize = Vec_IntSize(vSuper); Vec_IntSort( p->vSuper, 0 ); Gia_ManSimplifyXor( p->vSuper ); // if ( nSize != Vec_IntSize(vSuper) ) // printf( "X %d->%d ", nSize, Vec_IntSize(vSuper) ); } else if ( Gia_ObjIsAndReal(p, pObj) ) { Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj) ); Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj) ); // nSize = Vec_IntSize(vSuper); Vec_IntSort( p->vSuper, 0 ); Gia_ManSimplifyAnd( p->vSuper ); // if ( nSize != Vec_IntSize(vSuper) ) // printf( "A %d->%d ", nSize, Vec_IntSize(vSuper) ); } else assert( 0 ); // if ( nSize > 10 ) // printf( "%d ", nSize ); assert( Vec_IntSize(p->vSuper) > 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManCreateGate( Gia_Man_t * pNew, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) { int iLit0 = Vec_IntPop(vSuper); int iLit1 = Vec_IntPop(vSuper); int iLit, i; if ( !Gia_ObjIsXor(pObj) ) iLit = Gia_ManHashAnd( pNew, iLit0, iLit1 ); else if ( pNew->pMuxes ) iLit = Gia_ManHashXorReal( pNew, iLit0, iLit1 ); else iLit = Gia_ManHashXor( pNew, iLit0, iLit1 ); Vec_IntPush( vSuper, iLit ); Bal_ManSetGateLevel( Bal_GiaMan(pNew), pObj, iLit ); // Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(iLit)) ); // shift to the corrent location for ( i = Vec_IntSize(vSuper)-1; i > 0; i-- ) { int iLit1 = Vec_IntEntry(vSuper, i); int iLit2 = Vec_IntEntry(vSuper, i-1); if ( Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit1)) <= Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit2)) ) break; Vec_IntWriteEntry( vSuper, i, iLit2 ); Vec_IntWriteEntry( vSuper, i-1, iLit1 ); } } static inline int Gia_ManBalanceGate( Gia_Man_t * pNew, Gia_Obj_t * pObj, Vec_Int_t * vSuper, int * pLits, int nLits ) { Vec_IntClear( vSuper ); if ( nLits == 1 ) Vec_IntPush( vSuper, pLits[0] ); else if ( nLits == 2 ) { Vec_IntPush( vSuper, pLits[0] ); Vec_IntPush( vSuper, pLits[1] ); Gia_ManCreateGate( pNew, pObj, vSuper ); } else if ( nLits > 2 ) { Bal_Man_t * p = Bal_GiaMan(pNew); int i; for ( i = 0; i < nLits; i++ ) Vec_IntPush( vSuper, pLits[i] ); // sort by level/cut-size Vec_IntSelectSortCostLit( vSuper, p->vCosts ); // iterate till everything is grouped while ( Vec_IntSize(vSuper) > 1 ) { int iLit, Res = Bal_ManFindBestPair( p, vSuper, pObj ); int iBest = Vec_IntEntry( vSuper, Res >> 16 ); int kBest = Vec_IntEntry( vSuper, Res & 0xFFFF ); Vec_IntRemove( vSuper, iBest ); Vec_IntRemove( vSuper, kBest ); if ( Gia_ObjIsXor(pObj) ) iLit = Gia_ManHashXorReal( pNew, iBest, kBest ); else iLit = Gia_ManHashAnd( pNew, iBest, kBest ); Bal_ManSetGateLevel( p, pObj, iLit ); Vec_IntPushOrderCost2( vSuper, p->vCosts, iLit ); } } // consider trivial case assert( Vec_IntSize(vSuper) == 1 ); return Vec_IntEntry(vSuper, 0); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManBalance_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { int i, iLit, iBeg, iEnd; if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); // handle MUX if ( Gia_ObjIsMux(p, pObj) ) { Gia_ManBalance_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManBalance_rec( pNew, p, Gia_ObjFanin1(pObj) ); Gia_ManBalance_rec( pNew, p, Gia_ObjFanin2(p, pObj) ); pObj->Value = Gia_ManHashMuxReal( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); Bal_ManSetGateLevel( Bal_GiaMan(pNew), pObj, pObj->Value ); // Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value)) ); return; } // find supergate Gia_ManSuperCollect( p, pObj ); // save entries if ( p->vStore == NULL ) p->vStore = Vec_IntAlloc( 1000 ); iBeg = Vec_IntSize( p->vStore ); Vec_IntAppend( p->vStore, p->vSuper ); iEnd = Vec_IntSize( p->vStore ); // call recursively Vec_IntForEachEntryStartStop( p->vStore, iLit, i, iBeg, iEnd ) { Gia_Obj_t * pTemp = Gia_ManObj( p, Abc_Lit2Var(iLit) ); Gia_ManBalance_rec( pNew, p, pTemp ); Vec_IntWriteEntry( p->vStore, i, Abc_LitNotCond(pTemp->Value, Abc_LitIsCompl(iLit)) ); } assert( Vec_IntSize(p->vStore) == iEnd ); // consider general case pObj->Value = Gia_ManBalanceGate( pNew, pObj, p->vSuper, Vec_IntEntryP(p->vStore, iBeg), iEnd-iBeg ); Vec_IntShrink( p->vStore, iBeg ); } static inline Gia_Man_t * Gia_ManBalanceInt( Gia_Man_t * p, int nLutSize, int nCutNum, int fVerbose ) { Bal_Man_t * pMan; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; Gia_ManFillValue( p ); Gia_ManCreateRefs( p ); // start the new manager pNew = Gia_ManStart( 3*Gia_ManObjNum(p)/2 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); pNew->vLevels = Vec_IntStart( pNew->nObjsAlloc ); // create constant and inputs Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); // create balancing manager pMan = Bal_ManAlloc( p, pNew, nLutSize, nCutNum, fVerbose ); // create internal nodes Gia_ManHashStart( pNew ); Gia_ManForEachCo( p, pObj, i ) Gia_ManBalance_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); // if ( fVerbose ) { int nLevelMax = 0; Gia_ManForEachCo( pNew, pObj, i ) { nLevelMax = Abc_MaxInt( nLevelMax, Bal_ObjDelay(pMan, Gia_ObjFaninId0p(pNew, pObj)) ); // printf( "%d=%d ", i, Bal_ObjDelay(pMan, Gia_ObjFaninId0p(pNew, pObj)) ); } printf( "Best delay = %d\n", nLevelMax ); } // assert( Gia_ManObjNum(pNew) <= Gia_ManObjNum(p) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // delete manager Bal_ManFree( pMan ); // perform cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } Gia_Man_t * Gia_ManBalanceLut( Gia_Man_t * p, int nLutSize, int nCutNum, int fVerbose ) { Gia_Man_t * pNew, * pNew1, * pNew2; if ( fVerbose ) Gia_ManPrintStats( p, NULL ); pNew = Gia_ManDupMuxes( p, 2 ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); pNew1 = Gia_ManBalanceInt( pNew, nLutSize, nCutNum, fVerbose ); if ( fVerbose ) Gia_ManPrintStats( pNew1, NULL ); Gia_ManStop( pNew ); pNew2 = Gia_ManDupNoMuxes( pNew1, 0 ); if ( fVerbose ) Gia_ManPrintStats( pNew2, NULL ); Gia_ManStop( pNew1 ); return pNew2; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaBalMap.c000066400000000000000000000241621477524141600162550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaSopb.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [SOP balancing for a window.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaSopb.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_ManHighlight_rec( Gia_Man_t * p, int iObj ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) return; Gia_ObjSetTravIdCurrentId(p, iObj); pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjIsAnd(pObj) ) Gia_ManHighlight_rec( p, Gia_ObjFaninId0(pObj, iObj) ); if ( Gia_ObjIsAnd(pObj) ) Gia_ManHighlight_rec( p, Gia_ObjFaninId1(pObj, iObj) ); } void Gia_ManPrepareWin( Gia_Man_t * p, Vec_Int_t * vOuts, Vec_Int_t ** pvPis, Vec_Int_t ** pvPos, Vec_Int_t ** pvAnds, int fPoOnly ) { Gia_Obj_t * pObj; int i; // mark the section Gia_ManIncrementTravId( p ); Gia_ManForEachCoVec( vOuts, p, pObj, i ) Gia_ManHighlight_rec( p, Gia_ObjFaninId0p(p, pObj) ); // mark fanins of the outside area Gia_ManCleanMark0( p ); if ( fPoOnly ) { Gia_ManForEachCoVec( vOuts, p, pObj, i ) Gia_ObjFanin0(pObj)->fMark0 = 1; } else { Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsCi(pObj) ) continue; if ( Gia_ObjIsAnd(pObj) && !Gia_ObjIsTravIdCurrentId(p, i) ) continue; Gia_ObjFanin0(pObj)->fMark0 = 1; if ( Gia_ObjIsAnd(pObj) ) Gia_ObjFanin1(pObj)->fMark0 = 1; } } // collect pointed nodes *pvPis = Vec_IntAlloc( 1000 ); *pvPos = Vec_IntAlloc( 1000 ); *pvAnds = Vec_IntAlloc( 1000 ); Gia_ManForEachObj1( p, pObj, i ) { if ( !Gia_ObjIsTravIdCurrentId(p, i) ) continue; if ( Gia_ObjIsCi(pObj) ) Vec_IntPush( *pvPis, i ); else if ( pObj->fMark0 ) Vec_IntPush( *pvPos, i ); if ( Gia_ObjIsAnd(pObj) ) Vec_IntPush( *pvAnds, i ); } Gia_ManCleanMark0( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManExtractWin( Gia_Man_t * p, Vec_Int_t * vOuts, int fPoOnly ) { Vec_Int_t * vPis, * vPos, * vAnds; Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; Gia_ManPrepareWin( p, vOuts, &vPis, &vPos, &vAnds, fPoOnly ); // create AIG pNew = Gia_ManStart( Vec_IntSize(vPis) + Vec_IntSize(vPos) + Vec_IntSize(vAnds) + 1 ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObjVec( vPis, 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( vPos, p, pObj, i ) Gia_ManAppendCo( pNew, pObj->Value ); Vec_IntFree( vPis ); Vec_IntFree( vPos ); Vec_IntFree( vAnds ); return pNew; } Gia_Man_t * Gia_ManInsertWin( Gia_Man_t * p, Vec_Int_t * vOuts, Gia_Man_t * pWin ) { Vec_Int_t * vPos, * vPis, * vAnds; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; Gia_ManPrepareWin( p, vOuts, &vPis, &vPos, &vAnds, 0 ); // create AIG pNew = Gia_ManStart( Gia_ManObjNum(p) - Vec_IntSize(vAnds) + Gia_ManAndNum(pWin) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // inputs Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManConst0(pWin)->Value = 0; Gia_ManForEachCi( pWin, pObj, i ) pObj->Value = Gia_ManObj(p, Vec_IntEntry(vPis, i))->Value; // internal nodes Gia_ManHashAlloc( pNew ); Gia_ManForEachAnd( pWin, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( pWin, pObj, i ) Gia_ManObj( p, Vec_IntEntry(vPos, i) )->Value = Gia_ObjFanin0Copy(pObj); Gia_ManForEachAnd( p, pObj, i ) if ( !Gia_ObjIsTravIdCurrentId(p, i) ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); // cleanup Vec_IntFree( vPis ); Vec_IntFree( vPos ); Vec_IntFree( vAnds ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManFindLatest( Gia_Man_t * p, int LevelMax, int nTimeWindow ) { Gia_Obj_t * pObj; Vec_Int_t * vOuts; vOuts = Vec_IntAlloc( 1000 ); if ( Gia_ManHasMapping(p) ) { int i, k, iFan, nLevels = 0; int * pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachLut( p, i ) { Gia_LutForEachFanin( p, i, iFan, k ) pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[iFan] ); pLevels[i]++; nLevels = Abc_MaxInt( nLevels, pLevels[i] ); } if ( nTimeWindow ) LevelMax = (int)((1.0 - 0.01 * nTimeWindow) * nLevels); if ( nLevels < LevelMax ) printf( "The maximum mapped level (%d) is less than the target level (%d).\n", nLevels, LevelMax ); Gia_ManForEachCo( p, pObj, i ) if ( pLevels[Gia_ObjFaninId0p(p, pObj)] >= LevelMax ) Vec_IntPush( vOuts, i ); ABC_FREE( pLevels ); } else { int i, nLevels = Gia_ManLevelNum( p ); if ( nTimeWindow ) LevelMax = (int)((1.0 - 0.01 * nTimeWindow) * nLevels); if ( nLevels < LevelMax ) printf( "The maximum AIG level (%d) is less than the target level (%d).\n", nLevels, LevelMax ); Gia_ManForEachCo( p, pObj, i ) if ( Gia_ObjLevel(p, pObj) >= LevelMax ) Vec_IntPush( vOuts, i ); } return vOuts; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManExtractWindow( Gia_Man_t * p, int LevelMax, int nTimeWindow, int fVerbose ) { Vec_Int_t * vOuts; Gia_Man_t * pWin; assert( !LevelMax != !nTimeWindow ); vOuts = Gia_ManFindLatest( p, LevelMax, nTimeWindow ); if ( fVerbose ) printf( "Collected %d outputs to extract.\n", Vec_IntSize(vOuts) ); if ( Vec_IntSize(vOuts) == 0 ) { Vec_IntFree( vOuts ); return Gia_ManDup( p ); } pWin = Gia_ManExtractWin( p, vOuts, 1 ); Vec_IntFree( vOuts ); return pWin; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManPerformSopBalanceWin( Gia_Man_t * p, int LevelMax, int nTimeWindow, int nCutNum, int nRelaxRatio, int fVerbose ) { Vec_Int_t * vOuts; Gia_Man_t * pNew, * pWin, * pWinNew; assert( !LevelMax != !nTimeWindow ); vOuts = Gia_ManFindLatest( p, LevelMax, nTimeWindow ); if ( fVerbose ) printf( "Collected %d outputs to extract.\n", Vec_IntSize(vOuts) ); if ( Vec_IntSize(vOuts) == 0 ) { Vec_IntFree( vOuts ); return Gia_ManDup( p ); } pWin = Gia_ManExtractWin( p, vOuts, 0 ); pWinNew = Gia_ManPerformSopBalance( pWin, nCutNum, nRelaxRatio, fVerbose ); Gia_ManStop( pWin ); pNew = Gia_ManInsertWin( p, vOuts, pWinNew ); Gia_ManStop( pWinNew ); Vec_IntFree( vOuts ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManPerformDsdBalanceWin( Gia_Man_t * p, int LevelMax, int nTimeWindow, int nLutSize, int nCutNum, int nRelaxRatio, int fVerbose ) { Vec_Int_t * vOuts; Gia_Man_t * pNew, * pWin, * pWinNew; assert( !LevelMax != !nTimeWindow ); vOuts = Gia_ManFindLatest( p, LevelMax, nTimeWindow ); if ( fVerbose ) printf( "Collected %d outputs to extract.\n", Vec_IntSize(vOuts) ); if ( Vec_IntSize(vOuts) == 0 ) { Vec_IntFree( vOuts ); return Gia_ManDup( p ); } pWin = Gia_ManExtractWin( p, vOuts, 0 ); pWinNew = Gia_ManPerformDsdBalance( pWin, nLutSize, nCutNum, nRelaxRatio, fVerbose ); Gia_ManStop( pWin ); pNew = Gia_ManInsertWin( p, vOuts, pWinNew ); Gia_ManStop( pWinNew ); Vec_IntFree( vOuts ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaBidec.c000066400000000000000000000264221477524141600161300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaBidec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Application of bi-decomposition to AIG minimization.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaBidec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "bool/bdc/bdc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes truth table of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Gia_ManConvertAigToTruth_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vTruth, int nWords, Vec_Int_t * vVisited ) { unsigned * pTruth, * pTruth0, * pTruth1; int i; assert( !Gia_IsComplement(pObj) ); if ( Vec_IntGetEntry(p->vTruths, Gia_ObjId(p, pObj)) != -1 ) return (unsigned *)Vec_IntEntryP( vTruth, nWords * Vec_IntGetEntry(p->vTruths, Gia_ObjId(p, pObj)) ); // compute the truth tables of the fanins pTruth0 = Gia_ManConvertAigToTruth_rec( p, Gia_ObjFanin0(pObj), vTruth, nWords, vVisited ); pTruth1 = Gia_ManConvertAigToTruth_rec( p, Gia_ObjFanin1(pObj), vTruth, nWords, vVisited ); // get room for the truth table pTruth = Vec_IntFetch( vTruth, nWords ); // create the truth table of the node if ( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] & pTruth1[i]; else if ( !Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] & ~pTruth1[i]; else if ( Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = ~pTruth0[i] & pTruth1[i]; else // if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; // save the visited node Vec_IntSetEntry( p->vTruths, Gia_ObjId(p, pObj), Vec_IntSize(vVisited) ); Vec_IntPush( vVisited, Gia_ObjId(p, pObj) ); return pTruth; } /**Function************************************************************* Synopsis [Computes truth table of the node.] Description [Assumes that the structural support is no more than 8 inputs. Uses array vTruth to store temporary truth tables. The returned pointer should be used immediately.] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Gia_ManConvertAigToTruth( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vTruth, Vec_Int_t * vVisited ) { static unsigned uTruths[8][8] = { // elementary truth tables { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } }; Gia_Obj_t * pObj; Vec_Ptr_t * vTtElems = NULL; unsigned * pTruth;//, * pTruth2; int i, nWords, nVars; // get the number of variables and words nVars = Vec_IntSize( vLeaves ); nWords = Abc_TruthWordNum( nVars ); // check the case of a constant if ( Gia_ObjIsConst0( Gia_Regular(pRoot) ) ) { Vec_IntClear( vTruth ); // get room for the truth table pTruth = Vec_IntFetch( vTruth, nWords ); if ( !Gia_IsComplement(pRoot) ) Gia_ManTruthClear( pTruth, nVars ); else Gia_ManTruthFill( pTruth, nVars ); return pTruth; } // if the number of variables is more than 8, allocate truth tables if ( nVars > 8 ) vTtElems = Vec_PtrAllocTruthTables( nVars ); // assign elementary truth tables Vec_IntClear( vTruth ); Vec_IntClear( vVisited ); Gia_ManForEachObjVec( vLeaves, p, pObj, i ) { // get room for the truth table pTruth = Vec_IntFetch( vTruth, nWords ); // assign elementary variable if ( vTtElems ) Gia_ManTruthCopy( pTruth, (unsigned *)Vec_PtrEntry(vTtElems, i), nVars ); else Gia_ManTruthCopy( pTruth, uTruths[i], nVars ); // save the visited node Vec_IntSetEntry( p->vTruths, Gia_ObjId(p, pObj), Vec_IntSize(vVisited) ); Vec_IntPush( vVisited, Gia_ObjId(p, pObj) ); } if ( vTtElems ) Vec_PtrFree( vTtElems ); // clear the marks and compute the truth table // pTruth2 = Gia_ManConvertAigToTruth_rec( p, Gia_Regular(pRoot), vTruth, nWords, vVisited ); pTruth = Gia_ManConvertAigToTruth_rec( p, Gia_Regular(pRoot), vTruth, nWords, vVisited ); // copy the result // Gia_ManTruthCopy( pTruth, pTruth2, nVars ); if ( Gia_IsComplement(pRoot) ) Gia_ManTruthNot( pTruth, pTruth, nVars ); // clean truth tables Gia_ManForEachObjVec( vVisited, p, pObj, i ) Vec_IntSetEntry( p->vTruths, Gia_ObjId(p, pObj), -1 ); return pTruth; } /**Function************************************************************* Synopsis [Resynthesizes nodes using bi-decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ObjPerformBidec( Bdc_Man_t * pManDec, Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vTruth, Vec_Int_t * vVisited ) { unsigned * pTruth; Bdc_Fun_t * pFunc; Gia_Obj_t * pFanin; int i, iFan, nVars, nNodes; // collect leaves of this gate Vec_IntClear( vLeaves ); Gia_LutForEachFanin( p, Gia_ObjId(p, pRoot), iFan, i ) Vec_IntPush( vLeaves, iFan ); nVars = Vec_IntSize( vLeaves ); assert( nVars < 16 ); // derive truth table pTruth = Gia_ManConvertAigToTruth( p, pRoot, vLeaves, vTruth, vVisited ); //Extra_PrintBinary( stdout, pTruth, (1<nVarsMax = Gia_ManLutSizeMax( p ); pPars->fVerbose = fVerbose; if ( pPars->nVarsMax < 2 ) { printf( "Resynthesis is not performed when nodes have less than 2 inputs.\n" ); return NULL; } if ( pPars->nVarsMax > 15 ) { printf( "Resynthesis is not performed when nodes have more than 15 inputs.\n" ); return NULL; } vLeaves = Vec_IntAlloc( 0 ); vTruth = Vec_IntAlloc( (1<<16) ); vVisited = Vec_IntAlloc( 0 ); // clean the old manager Gia_ManCleanTruth( p ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; // start the new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); // Gia_ManCleanLevels( pNew, Gia_ManObjNum(p) ); pManDec = Bdc_ManAlloc( pPars ); Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsCi(pObj) ) // transfer the CI level (is it needed?) pObj->Value = Gia_ManAppendCi( pNew ); else if ( Gia_ObjIsCo(pObj) ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); else if ( Gia_ObjIsLut(p, i) ) pObj->Value = Gia_ObjPerformBidec( pManDec, pNew, p, pObj, vLeaves, vTruth, vVisited ); } Bdc_ManFree( pManDec ); // cleanup the AIG Gia_ManHashStop( pNew ); // check the presence of dangling nodes if ( Gia_ManHasDangling(pNew) ) { pNew = Gia_ManCleanup( pTemp = pNew ); if ( Gia_ManAndNum(pNew) != Gia_ManAndNum(pTemp) ) printf( "Gia_ManPerformBidec() node count before and after: %6d and %6d.\n", Gia_ManAndNum(pNew), Gia_ManAndNum(pTemp) ); Gia_ManStop( pTemp ); } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); Vec_IntFree( vLeaves ); Vec_IntFree( vTruth ); Vec_IntFree( vVisited ); if ( fVerbose ) { // printf( "Total gain in AIG nodes = %d. ", Gia_ManObjNum(p)-Gia_ManObjNum(pNew) ); // ABC_PRT( "Total runtime", Abc_Clock() - clk ); } return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaBound.c000066400000000000000000001126651477524141600161760ustar00rootroot00000000000000#include "gia.h" #include "misc/tim/tim.h" #include "misc/vec/vecWec.h" #include "proof/cec/cec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Bnd_Man_t_ Bnd_Man_t; struct Bnd_Man_t_ { int nBI; int nBO; int nBI_miss; int nBO_miss; int nInternal; int nExtra; int nMerged_spec; int nMerged_impl; int nNode_spec; int nNode_impl; int nNode_patch; int nNode_patched; int fVerbose; int combLoop_spec; int combLoop_impl; int eq_out; int eq_res; int nChoice_spec; int nChoice_impl; int feedthrough; int maxNumClass; Vec_Ptr_t* vBmiter2Spec; Vec_Ptr_t* vBmiter2Impl; Vec_Bit_t* vSpec2Impl_phase; // TODO: record all phases Vec_Int_t* vImpl2Bmiter; Vec_Int_t* vSpec2Bmiter; Vec_Int_t* vBI; Vec_Int_t* vBO; Vec_Int_t* vEI_spec; Vec_Int_t* vEO_spec; Vec_Int_t* vEI_impl; Vec_Int_t* vEO_impl; Vec_Bit_t* vEI_phase; Vec_Bit_t* vEO_phase; }; Bnd_Man_t* pBnd = 0; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// void Bnd_ManSetEqOut( int eq ) { pBnd -> eq_out = eq;} void Bnd_ManSetEqRes( int eq ) { pBnd -> eq_res = eq;} Vec_Int_t* Bnd_ManSpec2Impl( int id ) { return (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Impl, Vec_IntEntry( pBnd->vSpec2Bmiter, id ) ); } int Bnd_ManSpec2ImplNum( int id ) { return Vec_IntSize( (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Impl, Vec_IntEntry( pBnd->vSpec2Bmiter, id ) ) ); } Vec_Int_t* Bnd_ManImpl2Spec( int id ) { return (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Spec, Vec_IntEntry( pBnd->vImpl2Bmiter, id ) ); } int Bnd_ManImpl2SpecNum( int id ) { return Vec_IntSize( (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Spec, Vec_IntEntry( pBnd->vImpl2Bmiter, id ) ) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl, int fVerbose ) { int i; Bnd_Man_t* p = ABC_CALLOC( Bnd_Man_t, 1 ); p -> maxNumClass = Gia_ManCiNum( pSpec ) + Gia_ManAndNotBufNum(pSpec) + Gia_ManAndNum(pImpl) + 2 + Gia_ManCoNum(pSpec) * 2; // one for constant node and one for dummy p -> vBmiter2Spec = Vec_PtrAlloc( p -> maxNumClass ); p -> vBmiter2Impl = Vec_PtrAlloc( p -> maxNumClass ); Vec_PtrFill( p -> vBmiter2Spec, p -> maxNumClass, 0 ); Vec_PtrFill( p -> vBmiter2Impl, p -> maxNumClass, 0 ); for( i = 0; i < Vec_PtrSize( p -> vBmiter2Impl ); i ++ ) { Vec_PtrSetEntry( p -> vBmiter2Spec, i, Vec_IntAlloc(1) ); Vec_PtrSetEntry( p -> vBmiter2Impl, i, Vec_IntAlloc(1) ); } p -> vSpec2Impl_phase = Vec_BitAlloc( Gia_ManObjNum(pSpec) ); Vec_BitFill( p -> vSpec2Impl_phase, Gia_ManObjNum(pSpec), 0 ); p -> vImpl2Bmiter = Vec_IntAlloc( Gia_ManObjNum(pImpl) ); Vec_IntFill( p -> vImpl2Bmiter, Gia_ManObjNum(pImpl), p -> maxNumClass - 1 ); p -> vSpec2Bmiter = Vec_IntAlloc( Gia_ManObjNum(pSpec) ); Vec_IntFill( p -> vSpec2Bmiter, Gia_ManObjNum(pSpec), p -> maxNumClass - 1); p -> vBI = Vec_IntAlloc(16); p -> vBO = Vec_IntAlloc(16); p -> vEI_spec = Vec_IntAlloc(16); p -> vEO_spec = Vec_IntAlloc(16); p -> vEI_impl = Vec_IntAlloc(16); p -> vEO_impl = Vec_IntAlloc(16); p -> vEI_phase = Vec_BitAlloc(16); p -> vEO_phase = Vec_BitAlloc(16); p -> nNode_spec = Gia_ManAndNum(pSpec) - Gia_ManBufNum(pSpec); p -> nNode_impl = Gia_ManAndNum(pImpl); p -> nNode_patch = 0; p -> nNode_patched = 0; p -> fVerbose = fVerbose; p -> combLoop_spec = 0; p -> combLoop_impl = 0; p -> eq_out = 0; p -> eq_res = 0; p -> nChoice_spec = 0; p -> nChoice_impl = 0; p -> feedthrough = 0; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Bnd_ManStop() { assert(pBnd); Vec_PtrFree( pBnd-> vBmiter2Spec ); Vec_PtrFree( pBnd-> vBmiter2Impl ); Vec_BitFree( pBnd-> vSpec2Impl_phase ); Vec_IntFree( pBnd-> vImpl2Bmiter ); Vec_IntFree( pBnd-> vSpec2Bmiter ); Vec_IntFree( pBnd->vBI ); Vec_IntFree( pBnd->vBO ); Vec_IntFree( pBnd->vEI_spec ); Vec_IntFree( pBnd->vEO_spec ); Vec_IntFree( pBnd->vEI_impl ); Vec_IntFree( pBnd->vEO_impl ); Vec_BitFree( pBnd->vEI_phase ); Vec_BitFree( pBnd->vEO_phase ); ABC_FREE( pBnd ); } int Bnd_ManGetNInternal() { assert(pBnd); return pBnd -> nInternal; } int Bnd_ManGetNExtra() { assert(pBnd); return pBnd -> nExtra; } void Bnd_ManMap( int iLit, int id, int spec ) { if ( spec ) { Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry( pBnd -> vBmiter2Spec, iLit >> 1), id ); Vec_BitSetEntry( pBnd -> vSpec2Impl_phase, id, iLit & 1 ); } else { assert( (iLit & 1) == 0 ); Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry( pBnd -> vBmiter2Impl, iLit >> 1), id ); } } void Bnd_ManMerge( int id_repr, int id_obj, int phaseDiff ) { Vec_Ptr_t* vBmiter2Spec = pBnd -> vBmiter2Spec; Vec_Ptr_t* vBmiter2Impl = pBnd -> vBmiter2Impl; Vec_Bit_t* vSpec2Impl_phase = pBnd -> vSpec2Impl_phase; int id, i; Vec_Int_t *vIds_spec_repr, *vIds_impl_repr, *vIds_spec_obj, *vIds_impl_obj; vIds_spec_repr = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, id_repr ); vIds_impl_repr = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, id_repr ); vIds_spec_obj = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, id_obj ); vIds_impl_obj = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, id_obj ); Vec_IntForEachEntry( vIds_spec_obj, id, i ) { Vec_IntPush(vIds_spec_repr, id); } Vec_IntForEachEntry( vIds_impl_obj, id, i ) { Vec_IntPush(vIds_impl_repr, id); } // handle spec2impl phase if ( phaseDiff ) { Vec_IntForEachEntry( vIds_spec_obj, id, i ) { Vec_BitSetEntry( vSpec2Impl_phase, id, !Vec_BitEntry(vSpec2Impl_phase, id) ); // printf( "spec id %d's phase set to %d\n", id, Vec_BitEntry(vSpec2Impl_phase, id) ); } } Vec_IntClear(vIds_spec_obj); Vec_IntClear(vIds_impl_obj); } void Bnd_ManFinalizeMappings() { Vec_Ptr_t* vBmiter2Spec = pBnd -> vBmiter2Spec; Vec_Ptr_t* vBmiter2Impl = pBnd -> vBmiter2Impl; Vec_Int_t *vSpec, *vImpl; int i, j, id; pBnd -> nMerged_impl = 0; pBnd -> nMerged_spec = 0; for( i = 0; i < Vec_PtrSize(vBmiter2Spec); i++ ) { vSpec = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, i ); vImpl = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, i ); Vec_IntForEachEntry( vSpec, id, j ) { // vSpec2Bmiter Vec_IntSetEntry( pBnd->vSpec2Bmiter, id, i ); } Vec_IntForEachEntry( vImpl, id, j ) { // vImpl2Bmiter Vec_IntSetEntry( pBnd->vImpl2Bmiter, id, i ); } // count number of nodes merged into the same circuit if ( Vec_IntSize(vSpec) != 0 ) { pBnd->nMerged_spec += Vec_IntSize(vSpec) - 1; } if ( Vec_IntSize(vImpl) != 0 ) { pBnd->nMerged_impl += Vec_IntSize(vImpl) - 1; } } } void Bnd_ManPrintMappings() { Vec_Ptr_t* vBmiter2Spec = pBnd -> vBmiter2Spec; Vec_Ptr_t* vBmiter2Impl = pBnd -> vBmiter2Impl; Vec_Int_t* vIds_spec, *vIds_impl; int k, id; for( int j=0; j < Vec_PtrSize(vBmiter2Spec); j++ ) { printf("node %d: ", j); vIds_spec = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, j); vIds_impl = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, j); Vec_IntForEachEntry(vIds_spec, id, k) printf("%d ", id); printf("| "); Vec_IntForEachEntry(vIds_impl, id, k) printf("%d ", id); printf("\n"); } } void Bnd_ManPrintBound() { // printf("%d nodes merged in spec\n", pBnd ->nMerged_spec - Vec_IntSize(pBnd->vBI) - Vec_IntSize(pBnd->vBO) ); // printf("%d nodes merged in impl\n", pBnd ->nMerged_impl ); printf("BI spec:\t"); Vec_IntPrint(pBnd -> vBI); printf("BO spec:\t"); Vec_IntPrint(pBnd -> vBO); printf("EI spec:\t"); Vec_IntPrint(pBnd -> vEI_spec); printf("EI impl:\t"); Vec_IntPrint(pBnd -> vEI_impl); printf("EI phase:\t"); Vec_BitPrint(pBnd -> vEI_phase); printf("EO spec:\t"); Vec_IntPrint(pBnd -> vEO_spec); printf("EO impl:\t"); Vec_IntPrint(pBnd -> vEO_impl); printf("EO phase:\t"); Vec_BitPrint(pBnd -> vEO_phase); } void Bnd_ManPrintStats() { Bnd_Man_t* p = pBnd; printf("\nSTATS\n"); int warning = 0; if ( p->nChoice_spec > 0 ) { warning = 1; printf("WARNING: multiple equiv nodes on the boundary of spec\n"); } if ( p->nChoice_impl > 0 ) { warning = 1; printf("WARNING: multiple equiv nodes on the boundary of impl\n"); } printf("The outsides of spec and impl are %sEQ.\n", p->eq_out ? "" : "NOT " ); printf("The patched impl is %sEQ. to spec (and impl)\n", p->eq_res ? "" : "NOT " ); // #internal // nBI, nBO // nBI_miss, nBO_miss // nEI, nEO, nExtra // #spec, #impl, #patched // combLoop_spec, combLoop_impl // #choice_impl // #choice_spec // #feedthrough // warning (may be neq) // eq_out, eq_res printf("\nRESULT\n"); printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", p->nInternal, p->nBI, p->nBO, p->nBI_miss, p->nBO_miss, Vec_IntSize(p->vEI_spec), Vec_IntSize(p->vEO_spec), p->nExtra, p->nNode_spec, p->nNode_impl, p->nNode_patched, p->combLoop_spec, p->combLoop_impl, p->nChoice_impl, p->nChoice_spec, warning, p->eq_out, p->eq_res ); printf("#Choice Spec\t%d\n", p->nChoice_spec); printf("#Choice Impl\t%d\n", p->nChoice_impl); } /**Function************************************************************* Synopsis [] Description [check if the given boundary is valid. Return 0 if the boundary is invalid. Return k if the boundary is valid and there're k boundary inputs. Can be called even if Bnd_Man_t is not created] SideEffects [] SeeAlso [] ***********************************************************************/ int Bnd_ManCheckBound( Gia_Man_t * p, int fVerbose ) { int i; Gia_Obj_t *pObj; int valid = 1; int nBI = 0, nBO = 0, nInternal = 0; if ( fVerbose ) printf( "Checking boundary... \n"); Vec_Int_t *vPath; vPath = Vec_IntAlloc( Gia_ManObjNum(p) ); Vec_IntFill( vPath, Gia_ManObjNum(p), 0 ); int path; Gia_ManForEachObjReverse1( p , pObj, i ) { if ( Gia_ObjIsCo( pObj ) ) { Vec_IntSetEntry( vPath, Gia_ObjId( p, pObj ), 1 ); } path = Vec_IntEntry( vPath, Gia_ObjId(p, pObj) ); // printf("path = %d\n", path); if ( path >= 8 ) { valid = 0; printf("there're more than 2 bufs in a path\n"); break; } if( Gia_ObjIsBuf( pObj ) ) { Vec_IntSetEntry( vPath, Gia_ObjId( p, Gia_ObjFanin0( pObj ) ), Vec_IntEntry( vPath, Gia_ObjId(p, Gia_ObjFanin0( pObj ) ) ) | path << 1 ); if ( path == 1 ) // boundary input { // TODO: record BIs here since they may not be in the first n buffers nBO ++; } } else if ( Gia_ObjFaninNum( p, pObj ) >= 1 ) { Vec_IntSetEntry( vPath, Gia_ObjId( p, Gia_ObjFanin0( pObj ) ), Vec_IntEntry( vPath, Gia_ObjId(p, Gia_ObjFanin0( pObj ) ) ) | path ); if ( Gia_ObjFaninNum( p, pObj ) >= 2 ) { assert( Gia_ObjFaninNum( p, pObj ) <= 2 ); Vec_IntSetEntry( vPath, Gia_ObjId( p, Gia_ObjFanin1( pObj ) ), Vec_IntEntry( vPath, Gia_ObjId(p, Gia_ObjFanin1( pObj ) ) ) | path ); } if ( path == 2 ) // inside boundary { // TODO: record BIs here since they may not be in the first n buffers nInternal ++; } } else // PI or const, check validity { if ( (Vec_IntEntry( vPath, Gia_ObjId(p, pObj) ) | 5) != 5 ) { valid = 0; printf("incorrect buf number at pi %d\n", Vec_IntEntry(vPath, Gia_ObjId(p, pObj)) ); break; } } } nBI = Gia_ManBufNum(p) - nBO; if ( !valid ) { printf("invalid boundary\n"); return 0; } else if ( nBI == 0 ) { printf("no boundary\n"); return 0; } else { if ( fVerbose ) { printf("valid boundary ("); printf("#BI = %d\t#BO = %d\t", nBI, Gia_ManBufNum(p)- nBI); printf("#Internal = %d)\n", nInternal ); } if ( pBnd ) { pBnd -> nBI = nBI; pBnd -> nBO = nBO; pBnd -> nInternal = nInternal; } return nBI; } } int Bnd_CheckFlagRec( Gia_Man_t *p, Gia_Obj_t *pObj, Vec_Int_t* vFlag ) { int id = Gia_ObjId(p, pObj); if ( Vec_IntEntry(vFlag, id) == 1 ) return 1; if ( Vec_IntEntry(vFlag, id) == 2 ) return 0; Vec_IntSetEntry(vFlag, id, 1); int ret = 1; for( int i = 0; i < Gia_ObjFaninNum(p, pObj); i++ ) { if ( !Bnd_CheckFlagRec( p, Gia_ObjFanin(pObj, i), vFlag ) ) { ret = 0; break; } } return ret; } /**Function************************************************************* Synopsis [] Description [check if combnational loop exist in the extended boundary] SideEffects [] SeeAlso [] ***********************************************************************/ int Bnd_ManCheckExtBound( Gia_Man_t * p, Vec_Int_t *vEI, Vec_Int_t *vEO ) { Vec_Int_t *vFlag = Vec_IntAlloc( Gia_ManObjNum(p) ); Vec_IntFill( vFlag, Gia_ManObjNum(p), 0 ); int success = 1; int i, id; Vec_IntForEachEntry( vEO, id, i ) { Vec_IntSetEntry( vFlag, id, 2 ); } Vec_IntForEachEntry( vEI, id, i ) { if ( Vec_IntEntry(vFlag, id) == 2 ) continue; // BI connected to BO directly if ( !Bnd_CheckFlagRec( p, Gia_ManObj(p, id), vFlag ) ) { success = 0; break; } } Vec_IntFree(vFlag); return success; } /**Function************************************************************* Synopsis [] Description [find the extended boundary in spec and compute the corresponding boundary in impl] SideEffects [] SeeAlso [] ***********************************************************************/ void Bnd_ManFindBound( Gia_Man_t * p, Gia_Man_t * pImpl ) { Vec_Int_t *vFlag; Vec_Ptr_t *vQ; Gia_Obj_t *pObj; int i, j, id, cnt; Vec_Int_t *vAI = Vec_IntAlloc(16); Vec_Int_t *vAO = Vec_IntAlloc(16); Vec_Bit_t *vSpec2Impl_phase = pBnd -> vSpec2Impl_phase; Vec_Int_t *vBI = pBnd -> vBI; Vec_Int_t *vBO = pBnd -> vBO; Vec_Int_t *vEI_spec = pBnd -> vEI_spec; Vec_Int_t *vEO_spec = pBnd -> vEO_spec; Vec_Int_t *vEI_impl = pBnd -> vEI_impl; Vec_Int_t *vEO_impl = pBnd -> vEO_impl; Vec_Bit_t *vEI_phase = pBnd -> vEI_phase; Vec_Bit_t *vEO_phase = pBnd -> vEO_phase; // prepare to compute extended boundary vQ = Vec_PtrAlloc(16); vFlag = Vec_IntAlloc( Gia_ManObjNum(p) ); Vec_IntFill( vFlag, Gia_ManObjNum(p), 0 ); Gia_ManStaticFanoutStart(p); // save bo, bi cnt = 0; Gia_ManForEachBuf(p, pObj, i) { if ( cnt < pBnd -> nBI ) { Vec_IntPush( vBI, Gia_ObjId(p, Gia_ObjFanin0(pObj) ) ); } else { Vec_IntPush( vBO, Gia_ObjId(p, pObj) ); } cnt++; } // compute EO, travse with flag 1 Vec_IntForEachEntry( vBO, id, i ) { if ( Bnd_ManSpec2ImplNum(id) == 0 ) // BO not matched { Vec_PtrPush( vQ, Gia_ManObj(p, id) ); } else { Vec_IntPush(vEO_spec, id); } } if ( pBnd -> fVerbose ) printf("%d BO doesn't match. ", Vec_PtrSize(vQ) ); pBnd -> nBO_miss = Vec_PtrSize(vQ); int cnt_extra = - Vec_PtrSize(vQ); while( Vec_PtrSize(vQ) > 0 ) { pObj = (Gia_Obj_t *)Vec_PtrPop(vQ); id = Gia_ObjId( p, pObj ); if ( Vec_IntEntry( vFlag, id ) == 1 ) continue; Vec_IntSetEntry( vFlag, id, 1 ); // printf("%d\n", id); if ( Bnd_ManSpec2ImplNum(id) != 0 ) // matched { Vec_IntPush( vEO_spec, id ); Vec_IntPush( vAO, id ); } else { for( j = 0; j < Gia_ObjFanoutNum(p, pObj); j++ ) { Vec_PtrPush( vQ, Gia_ObjFanout(p, pObj, j) ); // printf("\t%d\n", Gia_ObjId( p1, Gia_ObjFanout(p1, pObj, j) ) ); } } } // printf("%d AO found with %d extra nodes\n", Vec_IntSize(vAO) , cnt_extra ); if ( pBnd -> fVerbose ) printf("%d AO found\n", Vec_IntSize(vAO) ); // mark TFOC of BO with flag 1 to prevent them from being selected into EI // stop at CO Vec_IntForEachEntry( pBnd -> vBO, id, i ) { Vec_PtrPush( vQ, Gia_ManObj(p, id) ); } Vec_IntForEachEntry( vFlag, id, i ) { Vec_IntSetEntry( vFlag, id, 0 ); } while( Vec_PtrSize(vQ) > 0 ) { pObj = (Gia_Obj_t *)Vec_PtrPop(vQ); id = Gia_ObjId( p, pObj ); if ( Vec_IntEntry( vFlag, id ) == 1 ) continue; Vec_IntSetEntry( vFlag, id, 1 ); for( j = 0; j < Gia_ObjFanoutNum(p, pObj); j++ ) { Vec_PtrPush( vQ, Gia_ObjFanout(p, pObj, j) ); } } // compute EI, traverse with flag 2 // add unmatched BI to queue Vec_IntForEachEntry( vBI, id, i ) { if ( Bnd_ManSpec2ImplNum(id) == 0 ) // BO not matched { Vec_PtrPush( vQ, Gia_ManObj(p, id) ); } else { Vec_IntPush(vEI_spec, id); } } if ( pBnd -> fVerbose ) printf("%d BI doesn't match. ", Vec_PtrSize(vQ) ); pBnd -> nBI_miss = Vec_PtrSize(vQ); cnt_extra -= Vec_PtrSize(vQ); // add AO to queue Vec_IntForEachEntry( vAO, id, i ) { Vec_PtrPush( vQ, Gia_ManObj(p, id) ); } // set flag 2 for BO Vec_IntForEachEntry( vBO, id, i ) { Vec_IntSetEntry( vFlag, id, 2 ); } // traverse down from AI and unmatched BI while( Vec_PtrSize(vQ) > 0 ) { pObj = (Gia_Obj_t *)Vec_PtrPop(vQ); id = Gia_ObjId( p, pObj ); if ( Vec_IntEntry( vFlag, id ) == 2 ) continue; cnt_extra ++; // printf("%d\n", id); if ( Vec_IntEntry(vFlag, id) != 1 && Bnd_ManSpec2ImplNum(id) != 0 ) // matched { Vec_IntPush( vEI_spec, id ); Vec_IntPush( vAI, id ); } else { for( j = 0; j < Gia_ObjFaninNum(p, pObj); j++ ) { Vec_PtrPush( vQ, Gia_ObjFanin(pObj, j) ); // printf("\t%d\n", Gia_ObjId( p1, Gia_ObjFanout(p1, pObj, j) ) ); } } Vec_IntSetEntry( vFlag, id, 2 ); } if ( pBnd -> fVerbose ) printf("%d AI found with %d extra nodes in total\n", Vec_IntSize(vAI) , cnt_extra ); pBnd -> nExtra = cnt_extra; // gen vEI_impl, vEO_impl, vEI_phase, vEO_phase Vec_IntForEachEntry( vEI_spec, id, i ) { Vec_IntPush( vEI_impl, Vec_IntEntry( Bnd_ManSpec2Impl(id) , 0 ) ); Vec_BitPush( vEI_phase, Vec_BitEntry( vSpec2Impl_phase, id ) ); } Vec_IntForEachEntry( vEO_spec, id, i ) { Vec_IntPush( vEO_impl, Vec_IntEntry( Bnd_ManSpec2Impl(id), 0 ) ); Vec_BitPush( vEO_phase, Vec_BitEntry( vSpec2Impl_phase, id ) ); } // count number of choice of boundary Vec_IntForEachEntry( vEO_spec, id, i ) { pBnd -> nChoice_impl += Bnd_ManSpec2ImplNum( id ) - 1; } Vec_IntForEachEntry( vEO_impl, id, i ) { pBnd -> nChoice_spec += Bnd_ManImpl2SpecNum( id ) - 1; } // print if ( pBnd -> fVerbose ) { printf("#EI = %d\t#EO = %d\t#Extra Node = %d\n", Vec_IntSize(vEI_spec) , Vec_IntSize(vEO_spec), cnt_extra ); Bnd_ManPrintBound(); } // check boundary has comb loop if ( !Bnd_ManCheckExtBound( p, vEI_spec, vEO_spec ) ) { printf("Combinational loop exist\n"); pBnd -> combLoop_spec = 1; } // clean up Vec_IntFree(vAI); Vec_IntFree(vAO); } /**Function************************************************************* Synopsis [] Description [create circuit with the boundary changed to CI/CO] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec_Bit_t* vEI_phase, Vec_Bit_t* vEO_phase ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; Vec_Int_t * vValue; int i, id, lit; // check if the boundary has loop (EO cannot be in the TFC of EI ) if ( !Bnd_ManCheckExtBound( p, vEI, vEO ) ) { printf("Combinational loop exist\n"); pBnd -> combLoop_impl = 1; return 0; } // initialize pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew -> pName = ABC_ALLOC( char, strlen(p->pName)+10); sprintf( pNew -> pName, "%s_out", p -> pName ); Gia_ManHashStart( pNew ); Gia_ManFillValue(p); Gia_ManConst0(p) -> Value = 0; // record the original value for eo vValue = Vec_IntAlloc( Gia_ManObjNum(p) ); Vec_IntFill( vValue, Gia_ManObjNum(p), -1 ); // create ci for ci and eo Gia_ManForEachCi( p, pObj, i ) { pObj -> Value = Gia_ManAppendCi( pNew ); } Vec_IntForEachEntry( vEO, id, i ) { if( Gia_ManObj(p, id) -> Value != ~0 ) { Vec_IntSetEntry( vValue, id, Gia_ManObj(p, id) -> Value ); } Gia_ManObj( p, id ) -> Value = Gia_ManAppendCi(pNew); if ( vEO_phase && Vec_BitEntry( vEO_phase, i ) ) { Gia_ManObj( p, id ) -> Value ^= 1; } } // add aig nodes Gia_ManForEachAnd(p, pObj, i) { if ( pObj -> Value != ~0 ) continue; pObj -> Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } // create co for co and ei Gia_ManForEachCo(p, pObj, i) { Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Vec_IntForEachEntry( vEI, id, i ) { pObj = Gia_ManObj(p, id); // lit = Gia_ManObj(p, id)->Value; if ( Gia_ObjIsAnd(pObj) ) lit = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else { assert(Gia_ObjIsCi(pObj) || Gia_ObjIsConst0(pObj)); if ( Vec_IntEntry(vValue, id) != -1 ) { lit = Vec_IntEntry( vValue, id ); // EI at PI and EI merged with EO } else { lit = pObj -> Value; // EI at PI } } if ( vEI_phase && Vec_BitEntry( vEI_phase, i ) ) lit ^= 1; Gia_ManAppendCo( pNew, lit ); } // clean up Vec_IntFree( vValue ); Gia_ManHashStop( pNew ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } Gia_Man_t* Bnd_ManGenSpecOut( Gia_Man_t* p ) { if ( pBnd -> fVerbose ) printf("Generating spec_out with given boundary.\n"); Gia_Man_t *pNew = Bnd_ManCutBoundary( p, pBnd->vEI_spec, pBnd->vEO_spec, 0, 0 ); return pNew; } Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t* p) { if ( pBnd -> fVerbose ) printf("Generating impl_out with given boundary.\n"); Gia_Man_t *pNew = Bnd_ManCutBoundary( p, pBnd->vEI_impl, pBnd->vEO_impl, pBnd->vEI_phase, pBnd->vEO_phase ); if (!pNew) pBnd -> combLoop_impl = 1; return pNew; } void Bnd_AddNodeRec( Gia_Man_t *p, Gia_Man_t *pNew, Gia_Obj_t *pObj, int fSkipStrash ) { // TODO does this mean constant zero node? if ( pObj -> Value != ~0 ) return; for( int i = 0; i < Gia_ObjFaninNum(p, pObj); i++ ) { Bnd_AddNodeRec( p, pNew, Gia_ObjFanin(pObj, i), fSkipStrash ); } if ( Gia_ObjIsAnd(pObj) ) { if ( fSkipStrash ) { if ( Gia_ObjIsBuf(pObj) ) pObj -> Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); else pObj -> Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } else { pObj -> Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } } else { assert( Gia_ObjIsCo(pObj) ); // if ( Gia_ObjIsCi(pObj) ) printf("Ci with value ~0 encountered (id = %d)\n", Gia_ObjId(p, pObj) ); pObj -> Value = Gia_ObjFanin0Copy(pObj); } } /**Function************************************************************* Synopsis [] Description [perform ECO directly (not used)] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPatch ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, id, cnt; Vec_Int_t *vBI_patch, *vBO_patch; pBnd -> nNode_patch = Gia_ManAndNotBufNum( pPatch ); pNew = Gia_ManStart( Gia_ManObjNum(pOut) + Gia_ManObjNum( pSpec ) + Gia_ManObjNum(pPatch) ); pNew -> pName = ABC_ALLOC( char, strlen(pOut->pName)+3); sprintf( pNew -> pName, "%s_p", pOut -> pName ); Gia_ManHashStart( pNew ); Gia_ManFillValue(pOut); Gia_ManFillValue(pSpec); Gia_ManFillValue(pPatch); Gia_ManConst0(pOut)->Value = 0; Gia_ManConst0(pSpec)->Value = 0; Gia_ManConst0(pPatch)->Value = 0; // get bi and bo in patch cnt = 0; vBI_patch = Vec_IntAlloc(16); vBO_patch = Vec_IntAlloc(16); Gia_ManForEachBuf( pPatch, pObj, i ) { if ( cnt < pBnd -> nBI ) { Vec_IntPush( vBI_patch, Gia_ObjId( pPatch, pObj ) ); } else { Vec_IntPush( vBO_patch, Gia_ObjId( pPatch, pObj ) ); } cnt ++; } assert( Vec_IntSize( vBI_patch ) == Vec_IntSize(pBnd->vBI) ); assert( Vec_IntSize( vBO_patch ) == Vec_IntSize(pBnd->vBO) ); // add Impl (real) PI for ( i = 0; i < Gia_ManCiNum(pSpec); i++ ) { pObj = Gia_ManCi(pOut, i); pObj -> Value = Gia_ManAppendCi( pNew ); } // add Impl EI to CI // printf("adding EI to CI in Impl\n"); for ( i = 0; i < Vec_IntSize( pBnd -> vEI_spec ); i++ ) { pObj = Gia_ManCo(pOut, i + Gia_ManCoNum(pSpec) ); Bnd_AddNodeRec( pOut, pNew, pObj, 0 ); // set Spec EI Gia_ManObj( pSpec, Vec_IntEntry(pBnd -> vEI_spec, i) ) -> Value = pObj -> Value; // printf(" %d",pObj -> Value); } // printf("\n"); // add Spec BI to EI // printf("adding BI to EI in Spec\n"); Vec_IntForEachEntry( pBnd -> vBI, id, i ) { pObj = Gia_ManObj( pSpec, id ); Bnd_AddNodeRec( pSpec, pNew, pObj, 0 ); // set patch bi Gia_ManObj( pPatch, Vec_IntEntry( vBI_patch, i) ) -> Value = pObj -> Value; // printf(" %d",pObj -> Value); } // printf("\n"); // add Patch BO to BI // printf("adding BO to BI in Patch\n"); Vec_IntForEachEntry( vBO_patch, id, i ) { pObj = Gia_ManObj( pPatch, id ); Bnd_AddNodeRec( pPatch, pNew, pObj, 0 ); // set spec bo Gia_ManObj( pSpec, Vec_IntEntry( pBnd -> vBO, i) ) -> Value = pObj -> Value; // printf(" %d",pObj -> Value); } // printf("\n"); // add Spec EO to BO // printf("adding EO to BO in Spec\n"); Vec_IntForEachEntry( pBnd -> vEO_spec, id, i ) { pObj = Gia_ManObj( pSpec, id ); Bnd_AddNodeRec( pSpec, pNew, pObj, 0 ); // set impl EO (PI) Gia_ManCi( pOut, i + Gia_ManCiNum(pSpec) ) -> Value = pObj -> Value; // printf(" %d",pObj -> Value); } // printf("\n"); // add Impl (real) PO to EO // printf("adding CO to EO in Impl\n"); for ( i = 0; i < Gia_ManCoNum(pSpec); i++ ) { pObj = Gia_ManCo( pOut, i ); Bnd_AddNodeRec( pOut, pNew, pObj, 0 ); Gia_ManAppendCo( pNew, pObj->Value ); // printf(" %d",pObj -> Value); } // printf("\n"); // clean up Vec_IntFree( vBI_patch ); Vec_IntFree( vBO_patch ); Gia_ManHashStop( pNew ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); pBnd -> nNode_patched = Gia_ManAndNum( pNew ); return pNew; } /**Function************************************************************* Synopsis [] Description [recover bounadry] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t* Bnd_ManGenPatched1( Gia_Man_t *pOut, Gia_Man_t *pSpec ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, id; pNew = Gia_ManStart( Gia_ManObjNum(pOut) + Gia_ManObjNum( pSpec ) ); pNew -> pName = ABC_ALLOC( char, strlen(pOut->pName)+3); sprintf( pNew -> pName, "%s_p", pOut -> pName ); Gia_ManFillValue(pOut); Gia_ManFillValue(pSpec); Gia_ManConst0(pOut)->Value = 0; Gia_ManConst0(pSpec)->Value = 0; // add Impl (real) PI for ( i = 0; i < Gia_ManCiNum(pSpec); i++ ) { pObj = Gia_ManCi(pOut, i); pObj -> Value = Gia_ManAppendCi( pNew ); } // add Impl EI to CI // printf("adding EI to CI in Impl\n"); for ( i = 0; i < Vec_IntSize( pBnd -> vEI_spec ); i++ ) { pObj = Gia_ManCo(pOut, i + Gia_ManCoNum(pSpec) ); Bnd_AddNodeRec( pOut, pNew, pObj, 1 ); // set Spec EI Gia_ManObj( pSpec, Vec_IntEntry(pBnd -> vEI_spec, i) ) -> Value = pObj -> Value; // printf(" %d",pObj -> Value); } // printf("\n"); // add Spec EO to EI // add BI -> BO -> EO to maintain the order of bufs // Vec_IntForEachEntry( pBnd -> vBI, id, i ) // { // pObj = Gia_ManObj( pSpec, id ); // Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); // } // Vec_IntForEachEntry( pBnd -> vBO, id, i ) // { // pObj = Gia_ManObj( pSpec, id ); // Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); // } Gia_ManForEachBuf( pSpec, pObj, i ) { Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); } Vec_IntForEachEntry( pBnd -> vEO_spec, id, i ) { pObj = Gia_ManObj( pSpec, id ); Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); // set impl EO (PI) Gia_ManCi( pOut, i + Gia_ManCiNum(pSpec) ) -> Value = pObj -> Value; // printf(" %d",pObj -> Value); } // printf("\n"); // add Impl (real) PO to EO // printf("adding CO to EO in Impl\n"); for ( i = 0; i < Gia_ManCoNum(pSpec); i++ ) { pObj = Gia_ManCo( pOut, i ); Bnd_AddNodeRec( pOut, pNew, pObj, 1 ); Gia_ManAppendCo( pNew, pObj->Value ); // printf(" %d",pObj -> Value); } // printf("\n"); // clean up pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); pBnd -> nNode_patched = Gia_ManAndNum( pNew ); return pNew; } /**Function************************************************************* Synopsis [] Description [perform eco with recovered boundary. bnd_man is not used] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t* Bnd_ManGenPatched2( Gia_Man_t *pImpl, Gia_Man_t *pPatch, int fSkipStrash, int fVerbose ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, nBI, nBI_patch, cnt; Vec_Int_t* vLit; // check boundary first nBI = Bnd_ManCheckBound( pImpl, fVerbose ); nBI_patch = Bnd_ManCheckBound( pPatch, fVerbose ); if ( 0 == nBI_patch || Gia_ManBufNum(pImpl) != Gia_ManBufNum(pPatch) || nBI != nBI_patch ) { Abc_Print( -1, "Abc_CommandAbc9StrEco(): The given boundary is invalid.\n" ); return 0; } // prepare new network pNew = Gia_ManStart( Gia_ManObjNum(pImpl) + Gia_ManObjNum( pPatch ) ); pNew -> pName = ABC_ALLOC( char, strlen(pImpl->pName)+3); sprintf( pNew -> pName, "%s_p", pImpl -> pName ); if ( !fSkipStrash ) { Gia_ManHashAlloc( pNew ); } Gia_ManFillValue(pImpl); Gia_ManFillValue(pPatch); Gia_ManConst0(pImpl)->Value = 0; Gia_ManConst0(pPatch)->Value = 0; vLit = Vec_IntAlloc( Gia_ManBufNum(pImpl) ); // add Impl (real) CI Gia_ManForEachCi( pImpl, pObj, i ) { pObj -> Value = Gia_ManAppendCi( pNew ); } // add Impl BI to CI cnt = 0; Gia_ManForEachBuf( pImpl, pObj, i ) { Bnd_AddNodeRec( pImpl, pNew, pObj, fSkipStrash ); Vec_IntPush( vLit, pObj -> Value ); cnt ++; if ( cnt >= nBI ) break; } // set BI in patch // add patch BO to BI cnt = 0; Gia_ManForEachBuf( pPatch, pObj, i ) { if ( cnt < nBI ) { pObj -> Value = Vec_IntEntry( vLit, cnt ); } else { Bnd_AddNodeRec( pPatch, pNew, pObj, fSkipStrash ); Vec_IntPush( vLit, pObj -> Value ); } cnt ++; if ( cnt == nBI ) Vec_IntClear( vLit ); } // set BO in impl cnt = 0; Gia_ManForEachBuf( pImpl, pObj, i ) { cnt ++; if ( cnt <= nBI) continue; pObj -> Value = Vec_IntEntry( vLit, cnt-nBI-1 ); } // add impl CO to BO Gia_ManForEachCo( pImpl, pObj, i ) { Bnd_AddNodeRec( pImpl, pNew, pObj, fSkipStrash ); Gia_ManAppendCo( pNew, pObj -> Value ); } // clean up if ( !fSkipStrash ) { Gia_ManHashStop( pNew ); } Vec_IntFree( vLit ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } Gia_Man_t* Bnd_ManStackGias( Gia_Man_t *pSpec, Gia_Man_t *pImpl ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iLit; if ( Gia_ManBufNum(pSpec) == 0 ) { printf( "The spec AIG should have a boundary.\n" ); return NULL; } if ( Gia_ManBufNum(pImpl) != 0 ) { printf( "The impl AIG should have no boundary.\n" ); return NULL; } assert( Gia_ManBufNum(pSpec) > 0 ); assert( Gia_ManBufNum(pImpl) == 0 ); assert( Gia_ManRegNum(pSpec) == 0 ); assert( Gia_ManRegNum(pImpl) == 0 ); assert( Gia_ManCiNum(pSpec) == Gia_ManCiNum(pImpl) ); assert( Gia_ManCoNum(pSpec) == Gia_ManCoNum(pImpl) ); pNew = Gia_ManStart( Gia_ManObjNum(pSpec) + Gia_ManObjNum(pImpl) ); pNew->pName = ABC_ALLOC( char, strlen(pSpec->pName) + 10 ); sprintf( pNew->pName, "%s_stack", pSpec->pName ); Gia_ManHashStart( pNew ); Gia_ManConst0(pSpec)->Value = 0; Gia_ManConst0(pImpl)->Value = 0; for( int i = 0; i < Gia_ManCiNum(pSpec); i++ ) { int iLit = Gia_ManCi(pSpec, i)->Value = Gia_ManCi(pImpl, i) -> Value = Gia_ManAppendCi(pNew); pObj = Gia_ManCi(pSpec, i); Bnd_ManMap( iLit, Gia_ObjId( pSpec, pObj ), 1 ); pObj = Gia_ManCi(pImpl, i); Bnd_ManMap( iLit, Gia_ObjId( pImpl, pObj) , 0 ); } // record the corresponding impl node of each lit Gia_ManForEachAnd( pImpl, pObj, i ) { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( pBnd ) Bnd_ManMap( pObj -> Value, Gia_ObjId(pImpl, pObj), 0 ); } Vec_Int_t* vFlag = Vec_IntAlloc( Gia_ManObjNum( pSpec ) ); Vec_IntFill( vFlag, Gia_ManObjNum(pSpec), 0 ); int count = 0; Gia_ManForEachBuf( pSpec, pObj, i ) { if ( count < pBnd -> nBI ) { // it's BI, don't record buf Vec_IntSetEntry( vFlag, Gia_ObjId( pSpec, pObj ), 1 ); } else { // it's BO, don't record buf's fanin Vec_IntSetEntry( vFlag, Gia_ObjId( pSpec, Gia_ObjFanin0( pObj ) ), 1 ); } count++; } // record hashed equivalent nodes Gia_ManForEachAnd( pSpec, pObj, i ) { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( Vec_IntEntry( vFlag, Gia_ObjId( pSpec, pObj ) ) == 0 ) { Bnd_ManMap( pObj -> Value, Gia_ObjId(pSpec, pObj), 1 ); } } Vec_IntFree( vFlag ); Gia_ManForEachCo( pImpl, pObj, i ) { iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Gia_ManForEachCo( pSpec, pObj, i ) { iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } // miter // Gia_ManForEachCo( pImpl, pObj, i ) // { // iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(Gia_ManCo(pSpec,i)) ); // Gia_ManAppendCo( pNew, iLit ); // } Gia_ManHashStop( pNew ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } int Bnd_ManCheckCoMerged( Gia_Man_t* p ) { int nCO = Gia_ManCoNum(p)/2; Gia_Obj_t* pObj1; Gia_Obj_t* pObj2; for ( int i = 0; i < nCO; i++ ) { pObj1 = Gia_ManCo(p, i); pObj2 = Gia_ManCo(p, i + nCO); if ( Gia_ObjFaninLit0p(p, pObj1) != Gia_ObjFaninLit0p(p, pObj2) ) return 0; } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_ENDabc-0.52/src/aig/gia/giaCCof.c000066400000000000000000000255171477524141600157400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaCCof.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Backward reachability using circuit cofactoring.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaCCof.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Ccf_Man_t_ Ccf_Man_t; // manager struct Ccf_Man_t_ { // user data Gia_Man_t * pGia; // single-output AIG manager int nFrameMax; // maximum number of frames int nConfMax; // maximum number of conflicts int nTimeMax; // maximum runtime in seconds int fVerbose; // verbose flag // internal data void * pUnr; // unrolling manager Gia_Man_t * pFrames; // unrolled timeframes Vec_Int_t * vCopies; // copy pointers of the AIG sat_solver * pSat; // SAT solver }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Create manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ccf_Man_t * Ccf_ManStart( Gia_Man_t * pGia, int nFrameMax, int nConfMax, int nTimeMax, int fVerbose ) { static Gia_ParFra_t Pars, * pPars = &Pars; Ccf_Man_t * p; assert( nFrameMax > 0 ); p = ABC_CALLOC( Ccf_Man_t, 1 ); p->pGia = pGia; p->nFrameMax = nFrameMax; p->nConfMax = nConfMax; p->nTimeMax = nTimeMax; p->fVerbose = fVerbose; // create unrolling manager memset( pPars, 0, sizeof(Gia_ParFra_t) ); pPars->fVerbose = fVerbose; pPars->nFrames = nFrameMax; pPars->fSaveLastLit = 1; p->pUnr = Gia_ManUnrollStart( pGia, pPars ); p->vCopies = Vec_IntAlloc( 1000 ); // internal data p->pSat = sat_solver_new(); // sat_solver_setnvars( p->pSat, 10000 ); return p; } /**Function************************************************************* Synopsis [Delete manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ccf_ManStop( Ccf_Man_t * p ) { Vec_IntFree( p->vCopies ); Gia_ManUnrollStop( p->pUnr ); sat_solver_delete( p->pSat ); Gia_ManStopP( &p->pFrames ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Extends the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCofExtendSolver( Ccf_Man_t * p ) { Gia_Obj_t * pObj; int i; // add SAT clauses for ( i = sat_solver_nvars(p->pSat); i < Gia_ManObjNum(p->pFrames); i++ ) { pObj = Gia_ManObj( p->pFrames, i ); if ( Gia_ObjIsAnd(pObj) ) sat_solver_add_and( p->pSat, i, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninId1(pObj, i), Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); } sat_solver_setnvars( p->pSat, Gia_ManObjNum(p->pFrames) ); } static inline int Gia_Obj0Copy( Vec_Int_t * vCopies, int Fan0, int fCompl0 ) { return Abc_LitNotCond( Vec_IntEntry(vCopies, Fan0), fCompl0 ); } static inline int Gia_Obj1Copy( Vec_Int_t * vCopies, int Fan1, int fCompl1 ) { return Abc_LitNotCond( Vec_IntEntry(vCopies, Fan1), fCompl1 ); } /**Function************************************************************* Synopsis [Cofactor the circuit w.r.t. the given assignment.] Description [Assumes that the solver has just returned SAT.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCofOneDerive_rec( Ccf_Man_t * p, int Id ) { Gia_Obj_t * pObj; int Res; if ( Vec_IntEntry(p->vCopies, Id) != -1 ) return; pObj = Gia_ManObj(p->pFrames, Id); assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) ); if ( Gia_ObjIsAnd(pObj) ) { int fCompl0 = Gia_ObjFaninC0(pObj); int fCompl1 = Gia_ObjFaninC1(pObj); int Fan0 = Gia_ObjFaninId0p(p->pFrames, pObj); int Fan1 = Gia_ObjFaninId1p(p->pFrames, pObj); Gia_ManCofOneDerive_rec( p, Fan0 ); Gia_ManCofOneDerive_rec( p, Fan1 ); Res = Gia_ManHashAnd( p->pFrames, Gia_Obj0Copy(p->vCopies, Fan0, fCompl0), Gia_Obj1Copy(p->vCopies, Fan1, fCompl1) ); } else if ( Gia_ObjCioId(pObj) >= Gia_ManRegNum(p->pGia) ) // PI Res = sat_solver_var_value( p->pSat, Id ); else Res = Abc_Var2Lit( Id, 0 ); Vec_IntWriteEntry( p->vCopies, Id, Res ); } /**Function************************************************************* Synopsis [Cofactor the circuit w.r.t. the given assignment.] Description [Assumes that the solver has just returned SAT.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCofOneDerive( Ccf_Man_t * p, int LitProp ) { int LitOut; // derive the cofactor of the property node Vec_IntFill( p->vCopies, Gia_ManObjNum(p->pFrames), -1 ); Gia_ManCofOneDerive_rec( p, Abc_Lit2Var(LitProp) ); LitOut = Vec_IntEntry( p->vCopies, Abc_Lit2Var(LitProp) ); LitOut = Abc_LitNotCond( LitOut, Abc_LitIsCompl(LitProp) ); // add new PO for the cofactor Gia_ManAppendCo( p->pFrames, LitOut ); // add SAT clauses Gia_ManCofExtendSolver( p ); // return negative literal of the cofactor return Abc_LitNot(LitOut); } /**Function************************************************************* Synopsis [Enumerates backward reachable states.] Description [Return -1 if resource limit is reached. Returns 1 if computation converged (there is no more reachable states). Returns 0 if no more states to enumerate.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCofGetReachable( Ccf_Man_t * p, int Lit ) { int ObjPrev = 0, ConfPrev = 0; int Count = 0, LitOut, RetValue; abctime clk; // try solving for the first time and quit if converged RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, p->nConfMax, 0, 0, 0 ); if ( RetValue == l_False ) return 1; // iterate circuit cofactoring while ( RetValue == l_True ) { clk = Abc_Clock(); // derive cofactor LitOut = Gia_ManCofOneDerive( p, Lit ); // add the blocking clause RetValue = sat_solver_addclause( p->pSat, &LitOut, &LitOut + 1 ); assert( RetValue ); // try solving again RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, p->nConfMax, 0, 0, 0 ); // derive cofactors if ( p->fVerbose ) { printf( "%3d : AIG =%7d Conf =%7d. ", Count++, Gia_ManObjNum(p->pFrames) - ObjPrev, sat_solver_nconflicts(p->pSat) - ConfPrev ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); ObjPrev = Gia_ManObjNum(p->pFrames); ConfPrev = sat_solver_nconflicts(p->pSat); } } if ( RetValue == l_Undef ) return -1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManCofTest( Gia_Man_t * pGia, int nFrameMax, int nConfMax, int nTimeMax, int fVerbose ) { Gia_Man_t * pNew; Ccf_Man_t * p; Gia_Obj_t * pObj; int f, i, Lit, RetValue = -1, fFailed = 0; abctime nTimeToStop = Abc_Clock() + nTimeMax * CLOCKS_PER_SEC; abctime clk = Abc_Clock(); assert( Gia_ManPoNum(pGia) == 1 ); // create reachability manager p = Ccf_ManStart( pGia, nFrameMax, nConfMax, nTimeMax, fVerbose ); // set runtime limit if ( nTimeMax ) sat_solver_set_runtime_limit( p->pSat, nTimeToStop ); // perform backward image computation for ( f = 0; f < nFrameMax; f++ ) { if ( fVerbose ) printf( "ITER %3d :\n", f ); // add to the mapping of nodes p->pFrames = (Gia_Man_t *)Gia_ManUnrollAdd( p->pUnr, f+1 ); // add SAT clauses Gia_ManCofExtendSolver( p ); // return output literal Lit = Gia_ManUnrollLastLit( p->pUnr ); // derives cofactors of the property literal till all states are blocked RetValue = Gia_ManCofGetReachable( p, Lit ); if ( RetValue ) break; // check the property output Gia_ManSetPhase( p->pFrames ); Gia_ManForEachPo( p->pFrames, pObj, i ) if ( pObj->fPhase ) { printf( "Property failed in frame %d.\n", f ); fFailed = 1; break; } if ( i < Gia_ManPoNum(p->pFrames) ) break; } // report the result if ( nTimeToStop && Abc_Clock() > nTimeToStop ) printf( "Runtime limit (%d sec) is reached after %d frames. ", nTimeMax, f ); else if ( f == nFrameMax ) printf( "Completed %d frames without converging. ", f ); else if ( RetValue == 1 ) printf( "Backward reachability converged after %d iterations. ", f-1 ); else if ( RetValue == -1 ) printf( "Conflict limit or timeout is reached after %d frames. ", f-1 ); Abc_PrintTime( 1, "Runtime", Abc_Clock() - clk ); if ( !fFailed && RetValue == 1 ) printf( "Property holds.\n" ); else if ( !fFailed ) printf( "Property is undecided.\n" ); // get the resulting AIG manager Gia_ManHashStop( p->pFrames ); pNew = p->pFrames; p->pFrames = NULL; Ccf_ManStop( p ); // cleanup // if ( fVerbose ) // Gia_ManPrintStats( pNew, 0 ); pNew = Gia_ManCleanup( pGia = pNew ); Gia_ManStop( pGia ); // if ( fVerbose ) // Gia_ManPrintStats( pNew, 0 ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaCSat.c000066400000000000000000001102421477524141600157460ustar00rootroot00000000000000/**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 //#define gia_assert(exp) ((void)0) //#define gia_assert(exp) (assert(exp)) //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Cbs_Par_t_ Cbs_Par_t; struct Cbs_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; }; typedef struct Cbs_Que_t_ Cbs_Que_t; struct Cbs_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 Cbs_Man_t_ Cbs_Man_t; struct Cbs_Man_t_ { Cbs_Par_t Pars; // parameters Gia_Man_t * pAig; // AIG manager Cbs_Que_t pProp; // propagation queue Cbs_Que_t pJust; // justification queue Cbs_Que_t pClauses; // clause queue Gia_Obj_t ** pIter; // iterator through clause vars Vec_Int_t * vLevReas; // levels and decisions 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 }; static inline int Cbs_VarIsAssigned( Gia_Obj_t * pVar ) { return pVar->fMark0; } static inline void Cbs_VarAssign( Gia_Obj_t * pVar ) { assert(!pVar->fMark0); pVar->fMark0 = 1; } static inline void Cbs_VarUnassign( Gia_Obj_t * pVar ) { assert(pVar->fMark0); pVar->fMark0 = 0; pVar->fMark1 = 0; pVar->Value = ~0; } static inline int Cbs_VarValue( Gia_Obj_t * pVar ) { assert(pVar->fMark0); return pVar->fMark1; } static inline void Cbs_VarSetValue( Gia_Obj_t * pVar, int v ) { assert(pVar->fMark0); pVar->fMark1 = v; } static inline int Cbs_VarIsJust( Gia_Obj_t * pVar ) { return Gia_ObjIsAnd(pVar) && !Cbs_VarIsAssigned(Gia_ObjFanin0(pVar)) && !Cbs_VarIsAssigned(Gia_ObjFanin1(pVar)); } static inline int Cbs_VarFanin0Value( Gia_Obj_t * pVar ) { return !Cbs_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (Cbs_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); } static inline int Cbs_VarFanin1Value( Gia_Obj_t * pVar ) { return !Cbs_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (Cbs_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); } static inline int Cbs_VarDecLevel( Cbs_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return Vec_IntEntry(p->vLevReas, 3*pVar->Value); } static inline Gia_Obj_t * Cbs_VarReason0( Cbs_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+1); } static inline Gia_Obj_t * Cbs_VarReason1( Cbs_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+2); } static inline int Cbs_ClauseDecLevel( Cbs_Man_t * p, int hClause ) { return Cbs_VarDecLevel( p, p->pClauses.pData[hClause] ); } #define Cbs_QueForEachEntry( Que, pObj, i ) \ for ( i = (Que).iHead; (i < (Que).iTail) && ((pObj) = (Que).pData[i]); i++ ) #define Cbs_ClauseForEachVar( p, hClause, pObj ) \ for ( (p)->pIter = (p)->pClauses.pData + hClause; (pObj = *pIter); (p)->pIter++ ) #define Cbs_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 Cbs_SetDefaultParams( Cbs_Par_t * pPars ) { memset( pPars, 0, sizeof(Cbs_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 } void Cbs_ManSetConflictNum( Cbs_Man_t * p, int Num ) { p->Pars.nBTLimit = Num; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cbs_Man_t * Cbs_ManAlloc( Gia_Man_t * pGia ) { Cbs_Man_t * p; p = ABC_CALLOC( Cbs_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; Cbs_SetDefaultParams( &p->Pars ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cbs_ManStop( Cbs_Man_t * p ) { Vec_IntFree( p->vLevReas ); Vec_IntFree( p->vModel ); Vec_PtrFree( p->vTemp ); 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 * Cbs_ReadModel( Cbs_Man_t * p ) { return p->vModel; } /**Function************************************************************* Synopsis [Returns 1 if the solver is out of limits.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs_ManCheckLimits( Cbs_Man_t * p ) { 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 Cbs_ManSaveModel( Cbs_Man_t * p, Vec_Int_t * vCex ) { Gia_Obj_t * pVar; int i; Vec_IntClear( vCex ); p->pProp.iHead = 0; Cbs_QueForEachEntry( p->pProp, pVar, i ) if ( Gia_ObjIsCi(pVar) ) // Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !Cbs_VarValue(pVar)) ); Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjCioId(pVar), !Cbs_VarValue(pVar)) ); } static inline void Cbs_ManSaveModelAll( Cbs_Man_t * p, Vec_Int_t * vCex ) { Gia_Obj_t * pVar; int i; Vec_IntClear( vCex ); p->pProp.iHead = 0; Cbs_QueForEachEntry( p->pProp, pVar, i ) Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !Cbs_VarValue(pVar)) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs_QueIsEmpty( Cbs_Que_t * p ) { return p->iHead == p->iTail; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs_QuePush( Cbs_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 Cbs_QueHasNode( Cbs_Que_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pTemp; int i; Cbs_QueForEachEntry( *p, pTemp, i ) if ( pTemp == pObj ) return 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs_QueStore( Cbs_Que_t * p, int * piHeadOld, int * piTailOld ) { int i; *piHeadOld = p->iHead; *piTailOld = p->iTail; for ( i = *piHeadOld; i < *piTailOld; i++ ) Cbs_QuePush( p, p->pData[i] ); p->iHead = *piTailOld; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs_QueRestore( Cbs_Que_t * p, int iHeadOld, int iTailOld ) { p->iHead = iHeadOld; p->iTail = iTailOld; } /**Function************************************************************* Synopsis [Finalized the clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs_QueFinish( Cbs_Que_t * p ) { int iHeadOld = p->iHead; assert( p->iHead < p->iTail ); Cbs_QuePush( p, NULL ); p->iHead = p->iTail; return iHeadOld; } /**Function************************************************************* Synopsis [Max number of fanins fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs_VarFaninFanoutMax( Cbs_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 * Cbs_ManDecideHighest( Cbs_Man_t * p ) { Gia_Obj_t * pObj, * pObjMax = NULL; int i; Cbs_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 * Cbs_ManDecideLowest( Cbs_Man_t * p ) { Gia_Obj_t * pObj, * pObjMin = NULL; int i; Cbs_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 * Cbs_ManDecideMaxFF( Cbs_Man_t * p ) { Gia_Obj_t * pObj, * pObjMax = NULL; int i, iMaxFF = 0, iCurFF; assert( p->pAig->pRefs != NULL ); Cbs_QueForEachEntry( p->pJust, pObj, i ) { iCurFF = Cbs_VarFaninFanoutMax( p, pObj ); assert( iCurFF > 0 ); if ( iMaxFF < iCurFF ) { iMaxFF = iCurFF; pObjMax = pObj; } } return pObjMax; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs_ManCancelUntil( Cbs_Man_t * p, int iBound ) { Gia_Obj_t * pVar; int i; assert( iBound <= p->pProp.iTail ); p->pProp.iHead = iBound; Cbs_QueForEachEntry( p->pProp, pVar, i ) Cbs_VarUnassign( 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 Cbs_ManAssign( Cbs_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( !Cbs_VarIsAssigned(pObjR) ); Cbs_VarAssign( pObjR ); Cbs_VarSetValue( pObjR, !Gia_IsComplement(pObj) ); assert( pObjR->Value == ~0 ); pObjR->Value = p->pProp.iTail; Cbs_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 ); // s_Counter++; // s_Counter = Abc_MaxIntInt( s_Counter, Vec_IntSize(p->vLevReas)/3 ); } /**Function************************************************************* Synopsis [Returns clause size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs_ManClauseSize( Cbs_Man_t * p, int hClause ) { Cbs_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 Cbs_ManPrintClause( Cbs_Man_t * p, int Level, int hClause ) { Cbs_Que_t * pQue = &(p->pClauses); Gia_Obj_t * pObj; int i; assert( Cbs_QueIsEmpty( pQue ) ); printf( "Level %2d : ", Level ); for ( i = hClause; (pObj = pQue->pData[i]); i++ ) printf( "%d=%d(%d) ", Gia_ObjId(p->pAig, pObj), Cbs_VarValue(pObj), Cbs_VarDecLevel(p, pObj) ); printf( "\n" ); } /**Function************************************************************* Synopsis [Prints conflict clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs_ManPrintClauseNew( Cbs_Man_t * p, int Level, int hClause ) { Cbs_Que_t * pQue = &(p->pClauses); Gia_Obj_t * pObj; int i; assert( Cbs_QueIsEmpty( pQue ) ); printf( "Level %2d : ", Level ); for ( i = hClause; (pObj = pQue->pData[i]); i++ ) printf( "%c%d ", Cbs_VarValue(pObj)? '+':'-', Gia_ObjId(p->pAig, pObj) ); printf( "\n" ); } /**Function************************************************************* Synopsis [Returns conflict clause.] Description [Performs conflict analysis.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs_ManDeriveReason( Cbs_Man_t * p, int Level ) { Cbs_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 = Cbs_VarDecLevel( p, pObj ); if ( iLitLevel < Level ) { pQue->pData[k++] = pObj; continue; } assert( iLitLevel == Level ); pReason = Cbs_VarReason0( p, pObj ); if ( pReason == pObj ) // no reason { //assert( pQue->pData[pQue->iHead] == NULL ); pQue->pData[pQue->iHead] = pObj; continue; } Cbs_QuePush( pQue, pReason ); pReason = Cbs_VarReason1( p, pObj ); if ( pReason != pObj ) // second reason Cbs_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 Cbs_ManAnalyze( Cbs_Man_t * p, int Level, Gia_Obj_t * pVar, Gia_Obj_t * pFan0, Gia_Obj_t * pFan1 ) { Cbs_Que_t * pQue = &(p->pClauses); assert( Cbs_VarIsAssigned(pVar) ); assert( Cbs_VarIsAssigned(pFan0) ); assert( pFan1 == NULL || Cbs_VarIsAssigned(pFan1) ); assert( Cbs_QueIsEmpty( pQue ) ); Cbs_QuePush( pQue, NULL ); Cbs_QuePush( pQue, pVar ); Cbs_QuePush( pQue, pFan0 ); if ( pFan1 ) Cbs_QuePush( pQue, pFan1 ); Cbs_ManDeriveReason( p, Level ); return Cbs_QueFinish( pQue ); } /**Function************************************************************* Synopsis [Performs resolution of two clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs_ManResolve( Cbs_Man_t * p, int Level, int hClause0, int hClause1 ) { Cbs_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( Cbs_QueIsEmpty( pQue ) ); Cbs_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; Cbs_QuePush( pQue, pObj ); LevelCur = Cbs_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; Cbs_QuePush( pQue, pObj ); LevelCur = Cbs_VarDecLevel( p, pObj ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } for ( i = pQue->iHead + 1; i < pQue->iTail; i++ ) pQue->pData[i]->fMark0 = 1; Cbs_ManDeriveReason( p, LevelMax ); return Cbs_QueFinish( pQue ); } /**Function************************************************************* Synopsis [Propagates a variable.] Description [Returns clause handle if conflict; 0 if no conflict.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs_ManPropagateOne( Cbs_Man_t * p, Gia_Obj_t * pVar, int Level ) { int Value0, Value1; assert( !Gia_IsComplement(pVar) ); assert( Cbs_VarIsAssigned(pVar) ); if ( Gia_ObjIsCi(pVar) ) return 0; assert( Gia_ObjIsAnd(pVar) ); Value0 = Cbs_VarFanin0Value(pVar); Value1 = Cbs_VarFanin1Value(pVar); if ( Cbs_VarValue(pVar) ) { // value is 1 if ( Value0 == 0 || Value1 == 0 ) // one is 0 { if ( Value0 == 0 && Value1 != 0 ) return Cbs_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), NULL ); if ( Value0 != 0 && Value1 == 0 ) return Cbs_ManAnalyze( p, Level, pVar, Gia_ObjFanin1(pVar), NULL ); assert( Value0 == 0 && Value1 == 0 ); return Cbs_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); } if ( Value0 == 2 ) // first is unassigned Cbs_ManAssign( p, Gia_ObjChild0(pVar), Level, pVar, NULL ); if ( Value1 == 2 ) // first is unassigned Cbs_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 Cbs_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); if ( Value0 == 1 || Value1 == 1 ) // one is 1 { if ( Value0 == 2 ) // first is unassigned Cbs_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) ); if ( Value1 == 2 ) // second is unassigned Cbs_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)), Level, pVar, Gia_ObjFanin0(pVar) ); return 0; } assert( Cbs_VarIsJust(pVar) ); assert( !Cbs_QueHasNode( &p->pJust, pVar ) ); Cbs_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 Cbs_ManPropagateTwo( Cbs_Man_t * p, Gia_Obj_t * pVar, int Level ) { int Value0, Value1; assert( !Gia_IsComplement(pVar) ); assert( Gia_ObjIsAnd(pVar) ); assert( Cbs_VarIsAssigned(pVar) ); assert( !Cbs_VarValue(pVar) ); Value0 = Cbs_VarFanin0Value(pVar); Value1 = Cbs_VarFanin1Value(pVar); // value is 0 if ( Value0 == 0 || Value1 == 0 ) // one is 0 return 0; if ( Value0 == 1 && Value1 == 1 ) // both are 1 return Cbs_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); assert( Value0 == 1 || Value1 == 1 ); if ( Value0 == 2 ) // first is unassigned Cbs_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) ); if ( Value1 == 2 ) // first is unassigned Cbs_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 Cbs_ManPropagate( Cbs_Man_t * p, int Level ) { int hClause; Gia_Obj_t * pVar; int i, k; while ( 1 ) { Cbs_QueForEachEntry( p->pProp, pVar, i ) { if ( (hClause = Cbs_ManPropagateOne( p, pVar, Level )) ) return hClause; } p->pProp.iHead = p->pProp.iTail; k = p->pJust.iHead; Cbs_QueForEachEntry( p->pJust, pVar, i ) { if ( Cbs_VarIsJust( pVar ) ) p->pJust.pData[k++] = pVar; else if ( (hClause = Cbs_ManPropagateTwo( p, pVar, Level )) ) return hClause; } 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 Cbs_ManSolve_rec( Cbs_Man_t * p, int Level ) { Cbs_Que_t * pQue = &(p->pClauses); Gia_Obj_t * pVar = NULL, * pDecVar; int hClause, hLearn0, hLearn1; int iPropHead, iJustHead, iJustTail; // propagate assignments assert( !Cbs_QueIsEmpty(&p->pProp) ); if ( (hClause = Cbs_ManPropagate( p, Level )) ) return hClause; // check for satisfying assignment assert( Cbs_QueIsEmpty(&p->pProp) ); if ( Cbs_QueIsEmpty(&p->pJust) ) return 0; // quit using resource limits p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); if ( Cbs_ManCheckLimits( p ) ) return 0; // remember the state before branching iPropHead = p->pProp.iHead; Cbs_QueStore( &p->pJust, &iJustHead, &iJustTail ); // find the decision variable if ( p->Pars.fUseHighest ) pVar = Cbs_ManDecideHighest( p ); else if ( p->Pars.fUseLowest ) pVar = Cbs_ManDecideLowest( p ); else if ( p->Pars.fUseMaxFF ) pVar = Cbs_ManDecideMaxFF( p ); else assert( 0 ); assert( Cbs_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 Cbs_ManAssign( p, pDecVar, Level+1, NULL, NULL ); if ( !(hLearn0 = Cbs_ManSolve_rec( p, Level+1 )) ) return 0; if ( pQue->pData[hLearn0] != Gia_Regular(pDecVar) ) return hLearn0; Cbs_ManCancelUntil( p, iPropHead ); Cbs_QueRestore( &p->pJust, iJustHead, iJustTail ); // decide on second fanin Cbs_ManAssign( p, Gia_Not(pDecVar), Level+1, NULL, NULL ); if ( !(hLearn1 = Cbs_ManSolve_rec( p, Level+1 )) ) return 0; if ( pQue->pData[hLearn1] != Gia_Regular(pDecVar) ) return hLearn1; hClause = Cbs_ManResolve( p, Level, hLearn0, hLearn1 ); // Cbs_ManPrintClauseNew( p, Level, hClause ); // if ( Level > Cbs_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 Cbs_ManSolve( Cbs_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; Cbs_ManAssign( p, pObj, 0, NULL, NULL ); if ( !Cbs_ManSolve_rec(p, 0) && !Cbs_ManCheckLimits(p) ) Cbs_ManSaveModel( p, p->vModel ); else RetValue = 1; Cbs_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 ( Cbs_ManCheckLimits( p ) ) RetValue = -1; // printf( "%d ", s_Counter ); return RetValue; } int Cbs_ManSolve2( Cbs_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ) { 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; Cbs_ManAssign( p, pObj, 0, NULL, NULL ); if ( pObj2 ) Cbs_ManAssign( p, pObj2, 0, NULL, NULL ); if ( !Cbs_ManSolve_rec(p, 0) && !Cbs_ManCheckLimits(p) ) Cbs_ManSaveModelAll( p, p->vModel ); else RetValue = 1; Cbs_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 ( Cbs_ManCheckLimits( p ) ) RetValue = -1; // printf( "%d ", s_Counter ); return RetValue; } /**Function************************************************************* Synopsis [Prints statistics of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cbs_ManSatPrintStats( Cbs_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 * 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 ); Cbs_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 = Cbs_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 = Cbs_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 = Cbs_ManSolve( p, Gia_ObjChild0(pRoot) ); // printf( "\n" ); /* if ( status == -1 ) { p->Pars.fUseHighest = 0; p->Pars.fUseLowest = 1; status = Cbs_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 ) Cbs_ManSatPrintStats( p ); // printf( "RecCalls = %8d. RecClause = %8d. RecNonChro = %8d.\n", p->nRecCall, p->nRecClause, p->nRecNonChro ); Cbs_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 abc-0.52/src/aig/gia/giaCSat2.c000066400000000000000000001675311477524141600160450ustar00rootroot00000000000000/**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 //#define gia_assert(exp) ((void)0) //#define gia_assert(exp) (assert(exp)) //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Cbs2_Par_t_ Cbs2_Par_t; struct Cbs2_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 int fUseFanout; // use node with the largest fanin fanout // other int fVerbose; }; typedef struct Cbs2_Que_t_ Cbs2_Que_t; struct Cbs2_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 Cbs2_Man_t_ Cbs2_Man_t; struct Cbs2_Man_t_ { Cbs2_Par_t Pars; // parameters Gia_Man_t * pAig; // AIG manager Cbs2_Que_t pProp; // propagation queue Cbs2_Que_t pJust; // justification queue Cbs2_Que_t pClauses; // clause queue Vec_Int_t * vModel; // satisfying assignment Vec_Int_t * vTemp; // temporary storage // internal data Vec_Str_t vAssign; Vec_Str_t vMark; Vec_Int_t vLevReason; Vec_Int_t vWatches; Vec_Int_t vWatchUpds; Vec_Int_t vFanoutN; Vec_Int_t vFanout0; Vec_Int_t vActivity; Vec_Int_t vActStore; Vec_Int_t vJStore; // 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 timeSatUnsat; // unsat abctime timeSatSat; // sat abctime timeSatUndec; // undecided abctime timeTotal; // total runtime // other statistics int nPropCalls[3]; int nFails[2]; int nClauseConf; }; static inline int Cbs2_VarUnused( Cbs2_Man_t * p, int iVar ) { return Vec_IntEntry(&p->vLevReason, 3*iVar) == -1; } static inline void Cbs2_VarSetUnused( Cbs2_Man_t * p, int iVar ) { Vec_IntWriteEntry(&p->vLevReason, 3*iVar, -1); } /* static inline int Cbs2_VarMark0( Cbs2_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar); } static inline void Cbs2_VarSetMark0( Cbs2_Man_t * p, int iVar, int Value ) { Vec_StrWriteEntry(&p->vAssign, iVar, (char)Value); } static inline int Cbs2_VarMark1( Cbs2_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vValue, iVar); } static inline void Cbs2_VarSetMark1( Cbs2_Man_t * p, int iVar, int Value ) { Vec_StrWriteEntry(&p->vValue, iVar, (char)Value); } static inline int Cbs2_VarIsAssigned( Cbs2_Man_t * p, int iVar ) { return Cbs2_VarMark0(p, iVar); } static inline void Cbs2_VarAssign( Cbs2_Man_t * p, int iVar ) { assert(!Cbs2_VarIsAssigned(p, iVar)); Cbs2_VarSetMark0(p, iVar, 1); } static inline void Cbs2_VarUnassign( Cbs2_Man_t * p, int iVar ) { assert( Cbs2_VarIsAssigned(p, iVar)); Cbs2_VarSetMark0(p, iVar, 0); Cbs2_VarSetUnused(p, iVar); } static inline int Cbs2_VarValue( Cbs2_Man_t * p, int iVar ) { assert( Cbs2_VarIsAssigned(p, iVar)); return Cbs2_VarMark1(p, iVar); } static inline void Cbs2_VarSetValue( Cbs2_Man_t * p, int iVar, int v ) { assert( Cbs2_VarIsAssigned(p, iVar)); Cbs2_VarSetMark1(p, iVar, v); } static inline int Cbs2_VarIsJust( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Gia_ObjIsAnd(pVar) && !Cbs2_VarIsAssigned(p, Gia_ObjFaninId0(pVar, iVar)) && !Cbs2_VarIsAssigned(p, Gia_ObjFaninId1(pVar, iVar)); } static inline int Cbs2_VarFanin0Value( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Cbs2_VarIsAssigned(p, Gia_ObjFaninId0(pVar, iVar)) ? (Cbs2_VarValue(p, Gia_ObjFaninId0(pVar, iVar)) ^ Gia_ObjFaninC0(pVar)) : 2; } static inline int Cbs2_VarFanin1Value( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Cbs2_VarIsAssigned(p, Gia_ObjFaninId1(pVar, iVar)) ? (Cbs2_VarValue(p, Gia_ObjFaninId1(pVar, iVar)) ^ Gia_ObjFaninC1(pVar)) : 2; } */ static inline int Cbs2_VarMark0( Cbs2_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vMark, iVar); } static inline void Cbs2_VarSetMark0( Cbs2_Man_t * p, int iVar, int Value ) { Vec_StrWriteEntry(&p->vMark, iVar, (char)Value); } //static inline int Cbs2_VarMark0( Cbs2_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar) >= 2; } //static inline void Cbs2_VarSetMark0( Cbs2_Man_t * p, int iVar, int Value ) { Vec_StrWriteEntry(&p->vAssign, iVar, (char)(2^Vec_StrEntry(&p->vAssign, iVar))); } static inline int Cbs2_VarIsAssigned( Cbs2_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar) < 2; } static inline void Cbs2_VarUnassign( Cbs2_Man_t * p, int iVar ) { assert( Cbs2_VarIsAssigned(p, iVar)); Vec_StrWriteEntry(&p->vAssign, iVar, (char)(2+Vec_StrEntry(&p->vAssign, iVar))); Cbs2_VarSetUnused(p, iVar); } static inline int Cbs2_VarValue( Cbs2_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar); } static inline void Cbs2_VarSetValue( Cbs2_Man_t * p, int iVar, int v ) { assert( !Cbs2_VarIsAssigned(p, iVar)); Vec_StrWriteEntry(&p->vAssign, iVar, (char)v); } static inline int Cbs2_VarIsJust( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Gia_ObjIsAnd(pVar) && !Cbs2_VarIsAssigned(p, Gia_ObjFaninId0(pVar, iVar)) && !Cbs2_VarIsAssigned(p, Gia_ObjFaninId1(pVar, iVar)); } static inline int Cbs2_VarFanin0Value( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Cbs2_VarValue(p, Gia_ObjFaninId0(pVar, iVar)) ^ Gia_ObjFaninC0(pVar); } static inline int Cbs2_VarFanin1Value( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Cbs2_VarValue(p, Gia_ObjFaninId1(pVar, iVar)) ^ Gia_ObjFaninC1(pVar); } static inline int Cbs2_VarDecLevel( Cbs2_Man_t * p, int iVar ) { assert( !Cbs2_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar); } static inline int Cbs2_VarReason0( Cbs2_Man_t * p, int iVar ) { assert( !Cbs2_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar+1); } static inline int Cbs2_VarReason1( Cbs2_Man_t * p, int iVar ) { assert( !Cbs2_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar+2); } static inline int * Cbs2_VarReasonP( Cbs2_Man_t * p, int iVar ) { assert( !Cbs2_VarUnused(p, iVar) ); return Vec_IntEntryP(&p->vLevReason, 3*iVar+1); } //static inline int Cbs2_ClauseDecLevel( Cbs2_Man_t * p, int hClause ) { return Cbs2_VarDecLevel( p, p->pClauses.pData[hClause] ); } static inline int Cbs2_ClauseSize( Cbs2_Man_t * p, int hClause ) { return p->pClauses.pData[hClause]; } static inline int * Cbs2_ClauseLits( Cbs2_Man_t * p, int hClause ) { return p->pClauses.pData+hClause+1; } static inline int Cbs2_ClauseLit( Cbs2_Man_t * p, int hClause, int i ) { return p->pClauses.pData[hClause+1+i]; } static inline int * Cbs2_ClauseNext1p( Cbs2_Man_t * p, int hClause ) { return p->pClauses.pData+hClause+Cbs2_ClauseSize(p, hClause)+2; } static inline void Cbs2_ClauseSetSize( Cbs2_Man_t * p, int hClause, int x ) { p->pClauses.pData[hClause] = x; } static inline void Cbs2_ClauseSetLit( Cbs2_Man_t * p, int hClause, int i, int x ) { p->pClauses.pData[hClause+i+1] = x; } static inline void Cbs2_ClauseSetNext( Cbs2_Man_t * p, int hClause, int n, int x ){ p->pClauses.pData[hClause+Cbs2_ClauseSize(p, hClause)+1+n] = x; } #define Cbs2_QueForEachEntry( Que, iObj, i ) \ for ( i = (Que).iHead; (i < (Que).iTail) && ((iObj) = (Que).pData[i]); i++ ) #define Cbs2_ClauseForEachEntry( p, hClause, iObj, i ) \ for ( i = 1; i <= Cbs2_ClauseSize(p, hClause) && (iObj = (p)->pClauses.pData[hClause+i]); i++ ) #define Cbs2_ClauseForEachEntry1( p, hClause, iObj, i ) \ for ( i = 2; i <= Cbs2_ClauseSize(p, hClause) && (iObj = (p)->pClauses.pData[hClause+i]); i++ ) #define Cbs2_ObjForEachFanout( p, iObj, iFanLit ) \ for ( iFanLit = Vec_IntEntry(&p->vFanout0, iObj); iFanLit; iFanLit = Vec_IntEntry(&p->vFanoutN, iFanLit) ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Sets default values of the parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cbs2_SetDefaultParams( Cbs2_Par_t * pPars ) { memset( pPars, 0, sizeof(Cbs2_Par_t) ); pPars->nBTLimit = 1000; // limit on the number of conflicts pPars->nJustLimit = 500; // 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->fUseFanout = 1; pPars->fVerbose = 1; // print detailed statistics } void Cbs2_ManSetConflictNum( Cbs2_Man_t * p, int Num ) { p->Pars.nBTLimit = Num; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cbs2_Man_t * Cbs2_ManAlloc( Gia_Man_t * pGia ) { Cbs2_Man_t * p; p = ABC_CALLOC( Cbs2_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; Cbs2_SetDefaultParams( &p->Pars ); Vec_StrFill( &p->vAssign, Gia_ManObjNum(pGia), 2 ); Vec_StrFill( &p->vMark, Gia_ManObjNum(pGia), 0 ); Vec_IntFill( &p->vLevReason, 3*Gia_ManObjNum(pGia), -1 ); Vec_IntFill( &p->vWatches, 2*Gia_ManObjNum(pGia), 0 ); Vec_IntFill( &p->vFanout0, Gia_ManObjNum(pGia), 0 ); Vec_IntFill( &p->vFanoutN, 2*Gia_ManObjNum(pGia), 0 ); Vec_IntFill( &p->vActivity, Gia_ManObjNum(pGia), 0 ); Vec_IntGrow( &p->vActStore, 1000 ); Vec_IntGrow( &p->vJStore, 1000 ); Vec_IntGrow( &p->vWatchUpds, 1000 ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cbs2_ManStop( Cbs2_Man_t * p ) { Vec_StrErase( &p->vAssign ); Vec_StrErase( &p->vMark ); Vec_IntErase( &p->vLevReason ); Vec_IntErase( &p->vWatches ); Vec_IntErase( &p->vFanout0 ); Vec_IntErase( &p->vFanoutN ); Vec_IntErase( &p->vActivity ); Vec_IntErase( &p->vActStore ); Vec_IntErase( &p->vJStore ); 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 ); } /**Function************************************************************* Synopsis [Returns satisfying assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Cbs2_ReadModel( Cbs2_Man_t * p ) { return p->vModel; } /**Function************************************************************* Synopsis [Returns 1 if the solver is out of limits.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs2_ManCheckLimits( Cbs2_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 Cbs2_ManSaveModel( Cbs2_Man_t * p, Vec_Int_t * vCex ) { int i, iLit; Vec_IntClear( vCex ); p->pProp.iHead = 0; Cbs2_QueForEachEntry( p->pProp, iLit, i ) { int iVar = Abc_Lit2Var(iLit); if ( Gia_ObjIsCi(Gia_ManObj(p->pAig, iVar)) ) Vec_IntPush( vCex, Abc_Var2Lit(Gia_ManIdToCioId(p->pAig, iVar), !Cbs2_VarValue(p, iVar)) ); } } static inline void Cbs2_ManSaveModelAll( Cbs2_Man_t * p, Vec_Int_t * vCex ) { int i, iLit; Vec_IntClear( vCex ); p->pProp.iHead = 0; Cbs2_QueForEachEntry( p->pProp, iLit, i ) { int iVar = Abc_Lit2Var(iLit); Vec_IntPush( vCex, Abc_Var2Lit(iVar, !Cbs2_VarValue(p, iVar)) ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs2_QueIsEmpty( Cbs2_Que_t * p ) { return p->iHead == p->iTail; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs2_QuePush( Cbs2_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 Cbs2_QueGrow( Cbs2_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 Cbs2_QueHasNode( Cbs2_Que_t * p, int iObj ) { int i, iTemp; Cbs2_QueForEachEntry( *p, iTemp, i ) if ( iTemp == iObj ) return 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs2_QueStore( Cbs2_Que_t * p, int * piHeadOld, int * piTailOld ) { int i; *piHeadOld = p->iHead; *piTailOld = p->iTail; for ( i = *piHeadOld; i < *piTailOld; i++ ) Cbs2_QuePush( p, p->pData[i] ); p->iHead = *piTailOld; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs2_QueRestore( Cbs2_Que_t * p, int iHeadOld, int iTailOld ) { p->iHead = iHeadOld; p->iTail = iTailOld; } /**Function************************************************************* Synopsis [Max number of fanins fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs2_VarFaninFanoutMax( Cbs2_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 int Cbs2_ManDecideHighest( Cbs2_Man_t * p ) { int i, iObj, iObjMax = 0; Cbs2_QueForEachEntry( p->pJust, iObj, i ) if ( iObjMax == 0 || iObjMax < iObj ) iObjMax = iObj; return iObjMax; } /**Function************************************************************* Synopsis [Find variable with the lowest ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_Obj_t * Cbs2_ManDecideLowest( Cbs2_Man_t * p ) { int i, iObj, iObjMin = 0; Cbs2_QueForEachEntry( p->pJust, iObj, i ) if ( iObjMin == 0 || iObjMin > iObj ) iObjMin = iObj; return Gia_ManObj(p->pAig, iObjMin); } /**Function************************************************************* Synopsis [Find variable with the maximum number of fanin fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_Obj_t * Cbs2_ManDecideMaxFF( Cbs2_Man_t * p ) { Gia_Obj_t * pObj, * pObjMax = NULL; int i, iMaxFF = 0, iCurFF, iObj; assert( p->pAig->pRefs != NULL ); Cbs2_QueForEachEntry( p->pJust, iObj, i ) { pObj = Gia_ManObj(p->pAig, iObj); iCurFF = Cbs2_VarFaninFanoutMax( p, pObj ); assert( iCurFF > 0 ); if ( iMaxFF < iCurFF ) { iMaxFF = iCurFF; pObjMax = pObj; } } return pObjMax; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs2_ManCancelUntil( Cbs2_Man_t * p, int iBound ) { int i, iLit; assert( iBound <= p->pProp.iTail ); p->pProp.iHead = iBound; Cbs2_QueForEachEntry( p->pProp, iLit, i ) Cbs2_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 Cbs2_ManAssign( Cbs2_Man_t * p, int iLit, int Level, int iRes0, int iRes1 ) { int iObj = Abc_Lit2Var(iLit); assert( Cbs2_VarUnused(p, iObj) ); assert( !Cbs2_VarIsAssigned(p, iObj) ); //Cbs2_VarAssign( p, iObj ); Cbs2_VarSetValue( p, iObj, !Abc_LitIsCompl(iLit) ); Cbs2_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 Cbs2_ManPrintClause( Cbs2_Man_t * p, int Level, int hClause ) { int i, iLit; assert( Cbs2_QueIsEmpty( &p->pClauses ) ); printf( "Level %2d : ", Level ); Cbs2_ClauseForEachEntry( p, hClause, iLit, i ) printf( "%c%d ", Abc_LitIsCompl(iLit) ? '-':'+', Abc_Lit2Var(iLit) ); // printf( "%d=%d(%d) ", iObj, Cbs2_VarValue(p, Abc_Lit2Var(iLit)), Cbs2_VarDecLevel(p, Abc_Lit2Var(iLit)) ); printf( "\n" ); } static inline void Cbs2_ManPrintCube( Cbs2_Man_t * p, int Level, int hClause ) { int i, iObj; assert( Cbs2_QueIsEmpty( &p->pClauses ) ); printf( "Level %2d : ", Level ); Cbs2_ClauseForEachEntry( p, hClause, iObj, i ) printf( "%c%d ", Cbs2_VarValue(p, iObj)? '+':'-', iObj ); printf( "\n" ); } static inline void Cbs2_ManBumpClause( Cbs2_Man_t * p, int hClause ) { int i, iObj; assert( Cbs2_QueIsEmpty( &p->pClauses ) ); Cbs2_ClauseForEachEntry( p, hClause, iObj, i ) { //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 ) // Vec_IntPush( &p->vActStore, iObj ); //Vec_IntAddToEntry( &p->vActivity, iObj, 1 ); } } static inline void Cbs2_ManBumpClean( Cbs2_Man_t * p ) { int i, iObj; Vec_IntForEachEntry( &p->vActStore, iObj, i ) Vec_IntWriteEntry( &p->vActivity, iObj, 0 ); } /**Function************************************************************* Synopsis [Finalized the clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs2_ManCleanWatch( Cbs2_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 Cbs2_ManWatchClause( Cbs2_Man_t * p, int hClause, int Lit ) { int * pLits = Cbs2_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] ); Cbs2_ClauseSetNext( p, hClause, Lit == pLits[1], *pPlace ); *pPlace = hClause; } static inline int Cbs2_QueFinish( Cbs2_Man_t * p, int Level ) { Cbs2_Que_t * pQue = &(p->pClauses); int i, iObj, hClauseC, hClause = pQue->iHead, Size = pQue->iTail - pQue->iHead - 1; assert( pQue->iHead+1 < pQue->iTail ); Cbs2_ClauseSetSize( p, pQue->iHead, Size ); hClauseC = pQue->iHead = pQue->iTail; //printf( "Adding cube: " ); Cbs2_ManPrintCube(p, Level, hClause); if ( Size == 1 ) return hClause; // create watched clause pQue->iHead = hClause; Cbs2_QueForEachEntry( p->pClauses, iObj, i ) { if ( i == hClauseC ) break; else if ( i == hClause ) // nlits Cbs2_QuePush( pQue, iObj ); else // literals Cbs2_QuePush( pQue, Abc_Var2Lit(iObj, Cbs2_VarValue(p, iObj)) ); // complement } Cbs2_QuePush( pQue, 0 ); // next0 Cbs2_QuePush( pQue, 0 ); // next1 pQue->iHead = pQue->iTail; Cbs2_ManWatchClause( p, hClauseC, Cbs2_ClauseLit(p, hClauseC, 0) ); Cbs2_ManWatchClause( p, hClauseC, Cbs2_ClauseLit(p, hClauseC, 1) ); //printf( "Adding clause %d: ", hClauseC ); Cbs2_ManPrintClause(p, Level, hClauseC); return hClause; } /**Function************************************************************* Synopsis [Returns conflict clause.] Description [Performs conflict analysis.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs2_ManDeriveReason( Cbs2_Man_t * p, int Level ) { Cbs2_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( !Cbs2_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 ( Cbs2_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 Cbs2_VarSetMark0(p, iObj, 1); Vec_IntPush( p->vTemp, iObj ); // check decision level iLitLevel = Cbs2_VarDecLevel( p, iObj ); if ( iLitLevel < Level ) { pQue->pData[k++] = iObj; continue; } assert( iLitLevel == Level ); pReason = Cbs2_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 { Cbs2_QuePush( pQue, pReason[0] ); if ( pReason[1] ) Cbs2_QuePush( pQue, pReason[1] ); } else // clause reason { int i, * pLits, nLits = Cbs2_ClauseSize( p, pReason[1] ); assert( pReason[1] ); Cbs2_QueGrow( pQue, nLits ); pLits = Cbs2_ClauseLits( p, pReason[1] ); assert( iObj == Abc_Lit2Var(pLits[0]) ); for ( i = 1; i < nLits; i++ ) Cbs2_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 ) Cbs2_VarSetMark0(p, iObj, 0); return Cbs2_QueFinish( p, Level ); } static inline int Cbs2_ManAnalyze( Cbs2_Man_t * p, int Level, int iVar, int iFan0, int iFan1 ) { Cbs2_Que_t * pQue = &(p->pClauses); assert( Cbs2_VarIsAssigned(p, iVar) ); assert( Cbs2_QueIsEmpty( pQue ) ); Cbs2_QuePush( pQue, 0 ); Cbs2_QuePush( pQue, 0 ); if ( iFan0 ) // circuit conflict { assert( Cbs2_VarIsAssigned(p, iFan0) ); assert( iFan1 == 0 || Cbs2_VarIsAssigned(p, iFan1) ); Cbs2_QuePush( pQue, iVar ); Cbs2_QuePush( pQue, iFan0 ); if ( iFan1 ) Cbs2_QuePush( pQue, iFan1 ); } else // clause conflict { int i, * pLits, nLits = Cbs2_ClauseSize( p, iFan1 ); assert( iFan1 ); Cbs2_QueGrow( pQue, nLits ); pLits = Cbs2_ClauseLits( p, iFan1 ); assert( iVar == Abc_Lit2Var(pLits[0]) ); assert( Cbs2_VarValue(p, iVar) == Abc_LitIsCompl(pLits[0]) ); for ( i = 0; i < nLits; i++ ) Cbs2_QuePush( pQue, Abc_Lit2Var(pLits[i]) ); } return Cbs2_ManDeriveReason( p, Level ); } /**Function************************************************************* Synopsis [Propagate one assignment.] Description [Returns handle of the conflict clause, if conflict occurs.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs2_ManPropagateClauses( Cbs2_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 = Cbs2_ClauseSize( p, Cur ); int * pLits = Cbs2_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 ( Cbs2_VarValue(p, Abc_Lit2Var(pLits[0])) == !Abc_LitIsCompl(pLits[0]) ) { //ppPrev = &pCur->pNext1; pPrev = Cbs2_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 ( Cbs2_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 = *Cbs2_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] ); Cbs2_ManWatchClause( p, Cur, Cbs2_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 = Cbs2_VarValue(p, Abc_Lit2Var(pLits[0])); if ( Value >= 2 ) // unassigned { Cbs2_ManAssign( p, pLits[0], Level, 0, Cur ); pPrev = Cbs2_ClauseNext1p(p, Cur); continue; } // conflict detected - return the conflict clause //return pCur; if ( Value == Abc_LitIsCompl(pLits[0]) ) { p->nClauseConf++; return Cbs2_ManAnalyze( p, Level, Abc_Lit2Var(pLits[0]), 0, Cur ); } } return 0; } /**Function************************************************************* Synopsis [Performs resolution of two clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs2_ManResolve( Cbs2_Man_t * p, int Level, int hClause0, int hClause1 ) { Cbs2_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] ); //Cbs2_ClauseForEachEntry1( p, hClause0, iObj, i ) // assert( !Cbs2_VarMark0(p, iObj) ); //Cbs2_ClauseForEachEntry1( p, hClause1, iObj, i ) // assert( !Cbs2_VarMark0(p, iObj) ); assert( Cbs2_QueIsEmpty( pQue ) ); Cbs2_QuePush( pQue, 0 ); Cbs2_QuePush( pQue, 0 ); // for ( i = hClause0 + 1; (iObj = pQue->pData[i]); i++ ) Cbs2_ClauseForEachEntry1( p, hClause0, iObj, i ) { if ( Cbs2_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 Cbs2_VarSetMark0(p, iObj, 1); Cbs2_QuePush( pQue, iObj ); LevelCur = Cbs2_VarDecLevel( p, iObj ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } // for ( i = hClause1 + 1; (iObj = pQue->pData[i]); i++ ) Cbs2_ClauseForEachEntry1( p, hClause1, iObj, i ) { if ( Cbs2_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 Cbs2_VarSetMark0(p, iObj, 1); Cbs2_QuePush( pQue, iObj ); LevelCur = Cbs2_VarDecLevel( p, iObj ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } for ( i = pQue->iHead + 2; i < pQue->iTail; i++ ) Cbs2_VarSetMark0(p, pQue->pData[i], 0); return Cbs2_ManDeriveReason( p, LevelMax ); } /**Function************************************************************* Synopsis [Propagates a variable.] Description [Returns clause handle if conflict; 0 if no conflict.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs2_ManPropagateOne( Cbs2_Man_t * p, int iVar, int Level ) { Gia_Obj_t * pVar = Gia_ManObj( p->pAig, iVar ); int Value0, Value1; assert( !Gia_IsComplement(pVar) ); assert( Cbs2_VarIsAssigned(p, iVar) ); if ( Gia_ObjIsCi(pVar) ) return 0; p->nPropCalls[0]++; assert( Gia_ObjIsAnd(pVar) ); Value0 = Cbs2_VarFanin0Value(p, pVar, iVar); Value1 = Cbs2_VarFanin1Value(p, pVar, iVar); if ( Cbs2_VarValue(p, iVar) == 1 ) { // value is 1 if ( Value0 == 0 || Value1 == 0 ) // one is 0 { if ( Value0 == 0 && Value1 != 0 ) return Cbs2_ManAnalyze( p, Level, iVar, Gia_ObjFaninId0(pVar, iVar), 0 ); if ( Value0 != 0 && Value1 == 0 ) return Cbs2_ManAnalyze( p, Level, iVar, Gia_ObjFaninId1(pVar, iVar), 0 ); assert( Value0 == 0 && Value1 == 0 ); return Cbs2_ManAnalyze( p, Level, iVar, Gia_ObjFaninId0(pVar, iVar), Gia_ObjFaninId1(pVar, iVar) ); } if ( Value0 >= 2 ) // first is unassigned Cbs2_ManAssign( p, Gia_ObjFaninLit0(pVar, iVar), Level, iVar, 0 ); if ( Value1 >= 2 ) // first is unassigned Cbs2_ManAssign( p, Gia_ObjFaninLit1(pVar, iVar), Level, iVar, 0 ); return 0; } // value is 0 if ( Value0 == 0 || Value1 == 0 ) // one is 0 return 0; if ( Value0 == 1 && Value1 == 1 ) // both are 1 return Cbs2_ManAnalyze( p, Level, iVar, Gia_ObjFaninId0(pVar, iVar), Gia_ObjFaninId1(pVar, iVar) ); if ( Value0 == 1 || Value1 == 1 ) // one is 1 { if ( Value0 >= 2 ) // first is unassigned Cbs2_ManAssign( p, Abc_LitNot(Gia_ObjFaninLit0(pVar, iVar)), Level, iVar, Gia_ObjFaninId1(pVar, iVar) ); if ( Value1 >= 2 ) // second is unassigned Cbs2_ManAssign( p, Abc_LitNot(Gia_ObjFaninLit1(pVar, iVar)), Level, iVar, Gia_ObjFaninId0(pVar, iVar) ); return 0; } assert( Cbs2_VarIsJust(p, pVar, iVar) ); //assert( !Cbs2_QueHasNode( &p->pJust, iVar ) ); if ( !p->Pars.fUseFanout ) Cbs2_QuePush( &p->pJust, iVar ); return 0; } /**Function************************************************************* Synopsis [Propagates a variable.] Description [Returns 1 if conflict; 0 if no conflict.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs2_ManPropagateTwo( Cbs2_Man_t * p, int iVar, int Level ) { Gia_Obj_t * pVar = Gia_ManObj( p->pAig, iVar ); int Value0, Value1; assert( !Gia_IsComplement(pVar) ); assert( Gia_ObjIsAnd(pVar) ); assert( Cbs2_VarIsAssigned(p, iVar) ); assert( Cbs2_VarValue(p, iVar) == 0 ); Value0 = Cbs2_VarFanin0Value(p, pVar, iVar); Value1 = Cbs2_VarFanin1Value(p, pVar, iVar); p->nPropCalls[1]++; // value is 0 if ( Value0 == 0 || Value1 == 0 ) // one is 0 return 0; if ( Value0 == 1 && Value1 == 1 ) // both are 1 return Cbs2_ManAnalyze( p, Level, iVar, Gia_ObjFaninId0(pVar, iVar), Gia_ObjFaninId1(pVar, iVar) ); assert( Value0 == 1 || Value1 == 1 ); if ( Value0 >= 2 ) // first is unassigned Cbs2_ManAssign( p, Abc_LitNot(Gia_ObjFaninLit0(pVar, iVar)), Level, iVar, Gia_ObjFaninId1(pVar, iVar) ); if ( Value1 >= 2 ) // first is unassigned Cbs2_ManAssign( p, Abc_LitNot(Gia_ObjFaninLit1(pVar, iVar)), Level, iVar, Gia_ObjFaninId0(pVar, iVar) ); return 0; } /**Function************************************************************* Synopsis [Propagates a variable.] Description [Returns 1 if conflict; 0 if no conflict.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs2_ManPropagateUnassigned( Cbs2_Man_t * p, int iVar, int Level ) { Gia_Obj_t * pVar = Gia_ManObj( p->pAig, iVar ); int Value0, Value1; assert( !Gia_IsComplement(pVar) ); assert( Gia_ObjIsAnd(pVar) ); assert( !Cbs2_VarIsAssigned(p, iVar) ); Value0 = Cbs2_VarFanin0Value(p, pVar, iVar); Value1 = Cbs2_VarFanin1Value(p, pVar, iVar); p->nPropCalls[2]++; if ( Value0 == 0 && Value1 == 0 ) // the output becomes 1 Cbs2_ManAssign( p, Abc_Var2Lit(iVar, 1), Level, Gia_ObjFaninId0(pVar, iVar), Gia_ObjFaninId1(pVar, iVar) ); else if ( Value0 == 0 ) // the output becomes 0 Cbs2_ManAssign( p, Abc_Var2Lit(iVar, 1), Level, Gia_ObjFaninId0(pVar, iVar), 0 ); else if ( Value1 == 0 ) // the output becomes 0 Cbs2_ManAssign( p, Abc_Var2Lit(iVar, 1), Level, Gia_ObjFaninId1(pVar, iVar), 0 ); else if ( Value0 == 1 && Value1 == 1 ) // the output becomes 1 Cbs2_ManAssign( p, Abc_Var2Lit(iVar, 0), Level, Gia_ObjFaninId0(pVar, iVar), Gia_ObjFaninId1(pVar, iVar) ); } /**Function************************************************************* Synopsis [Propagates all variables.] Description [Returns 1 if conflict; 0 if no conflict.] SideEffects [] SeeAlso [] ***********************************************************************/ int Cbs2_ManPropagate( Cbs2_Man_t * p, int Level ) { while ( 1 ) { int i, k, iVar, iLit, hClause; Cbs2_QueForEachEntry( p->pProp, iLit, i ) { if ( (hClause = Cbs2_ManPropagateOne( p, Abc_Lit2Var(iLit), Level )) ) return hClause; } p->pProp.iHead = p->pProp.iTail; k = p->pJust.iHead; Cbs2_QueForEachEntry( p->pJust, iVar, i ) { if ( Cbs2_VarIsJust(p, Gia_ManObj(p->pAig, iVar), iVar) ) p->pJust.pData[k++] = iVar; else if ( (hClause = Cbs2_ManPropagateTwo( p, iVar, Level )) ) return hClause; } if ( k == p->pJust.iTail ) break; p->pJust.iTail = k; } return 0; } int Cbs2_ManPropagate2( Cbs2_Man_t * p, int Level ) { int i, iLit, iFan, hClause; Cbs2_QueForEachEntry( p->pProp, iLit, i ) { if ( (hClause = Cbs2_ManPropagateClauses(p, Level, iLit)) ) return hClause; Cbs2_ObjForEachFanout( p, Abc_Lit2Var(iLit), iFan ) { int iFanout = Abc_Lit2Var(iFan); if ( !Cbs2_VarIsAssigned(p, iFanout) ) Cbs2_ManPropagateUnassigned( p, iFanout, Level ); else if ( (hClause = Cbs2_ManPropagateOne(p, iFanout, Level)) ) return hClause; } if ( (hClause = Cbs2_ManPropagateOne( p, Abc_Lit2Var(iLit), Level )) ) return hClause; } p->pProp.iHead = p->pProp.iTail; return 0; } /**Function************************************************************* Synopsis [Updates J-frontier.] Description [Returns 1 if found SAT; 0 if continues solving.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs2_ManUpdateDecVar2( Cbs2_Man_t * p, int iObj, int iDecLit ) { Gia_Obj_t * pObj = Gia_ManObj(p->pAig, iObj); int iFan; iFan = Gia_ObjFaninId0(pObj, iObj); if ( iDecLit == -1 || Gia_ObjLevelId(p->pAig, Abc_Lit2Var(iDecLit)) < Gia_ObjLevelId(p->pAig, iFan) ) iDecLit = Abc_LitNot(Gia_ObjFaninLit0(pObj, iObj)); iFan = Gia_ObjFaninId1(pObj, iObj); if ( iDecLit == -1 || Gia_ObjLevelId(p->pAig, Abc_Lit2Var(iDecLit)) < Gia_ObjLevelId(p->pAig, iFan) ) iDecLit = Abc_LitNot(Gia_ObjFaninLit1(pObj, iObj)); return iDecLit; } static inline int Cbs2_ManUpdateDecVar3( Cbs2_Man_t * p, int iObj, int iDecLit ) { Gia_Obj_t * pObj = Gia_ManObj(p->pAig, iObj); int iFan; iFan = Gia_ObjFaninId0(pObj, iObj); if ( iDecLit == -1 || Vec_IntEntry(&p->vActivity, Abc_Lit2Var(iDecLit)) < Vec_IntEntry(&p->vActivity, iFan) ) iDecLit = Abc_LitNot(Gia_ObjFaninLit0(pObj, iObj)); iFan = Gia_ObjFaninId1(pObj, iObj); if ( iDecLit == -1 || Vec_IntEntry(&p->vActivity, Abc_Lit2Var(iDecLit)) < Vec_IntEntry(&p->vActivity, iFan) ) iDecLit = Abc_LitNot(Gia_ObjFaninLit1(pObj, iObj)); return iDecLit; } static inline int Cbs2_ManUpdateDecVar( Cbs2_Man_t * p, int iObj, int iDecLit ) { Gia_Obj_t * pObj = Gia_ManObj(p->pAig, iObj); int iFan; iFan = Gia_ObjFaninId0(pObj, iObj); if ( iDecLit == -1 || Gia_ObjRefNumId(p->pAig, Abc_Lit2Var(iDecLit)) < Gia_ObjRefNumId(p->pAig, iFan) ) iDecLit = Abc_LitNot(Gia_ObjFaninLit0(pObj, iObj)); iFan = Gia_ObjFaninId1(pObj, iObj); if ( iDecLit == -1 || Gia_ObjRefNumId(p->pAig, Abc_Lit2Var(iDecLit)) < Gia_ObjRefNumId(p->pAig, iFan) ) iDecLit = Abc_LitNot(Gia_ObjFaninLit1(pObj, iObj)); return iDecLit; } int Cbs2_ManUpdateFrontier( Cbs2_Man_t * p, int iPropHeadOld, int * piDecLit ) { abctime clk = Abc_Clock(); int i, iVar, iLit, iJustTailOld = p->pJust.iTail; *piDecLit = -1; assert( Cbs2_QueIsEmpty(&p->pProp) ); // visit old frontier nodes Cbs2_QueForEachEntry( p->pJust, iVar, i ) if ( i == iJustTailOld ) break; else if ( Cbs2_VarIsJust(p, Gia_ManObj(p->pAig, iVar), iVar) ) { Cbs2_QuePush( &p->pJust, iVar ); //*piDecLit = Cbs2_ManUpdateDecVar( p, iVar, *piDecLit ); } // append new nodes p->pProp.iHead = iPropHeadOld; Cbs2_QueForEachEntry( p->pProp, iLit, i ) { iVar = Abc_Lit2Var(iLit); if ( Cbs2_VarIsJust(p, Gia_ManObj(p->pAig, iVar), iVar) ) { Cbs2_QuePush( &p->pJust, iVar ); //*piDecLit = Cbs2_ManUpdateDecVar( p, iVar, *piDecLit ); } } p->pProp.iHead = p->pProp.iTail; // update the head of the frontier p->pJust.iHead = iJustTailOld; // return 1 if the queue is empty p->timeJFront += Abc_Clock() - clk; //printf( "%d ", p->pJust.iTail - p->pJust.iHead ); return Cbs2_QueIsEmpty(&p->pJust); } /**Function************************************************************* Synopsis [Solve the problem recursively.] Description [Returns learnt clause if unsat, NULL if sat or undecided.] SideEffects [] SeeAlso [] ***********************************************************************/ int Cbs2_ManSolve1_rec( Cbs2_Man_t * p, int Level ) { Gia_Obj_t * pVar; Cbs2_Que_t * pQue = &(p->pClauses); int iPropHead, iJustHead, iJustTail; int hClause, hLearn0, hLearn1, iVar, iDecLit; // propagate assignments assert( !Cbs2_QueIsEmpty(&p->pProp) ); if ( (hClause = Cbs2_ManPropagate( p, Level )) ) return hClause; // check for satisfying assignment assert( Cbs2_QueIsEmpty(&p->pProp) ); if ( Cbs2_QueIsEmpty(&p->pJust) ) return 0; // quit using resource limits p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); if ( Cbs2_ManCheckLimits( p ) ) return 0; // remember the state before branching iPropHead = p->pProp.iHead; Cbs2_QueStore( &p->pJust, &iJustHead, &iJustTail ); // find the decision variable assert( p->Pars.fUseHighest ); iVar = Cbs2_ManDecideHighest( p ); pVar = Gia_ManObj( p->pAig, iVar ); assert( Cbs2_VarIsJust(p, pVar, iVar) ); // chose decision variable using fanout count if ( Gia_ObjRefNum(p->pAig, Gia_ObjFanin0(pVar)) > Gia_ObjRefNum(p->pAig, Gia_ObjFanin1(pVar)) ) iDecLit = Abc_LitNot(Gia_ObjFaninLit0(pVar, iVar)); else iDecLit = Abc_LitNot(Gia_ObjFaninLit1(pVar, iVar)); // decide on first fanin Cbs2_ManAssign( p, iDecLit, Level+1, 0, 0 ); if ( !(hLearn0 = Cbs2_ManSolve1_rec( p, Level+1 )) ) return 0; if ( pQue->pData[hLearn0+1] != Abc_Lit2Var(iDecLit) ) return hLearn0; Cbs2_ManCancelUntil( p, iPropHead ); Cbs2_QueRestore( &p->pJust, iJustHead, iJustTail ); // decide on second fanin Cbs2_ManAssign( p, Abc_LitNot(iDecLit), Level+1, 0, 0 ); if ( !(hLearn1 = Cbs2_ManSolve1_rec( p, Level+1 )) ) return 0; if ( pQue->pData[hLearn1+1] != Abc_Lit2Var(iDecLit) ) return hLearn1; hClause = Cbs2_ManResolve( p, Level, hLearn0, hLearn1 ); Cbs2_ManBumpClause( p, hClause ); // Cbs2_ManPrintCube( p, Level, hClause ); // if ( Level > Cbs2_ClauseDecLevel(p, hClause) ) // p->Pars.nBTThisNc++; p->Pars.nBTThis++; return hClause; } int Cbs2_ManSolve2_rec( Cbs2_Man_t * p, int Level ) { Gia_Obj_t * pVar; Cbs2_Que_t * pQue = &(p->pClauses); int iPropHead, iJustHead, iJustTail; int hClause, hLearn0, hLearn1, iVar, iDecLit, iDecLit2; int iPropHeadOld = p->pProp.iHead; // propagate assignments assert( !Cbs2_QueIsEmpty(&p->pProp) ); if ( (hClause = Cbs2_ManPropagate2( p, Level )) ) return hClause; // check for satisfying assignment assert( Cbs2_QueIsEmpty(&p->pProp) ); // if ( Cbs2_QueIsEmpty(&p->pJust) ) // return 0; if ( Cbs2_ManUpdateFrontier(p, iPropHeadOld, &iDecLit2) ) return 0; // quit using resource limits p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); if ( Cbs2_ManCheckLimits( p ) ) return 0; // remember the state before branching iPropHead = p->pProp.iHead; // Cbs2_QueStore( &p->pJust, &iJustHead, &iJustTail ); iJustHead = p->pJust.iHead; iJustTail = p->pJust.iTail; // find the decision variable assert( p->Pars.fUseHighest ); iVar = Cbs2_ManDecideHighest( p ); pVar = Gia_ManObj( p->pAig, iVar ); assert( Cbs2_VarIsJust(p, pVar, iVar) ); // chose decision variable using fanout count if ( Gia_ObjRefNum(p->pAig, Gia_ObjFanin0(pVar)) > Gia_ObjRefNum(p->pAig, Gia_ObjFanin1(pVar)) ) // if ( Vec_IntEntry(&p->vActivity, Gia_ObjFaninId0(pVar, iVar)) > Vec_IntEntry(&p->vActivity, Gia_ObjFaninId1(pVar, iVar)) ) iDecLit = Abc_LitNot(Gia_ObjFaninLit0(pVar, iVar)); else iDecLit = Abc_LitNot(Gia_ObjFaninLit1(pVar, iVar)); //iDecLit = iDecLit2; // decide on first fanin Cbs2_ManAssign( p, iDecLit, Level+1, 0, 0 ); if ( !(hLearn0 = Cbs2_ManSolve2_rec( p, Level+1 )) ) return 0; if ( pQue->pData[hLearn0+1] != Abc_Lit2Var(iDecLit) ) return hLearn0; Cbs2_ManCancelUntil( p, iPropHead ); Cbs2_QueRestore( &p->pJust, iJustHead, iJustTail ); // decide on second fanin Cbs2_ManAssign( p, Abc_LitNot(iDecLit), Level+1, 0, 0 ); if ( !(hLearn1 = Cbs2_ManSolve2_rec( p, Level+1 )) ) return 0; if ( pQue->pData[hLearn1+1] != Abc_Lit2Var(iDecLit) ) return hLearn1; hClause = Cbs2_ManResolve( p, Level, hLearn0, hLearn1 ); Cbs2_ManBumpClause( p, hClause ); //Cbs2_ManPrintCube( p, Level, hClause ); // if ( Level > Cbs2_ClauseDecLevel(p, hClause) ) // p->Pars.nBTThisNc++; p->Pars.nBTThis++; return hClause; } int Cbs2_ManSolve_rec( Cbs2_Man_t * p, int Level ) { return p->Pars.fUseFanout ? Cbs2_ManSolve2_rec(p, Level) : Cbs2_ManSolve1_rec(p, Level); } /**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 Cbs2_ManSolve( Cbs2_Man_t * p, int iLit ) { int RetValue = 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; Cbs2_ManAssign( p, iLit, 0, 0, 0 ); if ( !Cbs2_ManSolve_rec(p, 0) && !Cbs2_ManCheckLimits(p) ) Cbs2_ManSaveModel( p, p->vModel ); else RetValue = 1; Cbs2_ManCancelUntil( p, 0 ); Cbs2_ManCleanWatch( p ); Cbs2_ManBumpClean( p ); 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 ( Cbs2_ManCheckLimits( p ) ) RetValue = -1; return RetValue; } int Cbs2_ManSolve2( Cbs2_Man_t * p, int iLit, int iLit2 ) { int RetValue = 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; Cbs2_ManAssign( p, iLit, 0, 0, 0 ); if ( iLit2 ) Cbs2_ManAssign( p, iLit2, 0, 0, 0 ); if ( !Cbs2_ManSolve_rec(p, 0) && !Cbs2_ManCheckLimits(p) ) Cbs2_ManSaveModelAll( p, p->vModel ); else RetValue = 1; Cbs2_ManCancelUntil( p, 0 ); Cbs2_ManCleanWatch( p ); Cbs2_ManBumpClean( p ); 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 ( Cbs2_ManCheckLimits( p ) ) RetValue = -1; return RetValue; } /**Function************************************************************* Synopsis [Prints statistics of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cbs2_ManSatPrintStats( Cbs2_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 [Create fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cbs2_ObjPrintFanouts( Cbs2_Man_t * p, int iObj ) { int iFanLit; printf( "Fanouts of node %d: ", iObj ); Cbs2_ObjForEachFanout( p, iObj, iFanLit ) printf( "%d ", Abc_Lit2Var(iFanLit) ); printf( "\n" ); } void Cbs2_ManPrintFanouts( Cbs2_Man_t * p ) { Gia_Obj_t * pObj; int iObj; Gia_ManForEachObj( p->pAig, pObj, iObj ) if ( Vec_IntEntry(&p->vFanout0, iObj) ) Cbs2_ObjPrintFanouts( p, iObj ); } void Cbs2_ObjCreateFanout( Cbs2_Man_t * p, int iObj, int iFan0, int iFan1 ) { Vec_IntWriteEntry( &p->vFanoutN, Abc_Var2Lit(iObj, 0), Vec_IntEntry(&p->vFanout0, iFan0) ); Vec_IntWriteEntry( &p->vFanoutN, Abc_Var2Lit(iObj, 1), Vec_IntEntry(&p->vFanout0, iFan1) ); Vec_IntWriteEntry( &p->vFanout0, iFan0, Abc_Var2Lit(iObj, 0) ); Vec_IntWriteEntry( &p->vFanout0, iFan1, Abc_Var2Lit(iObj, 1) ); } void Cbs2_ObjDeleteFanout( Cbs2_Man_t * p, int iObj ) { Vec_IntWriteEntry( &p->vFanoutN, Abc_Var2Lit(iObj, 0), 0 ); Vec_IntWriteEntry( &p->vFanoutN, Abc_Var2Lit(iObj, 1), 0 ); Vec_IntWriteEntry( &p->vFanout0, iObj, 0 ); } void Cbs2_ManCreateFanout_rec( Cbs2_Man_t * p, int iObj ) { Gia_Obj_t * pObj; int iFan0, iFan1; if ( !iObj || Gia_ObjIsTravIdCurrentId(p->pAig, iObj) ) return; Gia_ObjSetTravIdCurrentId(p->pAig, iObj); pObj = Gia_ManObj(p->pAig, iObj); if ( Gia_ObjIsCi(pObj) ) return; assert( Gia_ObjIsAnd(pObj) ); iFan0 = Gia_ObjFaninId0(pObj, iObj); iFan1 = Gia_ObjFaninId1(pObj, iObj); Cbs2_ManCreateFanout_rec( p, iFan0 ); Cbs2_ManCreateFanout_rec( p, iFan1 ); Cbs2_ObjCreateFanout( p, iObj, iFan0, iFan1 ); } void Cbs2_ManDeleteFanout_rec( Cbs2_Man_t * p, int iObj ) { Gia_Obj_t * pObj = Gia_ManObj(p->pAig, iObj); int iFan0, iFan1; Cbs2_ObjDeleteFanout( p, iObj ); if ( Gia_ObjIsCi(pObj) ) return; assert( Gia_ObjIsAnd(pObj) ); iFan0 = Gia_ObjFaninId0(pObj, iObj); iFan1 = Gia_ObjFaninId1(pObj, iObj); if ( Vec_IntEntry(&p->vFanout0, iFan0) ) Cbs2_ManDeleteFanout_rec( p, iFan0 ); if ( Vec_IntEntry(&p->vFanout0, iFan1) ) Cbs2_ManDeleteFanout_rec( p, iFan1 ); } void Cbs2_ManCheckFanouts( Cbs2_Man_t * p ) { Gia_Obj_t * pObj; int iObj; Gia_ManForEachObj( p->pAig, pObj, iObj ) { assert( Vec_IntEntry(&p->vFanout0, iObj) == 0 ); assert( Vec_IntEntry(&p->vFanoutN, Abc_Var2Lit(iObj, 0)) == 0 ); assert( Vec_IntEntry(&p->vFanoutN, Abc_Var2Lit(iObj, 1)) == 0 ); } } /**Function************************************************************* Synopsis [Procedure to test the new SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Cbs2_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ) { extern void Gia_ManCollectTest( Gia_Man_t * pAig ); extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); Cbs2_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_ManLevelNum( 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 = Cbs2_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 = Cbs2_ReadModel( p ); // solve for each output Gia_ManForEachCo( pAig, pRoot, i ) { //printf( "\nOutput %d\n", i ); 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; Gia_ManIncrementTravId( pAig ); Cbs2_ManCreateFanout_rec( p, Gia_ObjFaninId0p(pAig, pRoot) ); //Cbs2_ManPrintFanouts( p ); status = Cbs2_ManSolve( p, Gia_ObjFaninLit0p(pAig, pRoot) ); //printf( "\n" ); Cbs2_ManDeleteFanout_rec( p, Gia_ObjFaninId0p(pAig, pRoot) ); //Cbs2_ManCheckFanouts( p ); /* if ( status == -1 ) { p->Pars.fUseHighest = 0; p->Pars.fUseLowest = 1; status = Cbs2_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 ) { 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 ) 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; // 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 abc-0.52/src/aig/gia/giaCSat3.c000066400000000000000000001375401477524141600160430ustar00rootroot00000000000000/**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 abc-0.52/src/aig/gia/giaCSatOld.c000066400000000000000000000604131477524141600164110ustar00rootroot00000000000000/**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 Cbs0_Par_t_ Cbs0_Par_t; struct Cbs0_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 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; }; typedef struct Cbs0_Que_t_ Cbs0_Que_t; struct Cbs0_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 Cbs0_Man_t_ Cbs0_Man_t; struct Cbs0_Man_t_ { Cbs0_Par_t Pars; // parameters Gia_Man_t * pAig; // AIG manager Cbs0_Que_t pProp; // propagation queue Cbs0_Que_t pJust; // justification queue Vec_Int_t * vModel; // satisfying assignment // 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 }; static inline int Cbs0_VarIsAssigned( Gia_Obj_t * pVar ) { return pVar->fMark0; } static inline void Cbs0_VarAssign( Gia_Obj_t * pVar ) { assert(!pVar->fMark0); pVar->fMark0 = 1; } static inline void Cbs0_VarUnassign( Gia_Obj_t * pVar ) { assert(pVar->fMark0); pVar->fMark0 = 0; pVar->fMark1 = 0; } static inline int Cbs0_VarValue( Gia_Obj_t * pVar ) { assert(pVar->fMark0); return pVar->fMark1; } static inline void Cbs0_VarSetValue( Gia_Obj_t * pVar, int v ) { assert(pVar->fMark0); pVar->fMark1 = v; } static inline int Cbs0_VarIsJust( Gia_Obj_t * pVar ) { return Gia_ObjIsAnd(pVar) && !Cbs0_VarIsAssigned(Gia_ObjFanin0(pVar)) && !Cbs0_VarIsAssigned(Gia_ObjFanin1(pVar)); } static inline int Cbs0_VarFanin0Value( Gia_Obj_t * pVar ) { return !Cbs0_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (Cbs0_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); } static inline int Cbs0_VarFanin1Value( Gia_Obj_t * pVar ) { return !Cbs0_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (Cbs0_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); } #define Cbs0_QueForEachEntry( Que, pObj, i ) \ for ( i = (Que).iHead; (i < (Que).iTail) && ((pObj) = (Que).pData[i]); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Sets default values of the parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cbs0_SetDefaultParams( Cbs0_Par_t * pPars ) { memset( pPars, 0, sizeof(Cbs0_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 } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cbs0_Man_t * Cbs0_ManAlloc() { Cbs0_Man_t * p; p = ABC_CALLOC( Cbs0_Man_t, 1 ); p->pProp.nSize = p->pJust.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->vModel = Vec_IntAlloc( 1000 ); Cbs0_SetDefaultParams( &p->Pars ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cbs0_ManStop( Cbs0_Man_t * p ) { Vec_IntFree( p->vModel ); ABC_FREE( p->pProp.pData ); ABC_FREE( p->pJust.pData ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Returns satisfying assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Cbs0_ReadModel( Cbs0_Man_t * p ) { return p->vModel; } /**Function************************************************************* Synopsis [Returns 1 if the solver is out of limits.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs0_ManCheckLimits( Cbs0_Man_t * p ) { 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 Cbs0_ManSaveModel( Cbs0_Man_t * p, Vec_Int_t * vCex ) { Gia_Obj_t * pVar; int i; Vec_IntClear( vCex ); p->pProp.iHead = 0; Cbs0_QueForEachEntry( p->pProp, pVar, i ) if ( Gia_ObjIsCi(pVar) ) // Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !Cbs0_VarValue(pVar)) ); Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjCioId(pVar), !Cbs0_VarValue(pVar)) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs0_QueIsEmpty( Cbs0_Que_t * p ) { return p->iHead == p->iTail; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs0_QuePush( Cbs0_Que_t * p, Gia_Obj_t * 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 Cbs0_QueHasNode( Cbs0_Que_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pTemp; int i; Cbs0_QueForEachEntry( *p, pTemp, i ) if ( pTemp == pObj ) return 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs0_QueStore( Cbs0_Que_t * p, int * piHeadOld, int * piTailOld ) { int i; *piHeadOld = p->iHead; *piTailOld = p->iTail; for ( i = *piHeadOld; i < *piTailOld; i++ ) Cbs0_QuePush( p, p->pData[i] ); p->iHead = *piTailOld; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs0_QueRestore( Cbs0_Que_t * p, int iHeadOld, int iTailOld ) { p->iHead = iHeadOld; p->iTail = iTailOld; } /**Function************************************************************* Synopsis [Max number of fanins fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs0_VarFaninFanoutMax( Cbs0_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 * Cbs0_ManDecideHighest( Cbs0_Man_t * p ) { Gia_Obj_t * pObj, * pObjMax = NULL; int i; Cbs0_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 * Cbs0_ManDecideLowest( Cbs0_Man_t * p ) { Gia_Obj_t * pObj, * pObjMin = NULL; int i; Cbs0_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 * Cbs0_ManDecideMaxFF( Cbs0_Man_t * p ) { Gia_Obj_t * pObj, * pObjMax = NULL; int i, iMaxFF = 0, iCurFF; assert( p->pAig->pRefs != NULL ); Cbs0_QueForEachEntry( p->pJust, pObj, i ) { iCurFF = Cbs0_VarFaninFanoutMax( p, pObj ); assert( iCurFF > 0 ); if ( iMaxFF < iCurFF ) { iMaxFF = iCurFF; pObjMax = pObj; } } return pObjMax; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Cbs0_ManCancelUntil( Cbs0_Man_t * p, int iBound ) { Gia_Obj_t * pVar; int i; assert( iBound <= p->pProp.iTail ); p->pProp.iHead = iBound; Cbs0_QueForEachEntry( p->pProp, pVar, i ) Cbs0_VarUnassign( pVar ); 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 Cbs0_ManAssign( Cbs0_Man_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pObjR = Gia_Regular(pObj); assert( Gia_ObjIsCand(pObjR) ); assert( !Cbs0_VarIsAssigned(pObjR) ); Cbs0_VarAssign( pObjR ); Cbs0_VarSetValue( pObjR, !Gia_IsComplement(pObj) ); Cbs0_QuePush( &p->pProp, pObjR ); } /**Function************************************************************* Synopsis [Propagates a variable.] Description [Returns 1 if conflict; 0 if no conflict.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Cbs0_ManPropagateOne( Cbs0_Man_t * p, Gia_Obj_t * pVar ) { int Value0, Value1; assert( !Gia_IsComplement(pVar) ); assert( Cbs0_VarIsAssigned(pVar) ); if ( Gia_ObjIsCi(pVar) ) return 0; assert( Gia_ObjIsAnd(pVar) ); Value0 = Cbs0_VarFanin0Value(pVar); Value1 = Cbs0_VarFanin1Value(pVar); if ( Cbs0_VarValue(pVar) ) { // value is 1 if ( Value0 == 0 || Value1 == 0 ) // one is 0 return 1; if ( Value0 == 2 ) // first is unassigned Cbs0_ManAssign( p, Gia_ObjChild0(pVar) ); if ( Value1 == 2 ) // first is unassigned Cbs0_ManAssign( p, Gia_ObjChild1(pVar) ); return 0; } // value is 0 if ( Value0 == 0 || Value1 == 0 ) // one is 0 return 0; if ( Value0 == 1 && Value1 == 1 ) // both are 1 return 1; if ( Value0 == 1 || Value1 == 1 ) // one is 1 { if ( Value0 == 2 ) // first is unassigned Cbs0_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)) ); if ( Value1 == 2 ) // first is unassigned Cbs0_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)) ); return 0; } assert( Cbs0_VarIsJust(pVar) ); assert( !Cbs0_QueHasNode( &p->pJust, pVar ) ); Cbs0_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 Cbs0_ManPropagateTwo( Cbs0_Man_t * p, Gia_Obj_t * pVar ) { int Value0, Value1; assert( !Gia_IsComplement(pVar) ); assert( Gia_ObjIsAnd(pVar) ); assert( Cbs0_VarIsAssigned(pVar) ); assert( !Cbs0_VarValue(pVar) ); Value0 = Cbs0_VarFanin0Value(pVar); Value1 = Cbs0_VarFanin1Value(pVar); // value is 0 if ( Value0 == 0 || Value1 == 0 ) // one is 0 return 0; if ( Value0 == 1 && Value1 == 1 ) // both are 1 return 1; assert( Value0 == 1 || Value1 == 1 ); if ( Value0 == 2 ) // first is unassigned Cbs0_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)) ); if ( Value1 == 2 ) // first is unassigned Cbs0_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)) ); return 0; } /**Function************************************************************* Synopsis [Propagates all variables.] Description [Returns 1 if conflict; 0 if no conflict.] SideEffects [] SeeAlso [] ***********************************************************************/ int Cbs0_ManPropagate( Cbs0_Man_t * p ) { Gia_Obj_t * pVar; int i, k; while ( 1 ) { Cbs0_QueForEachEntry( p->pProp, pVar, i ) { if ( Cbs0_ManPropagateOne( p, pVar ) ) return 1; } p->pProp.iHead = p->pProp.iTail; k = p->pJust.iHead; Cbs0_QueForEachEntry( p->pJust, pVar, i ) { if ( Cbs0_VarIsJust( pVar ) ) p->pJust.pData[k++] = pVar; else if ( Cbs0_ManPropagateTwo( p, pVar ) ) return 1; } if ( k == p->pJust.iTail ) break; p->pJust.iTail = k; } return 0; } /**Function************************************************************* Synopsis [Solve the problem recursively.] Description [Returns 1 if unsat or undecided; 0 if satisfiable.] SideEffects [] SeeAlso [] ***********************************************************************/ int Cbs0_ManSolve_rec( Cbs0_Man_t * p ) { Gia_Obj_t * pVar = NULL, * pDecVar; int iPropHead, iJustHead, iJustTail; // propagate assignments assert( !Cbs0_QueIsEmpty(&p->pProp) ); if ( Cbs0_ManPropagate( p ) ) return 1; // check for satisfying assignment assert( Cbs0_QueIsEmpty(&p->pProp) ); if ( Cbs0_QueIsEmpty(&p->pJust) ) return 0; // quit using resource limits p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); if ( Cbs0_ManCheckLimits( p ) ) return 0; // remember the state before branching iPropHead = p->pProp.iHead; Cbs0_QueStore( &p->pJust, &iJustHead, &iJustTail ); // find the decision variable if ( p->Pars.fUseHighest ) pVar = Cbs0_ManDecideHighest( p ); else if ( p->Pars.fUseLowest ) pVar = Cbs0_ManDecideLowest( p ); else if ( p->Pars.fUseMaxFF ) pVar = Cbs0_ManDecideMaxFF( p ); else assert( 0 ); assert( Cbs0_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)); // decide on first fanin Cbs0_ManAssign( p, pDecVar ); if ( !Cbs0_ManSolve_rec( p ) ) return 0; Cbs0_ManCancelUntil( p, iPropHead ); Cbs0_QueRestore( &p->pJust, iJustHead, iJustTail ); // decide on second fanin Cbs0_ManAssign( p, Gia_Not(pDecVar) ); if ( !Cbs0_ManSolve_rec( p ) ) return 0; p->Pars.nBTThis++; return 1; } /**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 [] SeeAlso [] ***********************************************************************/ int Cbs0_ManSolve( Cbs0_Man_t * p, Gia_Obj_t * pObj ) { int RetValue; assert( !p->pProp.iHead && !p->pProp.iTail ); assert( !p->pJust.iHead && !p->pJust.iTail ); p->Pars.nBTThis = p->Pars.nJustThis = 0; Cbs0_ManAssign( p, pObj ); RetValue = Cbs0_ManSolve_rec( p ); if ( RetValue == 0 && !Cbs0_ManCheckLimits(p) ) Cbs0_ManSaveModel( p, p->vModel ); Cbs0_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 ( Cbs0_ManCheckLimits( p ) ) RetValue = -1; // printf( "Outcome = %2d. Confs = %6d. Decision level max = %3d.\n", // RetValue, p->Pars.nBTThis, p->DecLevelMax ); return RetValue; } /**Function************************************************************* Synopsis [Prints statistics of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cbs0_ManSatPrintStats( Cbs0_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 * Cbs_ManSolveMiter( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ) { extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); Cbs0_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 ); // prepare AIG Gia_ManCreateRefs( pAig ); Gia_ManCleanMark0( pAig ); Gia_ManCleanMark1( pAig ); // create logic network p = Cbs0_ManAlloc(); p->Pars.nBTLimit = nConfs; p->pAig = pAig; // create resulting data-structures vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); vCexStore = Vec_IntAlloc( 10000 ); vVisit = Vec_IntAlloc( 100 ); vCex = Cbs0_ReadModel( p ); // solve for each output Gia_ManForEachCo( pAig, pRoot, i ) { 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 = Cbs0_ManSolve( p, Gia_ObjChild0(pRoot) ); /* if ( status == -1 ) { p->Pars.fUseHighest = 0; p->Pars.fUseLowest = 1; status = Cbs0_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 ) { 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 ) Cbs0_ManSatPrintStats( p ); Cbs0_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 abc-0.52/src/aig/gia/giaCSatP.c000066400000000000000000001163261477524141600160770ustar00rootroot00000000000000/**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 abc-0.52/src/aig/gia/giaCSatP.h000066400000000000000000000076521477524141600161050ustar00rootroot00000000000000#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 abc-0.52/src/aig/gia/giaCTas.c000066400000000000000000001633641477524141600157630ustar00rootroot00000000000000/**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 //#define gia_assert(exp) ((void)0) //#define gia_assert(exp) (assert(exp)) //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Tas_Par_t_ Tas_Par_t; struct Tas_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 // activity float VarDecay; // variable activity decay int VarInc; // variable increment // decision heuristics int fUseActive; // use most active 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; }; typedef struct Tas_Cls_t_ Tas_Cls_t; struct Tas_Cls_t_ { int iNext[2]; // beginning of the queue int nLits; // the number of literals int pLits[0]; // clause literals }; typedef struct Tas_Sto_t_ Tas_Sto_t; struct Tas_Sto_t_ { int iCur; // current position int nSize; // allocated size int * pData; // clause information }; typedef struct Tas_Que_t_ Tas_Que_t; struct Tas_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 }; struct Tas_Man_t_ { Tas_Par_t Pars; // parameters Gia_Man_t * pAig; // AIG manager Tas_Que_t pProp; // propagation queue Tas_Que_t pJust; // justification queue Tas_Que_t pClauses; // clause queue Gia_Obj_t ** pIter; // iterator through clause vars Vec_Int_t * vLevReas; // levels and decisions Vec_Int_t * vModel; // satisfying assignment Vec_Ptr_t * vTemp; // temporary storage // watched clauses Tas_Sto_t pStore; // storage for watched clauses int * pWatches; // watched lists for each literal Vec_Int_t * vWatchLits; // lits whose watched are assigned int nClauses; // the counter of clauses // activity float * pActivity; // variable activity Vec_Int_t * vActiveVars; // variables with activity // 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 }; static inline int Tas_VarIsAssigned( Gia_Obj_t * pVar ) { return pVar->fMark0; } static inline void Tas_VarAssign( Gia_Obj_t * pVar ) { assert(!pVar->fMark0); pVar->fMark0 = 1; } static inline void Tas_VarUnassign( Gia_Obj_t * pVar ) { assert(pVar->fMark0); pVar->fMark0 = 0; pVar->fMark1 = 0; pVar->Value = ~0; } static inline int Tas_VarValue( Gia_Obj_t * pVar ) { assert(pVar->fMark0); return pVar->fMark1; } static inline void Tas_VarSetValue( Gia_Obj_t * pVar, int v ) { assert(pVar->fMark0); pVar->fMark1 = v; } static inline int Tas_VarIsJust( Gia_Obj_t * pVar ) { return Gia_ObjIsAnd(pVar) && !Tas_VarIsAssigned(Gia_ObjFanin0(pVar)) && !Tas_VarIsAssigned(Gia_ObjFanin1(pVar)); } static inline int Tas_VarFanin0Value( Gia_Obj_t * pVar ) { return !Tas_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (Tas_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); } static inline int Tas_VarFanin1Value( Gia_Obj_t * pVar ) { return !Tas_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (Tas_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); } static inline int Tas_VarToLit( Tas_Man_t * p, Gia_Obj_t * pObj ) { assert( Tas_VarIsAssigned(pObj) ); return Abc_Var2Lit( Gia_ObjId(p->pAig, pObj), !Tas_VarValue(pObj) ); } static inline int Tas_LitIsTrue( Gia_Obj_t * pObj, int Lit ) { assert( Tas_VarIsAssigned(pObj) ); return Tas_VarValue(pObj) != Abc_LitIsCompl(Lit); } static inline int Tas_ClsHandle( Tas_Man_t * p, Tas_Cls_t * pClause ) { return ((int *)pClause) - p->pStore.pData; } static inline Tas_Cls_t * Tas_ClsFromHandle( Tas_Man_t * p, int h ) { return (Tas_Cls_t *)(p->pStore.pData + h); } static inline int Tas_VarDecLevel( Tas_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return Vec_IntEntry(p->vLevReas, 3*pVar->Value); } static inline Gia_Obj_t * Tas_VarReason0( Tas_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+1); } static inline Gia_Obj_t * Tas_VarReason1( Tas_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+2); } static inline int Tas_ClauseDecLevel( Tas_Man_t * p, int hClause ) { return Tas_VarDecLevel( p, p->pClauses.pData[hClause] ); } static inline int Tas_VarHasReasonCls( Tas_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return Vec_IntEntry(p->vLevReas, 3*pVar->Value+1) == 0 && Vec_IntEntry(p->vLevReas, 3*pVar->Value+2) != 0; } static inline Tas_Cls_t * Tas_VarReasonCls( Tas_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return Tas_ClsFromHandle( p, Vec_IntEntry(p->vLevReas, 3*pVar->Value+2) ); } #define Tas_QueForEachEntry( Que, pObj, i ) \ for ( i = (Que).iHead; (i < (Que).iTail) && ((pObj) = (Que).pData[i]); i++ ) #define Tas_ClauseForEachVar( p, hClause, pObj ) \ for ( (p)->pIter = (p)->pClauses.pData + hClause; (pObj = *pIter); (p)->pIter++ ) #define Tas_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 Tas_SetDefaultParams( Tas_Par_t * pPars ) { memset( pPars, 0, sizeof(Tas_Par_t) ); pPars->nBTLimit = 2000; // limit on the number of conflicts pPars->nJustLimit = 2000; // limit on the size of justification queue pPars->fUseActive = 0; // use node with the highest activity pPars->fUseHighest = 1; // use node with the highest ID pPars->fUseLowest = 0; // use node with the lowest ID pPars->fUseMaxFF = 0; // use node with the largest fanin fanout pPars->fVerbose = 1; // print detailed statistics pPars->VarDecay = (float)0.95; // variable decay pPars->VarInc = 1.0; // variable increment } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Tas_Man_t * Tas_ManAlloc( Gia_Man_t * pAig, int nBTLimit ) { Tas_Man_t * p; p = ABC_CALLOC( Tas_Man_t, 1 ); Tas_SetDefaultParams( &p->Pars ); p->pAig = pAig; p->Pars.nBTLimit = nBTLimit; 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->pStore.iCur = 16; p->pStore.nSize = 10000; p->pStore.pData = ABC_ALLOC( int, p->pStore.nSize ); p->pWatches = ABC_CALLOC( int, 2 * Gia_ManObjNum(pAig) ); p->vWatchLits = Vec_IntAlloc( 100 ); p->pActivity = ABC_CALLOC( float, Gia_ManObjNum(pAig) ); p->vActiveVars = Vec_IntAlloc( 100 ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tas_ManStop( Tas_Man_t * p ) { Vec_IntFree( p->vActiveVars ); Vec_IntFree( p->vWatchLits ); Vec_IntFree( p->vLevReas ); Vec_IntFree( p->vModel ); Vec_PtrFree( p->vTemp ); ABC_FREE( p->pActivity ); ABC_FREE( p->pWatches ); ABC_FREE( p->pStore.pData ); 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 * Tas_ReadModel( Tas_Man_t * p ) { return p->vModel; } /**Function************************************************************* Synopsis [Returns 1 if the solver is out of limits.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Tas_ManCheckLimits( Tas_Man_t * p ) { 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 Tas_ManSaveModel( Tas_Man_t * p, Vec_Int_t * vCex ) { Gia_Obj_t * pVar; int i; Vec_IntClear( vCex ); p->pProp.iHead = 0; // printf( "\n" ); Tas_QueForEachEntry( p->pProp, pVar, i ) { if ( Gia_ObjIsCi(pVar) ) // Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !Tas_VarValue(pVar)) ); Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjCioId(pVar), !Tas_VarValue(pVar)) ); /* printf( "%5d(%d) = ", Gia_ObjId(p->pAig, pVar), Tas_VarValue(pVar) ); if ( Gia_ObjIsCi(pVar) ) printf( "pi %d\n", Gia_ObjCioId(pVar) ); else { printf( "%5d %d & ", Gia_ObjFaninId0p(p->pAig, pVar), Gia_ObjFaninC0(pVar) ); printf( "%5d %d ", Gia_ObjFaninId1p(p->pAig, pVar), Gia_ObjFaninC1(pVar) ); printf( "\n" ); } */ } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Tas_QueIsEmpty( Tas_Que_t * p ) { return p->iHead == p->iTail; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Tas_QuePush( Tas_Que_t * p, Gia_Obj_t * 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 Tas_QueHasNode( Tas_Que_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pTemp; int i; Tas_QueForEachEntry( *p, pTemp, i ) if ( pTemp == pObj ) return 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Tas_QueStore( Tas_Que_t * p, int * piHeadOld, int * piTailOld ) { int i; *piHeadOld = p->iHead; *piTailOld = p->iTail; for ( i = *piHeadOld; i < *piTailOld; i++ ) Tas_QuePush( p, p->pData[i] ); p->iHead = *piTailOld; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Tas_QueRestore( Tas_Que_t * p, int iHeadOld, int iTailOld ) { p->iHead = iHeadOld; p->iTail = iTailOld; } /**Function************************************************************* Synopsis [Finalized the clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Tas_QueFinish( Tas_Que_t * p ) { int iHeadOld = p->iHead; assert( p->iHead < p->iTail ); Tas_QuePush( p, NULL ); p->iHead = p->iTail; return iHeadOld; } /**Function************************************************************* Synopsis [Max number of fanins fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Tas_VarFaninFanoutMax( Tas_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 activity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_Obj_t * Tas_ManFindActive( Tas_Man_t * p ) { Gia_Obj_t * pObj, * pObjMax = NULL; float BestCost = 0.0; int i, ObjId; Tas_QueForEachEntry( p->pJust, pObj, i ) { assert( Gia_ObjIsAnd(pObj) ); ObjId = Gia_ObjId( p->pAig, pObj ); if ( pObjMax == NULL || p->pActivity[Gia_ObjFaninId0(pObj,ObjId)] > BestCost || (p->pActivity[Gia_ObjFaninId0(pObj,ObjId)] == BestCost && pObjMax < Gia_ObjFanin0(pObj)) ) { pObjMax = Gia_ObjFanin0(pObj); BestCost = p->pActivity[Gia_ObjFaninId0(pObj,ObjId)]; } if ( p->pActivity[Gia_ObjFaninId1(pObj,ObjId)] > BestCost || (p->pActivity[Gia_ObjFaninId1(pObj,ObjId)] == BestCost && pObjMax < Gia_ObjFanin1(pObj)) ) { pObjMax = Gia_ObjFanin1(pObj); BestCost = p->pActivity[Gia_ObjFaninId1(pObj,ObjId)]; } } return pObjMax; } /**Function************************************************************* Synopsis [Find variable with the highest activity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_Obj_t * Tas_ManDecideHighestFanin( Tas_Man_t * p ) { Gia_Obj_t * pObj, * pObjMax = NULL; int i, ObjId; Tas_QueForEachEntry( p->pJust, pObj, i ) { assert( Gia_ObjIsAnd(pObj) ); ObjId = Gia_ObjId( p->pAig, pObj ); if ( pObjMax == NULL || pObjMax < Gia_ObjFanin0(pObj) ) pObjMax = Gia_ObjFanin0(pObj); if ( pObjMax < Gia_ObjFanin1(pObj) ) pObjMax = Gia_ObjFanin1(pObj); } return pObjMax; } /**Function************************************************************* Synopsis [Find variable with the highest ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_Obj_t * Tas_ManDecideHighest( Tas_Man_t * p ) { Gia_Obj_t * pObj, * pObjMax = NULL; int i; Tas_QueForEachEntry( p->pJust, pObj, i ) { //printf( "%d %6.2f ", Gia_ObjId(p->pAig, pObj), p->pActivity[Gia_ObjId(p->pAig, pObj)] ); if ( pObjMax == NULL || pObjMax < pObj ) pObjMax = pObj; } //printf( "\n" ); return pObjMax; } /**Function************************************************************* Synopsis [Find variable with the highest ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_Obj_t * Tas_ManDecideHighestA( Tas_Man_t * p ) { Gia_Obj_t * pObj, * pObjMax = NULL; int i; Tas_QueForEachEntry( p->pJust, pObj, i ) { if ( pObjMax == NULL || p->pActivity[Gia_ObjId(p->pAig, pObjMax)] < p->pActivity[Gia_ObjId(p->pAig, pObj)] ) pObjMax = pObj; } return pObjMax; } /**Function************************************************************* Synopsis [Find variable with the lowest ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_Obj_t * Tas_ManDecideLowest( Tas_Man_t * p ) { Gia_Obj_t * pObj, * pObjMin = NULL; int i; Tas_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 * Tas_ManDecideMaxFF( Tas_Man_t * p ) { Gia_Obj_t * pObj, * pObjMax = NULL; int i, iMaxFF = 0, iCurFF; assert( p->pAig->pRefs != NULL ); Tas_QueForEachEntry( p->pJust, pObj, i ) { iCurFF = Tas_VarFaninFanoutMax( p, pObj ); assert( iCurFF > 0 ); if ( iMaxFF < iCurFF ) { iMaxFF = iCurFF; pObjMax = pObj; } } return pObjMax; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Tas_ManCancelUntil( Tas_Man_t * p, int iBound ) { Gia_Obj_t * pVar; int i; assert( iBound <= p->pProp.iTail ); p->pProp.iHead = iBound; Tas_QueForEachEntry( p->pProp, pVar, i ) Tas_VarUnassign( pVar ); p->pProp.iTail = iBound; Vec_IntShrink( p->vLevReas, 3*iBound ); } int s_Counter2 = 0; int s_Counter3 = 0; int s_Counter4 = 0; /**Function************************************************************* Synopsis [Assigns the variables a value.] Description [Returns 1 if conflict; 0 if no conflict.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Tas_ManAssign( Tas_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( !Tas_VarIsAssigned(pObjR) ); Tas_VarAssign( pObjR ); Tas_VarSetValue( pObjR, !Gia_IsComplement(pObj) ); assert( pObjR->Value == ~0 ); pObjR->Value = p->pProp.iTail; Tas_QuePush( &p->pProp, pObjR ); Vec_IntPush( p->vLevReas, Level ); if ( pRes0 == NULL && pRes1 != 0 ) // clause { Vec_IntPush( p->vLevReas, 0 ); Vec_IntPush( p->vLevReas, Tas_ClsHandle( p, (Tas_Cls_t *)pRes1 ) ); } else { 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 ); s_Counter2++; } /**Function************************************************************* Synopsis [Returns clause size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Tas_ManClauseSize( Tas_Man_t * p, int hClause ) { Tas_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 Tas_ManPrintClause( Tas_Man_t * p, int Level, int hClause ) { Tas_Que_t * pQue = &(p->pClauses); Gia_Obj_t * pObj; int i; assert( Tas_QueIsEmpty( pQue ) ); printf( "Level %2d : ", Level ); for ( i = hClause; (pObj = pQue->pData[i]); i++ ) printf( "%d=%d(%d) ", Gia_ObjId(p->pAig, pObj), Tas_VarValue(pObj), Tas_VarDecLevel(p, pObj) ); printf( "\n" ); } /**Function************************************************************* Synopsis [Prints conflict clause.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Tas_ManPrintClauseNew( Tas_Man_t * p, int Level, int hClause ) { Tas_Que_t * pQue = &(p->pClauses); Gia_Obj_t * pObj; int i; assert( Tas_QueIsEmpty( pQue ) ); printf( "Level %2d : ", Level ); for ( i = hClause; (pObj = pQue->pData[i]); i++ ) printf( "%c%d ", Tas_VarValue(pObj)? '+':'-', Gia_ObjId(p->pAig, pObj) ); printf( "\n" ); } /**Function************************************************************* Synopsis [Returns conflict clause.] Description [Performs conflict analysis.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Tas_ManDeriveReason( Tas_Man_t * p, int Level ) { Tas_Que_t * pQue = &(p->pClauses); Gia_Obj_t * pObj, * pReason; int i, k, j, iLitLevel, iLitLevel2;//, Id; 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->fPhase == 0 ); } */ // compact literals Vec_PtrClear( p->vTemp ); for ( i = k = pQue->iHead + 1; i < pQue->iTail; i++ ) { pObj = pQue->pData[i]; if ( pObj->fPhase ) // unassigned - seen again continue; // assigned - seen first time pObj->fPhase = 1; Vec_PtrPush( p->vTemp, pObj ); // bump activity // Id = Gia_ObjId( p->pAig, pObj ); // if ( p->pActivity[Id] == 0.0 ) // Vec_IntPush( p->vActiveVars, Id ); // p->pActivity[Id] += p->Pars.VarInc; // check decision level iLitLevel = Tas_VarDecLevel( p, pObj ); if ( iLitLevel < Level ) { pQue->pData[k++] = pObj; continue; } assert( iLitLevel == Level ); if ( Tas_VarHasReasonCls( p, pObj ) ) { Tas_Cls_t * pCls = Tas_VarReasonCls( p, pObj ); pReason = Gia_ManObj( p->pAig, Abc_Lit2Var(pCls->pLits[0]) ); assert( pReason == pObj ); for ( j = 1; j < pCls->nLits; j++ ) { pReason = Gia_ManObj( p->pAig, Abc_Lit2Var(pCls->pLits[j]) ); iLitLevel2 = Tas_VarDecLevel( p, pReason ); assert( Tas_VarIsAssigned( pReason ) ); assert( !Tas_LitIsTrue( pReason, pCls->pLits[j] ) ); Tas_QuePush( pQue, pReason ); } } else { pReason = Tas_VarReason0( p, pObj ); if ( pReason == pObj ) // no reason { assert( pQue->pData[pQue->iHead] == NULL || Level == 0 ); if ( pQue->pData[pQue->iHead] == NULL ) pQue->pData[pQue->iHead] = pObj; else Tas_QuePush( pQue, pObj ); continue; } Tas_QuePush( pQue, pReason ); pReason = Tas_VarReason1( p, pObj ); if ( pReason != pObj ) // second reason Tas_QuePush( pQue, pReason ); } } assert( pQue->pData[pQue->iHead] != NULL ); if ( pQue->pData[pQue->iHead] == NULL ) printf( "Tas_ManDeriveReason(): Failed to derive the clause!!!\n" ); pQue->iTail = k; // clear the marks Vec_PtrForEachEntry( Gia_Obj_t *, p->vTemp, pObj, i ) pObj->fPhase = 0; } /**Function************************************************************* Synopsis [Returns conflict clause.] Description [Performs conflict analysis.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Tas_ManAnalyze( Tas_Man_t * p, int Level, Gia_Obj_t * pVar, Gia_Obj_t * pFan0, Gia_Obj_t * pFan1 ) { Tas_Que_t * pQue = &(p->pClauses); assert( Tas_VarIsAssigned(pVar) ); assert( Tas_VarIsAssigned(pFan0) ); assert( pFan1 == NULL || Tas_VarIsAssigned(pFan1) ); assert( Tas_QueIsEmpty( pQue ) ); Tas_QuePush( pQue, NULL ); Tas_QuePush( pQue, pVar ); Tas_QuePush( pQue, pFan0 ); if ( pFan1 ) Tas_QuePush( pQue, pFan1 ); Tas_ManDeriveReason( p, Level ); return Tas_QueFinish( pQue ); } /**Function************************************************************* Synopsis [Performs resolution of two clauses.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Tas_ManResolve( Tas_Man_t * p, int Level, int hClause0, int hClause1 ) { Tas_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->fPhase == 0 ); for ( i = hClause1 + 1; (pObj = pQue->pData[i]); i++ ) assert( pObj->fPhase == 0 ); */ assert( Tas_QueIsEmpty( pQue ) ); Tas_QuePush( pQue, NULL ); for ( i = hClause0 + 1; (pObj = pQue->pData[i]); i++ ) { if ( pObj->fPhase ) // unassigned - seen again continue; // assigned - seen first time pObj->fPhase = 1; Tas_QuePush( pQue, pObj ); LevelCur = Tas_VarDecLevel( p, pObj ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } for ( i = hClause1 + 1; (pObj = pQue->pData[i]); i++ ) { if ( pObj->fPhase ) // unassigned - seen again continue; // assigned - seen first time pObj->fPhase = 1; Tas_QuePush( pQue, pObj ); LevelCur = Tas_VarDecLevel( p, pObj ); if ( LevelMax < LevelCur ) LevelMax = LevelCur; } for ( i = pQue->iHead + 1; i < pQue->iTail; i++ ) pQue->pData[i]->fPhase = 0; Tas_ManDeriveReason( p, LevelMax ); return Tas_QueFinish( pQue ); } /**Function************************************************************* Synopsis [Allocates clause of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Tas_Cls_t * Tas_ManAllocCls( Tas_Man_t * p, int nSize ) { Tas_Cls_t * pCls; if ( p->pStore.iCur + nSize > p->pStore.nSize ) { p->pStore.nSize *= 2; p->pStore.pData = ABC_REALLOC( int, p->pStore.pData, p->pStore.nSize ); } pCls = Tas_ClsFromHandle( p, p->pStore.iCur ); p->pStore.iCur += nSize; memset( pCls, 0, sizeof(int) * nSize ); p->nClauses++; return pCls; } /**Function************************************************************* Synopsis [Adds one clause to the watcher list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Tas_ManWatchClause( Tas_Man_t * p, Tas_Cls_t * pClause, int Lit ) { assert( Abc_Lit2Var(Lit) < Gia_ManObjNum(p->pAig) ); assert( pClause->nLits >= 2 ); assert( pClause->pLits[0] == Lit || pClause->pLits[1] == Lit ); if ( pClause->pLits[0] == Lit ) pClause->iNext[0] = p->pWatches[Abc_LitNot(Lit)]; else pClause->iNext[1] = p->pWatches[Abc_LitNot(Lit)]; if ( p->pWatches[Abc_LitNot(Lit)] == 0 ) Vec_IntPush( p->vWatchLits, Abc_LitNot(Lit) ); p->pWatches[Abc_LitNot(Lit)] = Tas_ClsHandle( p, pClause ); } /**Function************************************************************* Synopsis [Creates clause of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Tas_Cls_t * Tas_ManCreateCls( Tas_Man_t * p, int hClause ) { Tas_Cls_t * pClause; Tas_Que_t * pQue = &(p->pClauses); Gia_Obj_t * pObj; int i, nLits = 0; assert( Tas_QueIsEmpty( pQue ) ); assert( pQue->pData[hClause] != NULL ); for ( i = hClause; (pObj = pQue->pData[i]); i++ ) nLits++; if ( nLits == 1 ) return NULL; // create this clause pClause = Tas_ManAllocCls( p, nLits + 3 ); pClause->nLits = nLits; for ( i = hClause; (pObj = pQue->pData[i]); i++ ) { assert( Tas_VarIsAssigned( pObj ) ); pClause->pLits[i-hClause] = Abc_LitNot( Tas_VarToLit(p, pObj) ); } // add the clause as watched one if ( nLits >= 2 ) { Tas_ManWatchClause( p, pClause, pClause->pLits[0] ); Tas_ManWatchClause( p, pClause, pClause->pLits[1] ); } // increment activity // p->Pars.VarInc /= p->Pars.VarDecay; return pClause; } /**Function************************************************************* Synopsis [Creates clause of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Tas_ManCreateFromCls( Tas_Man_t * p, Tas_Cls_t * pCls, int Level ) { Tas_Que_t * pQue = &(p->pClauses); Gia_Obj_t * pObj; int i; assert( Tas_QueIsEmpty( pQue ) ); Tas_QuePush( pQue, NULL ); for ( i = 0; i < pCls->nLits; i++ ) { pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCls->pLits[i]) ); assert( Tas_VarIsAssigned(pObj) ); assert( !Tas_LitIsTrue( pObj, pCls->pLits[i] ) ); Tas_QuePush( pQue, pObj ); } Tas_ManDeriveReason( p, Level ); return Tas_QueFinish( pQue ); } /**Function************************************************************* Synopsis [Propagate one assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Tas_ManPropagateWatch( Tas_Man_t * p, int Level, int Lit ) { Gia_Obj_t * pObj; Tas_Cls_t * pCur; int * piPrev, iCur, iTemp; int i, LitF = Abc_LitNot(Lit); // iterate through the clauses piPrev = p->pWatches + Lit; for ( iCur = p->pWatches[Lit]; iCur; iCur = *piPrev ) { pCur = Tas_ClsFromHandle( p, iCur ); // make sure the false literal is in the second literal of the clause if ( pCur->pLits[0] == LitF ) { pCur->pLits[0] = pCur->pLits[1]; pCur->pLits[1] = LitF; iTemp = pCur->iNext[0]; pCur->iNext[0] = pCur->iNext[1]; pCur->iNext[1] = iTemp; } assert( pCur->pLits[1] == LitF ); // if the first literal is true, the clause is satisfied // if ( pCur->pLits[0] == p->pAssigns[Abc_Lit2Var(pCur->pLits[0])] ) pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[0]) ); if ( Tas_VarIsAssigned(pObj) && Tas_LitIsTrue( pObj, pCur->pLits[0] ) ) { piPrev = &pCur->iNext[1]; continue; } // look for a new literal to watch for ( i = 2; i < (int)pCur->nLits; i++ ) { // skip the case when the literal is false // if ( Abc_LitNot(pCur->pLits[i]) == p->pAssigns[Abc_Lit2Var(pCur->pLits[i])] ) pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[i]) ); if ( Tas_VarIsAssigned(pObj) && !Tas_LitIsTrue( pObj, pCur->pLits[i] ) ) continue; // the literal is either true or unassigned - watch it pCur->pLits[1] = pCur->pLits[i]; pCur->pLits[i] = LitF; // remove this clause from the watch list of Lit *piPrev = pCur->iNext[1]; // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) Tas_ManWatchClause( p, pCur, pCur->pLits[1] ); break; } if ( i < (int)pCur->nLits ) // found new watch continue; // clause is unit - enqueue new implication pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[0]) ); if ( !Tas_VarIsAssigned(pObj) ) { /* { int iLitLevel, iPlace; for ( i = 1; i < (int)pCur->nLits; i++ ) { pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[i]) ); iLitLevel = Tas_VarDecLevel( p, pObj ); iPlace = pObj->Value; printf( "Lit = %d. Level = %d. Place = %d.\n", pCur->pLits[i], iLitLevel, iPlace ); i = i; } } */ Tas_ManAssign( p, Gia_ObjFromLit(p->pAig, pCur->pLits[0]), Level, NULL, (Gia_Obj_t *)pCur ); piPrev = &pCur->iNext[1]; continue; } // conflict detected - return the conflict clause assert( !Tas_LitIsTrue( pObj, pCur->pLits[0] ) ); return Tas_ManCreateFromCls( p, pCur, Level ); } return 0; } /**Function************************************************************* Synopsis [Propagates a variable.] Description [Returns clause handle if conflict; 0 if no conflict.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Tas_ManPropagateOne( Tas_Man_t * p, Gia_Obj_t * pVar, int Level ) { int Value0, Value1, hClause; assert( !Gia_IsComplement(pVar) ); assert( Tas_VarIsAssigned(pVar) ); s_Counter3++; if ( (hClause = Tas_ManPropagateWatch( p, Level, Tas_VarToLit(p, pVar) )) ) return hClause; if ( Gia_ObjIsCi(pVar) ) return 0; /* if ( pVar->iDiff0 == 570869 && pVar->iDiff1 == 546821 && Level == 3 ) { Gia_Obj_t * pFan0 = Gia_ObjFanin0(pVar); Gia_Obj_t * pFan1 = Gia_ObjFanin1(pVar); int s = 0; } */ assert( Gia_ObjIsAnd(pVar) ); Value0 = Tas_VarFanin0Value(pVar); Value1 = Tas_VarFanin1Value(pVar); if ( Tas_VarValue(pVar) ) { // value is 1 if ( Value0 == 0 || Value1 == 0 ) // one is 0 { if ( Value0 == 0 && Value1 != 0 ) return Tas_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), NULL ); if ( Value0 != 0 && Value1 == 0 ) return Tas_ManAnalyze( p, Level, pVar, Gia_ObjFanin1(pVar), NULL ); assert( Value0 == 0 && Value1 == 0 ); return Tas_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); } if ( Value0 == 2 ) // first is unassigned Tas_ManAssign( p, Gia_ObjChild0(pVar), Level, pVar, NULL ); if ( Value1 == 2 ) // first is unassigned Tas_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 Tas_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); if ( Value0 == 1 || Value1 == 1 ) // one is 1 { if ( Value0 == 2 ) // first is unassigned Tas_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) ); if ( Value1 == 2 ) // second is unassigned Tas_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)), Level, pVar, Gia_ObjFanin0(pVar) ); return 0; } assert( Tas_VarIsJust(pVar) ); assert( !Tas_QueHasNode( &p->pJust, pVar ) ); Tas_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 Tas_ManPropagateTwo( Tas_Man_t * p, Gia_Obj_t * pVar, int Level ) { int Value0, Value1; s_Counter4++; assert( !Gia_IsComplement(pVar) ); assert( Gia_ObjIsAnd(pVar) ); assert( Tas_VarIsAssigned(pVar) ); assert( !Tas_VarValue(pVar) ); Value0 = Tas_VarFanin0Value(pVar); Value1 = Tas_VarFanin1Value(pVar); // value is 0 if ( Value0 == 0 || Value1 == 0 ) // one is 0 return 0; if ( Value0 == 1 && Value1 == 1 ) // both are 1 return Tas_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); assert( Value0 == 1 || Value1 == 1 ); if ( Value0 == 2 ) // first is unassigned Tas_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) ); if ( Value1 == 2 ) // first is unassigned Tas_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 Tas_ManPropagate( Tas_Man_t * p, int Level ) { int hClause; Gia_Obj_t * pVar; int i, k;//, nIter = 0; while ( 1 ) { // nIter++; Tas_QueForEachEntry( p->pProp, pVar, i ) { if ( (hClause = Tas_ManPropagateOne( p, pVar, Level )) ) return hClause; } p->pProp.iHead = p->pProp.iTail; k = p->pJust.iHead; Tas_QueForEachEntry( p->pJust, pVar, i ) { if ( Tas_VarIsJust( pVar ) ) p->pJust.pData[k++] = pVar; else if ( (hClause = Tas_ManPropagateTwo( p, pVar, Level )) ) return hClause; } if ( k == p->pJust.iTail ) break; p->pJust.iTail = k; } // printf( "%d ", nIter ); return 0; } /**Function************************************************************* Synopsis [Solve the problem recursively.] Description [Returns learnt clause if unsat, NULL if sat or undecided.] SideEffects [] SeeAlso [] ***********************************************************************/ int Tas_ManSolve_rec( Tas_Man_t * p, int Level ) { Tas_Que_t * pQue = &(p->pClauses); Gia_Obj_t * pVar = NULL, * pDecVar = NULL; int hClause, hLearn0, hLearn1; int iPropHead, iJustHead, iJustTail; // propagate assignments assert( !Tas_QueIsEmpty(&p->pProp) ); if ( (hClause = Tas_ManPropagate( p, Level )) ) { Tas_ManCreateCls( p, hClause ); return hClause; } // check for satisfying assignment assert( Tas_QueIsEmpty(&p->pProp) ); if ( Tas_QueIsEmpty(&p->pJust) ) return 0; // quit using resource limits p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); if ( Tas_ManCheckLimits( p ) ) return 0; // remember the state before branching iPropHead = p->pProp.iHead; Tas_QueStore( &p->pJust, &iJustHead, &iJustTail ); // find the decision variable if ( p->Pars.fUseActive ) pVar = NULL, pDecVar = Tas_ManFindActive( p ); else if ( p->Pars.fUseHighest ) // pVar = NULL, pDecVar = Tas_ManDecideHighestFanin( p ); pVar = Tas_ManDecideHighest( p ); else if ( p->Pars.fUseLowest ) pVar = Tas_ManDecideLowest( p ); else if ( p->Pars.fUseMaxFF ) pVar = Tas_ManDecideMaxFF( p ); else assert( 0 ); // chose decision variable using fanout count if ( pVar != NULL ) { assert( Tas_VarIsJust( pVar ) ); 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( pDecVar, Gia_Regular(pDecVar)->fMark1 ^ !Gia_IsComplement(pDecVar) ); } // decide on first fanin Tas_ManAssign( p, pDecVar, Level+1, NULL, NULL ); if ( !(hLearn0 = Tas_ManSolve_rec( p, Level+1 )) ) return 0; if ( pQue->pData[hLearn0] != Gia_Regular(pDecVar) ) return hLearn0; Tas_ManCancelUntil( p, iPropHead ); Tas_QueRestore( &p->pJust, iJustHead, iJustTail ); // decide on second fanin Tas_ManAssign( p, Gia_Not(pDecVar), Level+1, NULL, NULL ); if ( !(hLearn1 = Tas_ManSolve_rec( p, Level+1 )) ) return 0; if ( pQue->pData[hLearn1] != Gia_Regular(pDecVar) ) return hLearn1; hClause = Tas_ManResolve( p, Level, hLearn0, hLearn1 ); Tas_ManCreateCls( p, hClause ); // Tas_ManPrintClauseNew( p, Level, hClause ); // if ( Level > Tas_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 [] SeeAlso [] ***********************************************************************/ int Tas_ManSolve( Tas_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ) { int i, Entry, RetValue = 0; s_Counter2 = 0; Vec_IntClear( p->vModel ); if ( pObj == Gia_ManConst0(p->pAig) || pObj2 == Gia_ManConst0(p->pAig) || pObj == Gia_Not(pObj2) ) return 1; if ( pObj == Gia_ManConst1(p->pAig) && (pObj2 == NULL || pObj2 == Gia_ManConst1(p->pAig)) ) return 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; Tas_ManAssign( p, pObj, 0, NULL, NULL ); if ( pObj2 && !Tas_VarIsAssigned(Gia_Regular(pObj2)) ) Tas_ManAssign( p, pObj2, 0, NULL, NULL ); if ( !Tas_ManSolve_rec(p, 0) && !Tas_ManCheckLimits(p) ) Tas_ManSaveModel( p, p->vModel ); else RetValue = 1; Tas_ManCancelUntil( p, 0 ); p->pJust.iHead = p->pJust.iTail = 0; p->pClauses.iHead = p->pClauses.iTail = 1; // clauses if ( p->nClauses > 0 ) { p->pStore.iCur = 16; Vec_IntForEachEntry( p->vWatchLits, Entry, i ) p->pWatches[Entry] = 0; Vec_IntClear( p->vWatchLits ); p->nClauses = 0; } // activity Vec_IntForEachEntry( p->vActiveVars, Entry, i ) p->pActivity[Entry] = 0.0; Vec_IntClear( p->vActiveVars ); // statistics p->Pars.nBTTotal += p->Pars.nBTThis; p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); if ( Tas_ManCheckLimits( p ) ) RetValue = -1; return RetValue; } /**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 [] SeeAlso [] ***********************************************************************/ int Tas_ManSolveArray( Tas_Man_t * p, Vec_Ptr_t * vObjs ) { Gia_Obj_t * pObj; int i, Entry, RetValue = 0; s_Counter2 = 0; s_Counter3 = 0; s_Counter4 = 0; Vec_IntClear( p->vModel ); Vec_PtrForEachEntry( Gia_Obj_t *, vObjs, pObj, i ) if ( pObj == Gia_ManConst0(p->pAig) ) return 1; 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; Vec_PtrForEachEntry( Gia_Obj_t *, vObjs, pObj, i ) if ( pObj != Gia_ManConst1(p->pAig) && !Tas_VarIsAssigned(Gia_Regular(pObj)) ) Tas_ManAssign( p, pObj, 0, NULL, NULL ); if ( !Tas_ManSolve_rec(p, 0) && !Tas_ManCheckLimits(p) ) Tas_ManSaveModel( p, p->vModel ); else RetValue = 1; Tas_ManCancelUntil( p, 0 ); p->pJust.iHead = p->pJust.iTail = 0; p->pClauses.iHead = p->pClauses.iTail = 1; // clauses if ( p->nClauses > 0 ) { p->pStore.iCur = 16; Vec_IntForEachEntry( p->vWatchLits, Entry, i ) p->pWatches[Entry] = 0; Vec_IntClear( p->vWatchLits ); p->nClauses = 0; } // activity Vec_IntForEachEntry( p->vActiveVars, Entry, i ) p->pActivity[Entry] = 0.0; Vec_IntClear( p->vActiveVars ); // statistics p->Pars.nBTTotal += p->Pars.nBTThis; p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); if ( Tas_ManCheckLimits( p ) ) RetValue = -1; // printf( "%d ", Gia_ManObjNum(p->pAig) ); // printf( "%d ", p->Pars.nBTThis ); // printf( "%d ", p->Pars.nJustThis ); // printf( "%d ", s_Counter2 ); // printf( "%d ", s_Counter3 ); // printf( "%d ", s_Counter4 ); return RetValue; } /**Function************************************************************* Synopsis [Prints statistics of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tas_ManSatPrintStats( Tas_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 * Tas_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ) { extern void Gia_ManCollectTest( Gia_Man_t * pAig ); extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); Tas_Man_t * p; Vec_Int_t * vCex, * vVisit, * vCexStore; Vec_Str_t * vStatus; Gia_Obj_t * pRoot;//, * pRootCopy; // Gia_Man_t * pAigCopy = Gia_ManDup( pAig ), * pAigTemp; 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_ManCleanPhase( pAig ); // maps nodes into trail ids // create logic network p = Tas_ManAlloc( pAig, nConfs ); p->pAig = pAig; // create resulting data-structures vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); vCexStore = Vec_IntAlloc( 10000 ); vVisit = Vec_IntAlloc( 100 ); vCex = Tas_ReadModel( p ); // solve for each output Gia_ManForEachCo( pAig, pRoot, i ) { // printf( "%d=", i ); 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.fUseActive = 1; p->Pars.fUseHighest = 1; p->Pars.fUseLowest = 0; status = Tas_ManSolve( p, Gia_ObjChild0(pRoot), NULL ); // printf( "\n" ); /* if ( status == -1 ) { p->Pars.fUseHighest = 0; p->Pars.fUseLowest = 1; status = Tas_ManSolve( p, Gia_ObjChild0(pRoot) ); } */ Vec_StrPush( vStatus, (char)status ); if ( status == -1 ) { // printf( "Unsolved %d.\n", i ); p->nSatUndec++; p->nConfUndec += p->Pars.nBTThis; Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout p->timeSatUndec += Abc_Clock() - clk; continue; } // pRootCopy = Gia_ManCo( pAigCopy, i ); // pRootCopy->iDiff0 = Gia_ObjId( pAigCopy, pRootCopy ); // pRootCopy->fCompl0 = 0; 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; // printf( "%d ", Vec_IntSize(vCex) ); } // pAigCopy = Gia_ManCleanup( pAigTemp = pAigCopy ); // Gia_ManStop( pAigTemp ); // Gia_DumpAiger( pAigCopy, "test", 0, 2 ); // Gia_ManStop( pAigCopy ); Vec_IntFree( vVisit ); p->nSatTotal = Gia_ManPoNum(pAig); p->timeTotal = Abc_Clock() - clkTotal; if ( fVerbose ) Tas_ManSatPrintStats( p ); // printf( "RecCalls = %8d. RecClause = %8d. RecNonChro = %8d.\n", p->nRecCall, p->nRecClause, p->nRecNonChro ); Tas_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; } /**Function************************************************************* Synopsis [Packs patterns into array of simulation info.] Description [] SideEffects [] SeeAlso [] *************************************`**********************************/ int Tas_StorePatternTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits ) { unsigned * pInfo, * pPres; int i; for ( i = 0; i < nLits; i++ ) { pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); if ( Abc_InfoHasBit( pPres, iBit ) && Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) return 0; } for ( i = 0; i < nLits; i++ ) { pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); Abc_InfoSetBit( pPres, iBit ); if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) Abc_InfoXorBit( pInfo, iBit ); } return 1; } /**Function************************************************************* Synopsis [Procedure to test the new SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Tas_StorePattern( Vec_Ptr_t * vSimInfo, Vec_Ptr_t * vPres, Vec_Int_t * vCex ) { int k; for ( k = 1; k < 32; k++ ) if ( Tas_StorePatternTry( vSimInfo, vPres, k, (int *)Vec_IntArray(vCex), Vec_IntSize(vCex) ) ) break; return (int)(k < 32); } /**Function************************************************************* Synopsis [Procedure to test the new SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Tas_ManSolveMiterNc2( Gia_Man_t * pAig, int nConfs, Gia_Man_t * pAigOld, Vec_Ptr_t * vOldRoots, Vec_Ptr_t * vSimInfo ) { int nPatMax = 1000; int fVerbose = 1; extern void Gia_ManCollectTest( Gia_Man_t * pAig ); extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); Tas_Man_t * p; Vec_Ptr_t * vPres; Vec_Int_t * vCex, * vVisit, * vCexStore; Vec_Str_t * vStatus; Gia_Obj_t * pRoot, * pOldRoot; int i, status; abctime clk, clkTotal = Abc_Clock(); int Tried = 0, Stored = 0, Step = Gia_ManCoNum(pAig) / nPatMax; 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_ManCleanPhase( pAig ); // maps nodes into trail ids // create logic network p = Tas_ManAlloc( pAig, nConfs ); p->pAig = pAig; // create resulting data-structures vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); vCexStore = Vec_IntAlloc( 10000 ); vVisit = Vec_IntAlloc( 100 ); vCex = Tas_ReadModel( p ); // solve for each output vPres = Vec_PtrAllocSimInfo( Gia_ManCiNum(pAig), 1 ); Vec_PtrCleanSimInfo( vPres, 0, 1 ); Gia_ManForEachCo( pAig, pRoot, i ) { assert( !Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) ); Vec_IntClear( vCex ); clk = Abc_Clock(); p->Pars.fUseHighest = 1; p->Pars.fUseLowest = 0; status = Tas_ManSolve( p, Gia_ObjChild0(pRoot), NULL ); 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; i += Step; continue; } if ( status == 1 ) { p->nSatUnsat++; p->nConfUnsat += p->Pars.nBTThis; p->timeSatUnsat += Abc_Clock() - clk; // record proved pOldRoot = (Gia_Obj_t *)Vec_PtrEntry( vOldRoots, i ); assert( !Gia_ObjProved( pAigOld, Gia_ObjId(pAigOld, pOldRoot) ) ); Gia_ObjSetProved( pAigOld, Gia_ObjId(pAigOld, pOldRoot) ); i += Step; continue; } p->nSatSat++; p->nConfSat += p->Pars.nBTThis; // Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit ); // Cec_ManSatAddToStore( vCexStore, vCex, i ); // save pattern Tried++; Stored += Tas_StorePattern( vSimInfo, vPres, vCex ); p->timeSatSat += Abc_Clock() - clk; i += Step; } printf( "Tried = %d Stored = %d\n", Tried, Stored ); Vec_IntFree( vVisit ); p->nSatTotal = Gia_ManPoNum(pAig); p->timeTotal = Abc_Clock() - clkTotal; if ( fVerbose ) Tas_ManSatPrintStats( p ); Tas_ManStop( p ); Vec_PtrFree( vPres ); Vec_StrFree( vStatus ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaCTas2.c000066400000000000000000000205411477524141600160320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaCSat2.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Circuit-based SAT solver.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaCSat2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Tas_Par_t_ Tas_Par_t; struct Tas_Par_t_ { // conflict limits int nBTLimit; // limit on the number of conflicts // current parameters int nBTThis; // number of conflicts int nBTTotal; // total number of conflicts // decision heuristics int fUseHighest; // use node with the highest ID // other parameters int fVerbose; }; typedef struct Tas_Sto_t_ Tas_Sto_t; struct Tas_Sto_t_ { int iCur; // currently used int nSize; // allocated size char * pBuffer; // handles of objects stored in the queue }; typedef struct Tas_Que_t_ Tas_Que_t; struct Tas_Que_t_ { int iHead; // beginning of the queue int iTail; // end of the queue int nSize; // allocated size int * pData; // handles of objects stored in the queue }; typedef struct Tas_Var_t_ Tas_Var_t; struct Tas_Var_t_ { unsigned fTerm : 1; // terminal node unsigned fVal : 1; // current value unsigned fValOld : 1; // previous value unsigned fAssign : 1; // assigned status unsigned fJQueue : 1; // part of J-frontier unsigned fCompl0 : 1; // complemented attribute unsigned fCompl1 : 1; // complemented attribute unsigned fMark0 : 1; // multi-purpose mark unsigned fMark1 : 1; // multi-purpose mark unsigned fPhase : 1; // polarity unsigned Level : 22; // decision level int Id; // unique ID of this variable int IdAig; // original ID of this variable int Reason0; // reason of this variable int Reason1; // reason of this variable int Diff0; // difference for the first fanin int Diff1; // difference for the second fanin int Watch0; // handle of first watch int Watch1; // handle of second watch }; typedef struct Tas_Cls_t_ Tas_Cls_t; struct Tas_Cls_t_ { int Watch0; // next clause to watch int Watch1; // next clause to watch int pVars[0]; // variable handles }; typedef struct Tas_Man_t_ Tas_Man_t; struct Tas_Man_t_ { // user data Gia_Man_t * pAig; // AIG manager Tas_Par_t Pars; // parameters // solver data Tas_Sto_t * pVars; // variables Tas_Sto_t * pClauses; // clauses // state representation Tas_Que_t pProp; // propagation queue Tas_Que_t pJust; // justification queue 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 int nConfTotal; // total conflicts // runtime stats clock_t timeSatUnsat; // unsat clock_t timeSatSat; // sat clock_t timeSatUndec; // undecided clock_t timeTotal; // total runtime }; static inline int Tas_VarIsAssigned( Tas_Var_t * pVar ) { return pVar->fAssign; } static inline void Tas_VarAssign( Tas_Var_t * pVar ) { assert(!pVar->fAssign); pVar->fAssign = 1; } static inline void Tas_VarUnassign( Tas_Var_t * pVar ) { assert(pVar->fAssign); pVar->fAssign = 0; pVar->fVal = 0; } static inline int Tas_VarValue( Tas_Var_t * pVar ) { assert(pVar->fAssign); return pVar->fVal; } static inline void Tas_VarSetValue( Tas_Var_t * pVar, int v ) { assert(pVar->fAssign); pVar->fVal = v; } static inline int Tas_VarIsJust( Tas_Var_t * pVar ) { return Gia_ObjIsAnd(pVar) && !Tas_VarIsAssigned(Gia_ObjFanin0(pVar)) && !Tas_VarIsAssigned(Gia_ObjFanin1(pVar)); } static inline int Tas_VarFanin0Value( Tas_Var_t * pVar ) { return !Tas_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (Tas_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); } static inline int Tas_VarFanin1Value( Tas_Var_t * pVar ) { return !Tas_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (Tas_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); } static inline int Tas_VarDecLevel( Tas_Man_t * p, Tas_Var_t * pVar ) { assert( pVar->Value != ~0 ); return Vec_IntEntry(p->vLevReas, 3*pVar->Value); } static inline Tas_Var_t * Tas_VarReason0( Tas_Man_t * p, Tas_Var_t * pVar ) { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+1); } static inline Tas_Var_t * Tas_VarReason1( Tas_Man_t * p, Tas_Var_t * pVar ) { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+2); } static inline int Tas_ClauseDecLevel( Tas_Man_t * p, int hClause ) { return Tas_VarDecLevel( p, p->pClauses.pData[hClause] ); } static inline Tas_Var_t * Tas_ManVar( Tas_Man_t * p, int h ) { return (Tas_Var_t *)(p->pVars->pBuffer + h); } static inline Tas_Cls_t * Tas_ManClause( Tas_Man_t * p, int h ) { return (Tas_Cls_t *)(p->pClauses->pBuffer + h); } #define Tas_ClaForEachVar( p, pClause, pVar, i ) \ for ( pVar = Tas_ManVar(p, pClause->pVars[(i=0)]); pClause->pVars[i]; pVar = (Tas_Var_t *)(((char *)pVar + pClause->pVars[++i])) ) #define Tas_QueForEachVar( p, pQue, pVar, i ) \ for ( pVar = Tas_ManVar(p, pQue->pVars[(i=pQue->iHead)]); i < pQue->iTail; pVar = Tas_ManVar(p, pQue->pVars[i++]) ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Tas_Var_t * Tas_ManCreateVar( Tas_Man_t * p ) { Tas_Var_t * pVar; if ( p->pVars->iCur + sizeof(Tas_Var_t) > p->pVars->nSize ) { p->pVars->nSize *= 2; p->pVars->pData = ABC_REALLOC( char, p->pVars->pData, p->pVars->nSize ); } pVar = p->pVars->pData + p->pVars->iCur; p->pVars->iCur += sizeof(Tas_Var_t); memset( pVar, 0, sizeof(Tas_Var_t) ); pVar->Id = pVar - ((Tas_Var_t *)p->pVars->pData); return pVar; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Tas_Var_t * Tas_ManObj2Var( Tas_Man_t * p, Gia_Obj_t * pObj ) { Tas_Var_t * pVar; assert( !Gia_ObjIsComplement(pObj) ); if ( pObj->Value == 0 ) { pVar = Tas_ManCreateVar( p ); pVar-> } return Tas_ManVar( p, pObj->Value ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaCex.c000066400000000000000000000530761477524141600156460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaAbs.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Counter-example-guided abstraction refinement.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaAbs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "sat/bsat/satSolver.h" #include "sat/cnf/cnf.h" #include "sat/bmc/bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Resimulates the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManVerifyCex( Gia_Man_t * pAig, Abc_Cex_t * p, int fDualOut ) { Gia_Obj_t * pObj, * pObjRi, * pObjRo; int RetValue, i, k, iBit = 0; Gia_ManCleanMark0(pAig); Gia_ManForEachRo( pAig, pObj, i ) pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); for ( i = 0; i <= p->iFrame; i++ ) { Gia_ManForEachPi( pAig, pObj, k ) pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); Gia_ManForEachAnd( pAig, pObj, k ) pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); Gia_ManForEachCo( pAig, pObj, k ) pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); if ( i == p->iFrame ) break; Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, k ) { pObjRo->fMark0 = pObjRi->fMark0; } } assert( iBit == p->nBits ); if ( fDualOut ) RetValue = Gia_ManPo(pAig, 2*p->iPo)->fMark0 ^ Gia_ManPo(pAig, 2*p->iPo+1)->fMark0; else RetValue = Gia_ManPo(pAig, p->iPo)->fMark0; Gia_ManCleanMark0(pAig); return RetValue; } /**Function************************************************************* Synopsis [Resimulates the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFindFailedPoCex( Gia_Man_t * pAig, Abc_Cex_t * p, int nOutputs ) { Gia_Obj_t * pObj, * pObjRi, * pObjRo; int RetValue, i, k, iBit = 0; assert( Gia_ManPiNum(pAig) == p->nPis ); Gia_ManCleanMark0(pAig); Gia_ManForEachRo( pAig, pObj, i ) pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); iBit = p->nRegs; for ( i = 0; i <= p->iFrame; i++ ) { Gia_ManForEachPi( pAig, pObj, k ) pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); Gia_ManForEachAnd( pAig, pObj, k ) pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); Gia_ManForEachCo( pAig, pObj, k ) pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, k ) pObjRo->fMark0 = pObjRi->fMark0; } assert( iBit == p->nBits ); // figure out the number of failed output RetValue = -1; // for ( i = Gia_ManPoNum(pAig) - 1; i >= nOutputs; i-- ) for ( i = nOutputs; i < Gia_ManPoNum(pAig); i++ ) { if ( Gia_ManPo(pAig, i)->fMark0 ) { RetValue = i; break; } } Gia_ManCleanMark0(pAig); return RetValue; } /**Function************************************************************* Synopsis [Determines the failed PO when its exact frame is not known.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSetFailedPoCex( Gia_Man_t * pAig, Abc_Cex_t * p ) { Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i, k, iBit = 0; assert( Gia_ManPiNum(pAig) == p->nPis ); Gia_ManCleanMark0(pAig); p->iPo = -1; // Gia_ManForEachRo( pAig, pObj, i ) // pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); iBit = p->nRegs; for ( i = 0; i <= p->iFrame; i++ ) { Gia_ManForEachPi( pAig, pObj, k ) pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); Gia_ManForEachAnd( pAig, pObj, k ) pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); Gia_ManForEachCo( pAig, pObj, k ) pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, k ) pObjRo->fMark0 = pObjRi->fMark0; // check the POs Gia_ManForEachPo( pAig, pObj, k ) { if ( !pObj->fMark0 ) continue; p->iPo = k; p->iFrame = i; p->nBits = iBit; break; } } Gia_ManCleanMark0(pAig); return p->iPo; } /**Function************************************************************* Synopsis [Starts the process of returning values for internal nodes.] Description [Should be called when pCex is available, before probing any object for its value using Gia_ManCounterExampleValueLookup().] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCounterExampleValueStart( Gia_Man_t * pGia, Abc_Cex_t * pCex ) { Gia_Obj_t * pObj, * pObjRi, * pObjRo; int Val0, Val1, nObjs, i, k, iBit = 0; assert( Gia_ManRegNum(pGia) > 0 ); // makes sense only for sequential AIGs assert( pGia->pData2 == NULL ); // if this fail, there may be a memory leak // allocate memory to store simulation bits for internal nodes 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 ), iBit++; // iterate through the timeframes nObjs = Gia_ManObjNum(pGia); for ( i = 0; i <= pCex->iFrame; i++ ) { // no need to set constant-0 node // set primary inputs according to the counter-example Gia_ManForEachPi( pGia, pObj, k ) if ( Abc_InfoHasBit(pCex->pData, iBit++) ) Abc_InfoSetBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjId(pGia, pObj) ); // compute values for each node Gia_ManForEachAnd( pGia, pObj, k ) { Val0 = Abc_InfoHasBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjFaninId0p(pGia, pObj) ); Val1 = Abc_InfoHasBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjFaninId1p(pGia, pObj) ); if ( (Val0 ^ Gia_ObjFaninC0(pObj)) & (Val1 ^ Gia_ObjFaninC1(pObj)) ) Abc_InfoSetBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjId(pGia, pObj) ); } // derive values for combinational outputs Gia_ManForEachCo( pGia, pObj, k ) { Val0 = Abc_InfoHasBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjFaninId0p(pGia, pObj) ); if ( Val0 ^ Gia_ObjFaninC0(pObj) ) Abc_InfoSetBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjId(pGia, pObj) ); } if ( i == pCex->iFrame ) continue; // transfer values to the register output of the next frame Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, k ) if ( Abc_InfoHasBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjId(pGia, pObjRi) ) ) Abc_InfoSetBit( (unsigned *)pGia->pData2, nObjs * (i+1) + Gia_ObjId(pGia, pObjRo) ); } assert( iBit == pCex->nBits ); // check that the counter-example is correct, that is, the corresponding output is asserted assert( Abc_InfoHasBit( (unsigned *)pGia->pData2, nObjs * pCex->iFrame + Gia_ObjId(pGia, Gia_ManCo(pGia, pCex->iPo)) ) ); } /**Function************************************************************* Synopsis [Stops the process of returning values for internal nodes.] Description [Should be called when probing is no longer needed] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCounterExampleValueStop( Gia_Man_t * pGia ) { assert( pGia->pData2 != NULL ); // if this fail, we try to call this procedure more than once ABC_FREE( pGia->pData2 ); pGia->pData2 = NULL; } /**Function************************************************************* Synopsis [Returns the value of the given object in the given timeframe.] Description [Should be called to probe the value of an object with the given ID (iFrame is a 0-based number of a time frame - should not exceed the number of timeframes in the original counter-example).] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCounterExampleValueLookup( Gia_Man_t * pGia, int Id, int iFrame ) { assert( Id >= 0 && Id < Gia_ManObjNum(pGia) ); return Abc_InfoHasBit( (unsigned *)pGia->pData2, Gia_ManObjNum(pGia) * iFrame + Id ); } /**Function************************************************************* Synopsis [Procedure to test the above code.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCounterExampleValueTest( Gia_Man_t * pGia, Abc_Cex_t * pCex ) { Gia_Obj_t * pObj = Gia_ManObj( pGia, Gia_ManObjNum(pGia)/2 ); int iFrame = Abc_MaxInt( 0, pCex->iFrame - 1 ); printf( "\nUsing counter-example, which asserts output %d in frame %d.\n", pCex->iPo, pCex->iFrame ); Gia_ManCounterExampleValueStart( pGia, pCex ); printf( "Value of object %d in frame %d is %d.\n", Gia_ObjId(pGia, pObj), iFrame, Gia_ManCounterExampleValueLookup(pGia, Gia_ObjId(pGia, pObj), iFrame) ); Gia_ManCounterExampleValueStop( pGia ); } /**Function************************************************************* Synopsis [Returns CEX containing PI+CS values for each timeframe.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Gia_ManCexExtendToIncludeCurrentStates( Gia_Man_t * p, Abc_Cex_t * pCex ) { Abc_Cex_t * pNew; Gia_Obj_t * pObj, * pObjRo, * pObjRi; int i, k, iBit = 0; assert( pCex->nRegs > 0 ); // start the counter-example pNew = Abc_CexAlloc( 0, Gia_ManCiNum(p), pCex->iFrame + 1 ); pNew->iFrame = pCex->iFrame; pNew->iPo = pCex->iPo; // set const0 Gia_ManConst0(p)->fMark0 = 0; // set init state Gia_ManForEachRi( p, pObjRi, k ) pObjRi->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); assert( iBit == pCex->nRegs ); for ( i = 0; i <= pCex->iFrame; i++ ) { Gia_ManForEachPi( p, pObj, k ) pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); Gia_ManForEachRiRo( p, pObjRi, pObjRo, k ) pObjRo->fMark0 = pObjRi->fMark0; Gia_ManForEachCi( p, pObj, k ) if ( pObj->fMark0 ) Abc_InfoSetBit( pNew->pData, pNew->nPis * i + 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); } assert( iBit == pCex->nBits ); assert( Gia_ManPo(p, pCex->iPo)->fMark0 == 1 ); Gia_ManCleanMark0(p); return pNew; } /**Function************************************************************* Synopsis [Returns CEX containing all object valuess for each timeframe.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Gia_ManCexExtendToIncludeAllObjects( Gia_Man_t * p, Abc_Cex_t * pCex ) { Abc_Cex_t * pNew; Gia_Obj_t * pObj, * pObjRo, * pObjRi; int i, k, iBit = 0; assert( pCex->nRegs > 0 ); // start the counter-example pNew = Abc_CexAlloc( 0, Gia_ManObjNum(p), pCex->iFrame + 1 ); pNew->iFrame = pCex->iFrame; pNew->iPo = pCex->iPo; // set const0 Gia_ManConst0(p)->fMark0 = 0; // set init state Gia_ManForEachRi( p, pObjRi, k ) pObjRi->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); assert( iBit == pCex->nRegs ); for ( i = 0; i <= pCex->iFrame; i++ ) { Gia_ManForEachPi( p, pObj, k ) pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); Gia_ManForEachRiRo( p, pObjRi, pObjRo, k ) pObjRo->fMark0 = pObjRi->fMark0; Gia_ManForEachObj( p, pObj, k ) if ( pObj->fMark0 ) Abc_InfoSetBit( pNew->pData, pNew->nPis * i + 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); } assert( iBit == pCex->nBits ); assert( Gia_ManPo(p, pCex->iPo)->fMark0 == 1 ); Gia_ManCleanMark0(p); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFramesForCexMin( Gia_Man_t * p, int nFrames ) { Gia_Man_t * pFrames, * pTemp; Gia_Obj_t * pObj; int i, f; assert( Gia_ManPoNum(p) == 1 ); pFrames = Gia_ManStart( Gia_ManObjNum(p) ); pFrames->pName = Abc_UtilStrsav( p->pName ); pFrames->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pFrames ); Gia_ManConst0(p)->Value = 0; for ( f = 0; f < nFrames; f++ ) { Gia_ManForEachRo( p, pObj, i ) pObj->Value = f ? Gia_ObjRoToRi( p, pObj )->Value : 0; Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pFrames ); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManHashAnd( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); } Gia_ManForEachCo( p, pObj, i ) Gia_ManAppendCo( pFrames, Gia_ObjFanin0Copy(pObj) ); pFrames = Gia_ManCleanup( pTemp = pFrames ); //printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", // Gia_ManAndNum(pTemp), Gia_ManAndNum(pFrames) ); Gia_ManStop( pTemp ); return pFrames; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManMinCex( Gia_Man_t * p, Abc_Cex_t * pCex ) { abctime clk = Abc_Clock(); int n, i, iFirstVar, iLit, status, Counter = 0;//, Id; Vec_Int_t * vLits; sat_solver * pSat; Cnf_Dat_t * pCnf; int nFinal, * pFinal; Abc_Cex_t * pCexCare; Gia_Man_t * pFrames; // CEX minimization clk = Abc_Clock(); pCexCare = Bmc_CexCareMinimizeAig( p, Gia_ManPiNum(p), pCex, 1, 1, 1 ); for ( i = pCexCare->nRegs; i < pCexCare->nBits; i++ ) Counter += Abc_InfoHasBit(pCexCare->pData, i); Abc_CexFree( pCexCare ); printf( "Care bits = %d. ", Counter ); Abc_PrintTime( 1, "CEX minimization", Abc_Clock() - clk ); // SAT instance clk = Abc_Clock(); pFrames = Gia_ManFramesForCexMin( p, pCex->iFrame + 1 ); pCnf = (Cnf_Dat_t*)Mf_ManGenerateCnf( pFrames, 8, 0, 0, 0, 0 ); iFirstVar = pCnf->nVars - (pCex->iFrame+1) * pCex->nPis; pSat = (sat_solver*)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); iLit = Abc_Var2Lit( 1, 1 ); status = sat_solver_addclause( pSat, &iLit, &iLit + 1 ); assert( status ); // create literals vLits = Vec_IntAlloc( 100 ); for ( i = pCex->nRegs; i < pCex->nBits; i++ ) Vec_IntPush( vLits, Abc_Var2Lit(iFirstVar + i - pCex->nRegs, !Abc_InfoHasBit(pCex->pData, i)) ); Abc_PrintTime( 1, "SAT solver", Abc_Clock() - clk ); for ( n = 0; n < 2; n++ ) { if ( n ) Vec_IntReverseOrder( vLits ); // SAT-based minimization clk = Abc_Clock(); status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits), 0, 0, 0, 0 ); nFinal = sat_solver_final( pSat, &pFinal ); printf( "Status %d. Selected %d assumptions out of %d. ", status, nFinal, Vec_IntSize(vLits) ); Abc_PrintTime( 1, "Analyze_final", Abc_Clock() - clk ); // SAT-based minimization clk = Abc_Clock(); nFinal = sat_solver_minimize_assumptions( pSat, Vec_IntArray(vLits), Vec_IntSize(vLits), 0 ); printf( "Status %d. Selected %d assumptions out of %d. ", status, nFinal, Vec_IntSize(vLits) ); Abc_PrintTime( 1, "LEXUNSAT", Abc_Clock() - clk ); } // cleanup Vec_IntFree( vLits ); sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); Gia_ManStop( pFrames ); } Abc_Cex_t * Bmc_CexCareDeriveCex( Abc_Cex_t * pCex, int iFirstVar, int * pLits, int nLits ) { Abc_Cex_t * pCexMin; int i; pCexMin = Abc_CexAlloc( pCex->nRegs, pCex->nPis, pCex->iFrame + 1 ); pCexMin->iPo = pCex->iPo; pCexMin->iFrame = pCex->iFrame; for ( i = 0; i < nLits; i++ ) { int PiNum = Abc_Lit2Var(pLits[i]) - iFirstVar; assert( PiNum >= 0 && PiNum < pCex->nBits - pCex->nRegs ); Abc_InfoSetBit( pCexMin->pData, pCexMin->nRegs + PiNum ); } return pCexMin; } Abc_Cex_t * Bmc_CexCareSatBasedMinimizeAig( Gia_Man_t * p, Abc_Cex_t * pCex, int fHighEffort, int fVerbose ) { abctime clk = Abc_Clock(); int n, i, iFirstVar, iLit, status; Vec_Int_t * vLits = NULL, * vTemp; sat_solver * pSat; Cnf_Dat_t * pCnf; int nFinal, * pFinal; Abc_Cex_t * pCexBest = NULL; int CountBest = 0; Gia_Man_t * pFrames; // CEX minimization clk = Abc_Clock(); pCexBest = Bmc_CexCareMinimizeAig( p, Gia_ManPiNum(p), pCex, 1, 1, fVerbose ); for ( i = pCexBest->nRegs; i < pCexBest->nBits; i++ ) CountBest += Abc_InfoHasBit(pCexBest->pData, i); if ( fVerbose ) { printf( "Care bits = %d. ", CountBest ); Abc_PrintTime( 1, "Non-SAT-based CEX minimization", Abc_Clock() - clk ); } // SAT instance clk = Abc_Clock(); pFrames = Gia_ManFramesForCexMin( p, pCex->iFrame + 1 ); pCnf = (Cnf_Dat_t*)Mf_ManGenerateCnf( pFrames, 8, 0, 0, 0, 0 ); iFirstVar = pCnf->nVars - (pCex->iFrame+1) * pCex->nPis; pSat = (sat_solver*)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); iLit = Abc_Var2Lit( 1, 1 ); status = sat_solver_addclause( pSat, &iLit, &iLit + 1 ); assert( status ); // create literals vTemp = Vec_IntAlloc( 100 ); for ( i = pCex->nRegs; i < pCex->nBits; i++ ) Vec_IntPush( vTemp, Abc_Var2Lit(iFirstVar + i - pCex->nRegs, !Abc_InfoHasBit(pCex->pData, i)) ); if ( fVerbose ) Abc_PrintTime( 1, "Constructing SAT solver", Abc_Clock() - clk ); for ( n = 0; n < 2; n++ ) { Vec_IntFreeP( &vLits ); vLits = Vec_IntDup( vTemp ); if ( n ) Vec_IntReverseOrder( vLits ); // SAT-based minimization clk = Abc_Clock(); status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits), 0, 0, 0, 0 ); nFinal = sat_solver_final( pSat, &pFinal ); if ( fVerbose ) { printf( "Status %s Selected %5d assumptions out of %5d. ", status == l_False ? "OK ":"BUG", nFinal, Vec_IntSize(vLits) ); Abc_PrintTime( 1, "Analyze_final", Abc_Clock() - clk ); } if ( CountBest > nFinal ) { CountBest = nFinal; ABC_FREE( pCexBest ); pCexBest = Bmc_CexCareDeriveCex( pCex, iFirstVar, pFinal, nFinal ); } if ( !fHighEffort ) continue; // SAT-based minimization clk = Abc_Clock(); nFinal = sat_solver_minimize_assumptions( pSat, Vec_IntArray(vLits), Vec_IntSize(vLits), 0 ); if ( fVerbose ) { printf( "Status %s Selected %5d assumptions out of %5d. ", status == l_False ? "OK ":"BUG", nFinal, Vec_IntSize(vLits) ); Abc_PrintTime( 1, "LEXUNSAT ", Abc_Clock() - clk ); } if ( CountBest > nFinal ) { CountBest = nFinal; ABC_FREE( pCexBest ); pCexBest = Bmc_CexCareDeriveCex( pCex, iFirstVar, Vec_IntArray(vLits), nFinal ); } } if ( fVerbose ) { printf( "Final : " ); Bmc_CexPrint( pCexBest, pCexBest->nPis, 0 ); } // cleanup Vec_IntFreeP( &vLits ); Vec_IntFreeP( &vTemp ); sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); Gia_ManStop( pFrames ); return pCexBest; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaClp.c000066400000000000000000000424711477524141600156420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaClp.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: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #include "bdd/dsd/dsd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD extern int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ); extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ); extern int Abc_NtkDeriveFlatGiaSop( Gia_Man_t * pGia, int * gFanins, char * pSop ); extern int Gia_ManFactorNode( Gia_Man_t * p, char * pSop, Vec_Int_t * vLeaves ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManRebuildIsop( DdManager * dd, DdNode * bLocal, Gia_Man_t * pNew, Vec_Int_t * vFanins, Vec_Str_t * vSop, Vec_Str_t * vCube ) { char * pSop; DdNode * bCover, * zCover, * zCover0, * zCover1; int nFanins = Vec_IntSize(vFanins); int fPhase, nCubes, nCubes0, nCubes1; // get the ZDD of the negative polarity bCover = Cudd_zddIsop( dd, Cudd_Not(bLocal), Cudd_Not(bLocal), &zCover0 ); Cudd_Ref( zCover0 ); Cudd_Ref( bCover ); Cudd_RecursiveDeref( dd, bCover ); nCubes0 = Abc_CountZddCubes( dd, zCover0 ); // get the ZDD of the positive polarity bCover = Cudd_zddIsop( dd, bLocal, bLocal, &zCover1 ); Cudd_Ref( zCover1 ); Cudd_Ref( bCover ); Cudd_RecursiveDeref( dd, bCover ); nCubes1 = Abc_CountZddCubes( dd, zCover1 ); // compare the number of cubes if ( nCubes1 <= nCubes0 ) { // use positive polarity nCubes = nCubes1; zCover = zCover1; Cudd_RecursiveDerefZdd( dd, zCover0 ); fPhase = 1; } else { // use negative polarity nCubes = nCubes0; zCover = zCover0; Cudd_RecursiveDerefZdd( dd, zCover1 ); fPhase = 0; } if ( nCubes > 1000 ) { Cudd_RecursiveDerefZdd( dd, zCover ); return -1; } // allocate memory for the cover Vec_StrGrow( vSop, (nFanins + 3) * nCubes + 1 ); pSop = Vec_StrArray( vSop ); pSop[(nFanins + 3) * nCubes] = 0; // create the SOP Vec_StrFill( vCube, nFanins, '-' ); Vec_StrPush( vCube, '\0' ); Abc_ConvertZddToSop( dd, zCover, pSop, nFanins, vCube, fPhase ); Cudd_RecursiveDerefZdd( dd, zCover ); // perform factoring // return Abc_NtkDeriveFlatGiaSop( pNew, Vec_IntArray(vFanins), pSop ); return Gia_ManFactorNode( pNew, pSop, vFanins ); } int Gia_ManRebuildNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Gia_Man_t * pNew, DdManager * ddNew, Vec_Int_t * vFanins, Vec_Str_t * vSop, Vec_Str_t * vCube ) { DdManager * ddDsd = Dsd_ManagerReadDd( pManDsd ); DdNode * bLocal, * bTemp; Dsd_Node_t * pFaninDsd; Dsd_Type_t Type; int i, nDecs, iLit = -1; // add the fanins Type = Dsd_NodeReadType( pNodeDsd ); nDecs = Dsd_NodeReadDecsNum( pNodeDsd ); assert( nDecs > 1 ); Vec_IntClear( vFanins ); for ( i = 0; i < nDecs; i++ ) { pFaninDsd = Dsd_NodeReadDec( pNodeDsd, i ); iLit = Dsd_NodeReadMark( Dsd_Regular(pFaninDsd) ); iLit = Abc_LitNotCond( iLit, Dsd_IsComplement(pFaninDsd) ); assert( Type == DSD_NODE_OR || !Dsd_IsComplement(pFaninDsd) ); Vec_IntPush( vFanins, iLit ); } // create the local function depending on the type of the node switch ( Type ) { case DSD_NODE_CONST1: { iLit = 1; break; } case DSD_NODE_OR: { iLit = 0; for ( i = 0; i < nDecs; i++ ) iLit = Gia_ManHashOr( pNew, iLit, Vec_IntEntry(vFanins, i) ); break; } case DSD_NODE_EXOR: { iLit = 0; for ( i = 0; i < nDecs; i++ ) iLit = Gia_ManHashXor( pNew, iLit, Vec_IntEntry(vFanins, i) ); break; } case DSD_NODE_PRIME: { bLocal = Dsd_TreeGetPrimeFunction( ddDsd, pNodeDsd ); Cudd_Ref( bLocal ); bLocal = Extra_TransferLevelByLevel( ddDsd, ddNew, bTemp = bLocal ); Cudd_Ref( bLocal ); Cudd_RecursiveDeref( ddDsd, bTemp ); // bLocal is now in the new BDD manager iLit = Gia_ManRebuildIsop( ddNew, bLocal, pNew, vFanins, vSop, vCube ); Cudd_RecursiveDeref( ddNew, bLocal ); break; } default: { assert( 0 ); break; } } Dsd_NodeSetMark( pNodeDsd, iLit ); return iLit; } Gia_Man_t * Gia_ManRebuild( Gia_Man_t * p, Dsd_Manager_t * pManDsd, DdManager * ddNew ) { Gia_Man_t * pNew; Dsd_Node_t ** ppNodesDsd; Dsd_Node_t * pNodeDsd; int i, nNodesDsd, iLit = -1; Vec_Str_t * vSop, * vCube; Vec_Int_t * vFanins; vFanins = Vec_IntAlloc( 1000 ); vSop = Vec_StrAlloc( 10000 ); vCube = Vec_StrAlloc( 1000 ); pNew = Gia_ManStart( 2*Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); // save the CI nodes in the DSD nodes Dsd_NodeSetMark( Dsd_ManagerReadConst1(pManDsd), 1 ); for ( i = 0; i < Gia_ManCiNum(p); i++ ) { pNodeDsd = Dsd_ManagerReadInput( pManDsd, i ); Dsd_NodeSetMark( pNodeDsd, Gia_ManAppendCi( pNew ) ); } // collect DSD nodes in DFS order (leaves and const1 are not collected) ppNodesDsd = Dsd_TreeCollectNodesDfs( pManDsd, &nNodesDsd ); for ( i = 0; i < nNodesDsd; i++ ) { iLit = Gia_ManRebuildNode( pManDsd, ppNodesDsd[i], pNew, ddNew, vFanins, vSop, vCube ); if ( iLit == -1 ) break; } ABC_FREE( ppNodesDsd ); Vec_IntFree( vFanins ); Vec_StrFree( vSop ); Vec_StrFree( vCube ); if ( iLit == -1 ) { Gia_ManStop( pNew ); return Gia_ManDup(p); } // set the pointers to the CO drivers for ( i = 0; i < Gia_ManCoNum(p); i++ ) { pNodeDsd = Dsd_ManagerReadRoot( pManDsd, i ); iLit = Dsd_NodeReadMark( Dsd_Regular(pNodeDsd) ); iLit = Abc_LitNotCond( iLit, Dsd_IsComplement(pNodeDsd) ); Gia_ManAppendCo( pNew, iLit ); } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCollapseDeref( DdManager * dd, Vec_Ptr_t * vFuncs ) { DdNode * bFunc; int i; Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i ) if ( bFunc ) Cudd_RecursiveDeref( dd, bFunc ); Vec_PtrFree( vFuncs ); } void Gia_ObjCollapseDeref( Gia_Man_t * p, DdManager * dd, Vec_Ptr_t * vFuncs, int Id ) { if ( Gia_ObjRefDecId(p, Id) ) return; Cudd_RecursiveDeref( dd, (DdNode *)Vec_PtrEntry(vFuncs, Id) ); Vec_PtrWriteEntry( vFuncs, Id, NULL ); } Vec_Ptr_t * Gia_ManCollapse( Gia_Man_t * p, DdManager * dd, int nBddLimit, int fVerbose ) { Vec_Ptr_t * vFuncs; DdNode * bFunc0, * bFunc1, * bFunc; Gia_Obj_t * pObj; int i, Id; Gia_ManCreateRefs( p ); // assign constant node vFuncs = Vec_PtrStart( Gia_ManObjNum(p) ); if ( Gia_ObjRefNumId(p, 0) > 0 ) Vec_PtrWriteEntry( vFuncs, 0, Cudd_ReadLogicZero(dd) ), Cudd_Ref(Cudd_ReadLogicZero(dd)); // assign elementary variables Gia_ManForEachCiId( p, Id, i ) if ( Gia_ObjRefNumId(p, Id) > 0 ) Vec_PtrWriteEntry( vFuncs, Id, Cudd_bddIthVar(dd,i) ), Cudd_Ref(Cudd_bddIthVar(dd,i)); // create BDD for AND nodes Gia_ManForEachAnd( p, pObj, i ) { bFunc0 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(vFuncs, Gia_ObjFaninId0(pObj, i)), Gia_ObjFaninC0(pObj) ); bFunc1 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(vFuncs, Gia_ObjFaninId1(pObj, i)), Gia_ObjFaninC1(pObj) ); bFunc = Cudd_bddAndLimit( dd, bFunc0, bFunc1, nBddLimit ); if ( bFunc == NULL ) { Gia_ManCollapseDeref( dd, vFuncs ); return NULL; } Cudd_Ref( bFunc ); Vec_PtrWriteEntry( vFuncs, i, bFunc ); Gia_ObjCollapseDeref( p, dd, vFuncs, Gia_ObjFaninId0(pObj, i) ); Gia_ObjCollapseDeref( p, dd, vFuncs, Gia_ObjFaninId1(pObj, i) ); } // create BDD for outputs Gia_ManForEachCoId( p, Id, i ) { pObj = Gia_ManCo( p, i ); bFunc0 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(vFuncs, Gia_ObjFaninId0(pObj, Id)), Gia_ObjFaninC0(pObj) ); Vec_PtrWriteEntry( vFuncs, Id, bFunc0 ); Cudd_Ref( bFunc0 ); Gia_ObjCollapseDeref( p, dd, vFuncs, Gia_ObjFaninId0(pObj, Id) ); } assert( Vec_PtrSize(vFuncs) == Vec_PtrCountZero(vFuncs) + Gia_ManCoNum(p) ); // compact Gia_ManForEachCoId( p, Id, i ) Vec_PtrWriteEntry( vFuncs, i, Vec_PtrEntry(vFuncs, Id) ); Vec_PtrShrink( vFuncs, Gia_ManCoNum(p) ); return vFuncs; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManCollapseTest( Gia_Man_t * p, int fVerbose ) { Gia_Man_t * pNew; DdManager * dd, * ddNew; Dsd_Manager_t * pManDsd; Vec_Ptr_t * vFuncs; // derive global BDDs dd = Cudd_Init( Gia_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); vFuncs = Gia_ManCollapse( p, dd, 10000, 0 ); Cudd_AutodynDisable( dd ); if ( vFuncs == NULL ) { Extra_StopManager( dd ); return Gia_ManDup(p); } // start ISOP manager ddNew = Cudd_Init( Gia_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_zddVarsFromBddVars( ddNew, 2 ); // Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); if ( fVerbose ) printf( "Ins = %d. Outs = %d. Shared BDD nodes = %d. Peak live nodes = %d. Peak nodes = %d.\n", Gia_ManCiNum(p), Gia_ManCoNum(p), Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs) ), Cudd_ReadPeakLiveNodeCount(dd), (int)Cudd_ReadNodeCount(dd) ); // perform decomposition pManDsd = Dsd_ManagerStart( dd, Gia_ManCiNum(p), 0 ); Dsd_Decompose( pManDsd, (DdNode **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs) ); if ( fVerbose ) { Vec_Ptr_t * vNamesCi = Gia_GetFakeNames( Gia_ManCiNum(p), 0 ); Vec_Ptr_t * vNamesCo = Gia_GetFakeNames( Gia_ManCoNum(p), 1 ); char ** ppNamesCi = (char **)Vec_PtrArray( vNamesCi ); char ** ppNamesCo = (char **)Vec_PtrArray( vNamesCo ); Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, 0, -1, 0 ); Vec_PtrFreeFree( vNamesCi ); Vec_PtrFreeFree( vNamesCo ); } pNew = Gia_ManRebuild( p, pManDsd, ddNew ); Dsd_ManagerStop( pManDsd ); // return manager Gia_ManCollapseDeref( dd, vFuncs ); Extra_StopManager( dd ); Extra_StopManager( ddNew ); return pNew; } void Gia_ManCollapseTestTest( Gia_Man_t * p ) { Gia_Man_t * pNew; pNew = Gia_ManCollapseTest( p, 0 ); Gia_ManPrintStats( p, NULL ); Gia_ManPrintStats( pNew, NULL ); Gia_ManStop( pNew ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintDsdOne( Dsd_Manager_t * pManDsd, int Output, int OffSet ) { Vec_Str_t * vStr = Vec_StrAlloc( 100 ); Dsd_TreePrint4( vStr, pManDsd, Output ); for ( int i = 0; i < OffSet; i++ ) printf( " " ); printf( "Supp %2d nDsd %2d %s\n", Dsd_TreeSuppSize(pManDsd, Output), Dsd_TreeNonDsdMax(pManDsd, Output), Vec_StrArray(vStr) ); Vec_StrFree( vStr ); fflush( stdout ); } void Gia_ManPrintDsd( Dsd_Manager_t * pManDsd, int Output, int nOutputs, int OffSet ) { if ( Output == -1 ) { for ( int i = 0; i < nOutputs; i++ ) Gia_ManPrintDsdOne( pManDsd, i, OffSet ); } else { assert( Output >= 0 && Output < nOutputs ); Gia_ManPrintDsdOne( pManDsd, Output, OffSet ); } } void Gia_ManCheckDsd( Gia_Man_t * p, int OffSet, int fVerbose ) { DdManager * dd; Dsd_Manager_t * pManDsd; Vec_Ptr_t * vFuncs; dd = Cudd_Init( Gia_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); vFuncs = Gia_ManCollapse( p, dd, 10000, 0 ); Cudd_AutodynDisable( dd ); if ( vFuncs == NULL ) { Extra_StopManager( dd ); return; } pManDsd = Dsd_ManagerStart( dd, Gia_ManCiNum(p), 0 ); if ( pManDsd == NULL ) { Gia_ManCollapseDeref( dd, vFuncs ); Cudd_Quit( dd ); return; } Dsd_Decompose( pManDsd, (DdNode **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs) ); if ( fVerbose ) { Vec_Ptr_t * vNamesCi = Gia_GetFakeNames( Gia_ManCiNum(p), 0 ); Vec_Ptr_t * vNamesCo = Gia_GetFakeNames( Gia_ManCoNum(p), 1 ); char ** ppNamesCi = (char **)Vec_PtrArray( vNamesCi ); char ** ppNamesCo = (char **)Vec_PtrArray( vNamesCo ); Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, 0, -1, OffSet ); Vec_PtrFreeFree( vNamesCi ); Vec_PtrFreeFree( vNamesCo ); } else Gia_ManPrintDsd( pManDsd, 0, Vec_PtrSize(vFuncs), 0 ); Dsd_ManagerStop( pManDsd ); Gia_ManCollapseDeref( dd, vFuncs ); Extra_StopManager( dd ); } Vec_Ptr_t * Gia_ManRecurDsdCof( DdManager * dd, Vec_Ptr_t * vFuncs, int iVar ) { Vec_Ptr_t * vNew = Vec_PtrAlloc( 2 * Vec_PtrSize(vFuncs) ); DdNode * bFunc; int i; Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i ) { DdNode * bCof0 = Cudd_Cofactor( dd, bFunc, Cudd_Not(Cudd_bddIthVar(dd, iVar)) ); Cudd_Ref( bCof0 ); DdNode * bCof1 = Cudd_Cofactor( dd, bFunc, Cudd_bddIthVar(dd, iVar) ); Cudd_Ref( bCof1 ); Vec_PtrPush( vNew, bCof0 ); Vec_PtrPush( vNew, bCof1 ); } return vNew; } void Gia_ManRecurDsd( Gia_Man_t * p, int fVerbose ) { DdManager * dd; Dsd_Manager_t * pManDsd; Vec_Ptr_t * vFuncs, * vAux; dd = Cudd_Init( Gia_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); vFuncs = Gia_ManCollapse( p, dd, 10000, 0 ); Cudd_AutodynDisable( dd ); if ( vFuncs == NULL ) { Extra_StopManager( dd ); return; } pManDsd = Dsd_ManagerStart( dd, Gia_ManCiNum(p), 0 ); if ( pManDsd == NULL ) { Gia_ManCollapseDeref( dd, vFuncs ); Cudd_Quit( dd ); return; } Dsd_Decompose( pManDsd, (DdNode **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs) ); printf( "Function:\n" ); Gia_ManPrintDsd( pManDsd, 0, Vec_PtrSize(vFuncs), 0 ); for ( int i = 0; i < 5 && Dsd_TreeNonDsdMax(pManDsd, -1) > 0; i++ ) { int v, iBestV = -1, DsdMin = ABC_INFINITY, SuppMin = ABC_INFINITY; for ( v = 0; v < Gia_ManCiNum(p); v++ ) { Vec_Ptr_t * vTemp = Gia_ManRecurDsdCof( dd, vFuncs, v ); Dsd_Decompose( pManDsd, (DdNode **)Vec_PtrArray(vTemp), Vec_PtrSize(vTemp) ); int DsdCur = Dsd_TreeNonDsdMax( pManDsd, -1 ); int SuppCur = Dsd_TreeSuppSize( pManDsd, -1 ); if ( DsdMin > DsdCur || (DsdMin == DsdCur && SuppMin > SuppCur) ) DsdMin = DsdCur, SuppMin = SuppCur, iBestV = v; Gia_ManCollapseDeref( dd, vTemp ); } assert( iBestV >= 0 ); vFuncs = Gia_ManRecurDsdCof( dd, vAux = vFuncs, iBestV ); Gia_ManCollapseDeref( dd, vAux ); printf( "Cofactoring variable %c:\n", (int)(iBestV >= 26 ? 'A' - 26 : 'a') + iBestV ); Dsd_Decompose( pManDsd, (DdNode **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs) ); Gia_ManPrintDsd( pManDsd, -1, Vec_PtrSize(vFuncs), (i+1)*2 ); } Dsd_ManagerStop( pManDsd ); Gia_ManCollapseDeref( dd, vFuncs ); Extra_StopManager( dd ); } #else Gia_Man_t * Gia_ManCollapseTest( Gia_Man_t * p, int fVerbose ) { return NULL; } void Gia_ManCheckDsd( Gia_Man_t * p, int OffSet, int fVerbose ) { } void Gia_ManRecurDsd( Gia_Man_t * p, int fVerbose ) { } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaCof.c000066400000000000000000001117721477524141600156340ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaCof.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Cofactor estimation procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaCof.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Cof_Fan_t_ Cof_Fan_t; struct Cof_Fan_t_ { unsigned iFan : 31; // ID of the fanin/fanout unsigned fCompl : 1; // complemented attribute }; typedef struct Cof_Obj_t_ Cof_Obj_t; struct Cof_Obj_t_ { unsigned fTerm : 1; // terminal node (CI/CO) unsigned fPhase : 1; // value under 000 pattern unsigned fMark0 : 1; // first user-controlled mark unsigned fMark1 : 1; // second user-controlled mark unsigned nFanins : 4; // the number of fanins unsigned nFanouts : 24; // total number of fanouts unsigned nFanoutsM; // total number of MUX ctrl fanouts unsigned Value; // application specific data int Id; // ID of the node int iNext; // next one in the linked list int iLit; // literal of the node after rehashing Cof_Fan_t Fanios[0]; // the array of fanins/fanouts }; typedef struct Cof_Man_t_ Cof_Man_t; struct Cof_Man_t_ { Gia_Man_t * pGia; // the original AIG manager Vec_Int_t * vCis; // the vector of CIs (PIs + LOs) Vec_Int_t * vCos; // the vector of COs (POs + LIs) int nObjs; // the number of objects int nNodes; // the number of nodes int nTravIds; // traversal ID of the network int * pObjData; // the logic network defined for the AIG int nObjData; // the size of array to store the logic network int * pLevels; // the linked lists of levels int nLevels; // the max number of logic levels }; static inline unsigned Gia_ObjHandle( Gia_Obj_t * pObj ) { return pObj->Value; } static inline int Cof_ObjLevel( Cof_Man_t * p, Cof_Obj_t * pObj ) { return Gia_ObjLevel(p->pGia, Gia_ManObj(p->pGia,pObj->Id)); } static inline unsigned Cof_ObjHandle( Cof_Man_t * p, Cof_Obj_t * pObj ) { return (unsigned)(((int *)pObj) - p->pObjData); } static inline unsigned Cof_ObjHandleDiff( Cof_Obj_t * pObj, Cof_Obj_t * pFanin ) { return (unsigned)(((int *)pObj) - ((int *)pFanin)); } static inline int Cof_ObjIsTerm( Cof_Obj_t * pObj ) { return pObj->fTerm; } static inline int Cof_ObjIsCi( Cof_Obj_t * pObj ) { return pObj->fTerm && pObj->nFanins == 0; } static inline int Cof_ObjIsCo( Cof_Obj_t * pObj ) { return pObj->fTerm && pObj->nFanins == 1; } static inline int Cof_ObjIsNode( Cof_Obj_t * pObj ) { return!pObj->fTerm && pObj->nFanins > 0; } static inline int Cof_ObjIsConst0( Cof_Obj_t * pObj ) { return!pObj->fTerm && pObj->nFanins == 0; } static inline int Cof_ObjFaninNum( Cof_Obj_t * pObj ) { return pObj->nFanins; } static inline int Cof_ObjFanoutNum( Cof_Obj_t * pObj ) { return pObj->nFanouts; } static inline int Cof_ObjSize( Cof_Obj_t * pObj ) { return sizeof(Cof_Obj_t) / 4 + pObj->nFanins + pObj->nFanouts; } static inline Cof_Obj_t * Cof_ManObj( Cof_Man_t * p, unsigned iHandle ) { return (Cof_Obj_t *)(p->pObjData + iHandle); } static inline Cof_Obj_t * Cof_ObjFanin( Cof_Obj_t * pObj, int i ) { return (Cof_Obj_t *)(((int *)pObj) - pObj->Fanios[i].iFan); } static inline Cof_Obj_t * Cof_ObjFanout( Cof_Obj_t * pObj, int i ) { return (Cof_Obj_t *)(((int *)pObj) + pObj->Fanios[pObj->nFanins+i].iFan); } static inline int Cof_ManObjNum( Cof_Man_t * p ) { return p->nObjs; } static inline int Cof_ManNodeNum( Cof_Man_t * p ) { return p->nNodes; } static inline void Cof_ManResetTravId( Cof_Man_t * p ) { extern void Cof_ManCleanValue( Cof_Man_t * p ); Cof_ManCleanValue( p ); p->nTravIds = 1; } static inline void Cof_ManIncrementTravId( Cof_Man_t * p ) { p->nTravIds++; } static inline void Cof_ObjSetTravId( Cof_Obj_t * pObj, int TravId ) { pObj->Value = TravId; } static inline void Cof_ObjSetTravIdCurrent( Cof_Man_t * p, Cof_Obj_t * pObj ) { pObj->Value = p->nTravIds; } static inline void Cof_ObjSetTravIdPrevious( Cof_Man_t * p, Cof_Obj_t * pObj ) { pObj->Value = p->nTravIds - 1; } static inline int Cof_ObjIsTravIdCurrent( Cof_Man_t * p, Cof_Obj_t * pObj ) { return ((int)pObj->Value == p->nTravIds); } static inline int Cof_ObjIsTravIdPrevious( Cof_Man_t * p, Cof_Obj_t * pObj ) { return ((int)pObj->Value == p->nTravIds - 1); } #define Cof_ManForEachObj( p, pObj, i ) \ for ( i = 0; (i < p->nObjData) && (pObj = Cof_ManObj(p,i)); i += Cof_ObjSize(pObj) ) #define Cof_ManForEachNode( p, pObj, i ) \ for ( i = 0; (i < p->nObjData) && (pObj = Cof_ManObj(p,i)); i += Cof_ObjSize(pObj) ) if ( Cof_ObjIsTerm(pObj) ) {} else #define Cof_ObjForEachFanin( pObj, pNext, i ) \ for ( i = 0; (i < (int)pObj->nFanins) && (pNext = Cof_ObjFanin(pObj,i)); i++ ) #define Cof_ObjForEachFanout( pObj, pNext, i ) \ for ( i = 0; (i < (int)pObj->nFanouts) && (pNext = Cof_ObjFanout(pObj,i)); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates logic network isomorphic to the given AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cof_Man_t * Cof_ManCreateLogicSimple( Gia_Man_t * pGia ) { Cof_Man_t * p; Cof_Obj_t * pObjLog, * pFanLog; Gia_Obj_t * pObj; int * pMuxRefs; int i, iHandle = 0; p = ABC_CALLOC( Cof_Man_t, 1 ); p->pGia = pGia; p->vCis = Vec_IntAlloc( Gia_ManCiNum(pGia) ); p->vCos = Vec_IntAlloc( Gia_ManCoNum(pGia) ); p->nObjData = (sizeof(Cof_Obj_t) / 4) * Gia_ManObjNum(pGia) + 4 * Gia_ManAndNum(pGia) + 2 * Gia_ManCoNum(pGia); p->pObjData = ABC_CALLOC( int, p->nObjData ); ABC_FREE( pGia->pRefs ); Gia_ManCreateRefs( pGia ); Gia_ManForEachObj( pGia, pObj, i ) { pObj->Value = iHandle; pObjLog = Cof_ManObj( p, iHandle ); pObjLog->nFanins = 0; pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); pObjLog->Id = i; pObjLog->Value = 0; if ( Gia_ObjIsAnd(pObj) ) { pFanLog = Cof_ManObj( p, Gia_ObjHandle(Gia_ObjFanin0(pObj)) ); pFanLog->Fanios[pFanLog->nFanins + pFanLog->Value++].iFan = pObjLog->Fanios[pObjLog->nFanins].iFan = Cof_ObjHandleDiff( pObjLog, pFanLog ); pObjLog->Fanios[pObjLog->nFanins++].fCompl = Gia_ObjFaninC0(pObj); pFanLog = Cof_ManObj( p, Gia_ObjHandle(Gia_ObjFanin1(pObj)) ); pFanLog->Fanios[pFanLog->nFanins + pFanLog->Value++].iFan = pObjLog->Fanios[pObjLog->nFanins].iFan = Cof_ObjHandleDiff( pObjLog, pFanLog ); pObjLog->Fanios[pObjLog->nFanins++].fCompl = Gia_ObjFaninC1(pObj); p->nNodes++; } else if ( Gia_ObjIsCo(pObj) ) { pFanLog = Cof_ManObj( p, Gia_ObjHandle(Gia_ObjFanin0(pObj)) ); pFanLog->Fanios[pFanLog->nFanins + pFanLog->Value++].iFan = pObjLog->Fanios[pObjLog->nFanins].iFan = Cof_ObjHandleDiff( pObjLog, pFanLog ); pObjLog->Fanios[pObjLog->nFanins++].fCompl = Gia_ObjFaninC0(pObj); pObjLog->fTerm = 1; Vec_IntPush( p->vCos, iHandle ); } else if ( Gia_ObjIsCi(pObj) ) { pObjLog->fTerm = 1; Vec_IntPush( p->vCis, iHandle ); } iHandle += Cof_ObjSize( pObjLog ); p->nObjs++; } assert( iHandle == p->nObjData ); pMuxRefs = Gia_ManCreateMuxRefs( pGia ); Gia_ManForEachObj( pGia, pObj, i ) { pObjLog = Cof_ManObj( p, Gia_ObjHandle(pObj) ); assert( pObjLog->nFanouts == pObjLog->Value ); pObjLog->nFanoutsM = pMuxRefs[i]; } ABC_FREE( pMuxRefs ); return p; } /**Function************************************************************* Synopsis [Creates logic network isomorphic to the given AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cof_ManStop( Cof_Man_t * p ) { Vec_IntFree( p->vCis ); Vec_IntFree( p->vCos ); ABC_FREE( p->pObjData ); ABC_FREE( p->pLevels ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Collects support nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cof_ManTfoSize_rec( Cof_Man_t * p, Cof_Obj_t * pObj ) { Cof_Obj_t * pNext; unsigned i, Counter = 0; if ( Cof_ObjIsTravIdCurrent(p, pObj) ) return 0; Cof_ObjSetTravIdCurrent(p, pObj); if ( Cof_ObjIsCo(pObj) ) return 0; assert( Cof_ObjIsCi(pObj) || Cof_ObjIsNode(pObj) ); Cof_ObjForEachFanout( pObj, pNext, i ) Counter += Cof_ManTfoSize_rec( p, pNext ); return 1 + Counter; } /**Function************************************************************* Synopsis [Collects support nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cof_ManTfoSize( Cof_Man_t * p, Cof_Obj_t ** ppObjs, int nObjs ) { int i, Counter = 0; Cof_ManIncrementTravId( p ); for ( i = 0; i < nObjs; i++ ) Counter += Cof_ManTfoSize_rec( p, ppObjs[i] ) - 1; return Counter; } /**Function************************************************************* Synopsis [Collects support nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cof_ManTfiSize_rec( Cof_Man_t * p, Cof_Obj_t * pObj ) { Cof_Obj_t * pNext; unsigned i, Counter = 0; if ( Cof_ObjIsTravIdCurrent(p, pObj) ) return 0; Cof_ObjSetTravIdCurrent(p, pObj); if ( Cof_ObjIsCi(pObj) ) return 0; assert( Cof_ObjIsNode(pObj) ); Cof_ObjForEachFanin( pObj, pNext, i ) Counter += Cof_ManTfiSize_rec( p, pNext ); return 1 + Counter; } /**Function************************************************************* Synopsis [Collects support nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cof_ManTfiSize( Cof_Man_t * p, Cof_Obj_t ** ppObjs, int nObjs ) { int i, Counter = 0; Cof_ManIncrementTravId( p ); for ( i = 0; i < nObjs; i++ ) if ( Cof_ObjIsCo(ppObjs[i]) ) Counter += Cof_ManTfiSize_rec( p, Cof_ObjFanin(ppObjs[i],0) ); else Counter += Cof_ManTfiSize_rec( p, ppObjs[i] ); return Counter; } /**Function************************************************************* Synopsis [Collects support nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cof_ManSuppSize_rec( Cof_Man_t * p, Cof_Obj_t * pObj ) { Cof_Obj_t * pNext; unsigned i, Counter = 0; if ( Cof_ObjIsTravIdCurrent(p, pObj) ) return 0; Cof_ObjSetTravIdCurrent(p, pObj); if ( Cof_ObjIsCi(pObj) ) return 1; assert( Cof_ObjIsNode(pObj) ); Cof_ObjForEachFanin( pObj, pNext, i ) Counter += Cof_ManSuppSize_rec( p, pNext ); return Counter; } /**Function************************************************************* Synopsis [Collects support nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cof_ManSuppSize( Cof_Man_t * p, Cof_Obj_t ** ppObjs, int nObjs ) { int i, Counter = 0; Cof_ManIncrementTravId( p ); for ( i = 0; i < nObjs; i++ ) if ( Cof_ObjIsCo(ppObjs[i]) ) Counter += Cof_ManSuppSize_rec( p, Cof_ObjFanin(ppObjs[i],0) ); else Counter += Cof_ManSuppSize_rec( p, ppObjs[i] ); return Counter; } /**Function************************************************************* Synopsis [Cleans the value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cof_ManCleanValue( Cof_Man_t * p ) { Cof_Obj_t * pObj; int i; Cof_ManForEachObj( p, pObj, i ) pObj->Value = 0; } /**Function************************************************************* Synopsis [Returns sorted array of node handles with largest fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cof_ManInsertEntry_rec( Vec_Ptr_t * vNodes, Cof_Obj_t * pNode, int nNodeMax ) { Cof_Obj_t * pLast; if ( Vec_PtrSize(vNodes) == 0 ) { Vec_PtrPush(vNodes, pNode); return; } pLast = (Cof_Obj_t *)Vec_PtrPop(vNodes); if ( Cof_ObjFanoutNum(pLast) < Cof_ObjFanoutNum(pNode) ) { Cof_ManInsertEntry_rec( vNodes, pNode, nNodeMax ); if ( Vec_PtrSize(vNodes) < nNodeMax ) Vec_PtrPush( vNodes, pLast ); } else { Vec_PtrPush( vNodes, pLast ); if ( Vec_PtrSize(vNodes) < nNodeMax ) Vec_PtrPush( vNodes, pNode ); } } /**Function************************************************************* Synopsis [Returns sorted array of node handles with largest fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Cof_ManCollectHighFanout( Cof_Man_t * p, int nNodes ) { Vec_Ptr_t * vNodes; Cof_Obj_t * pObj; int i; vNodes = Vec_PtrAlloc( nNodes ); Cof_ManForEachObj( p, pObj, i ) if ( Cof_ObjIsCi(pObj) || Cof_ObjIsNode(pObj) ) Cof_ManInsertEntry_rec( vNodes, pObj, nNodes ); return vNodes; } /**Function************************************************************* Synopsis [Returns sorted array of node handles with largest fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cof_ManCountRemoved( Cof_Man_t * p, Cof_Obj_t * pRoot, int fConst1 ) { Gia_Obj_t * pNextGia; Cof_Obj_t * pTemp, * pNext, * pFanin0, * pFanin1; int Counter = 0, LevelStart, LevelNext; int i, k, iHandle, iLit0, iLit1, iNextNew; // restart the trav ids Cof_ManIncrementTravId( p ); Cof_ObjSetTravIdCurrent( p, pRoot ); // add the node to the queue LevelStart = Cof_ObjLevel(p, pRoot); assert( p->pLevels[LevelStart] == 0 ); pRoot->iNext = 0; p->pLevels[LevelStart] = Cof_ObjHandle( p, pRoot ); // set the new literal pRoot->iLit = Abc_Var2Lit( 0, fConst1 ); // process nodes in the levelized order for ( i = LevelStart; i < p->nLevels; i++ ) { for ( iHandle = p->pLevels[i]; iHandle && (pTemp = Cof_ManObj(p, iHandle)); iHandle = pTemp->iNext ) { assert( pTemp->Id != Abc_Lit2Var(pTemp->iLit) ); Cof_ObjForEachFanout( pTemp, pNext, k ) { if ( Cof_ObjIsCo(pNext) ) continue; if ( Cof_ObjIsTravIdCurrent(p, pNext) ) continue; pFanin0 = Cof_ObjFanin( pNext, 0 ); pFanin1 = Cof_ObjFanin( pNext, 1 ); assert( pFanin0 == pTemp || pFanin1 == pTemp ); pNextGia = Gia_ManObj( p->pGia, pNext->Id ); if ( Cof_ObjIsTravIdCurrent(p, pFanin0) ) iLit0 = Abc_LitNotCond( pFanin0->iLit, Gia_ObjFaninC0(pNextGia) ); else iLit0 = Gia_ObjFaninLit0( pNextGia, pNext->Id ); if ( Cof_ObjIsTravIdCurrent(p, pFanin1) ) iLit1 = Abc_LitNotCond( pFanin1->iLit, Gia_ObjFaninC1(pNextGia) ); else iLit1 = Gia_ObjFaninLit1( pNextGia, pNext->Id ); iNextNew = Gia_ManHashAndTry( p->pGia, iLit0, iLit1 ); if ( iNextNew == -1 ) continue; Cof_ObjSetTravIdCurrent(p, pNext); // set the new literal pNext->iLit = iNextNew; // add it to be processed LevelNext = Cof_ObjLevel( p, pNext ); assert( LevelNext > i && LevelNext < p->nLevels ); pNext->iNext = p->pLevels[LevelNext]; p->pLevels[LevelNext] = Cof_ObjHandle( p, pNext ); Counter++; } } p->pLevels[i] = 0; } return Counter; } /**Function************************************************************* Synopsis [Returns sorted array of node handles with largest fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cof_ManPrintHighFanoutOne( Cof_Man_t * p, Cof_Obj_t * pObj ) { printf( "%7d : ", pObj->Id ); printf( "i/o/c =%2d %5d %5d ", Cof_ObjFaninNum(pObj), Cof_ObjFanoutNum(pObj), 2*pObj->nFanoutsM ); printf( "l =%4d ", Cof_ObjLevel(p, pObj) ); printf( "s =%5d ", Cof_ManSuppSize(p, &pObj, 1) ); printf( "TFI =%7d ", Cof_ManTfiSize(p, &pObj, 1) ); printf( "TFO =%7d ", Cof_ManTfoSize(p, &pObj, 1) ); printf( "C0 =%6d ", Cof_ManCountRemoved(p, pObj, 0) ); printf( "C1 =%6d", Cof_ManCountRemoved(p, pObj, 1) ); printf( "\n" ); } /**Function************************************************************* Synopsis [Returns sorted array of node handles with largest fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cof_ManPrintHighFanout( Cof_Man_t * p, int nNodes ) { Vec_Ptr_t * vNodes; Cof_Obj_t * pObj; int i; vNodes = Cof_ManCollectHighFanout( p, nNodes ); Vec_PtrForEachEntry( Cof_Obj_t *, vNodes, pObj, i ) Cof_ManPrintHighFanoutOne( p, pObj ); Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Compute MFFC size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Cof_NodeDeref_rec( Cof_Obj_t * pNode ) { if ( pNode->nFanins == 0 ) return 0; if ( --pNode->nFanouts > 0 ) return 0; return 1 + Cof_NodeDeref_rec( Cof_ObjFanin(pNode, 0) ) + Cof_NodeDeref_rec( Cof_ObjFanin(pNode, 1) ); } int Cof_NodeRef_rec( Cof_Obj_t * pNode ) { if ( pNode->nFanins == 0 ) return 0; if ( pNode->nFanouts++ > 0 ) return 0; return 1 + Cof_NodeRef_rec( Cof_ObjFanin(pNode, 0) ) + Cof_NodeRef_rec( Cof_ObjFanin(pNode, 1) ); } static inline int Cof_ObjMffcSize( Cof_Obj_t * pNode ) { int Count1, Count2, nFanout; nFanout = pNode->nFanouts; pNode->nFanouts = 1; Count1 = Cof_NodeDeref_rec( pNode ); Count2 = Cof_NodeRef_rec( pNode ); pNode->nFanouts = nFanout; assert( Count1 == Count2 ); return Count1; } /**Function************************************************************* Synopsis [Prints the distribution of fanins/fanouts in the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cof_ManPrintFanio( Cof_Man_t * p ) { char Buffer[100]; Cof_Obj_t * pNode; Vec_Int_t * vFanins, * vFanouts, * vMffcs; int nFanins, nFanouts, nMffcs, nFaninsMax, nFanoutsMax, nMffcsMax, nFaninsAll, nFanoutsAll, nMffcsAll; int i, k, nSizeMax, nMffcNodes = 0; // determine the largest fanin and fanout nFaninsMax = nFanoutsMax = nMffcsMax = 0; nFaninsAll = nFanoutsAll = nMffcsAll = 0; Cof_ManForEachNode( p, pNode, i ) { if ( i == 0 ) continue; nFanins = Cof_ObjFaninNum(pNode); nFanouts = Cof_ObjFanoutNum(pNode); nMffcs = pNode->nFanouts > 1 ? Cof_ObjMffcSize(pNode) : 0; nFaninsAll += nFanins; nFanoutsAll += nFanouts; nMffcsAll += nMffcs; nFaninsMax = Abc_MaxInt( nFaninsMax, nFanins ); nFanoutsMax = Abc_MaxInt( nFanoutsMax, nFanouts ); nMffcsMax = Abc_MaxInt( nMffcsMax, nMffcs ); } // allocate storage for fanin/fanout numbers nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nFaninsMax) + 1), 10 * (Abc_Base10Log(nFanoutsMax) + 1) ); nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nMffcsMax) + 1), nSizeMax ); vFanins = Vec_IntStart( nSizeMax ); vFanouts = Vec_IntStart( nSizeMax ); vMffcs = Vec_IntStart( nSizeMax ); // count the number of fanins and fanouts Cof_ManForEachNode( p, pNode, i ) { if ( i == 0 ) continue; nFanins = Cof_ObjFaninNum(pNode); nFanouts = Cof_ObjFanoutNum(pNode); nMffcs = pNode->nFanouts > 1 ? Cof_ObjMffcSize(pNode) : 0; if ( nFanins < 10 ) Vec_IntAddToEntry( vFanins, nFanins, 1 ); else if ( nFanins < 100 ) Vec_IntAddToEntry( vFanins, 10 + nFanins/10, 1 ); else if ( nFanins < 1000 ) Vec_IntAddToEntry( vFanins, 20 + nFanins/100, 1 ); else if ( nFanins < 10000 ) Vec_IntAddToEntry( vFanins, 30 + nFanins/1000, 1 ); else if ( nFanins < 100000 ) Vec_IntAddToEntry( vFanins, 40 + nFanins/10000, 1 ); else if ( nFanins < 1000000 ) Vec_IntAddToEntry( vFanins, 50 + nFanins/100000, 1 ); else if ( nFanins < 10000000 ) Vec_IntAddToEntry( vFanins, 60 + nFanins/1000000, 1 ); if ( nFanouts < 10 ) Vec_IntAddToEntry( vFanouts, nFanouts, 1 ); else if ( nFanouts < 100 ) Vec_IntAddToEntry( vFanouts, 10 + nFanouts/10, 1 ); else if ( nFanouts < 1000 ) Vec_IntAddToEntry( vFanouts, 20 + nFanouts/100, 1 ); else if ( nFanouts < 10000 ) Vec_IntAddToEntry( vFanouts, 30 + nFanouts/1000, 1 ); else if ( nFanouts < 100000 ) Vec_IntAddToEntry( vFanouts, 40 + nFanouts/10000, 1 ); else if ( nFanouts < 1000000 ) Vec_IntAddToEntry( vFanouts, 50 + nFanouts/100000, 1 ); else if ( nFanouts < 10000000 ) Vec_IntAddToEntry( vFanouts, 60 + nFanouts/1000000, 1 ); if ( nMffcs == 0 ) continue; nMffcNodes++; if ( nMffcs < 10 ) Vec_IntAddToEntry( vMffcs, nMffcs, 1 ); else if ( nMffcs < 100 ) Vec_IntAddToEntry( vMffcs, 10 + nMffcs/10, 1 ); else if ( nMffcs < 1000 ) Vec_IntAddToEntry( vMffcs, 20 + nMffcs/100, 1 ); else if ( nMffcs < 10000 ) Vec_IntAddToEntry( vMffcs, 30 + nMffcs/1000, 1 ); else if ( nMffcs < 100000 ) Vec_IntAddToEntry( vMffcs, 40 + nMffcs/10000, 1 ); else if ( nMffcs < 1000000 ) Vec_IntAddToEntry( vMffcs, 50 + nMffcs/100000, 1 ); else if ( nMffcs < 10000000 ) Vec_IntAddToEntry( vMffcs, 60 + nMffcs/1000000, 1 ); } printf( "The distribution of fanins, fanouts. and MFFCs in the network:\n" ); printf( " Number Nodes with fanin Nodes with fanout Nodes with MFFC\n" ); for ( k = 0; k < nSizeMax; k++ ) { if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 && vMffcs->pArray[k] == 0 ) continue; if ( k < 10 ) printf( "%15d : ", k ); else { sprintf( Buffer, "%d - %d", (int)pow((double)10, k/10) * (k%10), (int)pow((double)10, k/10) * (k%10+1) - 1 ); printf( "%15s : ", Buffer ); } if ( vFanins->pArray[k] == 0 ) printf( " " ); else printf( "%11d ", vFanins->pArray[k] ); printf( " " ); if ( vFanouts->pArray[k] == 0 ) printf( " " ); else printf( "%12d ", vFanouts->pArray[k] ); printf( " " ); if ( vMffcs->pArray[k] == 0 ) printf( " " ); else printf( " %12d ", vMffcs->pArray[k] ); printf( "\n" ); } Vec_IntFree( vFanins ); Vec_IntFree( vFanouts ); Vec_IntFree( vMffcs ); printf( "Fanins: Max = %d. Ave = %.2f. Fanouts: Max = %d. Ave = %.2f. MFFCs: Max = %d. Ave = %.2f.\n", nFaninsMax, 1.0*nFaninsAll /Cof_ManNodeNum(p), nFanoutsMax, 1.0*nFanoutsAll/Cof_ManNodeNum(p), nMffcsMax, 1.0*nMffcsAll /nMffcNodes ); } /**Function************************************************************* Synopsis [Returns sorted array of node handles with largest fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintFanio( Gia_Man_t * pGia, int nNodes ) { Cof_Man_t * p; abctime clk = Abc_Clock(); p = Cof_ManCreateLogicSimple( pGia ); p->nLevels = 1 + Gia_ManLevelNum( pGia ); p->pLevels = ABC_CALLOC( int, p->nLevels ); Cof_ManPrintFanio( p ); if ( nNodes > 0 ) { Cof_ManResetTravId( p ); Gia_ManHashStart( pGia ); Cof_ManPrintHighFanout( p, nNodes ); Gia_ManHashStop( pGia ); ABC_PRMn( "Memory for logic network", 4*p->nObjData ); ABC_PRT( "Time", Abc_Clock() - clk ); } Cof_ManStop( p ); } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order while putting CIs first.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupCofInt( Gia_Man_t * p, int iVar ) { Gia_Man_t * pNew; Gia_Obj_t * pObj, * pPivot; int i, iCofVar = -1; if ( !(iVar > 0 && iVar < Gia_ManObjNum(p)) ) { printf( "Gia_ManDupCof(): Variable %d is out of range (%d; %d).\n", iVar, 0, Gia_ManObjNum(p) ); return NULL; } // find the cofactoring variable pPivot = Gia_ManObj( p, iVar ); if ( !Gia_ObjIsCand(pPivot) ) { printf( "Gia_ManDupCof(): Variable %d should be a CI or an AND node.\n", iVar ); return NULL; } 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; // compute negative cofactor Gia_ManForEachCi( p, pObj, i ) { pObj->Value = Gia_ManAppendCi(pNew); if ( pObj == pPivot ) { iCofVar = pObj->Value; pObj->Value = Abc_Var2Lit( 0, 0 ); } } Gia_ManForEachAnd( p, pObj, i ) { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( pObj == pPivot ) { iCofVar = pObj->Value; pObj->Value = Abc_Var2Lit( 0, 0 ); } } Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); // compute the positive cofactor Gia_ManForEachCi( p, pObj, i ) { pObj->Value = Abc_Var2Lit( Gia_ObjId(pNew, Gia_ManCi(pNew, i)), 0 ); if ( pObj == pPivot ) pObj->Value = Abc_Var2Lit( 0, 1 ); } Gia_ManForEachAnd( p, pObj, i ) { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( pObj == pPivot ) pObj->Value = Abc_Var2Lit( 0, 1 ); } // create MUXes assert( iCofVar > 0 ); Gia_ManForEachCo( p, pObj, i ) { if ( pObj->Value == (unsigned)Gia_ObjFanin0Copy(pObj) ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); else pObj->Value = Gia_ManAppendCo( pNew, Gia_ManHashMux(pNew, iCofVar, Gia_ObjFanin0Copy(pObj), pObj->Value) ); } Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order while putting CIs first.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupCof( Gia_Man_t * p, int iVar ) { Gia_Man_t * pNew, * pTemp; pNew = Gia_ManDupCofInt( p, iVar ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Determines variables whose fanout count is higher than this.] Description [Variables are returned in a reverse topological order.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManCofVars( Gia_Man_t * p, int nFanLim ) { Vec_Int_t * vVars; Gia_Obj_t * pObj; int i; ABC_FREE( p->pRefs ); Gia_ManCreateRefs( p ); vVars = Vec_IntAlloc( 100 ); Gia_ManForEachObj( p, pObj, i ) if ( Gia_ObjIsCand(pObj) && Gia_ObjRefNum(p, pObj) >= nFanLim ) Vec_IntPush( vVars, i ); ABC_FREE( p->pRefs ); return vVars; } /**Function************************************************************* Synopsis [Transfers attributes from the original one to the final one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManTransfer( Gia_Man_t * pAig, Gia_Man_t * pCof, Gia_Man_t * pNew, Vec_Int_t * vSigs ) { Vec_Int_t * vSigsNew; Gia_Obj_t * pObj, * pObjF; int i; vSigsNew = Vec_IntAlloc( 100 ); Gia_ManForEachObjVec( vSigs, pAig, pObj, i ) { assert( Gia_ObjIsCand(pObj) ); pObjF = Gia_ManObj( pCof, Abc_Lit2Var(pObj->Value) ); if ( pObjF->Value && ~pObjF->Value ) Vec_IntPushUnique( vSigsNew, Abc_Lit2Var(pObjF->Value) ); } return vSigsNew; } /**Function************************************************************* Synopsis [Cofactors selected variables (should be in reverse topo order).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupCofAllInt( Gia_Man_t * p, Vec_Int_t * vSigs, int fVerbose ) { Vec_Int_t * vSigsNew, * vTemp; Gia_Man_t * pAig, * pCof, * pNew; int iVar; if ( fVerbose ) { printf( "Cofactoring %d signals.\n", Vec_IntSize(vSigs) ); Gia_ManPrintStats( p, NULL ); } if ( Vec_IntSize( vSigs ) > 200 ) { printf( "Too many signals to cofactor.\n" ); return NULL; } pAig = Gia_ManDup( p ); vSigsNew = Vec_IntDup( vSigs ); while ( Vec_IntSize(vSigsNew) > 0 ) { Vec_IntSort( vSigsNew, 0 ); iVar = Vec_IntPop( vSigsNew ); // Gia_ManCreateRefs( pAig ); // printf( "ref count = %d\n", Gia_ObjRefNum( pAig, Gia_ManObj(pAig, iVar) ) ); // ABC_FREE( pAig->pRefs ); pCof = Gia_ManDupCofInt( pAig, iVar ); pNew = Gia_ManCleanup( pCof ); vSigsNew = Gia_ManTransfer( pAig, pCof, pNew, vTemp = vSigsNew ); Vec_IntFree( vTemp ); Gia_ManStop( pAig ); Gia_ManStop( pCof ); pAig = pNew; if ( fVerbose ) printf( "Cofactored variable %d.\n", iVar ); if ( fVerbose ) Gia_ManPrintStats( pAig, NULL ); } Vec_IntFree( vSigsNew ); return pAig; } /**Function************************************************************* Synopsis [Cofactors all variables whose fanout is higher than this.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupCofAll( Gia_Man_t * p, int nFanLim, int fVerbose ) { Gia_Man_t * pNew; Vec_Int_t * vSigs = Gia_ManCofVars( p, nFanLim ); pNew = Gia_ManDupCofAllInt( p, vSigs, fVerbose ); Vec_IntFree( vSigs ); return pNew; } /**Function************************************************************* Synopsis [Print the matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDsdMatrix( Gia_Man_t * p, int iIn ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, j; Vec_Int_t * vRes = Vec_IntAlloc( 100 ); assert( Gia_ManPoNum(p) == 1 ); assert( iIn >= 0 && iIn < Gia_ManPiNum(p) ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); for ( i = 0; i < Gia_ManPiNum(p); i++ ) if ( i != iIn ) for ( j = i+1; j < Gia_ManPiNum(p); j++ ) if ( j != iIn ) { int pRes[8], k, n; int iLit0 = Gia_ManPi(p, iIn)->Value; int iLit1 = Gia_ManPi(p, i)->Value; int iLit2 = Gia_ManPi(p, j)->Value; for ( k = 0; k < 8; k++ ) { Gia_ManPi(p, iIn)->Value = k & 1; Gia_ManPi(p, i)->Value = (k >> 1) & 1; Gia_ManPi(p, j)->Value = (k >> 2) & 1; Gia_ManForEachAnd( p, pObj, n ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); pRes[k] = Gia_ObjFanin0Copy(Gia_ManPo(p, 0)); } Gia_ManPi(p, iIn)->Value = iLit0; Gia_ManPi(p, i)->Value = iLit1; Gia_ManPi(p, j)->Value = iLit2; for ( k = 0; k < 4; k++ ) pRes[k] = Gia_ManHashXor( pNew, pRes[2*k], pRes[2*k+1] ); Vec_IntPush( vRes, Gia_ManHashXor(pNew, Gia_ManHashAnd(pNew, pRes[0], pRes[3]), Gia_ManHashAnd(pNew, pRes[1], pRes[2])) ); } Vec_IntForEachEntry( vRes, j, i ) Gia_ManAppendCo( pNew, j ); Vec_IntFree( vRes ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } void Gia_ManPrintDsdMatrix( Gia_Man_t * p, int iIn ) { extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); Gia_Man_t * pNew = Gia_ManDsdMatrix( p, iIn ); int i, j, fFirst = 1, Count = 0; Gia_Man_t * pSweep = Cec4_ManSimulateTest3( pNew, 0, 0 ); Gia_ManStop( pNew ); printf( "%4c : ", ' ' ); for ( j = 0; j < Gia_ManPiNum(p); j++ ) printf( "%4d", j ); printf( "\n" ); for ( i = 0; i < Gia_ManPiNum(p); i++, printf("\n"), fFirst = 1 ) for ( j = 0; j < Gia_ManPiNum(p); j++ ) { if ( fFirst ) printf( "%4d : ", i ), fFirst = 0; if ( i == iIn ) continue; if ( j == iIn ) printf( "%4c", ' ' ); else { if ( j > i ) { if ( Gia_ObjFaninLit0p(pSweep, Gia_ManPo(pSweep, Count++)) == 0 ) printf( "%4c", '.' ); else printf( "%4c", '+' ); } else printf( "%4c", ' ' ); } } assert( Count == Gia_ManPoNum(pSweep) ); Gia_ManStop( pSweep ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaCone.c000066400000000000000000000423111477524141600160010ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaCone.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: giaCone.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/extra/extra.h" #include "misc/vec/vecHsh.h" #include "misc/vec/vecWec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Opa_Man_t_ Opa_Man_t; struct Opa_Man_t_ { Gia_Man_t * pGia; Vec_Int_t * vFront; Vec_Int_t * pvParts; int * pId2Part; int nParts; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Opa_Man_t * Opa_ManStart( Gia_Man_t * pGia) { Opa_Man_t * p; Gia_Obj_t * pObj; int i; p = ABC_CALLOC( Opa_Man_t, 1 ); p->pGia = pGia; p->pvParts = ABC_CALLOC( Vec_Int_t, Gia_ManPoNum(pGia) ); p->pId2Part = ABC_FALLOC( int, Gia_ManObjNum(pGia) ); p->vFront = Vec_IntAlloc( 100 ); Gia_ManForEachPo( pGia, pObj, i ) { Vec_IntPush( p->pvParts + i, Gia_ObjId(pGia, pObj) ); p->pId2Part[Gia_ObjId(pGia, pObj)] = i; Vec_IntPush( p->vFront, Gia_ObjId(pGia, pObj) ); } p->nParts = Gia_ManPoNum(pGia); return p; } static inline void Opa_ManStop( Opa_Man_t * p ) { int i; Vec_IntFree( p->vFront ); for ( i = 0; i < Gia_ManPoNum(p->pGia); i++ ) ABC_FREE( p->pvParts[i].pArray ); ABC_FREE( p->pvParts ); ABC_FREE( p->pId2Part ); ABC_FREE( p ); } static inline void Opa_ManPrint( Opa_Man_t * p ) { int i, k; printf( "Groups:\n" ); for ( i = 0; i < Gia_ManPoNum(p->pGia); i++ ) { if ( p->pvParts[i].nSize == 0 ) continue; printf( "%3d : ", i ); for ( k = 0; k < p->pvParts[i].nSize; k++ ) printf( "%d ", p->pvParts[i].pArray[k] ); printf( "\n" ); } } static inline void Opa_ManPrint2( Opa_Man_t * p ) { Gia_Obj_t * pObj; int i, k, Count; printf( "Groups %d: ", p->nParts ); for ( i = 0; i < Gia_ManPoNum(p->pGia); i++ ) { if ( p->pvParts[i].nSize == 0 ) continue; // count POs in this group Count = 0; Gia_ManForEachObjVec( p->pvParts + i, p->pGia, pObj, k ) Count += Gia_ObjIsPo(p->pGia, pObj); printf( "%d ", Count ); } printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Opa_ManMoveOne( Opa_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanin ) { int iObj = Gia_ObjId(p->pGia, pObj); int iFanin = Gia_ObjId(p->pGia, pFanin); if ( iFanin == 0 ) return; assert( p->pId2Part[ iObj ] >= 0 ); if ( p->pId2Part[ iFanin ] == -1 ) { p->pId2Part[ iFanin ] = p->pId2Part[ iObj ]; Vec_IntPush( p->pvParts + p->pId2Part[ iObj ], iFanin ); assert( Gia_ObjIsCi(pFanin) || Gia_ObjIsAnd(pFanin) ); if ( Gia_ObjIsAnd(pFanin) ) Vec_IntPush( p->vFront, iFanin ); else if ( Gia_ObjIsRo(p->pGia, pFanin) ) { pFanin = Gia_ObjRoToRi(p->pGia, pFanin); iFanin = Gia_ObjId(p->pGia, pFanin); assert( p->pId2Part[ iFanin ] == -1 ); p->pId2Part[ iFanin ] = p->pId2Part[ iObj ]; Vec_IntPush( p->pvParts + p->pId2Part[ iObj ], iFanin ); Vec_IntPush( p->vFront, iFanin ); } } else if ( p->pId2Part[ iObj ] != p->pId2Part[ iFanin ] ) { Vec_Int_t * vPartObj = p->pvParts + p->pId2Part[ iObj ]; Vec_Int_t * vPartFan = p->pvParts + p->pId2Part[ iFanin ]; int iTemp, i; // printf( "Moving %d to %d (%d -> %d)\n", iObj, iFanin, Vec_IntSize(vPartObj), Vec_IntSize(vPartFan) ); // add group of iObj to group of iFanin assert( Vec_IntSize(vPartObj) > 0 ); Vec_IntForEachEntry( vPartObj, iTemp, i ) { Vec_IntPush( vPartFan, iTemp ); p->pId2Part[ iTemp ] = p->pId2Part[ iFanin ]; } Vec_IntShrink( vPartObj, 0 ); p->nParts--; } } void Opa_ManPerform( Gia_Man_t * pGia ) { Opa_Man_t * p; Gia_Obj_t * pObj; int i, Limit, Count = 0; p = Opa_ManStart( pGia ); Limit = Vec_IntSize(p->vFront); //Opa_ManPrint2( p ); Gia_ManForEachObjVec( p->vFront, pGia, pObj, i ) { if ( i == Limit ) { printf( "%6d : %6d -> %6d\n", ++Count, i, p->nParts ); Limit = Vec_IntSize(p->vFront); if ( Count > 1 ) Opa_ManPrint2( p ); } // printf( "*** Object %d ", Gia_ObjId(pGia, pObj) ); if ( Gia_ObjIsAnd(pObj) ) { Opa_ManMoveOne( p, pObj, Gia_ObjFanin0(pObj) ); Opa_ManMoveOne( p, pObj, Gia_ObjFanin1(pObj) ); } else if ( Gia_ObjIsCo(pObj) ) Opa_ManMoveOne( p, pObj, Gia_ObjFanin0(pObj) ); else assert( 0 ); // if ( i % 10 == 0 ) // printf( "%d ", p->nParts ); if ( p->nParts == 1 ) break; if ( Count == 5 ) break; } printf( "\n" ); Opa_ManStop( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManConeMark_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vRoots, int nLimit ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 0; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsAnd(pObj) ) { if ( Gia_ManConeMark_rec( p, Gia_ObjFanin0(pObj), vRoots, nLimit ) ) return 1; if ( Gia_ManConeMark_rec( p, Gia_ObjFanin1(pObj), vRoots, nLimit ) ) return 1; } else if ( Gia_ObjIsCo(pObj) ) { if ( Gia_ManConeMark_rec( p, Gia_ObjFanin0(pObj), vRoots, nLimit ) ) return 1; } else if ( Gia_ObjIsRo(p, pObj) ) Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) ); else if ( Gia_ObjIsPi(p, pObj) ) {} else assert( 0 ); return (int)(Vec_IntSize(vRoots) > nLimit); } int Gia_ManConeMark( Gia_Man_t * p, int iOut, int Limit ) { Vec_Int_t * vRoots; Gia_Obj_t * pObj; int i, RetValue; // start the outputs pObj = Gia_ManPo( p, iOut ); vRoots = Vec_IntAlloc( 100 ); Vec_IntPush( vRoots, Gia_ObjId(p, pObj) ); // mark internal nodes Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); Gia_ManForEachObjVec( vRoots, p, pObj, i ) if ( Gia_ManConeMark_rec( p, pObj, vRoots, Limit ) ) break; RetValue = Vec_IntSize( vRoots ) - 1; Vec_IntFree( vRoots ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCountFlops( Gia_Man_t * p, Vec_Int_t * vOuts ) { int Limit = ABC_INFINITY; Vec_Int_t * vRoots; Gia_Obj_t * pObj; int i, RetValue, iOut; // start the outputs vRoots = Vec_IntAlloc( 100 ); Vec_IntForEachEntry( vOuts, iOut, i ) { pObj = Gia_ManPo( p, iOut ); Vec_IntPush( vRoots, Gia_ObjId(p, pObj) ); } // mark internal nodes Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); Gia_ManForEachObjVec( vRoots, p, pObj, i ) if ( Gia_ManConeMark_rec( p, pObj, vRoots, Limit ) ) break; RetValue = Vec_IntSize( vRoots ) - Vec_IntSize(vOuts); Vec_IntFree( vRoots ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFindPoPartition3( Gia_Man_t * p, int iOut, int nDelta, int nOutsMin, int nOutsMax, int fVerbose, Vec_Ptr_t ** pvPosEquivs ) { /* int i, Count = 0; // mark nodes belonging to output 'iOut' for ( i = 0; i < Gia_ManPoNum(p); i++ ) Count += (Gia_ManConeMark(p, i, 10000) < 10000); // printf( "%d ", Gia_ManConeMark(p, i, 1000) ); printf( "%d out of %d\n", Count, Gia_ManPoNum(p) ); // add other outputs as long as they are nDelta away */ // Opa_ManPerform( p ); return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManFindPivots( Gia_Man_t * p, int SelectShift, int fOnlyCis, int fVerbose ) { Vec_Int_t * vPivots, * vWeights; Vec_Int_t * vCount, * vResult; int i, j, Count, * pPerm, Limit; /* Gia_Obj_t * pObj; // count MUX controls vCount = Vec_IntStart( Gia_ManObjNum(p) ); Gia_ManForEachAnd( p, pObj, i ) { Gia_Obj_t * pNodeC, * pNodeT, * pNodeE; if ( !Gia_ObjIsMuxType(pObj) ) continue; pNodeC = Gia_ObjRecognizeMux( pObj, &pNodeT, &pNodeE ); Vec_IntAddToEntry( vCount, Gia_ObjId(p, Gia_Regular(pNodeC)), 1 ); } */ // count references Gia_ManCreateRefs( p ); vCount = Vec_IntAllocArray( p->pRefs, Gia_ManObjNum(p) ); p->pRefs = NULL; // collect nodes vPivots = Vec_IntAlloc( 100 ); vWeights = Vec_IntAlloc( 100 ); Vec_IntForEachEntry( vCount, Count, i ) { if ( Count < 2 ) continue; if ( fOnlyCis && !Gia_ObjIsCi(Gia_ManObj(p, i)) ) continue; Vec_IntPush( vPivots, i ); Vec_IntPush( vWeights, Count ); } Vec_IntFree( vCount ); if ( fVerbose ) printf( "Selected %d pivots with more than one fanout (out of %d CIs and ANDs).\n", Vec_IntSize(vWeights), Gia_ManCiNum(p) + Gia_ManAndNum(p) ); // permute Gia_ManRandom(1); Gia_ManRandom(0); for ( i = 0; i < Vec_IntSize(vWeights); i++ ) { j = (Gia_ManRandom(0) >> 1) % Vec_IntSize(vWeights); ABC_SWAP( int, vPivots->pArray[i], vPivots->pArray[j] ); ABC_SWAP( int, vWeights->pArray[i], vWeights->pArray[j] ); } // sort if ( SelectShift == 0 ) pPerm = Abc_QuickSortCost( Vec_IntArray(vWeights), Vec_IntSize(vWeights), 1 ); else { Vec_Int_t * vTemp = Vec_IntStartNatural( Vec_IntSize(vWeights) ); pPerm = Vec_IntReleaseArray( vTemp ); Vec_IntFree( vTemp ); } // select Limit = Abc_MinInt( 64, Vec_IntSize(vWeights) ); vResult = Vec_IntAlloc( Limit ); for ( i = 0; i < Limit; i++ ) { j = (i + SelectShift) % Vec_IntSize(vWeights); if ( fVerbose ) printf( "%2d : Pivot =%7d Fanout =%7d\n", j, Vec_IntEntry(vPivots, pPerm[j]), Vec_IntEntry(vWeights, pPerm[j]) ); Vec_IntPush( vResult, Vec_IntEntry(vPivots, pPerm[j]) ); } Vec_IntFree( vPivots ); Vec_IntFree( vWeights ); ABC_FREE( pPerm ); return vResult; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wrd_t * Gia_ManDeriveSigns( Gia_Man_t * p, Vec_Int_t * vPivots, int fVerbose ) { Vec_Wrd_t * vSigns; Gia_Obj_t * pObj, * pObjRi; int i, fChange = 1, Counter; Gia_ManFillValue( p ); Gia_ManForEachObjVec( vPivots, p, pObj, i ) pObj->Value = i; if ( fVerbose ) printf( "Signature propagation: " ); vSigns = Vec_WrdStart( Gia_ManObjNum(p) ); while ( fChange ) { fChange = 0; Gia_ManForEachObj( p, pObj, i ) { if ( ~pObj->Value ) { assert( pObj->Value >= 0 && pObj->Value < 64 ); *Vec_WrdEntryP( vSigns, i ) |= ( (word)1 << pObj->Value ); } if ( Gia_ObjIsAnd(pObj) ) *Vec_WrdEntryP( vSigns, i ) |= Vec_WrdEntry(vSigns, Gia_ObjFaninId0(pObj, i)) | Vec_WrdEntry(vSigns, Gia_ObjFaninId1(pObj, i)); else if ( Gia_ObjIsCo(pObj) ) *Vec_WrdEntryP( vSigns, i ) |= Vec_WrdEntry(vSigns, Gia_ObjFaninId0(pObj, i)); } Counter = 0; Gia_ManForEachRiRo( p, pObjRi, pObj, i ) { word Value = Vec_WrdEntry(vSigns, Gia_ObjId(p, pObj)); *Vec_WrdEntryP( vSigns, Gia_ObjId(p, pObj) ) |= Vec_WrdEntry(vSigns, Gia_ObjId(p, pObjRi)); if ( Value != Vec_WrdEntry(vSigns, Gia_ObjId(p, pObj)) ) fChange = 1, Counter++; } if ( fVerbose ) printf( "%d ", Counter ); } if ( fVerbose ) printf( "\n" ); return vSigns; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Gia_ManHashOutputs( Gia_Man_t * p, Vec_Wrd_t * vSigns, int fVerbose ) { Vec_Ptr_t * vBins; Vec_Wec_t * vClasses; Vec_Wrd_t * vSignsPo; Vec_Int_t * vPriority, * vBin; Gia_Obj_t * pObj; int i; // collect PO signatures vSignsPo = Vec_WrdAlloc( Gia_ManPoNum(p) ); Gia_ManForEachPo( p, pObj, i ) Vec_WrdPush( vSignsPo, Vec_WrdEntry(vSigns, Gia_ObjId(p, pObj)) ); // find equivalence classes vPriority = Hsh_WrdManHashArray( vSignsPo, 1 ); Vec_WrdFree( vSignsPo ); vClasses = Vec_WecCreateClasses( vPriority ); Vec_IntFree( vPriority ); vBins = (Vec_Ptr_t *)Vec_WecConvertToVecPtr( vClasses ); Vec_WecFree( vClasses ); Vec_VecSort( (Vec_Vec_t *)vBins, 1 ); if ( fVerbose ) printf( "Computed %d partitions:\n", Vec_PtrSize(vBins) ); if ( !fVerbose ) printf( "Listing partitions with more than 100 outputs:\n" ); Vec_PtrForEachEntry( Vec_Int_t *, vBins, vBin, i ) { assert( Vec_IntSize(vBin) > 0 ); if ( fVerbose || Vec_IntSize(vBin) > 100 ) { int PoNum = Vec_IntEntry( vBin, 0 ); Gia_Obj_t * pObj = Gia_ManPo( p, PoNum ); word Sign = Vec_WrdEntry( vSigns, Gia_ObjId(p, pObj) ); // print printf( "%3d ", i ); Extra_PrintBinary( stdout, (unsigned *)&Sign, 64 ); printf( " " ); printf( "PO =%7d ", Vec_IntSize(vBin) ); printf( "FF =%7d", Gia_ManCountFlops(p, vBin) ); printf( "\n" ); } } return vBins; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFindPoPartition2( Gia_Man_t * p, int iStartNum, int nDelta, int nOutsMin, int nOutsMax, int fSetLargest, int fVerbose, Vec_Ptr_t ** pvPosEquivs ) { return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFindPoPartition( Gia_Man_t * p, int SelectShift, int fOnlyCis, int fSetLargest, int fVerbose, Vec_Ptr_t ** pvPosEquivs ) { Gia_Man_t * pGia = NULL; Vec_Int_t * vPivots; Vec_Wrd_t * vSigns; Vec_Ptr_t * vParts; Vec_Int_t * vPart; abctime clk = Abc_Clock(); vPivots = Gia_ManFindPivots( p, SelectShift, fOnlyCis, fVerbose ); vSigns = Gia_ManDeriveSigns( p, vPivots, fVerbose ); Vec_IntFree( vPivots ); vParts = Gia_ManHashOutputs( p, vSigns, fVerbose ); Vec_WrdFree( vSigns ); if ( fSetLargest ) { vPart = Vec_VecEntryInt( (Vec_Vec_t *)vParts, 0 ); pGia = Gia_ManDupCones( p, Vec_IntArray(vPart), Vec_IntSize(vPart), 1 ); } if ( pvPosEquivs ) { *pvPosEquivs = vParts; printf( "The algorithm divided %d POs into %d partitions. ", Gia_ManPoNum(p), Vec_PtrSize(vParts) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } else Vec_VecFree( (Vec_Vec_t *)vParts ); return pGia; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaConstr.c000066400000000000000000000027271477524141600163740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaConstr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Constraint propagation in CNF-based solver.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaConstr.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 [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaCut.c000066400000000000000000001453161477524141600156610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaCut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Stand-alone cut computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaCut.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" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define GIA_MAX_CUTSIZE 8 #define GIA_MAX_CUTNUM 257 #define GIA_MAX_TT_WORDS ((GIA_MAX_CUTSIZE > 6) ? 1 << (GIA_MAX_CUTSIZE-6) : 1) #define GIA_CUT_NO_LEAF 0xF typedef struct Gia_Cut_t_ Gia_Cut_t; struct Gia_Cut_t_ { word Sign; // signature int iFunc; // functionality int Cost; // cut cost int CostLev; // cut cost unsigned nTreeLeaves : 28; // tree leaves unsigned nLeaves : 4; // leaf count int pLeaves[GIA_MAX_CUTSIZE]; // leaves float CostF; }; typedef struct Gia_Sto_t_ Gia_Sto_t; struct Gia_Sto_t_ { int nCutSize; int nCutNum; int fCutMin; int fTruthMin; int fVerbose; Gia_Man_t * pGia; // user's AIG manager (will be modified by adding nodes) Vec_Int_t * vRefs; // refs for each node Vec_Wec_t * vCuts; // cuts for each node Vec_Mem_t * vTtMem; // truth tables Gia_Cut_t pCuts[3][GIA_MAX_CUTNUM]; // temporary cuts Gia_Cut_t * ppCuts[GIA_MAX_CUTNUM]; // temporary cut pointers int nCutsR; // the number of cuts int Pivot; // current object int iCutBest; // best-delay cut int nCutsOver; // overflow cuts double CutCount[4]; // cut counters abctime clkStart; // starting time }; static inline word * Gia_CutTruth( Gia_Sto_t * p, Gia_Cut_t * pCut ) { return Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut->iFunc)); } #define Sdb_ForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += pCut[0] + 2 ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Check correctness of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Gia_CutGetSign( Gia_Cut_t * pCut ) { word Sign = 0; int i; for ( i = 0; i < (int)pCut->nLeaves; i++ ) Sign |= ((word)1) << (pCut->pLeaves[i] & 0x3F); return Sign; } static inline int Gia_CutCheck( Gia_Cut_t * pBase, Gia_Cut_t * pCut ) // check if pCut is contained in pBase { int nSizeB = pBase->nLeaves; int nSizeC = pCut->nLeaves; int i, * pB = pBase->pLeaves; int k, * pC = pCut->pLeaves; for ( i = 0; i < nSizeC; i++ ) { for ( k = 0; k < nSizeB; k++ ) if ( pC[i] == pB[k] ) break; if ( k == nSizeB ) return 0; } return 1; } static inline int Gia_CutSetCheckArray( Gia_Cut_t ** ppCuts, int nCuts ) { Gia_Cut_t * pCut0, * pCut1; int i, k, m, n, Value; assert( nCuts > 0 ); for ( i = 0; i < nCuts; i++ ) { pCut0 = ppCuts[i]; assert( pCut0->nLeaves <= GIA_MAX_CUTSIZE ); assert( pCut0->Sign == Gia_CutGetSign(pCut0) ); // check duplicates for ( m = 0; m < (int)pCut0->nLeaves; m++ ) for ( n = m + 1; n < (int)pCut0->nLeaves; n++ ) assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] ); // check pairs for ( k = 0; k < nCuts; k++ ) { pCut1 = ppCuts[k]; if ( pCut0 == pCut1 ) continue; // check containments Value = Gia_CutCheck( pCut0, pCut1 ); assert( Value == 0 ); } } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_CutMergeOrder( Gia_Cut_t * pCut0, Gia_Cut_t * pCut1, Gia_Cut_t * pCut, int nCutSize ) { int nSize0 = pCut0->nLeaves; int nSize1 = pCut1->nLeaves; int i, * pC0 = pCut0->pLeaves; int k, * pC1 = pCut1->pLeaves; int c, * pC = pCut->pLeaves; // the case of the largest cut sizes if ( nSize0 == nCutSize && nSize1 == nCutSize ) { for ( i = 0; i < nSize0; i++ ) { if ( pC0[i] != pC1[i] ) return 0; pC[i] = pC0[i]; } pCut->nLeaves = nCutSize; pCut->iFunc = -1; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; } // compare two cuts with different numbers i = k = c = 0; if ( nSize0 == 0 ) goto FlushCut1; if ( nSize1 == 0 ) goto FlushCut0; while ( 1 ) { if ( c == nCutSize ) return 0; if ( pC0[i] < pC1[k] ) { pC[c++] = pC0[i++]; if ( i >= nSize0 ) goto FlushCut1; } else if ( pC0[i] > pC1[k] ) { pC[c++] = pC1[k++]; if ( k >= nSize1 ) goto FlushCut0; } else { pC[c++] = pC0[i++]; k++; if ( i >= nSize0 ) goto FlushCut1; if ( k >= nSize1 ) goto FlushCut0; } } FlushCut0: if ( c + nSize0 > nCutSize + i ) return 0; while ( i < nSize0 ) pC[c++] = pC0[i++]; pCut->nLeaves = c; pCut->iFunc = -1; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; FlushCut1: if ( c + nSize1 > nCutSize + k ) return 0; while ( k < nSize1 ) pC[c++] = pC1[k++]; pCut->nLeaves = c; pCut->iFunc = -1; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; } static inline int Gia_CutMergeOrder2( Gia_Cut_t * pCut0, Gia_Cut_t * pCut1, Gia_Cut_t * pCut, int nCutSize ) { int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; int xMin, c = 0, * pC = pCut->pLeaves; while ( 1 ) { x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; xMin = Abc_MinInt(x0, x1); if ( xMin == ABC_INFINITY ) break; if ( c == nCutSize ) return 0; pC[c++] = xMin; if (x0 == xMin) i0++; if (x1 == xMin) i1++; } pCut->nLeaves = c; pCut->iFunc = -1; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; } static inline int Gia_CutSetCutIsContainedOrder( Gia_Cut_t * pBase, Gia_Cut_t * pCut ) // check if pCut is contained in pBase { int i, nSizeB = pBase->nLeaves; int k, nSizeC = pCut->nLeaves; if ( nSizeB == nSizeC ) { for ( i = 0; i < nSizeB; i++ ) if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) return 0; return 1; } assert( nSizeB > nSizeC ); if ( nSizeC == 0 ) return 1; for ( i = k = 0; i < nSizeB; i++ ) { if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) return 0; if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) { if ( ++k == nSizeC ) return 1; } } return 0; } static inline int Gia_CutSetLastCutIsContained( Gia_Cut_t ** pCuts, int nCuts ) { int i; for ( i = 0; i < nCuts; i++ ) if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Gia_CutSetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) ) return 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_CutCompare2( Gia_Cut_t * pCut0, Gia_Cut_t * pCut1 ) { if ( pCut0->nTreeLeaves < pCut1->nTreeLeaves ) return -1; if ( pCut0->nTreeLeaves > pCut1->nTreeLeaves ) return 1; if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; return 0; } static inline int Gia_CutCompare( Gia_Cut_t * pCut0, Gia_Cut_t * pCut1 ) { if ( pCut0->CostF > pCut1->CostF ) return -1; if ( pCut0->CostF < pCut1->CostF ) return 1; if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; return 0; } static inline int Gia_CutSetLastCutContains( Gia_Cut_t ** pCuts, int nCuts ) { int i, k, fChanges = 0; for ( i = 0; i < nCuts; i++ ) if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Gia_CutSetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) ) pCuts[i]->nLeaves = GIA_CUT_NO_LEAF, fChanges = 1; if ( !fChanges ) return nCuts; for ( i = k = 0; i <= nCuts; i++ ) { if ( pCuts[i]->nLeaves == GIA_CUT_NO_LEAF ) continue; if ( k < i ) ABC_SWAP( Gia_Cut_t *, pCuts[k], pCuts[i] ); k++; } return k - 1; } static inline void Gia_CutSetSortByCost( Gia_Cut_t ** pCuts, int nCuts ) { int i; for ( i = nCuts; i > 0; i-- ) { if ( Gia_CutCompare(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 ) return; ABC_SWAP( Gia_Cut_t *, pCuts[i - 1], pCuts[i] ); } } static inline int Gia_CutSetAddCut( Gia_Cut_t ** pCuts, int nCuts, int nCutNum ) { if ( nCuts == 0 ) return 1; nCuts = Gia_CutSetLastCutContains(pCuts, nCuts); assert( nCuts >= 0 ); Gia_CutSetSortByCost( pCuts, nCuts ); // add new cut if there is room return Abc_MinInt( nCuts + 1, nCutNum - 1 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_CutComputeTruth6( Gia_Sto_t * p, Gia_Cut_t * pCut0, Gia_Cut_t * pCut1, int fCompl0, int fCompl1, Gia_Cut_t * pCutR, int fIsXor ) { int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; word t0 = *Gia_CutTruth(p, pCut0); word t1 = *Gia_CutTruth(p, pCut1); if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t = fIsXor ? t0 ^ t1 : t0 & t1; if ( (fCompl = (int)(t & 1)) ) t = ~t; if ( p->fTruthMin ) pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); assert( (int)(t & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, &t); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } static inline int Gia_CutComputeTruth( Gia_Sto_t * p, Gia_Cut_t * pCut0, Gia_Cut_t * pCut1, int fCompl0, int fCompl1, Gia_Cut_t * pCutR, int fIsXor ) { if ( p->nCutSize <= 6 ) return Gia_CutComputeTruth6( p, pCut0, pCut1, fCompl0, fCompl1, pCutR, fIsXor ); { word uTruth[GIA_MAX_TT_WORDS], uTruth0[GIA_MAX_TT_WORDS], uTruth1[GIA_MAX_TT_WORDS]; int nOldSupp = pCutR->nLeaves, truthId; int nCutSize = p->nCutSize, fCompl; int nWords = Abc_Truth6WordNum(nCutSize); word * pTruth0 = Gia_CutTruth(p, pCut0); word * pTruth1 = Gia_CutTruth(p, pCut1); Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ); Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ); Abc_TtExpand( uTruth0, nCutSize, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); Abc_TtExpand( uTruth1, nCutSize, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); if ( fIsXor ) Abc_TtXor( uTruth, uTruth0, uTruth1, nWords, (fCompl = (int)((uTruth0[0] ^ uTruth1[0]) & 1)) ); else Abc_TtAnd( uTruth, uTruth0, uTruth1, nWords, (fCompl = (int)((uTruth0[0] & uTruth1[0]) & 1)) ); if ( p->fTruthMin ) pCutR->nLeaves = Abc_TtMinBase( uTruth, pCutR->pLeaves, pCutR->nLeaves, nCutSize ); assert( (uTruth[0] & 1) == 0 ); //Kit_DsdPrintFromTruth( uTruth, pCutR->nLeaves ), printf("\n" ), printf("\n" ); truthId = Vec_MemHashInsert(p->vTtMem, uTruth); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_CutCountBits( word i ) { i = i - ((i >> 1) & 0x5555555555555555); i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); return (i*(0x0101010101010101))>>56; } static inline void Gia_CutAddUnit( Gia_Sto_t * p, int iObj ) { Vec_Int_t * vThis = Vec_WecEntry( p->vCuts, iObj ); if ( Vec_IntSize(vThis) == 0 ) Vec_IntPush( vThis, 1 ); else Vec_IntAddToEntry( vThis, 0, 1 ); Vec_IntPush( vThis, 1 ); Vec_IntPush( vThis, iObj ); Vec_IntPush( vThis, 2 ); } static inline void Gia_CutAddZero( Gia_Sto_t * p, int iObj ) { Vec_Int_t * vThis = Vec_WecEntry( p->vCuts, iObj ); assert( Vec_IntSize(vThis) == 0 ); Vec_IntPush( vThis, 1 ); Vec_IntPush( vThis, 0 ); Vec_IntPush( vThis, 0 ); } static inline int Gia_CutTreeLeaves( Gia_Sto_t * p, Gia_Cut_t * pCut ) { int i, Cost = 0; for ( i = 0; i < (int)pCut->nLeaves; i++ ) Cost += Vec_IntEntry( p->vRefs, pCut->pLeaves[i] ) == 1; return Cost; } static inline float Gia_CutGetCost( Gia_Sto_t * p, Gia_Cut_t * pCut ) { int i, Cost = 0; for ( i = 0; i < (int)pCut->nLeaves; i++ ) Cost += Vec_IntEntry( p->vRefs, pCut->pLeaves[i] ); return (float)Cost / Abc_MaxInt(1, pCut->nLeaves); } static inline int Gia_StoPrepareSet( Gia_Sto_t * p, int iObj, int Index ) { Vec_Int_t * vThis = Vec_WecEntry( p->vCuts, iObj ); int i, v, * pCut, * pList = Vec_IntArray( vThis ); Sdb_ForEachCut( pList, pCut, i ) { Gia_Cut_t * pCutTemp = &p->pCuts[Index][i]; pCutTemp->nLeaves = pCut[0]; for ( v = 1; v <= pCut[0]; v++ ) pCutTemp->pLeaves[v-1] = pCut[v]; pCutTemp->iFunc = pCut[pCut[0]+1]; pCutTemp->Sign = Gia_CutGetSign( pCutTemp ); pCutTemp->nTreeLeaves = Gia_CutTreeLeaves( p, pCutTemp ); pCutTemp->CostF = Gia_CutGetCost( p, pCutTemp ); } return pList[0]; } static inline void Gia_StoInitResult( Gia_Sto_t * p ) { int i; for ( i = 0; i < GIA_MAX_CUTNUM; i++ ) p->ppCuts[i] = &p->pCuts[2][i]; } static inline void Gia_StoStoreResult( Gia_Sto_t * p, int iObj, Gia_Cut_t ** pCuts, int nCuts ) { int i, v; Vec_Int_t * vList = Vec_WecEntry( p->vCuts, iObj ); Vec_IntPush( vList, nCuts ); for ( i = 0; i < nCuts; i++ ) { Vec_IntPush( vList, pCuts[i]->nLeaves ); for ( v = 0; v < (int)pCuts[i]->nLeaves; v++ ) Vec_IntPush( vList, pCuts[i]->pLeaves[v] ); Vec_IntPush( vList, pCuts[i]->iFunc ); } } static inline void Gia_CutPrint( Gia_Sto_t * p, int iObj, Gia_Cut_t * pCut ) { int i, nDigits = Abc_Base10Log(Gia_ManObjNum(p->pGia)); if ( pCut == NULL ) { printf( "No cut.\n" ); return; } printf( "%d {", pCut->nLeaves ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) printf( " %*d", nDigits, pCut->pLeaves[i] ); for ( ; i < (int)p->nCutSize; i++ ) printf( " %*s", nDigits, " " ); printf( " } Cost = %3d CostL = %3d Tree = %d ", pCut->Cost, pCut->CostLev, pCut->nTreeLeaves ); printf( "\n" ); } void Gia_StoMergeCuts( Gia_Sto_t * p, int iObj ) { Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); int fIsXor = Gia_ObjIsXor(pObj); int nCutSize = p->nCutSize; int nCutNum = p->nCutNum; int fComp0 = Gia_ObjFaninC0(pObj); int fComp1 = Gia_ObjFaninC1(pObj); int Fan0 = Gia_ObjFaninId0(pObj, iObj); int Fan1 = Gia_ObjFaninId1(pObj, iObj); int nCuts0 = Gia_StoPrepareSet( p, Fan0, 0 ); int nCuts1 = Gia_StoPrepareSet( p, Fan1, 1 ); int i, k, nCutsR = 0; Gia_Cut_t * pCut0, * pCut1, ** pCutsR = p->ppCuts; assert( !Gia_ObjIsBuf(pObj) ); assert( !Gia_ObjIsMux(p->pGia, pObj) ); Gia_StoInitResult( p ); p->CutCount[0] += nCuts0 * nCuts1; for ( i = 0, pCut0 = p->pCuts[0]; i < nCuts0; i++, pCut0++ ) for ( k = 0, pCut1 = p->pCuts[1]; k < nCuts1; k++, pCut1++ ) { if ( (int)(pCut0->nLeaves + pCut1->nLeaves) > nCutSize && Gia_CutCountBits(pCut0->Sign | pCut1->Sign) > nCutSize ) continue; p->CutCount[1]++; if ( !Gia_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], nCutSize) ) continue; if ( Gia_CutSetLastCutIsContained(pCutsR, nCutsR) ) continue; p->CutCount[2]++; if ( p->fCutMin && Gia_CutComputeTruth(p, pCut0, pCut1, fComp0, fComp1, pCutsR[nCutsR], fIsXor) ) pCutsR[nCutsR]->Sign = Gia_CutGetSign(pCutsR[nCutsR]); pCutsR[nCutsR]->nTreeLeaves = Gia_CutTreeLeaves( p, pCutsR[nCutsR] ); pCutsR[nCutsR]->CostF = Gia_CutGetCost( p, pCutsR[nCutsR] ); nCutsR = Gia_CutSetAddCut( pCutsR, nCutsR, nCutNum ); } p->CutCount[3] += nCutsR; p->nCutsOver += nCutsR == nCutNum-1; p->nCutsR = nCutsR; p->Pivot = iObj; // debug printout if ( 0 ) { printf( "*** Obj = %4d NumCuts = %4d\n", iObj, nCutsR ); for ( i = 0; i < nCutsR; i++ ) Gia_CutPrint( p, iObj, pCutsR[i] ); printf( "\n" ); } // verify assert( nCutsR > 0 && nCutsR < nCutNum ); assert( Gia_CutSetCheckArray(pCutsR, nCutsR) ); // store the cutset Gia_StoStoreResult( p, iObj, pCutsR, nCutsR ); if ( nCutsR > 1 || pCutsR[0]->nLeaves > 1 ) Gia_CutAddUnit( p, iObj ); } /**Function************************************************************* Synopsis [Incremental cut computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Sto_t * Gia_StoAlloc( Gia_Man_t * pGia, int nCutSize, int nCutNum, int fCutMin, int fTruthMin, int fVerbose ) { Gia_Sto_t * p; assert( nCutSize < GIA_CUT_NO_LEAF ); assert( nCutSize > 1 && nCutSize <= GIA_MAX_CUTSIZE ); assert( nCutNum > 1 && nCutNum < GIA_MAX_CUTNUM ); p = ABC_CALLOC( Gia_Sto_t, 1 ); p->clkStart = Abc_Clock(); p->nCutSize = nCutSize; p->nCutNum = nCutNum; p->fCutMin = fCutMin; p->fTruthMin = fTruthMin; p->fVerbose = fVerbose; p->pGia = pGia; p->vRefs = Vec_IntAlloc( Gia_ManObjNum(pGia) ); p->vCuts = Vec_WecStart( Gia_ManObjNum(pGia) ); p->vTtMem = fCutMin ? Vec_MemAllocForTT( nCutSize, 0 ) : NULL; return p; } void Gia_StoFree( Gia_Sto_t * p ) { Vec_IntFree( p->vRefs ); Vec_WecFree( p->vCuts ); if ( p->fCutMin ) Vec_MemHashFree( p->vTtMem ); if ( p->fCutMin ) Vec_MemFree( p->vTtMem ); ABC_FREE( p ); } void Gia_StoComputeCutsConst0( Gia_Sto_t * p, int iObj ) { Gia_CutAddZero( p, iObj ); } void Gia_StoComputeCutsCi( Gia_Sto_t * p, int iObj ) { Gia_CutAddUnit( p, iObj ); } void Gia_StoComputeCutsNode( Gia_Sto_t * p, int iObj ) { Gia_StoMergeCuts( p, iObj ); } void Gia_StoRefObj( Gia_Sto_t * p, int iObj ) { Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); assert( iObj == Vec_IntSize(p->vRefs) ); Vec_IntPush( p->vRefs, 0 ); if ( Gia_ObjIsAnd(pObj) ) { Vec_IntAddToEntry( p->vRefs, Gia_ObjFaninId0(pObj, iObj), 1 ); Vec_IntAddToEntry( p->vRefs, Gia_ObjFaninId1(pObj, iObj), 1 ); } else if ( Gia_ObjIsCo(pObj) ) Vec_IntAddToEntry( p->vRefs, Gia_ObjFaninId0(pObj, iObj), 1 ); } void Gia_StoComputeCuts( Gia_Man_t * pGia ) { 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; 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 ); } 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; } void Gia_ManExploreCutsTest( Gia_Man_t * pGia, int nCutSize0, int nCuts0, int fVerbose0 ) { Vec_Wec_t * vCutSel = Gia_ManExploreCuts( pGia, nCutSize0, nCuts0, fVerbose0 ); Vec_WecPrint( vCutSel, 0 ); Vec_WecFree( vCutSel ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Sto_t * Gia_ManMatchCutsInt( Gia_Man_t * pGia, int nCutSize0, int nCutNum0, int fVerbose0 ) { int nCutSize = nCutSize0; int nCutNum = nCutNum0; int fCutMin = 1; int fTruthMin = 1; int fVerbose = fVerbose0; Gia_Sto_t * p = Gia_StoAlloc( pGia, nCutSize, nCutNum, fCutMin, fTruthMin, fVerbose ); Gia_Obj_t * pObj; int i, iObj; assert( nCutSize <= GIA_MAX_CUTSIZE ); assert( nCutNum < GIA_MAX_CUTNUM ); // prepare references Gia_ManForEachObj( p->pGia, pObj, iObj ) Gia_StoRefObj( p, iObj ); // compute cuts Gia_StoComputeCutsConst0( p, 0 ); Gia_ManForEachCiId( p->pGia, iObj, i ) Gia_StoComputeCutsCi( p, iObj ); Gia_ManForEachAnd( p->pGia, pObj, iObj ) Gia_StoComputeCutsNode( p, iObj ); if ( p->fVerbose ) { printf( "Running cut computation with CutSize = %d CutNum = %d CutMin = %s TruthMin = %s\n", p->nCutSize, p->nCutNum, p->fCutMin ? "yes":"no", p->fTruthMin ? "yes":"no" ); printf( "CutPair = %.0f ", p->CutCount[0] ); printf( "Merge = %.0f (%.2f %%) ", p->CutCount[1], 100.0*p->CutCount[1]/p->CutCount[0] ); printf( "Eval = %.0f (%.2f %%) ", p->CutCount[2], 100.0*p->CutCount[2]/p->CutCount[0] ); printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] ); printf( "Cut/Node = %.2f ", p->CutCount[3] / Gia_ManAndNum(p->pGia) ); printf( "\n" ); printf( "The number of nodes with cut count over the limit (%d cuts) = %d nodes (out of %d). ", p->nCutNum, p->nCutsOver, Gia_ManAndNum(pGia) ); Abc_PrintTime( 0, "Time", Abc_Clock() - p->clkStart ); } return p; } void Gia_ManMatchCuts( Vec_Mem_t * vTtMem, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose ) { Gia_Sto_t * p = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, fVerbose ); Vec_Int_t * vLevel; int i, j, k, * pCut; Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); Vec_Wec_t * vCuts = Vec_WecAlloc( 100 ); abctime clkStart = Abc_Clock(); assert( Abc_Truth6WordNum(nCutSize) == Vec_MemEntrySize(vTtMem) ); Vec_WecForEachLevel( p->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) { Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) if ( pCut[0] > 1 ) { word * pTruth = Vec_MemReadEntry( p->vTtMem, Abc_Lit2Var(pCut[pCut[0]+1]) ); int * pSpot = Vec_MemHashLookup( vTtMem, pTruth ); if ( *pSpot == -1 ) continue; Vec_IntPush( vNodes, i ); vLevel = Vec_WecPushLevel( vCuts ); Vec_IntPush( vLevel, i ); for ( j = 1; j <= pCut[0]; j++ ) Vec_IntPush( vLevel, pCut[j] ); break; } } printf( "Nodes with matching cuts: " ); Vec_IntPrint( vNodes ); if ( Vec_WecSize(vCuts) > 32 ) Vec_WecShrink(vCuts, 32); Vec_WecPrint( vCuts, 0 ); Vec_WecFree( vCuts ); Vec_IntFree( vNodes ); Gia_StoFree( p ); if ( fVerbose ) Abc_PrintTime( 1, "Cut matching time", Abc_Clock() - clkStart ); } Vec_Ptr_t * Gia_ManMatchCutsArray( Vec_Ptr_t * vTtMems, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose ) { Vec_Ptr_t * vRes = Vec_PtrAlloc( Vec_PtrSize(vTtMems) ); Gia_Sto_t * p = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, fVerbose ); Vec_Int_t * vLevel, * vTemp; int i, k, c, * pCut; abctime clkStart = Abc_Clock(); for ( i = 0; i < Vec_PtrSize(vTtMems); i++ ) Vec_PtrPush( vRes, Vec_WecAlloc(100) ); Vec_WecForEachLevel( p->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) { Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) if ( pCut[0] > 1 ) { Vec_Mem_t * vTtMem; int m; Vec_PtrForEachEntry( Vec_Mem_t *, vTtMems, vTtMem, m ) { word * pTruth = Vec_MemReadEntry( p->vTtMem, Abc_Lit2Var(pCut[pCut[0]+1]) ); int * pSpot = Vec_MemHashLookup( vTtMem, pTruth ); if ( *pSpot == -1 ) continue; vTemp = Vec_WecPushLevel( (Vec_Wec_t *)Vec_PtrEntry(vRes, m) ); Vec_IntPush( vTemp, i ); for ( c = 1; c <= pCut[0]; c++ ) Vec_IntPush( vTemp, pCut[c] ); } } } Gia_StoFree( p ); if ( fVerbose ) { Vec_Wec_t * vCuts; printf( "Detected nodes by type: " ); Vec_PtrForEachEntry( Vec_Wec_t *, vRes, vCuts, i ) printf( "Type%d = %d ", i, Vec_WecSize(vCuts) ); Abc_PrintTime( 1, "Cut matching time", Abc_Clock() - clkStart ); } return vRes; } Vec_Ptr_t * Gia_ManMatchCutsMany( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, int nFuncs, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose ) { Gia_Sto_t * p = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, fVerbose ); Vec_Int_t * vLevel; int i, j, k, * pCut; abctime clkStart = Abc_Clock(); assert( Abc_Truth6WordNum(nCutSize) == Vec_MemEntrySize(vTtMem) ); Vec_Ptr_t * vRes = Vec_PtrAlloc( nFuncs ); for ( i = 0; i < nFuncs; i++ ) Vec_PtrPush( vRes, Vec_WecAlloc(10) ); Vec_WecForEachLevel( p->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) { Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) if ( pCut[0] > 1 ) { word * pTruth = Vec_MemReadEntry( p->vTtMem, Abc_Lit2Var(pCut[pCut[0]+1]) ); assert( (pTruth[0] & 1) == 0 ); int * pSpot = Vec_MemHashLookup( vTtMem, pTruth ); if ( *pSpot == -1 ) continue; int iFunc = vMap ? Vec_IntEntry( vMap, *pSpot ) : 0; assert( iFunc < nFuncs ); Vec_Wec_t * vCuts = (Vec_Wec_t *)Vec_PtrEntry( vRes, iFunc ); vLevel = Vec_WecPushLevel( vCuts ); Vec_IntPush( vLevel, i ); for ( j = 1; j <= pCut[0]; j++ ) Vec_IntPush( vLevel, pCut[j] ); break; } } Gia_StoFree( p ); if ( fVerbose ) Abc_PrintTime( 1, "Cut matching time", Abc_Clock() - clkStart ); return vRes; } /**Function************************************************************* Synopsis [Function enumeration.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wrd_t * Gia_ManCollectCutFuncs( Gia_Man_t * p, int nCutSize, int nCutNum, int fVerbose ) { Gia_Sto_t * pSto = Gia_ManMatchCutsInt( p, nCutSize, nCutNum, 0 ); Vec_Wrd_t * vFuncs = Vec_WrdAlloc( 1000 ); Vec_Int_t * vLevel; int i, k, * pCut; Vec_WecForEachLevel( pSto->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) if ( pCut[0] == nCutSize ) { word * pTruth = Vec_MemReadEntry( pSto->vTtMem, Abc_Lit2Var(pCut[pCut[0]+1]) ); Vec_WrdPush( vFuncs, pTruth[0] ); } Gia_StoFree( pSto ); if ( fVerbose ) printf( "Collected %d cut functions using the AIG with %d nodes.\n", Vec_WrdSize(vFuncs), Gia_ManAndNum(p) ); return vFuncs; } Vec_Int_t * Gia_ManCountNpnClasses( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, int nClasses, Vec_Wrd_t * vOrig ) { assert( Vec_MemEntryNum(vTtMem) == Vec_IntSize(vMap) ); Vec_Int_t * vClassCounts = Vec_IntStart( nClasses ); int i; word Func; Vec_WrdForEachEntry( vOrig, Func, i ) { int * pSpot = Vec_MemHashLookup( vTtMem, &Func ); if ( *pSpot == -1 ) continue; int iClass = Vec_IntEntry( vMap, *pSpot ); if ( iClass == -1 ) continue; assert( iClass < Vec_IntSize(vClassCounts) ); Vec_IntAddToEntry( vClassCounts, iClass, 1 ); } return vClassCounts; } Vec_Wrd_t * Gia_ManMatchFilterClasses( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, Vec_Int_t * vClassCounts, int nNumFuncs, int fVerbose ) { int * pPerm = Abc_MergeSortCost( Vec_IntArray(vClassCounts), Vec_IntSize(vClassCounts) ); Vec_Wrd_t * vBest = Vec_WrdAlloc( nNumFuncs ); int i, k, Entry; Vec_Int_t * vMapNew = Vec_IntStartFull( Vec_IntSize(vMap) ); for ( i = Vec_IntSize(vClassCounts)-1; i >= 0; i-- ) { word Best = ~(word)0; Vec_IntForEachEntry( vMap, Entry, k ) { if ( Entry != pPerm[i] ) continue; if ( Best > Vec_MemReadEntry(vTtMem, k)[0] ) Best = Vec_MemReadEntry(vTtMem, k)[0]; Vec_IntWriteEntry( vMapNew, k, Vec_WrdSize(vBest) ); } Vec_WrdPush( vBest, Best ); assert( ~Best ); if ( Vec_WrdSize(vBest) == nNumFuncs ) break; } ABC_SWAP( Vec_Int_t, *vMap, *vMapNew ); Vec_IntFree( vMapNew ); ABC_FREE( pPerm ); if ( fVerbose ) printf( "Isolated %d (out of %d) most frequently occuring classes.\n", Vec_WrdSize(vBest), Vec_IntSize(vClassCounts) ); return vBest; } void Gia_ManMatchProfileFunctions( Vec_Wrd_t * vBestReprs, Vec_Mem_t * vTtMem, Vec_Int_t * vMap, Vec_Wrd_t * vFuncs, int nCutSize ) { int BarSize = 60; extern void Dau_DsdPrintFromTruth( word * pTruth, int nVarsInit ); Vec_Int_t * vCounts = Gia_ManCountNpnClasses( vTtMem, vMap, Vec_WrdSize(vBestReprs), vFuncs ); word Repr; int c, i, MaxCount = Vec_IntFindMax( vCounts ); Vec_WrdForEachEntry( vBestReprs, Repr, c ) { int nSymb = BarSize*Vec_IntEntry(vCounts, c)/Abc_MaxInt(MaxCount, 1); printf( "Class%4d : ", c ); printf( "Count =%6d ", Vec_IntEntry(vCounts, c) ); for ( i = 0; i < nSymb; i++ ) printf( "*" ); for ( i = nSymb; i < BarSize+3; i++ ) printf( " " ); Dau_DsdPrintFromTruth( &Repr, nCutSize ); } Vec_IntFree( vCounts ); } void Gia_ManMatchCones( Gia_Man_t * pBig, Gia_Man_t * pSmall, int nCutSize, int nCutNum, int nNumFuncs, int nNumCones, int fVerbose ) { abctime clkStart = Abc_Clock(); extern void Dau_CanonicizeArray( Vec_Wrd_t * vFuncs, int nVars, int fVerbose ); extern Vec_Mem_t * Dau_CollectNpnFunctionsArray( Vec_Wrd_t * vFuncs, int nVars, Vec_Int_t ** pvMap, int fVerbose ); Vec_Wrd_t * vFuncs = Gia_ManCollectCutFuncs( pSmall, nCutSize, nCutNum, fVerbose ); Vec_Wrd_t * vOrig = Vec_WrdDup( vFuncs ); Dau_CanonicizeArray( vFuncs, nCutSize, fVerbose ); Vec_Int_t * vMap = NULL; int n; Vec_Mem_t * vTtMem = Dau_CollectNpnFunctionsArray( vFuncs, nCutSize, &vMap, fVerbose ); Vec_WrdFree( vFuncs ); Vec_Int_t * vClassCounts = Gia_ManCountNpnClasses( vTtMem, vMap, Vec_IntEntryLast(vMap)+1, vOrig ); Vec_Wrd_t * vBestReprs = Gia_ManMatchFilterClasses( vTtMem, vMap, vClassCounts, nNumFuncs, fVerbose ); assert( Vec_WrdSize(vBestReprs) == nNumFuncs ); Vec_IntFree( vClassCounts ); printf( "Frequency profile for %d most popular classes in the small AIG:\n", nNumFuncs ); Gia_ManMatchProfileFunctions( vBestReprs, vTtMem, vMap, vOrig, nCutSize ); Vec_WrdFree( vOrig ); Abc_Random( 1 ); for ( n = 0; n < nNumCones; n++ ) { int nRand = Abc_Random( 0 ) % Gia_ManCoNum(pBig); Gia_Man_t * pCone = Gia_ManDupCones( pBig, &nRand, 1, 1 ); Vec_Wrd_t * vCutFuncs = Gia_ManCollectCutFuncs( pCone, nCutSize, nCutNum, 0 ); printf( "ITER %d: Considering output cone %d with %d and-nodes. ", n+1, nRand, Gia_ManAndNum(pCone) ); printf( "Profiling %d functions of %d-cuts:\n", Vec_WrdSize(vCutFuncs), nCutSize ); Gia_ManMatchProfileFunctions( vBestReprs, vTtMem, vMap, vCutFuncs, nCutSize ); Vec_WrdFree( vCutFuncs ); Gia_ManStop( pCone ); } Vec_WrdFree( vBestReprs ); Vec_IntFree( vMap ); Vec_MemHashFree( vTtMem ); Vec_MemFree( vTtMem ); Abc_PrintTime( 1, "Total computation time", Abc_Clock() - clkStart ); } /**Function************************************************************* Synopsis [Function enumeration.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManMatchConesMinimizeTts( Vec_Wrd_t * vSims, int nVarsMax ) { int nVars = 0; int nWordsMax = Abc_Truth6WordNum( nVarsMax ), nWords; int i, k = 0, nTruths = Vec_WrdSize(vSims) / nWordsMax; assert( nTruths * nWordsMax == Vec_WrdSize(vSims) ); // support-minimize and find the largest supp size for ( i = 0; i < nTruths; i++ ) { word * pTruth = Vec_WrdEntryP( vSims, i * nWordsMax ); int nVarsCur = Abc_TtMinBase( pTruth, NULL, nVarsMax, nVarsMax ); nVars = Abc_MaxInt( nVars, nVarsCur ); } // remap truth tables nWords = Abc_Truth6WordNum( nVars ); for ( i = 0; i < nTruths; i++ ) { word * pTruth = Vec_WrdEntryP( vSims, i * nWordsMax ); word * pTruth2 = Vec_WrdEntryP( vSims, k * nWords ); if ( Abc_TtSupportSize(pTruth, nVars) < 3 ) continue; memmove( pTruth2, pTruth, nWords * sizeof(word) ); k++; if ( 0 ) { extern void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars ); printf( "Type%d : ", i ); Extra_PrintHexadecimal( stdout, (unsigned *)pTruth2, nVars ); printf( "\n" ); } } Vec_WrdShrink ( vSims, k * nWords ); return nVars; } void Gia_ManMatchConesOutputPrint( Vec_Ptr_t * p, int fVerbose ) { Vec_Wec_t * vCuts; int i; printf( "Nodes with matching cuts:\n" ); Vec_PtrForEachEntry( Vec_Wec_t *, p, vCuts, i ) { if ( fVerbose ) { printf( "Type %d:\n", i ); Vec_WecPrint( vCuts, 0 ); } else printf( "Type %d present in %d cuts\n", i, Vec_WecSize(vCuts) ); } } void Gia_ManMatchConesOutputFree( Vec_Ptr_t * p ) { Vec_Wec_t * vCuts; int i; Vec_PtrForEachEntry( Vec_Wec_t *, p, vCuts, i ) Vec_WecFree( vCuts ); Vec_PtrFree( p ); } void Gia_ManMatchConesOutput( Gia_Man_t * pBig, Gia_Man_t * pSmall, int nCutNum, int fVerbose ) { abctime clkStart = Abc_Clock(); extern Vec_Mem_t * Dau_CollectNpnFunctionsArray( Vec_Wrd_t * vFuncs, int nVars, Vec_Int_t ** pvMap, int fVerbose ); Vec_Wrd_t * vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(pSmall) ); Vec_Wrd_t * vSims = Gia_ManSimPatSimOut( pSmall, vSimsPi, 1 ); int nVars = Gia_ManMatchConesMinimizeTts( vSims, Gia_ManCiNum(pSmall) ); Vec_WrdFree( vSimsPi ); if ( nVars > 10 ) { printf( "Some output functions have support size more than 10.\n" ); Vec_WrdFree( vSims ); return; } Vec_Int_t * vMap = NULL; Vec_Mem_t * vTtMem = Dau_CollectNpnFunctionsArray( vSims, nVars, &vMap, fVerbose ); int nFuncs = Vec_WrdSize(vSims) / Abc_Truth6WordNum(nVars); assert( Vec_WrdSize(vSims) == nFuncs * Abc_Truth6WordNum(nVars) ); Vec_WrdFree( vSims ); printf( "Using %d output functions with the support size between 3 and %d.\n", nFuncs, nVars ); Vec_Ptr_t * vRes = Gia_ManMatchCutsMany( vTtMem, vMap, nFuncs, pBig, nVars, nCutNum, fVerbose ); Vec_MemHashFree( vTtMem ); Vec_MemFree( vTtMem ); Vec_IntFree( vMap ); Gia_ManMatchConesOutputPrint( vRes, fVerbose ); Gia_ManMatchConesOutputFree( vRes ); Abc_PrintTime( 1, "Total computation time", Abc_Clock() - clkStart ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaDecs.c000066400000000000000000000322341477524141600157760ustar00rootroot00000000000000/**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 abc-0.52/src/aig/gia/giaDeep.c000066400000000000000000000211141477524141600157700ustar00rootroot00000000000000/**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++ ) { char * pCompress2rs = "balance -l; resub -K 6 -l; rewrite -l; resub -K 6 -N 2 -l; refactor -l; resub -K 8 -l; balance -l; resub -K 8 -N 2 -l; rewrite -l; resub -K 10 -l; rewrite -z -l; resub -K 10 -N 2 -l; balance -l; resub -K 12 -l; refactor -z -l; resub -K 12 -N 2 -l; rewrite -z -l; balance -l"; 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[2000]; char pComp[1000]; if ( fCom == 3 ) sprintf( pComp, "; &put; %s; %s; %s; &get", pCompress2rs, pCompress2rs, pCompress2rs ); else if ( fCom == 2 ) sprintf( pComp, "; &put; %s; %s; &get", pCompress2rs, pCompress2rs ); else if ( fCom == 1 ) sprintf( pComp, "; &put; %s; &get", pCompress2rs ); else if ( fCom == 0 ) sprintf( 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; } /**Function************************************************************* Synopsis [Generating one AIG by applying a randomized script.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManRandSyn( Gia_Man_t * p, unsigned random_seed ) { char * pCompress2rs = "balance -l; resub -K 6 -l; rewrite -l; resub -K 6 -N 2 -l; refactor -l; resub -K 8 -l; balance -l; resub -K 8 -N 2 -l; rewrite -l; resub -K 10 -l; rewrite -z -l; resub -K 10 -N 2 -l; balance -l; resub -K 12 -l; refactor -z -l; resub -K 12 -N 2 -l; rewrite -z -l; balance -l"; unsigned Rand = random_seed; int fDch = Rand & 1; //int fCom = (Rand >> 1) & 3; int fCom = (Rand >> 1) & 1; int fFx = (Rand >> 2) & 1; int fUseTwo = 0; int KLut = fUseTwo ? 2 + (Rand % 5) : 3 + (Rand % 4); //int fChange = 0; char Command[2000]; char pComp[1000]; if ( fCom == 3 ) sprintf( pComp, "; &put; %s; %s; %s; &get", pCompress2rs, pCompress2rs, pCompress2rs ); else if ( fCom == 2 ) sprintf( pComp, "; &put; %s; %s; &get", pCompress2rs, pCompress2rs ); else if ( fCom == 1 ) sprintf( pComp, "; &put; %s; &get", pCompress2rs ); else if ( fCom == 0 ) sprintf( 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 ); Gia_Man_t * pOld = Abc_FrameGetGia(Abc_FrameGetGlobalFrame()); Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), Gia_ManDup(p) ); 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 ); } Gia_Man_t * pRes = Abc_FrameGetGia(Abc_FrameGetGlobalFrame()); Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pOld ); return pRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaDfs.c000066400000000000000000000424021477524141600156320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaDfs.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [DFS procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Counts the support size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCollectCis_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) { Vec_IntPush( vSupp, Gia_ObjId(p, pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); Gia_ManCollectCis_rec( p, Gia_ObjFanin0(pObj), vSupp ); Gia_ManCollectCis_rec( p, Gia_ObjFanin1(pObj), vSupp ); } /**Function************************************************************* Synopsis [Collects support nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCollectCis( Gia_Man_t * p, int * pNodes, int nNodes, Vec_Int_t * vSupp ) { Gia_Obj_t * pObj; int i; Vec_IntClear( vSupp ); Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); for ( i = 0; i < nNodes; i++ ) { pObj = Gia_ManObj( p, pNodes[i] ); if ( Gia_ObjIsCo(pObj) ) Gia_ManCollectCis_rec( p, Gia_ObjFanin0(pObj), vSupp ); else Gia_ManCollectCis_rec( p, pObj, vSupp ); } } /**Function************************************************************* Synopsis [Counts the support size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCollectAnds_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vNodes ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) return; Gia_ObjSetTravIdCurrentId(p, iObj); pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjIsCi(pObj) ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManCollectAnds_rec( p, Gia_ObjFaninId0(pObj, iObj), vNodes ); Gia_ManCollectAnds_rec( p, Gia_ObjFaninId1(pObj, iObj), vNodes ); Vec_IntPush( vNodes, iObj ); } /**Function************************************************************* Synopsis [Collects support nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCollectAnds( Gia_Man_t * p, int * pNodes, int nNodes, Vec_Int_t * vNodes, Vec_Int_t * vLeaves ) { int i, iLeaf; // Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrentId( p, 0 ); if ( vLeaves ) Vec_IntForEachEntry( vLeaves, iLeaf, i ) Gia_ObjSetTravIdCurrentId( p, iLeaf ); Vec_IntClear( vNodes ); for ( i = 0; i < nNodes; i++ ) { Gia_Obj_t * pObj = Gia_ManObj( p, pNodes[i] ); if ( Gia_ObjIsCo(pObj) ) Gia_ManCollectAnds_rec( p, Gia_ObjFaninId0(pObj, pNodes[i]), vNodes ); else if ( Gia_ObjIsAnd(pObj) ) Gia_ManCollectAnds_rec( p, pNodes[i], vNodes ); } } /**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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCollectNodesCis_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) { Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); Gia_ManCollectNodesCis_rec( p, Gia_ObjFanin0(pObj), vNodes ); Gia_ManCollectNodesCis_rec( p, Gia_ObjFanin1(pObj), vNodes ); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); } /**Function************************************************************* Synopsis [Collects support nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManCollectNodesCis( Gia_Man_t * p, int * pNodes, int nNodes ) { Vec_Int_t * vNodes; Gia_Obj_t * pObj; int i; vNodes = Vec_IntAlloc( 10000 ); Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); for ( i = 0; i < nNodes; i++ ) { pObj = Gia_ManObj( p, pNodes[i] ); if ( Gia_ObjIsCo(pObj) ) Gia_ManCollectNodesCis_rec( p, Gia_ObjFanin0(pObj), vNodes ); else Gia_ManCollectNodesCis_rec( p, pObj, vNodes ); } return vNodes; } /**Function************************************************************* Synopsis [Collects support nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCollectTest( Gia_Man_t * p ) { Vec_Int_t * vNodes; Gia_Obj_t * pObj; int i, iNode; abctime clk = Abc_Clock(); vNodes = Vec_IntAlloc( 100 ); Gia_ManIncrementTravId( p ); Gia_ManForEachCo( p, pObj, i ) { iNode = Gia_ObjId(p, pObj); Gia_ManCollectAnds( p, &iNode, 1, vNodes, NULL ); } Vec_IntFree( vNodes ); ABC_PRT( "DFS from each output", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Collects support nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSuppSize_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 0; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) return 1; assert( Gia_ObjIsAnd(pObj) ); return Gia_ManSuppSize_rec( p, Gia_ObjFanin0(pObj) ) + Gia_ManSuppSize_rec( p, Gia_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Computes support size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSuppSizeOne( Gia_Man_t * p, Gia_Obj_t * pObj ) { Gia_ManIncrementTravId( p ); return Gia_ManSuppSize_rec( p, pObj ); } /**Function************************************************************* Synopsis [Computes support size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSuppSizeTest( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, Counter = 0; abctime clk = Abc_Clock(); Gia_ManForEachObj( p, pObj, i ) if ( Gia_ObjIsAnd(pObj) ) Counter += (Gia_ManSuppSizeOne(p, pObj) <= 16); printf( "Nodes with small support %d (out of %d)\n", Counter, Gia_ManAndNum(p) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return Counter; } /**Function************************************************************* Synopsis [Collects support nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSuppSize( Gia_Man_t * p, int * pNodes, int nNodes ) { Gia_Obj_t * pObj; int i, Counter = 0; Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); for ( i = 0; i < nNodes; i++ ) { pObj = Gia_ManObj( p, pNodes[i] ); if ( Gia_ObjIsCo(pObj) ) Counter += Gia_ManSuppSize_rec( p, Gia_ObjFanin0(pObj) ); else Counter += Gia_ManSuppSize_rec( p, pObj ); } return Counter; } /**Function************************************************************* Synopsis [Collects support nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManConeSize_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 0; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) return 0; assert( Gia_ObjIsAnd(pObj) ); return 1 + Gia_ManConeSize_rec( p, Gia_ObjFanin0(pObj) ) + Gia_ManConeSize_rec( p, Gia_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Collects support nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManConeSize( Gia_Man_t * p, int * pNodes, int nNodes ) { Gia_Obj_t * pObj; int i, Counter = 0; Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); for ( i = 0; i < nNodes; i++ ) { pObj = Gia_ManObj( p, pNodes[i] ); if ( Gia_ObjIsCo(pObj) ) Counter += Gia_ManConeSize_rec( p, Gia_ObjFanin0(pObj) ); else Counter += Gia_ManConeSize_rec( p, pObj ); } return Counter; } /**Function************************************************************* Synopsis [Levelizes the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Gia_ManLevelize( Gia_Man_t * p ) { Gia_Obj_t * pObj; Vec_Vec_t * vLevels; int nLevels, Level, i; nLevels = Gia_ManLevelNum( p ); vLevels = Vec_VecStart( nLevels + 1 ); Gia_ManForEachAnd( p, pObj, i ) { Level = Gia_ObjLevel( p, pObj ); assert( Level <= nLevels ); Vec_VecPush( vLevels, Level, pObj ); } 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.] Description [Assumes that levels are already assigned. The levels of CO nodes may not be assigned.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManOrderReverse( Gia_Man_t * p ) { Gia_Obj_t * pObj; Vec_Vec_t * vLevels; Vec_Ptr_t * vLevel; Vec_Int_t * vResult; int i, k; vLevels = Vec_VecStart( 100 ); // make sure levels are assigned Gia_ManForEachAnd( p, pObj, i ) assert( Gia_ObjLevel(p, pObj) > 0 ); // add CO nodes based on the level of their fanin Gia_ManForEachCo( p, pObj, i ) Vec_VecPush( vLevels, Gia_ObjLevel(p, Gia_ObjFanin0(pObj)), pObj ); // add other nodes based on their level Gia_ManForEachObj( p, pObj, i ) if ( !Gia_ObjIsCo(pObj) ) Vec_VecPush( vLevels, Gia_ObjLevel(p, pObj), pObj ); // put the nodes in the reverse topological order vResult = Vec_IntAlloc( Gia_ManObjNum(p) ); Vec_VecForEachLevelReverse( vLevels, vLevel, i ) Vec_PtrForEachEntry( Gia_Obj_t *, vLevel, pObj, k ) Vec_IntPush( vResult, Gia_ObjId(p, pObj) ); Vec_VecFree( vLevels ); return vResult; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCollectSeq_rec( Gia_Man_t * p, int Id, Vec_Int_t * vRoots, Vec_Int_t * vObjs ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId( p, Id ) ) return; Gia_ObjSetTravIdCurrentId( p, Id ); pObj = Gia_ManObj( p, Id ); if ( Gia_ObjIsAnd(pObj) ) { Gia_ManCollectSeq_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vObjs ); Gia_ManCollectSeq_rec( p, Gia_ObjFaninId1(pObj, Id), vRoots, vObjs ); } else if ( Gia_ObjIsCi(pObj) ) { if ( Gia_ObjIsRo(p, pObj) ) Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) ); } else if ( Gia_ObjIsCo(pObj) ) Gia_ManCollectSeq_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vObjs ); else assert( 0 ); Vec_IntPush( vObjs, Id ); } Vec_Int_t * Gia_ManCollectSeq( Gia_Man_t * p, int * pPos, int nPos ) { Vec_Int_t * vObjs, * vRoots; int i, iRoot; // collect roots vRoots = Vec_IntAlloc( 100 ); for ( i = 0; i < nPos; i++ ) Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ManPo(p, pPos[i])) ); // start trav IDs Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrentId( p, 0 ); // collect objects vObjs = Vec_IntAlloc( 1000 ); Vec_IntPush( vObjs, 0 ); Vec_IntForEachEntry( vRoots, iRoot, i ) Gia_ManCollectSeq_rec( p, iRoot, vRoots, vObjs ); Vec_IntFree( vRoots ); return vObjs; } void Gia_ManCollectSeqTest( Gia_Man_t * p ) { Vec_Int_t * vObjs; int i; abctime clk = Abc_Clock(); for ( i = 0; i < Gia_ManPoNum(p); i++ ) { if ( i % 10000 == 0 ) printf( "%8d finished...\r", i ); vObjs = Gia_ManCollectSeq( p, &i, 1 ); // printf( "%d ", Vec_IntSize(vObjs) ); Vec_IntFree( vObjs ); } Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Collect TFI nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCollectTfi_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vNodes ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) return; Gia_ObjSetTravIdCurrentId(p, iObj); pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjIsCi(pObj) ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManCollectTfi_rec( p, Gia_ObjFaninId0(pObj, iObj), vNodes ); Gia_ManCollectTfi_rec( p, Gia_ObjFaninId1(pObj, iObj), vNodes ); Vec_IntPush( vNodes, iObj ); } void Gia_ManCollectTfi( Gia_Man_t * p, Vec_Int_t * vRoots, Vec_Int_t * vNodes ) { int i, iRoot; Vec_IntClear( vNodes ); Gia_ManIncrementTravId( p ); Vec_IntForEachEntry( vRoots, iRoot, i ) Gia_ManCollectTfi_rec( p, iRoot, vNodes ); } /**Function************************************************************* Synopsis [Collect TFI nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCollectTfo_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vNodes ) { Gia_Obj_t * pObj; int i, iFan; if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) return; Gia_ObjSetTravIdCurrentId(p, iObj); pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjIsCo(pObj) ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ObjForEachFanoutStaticId( p, iObj, iFan, i ) Gia_ManCollectTfo_rec( p, iFan, vNodes ); Vec_IntPush( vNodes, iObj ); } void Gia_ManCollectTfo( Gia_Man_t * p, Vec_Int_t * vRoots, Vec_Int_t * vNodes ) { int i, iRoot; Vec_IntClear( vNodes ); Gia_ManIncrementTravId( p ); Vec_IntForEachEntry( vRoots, iRoot, i ) Gia_ManCollectTfo_rec( p, iRoot, vNodes ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaDup.c000066400000000000000000006422531477524141600156600ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaDup.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Duplication procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaDup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/tim/tim.h" #include "misc/vec/vecWec.h" #include "proof/cec/cec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern Bnd_Man_t* pBnd; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Removes pointers to the unmarked nodes..] Description [Array vLits contains literals of p. At the same time, each object pObj of p points to a literal of pNew. This procedure remaps literals in array vLits into literals of pNew.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupRemapLiterals( Vec_Int_t * vLits, Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, iLit, iLitNew; Vec_IntForEachEntry( vLits, iLit, i ) { if ( iLit < 0 ) continue; pObj = Gia_ManObj( p, Abc_Lit2Var(iLit) ); if ( ~pObj->Value == 0 ) iLitNew = -1; else iLitNew = Abc_LitNotCond( pObj->Value, Abc_LitIsCompl(iLit) ); Vec_IntWriteEntry( vLits, i, iLitNew ); } } /**Function************************************************************* Synopsis [Removes pointers to the unmarked nodes..] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupRemapEquiv( Gia_Man_t * pNew, Gia_Man_t * p ) { Vec_Int_t * vClass; int i, k, iNode, iRepr, iPrev; if ( p->pReprs == NULL ) return; assert( pNew->pReprs == NULL && 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 = iPrev = Vec_IntEntry( vClass, 0 ); Vec_IntForEachEntryStart( vClass, iNode, k, 1 ) { Gia_ObjSetRepr( pNew, iNode, iRepr ); assert( iPrev < iNode ); iPrev = iNode; } } Vec_IntFree( vClass ); pNew->pNexts = Gia_ManDeriveNexts( pNew ); } /**Function************************************************************* Synopsis [Remaps combinational inputs when objects are DFS ordered.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupRemapCis( Gia_Man_t * pNew, Gia_Man_t * p ) { Gia_Obj_t * pObj, * pObjNew; int i; assert( Vec_IntSize(p->vCis) == Vec_IntSize(pNew->vCis) ); Gia_ManForEachCi( p, pObj, i ) { assert( Gia_ObjCioId(pObj) == i ); pObjNew = Gia_ObjFromLit( pNew, pObj->Value ); assert( !Gia_IsComplement(pObjNew) ); Vec_IntWriteEntry( pNew->vCis, i, Gia_ObjId(pNew, pObjNew) ); Gia_ObjSetCioId( pObjNew, i ); } } /**Function************************************************************* Synopsis [Remaps combinational outputs when objects are DFS ordered.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupRemapCos( Gia_Man_t * pNew, Gia_Man_t * p ) { Gia_Obj_t * pObj, * pObjNew; int i; assert( Vec_IntSize(p->vCos) == Vec_IntSize(pNew->vCos) ); Gia_ManForEachCo( p, pObj, i ) { assert( Gia_ObjCioId(pObj) == i ); pObjNew = Gia_ObjFromLit( pNew, pObj->Value ); assert( !Gia_IsComplement(pObjNew) ); Vec_IntWriteEntry( pNew->vCos, i, Gia_ObjId(pNew, pObjNew) ); Gia_ObjSetCioId( pObjNew, i ); } } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManDupOrderDfs_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); // if ( p->pNexts && Gia_ObjNext(p, Gia_ObjId(p, pObj)) ) // Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjNextObj(p, Gia_ObjId(p, pObj)) ); Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); if ( Gia_ObjIsCo(pObj) ) return pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin1(pObj) ); return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } /**Function************************************************************* Synopsis [Duplicates AIG while putting objects in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupOrderDfs( Gia_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; 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_ManForEachCo( 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) ); Gia_ManDupRemapCis( pNew, p ); Gia_ManDupRemapEquiv( pNew, p ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG while putting objects in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupAbs( Gia_Man_t * p, Vec_Int_t * vMapPpi2Ff, Vec_Int_t * vMapFf2Ppi ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int k, Flop, Used; assert( Vec_IntSize(vMapFf2Ppi) == Vec_IntSize(vMapPpi2Ff) + Vec_IntCountEntry(vMapFf2Ppi, -1) ); 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; // create inputs Gia_ManForEachPi( p, pObj, k ) pObj->Value = Gia_ManAppendCi(pNew); Vec_IntForEachEntry( vMapPpi2Ff, Flop, k ) { pObj = Gia_ManCi( p, Gia_ManPiNum(p) + Flop ); pObj->Value = Gia_ManAppendCi(pNew); } Vec_IntForEachEntry( vMapFf2Ppi, Used, Flop ) { pObj = Gia_ManCi( p, Gia_ManPiNum(p) + Flop ); if ( Used >= 0 ) { assert( pObj->Value != ~0 ); continue; } assert( pObj->Value == ~0 ); pObj->Value = Gia_ManAppendCi(pNew); } Gia_ManForEachCi( p, pObj, k ) assert( pObj->Value != ~0 ); // create nodes Gia_ManForEachPo( p, pObj, k ) Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); Vec_IntForEachEntry( vMapFf2Ppi, Used, Flop ) { if ( Used >= 0 ) continue; pObj = Gia_ManCi( p, Gia_ManPiNum(p) + Flop ); pObj = Gia_ObjRoToRi( p, pObj ); Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); } // create outputs Gia_ManForEachPo( p, pObj, k ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Vec_IntForEachEntry( vMapFf2Ppi, Used, Flop ) { if ( Used >= 0 ) continue; pObj = Gia_ManCi( p, Gia_ManPiNum(p) + Flop ); pObj = Gia_ObjRoToRi( p, pObj ); pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) - Vec_IntSize(vMapPpi2Ff) ); assert( Gia_ManPiNum(pNew) == Gia_ManPiNum(p) + Vec_IntSize(vMapPpi2Ff) ); assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) ); assert( Gia_ManPoNum(pNew) == Gia_ManPoNum(p) ); assert( Gia_ManCoNum(pNew) == Gia_ManCoNum(p) - Vec_IntSize(vMapPpi2Ff) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG while putting objects in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupOutputGroup( Gia_Man_t * p, int iOutStart, int iOutStop ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; 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; for ( i = iOutStart; i < iOutStop; i++ ) { pObj = Gia_ManCo( p, i ); Gia_ManDupOrderDfs_rec( pNew, p, pObj ); } return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG while putting objects in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupOutputVec( Gia_Man_t * p, Vec_Int_t * vOutPres ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; assert( Gia_ManRegNum(p) == 0 ); assert( Gia_ManPoNum(p) == Vec_IntSize(vOutPres) ); 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_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManForEachPo( p, pObj, i ) if ( Vec_IntEntry(vOutPres, i) ) Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManForEachPo( p, pObj, i ) if ( Vec_IntEntry(vOutPres, i) ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG while putting objects in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupSelectedOutputs( Gia_Man_t * p, Vec_Int_t * vOutsLeft ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, iOut; assert( Gia_ManRegNum(p) == 0 ); assert( Gia_ManPoNum(p) >= Vec_IntSize(vOutsLeft) ); 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_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Vec_IntForEachEntry( vOutsLeft, iOut, i ) Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(Gia_ManPo(p, iOut)) ); Vec_IntForEachEntry( vOutsLeft, iOut, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, iOut)) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupOrderDfsChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pNext; if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); pNext = Gia_ObjNextObj( p, Gia_ObjId(p, pObj) ); if ( pNext ) Gia_ManDupOrderDfsChoices_rec( pNew, p, pNext ); Gia_ManDupOrderDfsChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManDupOrderDfsChoices_rec( pNew, p, Gia_ObjFanin1(pObj) ); pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( pNext ) { pNew->pNexts[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var( Abc_Lit2Var(pNext->Value) ); assert( Abc_Lit2Var(pObj->Value) > Abc_Lit2Var(pNext->Value) ); } } /**Function************************************************************* Synopsis [Duplicates AIG while putting objects in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupOrderDfsChoices( Gia_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; assert( p->pReprs && p->pNexts ); Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManForEachCo( p, pObj, i ) { Gia_ManDupOrderDfsChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // Gia_ManDeriveReprs( pNew ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG while putting objects in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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; int i; 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); 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 ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG while putting first PIs, then nodes, then POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupOrderAiger( 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_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) ); Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManDupRemapEquiv( pNew, p ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); assert( Gia_ManIsNormalized(pNew) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG while putting first PIs, then nodes, then POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupOnsetOffset( 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_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) ); Gia_ManForEachCo( p, pObj, i ) { pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); pObj->Value = Gia_ManAppendCo( pNew, Abc_LitNot(Gia_ObjFanin0Copy(pObj)) ); } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG while putting first PIs, then nodes, then POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupLastPis( Gia_Man_t * p, int nLastPis ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; assert( Gia_ManRegNum(p) == 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_ManForEachCi( p, pObj, i ) pObj->Value = (i < Gia_ManCiNum(p) - nLastPis) ? ~0 : 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) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG while complementing the flops.] Description [The array of initial state contains the init state for each state bit of the flops in the design.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupFlip( Gia_Man_t * p, int * pInitState ) { 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_ObjIsAnd(pObj) ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsCi(pObj) ) { pObj->Value = Gia_ManAppendCi( pNew ); if ( Gia_ObjCioId(pObj) >= Gia_ManPiNum(p) ) pObj->Value = Abc_LitNotCond( pObj->Value, Abc_InfoHasBit((unsigned *)pInitState, Gia_ObjCioId(pObj) - Gia_ManPiNum(p)) ); } else if ( Gia_ObjIsCo(pObj) ) { pObj->Value = Gia_ObjFanin0Copy(pObj); if ( Gia_ObjCioId(pObj) >= Gia_ManPoNum(p) ) pObj->Value = Abc_LitNotCond( pObj->Value, Abc_InfoHasBit((unsigned *)pInitState, Gia_ObjCioId(pObj) - Gia_ManPoNum(p)) ); pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); } } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Cycles AIG using random input.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCycle( Gia_Man_t * p, Abc_Cex_t * pCex, int nFrames ) { Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i, k; Gia_ManRandom( 1 ); assert( pCex == NULL || nFrames <= pCex->iFrame ); // iterate for the given number of frames for ( i = 0; i < nFrames; i++ ) { Gia_ManForEachPi( p, pObj, k ) pObj->fMark0 = pCex ? Abc_InfoHasBit(pCex->pData, pCex->nRegs+i*pCex->nPis+k) : (1 & Gia_ManRandom(0)); 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_ManForEachRiRo( p, pObjRi, pObjRo, k ) pObjRo->fMark0 = pObjRi->fMark0; } } Gia_Man_t * Gia_ManDupCycled( Gia_Man_t * p, Abc_Cex_t * pCex, int nFrames ) { Gia_Man_t * pNew; Vec_Bit_t * vInits; Gia_Obj_t * pObj; int i; Gia_ManCleanMark0(p); Gia_ManCycle( p, pCex, nFrames ); vInits = Vec_BitAlloc( Gia_ManRegNum(p) ); Gia_ManForEachRo( p, pObj, i ) Vec_BitPush( vInits, pObj->fMark0 ); pNew = Gia_ManDupFlip( p, Vec_BitArray(vInits) ); Vec_BitFree( vInits ); Gia_ManCleanMark0(p); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG without any changes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDup( 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 ); if ( Gia_ManHasChoices(p) ) pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManConst0(p)->Value = 0; 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_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) ) pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))->Value); } 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) ); if ( p->pCexSeq ) pNew->pCexSeq = Abc_CexDup( p->pCexSeq, Gia_ManRegNum(p) ); return pNew; } Gia_Man_t * Gia_ManDup2( Gia_Man_t * p1, Gia_Man_t * p2 ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; assert( Gia_ManCiNum(p1) == Gia_ManCiNum(p2) ); assert( Gia_ManCoNum(p1) == Gia_ManCoNum(p2) ); pNew = Gia_ManStart( Gia_ManObjNum(p1) + Gia_ManObjNum(p2) ); 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( p1, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachAnd( p2, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( p1, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManForEachCo( p2, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p1) ); Gia_ManHashStop( pNew ); return pNew; } Gia_Man_t * Gia_ManDupWithAttributes( Gia_Man_t * p ) { Gia_Man_t * pNew = Gia_ManDup(p); Gia_ManTransferMapping( pNew, p ); Gia_ManTransferPacking( pNew, p ); if ( p->pManTime ) pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); if ( p->pAigExtra ) pNew->pAigExtra = Gia_ManDup( p->pAigExtra ); if ( p->nAnd2Delay ) pNew->nAnd2Delay = p->nAnd2Delay; if ( p->vRegClasses ) pNew->vRegClasses = Vec_IntDup( p->vRegClasses ); if ( p->vRegInits ) pNew->vRegInits = Vec_IntDup( p->vRegInits ); if ( p->vConfigs ) pNew->vConfigs = Vec_IntDup( p->vConfigs ); if ( p->pCellStr ) pNew->pCellStr = Abc_UtilStrsav( p->pCellStr ); // copy names if present if ( p->vNamesIn ) pNew->vNamesIn = Vec_PtrDupStr( p->vNamesIn ); if ( p->vNamesOut ) pNew->vNamesOut = Vec_PtrDupStr( p->vNamesOut ); return pNew; } Gia_Man_t * Gia_ManDupRemovePis( Gia_Man_t * p, int nRemPis ) { 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_ObjIsAnd(pObj) ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsCi(pObj) && Gia_ObjCioId(pObj) < Gia_ManCiNum(p)-nRemPis ) 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_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************************************************************* Synopsis [Duplicates AIG without any changes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupZero( Gia_Man_t * p ) { Gia_Man_t * pNew; int i; pNew = Gia_ManStart( 1 + Gia_ManCiNum(p) + Gia_ManCoNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); for ( i = 0; i < Gia_ManCiNum(p); i++ ) Gia_ManAppendCi( pNew ); for ( i = 0; i < Gia_ManCoNum(p); i++ ) Gia_ManAppendCo( pNew, 0 ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG without any changes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupPerm( Gia_Man_t * p, Vec_Int_t * vPiPerm ) { // Vec_Int_t * vPiPermInv; Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; assert( Vec_IntSize(vPiPerm) == Gia_ManPiNum(p) ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; // vPiPermInv = Vec_IntInvert( vPiPerm, -1 ); Gia_ManForEachPi( p, pObj, i ) // Gia_ManPi(p, Vec_IntEntry(vPiPermInv,i))->Value = Gia_ManAppendCi( pNew ); Gia_ManPi(p, Vec_IntEntry(vPiPerm,i))->Value = Gia_ManAppendCi( pNew ); // Vec_IntFree( vPiPermInv ); 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_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsCi(pObj) ) { if ( Gia_ObjIsRo(p, 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_ManDupPermFlop( Gia_Man_t * p, Vec_Int_t * vFfPerm ) { //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 ); 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 ) 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(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)) ) ); 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; } Gia_Man_t * Gia_ManDupSpreadFlop( Gia_Man_t * p, Vec_Int_t * vFfMask ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, k, Entry; assert( Vec_IntSize(vFfMask) >= Gia_ManRegNum(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_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); k = 0; Vec_IntForEachEntry( vFfMask, Entry, i ) if ( Entry == -1 ) Gia_ManAppendCi(pNew); else Gia_ManRo(p, k++)->Value = Gia_ManAppendCi(pNew); assert( k == Gia_ManRegNum(p) ); 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) ); k = 0; Vec_IntForEachEntry( vFfMask, Entry, i ) if ( Entry == -1 ) Gia_ManAppendCo( pNew, 0 ); else { pObj = Gia_ManRi( p, k++ ); pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } assert( k == Gia_ManRegNum(p) ); Gia_ManSetRegNum( pNew, Vec_IntSize(vFfMask) ); return pNew; } Gia_Man_t * Gia_ManDupPermFlopGap( Gia_Man_t * p, Vec_Int_t * vFfMask ) { Vec_Int_t * vPerm = Vec_IntCondense( vFfMask, -1 ); Gia_Man_t * pPerm = Gia_ManDupPermFlop( p, vPerm ); Gia_Man_t * pSpread = Gia_ManDupSpreadFlop( pPerm, vFfMask ); Vec_IntFree( vPerm ); Gia_ManStop( pPerm ); 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupAppend( Gia_Man_t * pNew, Gia_Man_t * pTwo ) { Gia_Obj_t * pObj; int i; if ( pNew->nRegs > 0 ) pNew->nRegs = 0; if ( Vec_IntSize(&pNew->vHTable) == 0 ) Gia_ManHashStart( pNew ); Gia_ManConst0(pTwo)->Value = 0; Gia_ManForEachObj1( pTwo, pObj, i ) { 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) ); } } void Gia_ManDupAppendShare( Gia_Man_t * pNew, Gia_Man_t * pTwo ) { Gia_Obj_t * pObj; int i; assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(pTwo) ); if ( Vec_IntSize(&pNew->vHTable) == 0 ) Gia_ManHashStart( pNew ); Gia_ManConst0(pTwo)->Value = 0; Gia_ManForEachObj1( pTwo, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsCi(pObj) ) pObj->Value = Gia_Obj2Lit( pNew, Gia_ManCi( pNew, Gia_ObjCioId(pObj) ) ); else if ( Gia_ObjIsCo(pObj) ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } } Gia_Man_t * Gia_ManDupAppendNew( Gia_Man_t * pOne, Gia_Man_t * pTwo ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; pNew = Gia_ManStart( Gia_ManObjNum(pOne) + Gia_ManObjNum(pTwo) ); pNew->pName = Abc_UtilStrsav( pOne->pName ); pNew->pSpec = Abc_UtilStrsav( pOne->pSpec ); Gia_ManHashAlloc( pNew ); Gia_ManConst0(pOne)->Value = 0; Gia_ManForEachObj1( pOne, pObj, i ) { 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 ); } Gia_ManConst0(pTwo)->Value = 0; Gia_ManForEachObj1( pTwo, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsPi(pTwo, pObj) ) pObj->Value = Gia_ManPi(pOne, Gia_ObjCioId(pObj))->Value; else if ( Gia_ObjIsCi(pObj) ) pObj->Value = Gia_ManAppendCi( pNew ); } Gia_ManHashStop( pNew ); // primary outputs Gia_ManForEachPo( pOne, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManForEachPo( pTwo, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); // flop inputs Gia_ManForEachRi( pOne, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManForEachRi( pTwo, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); 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************************************************************* Synopsis [Creates a miter for inductive checking of the invariant.] Description [The first GIA (p) is a sequential AIG whose transition relation is used. The second GIA (pInv) is a combinational AIG representing the invariant over the register outputs. If the resulting combination miter is UNSAT, the invariant holds by simple induction.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupInvMiter( Gia_Man_t * p, Gia_Man_t * pInv ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, Node1, Node2, Node; assert( Gia_ManRegNum(p) > 0 ); assert( Gia_ManRegNum(pInv) == 0 ); assert( Gia_ManCoNum(pInv) == 1 ); assert( Gia_ManRegNum(p) == Gia_ManCiNum(pInv) ); Gia_ManFillValue(p); pNew = Gia_ManStart( Gia_ManObjNum(p) + 2*Gia_ManObjNum(pInv) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObj1( p, pObj, i ) { 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); } // build invariant on top of register outputs in the first frame Gia_ManForEachRo( p, pObj, i ) Gia_ManCi(pInv, i)->Value = pObj->Value; Gia_ManForEachAnd( pInv, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); pObj = Gia_ManCo( pInv, 0 ); Node1 = Gia_ObjFanin0Copy(pObj); // build invariant on top of register outputs in the second frame Gia_ManForEachRi( p, pObj, i ) Gia_ManCi(pInv, i)->Value = pObj->Value; Gia_ManForEachAnd( pInv, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); pObj = Gia_ManCo( pInv, 0 ); Node2 = Gia_ObjFanin0Copy(pObj); // create miter output Node = Gia_ManHashAnd( pNew, Node1, Abc_LitNot(Node2) ); Gia_ManAppendCo( pNew, Node ); // cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Appends logic cones as additional property outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupAppendCones( Gia_Man_t * p, Gia_Man_t ** ppCones, int nCones, int fOnlyRegs ) { Gia_Man_t * pNew, * pOne; 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_ManHashAlloc( 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_ManForEachPo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); for ( k = 0; k < nCones; k++ ) { pOne = ppCones[k]; assert( Gia_ManPoNum(pOne) == 1 ); assert( Gia_ManRegNum(pOne) == 0 ); if ( fOnlyRegs ) assert( Gia_ManPiNum(pOne) == Gia_ManRegNum(p) ); else assert( Gia_ManPiNum(pOne) == Gia_ManCiNum(p) ); Gia_ManConst0(pOne)->Value = 0; Gia_ManForEachPi( pOne, pObj, i ) pObj->Value = Gia_ManCiLit( pNew, fOnlyRegs ? Gia_ManPiNum(p) + i : i ); Gia_ManForEachAnd( pOne, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachPo( pOne, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Gia_ManForEachRi( 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 [Duplicates while adding self-loops to the registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupSelf( Gia_Man_t * p ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iCtrl; 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; iCtrl = Gia_ManAppendCi( 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 ) pObj->Value = Gia_ObjFanin0Copy(pObj); Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ManHashMux( pNew, iCtrl, Gia_ObjFanin0Copy(pObj), Gia_ObjRiToRo(p, pObj)->Value ); Gia_ManForEachCo( p, pObj, i ) Gia_ManAppendCo( pNew, pObj->Value ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Duplicates while adding self-loops to the registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupFlopClass( Gia_Man_t * p, int iClass ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, Counter1 = 0, Counter2 = 0; assert( p->vFlopClasses != NULL ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachRo( p, pObj, i ) if ( Vec_IntEntry(p->vFlopClasses, i) != iClass ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachRo( p, pObj, i ) if ( Vec_IntEntry(p->vFlopClasses, i) == iClass ) pObj->Value = Gia_ManAppendCi( pNew ), Counter1++; Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachPo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManForEachRi( p, pObj, i ) if ( Vec_IntEntry(p->vFlopClasses, i) != iClass ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManForEachRi( p, pObj, i ) if ( Vec_IntEntry(p->vFlopClasses, i) == iClass ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ), Counter2++; assert( Counter1 == Counter2 ); Gia_ManSetRegNum( pNew, Counter1 ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG without any changes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupMarked( Gia_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, nRos = 0, nRis = 0; int CountMarked = 0; Gia_ManForEachObj( p, pObj, i ) CountMarked += pObj->fMark0; Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) - CountMarked ); if ( p->pMuxes ) pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); pNew->nConstrs = p->nConstrs; pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObj1( p, pObj, i ) { if ( pObj->fMark0 ) { assert( !Gia_ObjIsBuf(pObj) ); pObj->fMark0 = 0; continue; } if ( Gia_ObjIsBuf(pObj) ) pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); else if ( Gia_ObjIsAnd(pObj) ) { if ( Gia_ObjIsXor(pObj) ) pObj->Value = Gia_ManAppendXorReal( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsMux(p, pObj) ) pObj->Value = Gia_ManAppendMuxReal( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); else pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } else if ( Gia_ObjIsCi(pObj) ) { pObj->Value = Gia_ManAppendCi( pNew ); nRos += Gia_ObjIsRo(p, pObj); } else if ( Gia_ObjIsCo(pObj) ) { // Gia_Obj_t * pFanin = Gia_ObjFanin0(pObj); pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); nRis += Gia_ObjIsRi(p, pObj); } } assert( pNew->nObjsAlloc == pNew->nObjs ); assert( nRos == nRis ); Gia_ManSetRegNum( pNew, nRos ); if ( p->pReprs && p->pNexts ) { Gia_Obj_t * pRepr; pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pNew) ); for ( i = 0; i < Gia_ManObjNum(pNew); i++ ) Gia_ObjSetRepr( pNew, i, GIA_VOID ); Gia_ManForEachObj1( p, pObj, i ) { if ( !~pObj->Value ) continue; pRepr = Gia_ObjReprObj( p, i ); if ( pRepr == NULL ) continue; if ( !~pRepr->Value ) continue; assert( !Gia_ObjIsBuf(pObj) ); if ( Abc_Lit2Var(pObj->Value) != Abc_Lit2Var(pRepr->Value) ) Gia_ObjSetRepr( pNew, Abc_Lit2Var(pObj->Value), Abc_Lit2Var(pRepr->Value) ); } pNew->pNexts = Gia_ManDeriveNexts( pNew ); } if ( Gia_ManHasChoices(p) ) { Gia_Obj_t * pSibl; pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(pNew) ); Gia_ManForEachObj1( p, pObj, i ) { if ( !~pObj->Value ) continue; pSibl = Gia_ObjSiblObj( p, i ); if ( pSibl == NULL ) continue; if ( !~pSibl->Value ) continue; assert( !Gia_ObjIsBuf(pObj) ); assert( Abc_Lit2Var(pObj->Value) > Abc_Lit2Var(pSibl->Value) ); pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(pSibl->Value); } } return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG while creating "parallel" copies.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupTimes( Gia_Man_t * p, int nTimes ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; Vec_Int_t * vPis, * vPos, * vRis, * vRos; int i, t, Entry; assert( nTimes > 0 ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; vPis = Vec_IntAlloc( Gia_ManPiNum(p) * nTimes ); vPos = Vec_IntAlloc( Gia_ManPoNum(p) * nTimes ); vRis = Vec_IntAlloc( Gia_ManRegNum(p) * nTimes ); vRos = Vec_IntAlloc( Gia_ManRegNum(p) * nTimes ); for ( t = 0; t < nTimes; t++ ) { Gia_ManForEachObj1( p, pObj, i ) { 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 ); if ( Gia_ObjIsPi(p, pObj) ) Vec_IntPush( vPis, Abc_Lit2Var(pObj->Value) ); else Vec_IntPush( vRos, Abc_Lit2Var(pObj->Value) ); } else if ( Gia_ObjIsCo(pObj) ) { pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); if ( Gia_ObjIsPo(p, pObj) ) Vec_IntPush( vPos, Abc_Lit2Var(pObj->Value) ); else Vec_IntPush( vRis, Abc_Lit2Var(pObj->Value) ); } } } Vec_IntClear( pNew->vCis ); Vec_IntForEachEntry( vPis, Entry, i ) { Gia_ObjSetCioId( Gia_ManObj(pNew, Entry), Vec_IntSize(pNew->vCis) ); Vec_IntPush( pNew->vCis, Entry ); } Vec_IntForEachEntry( vRos, Entry, i ) { Gia_ObjSetCioId( Gia_ManObj(pNew, Entry), Vec_IntSize(pNew->vCis) ); Vec_IntPush( pNew->vCis, Entry ); } Vec_IntClear( pNew->vCos ); Vec_IntForEachEntry( vPos, Entry, i ) { Gia_ObjSetCioId( Gia_ManObj(pNew, Entry), Vec_IntSize(pNew->vCos) ); Vec_IntPush( pNew->vCos, Entry ); } Vec_IntForEachEntry( vRis, Entry, i ) { Gia_ObjSetCioId( Gia_ManObj(pNew, Entry), Vec_IntSize(pNew->vCos) ); Vec_IntPush( pNew->vCos, Entry ); } Vec_IntFree( vPis ); Vec_IntFree( vPos ); Vec_IntFree( vRis ); Vec_IntFree( vRos ); Gia_ManSetRegNum( pNew, nTimes * Gia_ManRegNum(p) ); 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManDupDfs2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( ~pObj->Value ) return pObj->Value; if ( p->pReprsOld && ~p->pReprsOld[Gia_ObjId(p, pObj)] ) { Gia_Obj_t * pRepr = Gia_ManObj( p, p->pReprsOld[Gia_ObjId(p, pObj)] ); pRepr->Value = Gia_ManDupDfs2_rec( pNew, p, pRepr ); return pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); } if ( Gia_ObjIsCi(pObj) ) return pObj->Value = Gia_ManAppendCi(pNew); Gia_ManDupDfs2_rec( pNew, p, Gia_ObjFanin0(pObj) ); if ( Gia_ObjIsCo(pObj) ) return pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManDupDfs2_rec( pNew, p, Gia_ObjFanin1(pObj) ); if ( Vec_IntSize(&pNew->vHTable) ) return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupDfs2( Gia_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj, * pObjNew; int i; 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_ManForEachCo( p, pObj, i ) Gia_ManDupDfs2_rec( pNew, p, pObj ); Gia_ManForEachCi( p, pObj, i ) if ( ~pObj->Value == 0 ) pObj->Value = Gia_ManAppendCi(pNew); assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) ); // remap combinational inputs Gia_ManForEachCi( p, pObj, i ) { pObjNew = Gia_ObjFromLit( pNew, pObj->Value ); assert( !Gia_IsComplement(pObjNew) ); Vec_IntWriteEntry( pNew->vCis, Gia_ObjCioId(pObj), Gia_ObjId(pNew, pObjNew) ); Gia_ObjSetCioId( pObjNew, Gia_ObjCioId(pObj) ); } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupDfs_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManDupDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManDupDfs_rec( pNew, p, Gia_ObjFanin1(pObj) ); pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } Gia_Man_t * Gia_ManDupDfs( 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_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManForEachCo( p, pObj, i ) Gia_ManDupDfs_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) ); pNew->nConstrs = p->nConstrs; if ( p->pCexSeq ) 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************************************************************* Synopsis [Cofactors w.r.t. a primary input variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupCofactorVar_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManDupCofactorVar_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManDupCofactorVar_rec( pNew, p, Gia_ObjFanin1(pObj) ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } Gia_Man_t * Gia_ManDupCofactorVar( Gia_Man_t * p, int iVar, int Value ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; assert( iVar >= 0 && iVar < Gia_ManPiNum(p) ); assert( Value == 0 || Value == 1 ); 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_ManPi( p, iVar )->Value = Value; // modification! Gia_ManHashAlloc( pNew ); Gia_ManForEachCo( p, pObj, i ) Gia_ManDupCofactorVar_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManForEachCo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew->nConstrs = p->nConstrs; pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } Gia_Man_t * Gia_ManDupMux( int iVar, Gia_Man_t * pCof1, Gia_Man_t * pCof0 ) { Gia_Man_t * pGia[2] = {pCof0, pCof1}; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, n; assert( Gia_ManRegNum(pCof0) == 0 ); assert( Gia_ManRegNum(pCof1) == 0 ); assert( Gia_ManCoNum(pCof0) == 1 ); assert( Gia_ManCoNum(pCof1) == 1 ); assert( Gia_ManCiNum(pCof1) == Gia_ManCiNum(pCof0) ); assert( iVar >= 0 && iVar < Gia_ManCiNum(pCof1) ); pNew = Gia_ManStart( Gia_ManObjNum(pCof1) + Gia_ManObjNum(pCof0) ); pNew->pName = Abc_UtilStrsav( pCof1->pName ); pNew->pSpec = Abc_UtilStrsav( pCof1->pSpec ); Gia_ManHashAlloc( pNew ); for ( n = 0; n < 2; n++ ) { Gia_ManFillValue( pGia[n] ); Gia_ManConst0(pGia[n])->Value = 0; Gia_ManForEachCi( pGia[n], pObj, i ) pObj->Value = n ? Gia_ManCi(pGia[0], i)->Value : Gia_ManAppendCi(pNew); Gia_ManForEachCo( pGia[n], pObj, i ) Gia_ManDupCofactorVar_rec( pNew, pGia[n], Gia_ObjFanin0(pObj) ); } Gia_ManForEachCo( pGia[0], pObj, i ) { int Ctrl = Gia_ManCi(pGia[0], iVar)->Value; int Lit1 = Gia_ObjFanin0Copy(Gia_ManCo(pGia[1], i)); int Lit0 = Gia_ObjFanin0Copy(pObj); Gia_ManAppendCo( pNew, Gia_ManHashMux( pNew, Ctrl, Lit1, Lit0 ) ); } pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Cofactors w.r.t. an internal node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupCofactorObj( Gia_Man_t * p, int iObj, int Value ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iObjValue = -1; assert( Gia_ManRegNum(p) == 0 ); assert( iObj > 0 && iObj < Gia_ManObjNum(p) ); assert( Gia_ObjIsCand(Gia_ManObj(p, iObj)) ); assert( Value == 0 || Value == 1 ); 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_ObjIsCi(pObj) ) pObj->Value = Gia_ManAppendCi( pNew ); else if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsCo(pObj) ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, Gia_ObjFanin0Copy(pObj), iObjValue) ); if ( i == iObj ) iObjValue = Abc_LitNotCond(pObj->Value, !Value), pObj->Value = Value; } pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Reduce bit-width of GIA assuming it is Boolean.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupBlock( Gia_Man_t * p, int nBlock ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; assert( Gia_ManCiNum(p) % nBlock == 0 ); assert( Gia_ManCoNum(p) % nBlock == 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, pObj, i ) pObj->Value = (i % nBlock == 0) ? Gia_ManAppendCi(pNew) : 0; Gia_ManHashAlloc( pNew ); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( p, pObj, i ) if ( i % nBlock == 0 ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p)/nBlock ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Existentially quantified given variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupExist( Gia_Man_t * p, int iVar ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; assert( iVar >= 0 && iVar < Gia_ManPiNum(p) ); assert( Gia_ManPoNum(p) == 1 ); assert( Gia_ManRegNum(p) == 0 ); Gia_ManFillValue( p ); // find the cofactoring variable pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); // compute negative cofactor Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManPi( p, iVar )->Value = Abc_Var2Lit( 0, 0 ); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachPo( p, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); // compute the positive cofactor Gia_ManPi( p, iVar )->Value = Abc_Var2Lit( 0, 1 ); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // create OR gate Gia_ManForEachPo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ManHashOr(pNew, Gia_ObjFanin0Copy(pObj), pObj->Value) ); Gia_ManHashStop( pNew ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Existentially quantified given variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupUniv( Gia_Man_t * p, int iVar ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; assert( iVar >= 0 && iVar < Gia_ManPiNum(p) ); assert( Gia_ManRegNum(p) == 0 ); Gia_ManFillValue( p ); // find the cofactoring variable pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); // compute negative cofactor Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManPi( p, iVar )->Value = Abc_Var2Lit( 0, 0 ); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachPo( p, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); // compute the positive cofactor Gia_ManPi( p, iVar )->Value = Abc_Var2Lit( 0, 1 ); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // create OR gate Gia_ManForEachPo( p, pObj, i ) { if ( i == 0 ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, Gia_ObjFanin0Copy(pObj), pObj->Value) ); else pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Gia_ManHashStop( pNew ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Existentially quantifies the given variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupExist2( Gia_Man_t * p, int iVar ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; assert( iVar >= 0 && iVar < Gia_ManPiNum(p) ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManFillValue( p ); Gia_ManHashAlloc( pNew ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); // first part Gia_ManPi( p, iVar )->Value = 0; // modification! Gia_ManForEachCo( p, pObj, i ) Gia_ManDupCofactorVar_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); // second part Gia_ManPi( p, iVar )->Value = 1; // modification! Gia_ManForEachAnd( p, pObj, i ) pObj->Value = ~0; Gia_ManForEachCo( p, pObj, i ) Gia_ManDupCofactorVar_rec( pNew, p, Gia_ObjFanin0(pObj) ); // combination Gia_ManForEachCo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ManHashOr(pNew, Gia_ObjFanin0Copy(pObj), pObj->Value) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew->nConstrs = p->nConstrs; pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order while putting CIs first.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupDfsSkip( Gia_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; 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_ManForEachCo( p, pObj, i ) if ( pObj->fMark1 == 0 ) Gia_ManDupDfs_rec( pNew, p, pObj ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order while putting CIs first.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupDfsCone( Gia_Man_t * p, Gia_Obj_t * pRoot ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; assert( Gia_ObjIsCo(pRoot) ); 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_ManDupDfs_rec( pNew, p, Gia_ObjFanin0(pRoot) ); Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pRoot) ); Gia_ManSetRegNum( pNew, 0 ); return pNew; } /**Function************************************************************* Synopsis [Duplicates logic cone of the literal and inserts it back.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupConeSupp_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjs ) { int iLit0, iLit1, iObj = Gia_ObjId( p, pObj ); int iLit = Gia_ObjCopyArray( p, iObj ); if ( iLit >= 0 ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManDupConeSupp_rec( pNew, p, Gia_ObjFanin0(pObj), vObjs ); Gia_ManDupConeSupp_rec( pNew, p, Gia_ObjFanin1(pObj), vObjs ); iLit0 = Gia_ObjCopyArray( p, Gia_ObjFaninId0(pObj, iObj) ); iLit1 = Gia_ObjCopyArray( p, Gia_ObjFaninId1(pObj, iObj) ); iLit0 = Abc_LitNotCond( iLit0, Gia_ObjFaninC0(pObj) ); iLit1 = Abc_LitNotCond( iLit1, Gia_ObjFaninC1(pObj) ); iLit = Gia_ManAppendAnd( pNew, iLit0, iLit1 ); Gia_ObjSetCopyArray( p, iObj, iLit ); Vec_IntPush( vObjs, iObj ); } Gia_Man_t * Gia_ManDupConeSupp( Gia_Man_t * p, int iLit, Vec_Int_t * vCiIds ) { Gia_Man_t * pNew; int i, iLit0; Gia_Obj_t * pObj, * pRoot = Gia_ManObj( p, Abc_Lit2Var(iLit) ); Vec_Int_t * vObjs = Vec_IntAlloc( 1000 ); //assert( Gia_ObjIsAnd(pRoot) ); if ( Vec_IntSize(&p->vCopies) < Gia_ManObjNum(p) ) Vec_IntFillExtra( &p->vCopies, Gia_ManObjNum(p), -1 ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManForEachCiVec( vCiIds, p, pObj, i ) Gia_ObjSetCopyArray( p, Gia_ObjId(p, pObj), Gia_ManAppendCi(pNew) ); Gia_ManDupConeSupp_rec( pNew, p, pRoot, vObjs ); iLit0 = Gia_ObjCopyArray( p, Abc_Lit2Var(iLit) ); iLit0 = Abc_LitNotCond( iLit0, Abc_LitIsCompl(iLit) ); Gia_ManAppendCo( pNew, iLit0 ); Gia_ManForEachCiVec( vCiIds, p, pObj, i ) Gia_ObjSetCopyArray( p, Gia_ObjId(p, pObj), -1 ); Gia_ManForEachObjVec( vObjs, p, pObj, i ) Gia_ObjSetCopyArray( p, Gia_ObjId(p, pObj), -1 ); Vec_IntFree( vObjs ); //assert( Vec_IntCountLarger(&p->vCopies, -1) == 0 ); return pNew; } void Gia_ManDupConeBack_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManDupConeBack_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManDupConeBack_rec( pNew, p, Gia_ObjFanin1(pObj) ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } int Gia_ManDupConeBack( Gia_Man_t * p, Gia_Man_t * pNew, Vec_Int_t * vCiIds ) { Gia_Obj_t * pObj, * pRoot; int i; assert( Gia_ManCiNum(pNew) == Vec_IntSize(vCiIds) ); Gia_ManFillValue(pNew); Gia_ManConst0(pNew)->Value = 0; Gia_ManForEachCi( pNew, pObj, i ) pObj->Value = Gia_Obj2Lit( p, Gia_ManCi(p, Vec_IntEntry(vCiIds, i)) ); pRoot = Gia_ManCo(pNew, 0); Gia_ManDupConeBack_rec( p, pNew, Gia_ObjFanin0(pRoot) ); return Gia_ObjFanin0Copy(pRoot); } int Gia_ManDupConeBackObjs( Gia_Man_t * p, Gia_Man_t * pNew, Vec_Int_t * vObjs ) { Gia_Obj_t * pObj, * pRoot; int i; assert( Gia_ManCiNum(pNew) == Vec_IntSize(vObjs) ); Gia_ManFillValue(pNew); Gia_ManConst0(pNew)->Value = 0; Gia_ManForEachCi( pNew, pObj, i ) pObj->Value = Abc_Var2Lit( Vec_IntEntry(vObjs, i), 0 ); pRoot = Gia_ManCo(pNew, 0); Gia_ManDupConeBack_rec( p, pNew, Gia_ObjFanin0(pRoot) ); return Gia_ObjFanin0Copy(pRoot); } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order while putting CIs first.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupDfs3_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( ~pObj->Value ) return; if ( Gia_ObjIsCi(pObj) ) { pObj->Value = Gia_ManAppendCi(pNew); return; } assert( Gia_ObjIsAnd(pObj) ); Gia_ManDupDfs3_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManDupDfs3_rec( pNew, p, Gia_ObjFanin1(pObj) ); pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } Gia_Man_t * Gia_ManDupDfsNode( Gia_Man_t * p, Gia_Obj_t * pRoot ) { Gia_Man_t * pNew; assert( Gia_ObjIsAnd(pRoot) ); 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_ManDupDfs3_rec( pNew, p, pRoot ); Gia_ManAppendCo( pNew, pRoot->Value ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order while putting CIs first.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupDfsLitArray( Gia_Man_t * p, Vec_Int_t * vLits ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, iLit, iLitRes; 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); Vec_IntForEachEntry( vLits, iLit, i ) { iLitRes = Gia_ManDupDfs2_rec( pNew, p, Gia_ManObj(p, Abc_Lit2Var(iLit)) ); Gia_ManAppendCo( pNew, Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iLit)) ); } Gia_ManSetRegNum( pNew, 0 ); return pNew; } /**Function************************************************************* Synopsis [Returns the array of non-const-0 POs of the dual-output miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManDupTrimmedNonZero( Gia_Man_t * p ) { Vec_Int_t * vNonZero; Gia_Man_t * pTemp, * pNonDual; Gia_Obj_t * pObj; int i; assert( (Gia_ManPoNum(p) & 1) == 0 ); pNonDual = Gia_ManTransformMiter( p ); pNonDual = Gia_ManSeqStructSweep( pTemp = pNonDual, 1, 1, 0 ); Gia_ManStop( pTemp ); assert( Gia_ManPiNum(pNonDual) > 0 ); assert( 2 * Gia_ManPoNum(pNonDual) == Gia_ManPoNum(p) ); // skip PO pairs corresponding to const0 POs of the non-dual miter vNonZero = Vec_IntAlloc( 100 ); Gia_ManForEachPo( pNonDual, pObj, i ) if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) Vec_IntPush( vNonZero, i ); Gia_ManStop( pNonDual ); return vNonZero; } /**Function************************************************************* Synopsis [Returns 1 if PO can be removed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManPoIsToRemove( Gia_Man_t * p, Gia_Obj_t * pObj, int Value ) { assert( Gia_ObjIsCo(pObj) ); if ( Value == -1 ) return Gia_ObjIsConst0(Gia_ObjFanin0(pObj)); assert( Value == 0 || Value == 1 ); return Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) && Value == Gia_ObjFaninC0(pObj); } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order while putting CIs first.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupTrimmed( Gia_Man_t * p, int fTrimCis, int fTrimCos, int fDualOut, int OutValue ) { Vec_Int_t * vNonZero = NULL; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, Entry; // collect non-zero if ( fDualOut && fTrimCos ) vNonZero = Gia_ManDupTrimmedNonZero( p ); // start new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // check if there are PIs to be added Gia_ManCreateRefs( p ); Gia_ManForEachPi( p, pObj, i ) if ( !fTrimCis || Gia_ObjRefNum(p, pObj) ) break; if ( i == Gia_ManPiNum(p) ) // there is no PIs - add dummy PI Gia_ManAppendCi(pNew); // add the ROs Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) if ( !fTrimCis || Gia_ObjRefNum(p, pObj) || Gia_ObjIsRo(p, pObj) ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( fDualOut && fTrimCos ) { Vec_IntForEachEntry( vNonZero, Entry, i ) { Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, 2*Entry+0)) ); Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, 2*Entry+1)) ); } if ( Gia_ManPoNum(pNew) == 0 ) // nothing - add dummy PO { // Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, 0)) ); // Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, 1)) ); Gia_ManAppendCo( pNew, 0 ); Gia_ManAppendCo( pNew, 0 ); } Gia_ManForEachRi( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // cleanup pNew = Gia_ManSeqStructSweep( pTemp = pNew, 1, 1, 0 ); Gia_ManStop( pTemp ); // trim the PIs // pNew = Gia_ManDupTrimmed( pTemp = pNew, 1, 0, 0 ); // Gia_ManStop( pTemp ); } else { // check if there are POs to be added Gia_ManForEachPo( p, pObj, i ) if ( !fTrimCos || !Gia_ManPoIsToRemove(p, pObj, OutValue) ) break; if ( i == Gia_ManPoNum(p) ) // there is no POs - add dummy PO Gia_ManAppendCo( pNew, 0 ); Gia_ManForEachCo( p, pObj, i ) if ( !fTrimCos || !Gia_ManPoIsToRemove(p, pObj, OutValue) || Gia_ObjIsRi(p, pObj) ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); } Vec_IntFreeP( &vNonZero ); assert( !Gia_ManHasDangling( pNew ) ); return pNew; } /**Function************************************************************* Synopsis [Removes POs driven by PIs and PIs without fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupTrimmed2( Gia_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; // start new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // check if there are PIs to be added Gia_ManCreateRefs( p ); // discount references of POs Gia_ManForEachPo( p, pObj, i ) Gia_ObjRefFanin0Dec( p, pObj ); // check if PIs are left Gia_ManForEachPi( p, pObj, i ) if ( Gia_ObjRefNum(p, pObj) ) break; if ( i == Gia_ManPiNum(p) ) // there is no PIs - add dummy PI Gia_ManAppendCi(pNew); // add the ROs Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) if ( Gia_ObjRefNum(p, pObj) || Gia_ObjIsRo(p, pObj) ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // check if there are POs to be added Gia_ManForEachPo( p, pObj, i ) if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) && !Gia_ObjIsPi(p, Gia_ObjFanin0(pObj)) ) break; if ( i == Gia_ManPoNum(p) ) // there is no POs - add dummy PO Gia_ManAppendCo( pNew, 0 ); Gia_ManForEachCo( p, pObj, i ) if ( (!Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) && !Gia_ObjIsPi(p, Gia_ObjFanin0(pObj))) || Gia_ObjIsRi(p, pObj) ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); assert( !Gia_ManHasDangling( pNew ) ); return pNew; } Gia_Man_t * Gia_ManDupTrimmed3( Gia_Man_t * p ) { Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // mark duplicated POs Gia_ManForEachPo( p, pObj, i ) Vec_IntWriteEntry( vMap, Gia_ObjFaninId0p(p, pObj), i ); Gia_ManForEachPo( p, pObj, i ) if ( Vec_IntEntry(vMap, Gia_ObjFaninId0p(p, pObj)) == i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Vec_IntFree( vMap ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order while putting CIs first.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupOntop( Gia_Man_t * p, Gia_Man_t * p2 ) { Gia_Man_t * pTemp, * pNew; Gia_Obj_t * pObj; int i; assert( Gia_ManPoNum(p) == Gia_ManPiNum(p2) ); assert( Gia_ManRegNum(p) == 0 ); assert( Gia_ManRegNum(p2) == 0 ); pNew = Gia_ManStart( Gia_ManObjNum(p)+Gia_ManObjNum(p2) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); // dup first AIG 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) ); // dup second AIG Gia_ManConst0(p2)->Value = 0; Gia_ManForEachCo( p, pObj, i ) Gia_ManPi(p2, i)->Value = Gia_ObjFanin0Copy(pObj); Gia_ManForEachAnd( p2, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( p2, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); // Gia_ManPrintStats( pGiaNew, 0 ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Duplicates transition relation from p1 and property from p2.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupWithNewPo( Gia_Man_t * p1, Gia_Man_t * p2 ) { Gia_Man_t * pTemp, * pNew; Gia_Obj_t * pObj; int i; // there is no flops in p2 assert( Gia_ManRegNum(p2) == 0 ); // there is only one PO in p2 // assert( Gia_ManPoNum(p2) == 1 ); // input count of p2 is equal to flop count of p1 assert( Gia_ManPiNum(p2) == Gia_ManRegNum(p1) ); // start new AIG pNew = Gia_ManStart( Gia_ManObjNum(p1)+Gia_ManObjNum(p2) ); pNew->pName = Abc_UtilStrsav( p1->pName ); pNew->pSpec = Abc_UtilStrsav( p1->pSpec ); Gia_ManHashAlloc( pNew ); // dup first AIG Gia_ManConst0(p1)->Value = 0; Gia_ManForEachCi( p1, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManForEachAnd( p1, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // dup second AIG Gia_ManConst0(p2)->Value = 0; Gia_ManForEachPi( p2, pObj, i ) pObj->Value = Gia_ManRo(p1, i)->Value; Gia_ManForEachAnd( p2, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // add property output Gia_ManForEachPo( p2, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); // add flop inputs Gia_ManForEachRi( p1, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p1) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Print representatives.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintRepr( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) if ( ~p->pReprsOld[i] ) printf( "%d->%d ", i, p->pReprs[i].iRepr ); printf( "\n" ); } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupDfsCiMap( Gia_Man_t * p, int * pCi2Lit, Vec_Int_t * vLits ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; 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); if ( ~pCi2Lit[i] ) pObj->Value = Abc_LitNotCond( Gia_ManObj(p, Abc_Lit2Var(pCi2Lit[i]))->Value, Abc_LitIsCompl(pCi2Lit[i]) ); } Gia_ManHashAlloc( pNew ); if ( vLits ) { int iLit, iLitRes; Vec_IntForEachEntry( vLits, iLit, i ) { iLitRes = Gia_ManDupDfs2_rec( pNew, p, Gia_ManObj(p, Abc_Lit2Var(iLit)) ); Gia_ManAppendCo( pNew, Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iLit)) ); } } else { Gia_ManForEachCo( p, pObj, i ) { Gia_ManDupDfs2_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } } Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Permute inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManPermuteInputs( Gia_Man_t * p, int nPpis, int nExtra ) { 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; for ( i = 0; i < Gia_ManPiNum(p) - nPpis - nExtra; i++ ) // regular PIs Gia_ManCi(p, i)->Value = Gia_ManAppendCi( pNew ); for ( i = Gia_ManPiNum(p) - nExtra; i < Gia_ManPiNum(p); i++ ) // extra PIs due to DC values Gia_ManCi(p, i)->Value = Gia_ManAppendCi( pNew ); for ( i = Gia_ManPiNum(p) - nPpis - nExtra; i < Gia_ManPiNum(p) - nExtra; i++ ) // pseudo-PIs Gia_ManCi(p, i)->Value = Gia_ManAppendCi( pNew ); for ( i = Gia_ManPiNum(p); i < Gia_ManCiNum(p); i++ ) // flop outputs Gia_ManCi(p, i)->Value = Gia_ManAppendCi( pNew ); assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) ); 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) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupDfsClasses( Gia_Man_t * p ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; assert( p->pReprsOld != NULL ); 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_ManHashAlloc( pNew ); Gia_ManForEachCo( p, pObj, i ) Gia_ManDupDfs_rec( pNew, p, pObj ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Detect topmost gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupTopAnd_iter( Gia_Man_t * p, int fVerbose ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; Vec_Int_t * vFront, * vLeaves; int i, iLit, iObjId, nCiLits, * pCi2Lit; char * pVar2Val; // collect the frontier vFront = Vec_IntAlloc( 1000 ); vLeaves = Vec_IntAlloc( 1000 ); Gia_ManForEachCo( p, pObj, i ) { if ( Gia_ObjIsConst0( Gia_ObjFanin0(pObj) ) ) continue; if ( Gia_ObjFaninC0(pObj) ) Vec_IntPush( vLeaves, Gia_ObjFaninLit0p(p, pObj) ); else Vec_IntPush( vFront, Gia_ObjFaninId0p(p, pObj) ); } if ( Vec_IntSize(vFront) == 0 ) { if ( fVerbose ) printf( "The AIG cannot be decomposed using AND-decomposition.\n" ); Vec_IntFree( vFront ); Vec_IntFree( vLeaves ); return Gia_ManDupNormalize( p, 0 ); } // expand the frontier Gia_ManForEachObjVec( vFront, p, pObj, i ) { if ( Gia_ObjIsCi(pObj) ) { Vec_IntPush( vLeaves, Abc_Var2Lit( Gia_ObjId(p, pObj), 0 ) ); continue; } assert( Gia_ObjIsAnd(pObj) ); if ( Gia_ObjFaninC0(pObj) ) Vec_IntPush( vLeaves, Gia_ObjFaninLit0p(p, pObj) ); else Vec_IntPush( vFront, Gia_ObjFaninId0p(p, pObj) ); if ( Gia_ObjFaninC1(pObj) ) Vec_IntPush( vLeaves, Gia_ObjFaninLit1p(p, pObj) ); else Vec_IntPush( vFront, Gia_ObjFaninId1p(p, pObj) ); } Vec_IntFree( vFront ); // sort the literals nCiLits = 0; pCi2Lit = ABC_FALLOC( int, Gia_ManObjNum(p) ); pVar2Val = ABC_FALLOC( char, Gia_ManObjNum(p) ); Vec_IntForEachEntry( vLeaves, iLit, i ) { iObjId = Abc_Lit2Var(iLit); pObj = Gia_ManObj(p, iObjId); if ( Gia_ObjIsCi(pObj) ) { pCi2Lit[Gia_ObjCioId(pObj)] = !Abc_LitIsCompl(iLit); nCiLits++; } if ( pVar2Val[iObjId] != 0 && pVar2Val[iObjId] != 1 ) pVar2Val[iObjId] = Abc_LitIsCompl(iLit); else if ( pVar2Val[iObjId] != Abc_LitIsCompl(iLit) ) break; } if ( i < Vec_IntSize(vLeaves) ) { printf( "Problem is trivially UNSAT.\n" ); ABC_FREE( pCi2Lit ); ABC_FREE( pVar2Val ); Vec_IntFree( vLeaves ); return Gia_ManDupNormalize( p, 0 ); } // create array of input literals Vec_IntClear( vLeaves ); Gia_ManForEachObj( p, pObj, i ) if ( !Gia_ObjIsCi(pObj) && (pVar2Val[i] == 0 || pVar2Val[i] == 1) ) Vec_IntPush( vLeaves, Abc_Var2Lit(i, pVar2Val[i]) ); if ( fVerbose ) printf( "Detected %6d AND leaves and %6d CI leaves.\n", Vec_IntSize(vLeaves), nCiLits ); // create the input map if ( nCiLits == 0 ) pNew = Gia_ManDupDfsLitArray( p, vLeaves ); else pNew = Gia_ManDupDfsCiMap( p, pCi2Lit, vLeaves ); ABC_FREE( pCi2Lit ); ABC_FREE( pVar2Val ); Vec_IntFree( vLeaves ); return pNew; } /**Function************************************************************* Synopsis [Detect topmost gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupTopAnd( Gia_Man_t * p, int fVerbose ) { Gia_Man_t * pNew, * pTemp; int fContinue, iIter = 0; pNew = Gia_ManDupNormalize( p, 0 ); for ( fContinue = 1; fContinue; ) { pNew = Gia_ManDupTopAnd_iter( pTemp = pNew, fVerbose ); if ( Gia_ManCoNum(pNew) == Gia_ManCoNum(pTemp) && Gia_ManAndNum(pNew) == Gia_ManAndNum(pTemp) ) fContinue = 0; Gia_ManStop( pTemp ); if ( fVerbose ) { printf( "Iter %2d : ", ++iIter ); Gia_ManPrintStatsShort( pNew ); } } return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManMiter_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( ~pObj->Value ) return pObj->Value; assert( Gia_ObjIsAnd(pObj) ); Gia_ManMiter_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManMiter_rec( pNew, p, Gia_ObjFanin1(pObj) ); return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } /**Function************************************************************* Synopsis [Creates miter of two designs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManMiter( Gia_Man_t * p0, Gia_Man_t * p1, int nInsDup, int fDualOut, int fSeq, int fImplic, int fVerbose ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iLit; if ( fSeq ) { if ( Gia_ManPiNum(p0) != Gia_ManPiNum(p1) ) { printf( "Gia_ManMiter(): Designs have different number of PIs.\n" ); return NULL; } if ( Gia_ManPoNum(p0) != Gia_ManPoNum(p1) ) { printf( "Gia_ManMiter(): Designs have different number of POs.\n" ); return NULL; } if ( Gia_ManRegNum(p0) == 0 || Gia_ManRegNum(p1) == 0 ) { printf( "Gia_ManMiter(): At least one of the designs has no registers.\n" ); return NULL; } } else { if ( Gia_ManCiNum(p0) != Gia_ManCiNum(p1) ) { printf( "Gia_ManMiter(): Designs have different number of CIs.\n" ); return NULL; } if ( Gia_ManCoNum(p0) != Gia_ManCoNum(p1) ) { printf( "Gia_ManMiter(): Designs have different number of COs.\n" ); return NULL; } } // start the manager pNew = Gia_ManStart( Gia_ManObjNum(p0) + Gia_ManObjNum(p1) ); pNew->pName = Abc_UtilStrsav( "miter" ); // map combinational inputs Gia_ManFillValue( p0 ); Gia_ManFillValue( p1 ); Gia_ManConst0(p0)->Value = 0; Gia_ManConst0(p1)->Value = 0; // map internal nodes and outputs Gia_ManHashAlloc( pNew ); if ( fSeq ) { // create primary inputs Gia_ManForEachPi( p0, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachPi( p1, pObj, i ) if ( i < Gia_ManPiNum(p1) - nInsDup ) pObj->Value = Gia_ObjToLit( pNew, Gia_ManPi(pNew, i) ); else pObj->Value = Gia_ManAppendCi( pNew ); // create latch outputs Gia_ManForEachRo( p0, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachRo( p1, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); // create primary outputs Gia_ManForEachPo( p0, pObj, i ) { Gia_ManMiter_rec( pNew, p0, Gia_ObjFanin0(pObj) ); Gia_ManMiter_rec( pNew, p1, Gia_ObjFanin0(Gia_ManPo(p1,i)) ); if ( fDualOut ) { Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p1,i)) ); } else if ( fImplic ) { iLit = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Abc_LitNot(Gia_ObjFanin0Copy(Gia_ManPo(p1,i))) ); Gia_ManAppendCo( pNew, iLit ); } else { iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(Gia_ManPo(p1,i)) ); Gia_ManAppendCo( pNew, iLit ); } } // create register inputs Gia_ManForEachRi( p0, pObj, i ) { Gia_ManMiter_rec( pNew, p0, Gia_ObjFanin0(pObj) ); pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Gia_ManForEachRi( p1, pObj, i ) { Gia_ManMiter_rec( pNew, p1, Gia_ObjFanin0(pObj) ); pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p0) + Gia_ManRegNum(p1) ); } else { // create combinational inputs Gia_ManForEachCi( p0, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachCi( p1, pObj, i ) if ( i < Gia_ManCiNum(p1) - nInsDup ) pObj->Value = Gia_ObjToLit( pNew, Gia_ManCi(pNew, i) ); else pObj->Value = Gia_ManAppendCi( pNew ); // create combinational outputs Gia_ManForEachCo( p0, pObj, i ) { Gia_ManMiter_rec( pNew, p0, Gia_ObjFanin0(pObj) ); Gia_ManMiter_rec( pNew, p1, Gia_ObjFanin0(Gia_ManCo(p1,i)) ); if ( fDualOut ) { Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManCo(p1,i)) ); } else if ( fImplic ) { iLit = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Abc_LitNot(Gia_ObjFanin0Copy(Gia_ManPo(p1,i))) ); Gia_ManAppendCo( pNew, iLit ); } else { iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(Gia_ManCo(p1,i)) ); Gia_ManAppendCo( pNew, iLit ); } } } Gia_ManHashStop( pNew ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); pNew = Gia_ManDupNormalize( pTemp = pNew, 0 ); Gia_ManStop( pTemp ); 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupAndOr( Gia_Man_t * p, int nOuts, int fUseOr, int fCompl ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iResult; assert( Gia_ManRegNum(p) == 0 ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManConst0(p)->Value = 0; Gia_ManHashAlloc( pNew ); Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( fUseOr ) // construct OR of all POs { iResult = 0; Gia_ManForEachPo( p, pObj, i ) iResult = Gia_ManHashOr( pNew, iResult, Gia_ObjFanin0Copy(pObj) ); } else // construct AND of all POs { iResult = 1; Gia_ManForEachPo( p, pObj, i ) iResult = Gia_ManHashAnd( pNew, iResult, Gia_ObjFanin0Copy(pObj) ); } iResult = Abc_LitNotCond( iResult, (int)(fCompl > 0) ); // Gia_ManForEachPo( p, pObj, i ) // pObj->Value = Gia_ManAppendCo( pNew, iResult ); for ( i = 0; i < nOuts; i++ ) Gia_ManAppendCo( pNew, iResult ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManTransformMiter( Gia_Man_t * p ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObj2; int i, iLit; assert( (Gia_ManPoNum(p) & 1) == 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_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 ) { pObj2 = Gia_ManPo( p, ++i ); iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(pObj2) ); Gia_ManAppendCo( pNew, iLit ); } Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); 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 ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObj2; int i, iLit, nPart = Gia_ManPoNum(p)/2; assert( (Gia_ManPoNum(p) & 1) == 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_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 ) { if ( i == nPart ) break; pObj2 = Gia_ManPo( p, nPart + i ); iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(pObj2) ); Gia_ManAppendCo( pNew, iLit ); } Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } Gia_Man_t * Gia_ManTransformToDual( 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_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_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManAppendCo( pNew, 0 ); } Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } Gia_Man_t * Gia_ManTransformTwoWord2DualOutput( Gia_Man_t * p ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObj2; int i, nPart = Gia_ManPoNum(p)/2; assert( (Gia_ManPoNum(p) & 1) == 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_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 ) { if ( i == nPart ) break; pObj2 = Gia_ManPo( p, nPart + i ); Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj2) ); } Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } void Gia_ManCollectOneSide_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( !Gia_ObjIsAnd(pObj) ) return; Gia_ManCollectOneSide_rec( p, Gia_ObjFanin0(pObj), vNodes ); Gia_ManCollectOneSide_rec( p, Gia_ObjFanin1(pObj), vNodes ); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); } Vec_Int_t * Gia_ManCollectOneSide( Gia_Man_t * p, int iSide ) { Gia_Obj_t * pObj; int i; Vec_Int_t * vNodes = Vec_IntAlloc( Gia_ManAndNum(p) ); Gia_ManIncrementTravId( p ); Gia_ManForEachPo( p, pObj, i ) if ( (i & 1) == iSide ) Gia_ManCollectOneSide_rec( p, Gia_ObjFanin0(pObj), vNodes ); return vNodes; } Gia_Man_t * Gia_ManTransformDualOutput( Gia_Man_t * p ) { Vec_Int_t * vNodes0 = Gia_ManCollectOneSide( p, 0 ); Vec_Int_t * vNodes1 = Gia_ManCollectOneSide( p, 1 ); Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObj2; int i, fSwap = 0; assert( Gia_ManRegNum(p) == 0 ); assert( (Gia_ManPoNum(p) & 1) == 0 ); if ( Vec_IntSize(vNodes0) > Vec_IntSize(vNodes1) ) { ABC_SWAP( Vec_Int_t *, vNodes0, vNodes1 ); fSwap = 1; } assert( Vec_IntSize(vNodes0) <= Vec_IntSize(vNodes1) ); 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_ManForEachObjVec( vNodes0, p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachObjVec( vNodes1, p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Vec_IntFree( vNodes0 ); Vec_IntFree( vNodes1 ); Gia_ManForEachPo( p, pObj, i ) { pObj2 = Gia_ManPo( p, i^fSwap ); pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj2) ); } Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Performs 'zero' and 'undc' operation.] Description [The init string specifies 0/1/X for each flop.] SideEffects [] SeeAlso [] ***********************************************************************/ 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; int CountPis = Gia_ManPiNum(p), * pPiLits; int i, iResetFlop = -1, Count1 = 0; //printf( "Using %s\n", pInit ); // map X-valued flops into new PIs assert( (int)strlen(pInit) == Gia_ManRegNum(p) ); pPiLits = ABC_FALLOC( int, Gia_ManRegNum(p) ); for ( i = 0; i < Gia_ManRegNum(p); i++ ) if ( pInit[i] == 'x' || pInit[i] == 'X' ) pPiLits[i] = CountPis++; // create new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->fGiaSimple = fGiaSimple; Gia_ManConst0(p)->Value = 0; // create primary inputs Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); // 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 ); // create reset flop output if ( CountPis > Gia_ManPiNum(p) ) iResetFlop = Gia_ManAppendCi( pNew ); // update flop outputs Gia_ManMarkFanoutDrivers( p ); Gia_ManForEachRo( p, pObj, i ) { if ( pInit[i] == '1' ) pObj->Value = Abc_LitNot(pObj->Value), Count1++; else if ( pInit[i] == 'x' || pInit[i] == 'X' ) { if ( pObj->fMark0 ) // only add MUX if the flop has fanout pObj->Value = Gia_ManAppendMux( pNew, iResetFlop, pObj->Value, Gia_Obj2Lit(pNew, Gia_ManPi(pNew, pPiLits[i])) ); } else if ( pInit[i] != '0' ) assert( 0 ); } Gia_ManCleanMark0( p ); ABC_FREE( pPiLits ); // build internal nodes Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // create POs Gia_ManForEachPo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); // create flop inputs Gia_ManForEachRi( p, pObj, i ) if ( pInit[i] == '1' ) pObj->Value = Gia_ManAppendCo( pNew, Abc_LitNot(Gia_ObjFanin0Copy(pObj)) ); else pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); // create reset flop input if ( CountPis > Gia_ManPiNum(p) ) Gia_ManAppendCo( pNew, 1 ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) + (int)(CountPis > Gia_ManPiNum(p)) ); if ( fVerbose ) printf( "Converted %d 1-valued FFs and %d DC-valued FFs.\n", Count1, CountPis-Gia_ManPiNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Creates miter of two designs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManMiter2( Gia_Man_t * pStart, char * pInit, int fVerbose ) { Vec_Int_t * vCiValues, * vCoValues0, * vCoValues1; Gia_Man_t * pNew, * pUndc, * pTemp; Gia_Obj_t * pObj; char * pInitNew; int i, k; // check PI values 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, 0, fVerbose ); // create new init string pInitNew = ABC_ALLOC( char, Gia_ManPiNum(pUndc)+1 ); for ( i = 0; i < Gia_ManPiNum(pStart); i++ ) pInitNew[i] = pInit[i]; for ( i = k = Gia_ManPiNum(pStart); i < Gia_ManCiNum(pStart); i++ ) if ( pInit[i] == 'x' || pInit[i] == 'X' ) pInitNew[k++] = pInit[i]; pInitNew[k] = 0; assert( k == Gia_ManPiNum(pUndc) ); // derive miter pNew = Gia_ManStart( Gia_ManObjNum(pUndc) ); pNew->pName = Abc_UtilStrsav( pUndc->pName ); pNew->pSpec = Abc_UtilStrsav( pUndc->pSpec ); Gia_ManConst0(pUndc)->Value = 0; Gia_ManHashAlloc( pNew ); // add PIs of the first side Gia_ManForEachPi( pUndc, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); // add PIs of the second side vCiValues = Vec_IntAlloc( Gia_ManPiNum(pUndc) ); Gia_ManForEachPi( pUndc, pObj, i ) if ( pInitNew[i] == 'x' ) Vec_IntPush( vCiValues, Gia_Obj2Lit( pNew, Gia_ManPi(pNew, i) ) ); else if ( pInitNew[i] == 'X' ) Vec_IntPush( vCiValues, Gia_ManAppendCi( pNew ) ); else assert( 0 ); // build flops and internal nodes Gia_ManForEachRo( pUndc, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachAnd( pUndc, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // collect CO values vCoValues0 = Vec_IntAlloc( Gia_ManPoNum(pUndc) ); Gia_ManForEachCo( pUndc, pObj, i ) Vec_IntPush( vCoValues0, Gia_ObjFanin0Copy(pObj) ); // build the other side Gia_ManForEachPi( pUndc, pObj, i ) pObj->Value = Vec_IntEntry( vCiValues, i ); Gia_ManForEachRo( pUndc, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachAnd( pUndc, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // collect CO values vCoValues1 = Vec_IntAlloc( Gia_ManPoNum(pUndc) ); Gia_ManForEachCo( pUndc, pObj, i ) Vec_IntPush( vCoValues1, Gia_ObjFanin0Copy(pObj) ); // create POs Gia_ManForEachPo( pUndc, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ManHashXor( pNew, Vec_IntEntry(vCoValues0, i), Vec_IntEntry(vCoValues1, i) ) ); // create flop inputs Gia_ManForEachRi( pUndc, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Vec_IntEntry(vCoValues0, Gia_ManPoNum(pUndc)+i) ); Gia_ManForEachRi( pUndc, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Vec_IntEntry(vCoValues1, Gia_ManPoNum(pUndc)+i) ); Vec_IntFree( vCoValues0 ); Vec_IntFree( vCoValues1 ); Vec_IntFree( vCiValues ); ABC_FREE( pInitNew ); // cleanup Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, 2*Gia_ManRegNum(pUndc) ); Gia_ManStop( pUndc ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManChoiceMiter_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( ~pObj->Value ) return pObj->Value; Gia_ManChoiceMiter_rec( pNew, p, Gia_ObjFanin0(pObj) ); if ( Gia_ObjIsCo(pObj) ) return pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManChoiceMiter_rec( pNew, p, Gia_ObjFanin1(pObj) ); return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } /**Function************************************************************* Synopsis [Derives the miter of several AIGs for choice computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManChoiceMiter( Vec_Ptr_t * vGias ) { Gia_Man_t * pNew, * pGia, * pGia0; int i, k, iNode, nNodes; // make sure they have equal parameters assert( Vec_PtrSize(vGias) > 0 ); pGia0 = (Gia_Man_t *)Vec_PtrEntry( vGias, 0 ); Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) { assert( Gia_ManCiNum(pGia) == Gia_ManCiNum(pGia0) ); assert( Gia_ManCoNum(pGia) == Gia_ManCoNum(pGia0) ); assert( Gia_ManRegNum(pGia) == Gia_ManRegNum(pGia0) ); Gia_ManFillValue( pGia ); Gia_ManConst0(pGia)->Value = 0; } // start the new manager pNew = Gia_ManStart( Vec_PtrSize(vGias) * Gia_ManObjNum(pGia0) ); pNew->pName = Abc_UtilStrsav( pGia0->pName ); pNew->pSpec = Abc_UtilStrsav( pGia0->pSpec ); // create new CIs and assign them to the old manager CIs for ( k = 0; k < Gia_ManCiNum(pGia0); k++ ) { iNode = Gia_ManAppendCi(pNew); Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) Gia_ManCi( pGia, k )->Value = iNode; } // create internal nodes Gia_ManHashAlloc( pNew ); for ( k = 0; k < Gia_ManCoNum(pGia0); k++ ) { Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) Gia_ManChoiceMiter_rec( pNew, pGia, Gia_ManCo( pGia, k ) ); } Gia_ManHashStop( pNew ); // check the presence of dangling nodes nNodes = Gia_ManHasDangling( pNew ); //assert( nNodes == 0 ); // finalize Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia0) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG while putting first PIs, then nodes, then POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupWithConstraints( Gia_Man_t * p, Vec_Int_t * vPoTypes ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, nConstr = 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_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) ); Gia_ManForEachPo( p, pObj, i ) if ( Vec_IntEntry(vPoTypes, i) == 0 ) // regular PO pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManForEachPo( p, pObj, i ) if ( Vec_IntEntry(vPoTypes, i) == 1 ) // constraint (should be complemented!) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ^ 1 ), nConstr++; Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); // Gia_ManDupRemapEquiv( pNew, p ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew->nConstrs = nConstr; assert( Gia_ManIsNormalized(pNew) ); return pNew; } /**Function************************************************************* Synopsis [Copy an AIG structure related to the selected POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ObjCompareByCioId( Gia_Obj_t ** pp1, Gia_Obj_t ** pp2 ) { Gia_Obj_t * pObj1 = *pp1; Gia_Obj_t * pObj2 = *pp2; return Gia_ObjCioId(pObj1) - Gia_ObjCioId(pObj2); } void Gia_ManDupCones_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vRoots ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsAnd(pObj) ) { Gia_ManDupCones_rec( p, Gia_ObjFanin0(pObj), vLeaves, vNodes, vRoots ); Gia_ManDupCones_rec( p, Gia_ObjFanin1(pObj), vLeaves, vNodes, vRoots ); Vec_PtrPush( vNodes, pObj ); } else if ( Gia_ObjIsCo(pObj) ) Gia_ManDupCones_rec( p, Gia_ObjFanin0(pObj), vLeaves, vNodes, vRoots ); else if ( Gia_ObjIsRo(p, pObj) ) Vec_PtrPush( vRoots, Gia_ObjRoToRi(p, pObj) ); else if ( Gia_ObjIsPi(p, pObj) ) Vec_PtrPush( vLeaves, pObj ); else assert( 0 ); } Gia_Man_t * Gia_ManDupCones( Gia_Man_t * p, int * pPos, int nPos, int fTrimPis ) { Gia_Man_t * pNew; Vec_Ptr_t * vLeaves, * vNodes, * vRoots; Gia_Obj_t * pObj; int i; // collect initial POs vLeaves = Vec_PtrAlloc( 100 ); vNodes = Vec_PtrAlloc( 100 ); vRoots = Vec_PtrAlloc( 100 ); for ( i = 0; i < nPos; i++ ) Vec_PtrPush( vRoots, Gia_ManPo(p, pPos[i]) ); // mark internal nodes Gia_ManIncrementTravId( p ); 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 (*)(const void *, const void *))Gia_ObjCompareByCioId ); // start the new manager // Gia_ManFillValue( p ); pNew = Gia_ManStart( (fTrimPis ? Vec_PtrSize(vLeaves) : Gia_ManCiNum(p)) + Vec_PtrSize(vNodes) + Vec_PtrSize(vRoots) + 1 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // map the constant node Gia_ManConst0(p)->Value = 0; // 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 ); } else { Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); } // create LOs Vec_PtrForEachEntryStart( Gia_Obj_t *, vRoots, pObj, i, nPos ) Gia_ObjRiToRo(p, pObj)->Value = Gia_ManAppendCi( pNew ); // create internal nodes Vec_PtrForEachEntry( Gia_Obj_t *, vNodes, pObj, i ) 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) ); // finalize Gia_ManSetRegNum( pNew, Vec_PtrSize(vRoots)-nPos ); Vec_PtrFree( vLeaves ); Vec_PtrFree( vNodes ); Vec_PtrFree( vRoots ); return pNew; } Gia_Man_t * Gia_ManDupAndCones( Gia_Man_t * p, int * pAnds, int nAnds, int fTrimPis ) { Gia_Man_t * pNew; Vec_Ptr_t * vLeaves, * vNodes, * vRoots; Gia_Obj_t * pObj; int i; // collect initial POs vLeaves = Vec_PtrAlloc( 100 ); vNodes = Vec_PtrAlloc( 100 ); vRoots = Vec_PtrAlloc( 100 ); for ( i = 0; i < nAnds; i++ ) // Vec_PtrPush( vRoots, Gia_ManPo(p, pPos[i]) ); Vec_PtrPush( vRoots, Gia_ManObj(p, pAnds[i]) ); // mark internal nodes Gia_ManIncrementTravId( p ); 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 (*)(const void *, const void *))Gia_ObjCompareByCioId ); // start the new manager // Gia_ManFillValue( p ); pNew = Gia_ManStart( Vec_PtrSize(vLeaves) + Vec_PtrSize(vNodes) + Vec_PtrSize(vRoots) + 1); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // map the constant node Gia_ManConst0(p)->Value = 0; // create PIs if ( fTrimPis ) { Vec_PtrForEachEntry( Gia_Obj_t *, vLeaves, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); } else { Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); } // create LOs // Vec_PtrForEachEntryStart( Gia_Obj_t *, vRoots, pObj, i, nPos ) // Gia_ObjRiToRo(p, pObj)->Value = Gia_ManAppendCi( pNew ); // create internal nodes Vec_PtrForEachEntry( Gia_Obj_t *, vNodes, pObj, i ) if ( Gia_ObjIsMux(p, pObj) ) pObj->Value = Gia_ManAppendMux( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); else 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) ); Gia_ManAppendCo( pNew, pObj->Value ); // finalize // Gia_ManSetRegNum( pNew, Vec_PtrSize(vRoots)-nPos ); Gia_ManSetRegNum( pNew, 0 ); Vec_PtrFree( vLeaves ); Vec_PtrFree( vNodes ); Vec_PtrFree( vRoots ); return pNew; } void Gia_ManDupAndConesLimit_rec( Gia_Man_t * pNew, Gia_Man_t * p, int iObj, int Level ) { Gia_Obj_t * pObj = Gia_ManObj(p, iObj); if ( ~pObj->Value ) return; if ( !Gia_ObjIsAnd(pObj) || Gia_ObjLevel(p, pObj) < Level ) { pObj->Value = Gia_ManAppendCi( pNew ); //printf( "PI %d for %d.\n", Abc_Lit2Var(pObj->Value), iObj ); return; } Gia_ManDupAndConesLimit_rec( pNew, p, Gia_ObjFaninId0(pObj, iObj), Level ); Gia_ManDupAndConesLimit_rec( pNew, p, Gia_ObjFaninId1(pObj, iObj), Level ); pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); //printf( "Obj %d for %d.\n", Abc_Lit2Var(pObj->Value), iObj ); } Gia_Man_t * Gia_ManDupAndConesLimit( Gia_Man_t * p, int * pAnds, int nAnds, int Level ) { Gia_Man_t * pNew; int i; pNew = Gia_ManStart( 1000 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManLevelNum( p ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; for ( i = 0; i < nAnds; i++ ) Gia_ManDupAndConesLimit_rec( pNew, p, pAnds[i], Level ); for ( i = 0; i < nAnds; i++ ) Gia_ManAppendCo( pNew, Gia_ManObj(p, pAnds[i])->Value ); return pNew; } void Gia_ManDupAndConesLimit2_rec( Gia_Man_t * pNew, Gia_Man_t * p, int iObj, int Level ) { Gia_Obj_t * pObj = Gia_ManObj(p, iObj); if ( ~pObj->Value ) return; if ( !Gia_ObjIsAnd(pObj) || Level <= 0 ) { pObj->Value = Gia_ManAppendCi( pNew ); //printf( "PI %d for %d.\n", Abc_Lit2Var(pObj->Value), iObj ); return; } Gia_ManDupAndConesLimit2_rec( pNew, p, Gia_ObjFaninId0(pObj, iObj), Level-1 ); Gia_ManDupAndConesLimit2_rec( pNew, p, Gia_ObjFaninId1(pObj, iObj), Level-1 ); pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); //printf( "Obj %d for %d.\n", Abc_Lit2Var(pObj->Value), iObj ); } Gia_Man_t * Gia_ManDupAndConesLimit2( Gia_Man_t * p, int * pAnds, int nAnds, int Level ) { Gia_Man_t * pNew; int i; pNew = Gia_ManStart( 1000 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; for ( i = 0; i < nAnds; i++ ) Gia_ManDupAndConesLimit2_rec( pNew, p, pAnds[i], Level ); for ( i = 0; i < nAnds; i++ ) Gia_ManAppendCo( pNew, Gia_ManObj(p, pAnds[i])->Value ); return pNew; } /**Function************************************************************* Synopsis [Generates AIG representing 1-hot condition for N inputs.] Description [The condition is true of all POs are 0.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManOneHot( int nSkips, int nVars ) { Gia_Man_t * p; int i, b, Shift, iGiaLit, nLogVars = Abc_Base2Log( nVars ); int * pTemp = ABC_CALLOC( int, (1 << nLogVars) ); p = Gia_ManStart( nSkips + 4 * nVars + 1 ); p->pName = Abc_UtilStrsav( "onehot" ); for ( i = 0; i < nSkips; i++ ) Gia_ManAppendCi( p ); for ( i = 0; i < nVars; i++ ) pTemp[i] = Gia_ManAppendCi( p ); Gia_ManHashStart( p ); for ( b = 0; b < nLogVars; b++ ) for ( i = 0, Shift = (1<nConstrs += Gia_ManPoNum(pOneHot); Gia_ManStop( pOneHot ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG with nodes ordered by level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupLevelized( Gia_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, nLevels = Gia_ManLevelNum( p ); int * pCounts = ABC_CALLOC( int, nLevels + 1 ); int * pNodes = ABC_ALLOC( int, Gia_ManAndNum(p) ); Gia_ManForEachAnd( p, pObj, i ) pCounts[Gia_ObjLevel(p, pObj)]++; for ( i = 1; i <= nLevels; i++ ) pCounts[i] += pCounts[i-1]; Gia_ManForEachAnd( p, pObj, i ) pNodes[pCounts[Gia_ObjLevel(p, pObj)-1]++] = i; // duplicate 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 ); for ( i = 0; i < Gia_ManAndNum(p) && (pObj = Gia_ManObj(p, pNodes[i])); 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) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); ABC_FREE( pCounts ); ABC_FREE( pNodes ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupFromVecs( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; // start the new manager pNew = Gia_ManStart( 5000 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create constant Gia_ManConst0(p)->Value = 0; // create PIs Gia_ManForEachObjVec( vCis, p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); // create internal nodes Gia_ManForEachObjVec( vAnds, p, pObj, i ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // create ROs Gia_ManForEachObjVec( vCos, p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, nRegs ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupSliced( Gia_Man_t * p, int nSuppMax ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; // start the new manager pNew = Gia_ManStart( 5000 ); pNew->pName = Abc_UtilStrsav( p->pName ); // create constant and PIs Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); // create internal nodes Gia_ManCleanMark01(p); Gia_ManForEachAnd( p, pObj, i ) if ( Gia_ManSuppSize(p, &i, 1) <= nSuppMax ) { pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); pObj->fMark0 = 1; } else { Gia_ObjFanin0(pObj)->fMark1 = 1; Gia_ObjFanin1(pObj)->fMark1 = 1; } Gia_ManForEachCo( p, pObj, i ) Gia_ObjFanin0(pObj)->fMark1 = 1; // add POs for the nodes pointed to Gia_ManForEachAnd( p, pObj, i ) if ( pObj->fMark0 && pObj->fMark1 ) Gia_ManAppendCo( pNew, pObj->Value ); // cleanup and leave Gia_ManCleanMark01(p); return pNew; } /**Function************************************************************* Synopsis [Extract constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupWithConstrCollectAnd_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, int fFirst ) { if ( (Gia_IsComplement(pObj) || !Gia_ObjIsAnd(pObj)) && !fFirst ) { Vec_IntPushUnique( vSuper, Gia_ObjToLit(p, pObj) ); return; } Gia_ManDupWithConstrCollectAnd_rec( p, Gia_ObjChild0(pObj), vSuper, 0 ); Gia_ManDupWithConstrCollectAnd_rec( p, Gia_ObjChild1(pObj), vSuper, 0 ); } Gia_Man_t * Gia_ManDupWithConstr( Gia_Man_t * p ) { Vec_Int_t * vSuper; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iDriver, iLit, iLitBest = -1, LevelBest = -1; assert( Gia_ManPoNum(p) == 1 ); assert( Gia_ManRegNum(p) == 0 ); pObj = Gia_ManPo( p, 0 ); if ( Gia_ObjFaninC0(pObj) ) { printf( "The miter's output is not AND-decomposable.\n" ); return NULL; } if ( Gia_ObjFaninId0p(p, pObj) == 0 ) { printf( "The miter's output is a constant.\n" ); return NULL; } vSuper = Vec_IntAlloc( 100 ); Gia_ManDupWithConstrCollectAnd_rec( p, Gia_ObjChild0(pObj), vSuper, 1 ); assert( Vec_IntSize(vSuper) > 1 ); // find the highest level Gia_ManLevelNum( p ); Vec_IntForEachEntry( vSuper, iLit, i ) if ( LevelBest < Gia_ObjLevelId(p, Abc_Lit2Var(iLit)) ) LevelBest = Gia_ObjLevelId(p, Abc_Lit2Var(iLit)), iLitBest = iLit; assert( iLitBest != -1 ); // create new manager 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_ObjIsAnd(pObj) ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsCi(pObj) ) pObj->Value = Gia_ManAppendCi( pNew ); } // create AND of nodes iDriver = -1; Vec_IntForEachEntry( vSuper, iLit, i ) { if ( iLit == iLitBest ) continue; if ( iDriver == -1 ) iDriver = Gia_ObjLitCopy(p, iLit); else iDriver = Gia_ManHashAnd( pNew, iDriver, Gia_ObjLitCopy(p, iLit) ); } // create the main PO Gia_ManAppendCo( pNew, Gia_ObjLitCopy(p, iLitBest) ); // create the constraint PO Gia_ManAppendCo( pNew, Abc_LitNot(iDriver) ); pNew->nConstrs = 1; // rehash pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); Vec_IntFree( vSuper ); return pNew; } /**Function************************************************************* Synopsis [Compares two objects by their distance.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSortByValue( Gia_Obj_t ** pp1, Gia_Obj_t ** pp2 ) { int Diff = Gia_Regular(*pp1)->Value - Gia_Regular(*pp2)->Value; if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; return 0; } /**Function************************************************************* Synopsis [Decomposes the miter outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupOuts( 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_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) ); Gia_ManForEachPo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManForEachAnd( p, pObj, i ) Gia_ManAppendCo( pNew, pObj->Value ); Gia_ManForEachRi( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); assert( Gia_ManIsNormalized(pNew) ); return pNew; } /**Function************************************************************* Synopsis [Computes supports for each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wec_t * Gia_ManCreateNodeSupps( Gia_Man_t * p, Vec_Int_t * vNodes, int fVerbose ) { abctime clk = Abc_Clock(); Gia_Obj_t * pObj; int i, Id; Vec_Wec_t * vSuppsNo = Vec_WecStart( Vec_IntSize(vNodes) ); Vec_Wec_t * vSupps = Vec_WecStart( Gia_ManObjNum(p) ); Gia_ManForEachCiId( p, Id, i ) Vec_IntPush( Vec_WecEntry(vSupps, Id), i ); Gia_ManForEachAnd( p, pObj, Id ) Vec_IntTwoMerge2( Vec_WecEntry(vSupps, Gia_ObjFaninId0(pObj, Id)), Vec_WecEntry(vSupps, Gia_ObjFaninId1(pObj, Id)), Vec_WecEntry(vSupps, Id) ); Gia_ManForEachObjVec( vNodes, p, pObj, i ) Vec_IntAppend( Vec_WecEntry(vSuppsNo, i), Vec_WecEntry(vSupps, Gia_ObjId(p, pObj)) ); Vec_WecFree( vSupps ); if ( fVerbose ) Abc_PrintTime( 1, "Support computation", Abc_Clock() - clk ); return vSuppsNo; } Vec_Wec_t * Gia_ManCreateCoSupps( Gia_Man_t * p, int fVerbose ) { abctime clk = Abc_Clock(); Gia_Obj_t * pObj; int i, Id; Vec_Wec_t * vSuppsCo = Vec_WecStart( Gia_ManCoNum(p) ); Vec_Wec_t * vSupps = Vec_WecStart( Gia_ManObjNum(p) ); Gia_ManForEachCiId( p, Id, i ) Vec_IntPush( Vec_WecEntry(vSupps, Id), i ); Gia_ManForEachAnd( p, pObj, Id ) Vec_IntTwoMerge2( Vec_WecEntry(vSupps, Gia_ObjFaninId0(pObj, Id)), Vec_WecEntry(vSupps, Gia_ObjFaninId1(pObj, Id)), Vec_WecEntry(vSupps, Id) ); Gia_ManForEachCo( p, pObj, i ) Vec_IntAppend( Vec_WecEntry(vSuppsCo, i), Vec_WecEntry(vSupps, Gia_ObjFaninId0p(p, pObj)) ); Vec_WecFree( vSupps ); if ( fVerbose ) Abc_PrintTime( 1, "Support computation", Abc_Clock() - clk ); return vSuppsCo; } int Gia_ManCoSuppSizeMax( Gia_Man_t * p, Vec_Wec_t * vSupps ) { Gia_Obj_t * pObj; Vec_Int_t * vSuppOne; int i, nSuppMax = 1; Gia_ManForEachCo( p, pObj, i ) { vSuppOne = Vec_WecEntry( vSupps, i ); nSuppMax = Abc_MaxInt( nSuppMax, Vec_IntSize(vSuppOne) ); } return nSuppMax; } int Gia_ManCoLargestSupp( Gia_Man_t * p, Vec_Wec_t * vSupps ) { Gia_Obj_t * pObj; Vec_Int_t * vSuppOne; int i, iCoMax = -1, nSuppMax = -1; Gia_ManForEachCo( p, pObj, i ) { vSuppOne = Vec_WecEntry( vSupps, i ); if ( nSuppMax < Vec_IntSize(vSuppOne) ) { nSuppMax = Vec_IntSize(vSuppOne); iCoMax = i; } } return iCoMax; } Vec_Int_t * Gia_ManSortCoBySuppSize( Gia_Man_t * p, Vec_Wec_t * vSupps ) { Vec_Int_t * vOrder = Vec_IntAlloc( Gia_ManCoNum(p) ); Vec_Wrd_t * vSortData = Vec_WrdAlloc( Gia_ManCoNum(p) ); Vec_Int_t * vSuppOne; word Entry; int i; Vec_WecForEachLevel( vSupps, vSuppOne, i ) Vec_WrdPush( vSortData, ((word)i << 32) | Vec_IntSize(vSuppOne) ); Abc_QuickSort3( Vec_WrdArray(vSortData), Vec_WrdSize(vSortData), 1 ); Vec_WrdForEachEntry( vSortData, Entry, i ) Vec_IntPush( vOrder, (int)(Entry >> 32) ); Vec_WrdFree( vSortData ); return vOrder; } /**Function************************************************************* Synopsis [Remaps each CO cone to depend on the first CI variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManDupHashDfs_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( ~pObj->Value ) return pObj->Value; assert( Gia_ObjIsAnd(pObj) ); Gia_ManDupHashDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManDupHashDfs_rec( pNew, p, Gia_ObjFanin1(pObj) ); return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } void Gia_ManDupCleanDfs_rec( Gia_Obj_t * pObj ) { if ( !~pObj->Value ) return; pObj->Value = ~0; if ( Gia_ObjIsCi(pObj) ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManDupCleanDfs_rec( Gia_ObjFanin0(pObj) ); Gia_ManDupCleanDfs_rec( Gia_ObjFanin1(pObj) ); } Gia_Man_t * Gia_ManDupStrashReduce( Gia_Man_t * p, Vec_Wec_t * vSupps, Vec_Int_t ** pvCoMap ) { Gia_Obj_t * pObj; Gia_Man_t * pNew, * pTemp; Vec_Int_t * vSuppOne, * vCoMapLit; int i, k, iCi, iLit, nSuppMax; assert( Gia_ManRegNum(p) == 0 ); Gia_ManFillValue( p ); vCoMapLit = Vec_IntAlloc( Gia_ManCoNum(p) ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; nSuppMax = Gia_ManCoSuppSizeMax( p, vSupps ); for ( i = 0; i < nSuppMax; i++ ) Gia_ManAppendCi(pNew); Gia_ManHashAlloc( pNew ); Gia_ManForEachCo( p, pObj, i ) { vSuppOne = Vec_WecEntry( vSupps, i ); if ( Vec_IntSize(vSuppOne) == 0 ) Vec_IntPush( vCoMapLit, Abc_Var2Lit(0, Gia_ObjFaninC0(pObj)) ); else if ( Vec_IntSize(vSuppOne) == 1 ) Vec_IntPush( vCoMapLit, Abc_Var2Lit(1, Gia_ObjFaninC0(pObj)) ); else { Vec_IntForEachEntry( vSuppOne, iCi, k ) Gia_ManCi(p, iCi)->Value = Gia_Obj2Lit(pNew, Gia_ManCi(pNew, k) ); Gia_ManDupHashDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); assert( Gia_ObjFanin0Copy(pObj) < 2 * Gia_ManObjNum(pNew) ); Vec_IntPush( vCoMapLit, Gia_ObjFanin0Copy(pObj) ); Gia_ManDupCleanDfs_rec( Gia_ObjFanin0(pObj) ); } } Gia_ManHashStop( pNew ); assert( Vec_IntSize(vCoMapLit) == Gia_ManCoNum(p) ); if ( pvCoMap == NULL ) // do not remap { Vec_IntForEachEntry( vCoMapLit, iLit, i ) Gia_ManAppendCo( pNew, iLit ); } else // remap { Vec_Int_t * vCoMapRes = Vec_IntAlloc( Gia_ManCoNum(p) ); // map old CO into new CO Vec_Int_t * vMap = Vec_IntStartFull( 2*Gia_ManObjNum(pNew) ); // map new lit into new CO Vec_IntForEachEntry( vCoMapLit, iLit, i ) { if ( Vec_IntEntry(vMap, iLit) == -1 ) { Vec_IntWriteEntry( vMap, iLit, Gia_ManCoNum(pNew) ); Gia_ManAppendCo( pNew, iLit ); } Vec_IntPush( vCoMapRes, Vec_IntEntry(vMap, iLit) ); } Vec_IntFree( vMap ); *pvCoMap = vCoMapRes; } Vec_IntFree( vCoMapLit ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } Gia_Man_t * Gia_ManIsoStrashReduce2( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, int fVerbose ) { Vec_Int_t * vCoMap; Vec_Wec_t * vSupps = Gia_ManCreateCoSupps( p, fVerbose ); Gia_Man_t * pNew = Gia_ManDupStrashReduce( p, vSupps, &vCoMap ); Vec_IntFree( vCoMap ); Vec_WecFree( vSupps ); *pvPosEquivs = NULL; return pNew; } int Gia_ManIsoStrashReduceOne( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp ) { int k, iCi, iLit; assert( Gia_ObjIsCo(pObj) ); if ( Vec_IntSize(vSupp) == 0 ) return Abc_Var2Lit(0, Gia_ObjFaninC0(pObj)); if ( Vec_IntSize(vSupp) == 1 ) return Abc_Var2Lit(1, Gia_ObjFaninC0(pObj)); Vec_IntForEachEntry( vSupp, iCi, k ) Gia_ManCi(p, iCi)->Value = Gia_Obj2Lit(pNew, Gia_ManCi(pNew, k) ); Gia_ManDupHashDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); iLit = Gia_ObjFanin0Copy(pObj); Gia_ManDupCleanDfs_rec( Gia_ObjFanin0(pObj) ); return iLit; } Vec_Wec_t * Gia_ManIsoStrashReduceInt( Gia_Man_t * p, Vec_Wec_t * vSupps, int fVerbose ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; Vec_Wec_t * vPosEquivs = Vec_WecAlloc( 100 ); Vec_Int_t * vSuppOne, * vMap = Vec_IntAlloc( 10000 ); int i, iLit, nSuppMax = Gia_ManCoSuppSizeMax( p, vSupps ); // count how many times each support size appears Vec_Int_t * vSizeCount = Vec_IntStart( nSuppMax + 1 ); Vec_WecForEachLevel( vSupps, vSuppOne, i ) Vec_IntAddToEntry( vSizeCount, Vec_IntSize(vSuppOne), 1 ); // create array of unique outputs Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); Gia_ManConst0(p)->Value = 0; for ( i = 0; i < nSuppMax; i++ ) Gia_ManAppendCi(pNew); Gia_ManHashAlloc( pNew ); Gia_ManForEachCo( p, pObj, i ) { vSuppOne = Vec_WecEntry( vSupps, i ); if ( Vec_IntEntry(vSizeCount, Vec_IntSize(vSuppOne)) == 1 ) { Vec_IntPush( Vec_WecPushLevel(vPosEquivs), i ); continue; } iLit = Gia_ManIsoStrashReduceOne( pNew, p, pObj, vSuppOne ); Vec_IntFillExtra( vMap, iLit + 1, -1 ); if ( Vec_IntEntry(vMap, iLit) == -1 ) { Vec_IntWriteEntry( vMap, iLit, Vec_WecSize(vPosEquivs) ); Vec_IntPush( Vec_WecPushLevel(vPosEquivs), i ); continue; } Vec_IntPush( Vec_WecEntry(vPosEquivs, Vec_IntEntry(vMap, iLit)), i ); } Gia_ManHashStop( pNew ); Gia_ManStop( pNew ); Vec_IntFree( vSizeCount ); Vec_IntFree( vMap ); return vPosEquivs; } Gia_Man_t * Gia_ManIsoStrashReduce( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, int fVerbose ) { Vec_Wec_t * vSupps = Gia_ManCreateCoSupps( p, fVerbose ); Vec_Wec_t * vPosEquivs = Gia_ManIsoStrashReduceInt( p, vSupps, fVerbose ); // find the first outputs and derive GIA Vec_Int_t * vFirsts = Vec_WecCollectFirsts( vPosEquivs ); Gia_Man_t * pNew = Gia_ManDupCones( p, Vec_IntArray(vFirsts), Vec_IntSize(vFirsts), 0 ); Vec_IntFree( vFirsts ); Vec_WecFree( vSupps ); // report and return if ( fVerbose ) { printf( "Nontrivial classes:\n" ); Vec_WecPrint( vPosEquivs, 1 ); } if ( pvPosEquivs ) *pvPosEquivs = Vec_WecConvertToVecPtr( vPosEquivs ); Vec_WecFree( vPosEquivs ); return pNew; } /**Function************************************************************* Synopsis [Decomposes the miter outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupDemiter( Gia_Man_t * p, int fVerbose ) { Vec_Int_t * vSuper; Vec_Ptr_t * vSuperPtr; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObjPo; int i, iLit; assert( Gia_ManPoNum(p) == 1 ); // decompose pObjPo = Gia_ManPo( p, 0 ); vSuper = Vec_IntAlloc( 100 ); Gia_ManDupWithConstrCollectAnd_rec( p, Gia_ObjFanin0(pObjPo), vSuper, 1 ); assert( Vec_IntSize(vSuper) > 1 ); // report the result printf( "The miter is %s-decomposable into %d parts.\n", Gia_ObjFaninC0(pObjPo) ? "OR":"AND", Vec_IntSize(vSuper) ); // create levels Gia_ManLevelNum( p ); Vec_IntForEachEntry( vSuper, iLit, i ) Gia_ManObj(p, Abc_Lit2Var(iLit))->Value = Gia_ObjLevelId(p, Abc_Lit2Var(iLit)); // create pointer array vSuperPtr = Vec_PtrAlloc( Vec_IntSize(vSuper) ); Vec_IntForEachEntry( vSuper, iLit, i ) Vec_PtrPush( vSuperPtr, Gia_Lit2Obj(p, iLit) ); 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 ); 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) ); // create the outputs Vec_PtrForEachEntry( Gia_Obj_t *, vSuperPtr, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjLitCopy(p, Gia_Obj2Lit(p, pObj)) ^ Gia_ObjFaninC0(pObjPo) ); Gia_ManForEachRi( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // rehash pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); Vec_IntFree( vSuper ); Vec_PtrFree( vSuperPtr ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupDemiterOrderXors2( Gia_Man_t * p, Vec_Int_t * vXors ) { int i, iObj, * pPerm; Vec_Int_t * vSizes = Vec_IntAlloc( 100 ); Vec_IntForEachEntry( vXors, iObj, i ) Vec_IntPush( vSizes, Gia_ManSuppSize(p, &iObj, 1) ); pPerm = Abc_MergeSortCost( Vec_IntArray(vSizes), Vec_IntSize(vSizes) ); Vec_IntClear( vSizes ); for ( i = 0; i < Vec_IntSize(vXors); i++ ) Vec_IntPush( vSizes, Vec_IntEntry(vXors, pPerm[i]) ); ABC_FREE( pPerm ); Vec_IntClear( vXors ); Vec_IntAppend( vXors, vSizes ); Vec_IntFree( vSizes ); } int Gia_ManDupDemiterFindMin( Vec_Wec_t * vSupps, Vec_Int_t * vTakenIns, Vec_Int_t * vTakenOuts ) { Vec_Int_t * vLevel; int i, k, iObj, iObjBest = -1; int Count, CountBest = ABC_INFINITY; Vec_WecForEachLevel( vSupps, vLevel, i ) { if ( Vec_IntEntry(vTakenOuts, i) ) continue; Count = 0; Vec_IntForEachEntry( vLevel, iObj, k ) Count += !Vec_IntEntry(vTakenIns, iObj); if ( CountBest > Count ) { CountBest = Count; iObjBest = i; } } return iObjBest; } void Gia_ManDupDemiterOrderXors( Gia_Man_t * p, Vec_Int_t * vXors ) { extern Vec_Wec_t * Gia_ManCreateNodeSupps( Gia_Man_t * p, Vec_Int_t * vNodes, int fVerbose ); Vec_Wec_t * vSupps = Gia_ManCreateNodeSupps( p, vXors, 0 ); Vec_Int_t * vTakenIns = Vec_IntStart( Gia_ManCiNum(p) ); Vec_Int_t * vTakenOuts = Vec_IntStart( Vec_IntSize(vXors) ); Vec_Int_t * vOrder = Vec_IntAlloc( Vec_IntSize(vXors) ); int i, k, iObj; // add outputs in the order of increasing supports for ( i = 0; i < Vec_IntSize(vXors); i++ ) { int Index = Gia_ManDupDemiterFindMin( vSupps, vTakenIns, vTakenOuts ); assert( Index >= 0 && Index < Vec_IntSize(vXors) ); Vec_IntPush( vOrder, Vec_IntEntry(vXors, Index) ); assert( !Vec_IntEntry( vTakenOuts, Index ) ); Vec_IntWriteEntry( vTakenOuts, Index, 1 ); Vec_IntForEachEntry( Vec_WecEntry(vSupps, Index), iObj, k ) Vec_IntWriteEntry( vTakenIns, iObj, 1 ); } Vec_WecFree( vSupps ); Vec_IntFree( vTakenIns ); Vec_IntFree( vTakenOuts ); // reload Vec_IntClear( vXors ); Vec_IntAppend( vXors, vOrder ); Vec_IntFree( vOrder ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSetMark0Dfs_rec( Gia_Man_t * p, int iObj ) { Gia_Obj_t * pObj; pObj = Gia_ManObj( p, iObj ); if ( pObj->fMark0 ) return; pObj->fMark0 = 1; if ( !Gia_ObjIsAnd(pObj) ) return; Gia_ManSetMark0Dfs_rec( p, Gia_ObjFaninId0(pObj, iObj) ); Gia_ManSetMark0Dfs_rec( p, Gia_ObjFaninId1(pObj, iObj) ); } void Gia_ManSetMark1Dfs_rec( Gia_Man_t * p, int iObj ) { Gia_Obj_t * pObj; pObj = Gia_ManObj( p, iObj ); if ( pObj->fMark1 ) return; pObj->fMark1 = 1; if ( !Gia_ObjIsAnd(pObj) ) return; Gia_ManSetMark1Dfs_rec( p, Gia_ObjFaninId0(pObj, iObj) ); Gia_ManSetMark1Dfs_rec( p, Gia_ObjFaninId1(pObj, iObj) ); } int Gia_ManCountMark0Dfs_rec( Gia_Man_t * p, int iObj ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) return 0; Gia_ObjSetTravIdCurrentId(p, iObj); pObj = Gia_ManObj( p, iObj ); if ( !Gia_ObjIsAnd(pObj) ) return pObj->fMark0; return Gia_ManCountMark0Dfs_rec( p, Gia_ObjFaninId0(pObj, iObj) ) + Gia_ManCountMark0Dfs_rec( p, Gia_ObjFaninId1(pObj, iObj) ) + pObj->fMark0; } int Gia_ManCountMark0Dfs( Gia_Man_t * p, int iObj ) { Gia_ManIncrementTravId( p ); return Gia_ManCountMark0Dfs_rec( p, iObj ); } int Gia_ManCountMark1Dfs_rec( Gia_Man_t * p, int iObj ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) return 0; Gia_ObjSetTravIdCurrentId(p, iObj); pObj = Gia_ManObj( p, iObj ); if ( !Gia_ObjIsAnd(pObj) ) return pObj->fMark1; return Gia_ManCountMark1Dfs_rec( p, Gia_ObjFaninId0(pObj, iObj) ) + Gia_ManCountMark1Dfs_rec( p, Gia_ObjFaninId1(pObj, iObj) ) + pObj->fMark1; } int Gia_ManCountMark1Dfs( Gia_Man_t * p, int iObj ) { Gia_ManIncrementTravId( p ); return Gia_ManCountMark1Dfs_rec( p, iObj ); } int Gia_ManDecideWhereToAdd( Gia_Man_t * p, Vec_Int_t * vPart[2], Gia_Obj_t * pFan[2] ) { int Count0 = 1, Count1 = 0; assert( Vec_IntSize(vPart[0]) == Vec_IntSize(vPart[1]) ); if ( Vec_IntSize(vPart[0]) > 0 ) { Count0 = Gia_ManCountMark0Dfs(p, Gia_ObjId(p, pFan[0])) + Gia_ManCountMark1Dfs(p, Gia_ObjId(p, pFan[1])); Count1 = Gia_ManCountMark0Dfs(p, Gia_ObjId(p, pFan[1])) + Gia_ManCountMark1Dfs(p, Gia_ObjId(p, pFan[0])); } return Count0 < Count1; } void Gia_ManCollectTopXors_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXors ) { Gia_Obj_t * pFan0, * pFan1; int iObj = Gia_ObjId( p, pObj ); if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) || !Gia_ObjIsAnd(pObj) ) { Vec_IntPushUnique( vXors, Gia_ObjId(p, pObj) ); return; } if ( Gia_ObjFaninC0(pObj) ) Vec_IntPushUnique( vXors, Gia_ObjFaninId0(pObj, iObj) ); else Gia_ManCollectTopXors_rec( p, Gia_ObjFanin0(pObj), vXors ); if ( Gia_ObjFaninC1(pObj) ) Vec_IntPushUnique( vXors, Gia_ObjFaninId1(pObj, iObj) ); else Gia_ManCollectTopXors_rec( p, Gia_ObjFanin1(pObj), vXors ); } Vec_Int_t * Gia_ManCollectTopXors( Gia_Man_t * p ) { int i, iObj, iObj2, fFlip, Count1 = 0; Vec_Int_t * vXors, * vPart[2], * vOrder; Gia_Obj_t * pFan[2], * pObj = Gia_ManCo(p, 0); vXors = Vec_IntAlloc( 100 ); if ( Gia_ManCoNum(p) == 1 ) { if ( Gia_ObjFaninC0(pObj) ) Gia_ManCollectTopXors_rec( p, Gia_ObjFanin0(pObj), vXors ); else Vec_IntPush( vXors, Gia_ObjId(p, Gia_ObjFanin0(pObj)) ); } else { Gia_ManForEachCo( p, pObj, i ) if ( Gia_ObjFaninId0p(p, pObj) > 0 ) Vec_IntPush( vXors, Gia_ObjFaninId0p(p, pObj) ); } // order by support size Gia_ManDupDemiterOrderXors( p, vXors ); //Vec_IntPrint( vXors ); Vec_IntReverseOrder( vXors ); // from MSB to LSB // divide into groups Gia_ManCleanMark01(p); vPart[0] = Vec_IntAlloc( 100 ); vPart[1] = Vec_IntAlloc( 100 ); Gia_ManForEachObjVec( vXors, p, pObj, i ) { int fCompl = 0; if ( !Gia_ObjRecognizeExor(pObj, &pFan[0], &pFan[1]) ) pFan[0] = pObj, pFan[1] = Gia_ManConst0(p), Count1++; else { fCompl ^= Gia_IsComplement(pFan[0]); fCompl ^= Gia_IsComplement(pFan[1]); pFan[0] = Gia_Regular(pFan[0]); pFan[1] = Gia_Regular(pFan[1]); } fFlip = Gia_ManDecideWhereToAdd( p, vPart, pFan ); Vec_IntPush( vPart[0], Gia_ObjId(p, pFan[fFlip]) ); Vec_IntPush( vPart[1], Gia_ObjId(p, pFan[!fFlip]) ); Gia_ManSetMark0Dfs_rec( p, Gia_ObjId(p, pFan[fFlip]) ); Gia_ManSetMark1Dfs_rec( p, Gia_ObjId(p, pFan[!fFlip]) ); } //printf( "Detected %d single-output XOR miters and %d other miters.\n", Vec_IntSize(vXors) - Count1, Count1 ); Vec_IntFree( vXors ); Gia_ManCleanMark01(p); // create new order vOrder = Vec_IntAlloc( 100 ); Vec_IntForEachEntryTwo( vPart[0], vPart[1], iObj, iObj2, i ) Vec_IntPushTwo( vOrder, iObj, iObj2 ); Vec_IntFree( vPart[0] ); Vec_IntFree( vPart[1] ); Vec_IntReverseOrder( vOrder ); // from LSB to MSB //Vec_IntPrint( vOrder ); return vOrder; } Gia_Man_t * Gia_ManDemiterToDual( Gia_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; Vec_Int_t * vNodes; Vec_Int_t * vOrder = Gia_ManCollectTopXors( p ); if ( vOrder == NULL ) { printf( "Cannot demiter because the top-most gate is an AND-gate.\n" ); return NULL; } assert( Vec_IntSize(vOrder) % 2 == 0 ); vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); Gia_ManIncrementTravId( p ); Gia_ManCollectAnds( p, Vec_IntArray(vOrder), Vec_IntSize(vOrder), vNodes, NULL ); pNew = Gia_ManStart( 1 + Gia_ManCiNum(p) + Vec_IntSize(vNodes) + Vec_IntSize(vOrder) ); 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_ManForEachObjVec( vNodes, p, pObj, i ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); pObj = Gia_ManCo(p, 0); if ( Gia_ObjFanin0(pObj) == Gia_ManConst0(p) ) { Gia_ManAppendCo( pNew, 0 ); Gia_ManAppendCo( pNew, Gia_ObjFaninC0(pObj) ); } else { Gia_ManSetPhase( p ); Gia_ManForEachObjVec( vOrder, p, pObj, i ) Gia_ManAppendCo( pNew, Abc_LitNotCond(pObj->Value, pObj->fPhase) ); } Vec_IntFree( vNodes ); Vec_IntFree( vOrder ); return pNew; } /**Function************************************************************* Synopsis [Collect nodes reachable from odd/even outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCollectDfs_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vNodes ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) return; Gia_ObjSetTravIdCurrentId(p, iObj); pObj = Gia_ManObj( p, iObj ); if ( !Gia_ObjIsAnd(pObj) ) return; Gia_ManCollectDfs_rec( p, Gia_ObjFaninId0(pObj, iObj), vNodes ); Gia_ManCollectDfs_rec( p, Gia_ObjFaninId1(pObj, iObj), vNodes ); Vec_IntPush( vNodes, iObj ); } Vec_Int_t * Gia_ManCollectReach( Gia_Man_t * p, int fOdd ) { int i, iDriver; Vec_Int_t * vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); Gia_ManForEachCoDriverId( p, iDriver, i ) if ( (i & 1) == fOdd ) Gia_ManCollectDfs_rec( p, iDriver, vNodes ); return vNodes; } int Gia_ManDemiterDual( Gia_Man_t * p, Gia_Man_t ** pp0, Gia_Man_t ** pp1 ) { Gia_Obj_t * pObj; int i, fOdd; assert( Gia_ManRegNum(p) == 0 ); assert( Gia_ManCoNum(p) % 2 == 0 ); *pp0 = *pp1 = NULL; for ( fOdd = 0; fOdd < 2; fOdd++ ) { Vec_Int_t * vNodes = Gia_ManCollectReach( p, fOdd ); Gia_Man_t * pNew = Gia_ManStart( 1 + Gia_ManCiNum(p) + Vec_IntSize(vNodes) + Gia_ManCoNum(p)/2 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachObjVec( vNodes, p, pObj, i ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( p, pObj, i ) if ( (i & 1) == fOdd ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Vec_IntFree( vNodes ); if ( fOdd ) *pp1 = pNew; else *pp0 = pNew; } return 1; } /**Function************************************************************* Synopsis [Collect nodes reachable from first/second half of outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManCollectReach2( Gia_Man_t * p, int fSecond ) { int i, iDriver; Vec_Int_t * vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); Gia_ManForEachCoDriverId( p, iDriver, i ) if ( (i < Gia_ManCoNum(p)/2) ^ fSecond ) Gia_ManCollectDfs_rec( p, iDriver, vNodes ); return vNodes; } int Gia_ManDemiterTwoWords( Gia_Man_t * p, Gia_Man_t ** pp0, Gia_Man_t ** pp1 ) { Gia_Obj_t * pObj; int i, fSecond; assert( Gia_ManRegNum(p) == 0 ); assert( Gia_ManCoNum(p) % 2 == 0 ); *pp0 = *pp1 = NULL; for ( fSecond = 0; fSecond < 2; fSecond++ ) { Vec_Int_t * vNodes = Gia_ManCollectReach2( p, fSecond ); Gia_Man_t * pNew = Gia_ManStart( 1 + Gia_ManCiNum(p) + Vec_IntSize(vNodes) + Gia_ManCoNum(p)/2 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachObjVec( vNodes, p, pObj, i ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( p, pObj, i ) if ( (i < Gia_ManCoNum(p)/2) ^ fSecond ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Vec_IntFree( vNodes ); if ( fSecond ) *pp1 = pNew; else *pp0 = pNew; } 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; for( int i = 0; i < Gia_ManCiNum(p1); i++ ) { int iLit = Gia_ManCi(p1, i)->Value = Gia_ManCi(p2, i) -> Value = Gia_ManAppendCi(pNew); pObj = Gia_ManCi(p1, i); if ( pBnd ) Bnd_ManMap( iLit, Gia_ObjId( p1, pObj ), 1 ); pObj = Gia_ManCi(p2, i); if ( pBnd ) Bnd_ManMap( iLit, Gia_ObjId( p2, pObj) , 0 ); } // record the corresponding impl node of each lit Gia_ManForEachAnd( p2, pObj, i ) { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( pBnd ) Bnd_ManMap( pObj -> Value, Gia_ObjId(p2, pObj), 0 ); } // record hashed equivalent nodes Gia_ManForEachAnd( p1, pObj, i ) { pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( pBnd ) Bnd_ManMap( pObj -> Value, Gia_ObjId(p1, pObj), 1 ); } Gia_ManForEachCo( p2, pObj, i ) { iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Gia_ManForEachCo( p1, pObj, i ) { iLit = 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; } /**Function************************************************************* Synopsis [Duplicates AIG while putting objects in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManImplFromBMiter( Gia_Man_t * p, int nPo, int nBInput ) { Gia_Man_t * pNew, *pTemp; Gia_Obj_t * pObj, *pObj2; int i; int nBoundI = 0, nBoundO = 0; int nExtra; 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; // add po of impl Gia_ManForEachCo( p, pObj, i ) { if ( i < nPo ) { Gia_ManDupOrderDfs_rec( pNew, p, pObj ); } } nExtra = Gia_ManAndNum( pNew ); // add boundary as buf Gia_ManForEachCo( p, pObj, i ) { if ( i >= 2 * nPo ) { pObj2 = Gia_ObjFanin0(pObj); if (~pObj2->Value) // visited boundary { if ( i >= 2 * nPo + nBInput ) { nBoundO ++; } else nBoundI ++; } Gia_ManDupOrderDfs_rec( pNew, p, pObj2 ); Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); } } nExtra = Gia_ManAndNum( pNew ) - nExtra - Gia_ManBufNum( pNew ); Gia_ManForEachCi( p, pObj, i ) if ( !~pObj->Value ) pObj->Value = Gia_ManAppendCi(pNew); assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) ); Gia_ManDupRemapCis( pNew, p ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); printf( "synthesized implementation:\n" ); printf( "\t%d / %d input boundary recovered.\n", nBoundI, nBInput ); printf( "\t%d / %d output boundary recovered.\n", nBoundO, Gia_ManCoNum(p)-2*nPo-nBInput ); printf( "\t%d / %d unused nodes in the box.\n", nExtra, Gia_ManAndNum(pNew) - Gia_ManBufNum( pNew ) ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupOdc( Gia_Man_t * p, int iObj, int fVerbose ) { Vec_Int_t * vRoots = Vec_IntAlloc( 1 ); Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); Gia_Obj_t * pObj; int i, iRes = 0; Vec_IntPush( vRoots, iObj ); Gia_ManStaticFanoutStart( p ); Gia_ManCollectTfo( p, vRoots, vNodes ); Gia_ManStaticFanoutStop( p ); Vec_IntSort(vNodes, 0); Gia_ManForEachObjVecStart( vNodes, p, pObj, i, 1 ) { if ( !Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) ) Vec_IntPushUnique( vSupp, Gia_ObjFaninId0p(p, pObj) ); if ( !Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) Vec_IntPushUnique( vSupp, Gia_ObjFaninId1p(p, pObj) ); } Vec_IntSort(vSupp, 0); if ( fVerbose ) Vec_IntPrint( vSupp ); if ( fVerbose ) Vec_IntPrint( vNodes ); Gia_Man_t * pTemp, * pNew = Gia_ManStart( 100 ); pNew->pName = Abc_UtilStrsav( "care" ); Gia_ManFillValue(p); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObjVec( vSupp, p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManHashStart(pNew); Gia_ManObj(p, iObj)->Value = 0; Gia_ManForEachObjVecStart( vNodes, p, pObj, i, 1 ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( p, pObj, i ) if ( Gia_ObjIsTravIdCurrent(p, pObj) ) pObj->Value = Gia_ObjFanin0Copy(pObj); Gia_ManObj(p, iObj)->Value = 1; Gia_ManForEachObjVecStart( vNodes, p, pObj, i, 1 ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( p, pObj, i ) if ( Gia_ObjIsTravIdCurrent(p, pObj) ) iRes = Gia_ManHashOr( pNew, iRes, Gia_ManHashXor(pNew, pObj->Value, Gia_ObjFanin0Copy(pObj)) ); Gia_ManAppendCo( pNew, Abc_LitNot(iRes) ); Vec_IntFree( vRoots ); Vec_IntFree( vNodes ); Vec_IntFree( vSupp ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Mark nodes supported by the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManMarkSupported( Gia_Man_t * p, Vec_Int_t * vObjs ) { Gia_Obj_t * pObj; int i; Vec_Int_t * vInner = Vec_IntAlloc( 100 ); Gia_ManIncrementTravId(p); Gia_ManForEachObjVec( vObjs, p, pObj, i ) Gia_ObjSetTravIdCurrent(p, pObj); Vec_IntAppend( vInner, vObjs ); Gia_ManForEachAnd( p, pObj, i ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) continue; if ( !Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) || !Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) continue; Gia_ObjSetTravIdCurrent(p, pObj); Vec_IntPush( vInner, Gia_ObjId(p, pObj) ); } return vInner; } Vec_Int_t * Gia_ManMarkPointed( Gia_Man_t * p, Vec_Int_t * vCut, Vec_Int_t * vInner ) { Gia_Obj_t * pObj; int i; Vec_Int_t * vOuts = Vec_IntAlloc( 100 ); Gia_ManForEachObjVec( vCut, p, pObj, i ) Gia_ObjSetTravIdPrevious(p, pObj); Gia_ManForEachAnd( p, pObj, i ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) continue; if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) ) { Gia_ObjSetTravIdPrevious(p, Gia_ObjFanin0(pObj)); Vec_IntPush( vOuts, Gia_ObjFaninId0p(p, pObj) ); } if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) { Gia_ObjSetTravIdPrevious(p, Gia_ObjFanin1(pObj)); Vec_IntPush( vOuts, Gia_ObjFaninId1p(p, pObj) ); } } Gia_ManForEachCo( p, pObj, i ) { if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) ) { Gia_ObjSetTravIdPrevious(p, Gia_ObjFanin0(pObj)); Vec_IntPush( vOuts, Gia_ObjFaninId0p(p, pObj) ); } } Vec_IntSort( vOuts, 0 ); return vOuts; } Gia_Man_t * Gia_ManDupWindow( Gia_Man_t * p, Vec_Int_t * vCut ) { Gia_Obj_t * pObj; int i; Vec_Int_t * vInner = Gia_ManMarkSupported( p, vCut ); Vec_Int_t * vOuts = Gia_ManMarkPointed( p, vCut, vInner ); Gia_Man_t * pNew = Gia_ManStart( 100 ); pNew->pName = Abc_UtilStrsav( "win" ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObjVec( vCut, p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachObjVecStart( vInner, p, pObj, i, Vec_IntSize(vCut) ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachObjVec( vOuts, p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); printf( "Derived window with %d inputs, %d internal nodes, and %d outputs.\n", Vec_IntSize(vCut), Vec_IntSize(vInner), Vec_IntSize(vOuts) ); printf( "Outputs: " ); Vec_IntPrint( vOuts ); Vec_IntFree( vInner ); Vec_IntFree( vOuts ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wec_t * Gia_ManCollectIntTfos( Gia_Man_t * p, Vec_Int_t * vVarNums ) { Vec_Wec_t * vTfos = Vec_WecStart( Vec_IntSize(vVarNums) ); Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); Gia_Obj_t * pObj; int i, k, Input, iNode; Gia_ManIncrementTravId( p ); Vec_IntForEachEntry( vVarNums, Input, i ) Gia_ObjSetTravIdCurrentId( p, Gia_ManCiIdToId(p, Input) ); Gia_ManForEachAnd( p, pObj, i ) if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)) || Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)) ) Gia_ObjSetTravIdCurrentId( p, i ), Vec_IntPush( vNodes, i ); Vec_IntForEachEntry( vVarNums, Input, i ) { Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrentId( p, Gia_ManCiIdToId(p, Input) ); Vec_IntForEachEntry( vNodes, iNode, k ) if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(Gia_ManObj(p, iNode), iNode)) || Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(Gia_ManObj(p, iNode), iNode)) ) Gia_ObjSetTravIdCurrentId( p, iNode ), Vec_WecPush( vTfos, i, iNode ); } Vec_IntFree( vNodes ); return vTfos; } Gia_Man_t * Gia_ManDupCofs( Gia_Man_t * p, Vec_Int_t * vVarNums ) { Vec_Int_t * vOutLits = Vec_IntStartFull( 1 << Vec_IntSize(vVarNums) ); Vec_Wec_t * vTfos = Gia_ManCollectIntTfos( p, vVarNums ); Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pRoot = Gia_ManCo(p, 0); int i, iLit; assert( Gia_ManPoNum(p) == 1 && Gia_ManRegNum(p) == 0 ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManForEachCiVec( vVarNums, p, pObj, i ) pObj->Value = 0; Gia_ManHashAlloc( pNew ); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Vec_IntWriteEntry( vOutLits, 0, Gia_ObjFanin0Copy(pRoot) ); int m, g, x, b = 0; for ( m = 1; m < Vec_IntSize(vOutLits); m++ ) { g = m ^ (m >> 1); x = (b ^ g) == 1 ? 0 : Abc_Base2Log(b ^ g); b = g; Vec_Int_t * vNode = Vec_WecEntry( vTfos, x ); Gia_ManPi(p, Vec_IntEntry(vVarNums, x))->Value ^= 1; Gia_ManForEachObjVec( vNode, p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Vec_IntWriteEntry( vOutLits, g, Gia_ObjFanin0Copy(pRoot) ); } assert( Vec_IntFindMin(vOutLits) >= 0 ); Vec_IntForEachEntry( vOutLits, iLit, i ) Gia_ManAppendCo( pNew, iLit ); Vec_IntFree( vOutLits ); Vec_WecFree( vTfos ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManCofPattern( Gia_Man_t * p ) { Vec_Int_t * vRes = Vec_IntAlloc( Gia_ManCoNum(p) ); Vec_Int_t * vMap = Vec_IntStartFull( 2*Gia_ManObjNum(p) ); Gia_Obj_t * pObj; int i, iLit, iClass = 0; assert( Gia_ManCoNum(p) == 1 << Abc_Base2Log(Gia_ManCoNum(p)) ); Gia_ManForEachPo( p, pObj, i ) { iLit = Gia_ObjFaninLit0p(p, pObj); if ( Vec_IntEntry(vMap, iLit) == -1 ) Vec_IntWriteEntry( vMap, iLit, iClass++ ); Vec_IntPush( vRes, Vec_IntEntry(vMap, iLit) ); } Vec_IntFree( vMap ); return vRes; } Vec_Int_t * Gia_ManCofClassPattern( Gia_Man_t * p, Vec_Int_t * vVarNums, int fVerbose ) { extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); Gia_Man_t * pCofs = Gia_ManDupCofs( p, vVarNums ); Gia_Man_t * pSweep = Cec4_ManSimulateTest3( pCofs, 0, 0 ); Vec_Int_t * vRes = Gia_ManCofPattern( pSweep ); assert( Vec_IntSize(vRes) == 1 << Vec_IntSize(vVarNums) ); Gia_ManStop( pSweep ); Gia_ManStop( pCofs ); if ( fVerbose ) { int i, Class, nClasses = Vec_IntFindMax(vRes)+1; printf( "%d -> %d: ", Vec_IntSize(vVarNums), nClasses ); if ( nClasses <= 36 ) Vec_IntForEachEntry( vRes, Class, i ) printf( "%c", (Class < 10 ? (int)'0' : (int)'A'-10) + Class ); printf( "\n" ); } return vRes; } Gia_Man_t * Gia_ManDupEncode( Gia_Man_t * p, Vec_Int_t * vVarNums, int fVerbose ) { extern Vec_Int_t * Gia_GenDecoder( Gia_Man_t * p, int * pLits, int nLits ); Gia_Man_t * pNew, * pTemp; Vec_Int_t * vCols = Gia_ManCofClassPattern( p, vVarNums, fVerbose ); Vec_Int_t * vVars = Vec_IntAlloc( 100 ), * vDec; int i, k, Limit = Vec_IntSize(vCols), Entry; int nClasses = Vec_IntFindMax(vCols)+1; int nExtras = Abc_Base2Log(nClasses); pNew = Gia_ManStart( 1000 ); pNew->pName = Abc_UtilStrsav( p->pName ); for ( i = 0; i < Vec_IntSize(vVarNums) + nExtras; i++ ) Vec_IntPush( vVars, Gia_ManAppendCi(pNew) ); Gia_ManHashAlloc( pNew ); vDec = Gia_GenDecoder( pNew, Vec_IntEntryP(vVars, Vec_IntSize(vVarNums)), nExtras ); Vec_IntForEachEntry( vCols, Entry, i ) Vec_IntWriteEntry( vCols, i, Vec_IntEntry(vDec, Entry) ); Vec_IntFree( vDec ); for ( i = Vec_IntSize(vVarNums) - 1; i >= 0; i--, Limit /= 2 ) for ( k = 0; k < Limit; k += 2 ) Vec_IntWriteEntry( vCols, k/2, Gia_ManHashMux(pNew, Vec_IntEntry(vVars, i), Vec_IntEntry(vCols, k+1), Vec_IntEntry(vCols, k)) ); Gia_ManAppendCo( pNew, Vec_IntEntry(vCols, 0) ); Vec_IntFree( vCols ); Vec_IntFree( vVars ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); if ( fVerbose ) printf( "Generated AIG with %d inputs and %d nodes representing %d PIs with %d columns.\n", Gia_ManPiNum(pNew), Gia_ManAndNum(pNew), Vec_IntSize(vVarNums), nClasses ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCofClassRand( Gia_Man_t * p, int nVars, int nRands ) { for ( int n = 0; n < nRands; n++ ) { Abc_Random(1); for ( int i = 0; i < n; i++ ) Abc_Random(0); Vec_Int_t * vIns = Vec_IntStartNatural( Gia_ManPiNum(p) ); Vec_IntRandomizeOrder( vIns ); Vec_IntShrink( vIns, nVars ); int k, Entry; printf( "Vars: " ); Vec_IntForEachEntry( vIns, Entry, k ) printf( "%d ", Entry ); printf( " " ); Vec_Int_t * vTemp = Gia_ManCofClassPattern( p, vIns, 1 ); Vec_IntFree( vTemp ); Vec_IntFree( vIns ); } } void Gia_ManCofClassEnum( Gia_Man_t * p, int nVars ) { Vec_Int_t * vIns = Vec_IntAlloc( nVars ); int m, k, Entry, Count, nMints = 1 << Gia_ManPiNum(p); for ( m = 0; m < nMints; m++ ) { for ( Count = k = 0; k < Gia_ManPiNum(p); k++ ) Count += (m >> k) & 1; if ( Count != nVars ) continue; Vec_IntClear( vIns ); for ( k = 0; k < Gia_ManPiNum(p); k++ ) if ( (m >> k) & 1 ) Vec_IntPush( vIns, k ); assert( Vec_IntSize(vIns) == Count ); printf( "Vars: " ); Vec_IntForEachEntry( vIns, Entry, k ) printf( "%d ", Entry ); printf( " " ); Vec_Int_t * vTemp = Gia_ManCofClassPattern( p, vIns, 1 ); Vec_IntFree( vTemp ); } Vec_IntFree( vIns ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaEdge.c000066400000000000000000001036501477524141600157650ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaEdge.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Edge-related procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaEdge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/tim/tim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Gia_ObjEdgeCount( int iObj, Vec_Int_t * vEdge1, Vec_Int_t * vEdge2 ) { return (Vec_IntEntry(vEdge1, iObj) > 0) + (Vec_IntEntry(vEdge2, iObj) > 0); } static inline int Gia_ObjEdgeAdd( int iObj, int iNext, Vec_Int_t * vEdge1, Vec_Int_t * vEdge2 ) { int RetValue = 0; if ( Vec_IntEntry(vEdge1, iObj) == 0 ) Vec_IntWriteEntry(vEdge1, iObj, iNext); else if ( Vec_IntEntry(vEdge2, iObj) == 0 ) Vec_IntWriteEntry(vEdge2, iObj, iNext); else RetValue = 1; return RetValue; } static inline void Gia_ObjEdgeRemove( int iObj, int iNext, Vec_Int_t * vEdge1, Vec_Int_t * vEdge2 ) { assert( Vec_IntEntry(vEdge1, iObj) == iNext || Vec_IntEntry(vEdge2, iObj) == iNext ); if ( Vec_IntEntry(vEdge1, iObj) == iNext ) Vec_IntWriteEntry( vEdge1, iObj, Vec_IntEntry(vEdge2, iObj) ); Vec_IntWriteEntry( vEdge2, iObj, 0 ); } static inline void Gia_ObjEdgeClean( int iObj, Vec_Int_t * vEdge1, Vec_Int_t * vEdge2 ) { Vec_IntWriteEntry( vEdge1, iObj, 0 ); Vec_IntWriteEntry( vEdge2, iObj, 0 ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Transforms edge assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManEdgeFromArray( Gia_Man_t * p, Vec_Int_t * vArray ) { int i, iObj1, iObj2, Count = 0; Vec_IntFreeP( &p->vEdge1 ); Vec_IntFreeP( &p->vEdge2 ); p->vEdge1 = Vec_IntStart( Gia_ManObjNum(p) ); p->vEdge2 = Vec_IntStart( Gia_ManObjNum(p) ); Vec_IntForEachEntryDouble( vArray, iObj1, iObj2, i ) { assert( iObj1 < iObj2 ); Count += Gia_ObjEdgeAdd( iObj1, iObj2, p->vEdge1, p->vEdge2 ); Count += Gia_ObjEdgeAdd( iObj2, iObj1, p->vEdge1, p->vEdge2 ); } if ( Count ) printf( "Found %d violations during edge conversion.\n", Count ); } Vec_Int_t * Gia_ManEdgeToArray( Gia_Man_t * p ) { int iObj, iFanin; Vec_Int_t * vArray = Vec_IntAlloc( 1000 ); assert( p->vEdge1 && p->vEdge2 ); assert( Vec_IntSize(p->vEdge1) == Gia_ManObjNum(p) ); assert( Vec_IntSize(p->vEdge2) == Gia_ManObjNum(p) ); for ( iObj = 0; iObj < Gia_ManObjNum(p); iObj++ ) { iFanin = Vec_IntEntry( p->vEdge1, iObj ); if ( iFanin && iFanin < iObj ) Vec_IntPushTwo( vArray, iFanin, iObj ); iFanin = Vec_IntEntry( p->vEdge2, iObj ); if ( iFanin && iFanin < iObj ) Vec_IntPushTwo( vArray, iFanin, iObj ); } return vArray; } /**Function************************************************************* Synopsis [Prints mapping statistics.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManConvertPackingToEdges( Gia_Man_t * p ) { int i, k, Entry, nEntries, nEntries2, nNodes[4], Count = 0; if ( p->vPacking == NULL ) return; Vec_IntFreeP( &p->vEdge1 ); Vec_IntFreeP( &p->vEdge2 ); p->vEdge1 = Vec_IntStart( Gia_ManObjNum(p) ); p->vEdge2 = Vec_IntStart( Gia_ManObjNum(p) ); // iterate through structures nEntries = Vec_IntEntry( p->vPacking, 0 ); nEntries2 = 0; Vec_IntForEachEntryStart( p->vPacking, Entry, i, 1 ) { assert( Entry > 0 && Entry < 4 ); i++; for ( k = 0; k < Entry; k++, i++ ) nNodes[k] = Vec_IntEntry(p->vPacking, i); i--; nEntries2++; // create edges if ( Entry == 2 ) { Count += Gia_ObjEdgeAdd( nNodes[0], nNodes[1], p->vEdge1, p->vEdge2 ); Count += Gia_ObjEdgeAdd( nNodes[1], nNodes[0], p->vEdge1, p->vEdge2 ); } else if ( Entry == 3 ) { Count += Gia_ObjEdgeAdd( nNodes[0], nNodes[2], p->vEdge1, p->vEdge2 ); Count += Gia_ObjEdgeAdd( nNodes[2], nNodes[0], p->vEdge1, p->vEdge2 ); Count += Gia_ObjEdgeAdd( nNodes[1], nNodes[2], p->vEdge1, p->vEdge2 ); Count += Gia_ObjEdgeAdd( nNodes[2], nNodes[1], p->vEdge1, p->vEdge2 ); } } assert( nEntries == nEntries2 ); if ( Count ) printf( "Skipped %d illegal edges.\n", Count ); } /**Function************************************************************* Synopsis [Evaluates given edge assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ObjHaveEdge( Gia_Man_t * p, int iObj, int iNext ) { return Vec_IntEntry(p->vEdge1, iObj) == iNext || Vec_IntEntry(p->vEdge2, iObj) == iNext; } int Gia_ObjCheckEdge( Gia_Man_t * p, int iObj, int iNext ) { return Gia_ObjHaveEdge( p, iObj, iNext ); } static inline int Gia_ObjEvalEdgeDelay( Gia_Man_t * p, int iObj, Vec_Int_t * vDelay ) { int nEdgeDelay = 2; int i, iFan, Delay, DelayMax = 0; if ( Gia_ManHasMapping(p) && Gia_ObjIsLut(p, iObj) ) { assert( Gia_ObjLutSize(p, iObj) <= 4 ); Gia_LutForEachFanin( p, iObj, iFan, i ) { Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? nEdgeDelay : 10); DelayMax = Abc_MaxInt( DelayMax, Delay ); } } else if ( Gia_ObjIsLut2(p, iObj) ) { assert( Gia_ObjLutSize2(p, iObj) <= 4 ); Gia_LutForEachFanin2( p, iObj, iFan, i ) { Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? nEdgeDelay : 10); DelayMax = Abc_MaxInt( DelayMax, Delay ); } } else assert( 0 ); return DelayMax; } int Gia_ManEvalEdgeDelay( Gia_Man_t * p ) { int k, iLut, DelayMax = 0; assert( p->vEdge1 && p->vEdge2 ); Vec_IntFreeP( &p->vEdgeDelay ); p->vEdgeDelay = Vec_IntStart( Gia_ManObjNum(p) ); if ( Gia_ManHasMapping(p) ) { if ( p->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) ) { Gia_Obj_t * pObj; Vec_Int_t * vNodes = Gia_ManOrderWithBoxes( p ); Tim_ManIncrementTravId( (Tim_Man_t*)p->pManTime ); Gia_ManForEachObjVec( vNodes, p, pObj, k ) { iLut = Gia_ObjId( p, pObj ); if ( Gia_ObjIsAnd(pObj) ) { if ( Gia_ObjIsLut(p, iLut) ) Vec_IntWriteEntry( p->vEdgeDelay, iLut, Gia_ObjEvalEdgeDelay(p, iLut, p->vEdgeDelay) ); } else if ( Gia_ObjIsCi(pObj) ) { int arrTime = Tim_ManGetCiArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj) ); Vec_IntWriteEntry( p->vEdgeDelay, iLut, arrTime ); } else if ( Gia_ObjIsCo(pObj) ) { int arrTime = Vec_IntEntry( p->vEdgeDelay, Gia_ObjFaninId0(pObj, iLut) ); Tim_ManSetCoArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj), arrTime ); } else if ( !Gia_ObjIsConst0(pObj) ) assert( 0 ); } Vec_IntFree( vNodes ); } else { Gia_ManForEachLut( p, iLut ) Vec_IntWriteEntry( p->vEdgeDelay, iLut, Gia_ObjEvalEdgeDelay(p, iLut, p->vEdgeDelay) ); } } else if ( Gia_ManHasMapping2(p) ) { if ( p->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) ) { Gia_Obj_t * pObj; Vec_Int_t * vNodes = Gia_ManOrderWithBoxes( p ); Tim_ManIncrementTravId( (Tim_Man_t*)p->pManTime ); Gia_ManForEachObjVec( vNodes, p, pObj, k ) { iLut = Gia_ObjId( p, pObj ); if ( Gia_ObjIsAnd(pObj) ) { if ( Gia_ObjIsLut2(p, iLut) ) Vec_IntWriteEntry( p->vEdgeDelay, iLut, Gia_ObjEvalEdgeDelay(p, iLut, p->vEdgeDelay) ); } else if ( Gia_ObjIsCi(pObj) ) { int arrTime = Tim_ManGetCiArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj) ); Vec_IntWriteEntry( p->vEdgeDelay, iLut, arrTime ); } else if ( Gia_ObjIsCo(pObj) ) { int arrTime = Vec_IntEntry( p->vEdgeDelay, Gia_ObjFaninId0(pObj, iLut) ); Tim_ManSetCoArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj), arrTime ); } else if ( !Gia_ObjIsConst0(pObj) ) assert( 0 ); } Vec_IntFree( vNodes ); } else { Gia_ManForEachLut2( p, iLut ) Vec_IntWriteEntry( p->vEdgeDelay, iLut, Gia_ObjEvalEdgeDelay(p, iLut, p->vEdgeDelay) ); } } else assert( 0 ); Gia_ManForEachCoDriverId( p, iLut, k ) DelayMax = Abc_MaxInt( DelayMax, Vec_IntEntry(p->vEdgeDelay, iLut) ); return DelayMax; } int Gia_ManEvalEdgeCount( Gia_Man_t * p ) { return (Vec_IntCountPositive(p->vEdge1) + Vec_IntCountPositive(p->vEdge2))/2; } /**Function************************************************************* Synopsis [Finds edge assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ObjComputeEdgeDelay( Gia_Man_t * p, int iObj, Vec_Int_t * vDelay, Vec_Int_t * vEdge1, Vec_Int_t * vEdge2, int fUseTwo ) { int i, iFan, Delay, Status1, Status2; int DelayMax = 0, DelayMax2 = 0, nCountMax = 0; int iFanMax1 = -1, iFanMax2 = -1; Vec_IntWriteEntry(vEdge1, iObj, 0); Vec_IntWriteEntry(vEdge2, iObj, 0); if ( Gia_ManHasMapping(p) && Gia_ObjIsLut(p, iObj) ) { assert( Gia_ObjLutSize(p, iObj) <= 4 ); Gia_LutForEachFanin( p, iObj, iFan, i ) { Delay = Vec_IntEntry( vDelay, iFan ) + 10; if ( DelayMax < Delay ) { DelayMax2 = DelayMax; DelayMax = Delay; iFanMax1 = iFan; nCountMax = 1; } else if ( DelayMax == Delay ) { iFanMax2 = iFan; nCountMax++; if ( !fUseTwo ) DelayMax2 = DelayMax; } else DelayMax2 = Abc_MaxInt( DelayMax2, Delay ); } } else if ( Gia_ObjIsLut2(p, iObj) ) { assert( Gia_ObjLutSize2(p, iObj) <= 4 ); Gia_LutForEachFanin2( p, iObj, iFan, i ) { Delay = Vec_IntEntry( vDelay, iFan ) + 10; if ( DelayMax < Delay ) { DelayMax2 = DelayMax; DelayMax = Delay; iFanMax1 = iFan; nCountMax = 1; } else if ( DelayMax == Delay ) { iFanMax2 = iFan; nCountMax++; if ( !fUseTwo ) DelayMax2 = DelayMax; } else DelayMax2 = Abc_MaxInt( DelayMax2, Delay ); } } else assert( 0 ); assert( nCountMax > 0 ); if ( DelayMax <= 10 ) {} // skip first level else if ( nCountMax == 1 ) { Status1 = Gia_ObjEdgeCount( iFanMax1, vEdge1, vEdge2 ); if ( Status1 <= 1 ) { Gia_ObjEdgeAdd( iFanMax1, iObj, vEdge1, vEdge2 ); Gia_ObjEdgeAdd( iObj, iFanMax1, vEdge1, vEdge2 ); DelayMax = Abc_MaxInt( DelayMax2, DelayMax - 8 ); Vec_IntWriteEntry( vDelay, iObj, DelayMax ); return DelayMax; } } else if ( fUseTwo && nCountMax == 2 ) { Status1 = Gia_ObjEdgeCount( iFanMax1, vEdge1, vEdge2 ); Status2 = Gia_ObjEdgeCount( iFanMax2, vEdge1, vEdge2 ); if ( Status1 <= 1 && Status2 <= 1 ) { Gia_ObjEdgeAdd( iFanMax1, iObj, vEdge1, vEdge2 ); Gia_ObjEdgeAdd( iFanMax2, iObj, vEdge1, vEdge2 ); Gia_ObjEdgeAdd( iObj, iFanMax1, vEdge1, vEdge2 ); Gia_ObjEdgeAdd( iObj, iFanMax2, vEdge1, vEdge2 ); DelayMax = Abc_MaxInt( DelayMax2, DelayMax - 8 ); Vec_IntWriteEntry( vDelay, iObj, DelayMax ); return DelayMax; } } Vec_IntWriteEntry( vDelay, iObj, DelayMax ); return DelayMax; } int Gia_ManComputeEdgeDelay( Gia_Man_t * p, int fUseTwo ) { int k, iLut, DelayMax = 0; Vec_IntFreeP( &p->vEdgeDelay ); Vec_IntFreeP( &p->vEdge1 ); Vec_IntFreeP( &p->vEdge2 ); p->vEdge1 = Vec_IntStart( Gia_ManObjNum(p) ); p->vEdge2 = Vec_IntStart( Gia_ManObjNum(p) ); p->vEdgeDelay = Vec_IntStart( Gia_ManObjNum(p) ); if ( Gia_ManHasMapping(p) ) { if ( p->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) ) { Gia_Obj_t * pObj; Vec_Int_t * vNodes = Gia_ManOrderWithBoxes( p ); Tim_ManIncrementTravId( (Tim_Man_t*)p->pManTime ); Gia_ManForEachObjVec( vNodes, p, pObj, k ) { iLut = Gia_ObjId( p, pObj ); if ( Gia_ObjIsAnd(pObj) ) { if ( Gia_ObjIsLut(p, iLut) ) Gia_ObjComputeEdgeDelay( p, iLut, p->vEdgeDelay, p->vEdge1, p->vEdge2, fUseTwo ); } else if ( Gia_ObjIsCi(pObj) ) { int arrTime = Tim_ManGetCiArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj) ); Vec_IntWriteEntry( p->vEdgeDelay, iLut, arrTime ); } else if ( Gia_ObjIsCo(pObj) ) { int arrTime = Vec_IntEntry( p->vEdgeDelay, Gia_ObjFaninId0(pObj, iLut) ); Tim_ManSetCoArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj), arrTime ); } else if ( !Gia_ObjIsConst0(pObj) ) assert( 0 ); } Vec_IntFree( vNodes ); } else { Gia_ManForEachLut( p, iLut ) Gia_ObjComputeEdgeDelay( p, iLut, p->vEdgeDelay, p->vEdge1, p->vEdge2, fUseTwo ); } } else if ( Gia_ManHasMapping2(p) ) { if ( p->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) ) { Gia_Obj_t * pObj; Vec_Int_t * vNodes = Gia_ManOrderWithBoxes( p ); Tim_ManIncrementTravId( (Tim_Man_t*)p->pManTime ); Gia_ManForEachObjVec( vNodes, p, pObj, k ) { iLut = Gia_ObjId( p, pObj ); if ( Gia_ObjIsAnd(pObj) ) { if ( Gia_ObjIsLut2(p, iLut) ) Gia_ObjComputeEdgeDelay( p, iLut, p->vEdgeDelay, p->vEdge1, p->vEdge2, fUseTwo ); } else if ( Gia_ObjIsCi(pObj) ) { int arrTime = Tim_ManGetCiArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj) ); Vec_IntWriteEntry( p->vEdgeDelay, iLut, arrTime ); } else if ( Gia_ObjIsCo(pObj) ) { int arrTime = Vec_IntEntry( p->vEdgeDelay, Gia_ObjFaninId0(pObj, iLut) ); Tim_ManSetCoArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj), arrTime ); } else if ( !Gia_ObjIsConst0(pObj) ) assert( 0 ); } Vec_IntFree( vNodes ); } else { Gia_ManForEachLut2( p, iLut ) Gia_ObjComputeEdgeDelay( p, iLut, p->vEdgeDelay, p->vEdge1, p->vEdge2, fUseTwo ); } } else assert( 0 ); Gia_ManForEachCoDriverId( p, iLut, k ) DelayMax = Abc_MaxInt( DelayMax, Vec_IntEntry(p->vEdgeDelay, iLut) ); //printf( "The number of edges = %d. Delay = %d.\n", Gia_ManEvalEdgeCount(p), DelayMax ); return DelayMax; } /**Function************************************************************* Synopsis [Finds edge assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ObjComputeEdgeDelay2( Gia_Man_t * p, int iObj, Vec_Int_t * vDelay, Vec_Int_t * vEdge1, Vec_Int_t * vEdge2, Vec_Int_t * vFanMax1, Vec_Int_t * vFanMax2, Vec_Int_t * vCountMax ) { int i, iFan, DelayFanin, Status1, Status2; int DelayMax = 0, nCountMax = 0; int iFanMax1 = -1, iFanMax2 = -1; Vec_IntWriteEntry(vEdge1, iObj, 0); Vec_IntWriteEntry(vEdge2, iObj, 0); // analyze this node DelayMax = Vec_IntEntry( vDelay, iObj ); nCountMax = Vec_IntEntry( vCountMax, iObj ); if ( DelayMax == 0 ) {} else if ( nCountMax == 1 ) { iFanMax1 = Vec_IntEntry( vFanMax1, iObj ); Status1 = Gia_ObjEdgeCount( iFanMax1, vEdge1, vEdge2 ); if ( Status1 <= 1 ) { Gia_ObjEdgeAdd( iFanMax1, iObj, vEdge1, vEdge2 ); Gia_ObjEdgeAdd( iObj, iFanMax1, vEdge1, vEdge2 ); DelayMax--; } } else if ( nCountMax == 2 ) { iFanMax1 = Vec_IntEntry( vFanMax1, iObj ); iFanMax2 = Vec_IntEntry( vFanMax2, iObj ); Status1 = Gia_ObjEdgeCount( iFanMax1, vEdge1, vEdge2 ); Status2 = Gia_ObjEdgeCount( iFanMax2, vEdge1, vEdge2 ); if ( Status1 <= 1 && Status2 <= 1 ) { Gia_ObjEdgeAdd( iFanMax1, iObj, vEdge1, vEdge2 ); Gia_ObjEdgeAdd( iFanMax2, iObj, vEdge1, vEdge2 ); Gia_ObjEdgeAdd( iObj, iFanMax1, vEdge1, vEdge2 ); Gia_ObjEdgeAdd( iObj, iFanMax2, vEdge1, vEdge2 ); DelayMax--; } } Vec_IntWriteEntry( vDelay, iObj, DelayMax ); // computed DelayMax at this point if ( Gia_ManHasMapping(p) && Gia_ObjIsLut(p, iObj) ) { Gia_LutForEachFanin( p, iObj, iFan, i ) { DelayFanin = Vec_IntEntry( vDelay, iFan ); if ( DelayFanin < DelayMax + 1 ) { Vec_IntWriteEntry( vDelay, iFan, DelayMax + 1 ); Vec_IntWriteEntry( vFanMax1, iFan, iObj ); Vec_IntWriteEntry( vCountMax, iFan, 1 ); } else if ( DelayFanin == DelayMax + 1 ) { Vec_IntWriteEntry( vFanMax2, iFan, iObj ); Vec_IntAddToEntry( vCountMax, iFan, 1 ); } } } else if ( Gia_ObjIsLut2(p, iObj) ) { Gia_LutForEachFanin2( p, iObj, iFan, i ) { DelayFanin = Vec_IntEntry( vDelay, iFan ); if ( DelayFanin < DelayMax + 1 ) { Vec_IntWriteEntry( vDelay, iFan, DelayMax + 1 ); Vec_IntWriteEntry( vFanMax1, iFan, iObj ); Vec_IntWriteEntry( vCountMax, iFan, 1 ); } else if ( DelayFanin == DelayMax + 1 ) { Vec_IntWriteEntry( vFanMax2, iFan, iObj ); Vec_IntAddToEntry( vCountMax, iFan, 1 ); } } } else assert( 0 ); return DelayMax; } int Gia_ManComputeEdgeDelay2( Gia_Man_t * p ) { int k, iLut, DelayMax = 0; Vec_Int_t * vFanMax1 = Vec_IntStart( Gia_ManObjNum(p) ); Vec_Int_t * vFanMax2 = Vec_IntStart( Gia_ManObjNum(p) ); Vec_Int_t * vCountMax = Vec_IntStart( Gia_ManObjNum(p) ); assert( p->pManTime == NULL ); Vec_IntFreeP( &p->vEdgeDelay ); Vec_IntFreeP( &p->vEdge1 ); Vec_IntFreeP( &p->vEdge2 ); p->vEdgeDelay = Vec_IntStart( Gia_ManObjNum(p) ); p->vEdge1 = Vec_IntStart( Gia_ManObjNum(p) ); p->vEdge2 = Vec_IntStart( Gia_ManObjNum(p) ); // Gia_ManForEachCoDriverId( p, iLut, k ) // Vec_IntWriteEntry( p->vEdgeDelay, iLut, 1 ); if ( Gia_ManHasMapping(p) ) Gia_ManForEachLutReverse( p, iLut ) Gia_ObjComputeEdgeDelay2( p, iLut, p->vEdgeDelay, p->vEdge1, p->vEdge2, vFanMax1, vFanMax2, vCountMax ); else if ( Gia_ManHasMapping2(p) ) Gia_ManForEachLut2Reverse( p, iLut ) Gia_ObjComputeEdgeDelay2( p, iLut, p->vEdgeDelay, p->vEdge1, p->vEdge2, vFanMax1, vFanMax2, vCountMax ); else assert( 0 ); Gia_ManForEachCiId( p, iLut, k ) DelayMax = Abc_MaxInt( DelayMax, Vec_IntEntry(p->vEdgeDelay, iLut) ); Vec_IntFree( vFanMax1 ); Vec_IntFree( vFanMax2 ); Vec_IntFree( vCountMax ); //printf( "The number of edges = %d. Delay = %d.\n", Gia_ManEvalEdgeCount(p), DelayMax ); return DelayMax; } /**Function************************************************************* Synopsis [Finds edge assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManUpdateMapping( Gia_Man_t * p, Vec_Int_t * vNodes, Vec_Wec_t * vWin ) { int i, iNode; Vec_IntForEachEntry( vNodes, iNode, i ) ABC_SWAP( Vec_Int_t, *Vec_WecEntry(p->vMapping2, iNode), *Vec_WecEntry(vWin, i) ); } int Gia_ManEvalWindowInc( Gia_Man_t * p, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Wec_t * vWin, Vec_Int_t * vTemp, int fUseTwo ) { int i, iLut, Delay, DelayMax = 0; assert( Vec_IntSize(vNodes) == Vec_WecSize(vWin) ); Gia_ManUpdateMapping( p, vNodes, vWin ); Gia_ManCollectTfo( p, vLeaves, vTemp ); Vec_IntReverseOrder( vTemp ); Vec_IntForEachEntry( vTemp, iLut, i ) { if ( !Gia_ObjIsLut(p, iLut) ) continue; Delay = Gia_ObjComputeEdgeDelay( p, iLut, p->vEdgeDelay, p->vEdge1, p->vEdge2, fUseTwo ); DelayMax = Abc_MaxInt( DelayMax, Delay ); } Gia_ManUpdateMapping( p, vNodes, vWin ); return DelayMax; } int Gia_ManEvalWindow( Gia_Man_t * p, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Wec_t * vWin, Vec_Int_t * vTemp, int fUseTwo ) { int DelayMax; assert( Vec_IntSize(vNodes) == Vec_WecSize(vWin) ); Gia_ManUpdateMapping( p, vNodes, vWin ); DelayMax = Gia_ManComputeEdgeDelay( p, fUseTwo ); Gia_ManUpdateMapping( p, vNodes, vWin ); return DelayMax; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Edg_ManToMapping( Gia_Man_t * p ) { int iObj, iFanin, k; assert( Gia_ManHasMapping(p) ); Vec_WecFreeP( &p->vMapping2 ); Vec_WecFreeP( &p->vFanouts2 ); p->vMapping2 = Vec_WecStart( Gia_ManObjNum(p) ); p->vFanouts2 = Vec_WecStart( Gia_ManObjNum(p) ); Gia_ManForEachLut( p, iObj ) { assert( Gia_ObjLutSize(p, iObj) <= 4 ); Gia_LutForEachFanin( p, iObj, iFanin, k ) { Vec_WecPush( p->vMapping2, iObj, iFanin ); Vec_WecPush( p->vFanouts2, iFanin, iObj ); } } } /**Function************************************************************* Synopsis [Computes delay for the given edge assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Edg_ObjEvalEdgeDelay( Gia_Man_t * p, int iObj, Vec_Int_t * vDelay ) { int DelayEdge = 0; // 2; int DelayNoEdge = 1; int i, iFan, Delay, DelayMax = 0; assert( Gia_ObjIsLut2(p, iObj) ); Gia_LutForEachFanin2( p, iObj, iFan, i ) { Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? DelayEdge : DelayNoEdge); DelayMax = Abc_MaxInt( DelayMax, Delay ); } //printf( "Obj %d - Level %d\n", iObj, DelayMax ); return DelayMax; } int Edg_ManEvalEdgeDelay( Gia_Man_t * p ) { int iLut, Delay, DelayMax = 0; assert( p->vEdge1 && p->vEdge2 ); if ( p->vEdgeDelay == NULL ) p->vEdgeDelay = Vec_IntStart( Gia_ManObjNum(p) ); else Vec_IntFill( p->vEdgeDelay, Gia_ManObjNum(p), 0 ); Gia_ManForEachLut2( p, iLut ) { Delay = Edg_ObjEvalEdgeDelay(p, iLut, p->vEdgeDelay); Vec_IntWriteEntry( p->vEdgeDelay, iLut, Delay ); DelayMax = Abc_MaxInt( DelayMax, Delay ); } return DelayMax; } static inline int Edg_ObjEvalEdgeDelayR( Gia_Man_t * p, int iObj, Vec_Int_t * vDelay ) { int DelayEdge = 0; // 2; int DelayNoEdge = 1; int i, iFan, Delay, DelayMax = 0; assert( Gia_ObjIsLut2(p, iObj) ); Gia_LutForEachFanout2( p, iObj, iFan, i ) { Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? DelayEdge : DelayNoEdge); DelayMax = Abc_MaxInt( DelayMax, Delay ); } //printf( "Obj %d - LevelR %d\n", iObj, DelayMax ); return DelayMax; } int Edg_ManEvalEdgeDelayR( Gia_Man_t * p ) { // int k, DelayNoEdge = 1; int iLut, Delay, DelayMax = 0; assert( p->vEdge1 && p->vEdge2 ); if ( p->vEdgeDelayR == NULL ) p->vEdgeDelayR = Vec_IntStart( Gia_ManObjNum(p) ); else Vec_IntFill( p->vEdgeDelayR, Gia_ManObjNum(p), 0 ); // Gia_ManForEachCoDriverId( p, iLut, k ) // Vec_IntWriteEntry( p->vEdgeDelayR, iLut, DelayNoEdge ); Gia_ManForEachLut2Reverse( p, iLut ) { Delay = Edg_ObjEvalEdgeDelayR(p, iLut, p->vEdgeDelayR); Vec_IntWriteEntry( p->vEdgeDelayR, iLut, Delay ); DelayMax = Abc_MaxInt( DelayMax, Delay ); } return DelayMax; } void Edg_ManCollectCritEdges( Gia_Man_t * p, Vec_Wec_t * vEdges, int DelayMax ) { Vec_Int_t * vLevel; int k, iLut, Delay1, Delay2; assert( p->vEdge1 && p->vEdge2 ); Vec_WecClear( vEdges ); Vec_WecInit( vEdges, DelayMax + 1 ); Gia_ManForEachLut2( p, iLut ) { Delay1 = Vec_IntEntry( p->vEdgeDelay, iLut ); Delay2 = Vec_IntEntry( p->vEdgeDelayR, iLut ); assert( Delay1 + Delay2 <= DelayMax ); if ( Delay1 + Delay2 == DelayMax ) Vec_WecPush( vEdges, Delay1, iLut ); } // every level should have critical nodes, except the first one //Vec_WecPrint( vEdges, 0 ); Vec_WecForEachLevelStart( vEdges, vLevel, k, 1 ) assert( Vec_IntSize(vLevel) > 0 ); } /**Function************************************************************* Synopsis [Update one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Edg_ObjImprove( Gia_Man_t * p, int iObj, int nEdgeLimit, int DelayMax, int fVerbose ) { int nFaninsC = 0, nFanoutsC = 0; // critical int nFaninsEC = 0, nFanoutsEC = 0; // edge-critical int nFaninsENC = 0, nFanoutsENC = 0; // edge-non-critial int pFanins[4], pFanouts[4]; int nEdgeDiff, nEdges = 0, Count = 0; int i, iNext, Delay1, Delay2; // count how many fanins have critical edge Delay1 = Vec_IntEntry( p->vEdgeDelayR, iObj ); //if ( Delay1 > 1 ) Gia_LutForEachFanin2( p, iObj, iNext, i ) { if ( !Gia_ObjIsAnd(Gia_ManObj(p, iNext)) ) continue; Delay2 = Vec_IntEntry( p->vEdgeDelay, iNext ); if ( Gia_ObjHaveEdge(p, iObj, iNext) ) { nEdges++; assert( Delay1 + Delay2 <= DelayMax ); if ( Delay1 + Delay2 == DelayMax ) nFaninsEC++; else nFaninsENC++; } else { assert( Delay1 + Delay2 + 1 <= DelayMax ); if ( Delay1 + Delay2 + 1 == DelayMax ) pFanins[nFaninsC++] = iNext; } } // count how many fanouts have critical edge Delay1 = Vec_IntEntry( p->vEdgeDelay, iObj ); //if ( Delay2 < DelayMax - 1 ) Gia_LutForEachFanout2( p, iObj, iNext, i ) { //if ( !Gia_ObjIsAnd(Gia_ManObj(p, iNext)) ) // continue; assert( Gia_ObjIsAnd(Gia_ManObj(p, iNext)) ); Delay2 = Vec_IntEntry( p->vEdgeDelayR, iNext ); if ( Gia_ObjHaveEdge(p, iObj, iNext) ) { nEdges++; assert( Delay1 + Delay2 <= DelayMax ); if ( Delay1 + Delay2 == DelayMax ) nFanoutsEC++; else nFanoutsENC++; } else { assert( Delay1 + Delay2 + 1 <= DelayMax ); if ( Delay1 + Delay2 + 1 == DelayMax ) { if ( nFanoutsC < nEdgeLimit ) pFanouts[nFanoutsC] = iNext; nFanoutsC++; } } } if ( fVerbose ) { printf( "%8d : ", iObj ); printf( "Edges = %d ", nEdges ); printf( "Fanins (all %d EC %d ENC %d C %d) ", Gia_ObjLutSize2(p, iObj), nFaninsEC, nFaninsENC, nFaninsC ); printf( "Fanouts (all %d EC %d ENC %d C %d) ", Gia_ObjLutFanoutNum2(p, iObj), nFanoutsEC, nFanoutsENC, nFanoutsC ); } // consider simple cases assert( nEdges <= nEdgeLimit ); if ( nEdges == nEdgeLimit ) { if ( fVerbose ) printf( "Full\n" ); return 0; } nEdgeDiff = nEdgeLimit - nEdges; // check if fanins or fanouts could be improved if ( nFaninsEC == 0 && nFaninsC && nFaninsC <= nEdgeDiff ) { for ( i = 0; i < nFaninsC; i++ ) if ( Gia_ObjEdgeCount(pFanins[i], p->vEdge1, p->vEdge2) == nEdgeLimit ) break; if ( i == nFaninsC ) { for ( i = 0; i < nFaninsC; i++ ) { Count += Gia_ObjEdgeAdd( iObj, pFanins[i], p->vEdge1, p->vEdge2 ); Count += Gia_ObjEdgeAdd( pFanins[i], iObj, p->vEdge1, p->vEdge2 ); } if ( Count ) printf( "Wrong number of edges.\n" ); if ( fVerbose ) printf( "Fixed %d critical fanins\n", nFaninsC ); return 1; } } if ( nFanoutsEC == 0 && nFanoutsC && nFanoutsC <= nEdgeDiff ) { for ( i = 0; i < nFanoutsC; i++ ) if ( Gia_ObjEdgeCount(pFanouts[i], p->vEdge1, p->vEdge2) == nEdgeLimit ) break; if ( i == nFanoutsC ) { for ( i = 0; i < nFanoutsC; i++ ) { Count += Gia_ObjEdgeAdd( iObj, pFanouts[i], p->vEdge1, p->vEdge2 ); Count += Gia_ObjEdgeAdd( pFanouts[i], iObj, p->vEdge1, p->vEdge2 ); } if ( Count ) printf( "Wrong number of edges.\n" ); if ( fVerbose ) printf( "Fixed %d critical fanouts\n", nFanoutsC ); return 1; } } if ( fVerbose ) printf( "Cannot fix\n" ); return 0; } /**Function************************************************************* Synopsis [Finds edge assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Edg_ManAssignEdgeNew( Gia_Man_t * p, int nEdges, int fVerbose ) { int DelayNoEdge = 1; int fLevelVerbose = 0; Vec_Int_t * vLevel; Vec_Wec_t * vEdges = Vec_WecStart(0); Vec_Int_t * vEdge1 = NULL, * vEdge2 = NULL; int DelayD = 0, DelayR = 0, DelayPrev = ABC_INFINITY; int k, j, i, iLast = -1, iObj; if ( fVerbose ) printf( "Running edge assignment with E = %d.\n", nEdges ); // create fanouts Edg_ManToMapping( p ); // create empty assignment Vec_IntFreeP( &p->vEdge1 ); Vec_IntFreeP( &p->vEdge2 ); p->vEdge1 = Vec_IntStart( Gia_ManObjNum(p) ); p->vEdge2 = Vec_IntStart( Gia_ManObjNum(p) ); // perform optimization for ( i = 0; i < 10000; i++ ) { // if there is no improvement after 10 iterations, quit if ( i > iLast + 50 ) break; // create delay information DelayD = Edg_ManEvalEdgeDelay( p ); DelayR = Edg_ManEvalEdgeDelayR( p ); assert( DelayD == DelayR + DelayNoEdge ); if ( DelayPrev > DelayD ) { //printf( "Saving backup point at %d levels.\n", DelayD ); Vec_IntFreeP( &vEdge1 ); vEdge1 = Vec_IntDup( p->vEdge1 ); Vec_IntFreeP( &vEdge2 ); vEdge2 = Vec_IntDup( p->vEdge2 ); DelayPrev = DelayD; iLast = i; } if ( fVerbose ) printf( "\nIter %4d : Delay = %4d\n", i, DelayD ); // collect critical nodes (nodes with critical edges) Edg_ManCollectCritEdges( p, vEdges, DelayD ); // sort levels according to the number of critical edges if ( fLevelVerbose ) { Vec_WecForEachLevel( vEdges, vLevel, k ) Vec_IntPush( vLevel, k ); } Vec_WecSort( vEdges, 0 ); if ( fLevelVerbose ) { Vec_WecForEachLevel( vEdges, vLevel, k ) { int Level = Vec_IntPop( vLevel ); printf( "%d: Level %2d : ", k, Level ); Vec_IntPrint( vLevel ); } } Vec_WecForEachLevel( vEdges, vLevel, k ) { Vec_IntForEachEntry( vLevel, iObj, j ) if ( Edg_ObjImprove(p, iObj, nEdges, DelayD, fVerbose) ) // improved break; if ( j < Vec_IntSize(vLevel) ) break; } if ( k == Vec_WecSize(vEdges) ) // if we could not improve anything, quit break; } Vec_WecFree( vEdges ); // update to the saved version Vec_IntFreeP( &p->vEdge1 ); p->vEdge1 = vEdge1; Vec_IntFreeP( &p->vEdge2 ); p->vEdge2 = vEdge2; return DelayD; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaEmbed.c000066400000000000000000001720401477524141600161340ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaEmbed.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Logic network derived from AIG.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaEmbed.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "gia.h" #include "aig/ioa/ioa.h" ABC_NAMESPACE_IMPL_START /* The code is based on the paper by D. Harel and Y. Koren, "Graph drawing by high-dimensional embedding", J. Graph Algs & Apps, Vol 8(2), pp. 195-217 (2004). 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. http://www.eecs.umich.edu/~imarkov/pubs/conf/glsvlsi03-force.pdf */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define GIA_PLACE_SIZE 0x7fff // objects will be placed in box [0, GIA_PLACE_SIZE] x [0, GIA_PLACE_SIZE] typedef float Emb_Dat_t; typedef struct Emb_Obj_t_ Emb_Obj_t; struct Emb_Obj_t_ { unsigned fCi : 1; // terminal node CI unsigned fCo : 1; // terminal node CO unsigned fMark0 : 1; // first user-controlled mark unsigned fMark1 : 1; // second user-controlled mark unsigned nFanins : 28; // the number of fanins unsigned nFanouts; // the number of fanouts int hHandle; // the handle of the node union { unsigned TravId; // user-specified value unsigned iFanin; }; union { unsigned Value; // user-specified value unsigned iFanout; }; int Fanios[0]; // the array of fanins/fanouts }; typedef struct Emb_Man_t_ Emb_Man_t; struct Emb_Man_t_ { Gia_Man_t * pGia; // the original AIG manager Vec_Int_t * vCis; // the vector of CIs (PIs + LOs) Vec_Int_t * vCos; // the vector of COs (POs + LIs) int nObjs; // the number of objects int nRegs; // the number of registers int nTravIds; // traversal ID of the network int * pObjData; // the array containing data for objects int nObjData; // the size of array to store the logic network int fVerbose; // verbose output flag Emb_Dat_t * pVecs; // array of vectors of size nObjs * nDims int nReached; // the number of nodes reachable from the pivot int nDistMax; // the maximum distance from the node float ** pMatr; // covariance matrix nDims * nDims float ** pEigen; // the first several eigen values of the matrix float * pSols; // solutions to the problem nObjs * nSols; unsigned short*pPlacement; // (x,y) coordinates for each cell }; static inline int Emb_ManRegNum( Emb_Man_t * p ) { return p->nRegs; } static inline int Emb_ManCiNum( Emb_Man_t * p ) { return Vec_IntSize(p->vCis); } static inline int Emb_ManCoNum( Emb_Man_t * p ) { return Vec_IntSize(p->vCos); } static inline int Emb_ManPiNum( Emb_Man_t * p ) { return Vec_IntSize(p->vCis) - p->nRegs; } static inline int Emb_ManPoNum( Emb_Man_t * p ) { return Vec_IntSize(p->vCos) - p->nRegs; } static inline int Emb_ManObjNum( Emb_Man_t * p ) { return p->nObjs; } static inline int Emb_ManNodeNum( Emb_Man_t * p ) { return p->nObjs - Vec_IntSize(p->vCis) - Vec_IntSize(p->vCos); } static inline Emb_Obj_t * Emb_ManObj( Emb_Man_t * p, unsigned hHandle ) { return (Emb_Obj_t *)(p->pObjData + hHandle); } static inline Emb_Obj_t * Emb_ManCi( Emb_Man_t * p, int i ) { return Emb_ManObj( p, Vec_IntEntry(p->vCis,i) ); } static inline Emb_Obj_t * Emb_ManCo( Emb_Man_t * p, int i ) { return Emb_ManObj( p, Vec_IntEntry(p->vCos,i) ); } static inline int Emb_ObjIsTerm( Emb_Obj_t * pObj ) { return pObj->fCi || pObj->fCo; } static inline int Emb_ObjIsCi( Emb_Obj_t * pObj ) { return pObj->fCi; } static inline int Emb_ObjIsCo( Emb_Obj_t * pObj ) { return pObj->fCo; } //static inline int Emb_ObjIsPi( Emb_Obj_t * pObj ) { return pObj->fCi && pObj->nFanins == 0; } //static inline int Emb_ObjIsPo( Emb_Obj_t * pObj ) { return pObj->fCo && pObj->nFanouts == 0; } static inline int Emb_ObjIsNode( Emb_Obj_t * pObj ) { return!Emb_ObjIsTerm(pObj) && pObj->nFanins > 0; } //static inline int Emb_ObjIsConst0( Emb_Obj_t * pObj ) { return!Emb_ObjIsTerm(pObj) && pObj->nFanins == 0; } static inline int Emb_ObjSize( Emb_Obj_t * pObj ) { return sizeof(Emb_Obj_t) / 4 + pObj->nFanins + pObj->nFanouts; } static inline int Emb_ObjFaninNum( Emb_Obj_t * pObj ) { return pObj->nFanins; } static inline int Emb_ObjFanoutNum( Emb_Obj_t * pObj ) { return pObj->nFanouts; } static inline Emb_Obj_t * Emb_ObjFanin( Emb_Obj_t * pObj, int i ) { return (Emb_Obj_t *)(((int *)pObj) - pObj->Fanios[i]); } static inline Emb_Obj_t * Emb_ObjFanout( Emb_Obj_t * pObj, int i ) { return (Emb_Obj_t *)(((int *)pObj) + pObj->Fanios[pObj->nFanins+i]); } static inline void Emb_ManResetTravId( Emb_Man_t * p ) { extern void Emb_ManCleanTravId( Emb_Man_t * p ); Emb_ManCleanTravId( p ); p->nTravIds = 1; } static inline void Emb_ManIncrementTravId( Emb_Man_t * p ) { p->nTravIds++; } static inline void Emb_ObjSetTravId( Emb_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } static inline void Emb_ObjSetTravIdCurrent( Emb_Man_t * p, Emb_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } static inline void Emb_ObjSetTravIdPrevious( Emb_Man_t * p, Emb_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1; } static inline int Emb_ObjIsTravIdCurrent( Emb_Man_t * p, Emb_Obj_t * pObj ) { return ((int)pObj->TravId == p->nTravIds); } static inline int Emb_ObjIsTravIdPrevious( Emb_Man_t * p, Emb_Obj_t * pObj ) { return ((int)pObj->TravId == p->nTravIds - 1); } static inline Emb_Dat_t * Emb_ManVec( Emb_Man_t * p, int v ) { return p->pVecs + v * p->nObjs; } static inline float * Emb_ManSol( Emb_Man_t * p, int v ) { return p->pSols + v * p->nObjs; } #define Emb_ManForEachObj( p, pObj, i ) \ for ( i = 0; (i < p->nObjData) && (pObj = Emb_ManObj(p,i)); i += Emb_ObjSize(pObj) ) #define Emb_ManForEachNode( p, pObj, i ) \ for ( i = 0; (i < p->nObjData) && (pObj = Emb_ManObj(p,i)); i += Emb_ObjSize(pObj) ) if ( Emb_ObjIsTerm(pObj) ) {} else #define Emb_ManForEachObjVec( vVec, p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Emb_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) #define Emb_ObjForEachFanin( pObj, pNext, i ) \ for ( i = 0; (i < (int)pObj->nFanins) && (pNext = Emb_ObjFanin(pObj,i)); i++ ) #define Emb_ObjForEachFanout( pObj, pNext, i ) \ for ( i = 0; (i < (int)pObj->nFanouts) && (pNext = Emb_ObjFanout(pObj,i)); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates fanin/fanout pair.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ObjAddFanin( Emb_Obj_t * pObj, Emb_Obj_t * pFanin ) { assert( pObj->iFanin < pObj->nFanins ); assert( pFanin->iFanout < pFanin->nFanouts ); pFanin->Fanios[pFanin->nFanins + pFanin->iFanout++] = pObj->Fanios[pObj->iFanin++] = pObj->hHandle - pFanin->hHandle; } /**Function************************************************************* Synopsis [Creates logic network isomorphic to the given AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Emb_Man_t * Emb_ManStartSimple( Gia_Man_t * pGia ) { Emb_Man_t * p; Emb_Obj_t * pObjLog, * pFanLog; Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i, nNodes, hHandle = 0; // prepare the AIG Gia_ManCreateRefs( pGia ); // create logic network p = ABC_CALLOC( Emb_Man_t, 1 ); p->pGia = pGia; p->nRegs = Gia_ManRegNum(pGia); p->vCis = Vec_IntAlloc( Gia_ManCiNum(pGia) ); p->vCos = Vec_IntAlloc( Gia_ManCoNum(pGia) ); p->nObjData = (sizeof(Emb_Obj_t) / 4) * Gia_ManObjNum(pGia) + 2 * (2 * Gia_ManAndNum(pGia) + Gia_ManCoNum(pGia) + Gia_ManRegNum(pGia) + Gia_ManCoNum(pGia)); p->pObjData = ABC_CALLOC( int, p->nObjData ); // create constant node Gia_ManConst0(pGia)->Value = hHandle; pObjLog = Emb_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = Gia_ManCoNum(pGia); //0; pObjLog->nFanouts = Gia_ObjRefNum( pGia, Gia_ManConst0(pGia) ); // count objects hHandle += Emb_ObjSize( pObjLog ); nNodes = 1; p->nObjs++; // create the PIs Gia_ManForEachCi( pGia, pObj, i ) { // create PI object pObj->Value = hHandle; Vec_IntPush( p->vCis, hHandle ); pObjLog = Emb_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = Gia_ObjIsRo( pGia, pObj ); pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); pObjLog->fCi = 1; // count objects hHandle += Emb_ObjSize( pObjLog ); p->nObjs++; } // create internal nodes Gia_ManForEachAnd( pGia, pObj, i ) { assert( Gia_ObjRefNum( pGia, pObj ) > 0 ); // create node object pObj->Value = hHandle; pObjLog = Emb_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = 2; pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); // add fanins pFanLog = Emb_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); Emb_ObjAddFanin( pObjLog, pFanLog ); pFanLog = Emb_ManObj( p, Gia_ObjValue(Gia_ObjFanin1(pObj)) ); Emb_ObjAddFanin( pObjLog, pFanLog ); // count objects hHandle += Emb_ObjSize( pObjLog ); nNodes++; p->nObjs++; } // create the POs Gia_ManForEachCo( pGia, pObj, i ) { // create PO object pObj->Value = hHandle; Vec_IntPush( p->vCos, hHandle ); pObjLog = Emb_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = 1; pObjLog->nFanouts = 1 + Gia_ObjIsRi( pGia, pObj ); pObjLog->fCo = 1; // add fanins pFanLog = Emb_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); Emb_ObjAddFanin( pObjLog, pFanLog ); // count objects hHandle += Emb_ObjSize( pObjLog ); p->nObjs++; } // connect registers Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, i ) Emb_ObjAddFanin( Emb_ManObj(p,Gia_ObjValue(pObjRo)), Emb_ManObj(p,Gia_ObjValue(pObjRi)) ); assert( nNodes == Emb_ManNodeNum(p) ); assert( hHandle == p->nObjData ); assert( p->nObjs == Gia_ManObjNum(pGia) ); if ( hHandle != p->nObjData ) printf( "Emb_ManStartSimple(): Fatal error in internal representation.\n" ); // make sure the fanin/fanout counters are correct Gia_ManForEachObj( pGia, pObj, i ) { if ( !~Gia_ObjValue(pObj) ) continue; pObjLog = Emb_ManObj( p, Gia_ObjValue(pObj) ); assert( pObjLog->nFanins == pObjLog->iFanin || Gia_ObjIsConst0(pObj) ); assert( pObjLog->nFanouts == pObjLog->iFanout || Gia_ObjIsCo(pObj) ); pObjLog->iFanin = pObjLog->iFanout = 0; } ABC_FREE( pGia->pRefs ); return p; } /**Function************************************************************* Synopsis [Collect the fanin IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManCollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, Vec_Int_t * vVisit ) { if ( pObj->fMark1 ) return; pObj->fMark1 = 1; Vec_IntPush( vVisit, Gia_ObjId(p, pObj) ); if ( pObj->fMark0 ) { Vec_IntPush( vSuper, Gia_ObjId(p, pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); Emb_ManCollectSuper_rec( p, Gia_ObjFanin0(pObj), vSuper, vVisit ); Emb_ManCollectSuper_rec( p, Gia_ObjFanin1(pObj), vSuper, vVisit ); } /**Function************************************************************* Synopsis [Collect the fanin IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, Vec_Int_t * vVisit ) { int Entry, i; Vec_IntClear( vSuper ); Vec_IntClear( vVisit ); assert( pObj->fMark0 == 1 ); pObj->fMark0 = 0; Emb_ManCollectSuper_rec( p, pObj, vSuper, vVisit ); pObj->fMark0 = 1; Vec_IntForEachEntry( vVisit, Entry, i ) Gia_ManObj(p, Entry)->fMark1 = 0; } /**Function************************************************************* Synopsis [Assigns references while removing the MUX/XOR ones.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManCreateRefsSpecial( Gia_Man_t * p ) { Gia_Obj_t * pObj, * pFan0, * pFan1; Gia_Obj_t * pObjC, * pObjD0, * pObjD1; int i; assert( p->pRefs == NULL ); Gia_ManCleanMark0( p ); Gia_ManCreateRefs( p ); Gia_ManForEachAnd( p, pObj, i ) { assert( pObj->fMark0 == 0 ); pFan0 = Gia_ObjFanin0(pObj); pFan1 = Gia_ObjFanin1(pObj); // skip nodes whose fanins are PIs or are already marked if ( Gia_ObjIsCi(pFan0) || pFan0->fMark0 || Gia_ObjIsCi(pFan1) || pFan1->fMark0 ) continue; // skip nodes that are not MUX type if ( !Gia_ObjIsMuxType(pObj) ) continue; // the node is MUX type, mark it and its fanins pObj->fMark0 = 1; pFan0->fMark0 = 1; pFan1->fMark0 = 1; // deref the control pObjC = Gia_ObjRecognizeMux( pObj, &pObjD1, &pObjD0 ); Gia_ObjRefDec( p, Gia_Regular(pObjC) ); if ( Gia_Regular(pObjD0) == Gia_Regular(pObjD1) ) Gia_ObjRefDec( p, Gia_Regular(pObjD0) ); } Gia_ManForEachAnd( p, pObj, i ) assert( Gia_ObjRefNum(p, pObj) > 0 ); Gia_ManCleanMark0( p ); } /**Function************************************************************* Synopsis [Assigns references while removing the MUX/XOR ones.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManTransformRefs( Gia_Man_t * p, int * pnObjs, int * pnFanios ) { Vec_Int_t * vSuper, * vVisit; Gia_Obj_t * pObj, * pFanin; int i, k, Counter; assert( p->pRefs != NULL ); // mark nodes to be used in the logic network Gia_ManCleanMark0( p ); Gia_ManConst0(p)->fMark0 = 1; // mark the inputs Gia_ManForEachCi( p, pObj, i ) pObj->fMark0 = 1; // mark those nodes that have ref count more than 1 Gia_ManForEachAnd( p, pObj, i ) pObj->fMark0 = (Gia_ObjRefNum(p, pObj) > 1); // mark the output drivers Gia_ManForEachCoDriver( p, pObj, i ) pObj->fMark0 = 1; // count the number of nodes Counter = 0; Gia_ManForEachObj( p, pObj, i ) Counter += pObj->fMark0; *pnObjs = Counter + Gia_ManCoNum(p); // reset the references ABC_FREE( p->pRefs ); p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); // reference from internal nodes Counter = 0; vSuper = Vec_IntAlloc( 100 ); vVisit = Vec_IntAlloc( 100 ); Gia_ManCleanMark1( p ); Gia_ManForEachAnd( p, pObj, i ) { if ( pObj->fMark0 == 0 ) continue; Emb_ManCollectSuper( p, pObj, vSuper, vVisit ); Gia_ManForEachObjVec( vSuper, p, pFanin, k ) { assert( pFanin->fMark0 ); Gia_ObjRefInc( p, pFanin ); } Counter += Vec_IntSize( vSuper ); } Gia_ManCheckMark1( p ); Vec_IntFree( vSuper ); Vec_IntFree( vVisit ); // reference from outputs Gia_ManForEachCoDriver( p, pObj, i ) { assert( pObj->fMark0 ); Gia_ObjRefInc( p, pObj ); } *pnFanios = Counter + Gia_ManCoNum(p); } /**Function************************************************************* Synopsis [Cleans the value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManCleanTravId( Emb_Man_t * p ) { Emb_Obj_t * pObj; int i; Emb_ManForEachObj( p, pObj, i ) pObj->TravId = 0; } /**Function************************************************************* Synopsis [Cleans the value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManSetValue( Emb_Man_t * p ) { Emb_Obj_t * pObj; int i, Counter = 0; Emb_ManForEachObj( p, pObj, i ) { pObj->Value = Counter++; // if ( pObj->fCi && pObj->nFanins == 0 ) // printf( "CI: Handle = %8d. Value = %6d. Fanins = %d.\n", pObj->hHandle, pObj->Value, pObj->nFanins ); } } /**Function************************************************************* Synopsis [Creates logic network isomorphic to the given AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Emb_Man_t * Emb_ManStart( Gia_Man_t * pGia ) { Emb_Man_t * p; Emb_Obj_t * pObjLog, * pFanLog; Gia_Obj_t * pObj, * pObjRi, * pObjRo, * pFanin; Vec_Int_t * vSuper, * vVisit; int nObjs, nFanios, nNodes = 0; int i, k, hHandle = 0; // prepare the AIG // Gia_ManCreateRefs( pGia ); Emb_ManCreateRefsSpecial( pGia ); Emb_ManTransformRefs( pGia, &nObjs, &nFanios ); Gia_ManFillValue( pGia ); // create logic network p = ABC_CALLOC( Emb_Man_t, 1 ); p->pGia = pGia; p->nRegs = Gia_ManRegNum(pGia); p->vCis = Vec_IntAlloc( Gia_ManCiNum(pGia) ); p->vCos = Vec_IntAlloc( Gia_ManCoNum(pGia) ); p->nObjData = (sizeof(Emb_Obj_t) / 4) * nObjs + 2 * (nFanios + Gia_ManRegNum(pGia) + Gia_ManCoNum(pGia)); p->pObjData = ABC_CALLOC( int, p->nObjData ); // create constant node Gia_ManConst0(pGia)->Value = hHandle; pObjLog = Emb_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = Gia_ManCoNum(pGia); //0; pObjLog->nFanouts = Gia_ObjRefNum( pGia, Gia_ManConst0(pGia) ); // count objects hHandle += Emb_ObjSize( pObjLog ); nNodes++; p->nObjs++; // create the PIs Gia_ManForEachCi( pGia, pObj, i ) { // create PI object pObj->Value = hHandle; Vec_IntPush( p->vCis, hHandle ); pObjLog = Emb_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = Gia_ObjIsRo( pGia, pObj ); pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); pObjLog->fCi = 1; // count objects hHandle += Emb_ObjSize( pObjLog ); p->nObjs++; } // create internal nodes vSuper = Vec_IntAlloc( 100 ); vVisit = Vec_IntAlloc( 100 ); Gia_ManForEachAnd( pGia, pObj, i ) { if ( pObj->fMark0 == 0 ) { assert( Gia_ObjRefNum( pGia, pObj ) == 0 ); continue; } assert( Gia_ObjRefNum( pGia, pObj ) > 0 ); Emb_ManCollectSuper( pGia, pObj, vSuper, vVisit ); // create node object pObj->Value = hHandle; pObjLog = Emb_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = Vec_IntSize( vSuper ); pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); // add fanins Gia_ManForEachObjVec( vSuper, pGia, pFanin, k ) { pFanLog = Emb_ManObj( p, Gia_ObjValue(pFanin) ); Emb_ObjAddFanin( pObjLog, pFanLog ); } // count objects hHandle += Emb_ObjSize( pObjLog ); nNodes++; p->nObjs++; } Vec_IntFree( vSuper ); Vec_IntFree( vVisit ); // create the POs Gia_ManForEachCo( pGia, pObj, i ) { // create PO object pObj->Value = hHandle; Vec_IntPush( p->vCos, hHandle ); pObjLog = Emb_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = 1; pObjLog->nFanouts = 1 + Gia_ObjIsRi( pGia, pObj ); pObjLog->fCo = 1; // add fanins pFanLog = Emb_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); Emb_ObjAddFanin( pObjLog, pFanLog ); // count objects hHandle += Emb_ObjSize( pObjLog ); p->nObjs++; } // connect registers Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, i ) Emb_ObjAddFanin( Emb_ManObj(p,Gia_ObjValue(pObjRo)), Emb_ManObj(p,Gia_ObjValue(pObjRi)) ); Gia_ManCleanMark0( pGia ); assert( nNodes == Emb_ManNodeNum(p) ); assert( nObjs == p->nObjs ); assert( hHandle == p->nObjData ); if ( hHandle != p->nObjData ) printf( "Emb_ManStart(): Fatal error in internal representation.\n" ); // make sure the fanin/fanout counters are correct Gia_ManForEachObj( pGia, pObj, i ) { if ( !~Gia_ObjValue(pObj) ) continue; pObjLog = Emb_ManObj( p, Gia_ObjValue(pObj) ); assert( pObjLog->nFanins == pObjLog->iFanin || Gia_ObjIsConst0(pObj) ); assert( pObjLog->nFanouts == pObjLog->iFanout || Gia_ObjIsCo(pObj) ); pObjLog->iFanin = pObjLog->iFanout = 0; } ABC_FREE( pGia->pRefs ); return p; } /**Function************************************************************* Synopsis [Creates logic network isomorphic to the given AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManPrintStats( Emb_Man_t * p ) { // if ( p->pName ) // printf( "%8s : ", p->pName ); printf( "i/o =%7d/%7d ", Emb_ManPiNum(p), Emb_ManPoNum(p) ); if ( Emb_ManRegNum(p) ) printf( "ff =%7d ", Emb_ManRegNum(p) ); printf( "node =%8d ", Emb_ManNodeNum(p) ); printf( "obj =%8d ", Emb_ManObjNum(p) ); // printf( "lev =%5d ", Emb_ManLevelNum(p) ); // printf( "cut =%5d ", Emb_ManCrossCut(p) ); printf( "mem =%5.2f MB", 4.0*p->nObjData/(1<<20) ); // printf( "obj =%5d ", Emb_ManObjNum(p) ); printf( "\n" ); // Emb_ManSatExperiment( p ); } /**Function************************************************************* Synopsis [Creates logic network isomorphic to the given AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManStop( Emb_Man_t * p ) { Vec_IntFree( p->vCis ); Vec_IntFree( p->vCos ); ABC_FREE( p->pPlacement ); ABC_FREE( p->pVecs ); ABC_FREE( p->pSols ); ABC_FREE( p->pMatr ); ABC_FREE( p->pEigen ); ABC_FREE( p->pObjData ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints the distribution of fanins/fanouts in the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManPrintFanio( Emb_Man_t * p ) { char Buffer[100]; Emb_Obj_t * pNode; Vec_Int_t * vFanins, * vFanouts; int nFanins, nFanouts, nFaninsMax, nFanoutsMax, nFaninsAll, nFanoutsAll; int i, k, nSizeMax; // determine the largest fanin and fanout nFaninsMax = nFanoutsMax = 0; nFaninsAll = nFanoutsAll = 0; Emb_ManForEachNode( p, pNode, i ) { if ( i == 0 ) continue; // skip const 0 obj nFanins = Emb_ObjFaninNum(pNode); nFanouts = Emb_ObjFanoutNum(pNode); nFaninsAll += nFanins; nFanoutsAll += nFanouts; nFaninsMax = Abc_MaxInt( nFaninsMax, nFanins ); nFanoutsMax = Abc_MaxInt( nFanoutsMax, nFanouts ); } // allocate storage for fanin/fanout numbers nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nFaninsMax) + 1), 10 * (Abc_Base10Log(nFanoutsMax) + 1) ); vFanins = Vec_IntStart( nSizeMax ); vFanouts = Vec_IntStart( nSizeMax ); // count the number of fanins and fanouts Emb_ManForEachNode( p, pNode, i ) { if ( i == 0 ) continue; // skip const 0 obj nFanins = Emb_ObjFaninNum(pNode); nFanouts = Emb_ObjFanoutNum(pNode); if ( nFanins < 10 ) Vec_IntAddToEntry( vFanins, nFanins, 1 ); else if ( nFanins < 100 ) Vec_IntAddToEntry( vFanins, 10 + nFanins/10, 1 ); else if ( nFanins < 1000 ) Vec_IntAddToEntry( vFanins, 20 + nFanins/100, 1 ); else if ( nFanins < 10000 ) Vec_IntAddToEntry( vFanins, 30 + nFanins/1000, 1 ); else if ( nFanins < 100000 ) Vec_IntAddToEntry( vFanins, 40 + nFanins/10000, 1 ); else if ( nFanins < 1000000 ) Vec_IntAddToEntry( vFanins, 50 + nFanins/100000, 1 ); else if ( nFanins < 10000000 ) Vec_IntAddToEntry( vFanins, 60 + nFanins/1000000, 1 ); if ( nFanouts < 10 ) Vec_IntAddToEntry( vFanouts, nFanouts, 1 ); else if ( nFanouts < 100 ) Vec_IntAddToEntry( vFanouts, 10 + nFanouts/10, 1 ); else if ( nFanouts < 1000 ) Vec_IntAddToEntry( vFanouts, 20 + nFanouts/100, 1 ); else if ( nFanouts < 10000 ) Vec_IntAddToEntry( vFanouts, 30 + nFanouts/1000, 1 ); else if ( nFanouts < 100000 ) Vec_IntAddToEntry( vFanouts, 40 + nFanouts/10000, 1 ); else if ( nFanouts < 1000000 ) Vec_IntAddToEntry( vFanouts, 50 + nFanouts/100000, 1 ); else if ( nFanouts < 10000000 ) Vec_IntAddToEntry( vFanouts, 60 + nFanouts/1000000, 1 ); } printf( "The distribution of fanins and fanouts in the network:\n" ); printf( " Number Nodes with fanin Nodes with fanout\n" ); for ( k = 0; k < nSizeMax; k++ ) { if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 ) continue; if ( k < 10 ) printf( "%15d : ", k ); else { sprintf( Buffer, "%d - %d", (int)pow((double)10, k/10) * (k%10), (int)pow((double)10, k/10) * (k%10+1) - 1 ); printf( "%15s : ", Buffer ); } if ( vFanins->pArray[k] == 0 ) printf( " " ); else printf( "%12d ", vFanins->pArray[k] ); printf( " " ); if ( vFanouts->pArray[k] == 0 ) printf( " " ); else printf( "%12d ", vFanouts->pArray[k] ); printf( "\n" ); } Vec_IntFree( vFanins ); Vec_IntFree( vFanouts ); printf( "Fanins: Max = %d. Ave = %.2f. Fanouts: Max = %d. Ave = %.2f.\n", nFaninsMax, 1.0*nFaninsAll/Emb_ManNodeNum(p), nFanoutsMax, 1.0*nFanoutsAll/Emb_ManNodeNum(p) ); } /**Function************************************************************* Synopsis [Computes the distance from the given object] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Emb_ManComputeDistance_old( Emb_Man_t * p, Emb_Obj_t * pPivot ) { Vec_Int_t * vThis, * vNext, * vTemp; Emb_Obj_t * pThis, * pNext; int i, k, d, nVisited = 0; // assert( Emb_ObjIsTerm(pPivot) ); vThis = Vec_IntAlloc( 1000 ); vNext = Vec_IntAlloc( 1000 ); Emb_ManIncrementTravId( p ); Emb_ObjSetTravIdCurrent( p, pPivot ); Vec_IntPush( vThis, pPivot->hHandle ); for ( d = 0; Vec_IntSize(vThis) > 0; d++ ) { nVisited += Vec_IntSize(vThis); Vec_IntClear( vNext ); Emb_ManForEachObjVec( vThis, p, pThis, i ) { Emb_ObjForEachFanin( pThis, pNext, k ) { if ( Emb_ObjIsTravIdCurrent(p, pNext) ) continue; Emb_ObjSetTravIdCurrent(p, pNext); Vec_IntPush( vNext, pNext->hHandle ); nVisited += !Emb_ObjIsTerm(pNext); } Emb_ObjForEachFanout( pThis, pNext, k ) { if ( Emb_ObjIsTravIdCurrent(p, pNext) ) continue; Emb_ObjSetTravIdCurrent(p, pNext); Vec_IntPush( vNext, pNext->hHandle ); nVisited += !Emb_ObjIsTerm(pNext); } } vTemp = vThis; vThis = vNext; vNext = vTemp; } Vec_IntFree( vThis ); Vec_IntFree( vNext ); // check if there are several strongly connected components // if ( nVisited < Emb_ManNodeNum(p) ) // printf( "Visited less nodes (%d) than present (%d).\n", nVisited, Emb_ManNodeNum(p) ); return d; } /**Function************************************************************* Synopsis [Traverses from the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManTestDistanceInternal( Emb_Man_t * p ) { int nAttempts = 20; int i, iNode, Dist; abctime clk; Emb_Obj_t * pPivot, * pNext; Gia_ManRandom( 1 ); Emb_ManResetTravId( p ); // compute distances from several randomly selected PIs clk = Abc_Clock(); printf( "From inputs: " ); for ( i = 0; i < nAttempts; i++ ) { iNode = Gia_ManRandom( 0 ) % Emb_ManCiNum(p); pPivot = Emb_ManCi( p, iNode ); if ( Emb_ObjFanoutNum(pPivot) == 0 ) { i--; continue; } pNext = Emb_ObjFanout( pPivot, 0 ); if ( !Emb_ObjIsNode(pNext) ) { i--; continue; } Dist = Emb_ManComputeDistance_old( p, pPivot ); printf( "%d ", Dist ); } ABC_PRT( "Time", Abc_Clock() - clk ); // compute distances from several randomly selected POs clk = Abc_Clock(); printf( "From outputs: " ); for ( i = 0; i < nAttempts; i++ ) { iNode = Gia_ManRandom( 0 ) % Emb_ManCoNum(p); pPivot = Emb_ManCo( p, iNode ); pNext = Emb_ObjFanin( pPivot, 0 ); if ( !Emb_ObjIsNode(pNext) ) { i--; continue; } Dist = Emb_ManComputeDistance_old( p, pPivot ); printf( "%d ", Dist ); } ABC_PRT( "Time", Abc_Clock() - clk ); // compute distances from several randomly selected nodes clk = Abc_Clock(); printf( "From nodes: " ); for ( i = 0; i < nAttempts; i++ ) { iNode = Gia_ManRandom( 0 ) % Gia_ManObjNum(p->pGia); if ( !~Gia_ManObj(p->pGia, iNode)->Value ) { i--; continue; } pPivot = Emb_ManObj( p, Gia_ManObj(p->pGia, iNode)->Value ); if ( !Emb_ObjIsNode(pPivot) ) { i--; continue; } Dist = Emb_ManComputeDistance_old( p, pPivot ); printf( "%d ", Dist ); } ABC_PRT( "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Returns sorted array of node handles with largest fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManTestDistance( Gia_Man_t * pGia ) { Emb_Man_t * p; abctime clk = Abc_Clock(); p = Emb_ManStart( pGia ); // Emb_ManPrintFanio( p ); Emb_ManPrintStats( p ); ABC_PRT( "Time", Abc_Clock() - clk ); Gia_ManTestDistanceInternal( p ); Emb_ManStop( p ); } /**Function************************************************************* Synopsis [Perform BFS from the set of nodes.] Description [Returns one of the most distant objects.] SideEffects [] SeeAlso [] ***********************************************************************/ Emb_Obj_t * Emb_ManPerformBfs( Emb_Man_t * p, Vec_Int_t * vThis, Vec_Int_t * vNext, Emb_Dat_t * pDist ) { Vec_Int_t * vTemp; Emb_Obj_t * pThis, * pNext, * pResult; int i, k; assert( Vec_IntSize(vThis) > 0 ); for ( p->nDistMax = 0; Vec_IntSize(vThis) > 0; p->nDistMax++ ) { p->nReached += Vec_IntSize(vThis); Vec_IntClear( vNext ); Emb_ManForEachObjVec( vThis, p, pThis, i ) { if ( pDist ) pDist[pThis->Value] = p->nDistMax; Emb_ObjForEachFanin( pThis, pNext, k ) { if ( Emb_ObjIsTravIdCurrent(p, pNext) ) continue; Emb_ObjSetTravIdCurrent(p, pNext); Vec_IntPush( vNext, pNext->hHandle ); } Emb_ObjForEachFanout( pThis, pNext, k ) { if ( Emb_ObjIsTravIdCurrent(p, pNext) ) continue; Emb_ObjSetTravIdCurrent(p, pNext); Vec_IntPush( vNext, pNext->hHandle ); } } vTemp = vThis; vThis = vNext; vNext = vTemp; } assert( Vec_IntSize(vNext) > 0 ); pResult = Emb_ManObj( p, Vec_IntEntry(vNext, 0) ); assert( pDist == NULL || pDist[pResult->Value] == p->nDistMax - 1 ); return pResult; } /**Function************************************************************* Synopsis [Computes the distances from the given set of objects.] Description [Returns one of the most distant objects.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Emb_ManConnectedComponents( Emb_Man_t * p ) { Gia_Obj_t * pObj; Vec_Int_t * vThis, * vNext, * vResult; Emb_Obj_t * pThis; int i; vResult = Vec_IntAlloc( 1000 ); vThis = Vec_IntAlloc( 1000 ); vNext = Vec_IntAlloc( 1000 ); p->nReached = 0; Emb_ManIncrementTravId( p ); Gia_ManForEachCo( p->pGia, pObj, i ) { pThis = Emb_ManObj( p, Gia_ObjValue(pObj) ); if ( Emb_ObjIsTravIdCurrent(p, pThis) ) continue; Emb_ObjSetTravIdCurrent( p, pThis ); Vec_IntPush( vResult, pThis->hHandle ); // perform BFS from this node Vec_IntClear( vThis ); Vec_IntPush( vThis, pThis->hHandle ); Emb_ManPerformBfs( p, vThis, vNext, NULL ); } Vec_IntFree( vThis ); Vec_IntFree( vNext ); return vResult; } /**Function************************************************************* Synopsis [Computes the distances from the given set of objects.] Description [Returns one of the most distant objects.] SideEffects [] SeeAlso [] ***********************************************************************/ Emb_Obj_t * Emb_ManFindDistances( Emb_Man_t * p, Vec_Int_t * vStart, Emb_Dat_t * pDist ) { Vec_Int_t * vThis, * vNext; Emb_Obj_t * pThis, * pResult; int i; p->nReached = p->nDistMax = 0; vThis = Vec_IntAlloc( 1000 ); vNext = Vec_IntAlloc( 1000 ); Emb_ManIncrementTravId( p ); Emb_ManForEachObjVec( vStart, p, pThis, i ) { Emb_ObjSetTravIdCurrent( p, pThis ); Vec_IntPush( vThis, pThis->hHandle ); } pResult = Emb_ManPerformBfs( p, vThis, vNext, pDist ); Vec_IntFree( vThis ); Vec_IntFree( vNext ); return pResult; } /**Function************************************************************* Synopsis [Traverses from the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Emb_Obj_t * Emb_ManRandomVertex( Emb_Man_t * p ) { Emb_Obj_t * pPivot; do { int iNode = (911 * Gia_ManRandom(0)) % Gia_ManObjNum(p->pGia); if ( ~Gia_ManObj(p->pGia, iNode)->Value ) pPivot = Emb_ManObj( p, Gia_ManObj(p->pGia, iNode)->Value ); else pPivot = NULL; } while ( pPivot == NULL || !Emb_ObjIsNode(pPivot) ); return pPivot; } /**Function************************************************************* Synopsis [Computes the distances from the given set of objects.] Description [Returns one of the most distant objects.] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_DumpGraphIntoFile( Emb_Man_t * p ) { FILE * pFile; Emb_Obj_t * pThis, * pNext; int i, k; pFile = fopen( "1.g", "w" ); Emb_ManForEachObj( p, pThis, i ) { if ( !Emb_ObjIsTravIdCurrent(p, pThis) ) continue; Emb_ObjForEachFanout( pThis, pNext, k ) { assert( Emb_ObjIsTravIdCurrent(p, pNext) ); fprintf( pFile, "%d %d\n", pThis->Value, pNext->Value ); } } fclose( pFile ); } /**Function************************************************************* Synopsis [Computes dimentions of the graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManComputeDimensions( Emb_Man_t * p, int nDims ) { Emb_Obj_t * pRandom, * pPivot; Vec_Int_t * vStart, * vComps; int d, nReached; int i;//, Counter; // connect unconnected components vComps = Emb_ManConnectedComponents( p ); // printf( "Components = %d. Considered %d objects (out of %d).\n", Vec_IntSize(vComps), p->nReached, Emb_ManObjNum(p) ); if ( Vec_IntSize(vComps) > 1 ) { Emb_Obj_t * pFanin, * pObj = Emb_ManObj( p, 0 ); Emb_ManForEachObjVec( vComps, p, pFanin, i ) { assert( Emb_ObjIsCo(pFanin) ); pFanin->Fanios[pFanin->nFanins + pFanin->nFanouts-1] = pObj->Fanios[i] = pObj->hHandle - pFanin->hHandle; } } Vec_IntFree( vComps ); // allocate memory for vectors assert( p->pVecs == NULL ); p->pVecs = ABC_CALLOC( Emb_Dat_t, p->nObjs * nDims ); // for ( i = 0; i < p->nObjs * nDims; i++ ) // p->pVecs[i] = ABC_INFINITY; vStart = Vec_IntAlloc( nDims ); // get the pivot vertex pRandom = Emb_ManRandomVertex( p ); Vec_IntPush( vStart, pRandom->hHandle ); // get the most distant vertex from the pivot pPivot = Emb_ManFindDistances( p, vStart, NULL ); // Emb_DumpGraphIntoFile( p ); nReached = p->nReached; if ( nReached < Emb_ManObjNum(p) ) { // printf( "Considering a connected component with %d objects (out of %d).\n", p->nReached, Emb_ManObjNum(p) ); } // start dimensions with this vertex Vec_IntClear( vStart ); for ( d = 0; d < nDims; d++ ) { // printf( "%3d : Adding vertex %7d with distance %3d.\n", d+1, pPivot->Value, p->nDistMax ); Vec_IntPush( vStart, pPivot->hHandle ); if ( d+1 == nReached ) break; pPivot = Emb_ManFindDistances( p, vStart, Emb_ManVec(p, d) ); assert( nReached == p->nReached ); } Vec_IntFree( vStart ); // make sure the number of reached objects is correct // Counter = 0; // for ( i = 0; i < p->nObjs; i++ ) // if ( p->pVecs[i] < ABC_INFINITY ) // Counter++; // assert( Counter == nReached ); } /**Function************************************************************* Synopsis [Allocated square matrix of floats.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float ** Emb_ManMatrAlloc( int nDims ) { int i; float ** pMatr = (float **)ABC_ALLOC( char, sizeof(float *) * nDims + sizeof(float) * nDims * nDims ); pMatr[0] = (float *)(pMatr + nDims); for ( i = 1; i < nDims; i++ ) pMatr[i] = pMatr[i-1] + nDims; return pMatr; } /**Function************************************************************* Synopsis [Computes covariance matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManComputeCovariance( Emb_Man_t * p, int nDims ) { Emb_Dat_t * pOne, * pTwo; double Ave; float * pRow; int d, i, k, v; // average vectors for ( d = 0; d < nDims; d++ ) { // compute average Ave = 0.0; pOne = Emb_ManVec( p, d ); for ( v = 0; v < p->nObjs; v++ ) if ( pOne[v] < ABC_INFINITY ) Ave += pOne[v]; Ave /= p->nReached; // update the vector for ( v = 0; v < p->nObjs; v++ ) if ( pOne[v] < ABC_INFINITY ) pOne[v] -= Ave; else pOne[v] = 0.0; } // compute the matrix assert( p->pMatr == NULL ); assert( p->pEigen == NULL ); p->pMatr = Emb_ManMatrAlloc( nDims ); p->pEigen = Emb_ManMatrAlloc( nDims ); for ( i = 0; i < nDims; i++ ) { pOne = Emb_ManVec( p, i ); pRow = p->pMatr[i]; for ( k = 0; k < nDims; k++ ) { pTwo = Emb_ManVec( p, k ); pRow[k] = 0.0; for ( v = 0; v < p->nObjs; v++ ) pRow[k] += pOne[v]*pTwo[v]; } } } /**Function************************************************************* Synopsis [Returns random vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManVecRandom( float * pVec, int nDims ) { int i; for ( i = 0; i < nDims; i++ ) pVec[i] = Gia_ManRandom( 0 ); } /**Function************************************************************* Synopsis [Returns normalized vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManVecNormal( float * pVec, int nDims ) { int i; double Norm = 0.0; for ( i = 0; i < nDims; i++ ) Norm += pVec[i] * pVec[i]; Norm = pow( Norm, 0.5 ); for ( i = 0; i < nDims; i++ ) pVec[i] /= Norm; } /**Function************************************************************* Synopsis [Multiplies vector by vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Emb_ManVecMultiplyOne( float * pVec0, float * pVec1, int nDims ) { float Res = 0.0; int i; for ( i = 0; i < nDims; i++ ) Res += pVec0[i] * pVec1[i]; return Res; } /**Function************************************************************* Synopsis [Copies the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManVecCopyOne( float * pVecDest, float * pVecSour, int nDims ) { int i; for ( i = 0; i < nDims; i++ ) pVecDest[i] = pVecSour[i]; } /**Function************************************************************* Synopsis [Multiplies matrix by vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManVecMultiply( float ** pMatr, float * pVec, int nDims, float * pRes ) { int k; for ( k = 0; k < nDims; k++ ) pRes[k] = Emb_ManVecMultiplyOne( pMatr[k], pVec, nDims ); } /**Function************************************************************* Synopsis [Multiplies vector by matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManVecOrthogonolizeOne( float * pEigen, float * pVecI, int nDims, float * pVecRes ) { int k; for ( k = 0; k < nDims; k++ ) pVecRes[k] = pVecI[k] - pEigen[k] * Emb_ManVecMultiplyOne( pVecI, pEigen, nDims ); } /**Function************************************************************* Synopsis [Computes the first nSols eigen-vectors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManComputeEigenvectors( Emb_Man_t * p, int nDims, int nSols ) { float * pVecUiHat, * pVecUi; int i, j, k; assert( nSols < nDims ); pVecUiHat = p->pEigen[nSols]; for ( i = 0; i < nSols; i++ ) { pVecUi = p->pEigen[i]; Emb_ManVecRandom( pVecUiHat, nDims ); Emb_ManVecNormal( pVecUiHat, nDims ); k = 0; do { k++; Emb_ManVecCopyOne( pVecUi, pVecUiHat, nDims ); for ( j = 0; j < i; j++ ) { Emb_ManVecOrthogonolizeOne( p->pEigen[j], pVecUi, nDims, pVecUiHat ); Emb_ManVecCopyOne( pVecUi, pVecUiHat, nDims ); } Emb_ManVecMultiply( p->pMatr, pVecUi, nDims, pVecUiHat ); Emb_ManVecNormal( pVecUiHat, nDims ); } while ( Emb_ManVecMultiplyOne( pVecUiHat, pVecUi, nDims ) < 0.999 && k < 100 ); Emb_ManVecCopyOne( pVecUi, pVecUiHat, nDims ); // printf( "Converged after %d iterations.\n", k ); } } /**Function************************************************************* Synopsis [Derives solutions from original vectors and eigenvectors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManComputeSolutions( Emb_Man_t * p, int nDims, int nSols ) { Emb_Dat_t * pX; float * pY; int i, j, k; assert( p->pSols == NULL ); p->pSols = ABC_CALLOC( float, p->nObjs * nSols ); for ( i = 0; i < nDims; i++ ) { pX = Emb_ManVec( p, i ); for ( j = 0; j < nSols; j++ ) { pY = Emb_ManSol( p, j ); for ( k = 0; k < p->nObjs; k++ ) pY[k] += pX[k] * p->pEigen[j][i]; } } } /**Function************************************************************* Synopsis [Projects into square of size [0;GIA_PLACE_SIZE] x [0;GIA_PLACE_SIZE].] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManDerivePlacement( Emb_Man_t * p, int nSols ) { float * pY0, * pY1, Max0, Max1, Min0, Min1, Str0, Str1; int * pPerm0, * pPerm1; int k; if ( nSols != 2 ) return; // compute intervals Min0 = ABC_INFINITY; Max0 = -ABC_INFINITY; pY0 = Emb_ManSol( p, 0 ); for ( k = 0; k < p->nObjs; k++ ) { Min0 = Abc_MinInt( Min0, pY0[k] ); Max0 = Abc_MaxInt( Max0, pY0[k] ); } Str0 = 1.0*GIA_PLACE_SIZE/(Max0 - Min0); // update the coordinates for ( k = 0; k < p->nObjs; k++ ) pY0[k] = (pY0[k] != 0.0) ? ((pY0[k] - Min0) * Str0) : 0.0; // compute intervals Min1 = ABC_INFINITY; Max1 = -ABC_INFINITY; pY1 = Emb_ManSol( p, 1 ); for ( k = 0; k < p->nObjs; k++ ) { Min1 = Abc_MinInt( Min1, pY1[k] ); Max1 = Abc_MaxInt( Max1, pY1[k] ); } Str1 = 1.0*GIA_PLACE_SIZE/(Max1 - Min1); // update the coordinates for ( k = 0; k < p->nObjs; k++ ) pY1[k] = (pY1[k] != 0.0) ? ((pY1[k] - Min1) * Str1) : 0.0; // derive the order of these numbers pPerm0 = Gia_SortFloats( pY0, NULL, p->nObjs ); pPerm1 = Gia_SortFloats( pY1, NULL, p->nObjs ); // average solutions and project them into square [0;GIA_PLACE_SIZE] x [0;GIA_PLACE_SIZE] p->pPlacement = ABC_ALLOC( unsigned short, 2 * p->nObjs ); for ( k = 0; k < p->nObjs; k++ ) { p->pPlacement[2*pPerm0[k]+0] = (unsigned short)(int)(1.0 * k * GIA_PLACE_SIZE / p->nObjs); p->pPlacement[2*pPerm1[k]+1] = (unsigned short)(int)(1.0 * k * GIA_PLACE_SIZE / p->nObjs); } ABC_FREE( pPerm0 ); ABC_FREE( pPerm1 ); } /**Function************************************************************* Synopsis [Computes wire-length.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ double Emb_ManComputeHPWL( Emb_Man_t * p ) { double Result = 0.0; Emb_Obj_t * pThis, * pNext; int i, k, iMinX, iMaxX, iMinY, iMaxY; if ( p->pPlacement == NULL ) return 0.0; Emb_ManForEachObj( p, pThis, i ) { iMinX = iMaxX = p->pPlacement[2*pThis->Value+0]; iMinY = iMaxY = p->pPlacement[2*pThis->Value+1]; Emb_ObjForEachFanout( pThis, pNext, k ) { iMinX = Abc_MinInt( iMinX, p->pPlacement[2*pNext->Value+0] ); iMaxX = Abc_MaxInt( iMaxX, p->pPlacement[2*pNext->Value+0] ); iMinY = Abc_MinInt( iMinY, p->pPlacement[2*pNext->Value+1] ); iMaxY = Abc_MaxInt( iMaxY, p->pPlacement[2*pNext->Value+1] ); } Result += (iMaxX - iMinX) + (iMaxY - iMinY); } return Result; } /**Function************************************************************* Synopsis [Performs iterative refinement of the given placement.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManPlacementRefine( Emb_Man_t * p, int nIters, int fVerbose ) { Emb_Obj_t * pThis, * pNext; double CostThis, CostPrev; float * pEdgeX, * pEdgeY; float * pVertX, * pVertY; float VertX, VertY; int * pPermX, * pPermY; int i, k, Iter, iMinX, iMaxX, iMinY, iMaxY; abctime clk = Abc_Clock(); if ( p->pPlacement == NULL ) return; pEdgeX = ABC_ALLOC( float, p->nObjs ); pEdgeY = ABC_ALLOC( float, p->nObjs ); pVertX = ABC_ALLOC( float, p->nObjs ); pVertY = ABC_ALLOC( float, p->nObjs ); // refine placement CostPrev = 0.0; for ( Iter = 0; Iter < nIters; Iter++ ) { // compute centers of hyperedges CostThis = 0.0; Emb_ManForEachObj( p, pThis, i ) { iMinX = iMaxX = p->pPlacement[2*pThis->Value+0]; iMinY = iMaxY = p->pPlacement[2*pThis->Value+1]; Emb_ObjForEachFanout( pThis, pNext, k ) { iMinX = Abc_MinInt( iMinX, p->pPlacement[2*pNext->Value+0] ); iMaxX = Abc_MaxInt( iMaxX, p->pPlacement[2*pNext->Value+0] ); iMinY = Abc_MinInt( iMinY, p->pPlacement[2*pNext->Value+1] ); iMaxY = Abc_MaxInt( iMaxY, p->pPlacement[2*pNext->Value+1] ); } pEdgeX[pThis->Value] = 0.5 * (iMaxX + iMinX); pEdgeY[pThis->Value] = 0.5 * (iMaxY + iMinY); CostThis += (iMaxX - iMinX) + (iMaxY - iMinY); } // compute new centers of objects Emb_ManForEachObj( p, pThis, i ) { VertX = pEdgeX[pThis->Value]; VertY = pEdgeY[pThis->Value]; Emb_ObjForEachFanin( pThis, pNext, k ) { VertX += pEdgeX[pNext->Value]; VertY += pEdgeY[pNext->Value]; } pVertX[pThis->Value] = VertX / (Emb_ObjFaninNum(pThis) + 1); pVertY[pThis->Value] = VertY / (Emb_ObjFaninNum(pThis) + 1); } // sort these numbers pPermX = Gia_SortFloats( pVertX, NULL, p->nObjs ); pPermY = Gia_SortFloats( pVertY, NULL, p->nObjs ); for ( k = 0; k < p->nObjs; k++ ) { p->pPlacement[2*pPermX[k]+0] = (unsigned short)(int)(1.0 * k * GIA_PLACE_SIZE / p->nObjs); p->pPlacement[2*pPermY[k]+1] = (unsigned short)(int)(1.0 * k * GIA_PLACE_SIZE / p->nObjs); } ABC_FREE( pPermX ); ABC_FREE( pPermY ); // evaluate cost if ( fVerbose ) { printf( "%2d : HPWL = %e ", Iter+1, CostThis ); ABC_PRT( "Time", Abc_Clock() - clk ); } } ABC_FREE( pEdgeX ); ABC_FREE( pEdgeY ); ABC_FREE( pVertX ); ABC_FREE( pVertY ); } /**Function************************************************************* Synopsis [Derives solutions from original vectors and eigenvectors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManPrintSolutions( Emb_Man_t * p, int nSols ) { float * pSol; int i, k; for ( i = 0; i < nSols; i++ ) { pSol = Emb_ManSol( p, i ); for ( k = 0; k < p->nObjs; k++ ) printf( "%4d ", (int)(100 * pSol[k]) ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Prepares image for dumping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Emb_ManDumpGnuplotPrepare( Emb_Man_t * p ) { // int nRows = 496; // int nCols = 710; int nRows = 500; int nCols = 700; Vec_Int_t * vLines; Emb_Obj_t * pThis; char * pBuffer, ** ppRows; int i, k, placeX, placeY; int fStart; // alloc memory pBuffer = ABC_CALLOC( char, nRows * (nCols+1) ); ppRows = ABC_ALLOC( char *, nRows ); for ( i = 0; i < nRows; i++ ) ppRows[i] = pBuffer + i*(nCols+1); // put data into them Emb_ManForEachObj( p, pThis, i ) { placeX = p->pPlacement[2*pThis->Value+0] * nCols / (1<<16); placeY = p->pPlacement[2*pThis->Value+1] * nRows / (1<<16); assert( placeX < nCols && placeY < nRows ); ppRows[placeY][placeX] = 1; } // select lines vLines = Vec_IntAlloc( 1000 ); for ( i = 0; i < nRows; i++ ) { fStart = 0; for ( k = 0; k <= nCols; k++ ) { if ( ppRows[i][k] && !fStart ) { Vec_IntPush( vLines, k ); Vec_IntPush( vLines, i ); fStart = 1; } if ( !ppRows[i][k] && fStart ) { Vec_IntPush( vLines, k-1 ); Vec_IntPush( vLines, i ); fStart = 0; } } assert( fStart == 0 ); } ABC_FREE( pBuffer ); ABC_FREE( ppRows ); return vLines; } /**Function************************************************************* Synopsis [Derives solutions from original vectors and eigenvectors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Emb_ManDumpGnuplot( Emb_Man_t * p, char * pName, int fDumpLarge, int fShowImage ) { extern void Gia_ManGnuplotShow( char * pPlotFileName ); // char * pDirectory = "place\\"; char * pDirectory = ""; // extern char * Ioa_TimeStamp(); FILE * pFile; char Buffer[1000]; Emb_Obj_t * pThis, * pNext; int i, k; if ( p->pPlacement == NULL ) { printf( "Emb_ManDumpGnuplot(): Placement is not available.\n" ); return; } sprintf( Buffer, "%s%s", pDirectory, Gia_FileNameGenericAppend(pName, ".plt") ); pFile = fopen( Buffer, "w" ); fprintf( pFile, "# This Gnuplot file was produced by ABC on %s\n", Ioa_TimeStamp() ); fprintf( pFile, "\n" ); fprintf( pFile, "set nokey\n" ); fprintf( pFile, "\n" ); if ( !fShowImage ) { // fprintf( pFile, "set terminal postscript\n" ); fprintf( pFile, "set terminal gif font \'arial\' 10 size 800,600 xffffff x000000 x000000 x000000\n" ); fprintf( pFile, "set output \'%s\'\n", Gia_FileNameGenericAppend(pName, ".gif") ); fprintf( pFile, "\n" ); } fprintf( pFile, "set title \"%s : PI = %d PO = %d FF = %d Node = %d Obj = %d HPWL = %.2e\\n", pName, Emb_ManPiNum(p), Emb_ManPoNum(p), Emb_ManRegNum(p), Emb_ManNodeNum(p), Emb_ManObjNum(p), Emb_ManComputeHPWL(p) ); fprintf( pFile, "(image generated by ABC and Gnuplot on %s)\"", Ioa_TimeStamp() ); fprintf( pFile, "font \"Times, 12\"\n" ); fprintf( pFile, "\n" ); fprintf( pFile, "plot [:] '-' w l\n" ); fprintf( pFile, "\n" ); if ( fDumpLarge ) { int begX, begY, endX, endY; Vec_Int_t * vLines = Emb_ManDumpGnuplotPrepare( p ); Vec_IntForEachEntry( vLines, begX, i ) { begY = Vec_IntEntry( vLines, i+1 ); endX = Vec_IntEntry( vLines, i+2 ); endY = Vec_IntEntry( vLines, i+3 ); i += 3; fprintf( pFile, "%5d %5d\n", begX, begY ); fprintf( pFile, "%5d %5d\n", endX, endY ); fprintf( pFile, "\n" ); } Vec_IntFree( vLines ); } else { Emb_ManForEachObj( p, pThis, i ) { if ( !Emb_ObjIsTravIdCurrent(p, pThis) ) continue; Emb_ObjForEachFanout( pThis, pNext, k ) { assert( Emb_ObjIsTravIdCurrent(p, pNext) ); fprintf( pFile, "%5d %5d\n", p->pPlacement[2*pThis->Value+0], p->pPlacement[2*pThis->Value+1] ); fprintf( pFile, "%5d %5d\n", p->pPlacement[2*pNext->Value+0], p->pPlacement[2*pNext->Value+1] ); fprintf( pFile, "\n" ); } } } fprintf( pFile, "EOF\n" ); fprintf( pFile, "\n" ); if ( fShowImage ) { fprintf( pFile, "pause -1 \"Close window\"\n" ); // Hit return to continue fprintf( pFile, "reset\n" ); fprintf( pFile, "\n" ); } else { fprintf( pFile, "# pause -1 \"Close window\"\n" ); // Hit return to continue fprintf( pFile, "# reset\n" ); fprintf( pFile, "\n" ); } fclose( pFile ); if ( fShowImage ) Gia_ManGnuplotShow( Buffer ); } /**Function************************************************************* Synopsis [Computes dimentions of the graph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSolveProblem( Gia_Man_t * pGia, Emb_Par_t * pPars ) { Emb_Man_t * p; int i; abctime clkSetup; abctime clk; // Gia_ManTestDistance( pGia ); // transform AIG into internal data-structure clk = Abc_Clock(); if ( pPars->fCluster ) { p = Emb_ManStart( pGia ); if ( pPars->fVerbose ) { printf( "Clustered: " ); Emb_ManPrintStats( p ); } } else p = Emb_ManStartSimple( pGia ); p->fVerbose = pPars->fVerbose; // Emb_ManPrintFanio( p ); // prepare data-structure Gia_ManRandom( 1 ); // reset random numbers for deterministic behavior Emb_ManResetTravId( p ); Emb_ManSetValue( p ); clkSetup = Abc_Clock() - clk; clk = Abc_Clock(); Emb_ManComputeDimensions( p, pPars->nDims ); if ( pPars->fVerbose ) ABC_PRT( "Setup ", clkSetup ); if ( pPars->fVerbose ) ABC_PRT( "Dimensions", Abc_Clock() - clk ); clk = Abc_Clock(); Emb_ManComputeCovariance( p, pPars->nDims ); if ( pPars->fVerbose ) ABC_PRT( "Matrix ", Abc_Clock() - clk ); clk = Abc_Clock(); Emb_ManComputeEigenvectors( p, pPars->nDims, pPars->nSols ); Emb_ManComputeSolutions( p, pPars->nDims, pPars->nSols ); Emb_ManDerivePlacement( p, pPars->nSols ); if ( pPars->fVerbose ) ABC_PRT( "Eigenvecs ", Abc_Clock() - clk ); if ( pPars->fRefine ) { clk = Abc_Clock(); Emb_ManPlacementRefine( p, pPars->nIters, pPars->fVerbose ); if ( pPars->fVerbose ) ABC_PRT( "Refinement", Abc_Clock() - clk ); } if ( (pPars->fDump || pPars->fDumpLarge) && pPars->nSols == 2 ) { clk = Abc_Clock(); Emb_ManDumpGnuplot( p, pGia->pName, pPars->fDumpLarge, pPars->fShowImage ); if ( pPars->fVerbose ) ABC_PRT( "Image dump", Abc_Clock() - clk ); } // transfer placement if ( Gia_ManObjNum(pGia) == p->nObjs ) { // assuming normalized ordering of the AIG pGia->pPlacement = ABC_CALLOC( Gia_Plc_t, p->nObjs ); for ( i = 0; i < p->nObjs; i++ ) { pGia->pPlacement[i].xCoord = p->pPlacement[2*i+0]; pGia->pPlacement[i].yCoord = p->pPlacement[2*i+1]; } } Emb_ManStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaEnable.c000066400000000000000000000514651477524141600163150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [gia.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Structural detection of enables, sets and resets.] 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 [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_CollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) { // if the new node is complemented or a PI, another gate begins if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) ) { Vec_IntPushUnique( vSuper, Gia_ObjId(p, Gia_Regular(pObj)) ); return; } assert( Gia_ObjIsAnd(pObj) ); // go through the branches Gia_CollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper ); Gia_CollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper ); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_CollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) { assert( !Gia_IsComplement(pObj) ); Vec_IntClear( vSuper ); // Gia_CollectSuper_rec( p, pObj, vSuper ); if ( Gia_ObjIsAnd(pObj) ) { Vec_IntPushUnique( vSuper, Gia_ObjId(p, Gia_ObjFanin0(pObj)) ); Vec_IntPushUnique( vSuper, Gia_ObjId(p, Gia_ObjFanin1(pObj)) ); } else Vec_IntPushUnique( vSuper, Gia_ObjId(p, Gia_Regular(pObj)) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintSignals( Gia_Man_t * p, int * pFreq, char * pStr ) { Vec_Int_t * vObjs; int i, Counter = 0, nTotal = 0; vObjs = Vec_IntAlloc( 100 ); for ( i = 0; i < Gia_ManObjNum(p); i++ ) if ( pFreq[i] > 1 ) { nTotal += pFreq[i]; Counter++; } printf( "%s (total = %d driven = %d)\n", pStr, Counter, nTotal ); Counter = 0; for ( i = 0; i < Gia_ManObjNum(p); i++ ) if ( pFreq[i] > 10 ) { printf( "%3d : Obj = %6d Refs = %6d Freq = %6d\n", ++Counter, i, Gia_ObjRefNum(p, Gia_ManObj(p,i)), pFreq[i] ); Vec_IntPush( vObjs, i ); } Vec_IntFree( vObjs ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDetectSeqSignals( Gia_Man_t * p, int fSetReset, int fVerbose ) { Vec_Int_t * vSuper; Gia_Obj_t * pFlop, * pObjC, * pObj0, * pObj1, * pNode, * pTemp; int i, k, Ent, * pSets, * pResets, * pEnables; int nHaveSetReset = 0, nHaveEnable = 0; assert( Gia_ManRegNum(p) > 0 ); pSets = ABC_CALLOC( int, Gia_ManObjNum(p) ); pResets = ABC_CALLOC( int, Gia_ManObjNum(p) ); pEnables = ABC_CALLOC( int, Gia_ManObjNum(p) ); vSuper = Vec_IntAlloc( 100 ); Gia_ManForEachRi( p, pFlop, i ) { pNode = Gia_ObjFanin0(pFlop); if ( !Gia_ObjIsAnd(pNode) ) continue; // detect sets/resets Gia_CollectSuper( p, pNode, vSuper ); if ( Gia_ObjFaninC0(pFlop) ) Vec_IntForEachEntry( vSuper, Ent, k ) pSets[Ent]++; else Vec_IntForEachEntry( vSuper, Ent, k ) pResets[Ent]++; // detect enables if ( !Gia_ObjIsMuxType(pNode) ) continue; pObjC = Gia_ObjRecognizeMux( pNode, &pObj0, &pObj1 ); pTemp = Gia_ObjRiToRo( p, pFlop ); if ( Gia_Regular(pObj0) != pTemp && Gia_Regular(pObj1) != pTemp ) continue; if ( !Gia_ObjFaninC0(pFlop) ) { pObj0 = Gia_Not(pObj0); pObj1 = Gia_Not(pObj1); } if ( Gia_IsComplement(pObjC) ) { pObjC = Gia_Not(pObjC); pTemp = pObj0; pObj0 = pObj1; pObj1 = pTemp; } // detect controls // Gia_CollectSuper( p, pObjC, vSuper ); // Vec_IntForEachEntry( vSuper, Ent, k ) // pEnables[Ent]++; pEnables[Gia_ObjId(p, pObjC)]++; nHaveEnable++; } Gia_ManForEachRi( p, pFlop, i ) { pNode = Gia_ObjFanin0(pFlop); if ( !Gia_ObjIsAnd(pNode) ) continue; // detect sets/resets Gia_CollectSuper( p, pNode, vSuper ); Vec_IntForEachEntry( vSuper, Ent, k ) if ( pSets[Ent] > 1 || pResets[Ent] > 1 ) { nHaveSetReset++; break; } } Vec_IntFree( vSuper ); ABC_FREE( p->pRefs ); Gia_ManCreateRefs( p ); if ( fVerbose ) { printf( "Flops with set/reset = %6d. Flops with enable = %6d.\n", nHaveSetReset, nHaveEnable ); if ( fSetReset ) { Gia_ManPrintSignals( p, pSets, "Set signals" ); Gia_ManPrintSignals( p, pResets, "Reset signals" ); } Gia_ManPrintSignals( p, pEnables, "Enable signals" ); } ABC_FREE( p->pRefs ); ABC_FREE( pSets ); ABC_FREE( pResets ); ABC_FREE( pEnables ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManDetectSeqSignalsWithFanout( Gia_Man_t * p, int nFanMax, int fVerbose ) { Vec_Int_t * vResult; Vec_Int_t * vSuper; Gia_Obj_t * pFlop, * pObjC, * pObj0, * pObj1, * pNode, * pTemp; int i, k, Ent, * pSets, * pResets, * pEnables; int nHaveSetReset = 0, nHaveEnable = 0; assert( Gia_ManRegNum(p) > 0 ); pSets = ABC_CALLOC( int, Gia_ManObjNum(p) ); pResets = ABC_CALLOC( int, Gia_ManObjNum(p) ); pEnables = ABC_CALLOC( int, Gia_ManObjNum(p) ); vSuper = Vec_IntAlloc( 100 ); Gia_ManForEachRi( p, pFlop, i ) { pNode = Gia_ObjFanin0(pFlop); if ( !Gia_ObjIsAnd(pNode) ) continue; // detect sets/resets Gia_CollectSuper( p, pNode, vSuper ); if ( Gia_ObjFaninC0(pFlop) ) Vec_IntForEachEntry( vSuper, Ent, k ) pSets[Ent]++; else Vec_IntForEachEntry( vSuper, Ent, k ) pResets[Ent]++; // detect enables if ( !Gia_ObjIsMuxType(pNode) ) continue; pObjC = Gia_ObjRecognizeMux( pNode, &pObj0, &pObj1 ); pTemp = Gia_ObjRiToRo( p, pFlop ); if ( Gia_Regular(pObj0) != pTemp && Gia_Regular(pObj1) != pTemp ) continue; if ( !Gia_ObjFaninC0(pFlop) ) { pObj0 = Gia_Not(pObj0); pObj1 = Gia_Not(pObj1); } if ( Gia_IsComplement(pObjC) ) { pObjC = Gia_Not(pObjC); pTemp = pObj0; pObj0 = pObj1; pObj1 = pTemp; } // detect controls // Gia_CollectSuper( p, pObjC, vSuper ); // Vec_IntForEachEntry( vSuper, Ent, k ) // pEnables[Ent]++; pEnables[Gia_ObjId(p, pObjC)]++; nHaveEnable++; } Gia_ManForEachRi( p, pFlop, i ) { pNode = Gia_ObjFanin0(pFlop); if ( !Gia_ObjIsAnd(pNode) ) continue; // detect sets/resets Gia_CollectSuper( p, pNode, vSuper ); Vec_IntForEachEntry( vSuper, Ent, k ) if ( pSets[Ent] > 1 || pResets[Ent] > 1 ) { nHaveSetReset++; break; } } Vec_IntFree( vSuper ); vResult = Vec_IntAlloc( 100 ); for ( i = 1; i < Gia_ManObjNum(p); i++ ) if ( pSets[i] > nFanMax ) { if ( fVerbose ) printf( "Adding set signal %d related to %d flops.\n", i, pSets[i] ); Vec_IntPushUnique( vResult, i ); } for ( i = 1; i < Gia_ManObjNum(p); i++ ) if ( pResets[i] > nFanMax ) { if ( fVerbose ) printf( "Adding reset signal %d related to %d flops.\n", i, pResets[i] ); Vec_IntPushUnique( vResult, i ); } for ( i = 1; i < Gia_ManObjNum(p); i++ ) if ( pEnables[i] > nFanMax ) { if ( fVerbose ) printf( "Adding enable signal %d related to %d flops.\n", i, pEnables[i] ); Vec_IntPushUnique( vResult, i ); } ABC_FREE( pSets ); ABC_FREE( pResets ); ABC_FREE( pEnables ); return vResult; } /**Function************************************************************* Synopsis [Transfers attributes from the original one to the final one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManTransferFrames( Gia_Man_t * pAig, Gia_Man_t * pFrames, int nFrames, Gia_Man_t * pNew, Vec_Int_t * vSigs ) { Vec_Int_t * vSigsNew; Gia_Obj_t * pObj, * pObjF; int k, f; vSigsNew = Vec_IntAlloc( 100 ); Gia_ManForEachObjVec( vSigs, pAig, pObj, k ) { assert( Gia_ObjIsCand(pObj) ); for ( f = 0; f < nFrames; f++ ) { pObjF = Gia_ManObj( pFrames, Abc_Lit2Var(Gia_ObjCopyF( pAig, f, pObj )) ); if ( pObjF->Value && ~pObjF->Value ) Vec_IntPushUnique( vSigsNew, Abc_Lit2Var(pObjF->Value) ); } } return vSigsNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManUnrollInit( Gia_Man_t * p, int nFrames ) { Gia_Man_t * pNew; Gia_Obj_t * pObj, * pObjRi, * pObjRo; int f, i; Vec_IntFill( &p->vCopies, nFrames * Gia_ManObjNum(p), -1 ); pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); Gia_ManForEachRo( p, pObj, i ) Gia_ObjSetCopyF( p, 0, pObj, 0 ); for ( f = 0; f < nFrames; f++ ) { Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); Gia_ManForEachPi( p, pObj, i ) Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); Gia_ManForEachAnd( p, pObj, i ) Gia_ObjSetCopyF( p, f, pObj, Gia_ManHashAnd(pNew, Gia_ObjFanin0CopyF(p, f, pObj), Gia_ObjFanin1CopyF(p, f, pObj)) ); Gia_ManForEachCo( p, pObj, i ) Gia_ObjSetCopyF( p, f, pObj, Gia_ObjFanin0CopyF(p, f, pObj) ); Gia_ManForEachPo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjCopyF(p, f, pObj) ); if ( f == nFrames - 1 ) break; Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) Gia_ObjSetCopyF( p, f+1, pObjRo, Gia_ObjCopyF(p, f, pObjRi) ); } Gia_ManHashStop( pNew ); return pNew; } /**Function************************************************************* Synopsis [Unrolls initialized timeframes while cofactoring some vars.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManUnrollAndCofactor( Gia_Man_t * p, int nFrames, int nFanMax, int fVerbose ) { Vec_Int_t * vCofSigs, * vTemp; Gia_Man_t * pAig, * pFrames, * pNew; // compute initialized timeframes pFrames = Gia_ManUnrollInit( p, nFrames ); pAig = Gia_ManCleanup( pFrames ); // compute and remap set/reset/enable signals vCofSigs = Gia_ManDetectSeqSignalsWithFanout( p, nFanMax, fVerbose ); vCofSigs = Gia_ManTransferFrames( p, pFrames, nFrames, pAig, vTemp = vCofSigs ); Vec_IntFree( vTemp ); Gia_ManStop( pFrames ); Vec_IntErase( &p->vCopies ); // cofactor all these variables pNew = Gia_ManDupCofAllInt( pAig, vCofSigs, fVerbose ); Vec_IntFree( vCofSigs ); Gia_ManStop( pAig ); return pNew; } /**Function************************************************************* Synopsis [Transform seq circuits with enables by removing enables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManRemoveEnables2( Gia_Man_t * p ) { Gia_Man_t * pNew, * pAux; Gia_Obj_t * pTemp, * pObjC, * pObj0, * pObj1, * pFlopIn, * pFlopOut; Gia_Obj_t * pThis, * pNode; 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_ManForEachCi( p, pThis, i ) pThis->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachAnd( p, pThis, i ) pThis->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pThis), Gia_ObjFanin1Copy(pThis) ); Gia_ManForEachPo( p, pThis, i ) pThis->Value = Gia_ObjFanin0Copy(pThis); Gia_ManForEachRi( p, pFlopIn, i ) { pNode = Gia_ObjFanin0(pFlopIn); if ( !Gia_ObjIsMuxType(pNode) ) { printf( "Cannot recognize enable of flop %d.\n", i ); continue; } pObjC = Gia_ObjRecognizeMux( pNode, &pObj1, &pObj0 ); pFlopOut = Gia_ObjRiToRo( p, pFlopIn ); if ( Gia_Regular(pObj0) != pFlopOut && Gia_Regular(pObj1) != pFlopOut ) { printf( "Cannot recognize self-loop of enable flop %d.\n", i ); continue; } if ( !Gia_ObjFaninC0(pFlopIn) ) { pObj0 = Gia_Not(pObj0); pObj1 = Gia_Not(pObj1); } if ( Gia_IsComplement(pObjC) ) { pObjC = Gia_Not(pObjC); pTemp = pObj0; pObj0 = pObj1; pObj1 = pTemp; } if ( Gia_Regular(pObj0) == pFlopOut ) { // printf( "FlopIn compl = %d. FlopOut is d0. Complement = %d.\n", // Gia_ObjFaninC0(pFlopIn), Gia_IsComplement(pObj0) ); pFlopIn->Value = Abc_LitNotCond(Gia_Regular(pObj1)->Value, !Gia_IsComplement(pObj1)); } else if ( Gia_Regular(pObj1) == pFlopOut ) { // printf( "FlopIn compl = %d. FlopOut is d1. Complement = %d.\n", // Gia_ObjFaninC0(pFlopIn), Gia_IsComplement(pObj1) ); pFlopIn->Value = Abc_LitNotCond(Gia_Regular(pObj0)->Value, !Gia_IsComplement(pObj0)); } } Gia_ManForEachCo( p, pThis, i ) Gia_ManAppendCo( pNew, pThis->Value ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew = Gia_ManCleanup( pAux = pNew ); Gia_ManStop( pAux ); return pNew; } /**Function************************************************************* Synopsis [Transform seq circuits with enables by removing enables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManRemoveEnables( Gia_Man_t * p ) { Vec_Ptr_t * vCtrls, * vDatas; Vec_Int_t * vFlopClasses; Gia_Man_t * pNew, * pAux; Gia_Obj_t * pFlopIn, * pFlopOut, * pDriver, * pFan0, * pFan1, * pCtrl = NULL, * pData, * pObj; int i, iClass, fCompl, Counter = 0; vCtrls = Vec_PtrAlloc( 100 ); Vec_PtrPush( vCtrls, NULL ); vDatas = Vec_PtrAlloc( Gia_ManRegNum(p) ); vFlopClasses = Vec_IntAlloc( Gia_ManRegNum(p) ); Gia_ManForEachRi( p, pFlopIn, i ) { fCompl = Gia_ObjFaninC0(pFlopIn); pDriver = Gia_ObjFanin0(pFlopIn); if ( !Gia_ObjIsAnd(pDriver) ) { printf( "The flop driver %d is not a node.\n", i ); Vec_PtrPush( vDatas, NULL ); Vec_IntPush( vFlopClasses, 0 ); Counter++; continue; } if ( !Gia_ObjFaninC0(pDriver) || !Gia_ObjFaninC1(pDriver) ) { printf( "The flop driver %d is not an OR gate.\n", i ); Vec_PtrPush( vDatas, NULL ); Vec_IntPush( vFlopClasses, 0 ); Counter++; continue; } pFan0 = Gia_ObjFanin0(pDriver); pFan1 = Gia_ObjFanin1(pDriver); if ( !Gia_ObjIsAnd(pFan0) || !Gia_ObjIsAnd(pFan1) ) { printf( "The flop driver fanin %d is not a node.\n", i ); Vec_PtrPush( vDatas, NULL ); Vec_IntPush( vFlopClasses, 0 ); Counter++; continue; } pFlopOut = Gia_ObjRiToRo( p, pFlopIn ); pFlopOut = Gia_NotCond( pFlopOut, !fCompl ); if ( Gia_ObjChild0(pFan0) != pFlopOut && Gia_ObjChild1(pFan0) != pFlopOut && Gia_ObjChild0(pFan1) != pFlopOut && Gia_ObjChild1(pFan1) != pFlopOut ) { printf( "The flop %d does not have a self-loop.\n", i ); Vec_PtrPush( vDatas, NULL ); Vec_IntPush( vFlopClasses, 0 ); Counter++; continue; } pData = NULL; if ( Gia_ObjChild0(pFan0) == pFlopOut ) { pCtrl = Gia_Not( Gia_ObjChild1(pFan0) ); if ( Gia_ObjFanin0(pFan1) == Gia_Regular(pCtrl) ) pData = Gia_ObjChild1(pFan1); else pData = Gia_ObjChild0(pFan1); } else if ( Gia_ObjChild1(pFan0) == pFlopOut ) { pCtrl = Gia_Not( Gia_ObjChild0(pFan0) ); if ( Gia_ObjFanin0(pFan1) == Gia_Regular(pCtrl) ) pData = Gia_ObjChild1(pFan1); else pData = Gia_ObjChild0(pFan1); } else if ( Gia_ObjChild0(pFan1) == pFlopOut ) { pCtrl = Gia_Not( Gia_ObjChild1(pFan1) ); if ( Gia_ObjFanin0(pFan0) == Gia_Regular(pCtrl) ) pData = Gia_ObjChild1(pFan0); else pData = Gia_ObjChild0(pFan0); } else if ( Gia_ObjChild1(pFan1) == pFlopOut ) { pCtrl = Gia_Not( Gia_ObjChild0(pFan1) ); if ( Gia_ObjFanin0(pFan0) == Gia_Regular(pCtrl) ) pData = Gia_ObjChild1(pFan0); else pData = Gia_ObjChild0(pFan0); } else assert( 0 ); if ( Vec_PtrFind( vCtrls, pCtrl ) == -1 ) Vec_PtrPush( vCtrls, pCtrl ); iClass = Vec_PtrFind( vCtrls, pCtrl ); pData = Gia_NotCond( pData, !fCompl ); Vec_PtrPush( vDatas, pData ); Vec_IntPush( vFlopClasses, iClass ); } assert( Vec_PtrSize( vDatas ) == Gia_ManRegNum(p) ); assert( Vec_IntSize( vFlopClasses ) == Gia_ManRegNum(p) ); printf( "Detected %d classes.\n", Vec_PtrSize(vCtrls) - (Counter == 0) ); Vec_PtrFree( vCtrls ); 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_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_ObjIsPo(p, pObj) ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Gia_ManForEachRi( p, pObj, i ) { pData = (Gia_Obj_t *)Vec_PtrEntry(vDatas, i); if ( pData == NULL ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); else pObj->Value = Gia_ManAppendCo( pNew, Abc_LitNotCond(Gia_Regular(pData)->Value, Gia_IsComplement(pData)) ); } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); Vec_PtrFree( vDatas ); pNew = Gia_ManCleanup( pAux = pNew ); Gia_ManStop( pAux ); pNew->vFlopClasses = vFlopClasses; return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaEquiv.c000066400000000000000000002766611477524141600162270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaEquiv.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Manipulation of equivalence classes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaEquiv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "proof/cec/cec.h" #include "sat/bmc/bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Manipulating original IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManOrigIdsInit( Gia_Man_t * p ) { Vec_IntFreeP( &p->vIdsOrig ); p->vIdsOrig = Vec_IntStartNatural( Gia_ManObjNum(p) ); } void Gia_ManOrigIdsStart( Gia_Man_t * p ) { Vec_IntFreeP( &p->vIdsOrig ); p->vIdsOrig = Vec_IntStartFull( Gia_ManObjNum(p) ); } void Gia_ManOrigIdsRemap( Gia_Man_t * p, Gia_Man_t * pNew ) { Gia_Obj_t * pObj; int i; if ( p->vIdsOrig == NULL ) return; Gia_ManOrigIdsStart( pNew ); Vec_IntWriteEntry( pNew->vIdsOrig, 0, 0 ); Gia_ManForEachObj1( p, pObj, i ) if ( ~pObj->Value && Abc_Lit2Var(pObj->Value) && Vec_IntEntry(p->vIdsOrig, i) != -1 && Vec_IntEntry(pNew->vIdsOrig, Abc_Lit2Var(pObj->Value)) == -1 ) Vec_IntWriteEntry( pNew->vIdsOrig, Abc_Lit2Var(pObj->Value), Vec_IntEntry(p->vIdsOrig, i) ); Gia_ManForEachObj( pNew, pObj, i ) assert( Vec_IntEntry(pNew->vIdsOrig, i) >= 0 ); } // input is a set of equivalent node pairs in any order // output is the mapping of each node into the equiv node with the smallest ID void Gia_ManOrigIdsRemapPairsInsert( Vec_Int_t * vMap, int One, int Two ) { int Smo = One < Two ? One : Two; int Big = One < Two ? Two : One; assert( Smo != Big ); if ( Vec_IntEntry(vMap, Big) == -1 ) Vec_IntWriteEntry( vMap, Big, Smo ); else Gia_ManOrigIdsRemapPairsInsert( vMap, Smo, Vec_IntEntry(vMap, Big) ); } int Gia_ManOrigIdsRemapPairsExtract( Vec_Int_t * vMap, int One ) { if ( Vec_IntEntry(vMap, One) == -1 ) return One; return Gia_ManOrigIdsRemapPairsExtract( vMap, Vec_IntEntry(vMap, One) ); } Vec_Int_t * Gia_ManOrigIdsRemapPairs( Vec_Int_t * vEquivPairs, int nObjs ) { Vec_Int_t * vMapResult; Vec_Int_t * vMap2Smaller; int i, One, Two; // map bigger into smaller one vMap2Smaller = Vec_IntStartFull( nObjs ); Vec_IntForEachEntryDouble( vEquivPairs, One, Two, i ) Gia_ManOrigIdsRemapPairsInsert( vMap2Smaller, One, Two ); // collect results in the topo order vMapResult = Vec_IntStartFull( nObjs ); Vec_IntForEachEntry( vMap2Smaller, One, i ) if ( One >= 0 ) Vec_IntWriteEntry( vMapResult, i, Gia_ManOrigIdsRemapPairsExtract(vMap2Smaller, One) ); Vec_IntFree( vMap2Smaller ); return vMapResult; } // remap the AIG using the equivalent pairs proved // returns the reduced AIG and the equivalence classes of the original AIG Gia_Man_t * Gia_ManOrigIdsReduce( Gia_Man_t * p, Vec_Int_t * vPairs ) { Gia_Man_t * pNew = NULL; Gia_Obj_t * pObj, * pRepr; int i; Vec_Int_t * vMap = Gia_ManOrigIdsRemapPairs( vPairs, Gia_ManObjNum(p) ); Gia_ManSetPhase( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManFillValue(p); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManHashAlloc( pNew ); Gia_ManForEachAnd( p, pObj, i ) { if ( Vec_IntEntry(vMap, i) == -1 ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else { pRepr = Gia_ManObj( p, Vec_IntEntry(vMap, i) ); pObj->Value = Abc_LitNotCond( pRepr->Value, pRepr->fPhase ^ pObj->fPhase ); } } Gia_ManHashStop( pNew ); Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Vec_IntFree( vMap ); // compute equivalences assert( !p->pReprs && !p->pNexts ); p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); for ( i = 0; i < Gia_ManObjNum(p); i++ ) Gia_ObjSetRepr( p, i, GIA_VOID ); Gia_ManFillValue(pNew); Gia_ManForEachAnd( p, pObj, i ) { int iRepr = Abc_Lit2Var(pObj->Value); if ( iRepr == 0 ) { Gia_ObjSetRepr( p, i, 0 ); continue; } pRepr = Gia_ManObj( pNew, iRepr ); if ( !~pRepr->Value ) // first time { pRepr->Value = i; continue; } // add equivalence Gia_ObjSetRepr( p, i, pRepr->Value ); } p->pNexts = Gia_ManDeriveNexts( p ); return pNew; } Gia_Man_t * Gia_ManOrigIdsReduceTest( Gia_Man_t * p, Vec_Int_t * vPairs ) { Gia_Man_t * pTemp, * pNew = Gia_ManOrigIdsReduce( p, vPairs ); Gia_ManPrintStats( p, NULL ); Gia_ManPrintStats( pNew, NULL ); //Gia_ManStop( pNew ); // cleanup the resulting one pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Compute equivalence classes of nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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; pPars->fVerbose = fVerbose; pTemp = Cec_ManSatSweeping( pGia, pPars, 0 ); Gia_ManStop( pTemp ); return Gia_ManOrigIdsReduce( pGia, pGia->vIdsEquiv ); } /**Function************************************************************* Synopsis [Returns 1 if AIG is not in the required topo order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCheckTopoOrder_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pRepr; if ( pObj->Value == 0 ) return 1; pObj->Value = 0; assert( Gia_ObjIsAnd(pObj) ); if ( !Gia_ManCheckTopoOrder_rec( p, Gia_ObjFanin0(pObj) ) ) return 0; if ( !Gia_ManCheckTopoOrder_rec( p, Gia_ObjFanin1(pObj) ) ) return 0; pRepr = p->pReprs ? Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ) : NULL; return pRepr == NULL || pRepr->Value == 0; } /**Function************************************************************* Synopsis [Returns 0 if AIG is not in the required topo order.] Description [AIG should be in such an order that the representative is always traversed before the node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCheckTopoOrder( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, RetValue = 1; Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = 0; Gia_ManForEachCo( p, pObj, i ) RetValue &= Gia_ManCheckTopoOrder_rec( p, Gia_ObjFanin0(pObj) ); return RetValue; } /**Function************************************************************* Synopsis [Given representatives, derives pointers to the next objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Gia_ManDeriveNexts( Gia_Man_t * p ) { unsigned * pNexts, * pTails; int i; assert( p->pReprs != NULL ); assert( p->pNexts == NULL ); pNexts = ABC_CALLOC( unsigned, Gia_ManObjNum(p) ); pTails = ABC_ALLOC( unsigned, Gia_ManObjNum(p) ); for ( i = 0; i < Gia_ManObjNum(p); i++ ) 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; pTails[p->pReprs[i].iRepr] = i; } ABC_FREE( pTails ); return (int *)pNexts; } /**Function************************************************************* Synopsis [Given points to the next objects, derives representatives.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDeriveReprs( Gia_Man_t * p ) { int i, iObj; assert( p->pReprs == NULL ); assert( 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 ); for ( i = 0; i < Gia_ManObjNum(p); i++ ) { if ( p->pNexts[i] == 0 ) continue; if ( p->pReprs[i].iRepr != GIA_VOID ) continue; // next is set, repr is not set for ( iObj = p->pNexts[i]; iObj; iObj = p->pNexts[iObj] ) p->pReprs[iObj].iRepr = i; } } /**Function************************************************************* Synopsis [Given pSibls, derives original representitives and nexts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDeriveReprsFromSibls( Gia_Man_t *p ) { int i, iObj; assert( !p->pReprs && p->pSibls ); 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 ) continue; if ( p->pReprs[i].iRepr != GIA_VOID ) continue; for ( iObj = p->pSibls[i]; iObj; iObj = p->pSibls[iObj] ) p->pReprs[iObj].iRepr = i; } ABC_FREE( p->pNexts ); p->pNexts = Gia_ManDeriveNexts( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManEquivCountLitsAll( Gia_Man_t * p ) { int i, nLits = 0; for ( i = 0; i < Gia_ManObjNum(p); i++ ) nLits += (Gia_ObjRepr(p, i) != GIA_VOID); return nLits; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManEquivCountClasses( Gia_Man_t * p ) { int i, Counter = 0; if ( p->pReprs == NULL ) return 0; for ( i = 1; i < Gia_ManObjNum(p); i++ ) Counter += Gia_ObjIsHead(p, i); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManEquivCheckLits( Gia_Man_t * p, int nLits ) { int nLitsReal = Gia_ManEquivCountLitsAll( p ); if ( nLitsReal != nLits ) Abc_Print( 1, "Detected a mismatch in counting equivalence classes (%d).\n", nLitsReal - nLits ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintStatsClasses( Gia_Man_t * p ) { int i, Counter = 0, Counter0 = 0, CounterX = 0, Proved = 0, nLits; for ( i = 1; i < Gia_ManObjNum(p); i++ ) { if ( Gia_ObjIsHead(p, i) ) Counter++; else if ( Gia_ObjIsConst(p, i) ) Counter0++; else if ( Gia_ObjIsNone(p, i) ) CounterX++; if ( Gia_ObjProved(p, i) ) Proved++; } CounterX -= Gia_ManCoNum(p); nLits = Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX; // Abc_Print( 1, "i/o/ff =%5d/%5d/%5d ", Gia_ManPiNum(p), Gia_ManPoNum(p), Gia_ManRegNum(p) ); // Abc_Print( 1, "and =%5d ", Gia_ManAndNum(p) ); // Abc_Print( 1, "lev =%3d ", Gia_ManLevelNum(p) ); Abc_Print( 1, "cst =%3d cls =%6d lit =%8d\n", Counter0, Counter, nLits ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManEquivCountLits( Gia_Man_t * p ) { int i, Counter = 0, Counter0 = 0, CounterX = 0; if ( p->pReprs == NULL || p->pNexts == NULL ) return 0; for ( i = 1; i < Gia_ManObjNum(p); i++ ) { if ( Gia_ObjIsHead(p, i) ) Counter++; else if ( Gia_ObjIsConst(p, i) ) Counter0++; else if ( Gia_ObjIsNone(p, i) ) CounterX++; } CounterX -= Gia_ManCoNum(p); return Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManEquivCountOne( Gia_Man_t * p, int i ) { int Ent, nLits = 1; Gia_ClassForEachObj1( p, i, Ent ) { assert( Gia_ObjRepr(p, Ent) == i ); nLits++; } return nLits; } void Gia_ManEquivPrintOne( Gia_Man_t * p, int i, int Counter ) { int Ent; Abc_Print( 1, "Class %4d : Num = %2d {", Counter, Gia_ManEquivCountOne(p, i) ); Gia_ClassForEachObj( p, i, Ent ) { Abc_Print( 1," %d", Ent ); if ( p->pReprs[Ent].fColorA || p->pReprs[Ent].fColorB ) Abc_Print( 1," <%d%d>", p->pReprs[Ent].fColorA, p->pReprs[Ent].fColorB ); } Abc_Print( 1, " }\n" ); } void Gia_ManEquivPrintClasses( Gia_Man_t * p, int fVerbose, float Mem ) { int i, Counter = 0, Counter0 = 0, CounterX = 0, Proved = 0, nLits; for ( i = 1; i < Gia_ManObjNum(p); i++ ) { if ( Gia_ObjIsHead(p, i) ) Counter++; else if ( Gia_ObjIsConst(p, i) ) Counter0++; else if ( Gia_ObjIsNone(p, i) ) CounterX++; if ( Gia_ObjProved(p, i) ) Proved++; } 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\n", Counter0, Counter, nLits, CounterX, Proved ); assert( Gia_ManEquivCheckLits( p, nLits ) ); if ( fVerbose ) { // int Ent; Abc_Print( 1, "Const0 (%d) = ", Counter0 ); Gia_ManForEachConst( p, i ) Abc_Print( 1, "%d ", i ); Abc_Print( 1, "\n" ); Counter = 0; Gia_ManForEachClass( p, i ) Gia_ManEquivPrintOne( p, i, ++Counter ); /* Gia_ManLevelNum( p ); Gia_ManForEachClass( p, i ) if ( i % 100 == 0 ) { // Abc_Print( 1, "%d ", Gia_ManEquivCountOne(p, i) ); Gia_ClassForEachObj( p, i, Ent ) { Abc_Print( 1, "%d ", Gia_ObjLevel( p, Gia_ManObj(p, Ent) ) ); } Abc_Print( 1, "\n" ); } */ } } /**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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_Obj_t * Gia_ManEquivRepr( Gia_Man_t * p, Gia_Obj_t * pObj, int fUseAll, int fDualOut ) { if ( fUseAll ) { if ( Gia_ObjRepr(p, Gia_ObjId(p,pObj)) == GIA_VOID ) return NULL; } else { if ( !Gia_ObjProved(p, Gia_ObjId(p,pObj)) ) return NULL; } // if ( fDualOut && !Gia_ObjDiffColors( p, Gia_ObjId(p, pObj), Gia_ObjRepr(p, Gia_ObjId(p,pObj)) ) ) if ( fDualOut && !Gia_ObjDiffColors2( p, Gia_ObjId(p, pObj), Gia_ObjRepr(p, Gia_ObjId(p,pObj)) ) ) return NULL; return Gia_ManObj( p, Gia_ObjRepr(p, Gia_ObjId(p,pObj)) ); } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManEquivReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int fUseAll, int fDualOut ) { Gia_Obj_t * pRepr; if ( (pRepr = Gia_ManEquivRepr(p, pObj, fUseAll, fDualOut)) ) { Gia_ManEquivReduce_rec( pNew, p, pRepr, fUseAll, fDualOut ); pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); return; } if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManEquivReduce_rec( pNew, p, Gia_ObjFanin0(pObj), fUseAll, fDualOut ); Gia_ManEquivReduce_rec( pNew, p, Gia_ObjFanin1(pObj), fUseAll, fDualOut ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } /**Function************************************************************* Synopsis [Reduces AIG using equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManEquivReduce( Gia_Man_t * p, int fUseAll, int fDualOut, int fSkipPhase, int fVerbose ) { 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; } if ( fDualOut && (Gia_ManPoNum(p) & 1) ) { Abc_Print( 1, "Gia_ManEquivReduce(): Dual-output miter should have even number of POs.\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) ) { // Abc_Print( 1, "Gia_ManEquivReduce(): There are no equivalences to reduce.\n" ); // return NULL; return Gia_ManDup( p ); } /* if ( !Gia_ManCheckTopoOrder( p ) ) { Abc_Print( 1, "Gia_ManEquivReduce(): AIG is not in a correct topological order.\n" ); return NULL; } */ if ( !fSkipPhase ) Gia_ManSetPhase( p ); if ( fDualOut ) Gia_ManEquivSetColors( p, fVerbose ); 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_ManEquivReduce_rec( pNew, p, Gia_ObjFanin0(pObj), fUseAll, fDualOut ); Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Obj_t * Gia_MakeRandomChoice( Gia_Man_t * p, int iRepr ) { int iTemp, Rand, Count = 0; Gia_ClassForEachObj( p, iRepr, iTemp ) Count++; Rand = rand() % Count; Count = 0; Gia_ClassForEachObj( p, iRepr, iTemp ) if ( Count++ == Rand ) break; return Gia_ManObj(p, iTemp); } /**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 = vMap ? Gia_ManObj( p, Vec_IntEntry(vMap, iRepr) ) : Gia_MakeRandomChoice(p, 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, int fRandom ) { Vec_Int_t * vMap; Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; if ( fRandom ) srand(time(NULL)); 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 = fRandom ? NULL : 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_IntFreeP( &vMap ); return pNew; } /**Function************************************************************* Synopsis [Reduces AIG using equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManEquivFixOutputPairs( Gia_Man_t * p ) { Gia_Obj_t * pObj0, * pObj1; int i; assert( (Gia_ManPoNum(p) & 1) == 0 ); Gia_ManForEachPo( p, pObj0, i ) { pObj1 = Gia_ManPo( p, ++i ); if ( Gia_ObjChild0(pObj0) != Gia_ObjChild0(pObj1) ) continue; pObj0->iDiff0 = Gia_ObjId(p, pObj0); pObj0->fCompl0 = 0; pObj1->iDiff0 = Gia_ObjId(p, pObj1); pObj1->fCompl0 = 0; } } /**Function************************************************************* Synopsis [Removes pointers to the unmarked nodes..] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManEquivUpdatePointers( Gia_Man_t * p, Gia_Man_t * pNew ) { Gia_Obj_t * pObj, * pObjNew; int i; Gia_ManForEachObj( p, pObj, i ) { if ( !~pObj->Value ) continue; pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); if ( pObjNew->fMark0 ) pObj->Value = ~0; } } /**Function************************************************************* Synopsis [Removes pointers to the unmarked nodes..] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManEquivDeriveReprs( Gia_Man_t * p, Gia_Man_t * pNew, Gia_Man_t * pFinal ) { Vec_Int_t * vClass; Gia_Obj_t * pObj, * pObjNew; int i, k, iNode, iRepr, iPrev; // start representatives pFinal->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pFinal) ); for ( i = 0; i < Gia_ManObjNum(pFinal); i++ ) Gia_ObjSetRepr( pFinal, i, GIA_VOID ); // iterate over constant candidates Gia_ManForEachConst( p, i ) { pObj = Gia_ManObj( p, i ); if ( !~pObj->Value ) continue; pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); if ( Abc_Lit2Var(pObjNew->Value) == 0 ) continue; Gia_ObjSetRepr( pFinal, Abc_Lit2Var(pObjNew->Value), 0 ); } // iterate over class candidates vClass = Vec_IntAlloc( 100 ); Gia_ManForEachClass( p, i ) { Vec_IntClear( vClass ); Gia_ClassForEachObj( p, i, k ) { pObj = Gia_ManObj( p, k ); if ( !~pObj->Value ) continue; pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); Vec_IntPushUnique( vClass, Abc_Lit2Var(pObjNew->Value) ); } if ( Vec_IntSize( vClass ) < 2 ) continue; Vec_IntSort( vClass, 0 ); iRepr = iPrev = Vec_IntEntry( vClass, 0 ); Vec_IntForEachEntryStart( vClass, iNode, k, 1 ) { Gia_ObjSetRepr( pFinal, iNode, iRepr ); assert( iPrev < iNode ); iPrev = iNode; } } Vec_IntFree( vClass ); pFinal->pNexts = Gia_ManDeriveNexts( pFinal ); } /**Function************************************************************* Synopsis [Removes pointers to the unmarked nodes..] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManEquivRemapDfs( Gia_Man_t * p ) { Gia_Man_t * pNew; Vec_Int_t * vClass; int i, k, iNode, iRepr, iPrev; pNew = Gia_ManDupDfs( p ); // 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 = iPrev = Vec_IntEntry( vClass, 0 ); Vec_IntForEachEntryStart( vClass, iNode, k, 1 ) { Gia_ObjSetRepr( pNew, iNode, iRepr ); assert( iPrev < iNode ); iPrev = iNode; } } Vec_IntFree( vClass ); pNew->pNexts = Gia_ManDeriveNexts( pNew ); return pNew; } /**Function************************************************************* Synopsis [Reduces AIG while remapping equivalence classes.] Description [Drops the pairs of outputs if they are proved equivalent.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManEquivReduceAndRemap( Gia_Man_t * p, int fSeq, int fMiterPairs ) { Gia_Man_t * pNew, * pFinal; pNew = Gia_ManEquivReduce( p, 0, 0, 0, 0 ); if ( pNew == NULL ) return NULL; Gia_ManOrigIdsRemap( p, pNew ); if ( fMiterPairs ) Gia_ManEquivFixOutputPairs( pNew ); if ( fSeq ) Gia_ManSeqMarkUsed( pNew ); else Gia_ManCombMarkUsed( pNew ); Gia_ManEquivUpdatePointers( p, pNew ); pFinal = Gia_ManDupMarked( pNew ); Gia_ManOrigIdsRemap( pNew, pFinal ); Gia_ManEquivDeriveReprs( p, pNew, pFinal ); Gia_ManStop( pNew ); pFinal = Gia_ManEquivRemapDfs( pNew = pFinal ); Gia_ManOrigIdsRemap( pNew, pFinal ); Gia_ManStop( pNew ); return pFinal; } /**Function************************************************************* Synopsis [Marks CIs/COs/ANDs unreachable from POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManEquivSetColor_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int fOdds ) { if ( Gia_ObjVisitColor( p, Gia_ObjId(p,pObj), fOdds ) ) return 0; if ( Gia_ObjIsRo(p, pObj) ) return 1 + Gia_ManEquivSetColor_rec( p, Gia_ObjFanin0(Gia_ObjRoToRi(p, pObj)), fOdds ); assert( Gia_ObjIsAnd(pObj) ); return 1 + Gia_ManEquivSetColor_rec( p, Gia_ObjFanin0(pObj), fOdds ) + Gia_ManEquivSetColor_rec( p, Gia_ObjFanin1(pObj), fOdds ); } /**Function************************************************************* Synopsis [Marks CIs/COs/ANDs unreachable from POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManEquivSetColors( Gia_Man_t * p, int fVerbose ) { Gia_Obj_t * pObj; int i, nNodes[2], nDiffs[2]; assert( (Gia_ManPoNum(p) & 1) == 0 ); Gia_ObjSetColors( p, 0 ); Gia_ManForEachPi( p, pObj, i ) Gia_ObjSetColors( p, Gia_ObjId(p,pObj) ); nNodes[0] = nNodes[1] = Gia_ManPiNum(p); Gia_ManForEachPo( p, pObj, i ) nNodes[i&1] += Gia_ManEquivSetColor_rec( p, Gia_ObjFanin0(pObj), i&1 ); // Gia_ManForEachObj( p, pObj, i ) // if ( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) ) // assert( Gia_ObjColors(p, i) ); nDiffs[0] = Gia_ManCandNum(p) - nNodes[0]; nDiffs[1] = Gia_ManCandNum(p) - nNodes[1]; if ( fVerbose ) { Abc_Print( 1, "CI+AND = %7d A = %7d B = %7d Ad = %7d Bd = %7d AB = %7d.\n", Gia_ManCandNum(p), nNodes[0], nNodes[1], nDiffs[0], nDiffs[1], Gia_ManCandNum(p) - nDiffs[0] - nDiffs[1] ); } return (nDiffs[0] + nDiffs[1]) / 2; } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSpecBuild( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXorLits, int fDualOut, int fSpeculate, Vec_Int_t * vTrace, Vec_Int_t * vGuide, Vec_Int_t * vMap ) { Gia_Obj_t * pRepr; unsigned iLitNew; pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); if ( pRepr == NULL ) return; // if ( fDualOut && !Gia_ObjDiffColors( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) ) if ( fDualOut && !Gia_ObjDiffColors2( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) ) return; iLitNew = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); if ( pObj->Value != iLitNew && !Gia_ObjProved(p, Gia_ObjId(p,pObj)) ) { if ( vTrace ) Vec_IntPush( vTrace, 1 ); if ( vGuide == NULL || Vec_IntEntry( vGuide, Vec_IntSize(vTrace)-1 ) ) { if ( vMap ) Vec_IntPush( vMap, Gia_ObjId(p, pObj) ); Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, pObj->Value, iLitNew) ); } } else { if ( vTrace ) Vec_IntPush( vTrace, 0 ); } if ( fSpeculate ) pObj->Value = iLitNew; } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXorLits, int fDualOut, int fSpeculate, Vec_Int_t * vTrace, Vec_Int_t * vGuide, Vec_Int_t * vMap ) { if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), vXorLits, fDualOut, fSpeculate, vTrace, vGuide, vMap ); Gia_ManSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj), vXorLits, fDualOut, fSpeculate, vTrace, vGuide, vMap ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManSpecBuild( pNew, p, pObj, vXorLits, fDualOut, fSpeculate, vTrace, vGuide, vMap ); } /**Function************************************************************* Synopsis [Reduces AIG using equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManSpecReduceTrace( Gia_Man_t * p, Vec_Int_t * vTrace, Vec_Int_t * vMap ) { Vec_Int_t * vXorLits; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iLitNew; if ( !p->pReprs ) { Abc_Print( 1, "Gia_ManSpecReduce(): Equivalence classes are not available.\n" ); return NULL; } Vec_IntClear( vTrace ); vXorLits = Vec_IntAlloc( 1000 ); Gia_ManSetPhase( p ); Gia_ManFillValue( p ); 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_ManForEachRo( p, pObj, i ) Gia_ManSpecBuild( pNew, p, pObj, vXorLits, 0, 1, vTrace, NULL, vMap ); Gia_ManForEachCo( p, pObj, i ) Gia_ManSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), vXorLits, 0, 1, vTrace, NULL, vMap ); Gia_ManForEachPo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Vec_IntForEachEntry( vXorLits, iLitNew, i ) Gia_ManAppendCo( pNew, iLitNew ); if ( Vec_IntSize(vXorLits) == 0 ) { Abc_Print( 1, "Speculatively reduced model has no primary outputs.\n" ); Gia_ManAppendCo( pNew, 0 ); } Gia_ManForEachRi( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Vec_IntFree( vXorLits ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Reduces AIG using equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManSpecReduce( Gia_Man_t * p, int fDualOut, int fSynthesis, int fSpeculate, int fSkipSome, int fVerbose ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; Vec_Int_t * vXorLits; int i, iLitNew; Vec_Int_t * vTrace = NULL, * vGuide = NULL; if ( !p->pReprs ) { Abc_Print( 1, "Gia_ManSpecReduce(): Equivalence classes are not available.\n" ); return NULL; } if ( fDualOut && (Gia_ManPoNum(p) & 1) ) { Abc_Print( 1, "Gia_ManSpecReduce(): Dual-output miter should have even number of POs.\n" ); return NULL; } if ( fSkipSome ) { vGuide = Vec_IntAlloc( 100 ); pTemp = Gia_ManSpecReduceTrace( p, vGuide, NULL ); Gia_ManStop( pTemp ); assert( Vec_IntSize(vGuide) == Gia_ManEquivCountLitsAll(p) ); vTrace = Vec_IntAlloc( 100 ); } vXorLits = Vec_IntAlloc( 1000 ); Gia_ManSetPhase( p ); Gia_ManFillValue( p ); if ( fDualOut ) Gia_ManEquivSetColors( p, fVerbose ); 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_ManForEachRo( p, pObj, i ) Gia_ManSpecBuild( pNew, p, pObj, vXorLits, fDualOut, fSpeculate, vTrace, vGuide, NULL ); Gia_ManForEachCo( p, pObj, i ) Gia_ManSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), vXorLits, fDualOut, fSpeculate, vTrace, vGuide, NULL ); if ( !fSynthesis ) { Gia_ManForEachPo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Vec_IntForEachEntry( vXorLits, iLitNew, i ) Gia_ManAppendCo( pNew, iLitNew ); if ( Vec_IntSize(vXorLits) == 0 ) { Abc_Print( 1, "Speculatively reduced model has no primary outputs.\n" ); Gia_ManAppendCo( pNew, 0 ); } Gia_ManForEachRi( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Vec_IntFree( vXorLits ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); // update using trace if ( fSkipSome ) { // count the number of non-zero entries int iLit, nAddPos = 0; Vec_IntForEachEntry( vGuide, iLit, i ) if ( iLit ) nAddPos++; if ( nAddPos ) assert( Gia_ManPoNum(pNew) == Gia_ManPoNum(p) + nAddPos ); } Vec_IntFreeP( &vTrace ); Vec_IntFreeP( &vGuide ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSpecBuildInit( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXorLits, int f, int fDualOut ) { Gia_Obj_t * pRepr; int iLitNew; pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); if ( pRepr == NULL ) return; // if ( fDualOut && !Gia_ObjDiffColors( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) ) if ( fDualOut && !Gia_ObjDiffColors2( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) ) return; iLitNew = Abc_LitNotCond( Gia_ObjCopyF(p, f, pRepr), Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); if ( Gia_ObjCopyF(p, f, pObj) != iLitNew && !Gia_ObjProved(p, Gia_ObjId(p,pObj)) ) Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, Gia_ObjCopyF(p, f, pObj), iLitNew) ); Gia_ObjSetCopyF( p, f, pObj, iLitNew ); } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSpecReduceInit_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXorLits, int f, int fDualOut ) { if ( ~Gia_ObjCopyF(p, f, pObj) ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManSpecReduceInit_rec( pNew, p, Gia_ObjFanin0(pObj), vXorLits, f, fDualOut ); Gia_ManSpecReduceInit_rec( pNew, p, Gia_ObjFanin1(pObj), vXorLits, f, fDualOut ); Gia_ObjSetCopyF( p, f, pObj, Gia_ManHashAnd(pNew, Gia_ObjFanin0CopyF(p, f, pObj), Gia_ObjFanin1CopyF(p, f, pObj)) ); Gia_ManSpecBuildInit( pNew, p, pObj, vXorLits, f, fDualOut ); } /**Function************************************************************* Synopsis [Creates initialized SRM with the given number of frames.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManSpecReduceInit( Gia_Man_t * p, Abc_Cex_t * pInit, int nFrames, int fDualOut ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObjRi, * pObjRo; Vec_Int_t * vXorLits; int f, i, iLitNew; if ( !p->pReprs ) { Abc_Print( 1, "Gia_ManSpecReduceInit(): Equivalence classes are not available.\n" ); return NULL; } if ( Gia_ManRegNum(p) == 0 ) { Abc_Print( 1, "Gia_ManSpecReduceInit(): Circuit is not sequential.\n" ); return NULL; } if ( Gia_ManRegNum(p) != pInit->nRegs ) { Abc_Print( 1, "Gia_ManSpecReduceInit(): Mismatch in the number of registers.\n" ); return NULL; } if ( fDualOut && (Gia_ManPoNum(p) & 1) ) { Abc_Print( 1, "Gia_ManSpecReduceInit(): Dual-output miter should have even number of POs.\n" ); return NULL; } /* if ( !Gia_ManCheckTopoOrder( p ) ) { Abc_Print( 1, "Gia_ManSpecReduceInit(): AIG is not in a correct topological order.\n" ); return NULL; } */ assert( pInit->nRegs == Gia_ManRegNum(p) && pInit->nPis == 0 ); Vec_IntFill( &p->vCopies, nFrames * Gia_ManObjNum(p), -1 ); vXorLits = Vec_IntAlloc( 1000 ); Gia_ManSetPhase( p ); if ( fDualOut ) Gia_ManEquivSetColors( p, 0 ); pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); Gia_ManForEachRo( p, pObj, i ) Gia_ObjSetCopyF( p, 0, pObj, Abc_InfoHasBit(pInit->pData, i) ); for ( f = 0; f < nFrames; f++ ) { Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); Gia_ManForEachPi( p, pObj, i ) Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); Gia_ManForEachRo( p, pObj, i ) Gia_ManSpecBuildInit( pNew, p, pObj, vXorLits, f, fDualOut ); Gia_ManForEachCo( p, pObj, i ) { Gia_ManSpecReduceInit_rec( pNew, p, Gia_ObjFanin0(pObj), vXorLits, f, fDualOut ); Gia_ObjSetCopyF( p, f, pObj, Gia_ObjFanin0CopyF(p, f, pObj) ); } if ( f == nFrames - 1 ) break; Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) Gia_ObjSetCopyF( p, f+1, pObjRo, Gia_ObjCopyF(p, f, pObjRi) ); } Vec_IntForEachEntry( vXorLits, iLitNew, i ) Gia_ManAppendCo( pNew, iLitNew ); if ( Vec_IntSize(vXorLits) == 0 ) { // Abc_Print( 1, "Speculatively reduced model has no primary outputs.\n" ); Gia_ManAppendCo( pNew, 0 ); } Vec_IntErase( &p->vCopies ); Vec_IntFree( vXorLits ); Gia_ManHashStop( pNew ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Creates initialized SRM with the given number of frames.] Description [Uses as many frames as needed to create the number of output not less than the number of equivalence literals.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManSpecReduceInitFrames( Gia_Man_t * p, Abc_Cex_t * pInit, int nFramesMax, int * pnFrames, int fDualOut, int nMinOutputs ) { Gia_Man_t * pFrames; int f, nLits; nLits = Gia_ManEquivCountLits( p ); for ( f = 1; ; f++ ) { pFrames = Gia_ManSpecReduceInit( p, pInit, f, fDualOut ); if ( (nMinOutputs == 0 && Gia_ManPoNum(pFrames) >= nLits/2+1) || (nMinOutputs != 0 && Gia_ManPoNum(pFrames) >= nMinOutputs) ) break; if ( f == nFramesMax ) break; if ( Gia_ManAndNum(pFrames) > 500000 ) { Gia_ManStop( pFrames ); return NULL; } Gia_ManStop( pFrames ); pFrames = NULL; } if ( f == nFramesMax ) Abc_Print( 1, "Stopped unrolling after %d frames.\n", nFramesMax ); if ( pnFrames ) *pnFrames = f; return pFrames; } /**Function************************************************************* Synopsis [Transforms equiv classes by removing the AB nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManEquivTransform( Gia_Man_t * p, int fVerbose ) { extern void Cec_ManSimClassCreate( Gia_Man_t * p, Vec_Int_t * vClass ); Vec_Int_t * vClass, * vClassNew; int iRepr, iNode, Ent, k; int nRemovedLits = 0, nRemovedClas = 0; int nTotalLits = 0, nTotalClas = 0; Gia_Obj_t * pObj; int i; assert( p->pReprs && p->pNexts ); vClass = Vec_IntAlloc( 100 ); vClassNew = Vec_IntAlloc( 100 ); Gia_ManForEachObj( p, pObj, i ) if ( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) ) assert( Gia_ObjColors(p, i) ); Gia_ManForEachClassReverse( p, iRepr ) { nTotalClas++; Vec_IntClear( vClass ); Vec_IntClear( vClassNew ); Gia_ClassForEachObj( p, iRepr, iNode ) { nTotalLits++; Vec_IntPush( vClass, iNode ); assert( Gia_ObjColors(p, iNode) ); if ( Gia_ObjColors(p, iNode) != 3 ) Vec_IntPush( vClassNew, iNode ); else nRemovedLits++; } Vec_IntForEachEntry( vClass, Ent, k ) { p->pReprs[Ent].fFailed = p->pReprs[Ent].fProved = 0; p->pReprs[Ent].iRepr = GIA_VOID; p->pNexts[Ent] = 0; } if ( Vec_IntSize(vClassNew) < 2 ) { nRemovedClas++; continue; } Cec_ManSimClassCreate( p, vClassNew ); } Vec_IntFree( vClass ); Vec_IntFree( vClassNew ); if ( fVerbose ) Abc_Print( 1, "Removed classes = %6d (out of %6d). Removed literals = %6d (out of %6d).\n", nRemovedClas, nTotalClas, nRemovedLits, nTotalLits ); } /**Function************************************************************* Synopsis [Marks proved equivalences.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManEquivMark( Gia_Man_t * p, char * pFileName, int fSkipSome, int fVerbose ) { Gia_Man_t * pMiter, * pTemp; Gia_Obj_t * pObj; int i, iLit, nAddPos, nLits = 0; int nLitsAll, Counter = 0; nLitsAll = Gia_ManEquivCountLitsAll( p ); if ( nLitsAll == 0 ) { Abc_Print( 1, "Gia_ManEquivMark(): Current AIG does not have equivalences.\n" ); return; } // read AIGER file pMiter = Gia_AigerRead( pFileName, 0, 0, 0 ); if ( pMiter == NULL ) { Abc_Print( 1, "Gia_ManEquivMark(): Input file %s could not be read.\n", pFileName ); return; } if ( fSkipSome ) { Vec_Int_t * vTrace = Vec_IntAlloc( 100 ); pTemp = Gia_ManSpecReduceTrace( p, vTrace, NULL ); Gia_ManStop( pTemp ); assert( Vec_IntSize(vTrace) == nLitsAll ); // count the number of non-zero entries nAddPos = 0; Vec_IntForEachEntry( vTrace, iLit, i ) if ( iLit ) nAddPos++; // check the number if ( Gia_ManPoNum(pMiter) != Gia_ManPoNum(p) + nAddPos ) { Abc_Print( 1, "Gia_ManEquivMark(): The number of POs is not correct: MiterPONum(%d) != AIGPONum(%d) + AIGFilteredEquivNum(%d).\n", Gia_ManPoNum(pMiter), Gia_ManPoNum(p), nAddPos ); Gia_ManStop( pMiter ); Vec_IntFreeP( &vTrace ); return; } // mark corresponding POs as solved nLits = iLit = Counter = 0; for ( i = 0; i < Gia_ManObjNum(p); i++ ) { if ( Gia_ObjRepr(p, i) == GIA_VOID ) continue; if ( Vec_IntEntry( vTrace, nLits++ ) == 0 ) continue; pObj = Gia_ManPo( pMiter, Gia_ManPoNum(p) + iLit++ ); if ( Gia_ObjFaninLit0p(pMiter, pObj) == 0 ) // const 0 - proven { Gia_ObjSetProved(p, i); Counter++; } } assert( nLits == nLitsAll ); assert( iLit == nAddPos ); Vec_IntFreeP( &vTrace ); } else { if ( Gia_ManPoNum(pMiter) != Gia_ManPoNum(p) + nLitsAll ) { Abc_Print( 1, "Gia_ManEquivMark(): The number of POs is not correct: MiterPONum(%d) != AIGPONum(%d) + AIGEquivNum(%d).\n", Gia_ManPoNum(pMiter), Gia_ManPoNum(p), nLitsAll ); Gia_ManStop( pMiter ); return; } // mark corresponding POs as solved nLits = 0; for ( i = 0; i < Gia_ManObjNum(p); i++ ) { if ( Gia_ObjRepr(p, i) == GIA_VOID ) continue; pObj = Gia_ManPo( pMiter, Gia_ManPoNum(p) + nLits++ ); if ( Gia_ObjFaninLit0p(pMiter, pObj) == 0 ) // const 0 - proven { Gia_ObjSetProved(p, i); Counter++; } } assert( nLits == nLitsAll ); } if ( fVerbose ) Abc_Print( 1, "Set %d equivalences as proved.\n", Counter ); Gia_ManStop( pMiter ); } /**Function************************************************************* Synopsis [Transforms equiv classes by filtering those that correspond to disproved outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManEquivFilter( Gia_Man_t * p, Vec_Int_t * vPoIds, int fVerbose ) { Gia_Man_t * pSrm; Vec_Int_t * vTrace, * vMap; int i, iObjId, Entry, Prev = -1; // check if there are equivalences if ( p->pReprs == NULL || p->pNexts == NULL ) { Abc_Print( 1, "Gia_ManEquivFilter(): Equivalence classes are not defined.\n" ); return; } // check if PO indexes are available if ( vPoIds == NULL ) { Abc_Print( 1, "Gia_ManEquivFilter(): Array of disproved POs is not available.\n" ); return; } if ( Vec_IntSize(vPoIds) == 0 ) return; // create SRM with mapping into POs vMap = Vec_IntAlloc( 1000 ); vTrace = Vec_IntAlloc( 1000 ); pSrm = Gia_ManSpecReduceTrace( p, vTrace, vMap ); Vec_IntFree( vTrace ); // the resulting array (vMap) maps PO indexes of the SRM into object IDs assert( Gia_ManPoNum(pSrm) == Gia_ManPoNum(p) + Vec_IntSize(vMap) ); Gia_ManStop( pSrm ); if ( fVerbose ) printf( "Design POs = %d. SRM POs = %d. Spec POs = %d. Disproved POs = %d.\n", Gia_ManPoNum(p), Gia_ManPoNum(p) + Vec_IntSize(vMap), Vec_IntSize(vMap), Vec_IntSize(vPoIds) ); // check if disproved POs satisfy the range Vec_IntSort( vPoIds, 0 ); Vec_IntForEachEntry( vPoIds, Entry, i ) { if ( Entry < 0 || Entry >= Gia_ManPoNum(p) + Vec_IntSize(vMap) ) { Abc_Print( 1, "Gia_ManEquivFilter(): Array of disproved POs contains PO index (%d),\n", Entry ); Abc_Print( 1, "which does not fit into the range of available PO indexes of the SRM: [%d; %d].\n", 0, Gia_ManPoNum(p) + Vec_IntSize(vMap)-1 ); Vec_IntFree( vMap ); return; } if ( Entry < Gia_ManPoNum(p) ) Abc_Print( 0, "Gia_ManEquivFilter(): One of the original POs (%d) have failed.\n", Entry ); if ( Prev == Entry ) { Abc_Print( 1, "Gia_ManEquivFilter(): Array of disproved POs contains at least one duplicate entry (%d),\n", Entry ); Vec_IntFree( vMap ); return; } Prev = Entry; } // perform the reduction of the equivalence classes Vec_IntForEachEntry( vPoIds, Entry, i ) { if ( Entry < Gia_ManPoNum(p) ) continue; iObjId = Vec_IntEntry( vMap, Entry - Gia_ManPoNum(p) ); Gia_ObjUnsetRepr( p, iObjId ); // Gia_ObjSetNext( p, iObjId, 0 ); } Vec_IntFree( vMap ); ABC_FREE( p->pNexts ); p->pNexts = Gia_ManDeriveNexts( p ); } /**Function************************************************************* Synopsis [Transforms equiv classes by filtering those that correspond to disproved outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManEquivFilterTest( Gia_Man_t * p ) { Vec_Int_t * vPoIds; int i; vPoIds = Vec_IntAlloc( 1000 ); for ( i = 0; i < 10; i++ ) { Vec_IntPush( vPoIds, Gia_ManPoNum(p) + 2 * i + 2 ); printf( "%d ", Gia_ManPoNum(p) + 2*i + 2 ); } printf( "\n" ); Gia_ManEquivFilter( p, vPoIds, 1 ); Vec_IntFree( vPoIds ); } /**Function************************************************************* Synopsis [Transforms equiv classes by setting a good representative.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManEquivImprove( Gia_Man_t * p ) { Vec_Int_t * vClass; int i, k, iNode, iRepr; int iReprBest, iLevelBest, iLevelCur, iMffcBest, iMffcCur; assert( p->pReprs != NULL && p->pNexts != NULL ); Gia_ManLevelNum( p ); Gia_ManCreateRefs( p ); // iterate over class candidates vClass = Vec_IntAlloc( 100 ); Gia_ManForEachClass( p, i ) { Vec_IntClear( vClass ); iReprBest = -1; iLevelBest = iMffcBest = ABC_INFINITY; Gia_ClassForEachObj( p, i, k ) { iLevelCur = Gia_ObjLevel( p,Gia_ManObj(p, k) ); iMffcCur = Gia_NodeMffcSize( p, Gia_ManObj(p, k) ); if ( iLevelBest > iLevelCur || (iLevelBest == iLevelCur && iMffcBest > iMffcCur) ) { iReprBest = k; iLevelBest = iLevelCur; iMffcBest = iMffcCur; } Vec_IntPush( vClass, k ); } assert( Vec_IntSize( vClass ) > 1 ); assert( iReprBest > 0 ); if ( i == iReprBest ) continue; /* Abc_Print( 1, "Repr/Best = %6d/%6d. Lev = %3d/%3d. Mffc = %3d/%3d.\n", i, iReprBest, Gia_ObjLevel( p,Gia_ManObj(p, i) ), Gia_ObjLevel( p,Gia_ManObj(p, iReprBest) ), Gia_NodeMffcSize( p, Gia_ManObj(p, i) ), Gia_NodeMffcSize( p, Gia_ManObj(p, iReprBest) ) ); */ iRepr = iReprBest; Gia_ObjSetRepr( p, iRepr, GIA_VOID ); Gia_ObjSetProved( p, i ); Gia_ObjUnsetProved( p, iRepr ); Vec_IntForEachEntry( vClass, iNode, k ) if ( iNode != iRepr ) Gia_ObjSetRepr( p, iNode, iRepr ); } Vec_IntFree( vClass ); ABC_FREE( p->pNexts ); // p->pNexts = Gia_ManDeriveNexts( p ); } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNode.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ObjCheckTfi_rec( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode, Vec_Ptr_t * vVisited ) { // check the trivial cases if ( pNode == NULL ) return 0; if ( Gia_ObjIsCi(pNode) ) return 0; // if ( pNode->Id < pOld->Id ) // cannot use because of choices of pNode // return 0; if ( pNode == pOld ) return 1; // skip the visited node if ( pNode->fMark0 ) return 0; pNode->fMark0 = 1; Vec_PtrPush( vVisited, pNode ); // check the children if ( Gia_ObjCheckTfi_rec( p, pOld, Gia_ObjFanin0(pNode), vVisited ) ) return 1; if ( Gia_ObjCheckTfi_rec( p, pOld, Gia_ObjFanin1(pNode), vVisited ) ) return 1; // check equivalent nodes return Gia_ObjCheckTfi_rec( p, pOld, Gia_ObjNextObj(p, Gia_ObjId(p, pNode)), vVisited ); } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNode.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ObjCheckTfi( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode ) { Vec_Ptr_t * vVisited; Gia_Obj_t * pObj; int RetValue, i; assert( !Gia_IsComplement(pOld) ); assert( !Gia_IsComplement(pNode) ); vVisited = Vec_PtrAlloc( 100 ); RetValue = Gia_ObjCheckTfi_rec( p, pOld, pNode, vVisited ); Vec_PtrForEachEntry( Gia_Obj_t *, vVisited, pObj, i ) pObj->fMark0 = 0; Vec_PtrFree( vVisited ); return RetValue; } /**Function************************************************************* Synopsis [Adds the next entry while making choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManAddNextEntry_rec( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode ) { if ( Gia_ObjNext(p, Gia_ObjId(p, pOld)) == 0 ) { Gia_ObjSetNext( p, Gia_ObjId(p, pOld), Gia_ObjId(p, pNode) ); return; } Gia_ManAddNextEntry_rec( p, Gia_ObjNextObj(p, Gia_ObjId(p, pOld)), pNode ); } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManEquivToChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pRepr, * pReprNew, * pObjNew; if ( ~pObj->Value ) return; if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) && !Gia_ObjFailed(p,Gia_ObjId(p,pObj)) ) { if ( Gia_ObjIsConst0(pRepr) ) { pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); return; } Gia_ManEquivToChoices_rec( pNew, p, pRepr ); assert( Gia_ObjIsAnd(pObj) ); Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin1(pObj) ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( Abc_LitRegular(pObj->Value) == Abc_LitRegular(pRepr->Value) ) { assert( (int)pObj->Value == Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ) ); return; } if ( pRepr->Value > pObj->Value ) // should never happen with high resource limit return; assert( pRepr->Value < pObj->Value ); pReprNew = Gia_ManObj( pNew, Abc_Lit2Var(pRepr->Value) ); pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); if ( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) ) { // assert( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) == pReprNew ); if ( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) != pReprNew ) return; pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); return; } if ( !Gia_ObjCheckTfi( pNew, pReprNew, pObjNew ) ) { assert( Gia_ObjNext(pNew, Gia_ObjId(pNew, pObjNew)) == 0 ); Gia_ObjSetRepr( pNew, Gia_ObjId(pNew, pObjNew), Gia_ObjId(pNew, pReprNew) ); Gia_ManAddNextEntry_rec( pNew, pReprNew, pObjNew ); } pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin1(pObj) ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } /**Function************************************************************* Synopsis [Removes choices, which contain fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManRemoveBadChoices( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, iObj, iPrev, Counter = 0; // mark nodes with fanout Gia_ManForEachObj( p, pObj, i ) { pObj->fMark0 = 0; if ( Gia_ObjIsAnd(pObj) ) { Gia_ObjFanin0(pObj)->fMark0 = 1; Gia_ObjFanin1(pObj)->fMark0 = 1; } else if ( Gia_ObjIsCo(pObj) ) Gia_ObjFanin0(pObj)->fMark0 = 1; } // go through the classes and remove Gia_ManForEachClass( p, i ) { for ( iPrev = i, iObj = Gia_ObjNext(p, i); iObj; iObj = Gia_ObjNext(p, iPrev) ) { if ( !Gia_ManObj(p, iObj)->fMark0 ) { iPrev = iObj; continue; } Gia_ObjSetRepr( p, iObj, GIA_VOID ); Gia_ObjSetNext( p, iPrev, Gia_ObjNext(p, iObj) ); Gia_ObjSetNext( p, iObj, 0 ); Counter++; } } // remove the marks Gia_ManCleanMark0( p ); // Abc_Print( 1, "Removed %d bad choices.\n", Counter ); } /**Function************************************************************* Synopsis [Reduces AIG using equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManEquivToChoices( Gia_Man_t * p, int nSnapshots ) { Vec_Int_t * vNodes; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pRepr; int i; //Gia_ManEquivPrintClasses( p, 0, 0 ); assert( (Gia_ManCoNum(p) % nSnapshots) == 0 ); Gia_ManSetPhase( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->pName = Abc_UtilStrsav( p->pName ); 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++ ) pNew->pReprs[i].iRepr = GIA_VOID; Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManForEachRo( p, pObj, i ) if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) { assert( Gia_ObjIsConst0(pRepr) || Gia_ObjIsRo(p, pRepr) ); pObj->Value = pRepr->Value; } Gia_ManHashAlloc( pNew ); Gia_ManForEachCo( p, pObj, i ) Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); vNodes = Gia_ManGetDangling( p ); Gia_ManForEachObjVec( vNodes, p, pObj, i ) Gia_ManEquivToChoices_rec( pNew, p, pObj ); Vec_IntFree( vNodes ); Gia_ManForEachCo( p, pObj, i ) if ( i % nSnapshots == 0 ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); Gia_ManRemoveBadChoices( pNew ); //Gia_ManEquivPrintClasses( pNew, 0, 0 ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); //Gia_ManEquivPrintClasses( pNew, 0, 0 ); return pNew; } /**Function************************************************************* Synopsis [Counts the number of choice nodes] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCountChoiceNodes( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, Counter = 0; if ( p->pReprs == NULL || p->pNexts == NULL ) return 0; Gia_ManForEachObj( p, pObj, i ) Counter += Gia_ObjIsHead( p, i ); return Counter; } /**Function************************************************************* Synopsis [Counts the number of choices] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCountChoices( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, Counter = 0; if ( p->pReprs == NULL || p->pNexts == NULL ) return 0; Gia_ManForEachObj( p, pObj, i ) Counter += (int)(Gia_ObjNext( p, i ) > 0); return Counter; } ABC_NAMESPACE_IMPL_END #include "aig/aig/aig.h" #include "aig/saig/saig.h" #include "proof/cec/cec.h" #include "giaAig.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [Returns 1 if AIG has dangling nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManHasNoEquivs( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; if ( p->pReprs == NULL ) return 1; Gia_ManForEachObj( p, pObj, i ) if ( Gia_ObjReprObj(p, i) != NULL ) break; return i == Gia_ManObjNum(p); } /**Function************************************************************* Synopsis [Implements iteration during speculation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_CommandSpecI( Gia_Man_t * pGia, int nFramesInit, int nBTLimitInit, int fStart, int fCheckMiter, int fVerbose ) { // extern int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig ); Aig_Man_t * pTemp; Gia_Man_t * pSrm, * pReduce, * pAux; int nIter, nStart = 0; if ( pGia->pReprs == NULL || pGia->pNexts == NULL ) { Abc_Print( 1, "Gia_CommandSpecI(): Equivalence classes are not defined.\n" ); return 0; } // (spech)* where spech = &srm; restore save3; bmc2 -F 100 -C 25000; &resim Gia_ManCleanMark0( pGia ); Gia_ManPrintStats( pGia, NULL ); for ( nIter = 0; ; nIter++ ) { if ( Gia_ManHasNoEquivs(pGia) ) { Abc_Print( 1, "Gia_CommandSpecI: No equivalences left.\n" ); break; } Abc_Print( 1, "ITER %3d : ", nIter ); // if ( fVerbose ) // Abc_Print( 1, "Starting BMC from frame %d.\n", nStart ); // if ( fVerbose ) // Gia_ManPrintStats( pGia, 0 ); Gia_ManPrintStatsClasses( pGia ); // perform speculative reduction // if ( Gia_ManPoNum(pSrm) <= Gia_ManPoNum(pGia) ) if ( !Cec_ManCheckNonTrivialCands(pGia) ) { Abc_Print( 1, "Gia_CommandSpecI: There are only trivial equiv candidates left (PO drivers). Quitting.\n" ); break; } pSrm = Gia_ManSpecReduce( pGia, 0, 0, 1, 0, 0 ); // bmc2 -F 100 -C 25000 { Abc_Cex_t * pCex; int nFrames = nFramesInit; // different from default int nNodeDelta = 2000; int nBTLimit = nBTLimitInit; // different from default int nBTLimitAll = 2000000; pTemp = Gia_ManToAig( pSrm, 0 ); // Aig_ManPrintStats( pTemp ); Gia_ManStop( pSrm ); Saig_BmcPerform( pTemp, nStart, nFrames, nNodeDelta, 0, nBTLimit, nBTLimitAll, fVerbose, 0, NULL, 0, 0 ); pCex = pTemp->pSeqModel; pTemp->pSeqModel = NULL; Aig_ManStop( pTemp ); if ( pCex == NULL ) { Abc_Print( 1, "Gia_CommandSpecI(): Internal BMC could not find a counter-example.\n" ); break; } if ( fStart ) nStart = pCex->iFrame; // perform simulation { Cec_ParSim_t Pars, * pPars = &Pars; Cec_ManSimSetDefaultParams( pPars ); pPars->fCheckMiter = fCheckMiter; if ( Cec_ManSeqResimulateCounter( pGia, pPars, pCex ) ) { ABC_FREE( pCex ); break; } ABC_FREE( pCex ); } } // write equivalence classes 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, 0 ); // Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", "gsrm.aig" ); // Gia_ManPrintStatsShort( pReduce ); Gia_ManStop( pReduce ); } } return 1; } /**Function************************************************************* Synopsis [Reduces AIG using equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFilterEquivsForSpeculation( Gia_Man_t * pGia, char * pName1, char * pName2, int fLatchA, int fLatchB ) { Gia_Man_t * pGia1, * pGia2, * pMiter; Gia_Obj_t * pObj1, * pObj2, * pObjM, * pObj; int i, iObj, iNext, Counter = 0; if ( pGia->pReprs == NULL || pGia->pNexts == NULL ) { Abc_Print( 1, "Equivalences are not defined.\n" ); return 0; } pGia1 = Gia_AigerRead( pName1, 0, 0, 0 ); if ( pGia1 == NULL ) { Abc_Print( 1, "Cannot read first file %s.\n", pName1 ); return 0; } pGia2 = Gia_AigerRead( pName2, 0, 0, 0 ); if ( pGia2 == NULL ) { Gia_ManStop( pGia2 ); Abc_Print( 1, "Cannot read second file %s.\n", pName2 ); return 0; } pMiter = Gia_ManMiter( pGia1, pGia2, 0, 0, 1, 0, 0 ); if ( pMiter == NULL ) { Gia_ManStop( pGia1 ); Gia_ManStop( pGia2 ); Abc_Print( 1, "Cannot create sequential miter.\n" ); return 0; } // make sure the miter is isomorphic if ( Gia_ManObjNum(pGia) != Gia_ManObjNum(pMiter) ) { Gia_ManStop( pGia1 ); Gia_ManStop( pGia2 ); Gia_ManStop( pMiter ); Abc_Print( 1, "The number of objects in different.\n" ); return 0; } if ( memcmp( pGia->pObjs, pMiter->pObjs, sizeof(Gia_Obj_t) * Gia_ManObjNum(pGia) ) ) { Gia_ManStop( pGia1 ); Gia_ManStop( pGia2 ); Gia_ManStop( pMiter ); Abc_Print( 1, "The AIG structure of the miter does not match.\n" ); return 0; } // transfer copies Gia_ManCleanMark0( pGia ); Gia_ManForEachObj( pGia1, pObj1, i ) { if ( pObj1->Value == ~0 ) continue; pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj1->Value) ); pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) ); pObj->fMark0 = 1; } Gia_ManCleanMark1( pGia ); Gia_ManForEachObj( pGia2, pObj2, i ) { if ( pObj2->Value == ~0 ) continue; pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj2->Value) ); pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) ); pObj->fMark1 = 1; } // filter equivalences Gia_ManForEachConst( pGia, i ) { Gia_ObjUnsetRepr( pGia, i ); assert( pGia->pNexts[i] == 0 ); } Gia_ManForEachClass( pGia, i ) { // find the first colorA and colorB int ClassA = -1, ClassB = -1; Gia_ClassForEachObj( pGia, i, iObj ) { pObj = Gia_ManObj( pGia, iObj ); if ( ClassA == -1 && pObj->fMark0 && !pObj->fMark1 ) { if ( fLatchA && !Gia_ObjIsRo(pGia, pObj) ) continue; ClassA = iObj; } if ( ClassB == -1 && pObj->fMark1 && !pObj->fMark0 ) { if ( fLatchB && !Gia_ObjIsRo(pGia, pObj) ) continue; ClassB = iObj; } } // undo equivalence classes for ( iObj = i, iNext = Gia_ObjNext(pGia, iObj); iObj; iObj = iNext, iNext = Gia_ObjNext(pGia, iObj) ) { Gia_ObjUnsetRepr( pGia, iObj ); Gia_ObjSetNext( pGia, iObj, 0 ); } assert( !Gia_ObjIsHead(pGia, i) ); if ( ClassA > 0 && ClassB > 0 ) { if ( ClassA > ClassB ) { ClassA ^= ClassB; ClassB ^= ClassA; ClassA ^= ClassB; } assert( ClassA < ClassB ); Gia_ObjSetNext( pGia, ClassA, ClassB ); Gia_ObjSetRepr( pGia, ClassB, ClassA ); Counter++; assert( Gia_ObjIsHead(pGia, ClassA) ); } } Abc_Print( 1, "The number of two-node classes after filtering = %d.\n", Counter ); //Gia_ManEquivPrintClasses( pGia, 1, 0 ); Gia_ManCleanMark0( pGia ); Gia_ManCleanMark1( pGia ); return 1; } /**Function************************************************************* Synopsis [Reduces AIG using equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFilterEquivsUsingParts( Gia_Man_t * pGia, char * pName1, char * pName2 ) { Vec_Int_t * vNodes; Gia_Man_t * pGia1, * pGia2, * pMiter; Gia_Obj_t * pObj1, * pObj2, * pObjM, * pObj = NULL; int i, k, iObj, iNext, iPrev, iRepr; int iLitsOld, iLitsNew; if ( pGia->pReprs == NULL || pGia->pNexts == NULL ) { Abc_Print( 1, "Equivalences are not defined.\n" ); return 0; } pGia1 = Gia_AigerRead( pName1, 0, 0, 0 ); if ( pGia1 == NULL ) { Abc_Print( 1, "Cannot read first file %s.\n", pName1 ); return 0; } pGia2 = Gia_AigerRead( pName2, 0, 0, 0 ); if ( pGia2 == NULL ) { Gia_ManStop( pGia2 ); Abc_Print( 1, "Cannot read second file %s.\n", pName2 ); return 0; } pMiter = Gia_ManMiter( pGia1, pGia2, 0, 0, 1, 0, 0 ); if ( pMiter == NULL ) { Gia_ManStop( pGia1 ); Gia_ManStop( pGia2 ); Abc_Print( 1, "Cannot create sequential miter.\n" ); return 0; } // make sure the miter is isomorphic if ( Gia_ManObjNum(pGia) != Gia_ManObjNum(pMiter) ) { Gia_ManStop( pGia1 ); Gia_ManStop( pGia2 ); Gia_ManStop( pMiter ); Abc_Print( 1, "The number of objects in different.\n" ); return 0; } if ( memcmp( pGia->pObjs, pMiter->pObjs, sizeof(Gia_Obj_t) * Gia_ManObjNum(pGia) ) ) { Gia_ManStop( pGia1 ); Gia_ManStop( pGia2 ); Gia_ManStop( pMiter ); Abc_Print( 1, "The AIG structure of the miter does not match.\n" ); return 0; } // transfer copies Gia_ManCleanMark0( pGia ); Gia_ManForEachObj( pGia1, pObj1, i ) { if ( pObj1->Value == ~0 ) continue; pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj1->Value) ); pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) ); pObj->fMark0 = 1; } Gia_ManCleanMark1( pGia ); Gia_ManForEachObj( pGia2, pObj2, i ) { if ( pObj2->Value == ~0 ) continue; pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj2->Value) ); pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) ); pObj->fMark1 = 1; } // filter equivalences iLitsOld = iLitsNew = 0; Gia_ManForEachConst( pGia, i ) { iLitsOld++; pObj = Gia_ManObj( pGia, i ); assert( pGia->pNexts[i] == 0 ); assert( pObj->fMark0 || pObj->fMark1 ); if ( pObj->fMark0 && pObj->fMark1 ) // belongs to both A and B Gia_ObjUnsetRepr( pGia, i ); else iLitsNew++; } // filter equivalences vNodes = Vec_IntAlloc( 100 ); Gia_ManForEachClass( pGia, i ) { int fSeenA = 0, fSeenB = 0; assert( pObj->fMark0 || pObj->fMark1 ); Vec_IntClear( vNodes ); Gia_ClassForEachObj( pGia, i, iObj ) { pObj = Gia_ManObj( pGia, iObj ); if ( pObj->fMark0 && !pObj->fMark1 ) { fSeenA = 1; Vec_IntPush( vNodes, iObj ); } if ( !pObj->fMark0 && pObj->fMark1 ) { fSeenB = 1; Vec_IntPush( vNodes, iObj ); } iLitsOld++; } iLitsOld--; // undo equivalence classes for ( iObj = i, iNext = Gia_ObjNext(pGia, iObj); iObj; iObj = iNext, iNext = Gia_ObjNext(pGia, iObj) ) { Gia_ObjUnsetRepr( pGia, iObj ); Gia_ObjSetNext( pGia, iObj, 0 ); } assert( !Gia_ObjIsHead(pGia, i) ); if ( fSeenA && fSeenB && Vec_IntSize(vNodes) > 1 ) { // create new class iPrev = iRepr = Vec_IntEntry( vNodes, 0 ); Vec_IntForEachEntryStart( vNodes, iObj, k, 1 ) { Gia_ObjSetRepr( pGia, iObj, iRepr ); Gia_ObjSetNext( pGia, iPrev, iObj ); iPrev = iObj; iLitsNew++; } assert( Gia_ObjNext(pGia, iPrev) == 0 ); } } Vec_IntFree( vNodes ); Abc_Print( 1, "The number of literals: Before = %d. After = %d.\n", iLitsOld, iLitsNew ); //Gia_ManEquivPrintClasses( pGia, 1, 0 ); Gia_ManCleanMark0( pGia ); Gia_ManCleanMark1( pGia ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFilterEquivsUsingLatches( Gia_Man_t * pGia, int fFlopsOnly, int fFlopsWith, int fUseRiDrivers ) { Gia_Obj_t * pObjR; Vec_Int_t * vNodes, * vFfIds; int i, k, iObj, iNext, iPrev, iRepr; int iLitsOld = 0, iLitsNew = 0; assert( fFlopsOnly ^ fFlopsWith ); vNodes = Vec_IntAlloc( 100 ); // select nodes "flop" node IDs vFfIds = Vec_IntStart( Gia_ManObjNum(pGia) ); if ( fUseRiDrivers ) { Gia_ManForEachRi( pGia, pObjR, i ) Vec_IntWriteEntry( vFfIds, Gia_ObjFaninId0p(pGia, pObjR), 1 ); } else { Gia_ManForEachRo( pGia, pObjR, i ) Vec_IntWriteEntry( vFfIds, Gia_ObjId(pGia, pObjR), 1 ); } // remove all non-flop constants Gia_ManForEachConst( pGia, i ) { iLitsOld++; assert( pGia->pNexts[i] == 0 ); if ( !Vec_IntEntry(vFfIds, i) ) Gia_ObjUnsetRepr( pGia, i ); else iLitsNew++; } // clear the classes if ( fFlopsOnly ) { Gia_ManForEachClass( pGia, i ) { Vec_IntClear( vNodes ); Gia_ClassForEachObj( pGia, i, iObj ) { if ( Vec_IntEntry(vFfIds, iObj) ) Vec_IntPush( vNodes, iObj ); iLitsOld++; } iLitsOld--; // undo equivalence classes for ( iObj = i, iNext = Gia_ObjNext(pGia, iObj); iObj; iObj = iNext, iNext = Gia_ObjNext(pGia, iObj) ) { Gia_ObjUnsetRepr( pGia, iObj ); Gia_ObjSetNext( pGia, iObj, 0 ); } assert( !Gia_ObjIsHead(pGia, i) ); if ( Vec_IntSize(vNodes) > 1 ) { // create new class iPrev = iRepr = Vec_IntEntry( vNodes, 0 ); Vec_IntForEachEntryStart( vNodes, iObj, k, 1 ) { Gia_ObjSetRepr( pGia, iObj, iRepr ); Gia_ObjSetNext( pGia, iPrev, iObj ); iPrev = iObj; iLitsNew++; } assert( Gia_ObjNext(pGia, iPrev) == 0 ); } } } else { Gia_ManForEachClass( pGia, i ) { int fSeenFlop = 0; Gia_ClassForEachObj( pGia, i, iObj ) { if ( Vec_IntEntry(vFfIds, iObj) ) fSeenFlop = 1; iLitsOld++; iLitsNew++; } iLitsOld--; iLitsNew--; if ( fSeenFlop ) continue; // undo equivalence classes for ( iObj = i, iNext = Gia_ObjNext(pGia, iObj); iObj; iObj = iNext, iNext = Gia_ObjNext(pGia, iObj) ) { Gia_ObjUnsetRepr( pGia, iObj ); Gia_ObjSetNext( pGia, iObj, 0 ); iLitsNew--; } iLitsNew++; assert( !Gia_ObjIsHead(pGia, i) ); } } Vec_IntFree( vNodes ); Vec_IntFree( vFfIds ); 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 [Transfer from new to old.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManTransferEquivs2( Gia_Man_t * p, Gia_Man_t * pOld ) { Gia_Obj_t * pObj; Vec_Int_t * vClass; int i, k, iNode, iRepr; assert( p->pReprs != NULL ); assert( p->pNexts != NULL ); assert( pOld->pReprs == NULL ); assert( pOld->pNexts == NULL ); // create map Gia_ManFillValue( p ); Gia_ManForEachObj( pOld, pObj, i ) if ( ~pObj->Value ) Gia_ManObj(p, Abc_Lit2Var(pObj->Value))->Value = Abc_Var2Lit(i, 0); // start representatives pOld->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pOld) ); for ( i = 0; i < Gia_ManObjNum(pOld); i++ ) Gia_ObjSetRepr( pOld, i, GIA_VOID ); // iterate over constant candidates Gia_ManForEachConst( p, i ) Gia_ObjSetRepr( pOld, Abc_Lit2Var(Gia_ManObj(p, i)->Value), 0 ); // iterate over class candidates vClass = Vec_IntAlloc( 100 ); Gia_ManForEachClass( p, i ) { Vec_IntClear( vClass ); Gia_ClassForEachObj( p, i, k ) if ( (int)Gia_ManObj(p, k)->Value >= 0 ) Vec_IntPushUnique( vClass, Abc_Lit2Var(Gia_ManObj(p, k)->Value) ); if ( Vec_IntSize( vClass ) <= 1 ) continue; assert( Vec_IntSize( vClass ) > 1 ); Vec_IntSort( vClass, 0 ); iRepr = Vec_IntEntry( vClass, 0 ); Vec_IntForEachEntryStart( vClass, iNode, k, 1 ) Gia_ObjSetRepr( pOld, iNode, iRepr ); } Vec_IntFree( vClass ); pOld->pNexts = Gia_ManDeriveNexts( pOld ); } /**Function************************************************************* 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 /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaEra.c000066400000000000000000000464431477524141600156360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaEra.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Explicit reachability analysis.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaEra.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/mem/mem.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // explicit state representation typedef struct Gia_ObjEra_t_ Gia_ObjEra_t; struct Gia_ObjEra_t_ { int Num; // ID of this state int Cond; // input condition int iPrev; // previous state int iNext; // next state in the hash table unsigned pData[0]; // state bits }; // explicit state reachability typedef struct Gia_ManEra_t_ Gia_ManEra_t; struct Gia_ManEra_t_ { Gia_Man_t * pAig; // user's AIG manager int nWordsSim; // 2^(PInum) int nWordsDat; // Abc_BitWordNum unsigned * pDataSim; // simulation data Mem_Fixed_t * pMemory; // memory manager Vec_Ptr_t * vStates; // reached states Gia_ObjEra_t * pStateNew; // temporary state int iCurState; // the current state Vec_Int_t * vBugTrace; // the sequence of transitions Vec_Int_t * vStgDump; // STG written into a file // hash table for states int nBins; unsigned * pBins; }; static inline unsigned * Gia_ManEraData( Gia_ManEra_t * p, int i ) { return p->pDataSim + i * p->nWordsSim; } static inline Gia_ObjEra_t * Gia_ManEraState( Gia_ManEra_t * p, int i ) { return (Gia_ObjEra_t *)Vec_PtrEntry(p->vStates, i); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates reachability manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_ManEra_t * Gia_ManEraCreate( Gia_Man_t * pAig ) { Vec_Ptr_t * vTruths; Gia_ManEra_t * p; unsigned * pTruth, * pSimInfo; int i; p = ABC_CALLOC( Gia_ManEra_t, 1 ); p->pAig = pAig; p->nWordsSim = Abc_TruthWordNum( Gia_ManPiNum(pAig) ); p->nWordsDat = Abc_BitWordNum( Gia_ManRegNum(pAig) ); p->pDataSim = ABC_ALLOC( unsigned, p->nWordsSim*Gia_ManObjNum(pAig) ); p->pMemory = Mem_FixedStart( sizeof(Gia_ObjEra_t) + sizeof(unsigned) * p->nWordsDat ); p->vStates = Vec_PtrAlloc( 100000 ); p->nBins = Abc_PrimeCudd( 100000 ); p->pBins = ABC_CALLOC( unsigned, p->nBins ); Vec_PtrPush( p->vStates, NULL ); // assign primary input values vTruths = Vec_PtrAllocTruthTables( Gia_ManPiNum(pAig) ); Vec_PtrForEachEntry( unsigned *, vTruths, pTruth, i ) { pSimInfo = Gia_ManEraData( p, Gia_ObjId(pAig, Gia_ManPi(pAig, i)) ); memcpy( pSimInfo, pTruth, sizeof(unsigned) * p->nWordsSim ); } Vec_PtrFree( vTruths ); // assign constant zero node pSimInfo = Gia_ManEraData( p, 0 ); memset( pSimInfo, 0, sizeof(unsigned) * p->nWordsSim ); p->vStgDump = Vec_IntAlloc( 1000 ); return p; } /**Function************************************************************* Synopsis [Deletes reachability manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManEraFree( Gia_ManEra_t * p ) { Mem_FixedStop( p->pMemory, 0 ); Vec_IntFree( p->vStgDump ); Vec_PtrFree( p->vStates ); if ( p->vBugTrace ) Vec_IntFree( p->vBugTrace ); ABC_FREE( p->pDataSim ); ABC_FREE( p->pBins ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates new state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_ObjEra_t * Gia_ManEraCreateState( Gia_ManEra_t * p ) { Gia_ObjEra_t * pNew; pNew = (Gia_ObjEra_t *)Mem_FixedEntryFetch( p->pMemory ); pNew->Num = Vec_PtrSize( p->vStates ); pNew->iPrev = 0; Vec_PtrPush( p->vStates, pNew ); return pNew; } /**Function************************************************************* Synopsis [Computes hash value of the node using its simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManEraStateHash( unsigned * pState, int nWordsSim, int nTableSize ) { static int s_FPrimes[128] = { 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 }; unsigned uHash; int i; uHash = 0; for ( i = 0; i < nWordsSim; i++ ) uHash ^= pState[i] * s_FPrimes[i & 0x7F]; return uHash % nTableSize; } /**Function************************************************************* Synopsis [Returns the place of this state in the table or NULL if it exists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned * Gia_ManEraHashFind( Gia_ManEra_t * p, Gia_ObjEra_t * pState, int * pStateNum ) { Gia_ObjEra_t * pThis; unsigned * pPlace = p->pBins + Gia_ManEraStateHash( pState->pData, p->nWordsDat, p->nBins ); for ( pThis = (*pPlace)? Gia_ManEraState(p, *pPlace) : NULL; pThis; pPlace = (unsigned *)&pThis->iNext, pThis = (*pPlace)? Gia_ManEraState(p, *pPlace) : NULL ) if ( !memcmp( pState->pData, pThis->pData, sizeof(unsigned) * p->nWordsDat ) ) { if ( pStateNum ) *pStateNum = pThis->Num; return NULL; } if ( pStateNum ) *pStateNum = -1; return pPlace; } /**Function************************************************************* Synopsis [Resizes the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManEraHashResize( Gia_ManEra_t * p ) { Gia_ObjEra_t * pThis; unsigned * pBinsOld, * piPlace; int nBinsOld, iNext, Counter, i; assert( p->pBins != NULL ); // replace the table pBinsOld = p->pBins; nBinsOld = p->nBins; p->nBins = Abc_PrimeCudd( 3 * p->nBins ); p->pBins = ABC_CALLOC( unsigned, p->nBins ); // rehash the entries from the old table Counter = 0; for ( i = 0; i < nBinsOld; i++ ) for ( pThis = (pBinsOld[i]? Gia_ManEraState(p, pBinsOld[i]) : NULL), iNext = (pThis? pThis->iNext : 0); pThis; pThis = (iNext? Gia_ManEraState(p, iNext) : NULL), iNext = (pThis? pThis->iNext : 0) ) { assert( pThis->Num ); pThis->iNext = 0; piPlace = Gia_ManEraHashFind( p, pThis, NULL ); assert( *piPlace == 0 ); // should not be there *piPlace = pThis->Num; Counter++; } assert( Counter == Vec_PtrSize( p->vStates ) - 1 ); ABC_FREE( pBinsOld ); } /**Function************************************************************* Synopsis [Initialize register output to the given state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManInsertState( Gia_ManEra_t * p, Gia_ObjEra_t * pState ) { Gia_Obj_t * pObj; unsigned * pSimInfo; int i; Gia_ManForEachRo( p->pAig, pObj, i ) { pSimInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) ); if ( Abc_InfoHasBit(pState->pData, i) ) memset( pSimInfo, 0xff, sizeof(unsigned) * p->nWordsSim ); else memset( pSimInfo, 0, sizeof(unsigned) * p->nWordsSim ); } } /**Function************************************************************* Synopsis [Returns -1 if outputs are not asserted.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManOutputAsserted( Gia_ManEra_t * p, Gia_Obj_t * pObj ) { unsigned * pInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) ); int w; for ( w = 0; w < p->nWordsSim; w++ ) if ( pInfo[w] ) return 32*w + Gia_WordFindFirstBit( pInfo[w] ); return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSimulateCo( Gia_ManEra_t * p, Gia_Obj_t * pObj ) { int Id = Gia_ObjId(p->pAig, pObj); unsigned * pInfo = Gia_ManEraData( p, Id ); unsigned * pInfo0 = Gia_ManEraData( p, Gia_ObjFaninId0(pObj, Id) ); int w; if ( Gia_ObjFaninC0(pObj) ) for ( w = p->nWordsSim-1; w >= 0; w-- ) pInfo[w] = ~pInfo0[w]; else for ( w = p->nWordsSim-1; w >= 0; w-- ) pInfo[w] = pInfo0[w]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSimulateNode( Gia_ManEra_t * p, Gia_Obj_t * pObj ) { int Id = Gia_ObjId(p->pAig, pObj); unsigned * pInfo = Gia_ManEraData( p, Id ); unsigned * pInfo0 = Gia_ManEraData( p, Gia_ObjFaninId0(pObj, Id) ); unsigned * pInfo1 = Gia_ManEraData( p, Gia_ObjFaninId1(pObj, Id) ); int w; if ( Gia_ObjFaninC0(pObj) ) { if ( Gia_ObjFaninC1(pObj) ) for ( w = p->nWordsSim-1; w >= 0; w-- ) pInfo[w] = ~(pInfo0[w] | pInfo1[w]); else for ( w = p->nWordsSim-1; w >= 0; w-- ) pInfo[w] = ~pInfo0[w] & pInfo1[w]; } else { if ( Gia_ObjFaninC1(pObj) ) for ( w = p->nWordsSim-1; w >= 0; w-- ) pInfo[w] = pInfo0[w] & ~pInfo1[w]; else for ( w = p->nWordsSim-1; w >= 0; w-- ) pInfo[w] = pInfo0[w] & pInfo1[w]; } } /**Function************************************************************* Synopsis [Performs one iteration of reachability analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPerformOneIter( Gia_ManEra_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj1( p->pAig, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) Gia_ManSimulateNode( p, pObj ); else if ( Gia_ObjIsCo(pObj) ) Gia_ManSimulateCo( p, pObj ); } } /**Function************************************************************* Synopsis [Performs one iteration of reachability analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManCollectBugTrace( Gia_ManEra_t * p, Gia_ObjEra_t * pState, int iCond ) { Vec_Int_t * vTrace; vTrace = Vec_IntAlloc( 10 ); Vec_IntPush( vTrace, iCond ); for ( ; pState; pState = pState->iPrev ? Gia_ManEraState(p, pState->iPrev) : NULL ) Vec_IntPush( vTrace, pState->Cond ); Vec_IntReverseOrder( vTrace ); return vTrace; } /**Function************************************************************* Synopsis [Counts the depth of state transitions leading ot this state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCountDepth( Gia_ManEra_t * p ) { Gia_ObjEra_t * pState; int Counter = 0; pState = (Gia_ObjEra_t *)Vec_PtrEntryLast( p->vStates ); if ( pState->iPrev == 0 && Vec_PtrSize(p->vStates) > 3 ) pState = (Gia_ObjEra_t *)Vec_PtrEntry( p->vStates, Vec_PtrSize(p->vStates) - 2 ); for ( ; pState; pState = pState->iPrev ? Gia_ManEraState(p, pState->iPrev) : NULL ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Analized reached states.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManAnalyzeResult( Gia_ManEra_t * p, Gia_ObjEra_t * pState, int fMiter, int fStgDump ) { Gia_Obj_t * pObj; unsigned * pSimInfo, * piPlace, uOutput = 0; int i, k, iCond, nMints, iNextState; // check if the miter is asserted if ( fMiter ) { Gia_ManForEachPo( p->pAig, pObj, i ) { iCond = Gia_ManOutputAsserted( p, pObj ); if ( iCond >= 0 ) { p->vBugTrace = Gia_ManCollectBugTrace( p, pState, iCond ); return 1; } } } // collect reached states nMints = (1 << Gia_ManPiNum(p->pAig)); for ( k = 0; k < nMints; k++ ) { if ( p->pStateNew == NULL ) p->pStateNew = Gia_ManEraCreateState( p ); p->pStateNew->pData[p->nWordsDat-1] = 0; Gia_ManForEachRi( p->pAig, pObj, i ) { pSimInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) ); if ( Abc_InfoHasBit(p->pStateNew->pData, i) != Abc_InfoHasBit(pSimInfo, k) ) Abc_InfoXorBit( p->pStateNew->pData, i ); } if ( fStgDump ) { uOutput = 0; Gia_ManForEachPo( p->pAig, pObj, i ) { pSimInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) ); if ( Abc_InfoHasBit(pSimInfo, k) && i < 32 ) Abc_InfoXorBit( &uOutput, i ); } } piPlace = Gia_ManEraHashFind( p, p->pStateNew, &iNextState ); if ( fStgDump ) Vec_IntPush( p->vStgDump, k ); if ( fStgDump ) Vec_IntPush( p->vStgDump, pState->Num ); if ( piPlace == NULL ) { if ( fStgDump ) Vec_IntPush( p->vStgDump, iNextState ); if ( fStgDump ) Vec_IntPush( p->vStgDump, uOutput ); continue; } if ( fStgDump ) Vec_IntPush( p->vStgDump, p->pStateNew->Num ); if ( fStgDump ) Vec_IntPush( p->vStgDump, uOutput ); //printf( "Inserting %d ", Vec_PtrSize(p->vStates) ); //Extra_PrintBinary( stdout, p->pStateNew->pData, Gia_ManRegNum(p->pAig) ); printf( "\n" ); assert( *piPlace == 0 ); *piPlace = p->pStateNew->Num; p->pStateNew->Cond = k; p->pStateNew->iPrev = pState->Num; p->pStateNew->iNext = 0; p->pStateNew = NULL; // expand hash table if needed if ( Vec_PtrSize(p->vStates) > 2 * p->nBins ) Gia_ManEraHashResize( p ); } return 0; } /**Function************************************************************* Synopsis [Resizes the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCollectReachable( Gia_Man_t * pAig, int nStatesMax, int fMiter, int fDumpFile, int fVerbose ) { Gia_ManEra_t * p; Gia_ObjEra_t * pState; int Hash; abctime clk = Abc_Clock(); int RetValue = 1; assert( Gia_ManPiNum(pAig) <= 12 ); assert( Gia_ManRegNum(pAig) > 0 ); p = Gia_ManEraCreate( pAig ); // create init state pState = Gia_ManEraCreateState( p ); pState->Cond = 0; pState->iPrev = 0; pState->iNext = 0; memset( pState->pData, 0, sizeof(unsigned) * p->nWordsDat ); Hash = Gia_ManEraStateHash(pState->pData, p->nWordsDat, p->nBins); p->pBins[ Hash ] = pState->Num; // process reachable states while ( p->iCurState < Vec_PtrSize( p->vStates ) - 1 ) { if ( Vec_PtrSize(p->vStates) >= nStatesMax ) { printf( "Reached the limit on states traversed (%d). ", nStatesMax ); RetValue = -1; break; } pState = Gia_ManEraState( p, ++p->iCurState ); if ( p->iCurState > 1 && pState->iPrev == 0 ) continue; //printf( "Extracting %d ", p->iCurState ); //Extra_PrintBinary( stdout, p->pStateNew->pData, Gia_ManRegNum(p->pAig) ); printf( "\n" ); Gia_ManInsertState( p, pState ); Gia_ManPerformOneIter( p ); if ( Gia_ManAnalyzeResult( p, pState, fMiter, fDumpFile ) && fMiter ) { RetValue = 0; printf( "Miter failed in state %d after %d transitions. ", p->iCurState, Vec_IntSize(p->vBugTrace)-1 ); break; } if ( fVerbose && p->iCurState % 5000 == 0 ) { printf( "States =%10d. Reached =%10d. R = %5.3f. Depth =%6d. Mem =%9.2f MB. ", p->iCurState, Vec_PtrSize(p->vStates), 1.0*p->iCurState/Vec_PtrSize(p->vStates), Gia_ManCountDepth(p), (1.0/(1<<20))*(1.0*Vec_PtrSize(p->vStates)*(sizeof(Gia_ObjEra_t) + sizeof(unsigned) * p->nWordsDat) + 1.0*p->nBins*sizeof(unsigned) + 1.0*p->vStates->nCap * sizeof(void*)) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } printf( "Reachability analysis traversed %d states with depth %d. ", p->iCurState-1, Gia_ManCountDepth(p) ); ABC_PRT( "Time", Abc_Clock() - clk ); if ( fDumpFile ) { char * pFileName = "test.stg"; FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) printf( "Cannot open file \"%s\" for writing.\n", pFileName ); else { Gia_ManStgPrint( pFile, p->vStgDump, Gia_ManPiNum(pAig), Gia_ManPoNum(pAig), p->iCurState-1 ); fclose( pFile ); printf( "Extracted STG was written into file \"%s\".\n", pFileName ); } } Gia_ManEraFree( p ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaEra2.c000066400000000000000000001743411477524141600157170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [gia.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" #include "giaAig.h" ABC_NAMESPACE_IMPL_START /* Limitations of this package: - no more than (1<<31)-1 state cubes and internal nodes - no more than MAX_VARS_NUM state variables - no more than MAX_CALL_NUM transitions from a state - cube list rebalancing happens when cube count reaches MAX_CUBE_NUM */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define MAX_CALL_NUM (1000000) // the max number of recursive calls #define MAX_ITEM_NUM (1<<20) // the number of items on a page #define MAX_PAGE_NUM (1<<11) // the max number of memory pages #define MAX_VARS_NUM (1<<14) // the max number of state vars allowed #define MAX_CUBE_NUM 63 // the max number of cubes before rebalancing // pointer to the tree node or state cube typedef struct Gia_PtrAre_t_ Gia_PtrAre_t; struct Gia_PtrAre_t_ { unsigned nItem : 20; // item number (related to MAX_ITEM_NUM) unsigned nPage : 11; // page number (related to MAX_PAGE_NUM) unsigned fMark : 1; // user mark }; typedef union Gia_PtrAreInt_t_ Gia_PtrAreInt_t; union Gia_PtrAreInt_t_ { Gia_PtrAre_t iGia; unsigned iInt; }; // tree nodes typedef struct Gia_ObjAre_t_ Gia_ObjAre_t; struct Gia_ObjAre_t_ { unsigned iVar : 14; // variable (related to MAX_VARS_NUM) unsigned nStas0 : 6; // cube counter (related to MAX_CUBE_NUM) unsigned nStas1 : 6; // cube counter (related to MAX_CUBE_NUM) unsigned nStas2 : 6; // cube counter (related to MAX_CUBE_NUM) Gia_PtrAre_t F[3]; // branches }; // state cube typedef struct Gia_StaAre_t_ Gia_StaAre_t; struct Gia_StaAre_t_ { Gia_PtrAre_t iPrev; // previous state Gia_PtrAre_t iNext; // next cube in the list unsigned pData[0]; // state bits }; // explicit state reachability manager typedef struct Gia_ManAre_t_ Gia_ManAre_t; struct Gia_ManAre_t_ { Gia_Man_t * pAig; // user's AIG manager Gia_Man_t * pNew; // temporary AIG manager unsigned ** ppObjs; // storage for objects (MAX_PAGE_NUM pages) unsigned ** ppStas; // storage for states (MAX_PAGE_NUM pages) // unsigned * pfUseless; // to label useless cubes // int nUselessAlloc; // the number of useless alloced // internal flags int fMiter; // stops when a bug is discovered int fStopped; // set high when reachability is stopped int fTree; // working in the tree mode // internal parametesr int nWords; // the size of bit info in words int nSize; // the size of state structure in words int nObjPages; // the number of pages used for objects int nStaPages; // the number of pages used for states int nObjs; // the number of objects int nStas; // the number of states int iStaCur; // the next state to be explored Gia_PtrAre_t Root; // root of the tree Vec_Vec_t * vCiTfos; // storage for nodes in the CI TFOs Vec_Vec_t * vCiLits; // storage for literals of these nodes Vec_Int_t * vCubesA; // checked cubes Vec_Int_t * vCubesB; // unchecked cubes // deriving counter-example void * pSat; // SAT solver Vec_Int_t * vSatNumCis; // SAT variables for CIs Vec_Int_t * vSatNumCos; // SAT variables for COs Vec_Int_t * vCofVars; // variables used to cofactor Vec_Int_t * vAssumps; // temporary storage for assumptions Gia_StaAre_t * pTarget; // state that needs to be reached int iOutFail; // the number of the failed output // statistics int nChecks; // the number of timea cube was checked int nEquals; // total number of equal int nCompares; // the number of compares int nRecCalls; // the number of rec calls int nDisjs; // the number of disjoint cube pairs int nDisjs2; // the number of disjoint cube pairs int nDisjs3; // the number of disjoint cube pairs // time int timeAig; // AIG cofactoring time int timeCube; // cube checking time }; static inline Gia_PtrAre_t Gia_Int2Ptr( unsigned n ) { Gia_PtrAreInt_t g; g.iInt = n; return g.iGia; } static inline unsigned Gia_Ptr2Int( Gia_PtrAre_t n ) { Gia_PtrAreInt_t g; g.iGia = n; return g.iInt & 0x7fffffff; } static inline int Gia_ObjHasBranch0( Gia_ObjAre_t * q ) { return !q->nStas0 && (q->F[0].nPage || q->F[0].nItem); } static inline int Gia_ObjHasBranch1( Gia_ObjAre_t * q ) { return !q->nStas1 && (q->F[1].nPage || q->F[1].nItem); } static inline int Gia_ObjHasBranch2( Gia_ObjAre_t * q ) { return !q->nStas2 && (q->F[2].nPage || q->F[2].nItem); } static inline Gia_ObjAre_t * Gia_ManAreObj( Gia_ManAre_t * p, Gia_PtrAre_t n ) { return (Gia_ObjAre_t *)(p->ppObjs[n.nPage] + (n.nItem << 2)); } static inline Gia_StaAre_t * Gia_ManAreSta( Gia_ManAre_t * p, Gia_PtrAre_t n ) { return (Gia_StaAre_t *)(p->ppStas[n.nPage] + n.nItem * p->nSize); } static inline Gia_ObjAre_t * Gia_ManAreObjInt( Gia_ManAre_t * p, int n ) { return Gia_ManAreObj( p, Gia_Int2Ptr(n) ); } static inline Gia_StaAre_t * Gia_ManAreStaInt( Gia_ManAre_t * p, int n ) { return Gia_ManAreSta( p, Gia_Int2Ptr(n) ); } static inline Gia_ObjAre_t * Gia_ManAreObjLast( Gia_ManAre_t * p ) { return Gia_ManAreObjInt( p, p->nObjs-1 ); } static inline Gia_StaAre_t * Gia_ManAreStaLast( Gia_ManAre_t * p ) { return Gia_ManAreStaInt( p, p->nStas-1 ); } static inline Gia_ObjAre_t * Gia_ObjNextObj0( Gia_ManAre_t * p, Gia_ObjAre_t * q ) { return Gia_ManAreObj( p, q->F[0] ); } static inline Gia_ObjAre_t * Gia_ObjNextObj1( Gia_ManAre_t * p, Gia_ObjAre_t * q ) { return Gia_ManAreObj( p, q->F[1] ); } static inline Gia_ObjAre_t * Gia_ObjNextObj2( Gia_ManAre_t * p, Gia_ObjAre_t * q ) { return Gia_ManAreObj( p, q->F[2] ); } static inline int Gia_StaHasValue0( Gia_StaAre_t * p, int iReg ) { return Abc_InfoHasBit( p->pData, iReg << 1 ); } static inline int Gia_StaHasValue1( Gia_StaAre_t * p, int iReg ) { return Abc_InfoHasBit( p->pData, (iReg << 1) + 1 ); } static inline void Gia_StaSetValue0( Gia_StaAre_t * p, int iReg ) { Abc_InfoSetBit( p->pData, iReg << 1 ); } static inline void Gia_StaSetValue1( Gia_StaAre_t * p, int iReg ) { Abc_InfoSetBit( p->pData, (iReg << 1) + 1 ); } static inline Gia_StaAre_t * Gia_StaPrev( Gia_ManAre_t * p, Gia_StaAre_t * pS ) { return Gia_ManAreSta(p, pS->iPrev); } static inline Gia_StaAre_t * Gia_StaNext( Gia_ManAre_t * p, Gia_StaAre_t * pS ) { return Gia_ManAreSta(p, pS->iNext); } static inline int Gia_StaIsGood( Gia_ManAre_t * p, Gia_StaAre_t * pS ) { return ((unsigned *)pS) != p->ppStas[0]; } static inline void Gia_StaSetUnused( Gia_StaAre_t * pS ) { pS->iPrev.fMark = 1; } static inline int Gia_StaIsUnused( Gia_StaAre_t * pS ) { return pS->iPrev.fMark; } static inline int Gia_StaIsUsed( Gia_StaAre_t * pS ) { return !pS->iPrev.fMark; } #define Gia_ManAreForEachCubeList( p, pList, pCube ) \ for ( pCube = pList; Gia_StaIsGood(p, pCube); pCube = Gia_StaNext(p, pCube) ) #define Gia_ManAreForEachCubeList2( p, iList, pCube, iCube ) \ for ( iCube = Gia_Ptr2Int(iList), pCube = Gia_ManAreSta(p, iList); \ Gia_StaIsGood(p, pCube); \ iCube = Gia_Ptr2Int(pCube->iNext), pCube = Gia_StaNext(p, pCube) ) #define Gia_ManAreForEachCubeStore( p, pCube, i ) \ for ( i = 1; i < p->nStas && (pCube = Gia_ManAreStaInt(p, i)); i++ ) #define Gia_ManAreForEachCubeVec( vVec, p, pCube, i ) \ for ( i = 0; i < Vec_IntSize(vVec) && (pCube = Gia_ManAreStaInt(p, Vec_IntEntry(vVec,i))); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Count state minterms contained in a cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCountMintermsInCube( Gia_StaAre_t * pCube, int nVars, unsigned * pStore ) { unsigned Mint, Mask = 0; int i, m, nMints, nDashes = 0, Dashes[32]; // count the number of dashes for ( i = 0; i < nVars; i++ ) { if ( Gia_StaHasValue0( pCube, i ) ) continue; if ( Gia_StaHasValue1( pCube, i ) ) Mask |= (1 << i); else Dashes[nDashes++] = i; } // fill in the miterms nMints = (1 << nDashes); for ( m = 0; m < nMints; m++ ) { Mint = Mask; for ( i = 0; i < nVars; i++ ) if ( m & (1 << i) ) Mint |= (1 << Dashes[i]); Abc_InfoSetBit( pStore, Mint ); } } /**Function************************************************************* Synopsis [Count state minterms contains in the used cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCountMinterms( Gia_ManAre_t * p ) { Gia_StaAre_t * pCube; unsigned * pMemory; int i, nMemSize, Counter = 0; if ( Gia_ManRegNum(p->pAig) > 30 ) return -1; nMemSize = Abc_BitWordNum( 1 << Gia_ManRegNum(p->pAig) ); pMemory = ABC_CALLOC( unsigned, nMemSize ); Gia_ManAreForEachCubeStore( p, pCube, i ) if ( Gia_StaIsUsed(pCube) ) Gia_ManCountMintermsInCube( pCube, Gia_ManRegNum(p->pAig), pMemory ); for ( i = 0; i < nMemSize; i++ ) Counter += Gia_WordCountOnes( pMemory[i] ); ABC_FREE( pMemory ); return Counter; } /**Function************************************************************* Synopsis [Derives the TFO of one CI.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManDeriveCiTfo_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vRes ) { if ( Gia_ObjIsCi(pObj) ) return pObj->fMark0; if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return pObj->fMark0; Gia_ObjSetTravIdCurrent(p, pObj); assert( Gia_ObjIsAnd(pObj) ); Gia_ManDeriveCiTfo_rec( p, Gia_ObjFanin0(pObj), vRes ); Gia_ManDeriveCiTfo_rec( p, Gia_ObjFanin1(pObj), vRes ); pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 | Gia_ObjFanin1(pObj)->fMark0; if ( pObj->fMark0 ) Vec_IntPush( vRes, Gia_ObjId(p, pObj) ); return pObj->fMark0; } /**Function************************************************************* Synopsis [Derives the TFO of one CI.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManDeriveCiTfoOne( Gia_Man_t * p, Gia_Obj_t * pPivot ) { Vec_Int_t * vRes; Gia_Obj_t * pObj; int i; assert( pPivot->fMark0 == 0 ); pPivot->fMark0 = 1; vRes = Vec_IntAlloc( 100 ); Vec_IntPush( vRes, Gia_ObjId(p, pPivot) ); Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); Gia_ManForEachCo( p, pObj, i ) { Gia_ManDeriveCiTfo_rec( p, Gia_ObjFanin0(pObj), vRes ); if ( Gia_ObjFanin0(pObj)->fMark0 ) Vec_IntPush( vRes, Gia_ObjId(p, pObj) ); } pPivot->fMark0 = 0; return vRes; } /**Function************************************************************* Synopsis [Derives the TFO of each CI.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Gia_ManDeriveCiTfo( Gia_Man_t * p ) { Vec_Ptr_t * vRes; Gia_Obj_t * pPivot; int i; Gia_ManCleanMark0( p ); Gia_ManIncrementTravId( p ); vRes = Vec_PtrAlloc( Gia_ManCiNum(p) ); Gia_ManForEachCi( p, pPivot, i ) Vec_PtrPush( vRes, Gia_ManDeriveCiTfoOne(p, pPivot) ); Gia_ManCleanMark0( p ); return (Vec_Vec_t *)vRes; } /**Function************************************************************* Synopsis [Returns 1 if states are equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_StaAreEqual( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( p1->pData[w] != p2->pData[w] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if states are disjoint.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_StaAreDisjoint( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( ((p1->pData[w] ^ p2->pData[w]) >> 1) & (p1->pData[w] ^ p2->pData[w]) & 0x55555555 ) return 1; return 0; } /**Function************************************************************* Synopsis [Returns 1 if cube p1 contains cube p2.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_StaAreContain( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords ) { int w; for ( w = 0; w < nWords; w++ ) if ( (p1->pData[w] | p2->pData[w]) != p2->pData[w] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns the number of dashes in p1 that are non-dashes in p2.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_StaAreDashNum( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords ) { int w, Counter = 0; for ( w = 0; w < nWords; w++ ) Counter += Gia_WordCountOnes( (~(p1->pData[w] ^ (p1->pData[w] >> 1))) & (p2->pData[w] ^ (p2->pData[w] >> 1)) & 0x55555555 ); return Counter; } /**Function************************************************************* Synopsis [Returns the number of a variable for sharping the cube.] Description [Counts the number of variables that have dash in p1 and non-dash in p2. If there is exactly one such variable, returns its index. Otherwise returns -1.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_StaAreSharpVar( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords ) { unsigned Word; int w, iVar = -1; for ( w = 0; w < nWords; w++ ) { Word = (~(p1->pData[w] ^ (p1->pData[w] >> 1))) & (p2->pData[w] ^ (p2->pData[w] >> 1)) & 0x55555555; if ( Word == 0 ) continue; if ( !Gia_WordHasOneBit(Word) ) return -1; // has exactly one bit if ( iVar >= 0 ) return -1; // the first variable of this type iVar = 16 * w + Gia_WordFindFirstBit( Word ) / 2; } return iVar; } /**Function************************************************************* Synopsis [Returns the number of a variable for merging the cubes.] Description [If there is exactly one such variable, returns its index. Otherwise returns -1.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_StaAreDisjointVar( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords ) { unsigned Word; int w, iVar = -1; for ( w = 0; w < nWords; w++ ) { Word = (p1->pData[w] ^ p2->pData[w]) & ((p1->pData[w] ^ p2->pData[w]) >> 1) & 0x55555555; if ( Word == 0 ) continue; if ( !Gia_WordHasOneBit(Word) ) return -1; // has exactly one bit if ( iVar >= 0 ) return -1; // the first variable of this type iVar = 16 * w + Gia_WordFindFirstBit( Word ) / 2; } return iVar; } /**Function************************************************************* Synopsis [Creates reachability manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_ManAre_t * Gia_ManAreCreate( Gia_Man_t * pAig ) { Gia_ManAre_t * p; assert( sizeof(Gia_ObjAre_t) == 16 ); p = ABC_CALLOC( Gia_ManAre_t, 1 ); p->pAig = pAig; p->nWords = Abc_BitWordNum( 2 * Gia_ManRegNum(pAig) ); p->nSize = sizeof(Gia_StaAre_t)/4 + p->nWords; p->ppObjs = ABC_CALLOC( unsigned *, MAX_PAGE_NUM ); p->ppStas = ABC_CALLOC( unsigned *, MAX_PAGE_NUM ); p->vCiTfos = Gia_ManDeriveCiTfo( pAig ); p->vCiLits = Vec_VecDupInt( p->vCiTfos ); p->vCubesA = Vec_IntAlloc( 100 ); p->vCubesB = Vec_IntAlloc( 100 ); p->iOutFail = -1; return p; } /**Function************************************************************* Synopsis [Deletes reachability manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManAreFree( Gia_ManAre_t * p ) { int i; Gia_ManStop( p->pAig ); if ( p->pNew ) Gia_ManStop( p->pNew ); Vec_IntFree( p->vCubesA ); Vec_IntFree( p->vCubesB ); Vec_VecFree( p->vCiTfos ); Vec_VecFree( p->vCiLits ); for ( i = 0; i < p->nObjPages; i++ ) ABC_FREE( p->ppObjs[i] ); ABC_FREE( p->ppObjs ); for ( i = 0; i < p->nStaPages; i++ ) ABC_FREE( p->ppStas[i] ); ABC_FREE( p->ppStas ); // ABC_FREE( p->pfUseless ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Returns new object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_ObjAre_t * Gia_ManAreCreateObj( Gia_ManAre_t * p ) { if ( p->nObjs == p->nObjPages * MAX_ITEM_NUM ) { if ( p->nObjPages == MAX_PAGE_NUM ) { printf( "ERA manager has run out of memory after allocating 2B internal nodes.\n" ); return NULL; } p->ppObjs[p->nObjPages++] = ABC_CALLOC( unsigned, MAX_ITEM_NUM * 4 ); if ( p->nObjs == 0 ) p->nObjs = 1; } return Gia_ManAreObjInt( p, p->nObjs++ ); } /**Function************************************************************* Synopsis [Returns new state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_StaAre_t * Gia_ManAreCreateSta( Gia_ManAre_t * p ) { if ( p->nStas == p->nStaPages * MAX_ITEM_NUM ) { if ( p->nStaPages == MAX_PAGE_NUM ) { printf( "ERA manager has run out of memory after allocating 2B state cubes.\n" ); return NULL; } if ( p->ppStas[p->nStaPages] == NULL ) p->ppStas[p->nStaPages] = ABC_CALLOC( unsigned, MAX_ITEM_NUM * p->nSize ); p->nStaPages++; if ( p->nStas == 0 ) { p->nStas = 1; // p->nUselessAlloc = (1 << 18); // p->pfUseless = ABC_CALLOC( unsigned, p->nUselessAlloc ); } // if ( p->nStas == p->nUselessAlloc * 32 ) // { // p->nUselessAlloc *= 2; // p->pfUseless = ABC_REALLOC( unsigned, p->pfUseless, p->nUselessAlloc ); // memset( p->pfUseless + p->nUselessAlloc/2, 0, sizeof(unsigned) * p->nUselessAlloc/2 ); // } } return Gia_ManAreStaInt( p, p->nStas++ ); } /**Function************************************************************* Synopsis [Recycles new state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManAreRycycleSta( Gia_ManAre_t * p, Gia_StaAre_t * pSta ) { memset( pSta, 0, p->nSize << 2 ); if ( pSta == Gia_ManAreStaLast(p) ) { p->nStas--; if ( p->nStas == (p->nStaPages-1) * MAX_ITEM_NUM ) p->nStaPages--; } else { // Gia_StaSetUnused( pSta ); } } /**Function************************************************************* Synopsis [Creates new state state from the latch values.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_StaAre_t * Gia_ManAreCreateStaNew( Gia_ManAre_t * p ) { Gia_StaAre_t * pSta; Gia_Obj_t * pObj; int i; pSta = Gia_ManAreCreateSta( p ); Gia_ManForEachRi( p->pAig, pObj, i ) { if ( pObj->Value == 0 ) Gia_StaSetValue0( pSta, i ); else if ( pObj->Value == 1 ) Gia_StaSetValue1( pSta, i ); } return pSta; } /**Function************************************************************* Synopsis [Creates new state state with latch init values.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_StaAre_t * Gia_ManAreCreateStaInit( Gia_ManAre_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachRi( p->pAig, pObj, i ) pObj->Value = 0; return Gia_ManAreCreateStaNew( p ); } /**Function************************************************************* Synopsis [Prints the state cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManArePrintCube( Gia_ManAre_t * p, Gia_StaAre_t * pSta ) { Gia_Obj_t * pObj; int i, Count0 = 0, Count1 = 0, Count2 = 0; printf( "%4d %4d : ", p->iStaCur, p->nStas-1 ); printf( "Prev %4d ", Gia_Ptr2Int(pSta->iPrev) ); printf( "%p ", pSta ); Gia_ManForEachRi( p->pAig, pObj, i ) { if ( Gia_StaHasValue0(pSta, i) ) printf( "0" ), Count0++; else if ( Gia_StaHasValue1(pSta, i) ) printf( "1" ), Count1++; else printf( "-" ), Count2++; } printf( " 0 =%3d", Count0 ); printf( " 1 =%3d", Count1 ); printf( " - =%3d", Count2 ); printf( "\n" ); } /**Function************************************************************* Synopsis [Counts the depth of state transitions leading ot this state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManAreDepth( Gia_ManAre_t * p, int iState ) { Gia_StaAre_t * pSta; int Counter = 0; for ( pSta = Gia_ManAreStaInt(p, iState); Gia_StaIsGood(p, pSta); pSta = Gia_StaPrev(p, pSta) ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Counts the number of cubes in the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManAreListCountListUsed( Gia_ManAre_t * p, Gia_PtrAre_t Root ) { Gia_StaAre_t * pCube; int Counter = 0; Gia_ManAreForEachCubeList( p, Gia_ManAreSta(p, Root), pCube ) Counter += Gia_StaIsUsed(pCube); return Counter; } /**Function************************************************************* Synopsis [Counts the number of used cubes in the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManAreListCountUsed_rec( Gia_ManAre_t * p, Gia_PtrAre_t Root, int fTree ) { Gia_ObjAre_t * pObj; if ( !fTree ) return Gia_ManAreListCountListUsed( p, Root ); pObj = Gia_ManAreObj(p, Root); return Gia_ManAreListCountUsed_rec( p, pObj->F[0], Gia_ObjHasBranch0(pObj) ) + Gia_ManAreListCountUsed_rec( p, pObj->F[1], Gia_ObjHasBranch1(pObj) ) + Gia_ManAreListCountUsed_rec( p, pObj->F[2], Gia_ObjHasBranch2(pObj) ); } /**Function************************************************************* Synopsis [Counts the number of used cubes in the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManAreListCountUsed( Gia_ManAre_t * p ) { return Gia_ManAreListCountUsed_rec( p, p->Root, p->fTree ); } /**Function************************************************************* Synopsis [Prints used cubes in the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManArePrintListUsed( Gia_ManAre_t * p, Gia_PtrAre_t Root ) { Gia_StaAre_t * pCube; Gia_ManAreForEachCubeList( p, Gia_ManAreSta(p, Root), pCube ) if ( Gia_StaIsUsed(pCube) ) Gia_ManArePrintCube( p, pCube ); return 1; } /**Function************************************************************* Synopsis [Prints used cubes in the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManArePrintUsed_rec( Gia_ManAre_t * p, Gia_PtrAre_t Root, int fTree ) { Gia_ObjAre_t * pObj; if ( !fTree ) return Gia_ManArePrintListUsed( p, Root ); pObj = Gia_ManAreObj(p, Root); return Gia_ManArePrintUsed_rec( p, pObj->F[0], Gia_ObjHasBranch0(pObj) ) + Gia_ManArePrintUsed_rec( p, pObj->F[1], Gia_ObjHasBranch1(pObj) ) + Gia_ManArePrintUsed_rec( p, pObj->F[2], Gia_ObjHasBranch2(pObj) ); } /**Function************************************************************* Synopsis [Prints used cubes in the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManArePrintUsed( Gia_ManAre_t * p ) { return Gia_ManArePrintUsed_rec( p, p->Root, p->fTree ); } /**Function************************************************************* Synopsis [Best var has max weight.] Description [Weight is defined as the number of 0/1-lits minus the absolute value of the diff between the number of 0-lits and 1-lits.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManAreFindBestVar( Gia_ManAre_t * p, Gia_PtrAre_t List ) { Gia_StaAre_t * pCube; int Count0, Count1, Count2; int iVarThis, iVarBest = -1, WeightThis, WeightBest = -1; for ( iVarThis = 0; iVarThis < Gia_ManRegNum(p->pAig); iVarThis++ ) { Count0 = Count1 = Count2 = 0; Gia_ManAreForEachCubeList( p, Gia_ManAreSta(p, List), pCube ) { if ( Gia_StaIsUnused(pCube) ) continue; if ( Gia_StaHasValue0(pCube, iVarThis) ) Count0++; else if ( Gia_StaHasValue1(pCube, iVarThis) ) Count1++; else Count2++; } // printf( "%4d : %5d %5d %5d Weight = %5d\n", iVarThis, Count0, Count1, Count2, // Count0 + Count1 - (Count0 > Count1 ? Count0 - Count1 : Count1 - Count0) ); if ( (!Count0 && !Count1) || (!Count0 && !Count2) || (!Count1 && !Count2) ) continue; WeightThis = Count0 + Count1 - (Count0 > Count1 ? Count0 - Count1 : Count1 - Count0); if ( WeightBest < WeightThis ) { WeightBest = WeightThis; iVarBest = iVarThis; } } if ( iVarBest == -1 ) { Gia_ManArePrintListUsed( p, List ); printf( "Error: Best variable not found!!!\n" ); } assert( iVarBest != -1 ); return iVarBest; } /**Function************************************************************* Synopsis [Rebalances the tree when cubes exceed the limit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManAreRebalance( Gia_ManAre_t * p, Gia_PtrAre_t * pRoot ) { Gia_ObjAre_t * pNode; Gia_StaAre_t * pCube; Gia_PtrAre_t iCube, iNext; assert( pRoot->nItem || pRoot->nPage ); pNode = Gia_ManAreCreateObj( p ); pNode->iVar = Gia_ManAreFindBestVar( p, *pRoot ); for ( iCube = *pRoot, pCube = Gia_ManAreSta(p, iCube), iNext = pCube->iNext; Gia_StaIsGood(p, pCube); iCube = iNext, pCube = Gia_ManAreSta(p, iCube), iNext = pCube->iNext ) { if ( Gia_StaIsUnused(pCube) ) continue; if ( Gia_StaHasValue0(pCube, pNode->iVar) ) pCube->iNext = pNode->F[0], pNode->F[0] = iCube, pNode->nStas0++; else if ( Gia_StaHasValue1(pCube, pNode->iVar) ) pCube->iNext = pNode->F[1], pNode->F[1] = iCube, pNode->nStas1++; else pCube->iNext = pNode->F[2], pNode->F[2] = iCube, pNode->nStas2++; } *pRoot = Gia_Int2Ptr(p->nObjs - 1); assert( pNode == Gia_ManAreObj(p, *pRoot) ); p->fTree = 1; } /**Function************************************************************* Synopsis [Compresses the list by removing unused cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManAreCompress( Gia_ManAre_t * p, Gia_PtrAre_t * pRoot ) { Gia_StaAre_t * pCube; Gia_PtrAre_t iList = *pRoot; Gia_PtrAre_t iCube, iNext; assert( pRoot->nItem || pRoot->nPage ); pRoot->nItem = 0; pRoot->nPage = 0; for ( iCube = iList, pCube = Gia_ManAreSta(p, iCube), iNext = pCube->iNext; Gia_StaIsGood(p, pCube); iCube = iNext, pCube = Gia_ManAreSta(p, iCube), iNext = pCube->iNext ) { if ( Gia_StaIsUnused(pCube) ) continue; pCube->iNext = *pRoot; *pRoot = iCube; } } /**Function************************************************************* Synopsis [Checks if the state exists in the list.] Description [The state may be sharped.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManAreCubeCheckList( Gia_ManAre_t * p, Gia_PtrAre_t * pRoot, Gia_StaAre_t * pSta ) { int fVerbose = 0; Gia_StaAre_t * pCube; int iVar; if ( fVerbose ) { printf( "Trying cube: " ); Gia_ManArePrintCube( p, pSta ); } Gia_ManAreForEachCubeList( p, Gia_ManAreSta(p, *pRoot), pCube ) { p->nChecks++; if ( Gia_StaIsUnused( pCube ) ) continue; if ( Gia_StaAreDisjoint( pSta, pCube, p->nWords ) ) continue; if ( Gia_StaAreContain( pCube, pSta, p->nWords ) ) { if ( fVerbose ) { printf( "Contained in " ); Gia_ManArePrintCube( p, pCube ); } Gia_ManAreRycycleSta( p, pSta ); return 0; } if ( Gia_StaAreContain( pSta, pCube, p->nWords ) ) { if ( fVerbose ) { printf( "Contains " ); Gia_ManArePrintCube( p, pCube ); } Gia_StaSetUnused( pCube ); continue; } iVar = Gia_StaAreSharpVar( pSta, pCube, p->nWords ); if ( iVar == -1 ) continue; if ( fVerbose ) { printf( "Sharped by " ); Gia_ManArePrintCube( p, pCube ); Gia_ManArePrintCube( p, pSta ); } // printf( "%d %d\n", Gia_StaAreDashNum( pSta, pCube, p->nWords ), Gia_StaAreSharpVar( pSta, pCube, p->nWords ) ); assert( !Gia_StaHasValue0(pSta, iVar) && !Gia_StaHasValue1(pSta, iVar) ); assert( Gia_StaHasValue0(pCube, iVar) ^ Gia_StaHasValue1(pCube, iVar) ); if ( Gia_StaHasValue0(pCube, iVar) ) Gia_StaSetValue1( pSta, iVar ); else Gia_StaSetValue0( pSta, iVar ); // return Gia_ManAreCubeCheckList( p, pRoot, pSta ); } return 1; } /**Function************************************************************* Synopsis [Adds new state to the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManAreCubeAddToList( Gia_ManAre_t * p, Gia_PtrAre_t * pRoot, Gia_StaAre_t * pSta ) { int fVerbose = 0; pSta->iNext = *pRoot; *pRoot = Gia_Int2Ptr( p->nStas - 1 ); assert( pSta == Gia_ManAreSta(p, *pRoot) ); if ( fVerbose ) { printf( "Adding cube: " ); Gia_ManArePrintCube( p, pSta ); //printf( "\n" ); } } /**Function************************************************************* Synopsis [Checks if the cube like this exists in the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManAreCubeCheckTree_rec( Gia_ManAre_t * p, Gia_ObjAre_t * pObj, Gia_StaAre_t * pSta ) { int RetValue; if ( Gia_StaHasValue0(pSta, pObj->iVar) ) { if ( Gia_ObjHasBranch0(pObj) ) RetValue = Gia_ManAreCubeCheckTree_rec( p, Gia_ObjNextObj0(p, pObj), pSta ); else RetValue = Gia_ManAreCubeCheckList( p, pObj->F, pSta ); if ( RetValue == 0 ) return 0; } else if ( Gia_StaHasValue1(pSta, pObj->iVar) ) { if ( Gia_ObjHasBranch1(pObj) ) RetValue = Gia_ManAreCubeCheckTree_rec( p, Gia_ObjNextObj1(p, pObj), pSta ); else RetValue = Gia_ManAreCubeCheckList( p, pObj->F + 1, pSta ); if ( RetValue == 0 ) return 0; } if ( Gia_ObjHasBranch2(pObj) ) return Gia_ManAreCubeCheckTree_rec( p, Gia_ObjNextObj2(p, pObj), pSta ); return Gia_ManAreCubeCheckList( p, pObj->F + 2, pSta ); } /**Function************************************************************* Synopsis [Adds new cube to the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManAreCubeAddToTree_rec( Gia_ManAre_t * p, Gia_ObjAre_t * pObj, Gia_StaAre_t * pSta ) { if ( Gia_StaHasValue0(pSta, pObj->iVar) ) { if ( Gia_ObjHasBranch0(pObj) ) Gia_ManAreCubeAddToTree_rec( p, Gia_ObjNextObj0(p, pObj), pSta ); else { Gia_ManAreCubeAddToList( p, pObj->F, pSta ); if ( ++pObj->nStas0 == MAX_CUBE_NUM ) { pObj->nStas0 = Gia_ManAreListCountListUsed( p, pObj->F[0] ); if ( pObj->nStas0 < MAX_CUBE_NUM/2 ) Gia_ManAreCompress( p, pObj->F ); else { Gia_ManAreRebalance( p, pObj->F ); pObj->nStas0 = 0; } } } } else if ( Gia_StaHasValue1(pSta, pObj->iVar) ) { if ( Gia_ObjHasBranch1(pObj) ) Gia_ManAreCubeAddToTree_rec( p, Gia_ObjNextObj1(p, pObj), pSta ); else { Gia_ManAreCubeAddToList( p, pObj->F+1, pSta ); if ( ++pObj->nStas1 == MAX_CUBE_NUM ) { pObj->nStas1 = Gia_ManAreListCountListUsed( p, pObj->F[1] ); if ( pObj->nStas1 < MAX_CUBE_NUM/2 ) Gia_ManAreCompress( p, pObj->F+1 ); else { Gia_ManAreRebalance( p, pObj->F+1 ); pObj->nStas1 = 0; } } } } else { if ( Gia_ObjHasBranch2(pObj) ) Gia_ManAreCubeAddToTree_rec( p, Gia_ObjNextObj2(p, pObj), pSta ); else { Gia_ManAreCubeAddToList( p, pObj->F+2, pSta ); if ( ++pObj->nStas2 == MAX_CUBE_NUM ) { pObj->nStas2 = Gia_ManAreListCountListUsed( p, pObj->F[2] ); if ( pObj->nStas2 < MAX_CUBE_NUM/2 ) Gia_ManAreCompress( p, pObj->F+2 ); else { Gia_ManAreRebalance( p, pObj->F+2 ); pObj->nStas2 = 0; } } } } } /**Function************************************************************* Synopsis [Collects overlapping cubes in the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManAreCubeCollectList( Gia_ManAre_t * p, Gia_PtrAre_t * pRoot, Gia_StaAre_t * pSta ) { Gia_StaAre_t * pCube; int iCube; Gia_ManAreForEachCubeList2( p, *pRoot, pCube, iCube ) { if ( Gia_StaIsUnused( pCube ) ) continue; if ( Gia_StaAreDisjoint( pSta, pCube, p->nWords ) ) { /* int iVar; p->nDisjs++; iVar = Gia_StaAreDisjointVar( pSta, pCube, p->nWords ); if ( iVar >= 0 ) { p->nDisjs2++; if ( iCube > p->iStaCur ) p->nDisjs3++; } */ continue; } // p->nCompares++; // p->nEquals += Gia_StaAreEqual( pSta, pCube, p->nWords ); if ( iCube <= p->iStaCur ) Vec_IntPush( p->vCubesA, iCube ); else Vec_IntPush( p->vCubesB, iCube ); } return 1; } /**Function************************************************************* Synopsis [Collects overlapping cubes in the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManAreCubeCollectTree_rec( Gia_ManAre_t * p, Gia_ObjAre_t * pObj, Gia_StaAre_t * pSta ) { int RetValue; if ( Gia_StaHasValue0(pSta, pObj->iVar) ) { if ( Gia_ObjHasBranch0(pObj) ) RetValue = Gia_ManAreCubeCollectTree_rec( p, Gia_ObjNextObj0(p, pObj), pSta ); else RetValue = Gia_ManAreCubeCollectList( p, pObj->F, pSta ); if ( RetValue == 0 ) return 0; } else if ( Gia_StaHasValue1(pSta, pObj->iVar) ) { if ( Gia_ObjHasBranch1(pObj) ) RetValue = Gia_ManAreCubeCollectTree_rec( p, Gia_ObjNextObj1(p, pObj), pSta ); else RetValue = Gia_ManAreCubeCollectList( p, pObj->F + 1, pSta ); if ( RetValue == 0 ) return 0; } if ( Gia_ObjHasBranch2(pObj) ) return Gia_ManAreCubeCollectTree_rec( p, Gia_ObjNextObj2(p, pObj), pSta ); return Gia_ManAreCubeCollectList( p, pObj->F + 2, pSta ); } /**Function************************************************************* Synopsis [Checks if the cube like this exists in the tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManAreCubeCheckTree( Gia_ManAre_t * p, Gia_StaAre_t * pSta ) { Gia_StaAre_t * pCube; int i, iVar; assert( p->fTree ); Vec_IntClear( p->vCubesA ); Vec_IntClear( p->vCubesB ); Gia_ManAreCubeCollectTree_rec( p, Gia_ManAreObj(p, p->Root), pSta ); // if ( p->nStas > 3000 ) // printf( "%d %d \n", Vec_IntSize(p->vCubesA), Vec_IntSize(p->vCubesB) ); // Vec_IntSort( p->vCubesA, 0 ); // Vec_IntSort( p->vCubesB, 0 ); Gia_ManAreForEachCubeVec( p->vCubesA, p, pCube, i ) { if ( Gia_StaIsUnused( pCube ) ) continue; if ( Gia_StaAreDisjoint( pSta, pCube, p->nWords ) ) continue; if ( Gia_StaAreContain( pCube, pSta, p->nWords ) ) { Gia_ManAreRycycleSta( p, pSta ); return 0; } if ( Gia_StaAreContain( pSta, pCube, p->nWords ) ) { Gia_StaSetUnused( pCube ); continue; } iVar = Gia_StaAreSharpVar( pSta, pCube, p->nWords ); if ( iVar == -1 ) continue; assert( !Gia_StaHasValue0(pSta, iVar) && !Gia_StaHasValue1(pSta, iVar) ); assert( Gia_StaHasValue0(pCube, iVar) ^ Gia_StaHasValue1(pCube, iVar) ); if ( Gia_StaHasValue0(pCube, iVar) ) Gia_StaSetValue1( pSta, iVar ); else Gia_StaSetValue0( pSta, iVar ); return Gia_ManAreCubeCheckTree( p, pSta ); } Gia_ManAreForEachCubeVec( p->vCubesB, p, pCube, i ) { if ( Gia_StaIsUnused( pCube ) ) continue; if ( Gia_StaAreDisjoint( pSta, pCube, p->nWords ) ) continue; if ( Gia_StaAreContain( pCube, pSta, p->nWords ) ) { Gia_ManAreRycycleSta( p, pSta ); return 0; } if ( Gia_StaAreContain( pSta, pCube, p->nWords ) ) { Gia_StaSetUnused( pCube ); continue; } iVar = Gia_StaAreSharpVar( pSta, pCube, p->nWords ); if ( iVar == -1 ) continue; assert( !Gia_StaHasValue0(pSta, iVar) && !Gia_StaHasValue1(pSta, iVar) ); assert( Gia_StaHasValue0(pCube, iVar) ^ Gia_StaHasValue1(pCube, iVar) ); if ( Gia_StaHasValue0(pCube, iVar) ) Gia_StaSetValue1( pSta, iVar ); else Gia_StaSetValue0( pSta, iVar ); return Gia_ManAreCubeCheckTree( p, pSta ); } /* if ( p->nStas > 3000 ) { printf( "Trying cube: " ); Gia_ManArePrintCube( p, pSta ); Gia_ManAreForEachCubeVec( p->vCubesA, p, pCube, i ) { printf( "aaaaaaaaaaaa %5d ", Vec_IntEntry(p->vCubesA,i) ); Gia_ManArePrintCube( p, pCube ); } Gia_ManAreForEachCubeVec( p->vCubesB, p, pCube, i ) { printf( "bbbbbbbbbbbb %5d ", Vec_IntEntry(p->vCubesB,i) ); Gia_ManArePrintCube( p, pCube ); } } */ return 1; } /**Function************************************************************* Synopsis [Processes the new cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManAreCubeProcess( Gia_ManAre_t * p, Gia_StaAre_t * pSta ) { int RetValue; p->nChecks = 0; if ( !p->fTree && p->nStas == MAX_CUBE_NUM ) Gia_ManAreRebalance( p, &p->Root ); if ( p->fTree ) { // RetValue = Gia_ManAreCubeCheckTree_rec( p, Gia_ManAreObj(p, p->Root), pSta ); RetValue = Gia_ManAreCubeCheckTree( p, pSta ); if ( RetValue ) Gia_ManAreCubeAddToTree_rec( p, Gia_ManAreObj(p, p->Root), pSta ); } else { RetValue = Gia_ManAreCubeCheckList( p, &p->Root, pSta ); if ( RetValue ) Gia_ManAreCubeAddToList( p, &p->Root, pSta ); } // printf( "%d ", p->nChecks ); return RetValue; } /**Function************************************************************* Synopsis [Returns the most used CI, or NULL if condition is met.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManAreMostUsedPi_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) { pObj->Value++; return; } assert( Gia_ObjIsAnd(pObj) ); Gia_ManAreMostUsedPi_rec( p, Gia_ObjFanin0(pObj) ); Gia_ManAreMostUsedPi_rec( p, Gia_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Returns the most used CI, or NULL if condition is met.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_Obj_t * Gia_ManAreMostUsedPi( Gia_ManAre_t * p ) { Gia_Obj_t * pObj, * pObjMax = NULL; int i; // clean CI counters Gia_ManForEachCi( p->pNew, pObj, i ) pObj->Value = 0; // traverse from each register output Gia_ManForEachRi( p->pAig, pObj, i ) { if ( pObj->Value <= 1 ) continue; Gia_ManIncrementTravId( p->pNew ); Gia_ManAreMostUsedPi_rec( p->pNew, Gia_ManObj(p->pNew, Abc_Lit2Var(pObj->Value)) ); } // check the CI counters Gia_ManForEachCi( p->pNew, pObj, i ) if ( pObjMax == NULL || pObjMax->Value < pObj->Value ) pObjMax = pObj; // return the result return pObjMax->Value > 1 ? pObjMax : NULL; } /**Function************************************************************* Synopsis [Counts maximum support of primary outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCheckPOs_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 0; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) return 1; assert( Gia_ObjIsAnd(pObj) ); return Gia_ManCheckPOs_rec( p, Gia_ObjFanin0(pObj) ) + Gia_ManCheckPOs_rec( p, Gia_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Counts maximum support of primary outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManCheckPOs( Gia_ManAre_t * p ) { Gia_Obj_t * pObj, * pObjNew; int i, CountCur, CountMax = 0; Gia_ManForEachPo( p->pAig, pObj, i ) { pObjNew = Gia_ManObj( p->pNew, Abc_Lit2Var(pObj->Value) ); if ( Gia_ObjIsConst0(pObjNew) ) CountCur = 0; else { Gia_ManIncrementTravId( p->pNew ); CountCur = Gia_ManCheckPOs_rec( p->pNew, pObjNew ); } CountMax = Abc_MaxInt( CountMax, CountCur ); } return CountMax; } /**Function************************************************************* Synopsis [Returns the status of the primary outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManCheckPOstatus( Gia_ManAre_t * p ) { Gia_Obj_t * pObj, * pObjNew; int i; Gia_ManForEachPo( p->pAig, pObj, i ) { pObjNew = Gia_ManObj( p->pNew, Abc_Lit2Var(pObj->Value) ); if ( Gia_ObjIsConst0(pObjNew) ) { if ( Abc_LitIsCompl(pObj->Value) ) { p->iOutFail = i; return 1; } } else { p->iOutFail = i; // printf( "To fix later: PO may be assertable.\n" ); return 1; } } return 0; } /**Function************************************************************* Synopsis [Derives next state cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManAreDeriveNexts_rec( Gia_ManAre_t * p, Gia_PtrAre_t Sta ) { Gia_Obj_t * pPivot; Vec_Int_t * vLits, * vTfos; Gia_Obj_t * pObj; int i; abctime clk; if ( ++p->nRecCalls == MAX_CALL_NUM ) return 0; if ( (pPivot = Gia_ManAreMostUsedPi(p)) == NULL ) { Gia_StaAre_t * pNew; clk = Abc_Clock(); pNew = Gia_ManAreCreateStaNew( p ); pNew->iPrev = Sta; p->fStopped = (p->fMiter && (Gia_ManCheckPOstatus(p) & 1)); if ( p->fStopped ) { assert( p->pTarget == NULL ); p->pTarget = pNew; return 1; } Gia_ManAreCubeProcess( p, pNew ); p->timeCube += Abc_Clock() - clk; return p->fStopped; } // remember values in the cone and perform update vTfos = Vec_VecEntryInt( p->vCiTfos, Gia_ObjCioId(pPivot) ); vLits = Vec_VecEntryInt( p->vCiLits, Gia_ObjCioId(pPivot) ); assert( Vec_IntSize(vTfos) == Vec_IntSize(vLits) ); Gia_ManForEachObjVec( vTfos, p->pAig, pObj, i ) { Vec_IntWriteEntry( vLits, i, pObj->Value ); if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Gia_ManHashAnd( p->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsCo(pObj) ) pObj->Value = Gia_ObjFanin0Copy(pObj); else { assert( Gia_ObjIsCi(pObj) ); pObj->Value = 0; } } if ( Gia_ManAreDeriveNexts_rec( p, Sta ) ) return 1; // compute different values Gia_ManForEachObjVec( vTfos, p->pAig, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Gia_ManHashAnd( p->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjIsCo(pObj) ) pObj->Value = Gia_ObjFanin0Copy(pObj); else { assert( Gia_ObjIsCi(pObj) ); pObj->Value = 1; } } if ( Gia_ManAreDeriveNexts_rec( p, Sta ) ) return 1; // reset the original values Gia_ManForEachObjVec( vTfos, p->pAig, pObj, i ) pObj->Value = Vec_IntEntry( vLits, i ); return 0; } /**Function************************************************************* Synopsis [Derives next state cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManAreDeriveNexts( Gia_ManAre_t * p, Gia_PtrAre_t Sta ) { Gia_StaAre_t * pSta; Gia_Obj_t * pObj; int i, RetValue; abctime clk = Abc_Clock(); pSta = Gia_ManAreSta( p, Sta ); if ( Gia_StaIsUnused(pSta) ) return 0; // recycle the manager if ( p->pNew && Gia_ManObjNum(p->pNew) > 1000000 ) { Gia_ManStop( p->pNew ); p->pNew = NULL; } // allocate the manager if ( p->pNew == NULL ) { p->pNew = Gia_ManStart( 10 * Gia_ManObjNum(p->pAig) ); Gia_ManIncrementTravId( p->pNew ); Gia_ManHashAlloc( p->pNew ); Gia_ManConst0(p->pAig)->Value = 0; Gia_ManForEachCi( p->pAig, pObj, i ) pObj->Value = Gia_ManAppendCi(p->pNew); } Gia_ManForEachRo( p->pAig, pObj, i ) { if ( Gia_StaHasValue0( pSta, i ) ) pObj->Value = 0; else if ( Gia_StaHasValue1( pSta, i ) ) pObj->Value = 1; else // don't-care literal pObj->Value = Abc_Var2Lit( Gia_ObjId( p->pNew, Gia_ManCi(p->pNew, Gia_ObjCioId(pObj)) ), 0 ); } Gia_ManForEachAnd( p->pAig, pObj, i ) pObj->Value = Gia_ManHashAnd( p->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( p->pAig, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); // perform case-splitting p->nRecCalls = 0; RetValue = Gia_ManAreDeriveNexts_rec( p, Sta ); if ( p->nRecCalls >= MAX_CALL_NUM ) { printf( "Exceeded the limit on the number of transitions from a state cube (%d).\n", MAX_CALL_NUM ); p->fStopped = 1; } // printf( "%d ", p->nRecCalls ); //printf( "%d ", Gia_ManObjNum(p->pNew) ); p->timeAig += Abc_Clock() - clk; return RetValue; } /**Function************************************************************* Synopsis [Prints the report] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManArePrintReport( Gia_ManAre_t * p, abctime Time, int fFinal ) { printf( "States =%10d. Reached =%10d. R = %5.3f. Depth =%6d. Mem =%9.2f MB. ", p->iStaCur, p->nStas, 1.0*p->iStaCur/p->nStas, Gia_ManAreDepth(p, p->iStaCur), (sizeof(Gia_ManAre_t) + 4.0*Gia_ManRegNum(p->pAig) + 8.0*MAX_PAGE_NUM + 4.0*p->nStaPages*p->nSize*MAX_ITEM_NUM + 16.0*p->nObjPages*MAX_ITEM_NUM)/(1<<20) ); if ( fFinal ) { ABC_PRT( "Time", Abc_Clock() - Time ); } else { ABC_PRTr( "Time", Abc_Clock() - Time ); } } /**Function************************************************************* Synopsis [Performs explicit reachability.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManArePerform( Gia_Man_t * pAig, int nStatesMax, int fMiter, int fVerbose ) { // extern Gia_Man_t * Gia_ManCompress2( Gia_Man_t * p, int fUpdateLevel, int fVerbose ); extern Abc_Cex_t * Gia_ManAreDeriveCex( Gia_ManAre_t * p, Gia_StaAre_t * pLast ); Gia_ManAre_t * p; abctime clk = Abc_Clock(); int RetValue = 1; if ( Gia_ManRegNum(pAig) > MAX_VARS_NUM ) { printf( "Currently can only handle circuit with up to %d registers.\n", MAX_VARS_NUM ); return -1; } ABC_FREE( pAig->pCexSeq ); // p = Gia_ManAreCreate( Gia_ManCompress2(pAig, 0, 0) ); p = Gia_ManAreCreate( Gia_ManDup(pAig) ); p->fMiter = fMiter; Gia_ManAreCubeProcess( p, Gia_ManAreCreateStaInit(p) ); for ( p->iStaCur = 1; p->iStaCur < p->nStas; p->iStaCur++ ) { // printf( "Explored state %d. Total cubes %d.\n", p->iStaCur, p->nStas-1 ); if ( Gia_ManAreDeriveNexts( p, Gia_Int2Ptr(p->iStaCur) ) || p->nStas > nStatesMax ) pAig->pCexSeq = Gia_ManAreDeriveCex( p, p->pTarget ); if ( p->fStopped ) { RetValue = -1; break; } if ( fVerbose )//&& p->iStaCur % 5000 == 0 ) Gia_ManArePrintReport( p, clk, 0 ); } Gia_ManArePrintReport( p, clk, 1 ); printf( "%s after finding %d state cubes (%d not contained) with depth %d. ", p->fStopped ? "Stopped" : "Completed", p->nStas, Gia_ManAreListCountUsed(p), Gia_ManAreDepth(p, p->iStaCur-1) ); ABC_PRT( "Time", Abc_Clock() - clk ); if ( pAig->pCexSeq != NULL ) Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.\n", p->iStaCur, pAig->pName, Gia_ManAreDepth(p, p->iStaCur)-1 ); if ( fVerbose ) { ABC_PRTP( "Cofactoring", p->timeAig - p->timeCube, Abc_Clock() - clk ); ABC_PRTP( "Containment", p->timeCube, Abc_Clock() - clk ); ABC_PRTP( "Other ", Abc_Clock() - clk - p->timeAig, Abc_Clock() - clk ); ABC_PRTP( "TOTAL ", Abc_Clock() - clk, Abc_Clock() - clk ); } if ( Gia_ManRegNum(pAig) <= 30 ) { clk = Abc_Clock(); printf( "The number of unique state minterms in computed state cubes is %d. ", Gia_ManCountMinterms(p) ); ABC_PRT( "Time", Abc_Clock() - clk ); } // printf( "Compares = %d. Equals = %d. Disj = %d. Disj2 = %d. Disj3 = %d.\n", // p->nCompares, p->nEquals, p->nDisjs, p->nDisjs2, p->nDisjs3 ); // Gia_ManAreFindBestVar( p, Gia_ManAreSta(p, p->Root) ); // Gia_ManArePrintUsed( p ); Gia_ManAreFree( p ); // verify if ( pAig->pCexSeq ) { if ( !Gia_ManVerifyCex( pAig, pAig->pCexSeq, 0 ) ) printf( "Generated counter-example is INVALID. \n" ); else printf( "Generated counter-example verified correctly. \n" ); return 0; } return RetValue; } ABC_NAMESPACE_IMPL_END #include "giaAig.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManAreDeriveCexSatStart( Gia_ManAre_t * p ) { Aig_Man_t * pAig2; Cnf_Dat_t * pCnf; assert( p->pSat == NULL ); pAig2 = Gia_ManToAig( p->pAig, 0 ); Aig_ManSetRegNum( pAig2, 0 ); pCnf = Cnf_Derive( pAig2, Gia_ManCoNum(p->pAig) ); p->pSat = Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); p->vSatNumCis = Cnf_DataCollectCiSatNums( pCnf, pAig2 ); p->vSatNumCos = Cnf_DataCollectCoSatNums( pCnf, pAig2 ); Cnf_DataFree( pCnf ); Aig_ManStop( pAig2 ); p->vAssumps = Vec_IntAlloc( 100 ); p->vCofVars = Vec_IntAlloc( 100 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManAreDeriveCexSatStop( Gia_ManAre_t * p ) { assert( p->pSat != NULL ); assert( p->pTarget != NULL ); sat_solver_delete( (sat_solver *)p->pSat ); Vec_IntFree( p->vSatNumCis ); Vec_IntFree( p->vSatNumCos ); Vec_IntFree( p->vAssumps ); Vec_IntFree( p->vCofVars ); p->pTarget = NULL; p->pSat = NULL; } /**Function************************************************************* Synopsis [Computes satisfying assignment in one timeframe.] Description [Returns the vector of integers represeting PIO ids of the primary inputs that should be 1 in the counter-example.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManAreDeriveCexSat( Gia_ManAre_t * p, Gia_StaAre_t * pCur, Gia_StaAre_t * pNext, int iOutFailed ) { int i, status; // make assuptions Vec_IntClear( p->vAssumps ); for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) { if ( Gia_StaHasValue0(pCur, i) ) Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i), 1 ) ); else if ( Gia_StaHasValue1(pCur, i) ) Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i), 0 ) ); } if ( pNext ) for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) { if ( Gia_StaHasValue0(pNext, i) ) Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCos, Gia_ManPoNum(p->pAig)+i), 1 ) ); else if ( Gia_StaHasValue1(pNext, i) ) Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCos, Gia_ManPoNum(p->pAig)+i), 0 ) ); } if ( iOutFailed >= 0 ) { assert( iOutFailed < Gia_ManPoNum(p->pAig) ); Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCos, iOutFailed), 0 ) ); } // solve SAT status = sat_solver_solve( (sat_solver *)p->pSat, (int *)Vec_IntArray(p->vAssumps), (int *)Vec_IntArray(p->vAssumps) + Vec_IntSize(p->vAssumps), (ABC_INT64_T)1000000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status != l_True ) { printf( "SAT problem is not satisfiable. Failure...\n" ); return; } assert( status == l_True ); // check the model Vec_IntClear( p->vCofVars ); for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ ) { if ( sat_solver_var_value( (sat_solver *)p->pSat, Vec_IntEntry(p->vSatNumCis, i) ) ) Vec_IntPush( p->vCofVars, i ); } // write the current state for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) { if ( Gia_StaHasValue0(pCur, i) ) assert( sat_solver_var_value( (sat_solver *)p->pSat, Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i) ) == 0 ); else if ( Gia_StaHasValue1(pCur, i) ) assert( sat_solver_var_value( (sat_solver *)p->pSat, Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i) ) == 1 ); // set don't-care value if ( sat_solver_var_value( (sat_solver *)p->pSat, Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i) ) == 0 ) Gia_StaSetValue0( pCur, i ); else Gia_StaSetValue1( pCur, i ); } } /**Function************************************************************* Synopsis [Returns the status of the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Gia_ManAreDeriveCex( Gia_ManAre_t * p, Gia_StaAre_t * pLast ) { Abc_Cex_t * pCex; Vec_Ptr_t * vStates; Gia_StaAre_t * pSta, * pPrev; int Var, i, v; assert( p->iOutFail >= 0 ); Gia_ManAreDeriveCexSatStart( p ); // compute the trace vStates = Vec_PtrAlloc( 1000 ); for ( pSta = pLast; Gia_StaIsGood(p, pSta); pSta = Gia_StaPrev(p, pSta) ) if ( pSta != pLast ) Vec_PtrPush( vStates, pSta ); assert( Vec_PtrSize(vStates) >= 1 ); // start the counter-example pCex = Abc_CexAlloc( Gia_ManRegNum(p->pAig), Gia_ManPiNum(p->pAig), Vec_PtrSize(vStates) ); pCex->iFrame = Vec_PtrSize(vStates)-1; pCex->iPo = p->iOutFail; // compute states pPrev = NULL; Vec_PtrForEachEntry( Gia_StaAre_t *, vStates, pSta, i ) { Gia_ManAreDeriveCexSat( p, pSta, pPrev, (i == 0) ? p->iOutFail : -1 ); pPrev = pSta; // create the counter-example Vec_IntForEachEntry( p->vCofVars, Var, v ) { assert( Var < Gia_ManPiNum(p->pAig) ); Abc_InfoSetBit( pCex->pData, Gia_ManRegNum(p->pAig) + (Vec_PtrSize(vStates)-1-i) * Gia_ManPiNum(p->pAig) + Var ); } } // free temporary things Vec_PtrFree( vStates ); Gia_ManAreDeriveCexSatStop( p ); return pCex; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaEsop.c000066400000000000000000000413561477524141600160330ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaEsop.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [ESOP computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaEsop.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/extra/extra.h" #include "misc/vec/vecHsh.h" #include "misc/vec/vecWec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Eso_Man_t_ Eso_Man_t; struct Eso_Man_t_ { Gia_Man_t * pGia; // user's AIG int nVars; // number of variables int Cube1; // ID of const1 cube Vec_Wec_t * vEsops; // ESOP for each node Hsh_VecMan_t * pHash; // hash table for cubes Vec_Wec_t * vCubes; // cover during minimization // internal Vec_Int_t * vCube1; // first cube Vec_Int_t * vCube2; // second cube Vec_Int_t * vCube; // resulting cube }; static inline Vec_Int_t * Eso_ManCube( Eso_Man_t * p, int iCube ) { assert( iCube >= 0 ); return Hsh_VecReadEntry(p->pHash, iCube); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Eso_Man_t * Eso_ManAlloc( Gia_Man_t * pGia ) { int i, n, Id; Eso_Man_t * p = ABC_CALLOC( Eso_Man_t, 1 ); p->pGia = pGia; p->nVars = Gia_ManCiNum(pGia); p->Cube1 = ABC_INFINITY; p->vEsops = Vec_WecStart( Gia_ManObjNum(pGia) ); p->pHash = Hsh_VecManStart( 1000 ); p->vCubes = Vec_WecStart(Gia_ManCiNum(pGia)+1); p->vCube1 = Vec_IntAlloc(Gia_ManCiNum(pGia)); p->vCube2 = Vec_IntAlloc(Gia_ManCiNum(pGia)); p->vCube = Vec_IntAlloc(Gia_ManCiNum(pGia)); Gia_ManForEachCiId( pGia, Id, i ) { for ( n = 0; n < 2; n++ ) { Vec_IntFill( p->vCube, 1, Abc_Var2Lit(i, n) ); Hsh_VecManAdd( p->pHash, p->vCube ); } Vec_IntPush( Vec_WecEntry(p->vEsops, Id), Abc_Var2Lit(i, 0) ); } return p; } void Eso_ManStop( Eso_Man_t * p ) { Vec_WecFree( p->vEsops ); Hsh_VecManStop( p->pHash ); Vec_WecFree( p->vCubes ); Vec_IntFree( p->vCube1 ); Vec_IntFree( p->vCube2 ); Vec_IntFree( p->vCube ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Printing/transforming the cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Eso_ManCoverPrint( Eso_Man_t * p, Vec_Int_t * vEsop ) { Vec_Str_t * vStr; Vec_Int_t * vCube; int i, k, Lit, Cube; if ( Vec_IntSize(vEsop) == 0 ) { printf( "Const 0\n" ); return; } vStr = Vec_StrAlloc( p->nVars + 4 ); Vec_StrFill( vStr, p->nVars, '-' ); Vec_StrPush( vStr, ' ' ); Vec_StrPush( vStr, '1' ); Vec_StrPush( vStr, '\n' ); Vec_StrPush( vStr, '\0' ); assert( Vec_IntSize(vEsop) > 0 ); Vec_IntForEachEntry( vEsop, Cube, i ) { if ( Cube == p->Cube1 ) printf( "%s", Vec_StrArray(vStr) ); else { vCube = Eso_ManCube( p, Cube ); Vec_IntForEachEntry( vCube, Lit, k ) Vec_StrWriteEntry( vStr, Abc_Lit2Var(Lit), (char)(Abc_LitIsCompl(Lit)?'0':'1') ); printf( "%s", Vec_StrArray(vStr) ); Vec_IntForEachEntry( vCube, Lit, k ) Vec_StrWriteEntry( vStr, Abc_Lit2Var(Lit), '-' ); } } printf( "\n" ); Vec_StrFree( vStr ); } Vec_Wec_t * Eso_ManCoverDerive( Eso_Man_t * p, Vec_Ptr_t * vCover ) { Vec_Wec_t * vRes; Vec_Int_t * vEsop, * vLevel; int i; vRes = Vec_WecAlloc( Vec_VecSizeSize((Vec_Vec_t *)vCover) ); Vec_PtrForEachEntry( Vec_Int_t *, vCover, vEsop, i ) { if ( Vec_IntSize(vEsop) > 0 ) { int c, Cube; Vec_IntForEachEntry( vEsop, Cube, c ) { vLevel = Vec_WecPushLevel( vRes ); if ( Cube != p->Cube1 ) { int k, Lit; Vec_Int_t * vCube = Eso_ManCube( p, Cube ); Vec_IntForEachEntry( vCube, Lit, k ) Vec_IntPush( vLevel, Lit ); } Vec_IntPush( vLevel, -i-1 ); } } } //assert( Abc_MaxInt(Vec_WecSize(vRes), 8) == Vec_WecCap(vRes) ); return vRes; } Gia_Man_t * Eso_ManCoverConvert( Eso_Man_t * p, Vec_Ptr_t * vCover ) { Vec_Int_t * vEsop; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; pNew = Gia_ManStart( Gia_ManObjNum(p->pGia) ); pNew->pName = Abc_UtilStrsav( p->pGia->pName ); pNew->pSpec = Abc_UtilStrsav( p->pGia->pSpec ); Gia_ManHashAlloc( pNew ); Gia_ManConst0(p->pGia)->Value = 0; Gia_ManForEachCi( p->pGia, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Vec_PtrForEachEntry( Vec_Int_t *, vCover, vEsop, i ) { if ( Vec_IntSize(vEsop) > 0 ) { int c, Cube, iRoot = 0; Vec_IntForEachEntry( vEsop, Cube, c ) { int k, Lit, iAnd = 1; if ( Cube != p->Cube1 ) { Vec_Int_t * vCube = Eso_ManCube( p, Cube ); Vec_IntForEachEntry( vCube, Lit, k ) iAnd = Gia_ManHashAnd( pNew, iAnd, Lit + 2 ); } iRoot = Gia_ManHashXor( pNew, iRoot, iAnd ); } Gia_ManAppendCo( pNew, iRoot ); } else Gia_ManAppendCo( pNew, 0 ); } // cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Minimization.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Eso_ManFindDistOneLitEqual( int * pCube1, int * pCube2, int nLits ) // pCube1 and pCube2 both have nLits { int i, iDiff = -1; for ( i = 0; i < nLits; i++ ) if ( pCube1[i] != pCube2[i] ) { if ( iDiff != -1 ) return -1; if ( Abc_Lit2Var(pCube1[i]) != Abc_Lit2Var(pCube2[i]) ) return -1; iDiff = i; } return iDiff; } int Eso_ManFindDistOneLitNotEqual( int * pCube1, int * pCube2, int nLits ) // pCube1 has nLits; pCube2 has nLits + 1 { int i, k, iDiff = -1; for ( i = k = 0; i < nLits; i++, k++ ) if ( pCube1[i] != pCube2[k] ) { if ( iDiff != -1 ) return -1; iDiff = i; i--; } if ( iDiff == -1 ) iDiff = nLits; return iDiff; } void Eso_ManMinimizeAdd( Eso_Man_t * p, int Cube ) { int fMimimize = 1; Vec_Int_t * vCube = (Cube == p->Cube1) ? NULL : Eso_ManCube(p, Cube); int * pCube2, * pCube = (Cube == p->Cube1) ? NULL : Vec_IntArray(vCube); int Cube2, nLits = (Cube == p->Cube1) ? 0 : Vec_IntSize(vCube); Vec_Int_t * vLevel = Vec_WecEntry( p->vCubes, nLits ); int c, k, iLit, iPlace = Vec_IntFind( vLevel, Cube ); if ( iPlace >= 0 ) // identical found { Vec_IntDrop( vLevel, iPlace ); return; } if ( Cube == p->Cube1 ) // simple case { assert( Vec_IntSize(vLevel) == 0 ); Vec_IntPush( vLevel, Cube ); return; } // look for distance-1 in next bin if ( fMimimize && nLits < p->nVars - 1 ) { Vec_Int_t * vLevel = Vec_WecEntry( p->vCubes, nLits+1 ); Vec_IntForEachEntry( vLevel, Cube2, c ) { pCube2 = Hsh_VecReadArray( p->pHash, Cube2 ); iLit = Eso_ManFindDistOneLitNotEqual( pCube, pCube2, nLits ); if ( iLit == -1 ) continue; // remove this cube Vec_IntDrop( vLevel, c ); // create new cube Vec_IntClear( p->vCube ); for ( k = 0; k <= nLits; k++ ) Vec_IntPush( p->vCube, Abc_LitNotCond(pCube2[k], k == iLit) ); Cube = Hsh_VecManAdd( p->pHash, p->vCube ); // try to add new cube Eso_ManMinimizeAdd( p, Cube ); return; } } // look for distance-1 in the same bin if ( fMimimize ) { Vec_IntForEachEntry( vLevel, Cube2, c ) { pCube2 = Hsh_VecReadArray( p->pHash, Cube2 ); iLit = Eso_ManFindDistOneLitEqual( pCube2, pCube, nLits ); if ( iLit == -1 ) continue; // remove this cube Vec_IntDrop( vLevel, c ); // create new cube Vec_IntClear( p->vCube ); for ( k = 0; k < nLits; k++ ) if ( k != iLit ) Vec_IntPush( p->vCube, pCube[k] ); if ( Vec_IntSize(p->vCube) == 0 ) Cube = p->Cube1; else Cube = Hsh_VecManAdd( p->pHash, p->vCube ); // try to add new cube Eso_ManMinimizeAdd( p, Cube ); return; } } assert( nLits > 0 ); if ( fMimimize && nLits > 0 ) { // look for distance-1 in the previous bin Vec_Int_t * vLevel = Vec_WecEntry( p->vCubes, nLits-1 ); // check for the case of one-literal cube if ( nLits == 1 && Vec_IntSize(vLevel) == 1 ) { Vec_IntDrop( vLevel, 0 ); Cube = Abc_LitNot( Cube ); } else Vec_IntForEachEntry( vLevel, Cube2, c ) { pCube2 = Hsh_VecReadArray( p->pHash, Cube2 ); iLit = Eso_ManFindDistOneLitNotEqual( pCube2, pCube, nLits-1 ); if ( iLit == -1 ) continue; // remove this cube Vec_IntDrop( vLevel, c ); // create new cube Vec_IntClear( p->vCube ); for ( k = 0; k < nLits; k++ ) Vec_IntPush( p->vCube, Abc_LitNotCond(pCube[k], k == iLit) ); Cube = Hsh_VecManAdd( p->pHash, p->vCube ); // try to add new cube Eso_ManMinimizeAdd( p, Cube ); return; } } // could not find - simply add this cube Vec_IntPush( vLevel, Cube ); } void Eso_ManMinimizeCopy( Eso_Man_t * p, Vec_Int_t * vEsop ) { Vec_Int_t * vLevel; int i; Vec_IntClear( vEsop ); Vec_WecForEachLevel( p->vCubes, vLevel, i ) { Vec_IntAppend( vEsop, vLevel ); if ( i > 0 ) { int k, Cube; Vec_IntForEachEntry( vLevel, Cube, k ) assert( Vec_IntSize(Eso_ManCube(p, Cube)) == i ); } Vec_IntClear( vLevel ); } } /**Function************************************************************* Synopsis [Compute the produce of two covers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Eso_ManComputeAnd( Eso_Man_t * p, Vec_Int_t * vCube1, Vec_Int_t * vCube2, Vec_Int_t * vCube ) { int * pBeg = vCube->pArray; int * pBeg1 = vCube1->pArray; int * pBeg2 = vCube2->pArray; int * pEnd1 = vCube1->pArray + vCube1->nSize; int * pEnd2 = vCube2->pArray + vCube2->nSize; while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) { if ( *pBeg1 == *pBeg2 ) *pBeg++ = *pBeg1++, pBeg2++; else if ( Abc_Lit2Var(*pBeg1) == Abc_Lit2Var(*pBeg2) ) return -1; else if ( *pBeg1 < *pBeg2 ) *pBeg++ = *pBeg1++; else *pBeg++ = *pBeg2++; } while ( pBeg1 < pEnd1 ) *pBeg++ = *pBeg1++; while ( pBeg2 < pEnd2 ) *pBeg++ = *pBeg2++; vCube->nSize = pBeg - vCube->pArray; assert( vCube->nSize <= vCube->nCap ); assert( vCube->nSize >= vCube1->nSize ); assert( vCube->nSize >= vCube2->nSize ); return Hsh_VecManAdd( p->pHash, vCube ); } void Eso_ManComputeOne( Eso_Man_t * p, Vec_Int_t * vEsop1, Vec_Int_t * vEsop2, Vec_Int_t * vEsop ) { Vec_Int_t vCube1, vCube2; int i, k, Cube1, Cube2, Cube; Vec_IntClear( vEsop ); if ( Vec_IntSize(vEsop1) == 0 || Vec_IntSize(vEsop2) == 0 ) return; Cube1 = Vec_IntEntry(vEsop1, 0); Cube2 = Vec_IntEntry(vEsop2, 0); Vec_IntForEachEntry( vEsop1, Cube1, i ) { if ( Cube1 == p->Cube1 ) { Vec_IntForEachEntry( vEsop2, Cube2, k ) Eso_ManMinimizeAdd( p, Cube2 ); continue; } Vec_IntForEachEntry( vEsop2, Cube2, k ) { if ( Cube2 == p->Cube1 ) { Eso_ManMinimizeAdd( p, Cube1 ); continue; } vCube1 = *Hsh_VecReadEntry( p->pHash, Cube1 ); vCube2 = *Hsh_VecReadEntry( p->pHash, Cube2 ); Cube = Eso_ManComputeAnd( p, &vCube1, &vCube2, p->vCube ); if ( Cube >= 0 ) Eso_ManMinimizeAdd( p, Cube ); } } Eso_ManMinimizeCopy( p, vEsop ); } /**Function************************************************************* Synopsis [Complements the cover if needed, or just copy it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Eso_ManTransformOne( Eso_Man_t * p, Vec_Int_t * vEsop, int fCompl, Vec_Int_t * vRes ) { int i, Cube, Start = 0; Vec_IntClear( vRes ); if ( fCompl ) { if ( Vec_IntSize(vEsop) == 0 ) Vec_IntPush( vRes, p->Cube1 ); else { Cube = Vec_IntEntry(vEsop, 0); if ( Cube == p->Cube1 ) Start = 1; else if ( Cube < 2 * p->nVars ) Vec_IntPush( vRes, Abc_LitNot(Cube) ), Start = 1; else Vec_IntPush( vRes, p->Cube1 ); } } Vec_IntForEachEntryStart( vEsop, Cube, i, Start ) Vec_IntPush( vRes, Cube ); return vRes; } /**Function************************************************************* Synopsis [Computes ESOP from AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Eso_ManCompute( Gia_Man_t * pGia, int fVerbose, Vec_Wec_t ** pvRes ) { abctime clk = Abc_Clock(); Vec_Ptr_t * vCover; Gia_Man_t * pNew = NULL; Gia_Obj_t * pObj; int i, nCubes = 0, nCubesUsed = 0; Vec_Int_t * vEsop1, * vEsop2, * vEsop; Eso_Man_t * p = Eso_ManAlloc( pGia ); Gia_ManForEachAnd( pGia, pObj, i ) { vEsop1 = Vec_WecEntry( p->vEsops, Gia_ObjFaninId0(pObj, i) ); vEsop2 = Vec_WecEntry( p->vEsops, Gia_ObjFaninId1(pObj, i) ); vEsop1 = Eso_ManTransformOne( p, vEsop1, Gia_ObjFaninC0(pObj), p->vCube1 ); vEsop2 = Eso_ManTransformOne( p, vEsop2, Gia_ObjFaninC1(pObj), p->vCube2 ); vEsop = Vec_WecEntry( p->vEsops, i ); Eso_ManComputeOne( p, vEsop1, vEsop2, vEsop ); nCubes += Vec_IntSize(vEsop); } vCover = Vec_PtrAlloc( Gia_ManCoNum(pGia) ); Gia_ManForEachCo( pGia, pObj, i ) { vEsop1 = Vec_WecEntry( p->vEsops, Gia_ObjFaninId0p(pGia, pObj) ); vEsop1 = Eso_ManTransformOne( p, vEsop1, Gia_ObjFaninC0(pObj), p->vCube1 ); if ( fVerbose ) printf( "Output %3d: ESOP has %5d cubes\n", i, Vec_IntSize(vEsop1) ); // if ( fVerbose ) // Eso_ManCoverPrint( p, vEsop1 ); Vec_PtrPush( vCover, Vec_IntDup(vEsop1) ); nCubesUsed += Vec_IntSize(vEsop1); } if ( fVerbose ) { printf( "Outs = %d. Cubes = %d. Used = %d. Hashed = %d. ", Gia_ManCoNum(pGia), nCubes, nCubesUsed, Hsh_VecSize(p->pHash) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } if ( pvRes ) *pvRes = Eso_ManCoverDerive( p, vCover ); else pNew = Eso_ManCoverConvert( p, vCover ); Vec_VecFree( (Vec_Vec_t *)vCover ); Eso_ManStop( p ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaExist.c000066400000000000000000000476001477524141600162170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaExist.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Existential quantification.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaExist.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 /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Existentially quantified several variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word * Gia_ManQuantInfoId( Gia_Man_t * p, int iObj ) { return Vec_WrdEntryP( p->vSuppWords, p->nSuppWords * iObj ); } static inline word * Gia_ManQuantInfo( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ManQuantInfoId( p, Gia_ObjId(p, pObj) ); } static inline void Gia_ObjCopyGetTwoArray( Gia_Man_t * p, int iObj, int LitsOut[2] ) { int * pLits = Vec_IntEntryP( &p->vCopiesTwo, 2*iObj ); LitsOut[0] = pLits[0]; LitsOut[1] = pLits[1]; } static inline void Gia_ObjCopySetTwoArray( Gia_Man_t * p, int iObj, int LitsIn[2] ) { int * pLits = Vec_IntEntryP( &p->vCopiesTwo, 2*iObj ); pLits[0] = LitsIn[0]; pLits[1] = LitsIn[1]; } /**Function************************************************************* Synopsis [Existentially quantified several variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManQuantVerify_rec( Gia_Man_t * p, int iObj, int CiId ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId( p, iObj ) ) return 0; Gia_ObjSetTravIdCurrentId( p, iObj ); pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjIsCi(pObj) ) return Gia_ObjCioId(pObj) == CiId; return Gia_ManQuantVerify_rec( p, Gia_ObjFaninId0(pObj, iObj), CiId ) || Gia_ManQuantVerify_rec( p, Gia_ObjFaninId1(pObj, iObj), CiId ); } void Gia_ManQuantVerify( Gia_Man_t * p, int iObj ) { word * pInfo = Gia_ManQuantInfoId( p, iObj ); int i, CiId; assert( Gia_ObjIsAnd(Gia_ManObj(p, iObj)) ); Vec_IntForEachEntry( &p->vSuppVars, CiId, i ) { Gia_ManIncrementTravId( p ); if ( Abc_TtGetBit(pInfo, i) != Gia_ManQuantVerify_rec(p, iObj, CiId) ) printf( "Mismatch at node %d related to CI %d (%d).\n", iObj, CiId, Abc_TtGetBit(pInfo, i) ); } } void Gia_ManQuantSetSuppStart( Gia_Man_t * p ) { assert( Gia_ManObjNum(p) == 1 ); assert( p->vSuppWords == NULL ); assert( Vec_IntSize(&p->vSuppVars) == 0 ); p->iSuppPi = 0; p->nSuppWords = 1; p->vSuppWords = Vec_WrdAlloc( 1000 ); Vec_WrdPush( p->vSuppWords, 0 ); } void Gia_ManQuantSetSuppZero( Gia_Man_t * p ) { int w; for ( w = 0; w < p->nSuppWords; w++ ) Vec_WrdPush( p->vSuppWords, 0 ); assert( Vec_WrdSize(p->vSuppWords) == p->nSuppWords * Gia_ManObjNum(p) ); } void Gia_ManQuantSetSuppCi( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsCi(pObj) ); assert( p->vSuppWords != NULL ); if ( p->iSuppPi == 64 * p->nSuppWords ) { word Data; int w, Count = 0, Size = Vec_WrdSize(p->vSuppWords); Vec_Wrd_t * vTemp = Vec_WrdAlloc( Size ? 2 * Size : 1000 ); Vec_WrdForEachEntry( p->vSuppWords, Data, w ) { Vec_WrdPush( vTemp, Data ); if ( ++Count == p->nSuppWords ) { Vec_WrdPush( vTemp, 0 ); Count = 0; } } Vec_WrdFree( p->vSuppWords ); p->vSuppWords = vTemp; p->nSuppWords++; assert( Vec_WrdSize(p->vSuppWords) == p->nSuppWords * Gia_ManObjNum(p) ); //printf( "Resizing to %d words.\n", p->nSuppWords ); } assert( p->iSuppPi == Vec_IntSize(&p->vSuppVars) ); Vec_IntPush( &p->vSuppVars, Gia_ObjCioId(pObj) ); Abc_TtSetBit( Gia_ManQuantInfo(p, pObj), p->iSuppPi++ ); } void Gia_ManQuantSetSuppAnd( Gia_Man_t * p, Gia_Obj_t * pObj ) { int iObj = Gia_ObjId(p, pObj); int iFan0 = Gia_ObjFaninId0(pObj, iObj); int iFan1 = Gia_ObjFaninId1(pObj, iObj); assert( Gia_ObjIsAnd(pObj) ); Gia_ManQuantSetSuppZero( p ); Abc_TtOr( Gia_ManQuantInfo(p, pObj), Gia_ManQuantInfoId(p, iFan0), Gia_ManQuantInfoId(p, iFan1), p->nSuppWords ); } int Gia_ManQuantCheckSupp( Gia_Man_t * p, int iObj, int iSupp ) { return Abc_TtGetBit( Gia_ManQuantInfoId(p, iObj), iSupp ); } void Gia_ManQuantUpdateCiSupp( Gia_Man_t * p, int iObj ) { if ( Abc_TtIsConst0( Gia_ManQuantInfoId(p, iObj), p->nSuppWords ) ) Gia_ManQuantSetSuppCi( p, Gia_ManObj(p, iObj) ); assert( !Abc_TtIsConst0( Gia_ManQuantInfoId(p, iObj), p->nSuppWords ) ); } int Gia_ManQuantCheckOverlap( Gia_Man_t * p, int iObj ) { return Abc_TtIntersect( Gia_ManQuantInfoId(p, iObj), Gia_ManQuantInfoId(p, 0), p->nSuppWords, 0 ); } void Gia_ManQuantMarkUsedCis( Gia_Man_t * p, int(*pFuncCiToKeep)(void *, int), void * pData ) { int i, CiId; word * pInfo = Gia_ManQuantInfoId( p, 0 ); Abc_TtClear( pInfo, p->nSuppWords ); assert( Abc_TtIsConst0(pInfo, p->nSuppWords) ); Vec_IntForEachEntry( &p->vSuppVars, CiId, i ) if ( !pFuncCiToKeep( pData, CiId ) ) // quant var Abc_TtSetBit( pInfo, i ); } int Gia_ManQuantCountUsed_rec( Gia_Man_t * p, int iObj ) { Gia_Obj_t * pObj; int Count = 1; if ( Gia_ObjIsTravIdCurrentId( p, iObj ) ) return 0; Gia_ObjSetTravIdCurrentId( p, iObj ); pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjIsCi(pObj) ) return 0; if ( Gia_ManQuantCheckSupp(p, Gia_ObjFaninId0(pObj, iObj), p->iSuppPi) ) Count += Gia_ManQuantCountUsed_rec( p, Gia_ObjFaninId0(pObj, iObj) ); if ( Gia_ManQuantCheckSupp(p, Gia_ObjFaninId1(pObj, iObj), p->iSuppPi) ) Count += Gia_ManQuantCountUsed_rec( p, Gia_ObjFaninId1(pObj, iObj) ); return Count; } int Gia_ManQuantCountUsed( Gia_Man_t * p, int iObj ) { Gia_ManIncrementTravId( p ); return Gia_ManQuantCountUsed_rec( p, iObj ); } void Gia_ManQuantDupConeSupp_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vCis, Vec_Int_t * vObjs, int(*pFuncCiToKeep)(void *, int), void * pData ) { int iLit0, iLit1, iObj = Gia_ObjId( p, pObj ); int iLit = Gia_ObjCopyArray( p, iObj ); if ( iLit >= 0 ) return; if ( Gia_ObjIsCi(pObj) ) { int iLit = Gia_ManAppendCi( pNew ); Gia_Obj_t * pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(iLit) ); Gia_ManQuantSetSuppZero( pNew ); if ( !pFuncCiToKeep( pData, Gia_ObjCioId(pObj) ) ) { //printf( "Collecting CI %d\n", Gia_ObjCioId(pObj)+1 ); Gia_ManQuantSetSuppCi( pNew, pObjNew ); } Gia_ObjSetCopyArray( p, iObj, iLit ); Vec_IntPush( vCis, iObj ); return; } assert( Gia_ObjIsAnd(pObj) ); Gia_ManQuantDupConeSupp_rec( pNew, p, Gia_ObjFanin0(pObj), vCis, vObjs, pFuncCiToKeep, pData ); Gia_ManQuantDupConeSupp_rec( pNew, p, Gia_ObjFanin1(pObj), vCis, vObjs, pFuncCiToKeep, pData ); iLit0 = Gia_ObjCopyArray( p, Gia_ObjFaninId0(pObj, iObj) ); iLit1 = Gia_ObjCopyArray( p, Gia_ObjFaninId1(pObj, iObj) ); iLit0 = Abc_LitNotCond( iLit0, Gia_ObjFaninC0(pObj) ); iLit1 = Abc_LitNotCond( iLit1, Gia_ObjFaninC1(pObj) ); iLit = Gia_ManHashAnd( pNew, iLit0, iLit1 ); Gia_ObjSetCopyArray( p, iObj, iLit ); Vec_IntPush( vObjs, iObj ); } Gia_Man_t * Gia_ManQuantDupConeSupp( Gia_Man_t * p, int iLit, int(*pFuncCiToKeep)(void *, int), void * pData, Vec_Int_t ** pvCis, int * pOutLit ) { Gia_Man_t * pNew; int i, iLit0, iObj; Gia_Obj_t * pObj, * pRoot = Gia_ManObj( p, Abc_Lit2Var(iLit) ); Vec_Int_t * vCis = Vec_IntAlloc( 1000 ); Vec_Int_t * vObjs = Vec_IntAlloc( 1000 ); assert( Gia_ObjIsAnd(pRoot) ); if ( Vec_IntSize(&p->vCopies) < Gia_ManObjNum(p) ) Vec_IntFillExtra( &p->vCopies, Gia_ManObjNum(p), -1 ); pNew = Gia_ManStart( 1000 ); Gia_ManHashStart( pNew ); Gia_ManQuantSetSuppStart( pNew ); Gia_ManQuantDupConeSupp_rec( pNew, p, pRoot, vCis, vObjs, pFuncCiToKeep, pData ); iLit0 = Gia_ObjCopyArray( p, Abc_Lit2Var(iLit) ); iLit0 = Abc_LitNotCond( iLit0, Abc_LitIsCompl(iLit) ); if ( pOutLit ) *pOutLit = iLit0; Gia_ManForEachObjVec( vCis, p, pObj, i ) Gia_ObjSetCopyArray( p, Gia_ObjId(p, pObj), -1 ); Gia_ManForEachObjVec( vObjs, p, pObj, i ) Gia_ObjSetCopyArray( p, Gia_ObjId(p, pObj), -1 ); //assert( Vec_IntCountLarger(&p->vCopies, -1) == 0 ); Vec_IntFree( vObjs ); // remap into CI Ids Vec_IntForEachEntry( vCis, iObj, i ) Vec_IntWriteEntry( vCis, i, Gia_ManIdToCioId(p, iObj) ); if ( pvCis ) *pvCis = vCis; return pNew; } void Gia_ManQuantExist_rec( Gia_Man_t * p, int iObj, int pRes[2] ) { Gia_Obj_t * pObj; int Lits0[2], Lits1[2], pFans[2], fCompl[2]; if ( Gia_ObjIsTravIdCurrentId( p, iObj ) ) { Gia_ObjCopyGetTwoArray( p, iObj, pRes ); return; } Gia_ObjSetTravIdCurrentId( p, iObj ); pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjIsCi(pObj) ) { pRes[0] = 0; pRes[1] = 1; Gia_ObjCopySetTwoArray( p, iObj, pRes ); return; } pFans[0] = Gia_ObjFaninId0( pObj, iObj ); pFans[1] = Gia_ObjFaninId1( pObj, iObj ); fCompl[0] = Gia_ObjFaninC0( pObj ); fCompl[1] = Gia_ObjFaninC1( pObj ); if ( Gia_ManQuantCheckSupp(p, pFans[0], p->iSuppPi) ) Gia_ManQuantExist_rec( p, pFans[0], Lits0 ); else Lits0[0] = Lits0[1] = Abc_Var2Lit( pFans[0], 0 ); if ( Gia_ManQuantCheckSupp(p, pFans[1], p->iSuppPi) ) Gia_ManQuantExist_rec( p, pFans[1], Lits1 ); else Lits1[0] = Lits1[1] = Abc_Var2Lit( pFans[1], 0 ); pRes[0] = Gia_ManHashAnd( p, Abc_LitNotCond(Lits0[0], fCompl[0]), Abc_LitNotCond(Lits1[0], fCompl[1]) ); pRes[1] = Gia_ManHashAnd( p, Abc_LitNotCond(Lits0[1], fCompl[0]), Abc_LitNotCond(Lits1[1], fCompl[1]) ); Gia_ObjCopySetTwoArray( p, iObj, pRes ); } int Gia_ManQuantExist2( Gia_Man_t * p0, int iLit, int(*pFuncCiToKeep)(void *, int), void * pData ) { // abctime clk = Abc_Clock(); Gia_Man_t * pNew; Vec_Int_t * vOuts, * vOuts2, * vCis; Gia_Obj_t * pObj = Gia_ManObj( p0, Abc_Lit2Var(iLit) ); int i, n, Entry, Lit, OutLit = -1, pLits[2], nVarsQua, nAndsOld, nAndsNew; if ( iLit < 2 ) return iLit; if ( Gia_ObjIsCi(pObj) ) return pFuncCiToKeep(pData, Gia_ObjCioId(pObj)) ? iLit : 1; assert( Gia_ObjIsAnd(pObj) ); pNew = Gia_ManQuantDupConeSupp( p0, iLit, pFuncCiToKeep, pData, &vCis, &OutLit ); if ( pNew->iSuppPi == 0 ) { Gia_ManStop( pNew ); Vec_IntFree( vCis ); return iLit; } assert( pNew->iSuppPi > 0 && pNew->iSuppPi <= 64 * pNew->nSuppWords ); vOuts = Vec_IntAlloc( 100 ); vOuts2 = Vec_IntAlloc( 100 ); assert( OutLit > 1 ); Vec_IntPush( vOuts, OutLit ); nVarsQua = pNew->iSuppPi; nAndsOld = Gia_ManAndNum(pNew); while ( --pNew->iSuppPi >= 0 ) { Entry = Abc_Lit2Var( Vec_IntEntry(vOuts, 0) ); // printf( "Quantifying input %d with %d affected nodes (out of %d):\n", // pNew->iSuppPi, Gia_ManQuantCountUsed(pNew,Entry), Gia_ManAndNum(pNew) ); if ( Vec_IntSize(&pNew->vCopiesTwo) < 2*Gia_ManObjNum(pNew) ) Vec_IntFillExtra( &pNew->vCopiesTwo, 2*Gia_ManObjNum(pNew), -1 ); assert( Vec_IntSize(vOuts) > 0 ); Vec_IntClear( vOuts2 ); Gia_ManIncrementTravId( pNew ); Vec_IntForEachEntry( vOuts, Entry, i ) { Gia_ManQuantExist_rec( pNew, Abc_Lit2Var(Entry), pLits ); for ( n = 0; n < 2; n++ ) { Lit = Abc_LitNotCond( pLits[n], Abc_LitIsCompl(Entry) ); if ( Lit == 0 ) continue; if ( Lit == 1 ) { Vec_IntFree( vOuts ); Vec_IntFree( vOuts2 ); Gia_ManStop( pNew ); Vec_IntFree( vCis ); return 1; } Vec_IntPushUnique( vOuts2, Lit ); } } Vec_IntClear( vOuts ); ABC_SWAP( Vec_Int_t *, vOuts, vOuts2 ); } // printf( "\n" ); //printf( "The number of diff cofactors = %d.\n", Vec_IntSize(vOuts) ); assert( Vec_IntSize(vOuts) > 0 ); Vec_IntForEachEntry( vOuts, Entry, i ) Vec_IntWriteEntry( vOuts, i, Abc_LitNot(Entry) ); OutLit = Gia_ManHashAndMulti( pNew, vOuts ); OutLit = Abc_LitNot( OutLit ); Vec_IntFree( vOuts ); Vec_IntFree( vOuts2 ); // transfer back Gia_ManAppendCo( pNew, OutLit ); nAndsNew = Gia_ManAndNum(p0); Lit = Gia_ManDupConeBack( p0, pNew, vCis ); nAndsNew = Gia_ManAndNum(p0) - nAndsNew; Gia_ManStop( pNew ); // report the result // printf( "Performed quantification with %6d nodes, %3d keep-vars, %3d quant-vars, resulting in %5d new nodes. \n", // nAndsOld, Vec_IntSize(vCis) - nVarsQua, nVarsQua, nAndsNew ); // Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Vec_IntFree( vCis ); return Lit; } /**Function************************************************************* Synopsis [Existentially quantified several variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManQuantCollect_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vQuantCis, Vec_Int_t * vQuantSide, Vec_Int_t * vQuantAnds ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId( p, iObj ) ) return; Gia_ObjSetTravIdCurrentId( p, iObj ); if ( !Gia_ManQuantCheckOverlap(p, iObj) ) { Vec_IntPush( vQuantSide, iObj ); return; } pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjIsCi(pObj) ) { Vec_IntPush( vQuantCis, iObj ); return; } Gia_ManQuantCollect_rec( p, Gia_ObjFaninId0(pObj, iObj), vQuantCis, vQuantSide, vQuantAnds ); Gia_ManQuantCollect_rec( p, Gia_ObjFaninId1(pObj, iObj), vQuantCis, vQuantSide, vQuantAnds ); Vec_IntPush( vQuantAnds, iObj ); } void Gia_ManQuantCollect( Gia_Man_t * p, int iObj, int(*pFuncCiToKeep)(void *, int), void * pData, Vec_Int_t * vQuantCis, Vec_Int_t * vQuantSide, Vec_Int_t * vQuantAnds ) { Gia_ManQuantMarkUsedCis( p, pFuncCiToKeep, pData ); Gia_ManIncrementTravId( p ); Gia_ManQuantCollect_rec( p, iObj, vQuantCis, vQuantSide, vQuantAnds ); // printf( "\nCreated cone with %d quant-vars, %d side-inputs, and %d internal nodes.\n", // Vec_IntSize(p->vQuantCis), Vec_IntSize(p->vQuantSide), Vec_IntSize(p->vQuantAnds) ); } Gia_Man_t * Gia_ManQuantExist2Dup( Gia_Man_t * p, int iLit, Vec_Int_t * vCis, Vec_Int_t * vSide, Vec_Int_t * vAnds, int * pOutLit ) { int i, iObj, iLit0, iLit1, iLitR; Gia_Man_t * pNew = Gia_ManStart( Vec_IntSize(vSide) + Vec_IntSize(vCis) + 10*Vec_IntSize(vAnds) ); Gia_ManQuantSetSuppStart( pNew ); Gia_ManHashStart( pNew ); if ( Vec_IntSize(&p->vCopies) < Gia_ManObjNum(p) ) Vec_IntFillExtra( &p->vCopies, Gia_ManObjNum(p), -1 ); Vec_IntForEachEntry( vSide, iObj, i ) { Gia_ObjSetCopyArray( p, iObj, Gia_ManAppendCi(pNew) ); Gia_ManQuantSetSuppZero( pNew ); } Vec_IntForEachEntry( vCis, iObj, i ) { Gia_ObjSetCopyArray( p, iObj, (iLit0 = Gia_ManAppendCi(pNew)) ); Gia_ManQuantSetSuppZero( pNew ); Gia_ManQuantSetSuppCi( pNew, Gia_ManObj(pNew, Abc_Lit2Var(iLit0)) ); } Vec_IntForEachEntry( vAnds, iObj, i ) { Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); iLit0 = Gia_ObjCopyArray( p, Gia_ObjFaninId0(pObj, iObj) ); iLit1 = Gia_ObjCopyArray( p, Gia_ObjFaninId1(pObj, iObj) ); iLit0 = Abc_LitNotCond( iLit0, Gia_ObjFaninC0(pObj) ); iLit1 = Abc_LitNotCond( iLit1, Gia_ObjFaninC1(pObj) ); iLitR = Gia_ManHashAnd( pNew, iLit0, iLit1 ); Gia_ObjSetCopyArray( p, iObj, iLitR ); } iLit0 = Gia_ObjCopyArray( p, Abc_Lit2Var(iLit) ); iLit0 = Abc_LitNotCond( iLit0, Abc_LitIsCompl(iLit) ); if ( pOutLit ) *pOutLit = iLit0; Vec_IntForEachEntry( vSide, iObj, i ) Gia_ObjSetCopyArray( p, iObj, -1 ); Vec_IntForEachEntry( vCis, iObj, i ) Gia_ObjSetCopyArray( p, iObj, -1 ); Vec_IntForEachEntry( vAnds, iObj, i ) Gia_ObjSetCopyArray( p, iObj, -1 ); return pNew; } int Gia_ManQuantExistInt( Gia_Man_t * p0, int iLit, Vec_Int_t * vCis, Vec_Int_t * vSide, Vec_Int_t * vAnds ) { int i, Lit, iOutLit, nAndsNew, pLits[2], pRes[2] = {0}; Gia_Man_t * pNew; if ( iLit < 2 ) return 0; if ( Vec_IntSize(vCis) == 0 ) return iLit; if ( Vec_IntSize(vAnds) == 0 ) { assert( Gia_ObjIsCi( Gia_ManObj(p0, Abc_Lit2Var(iLit)) ) ); return Vec_IntFind(vCis, Abc_Lit2Var(iLit)) == -1 ? iLit : 1; } pNew = Gia_ManQuantExist2Dup( p0, iLit, vCis, vSide, vAnds, &iOutLit ); if ( Vec_IntSize(&pNew->vCopiesTwo) < 2*Gia_ManObjNum(pNew) ) Vec_IntFillExtra( &pNew->vCopiesTwo, 2*Gia_ManObjNum(pNew), -1 ); Gia_ObjCopySetTwoArray( pNew, 0, pRes ); for ( i = 0; i < Gia_ManCiNum(pNew); i++ ) { pRes[0] = pRes[1] = Abc_Var2Lit( i+1, 0 ); Gia_ObjCopySetTwoArray( pNew, i+1, pRes ); } assert( pNew->iSuppPi == Gia_ManCiNum(pNew) - Vec_IntSize(vSide) ); for ( i = Gia_ManCiNum(pNew) - 1; i >= Vec_IntSize(vSide); i-- ) { pRes[0] = 0; pRes[1] = 1; Gia_ObjCopySetTwoArray( pNew, i+1, pRes ); pNew->iSuppPi--; if ( Vec_IntSize(&pNew->vCopiesTwo) < 2*Gia_ManObjNum(pNew) ) Vec_IntFillExtra( &pNew->vCopiesTwo, 2*Gia_ManObjNum(pNew), -1 ); Gia_ManIncrementTravId( pNew ); Gia_ManQuantExist_rec( pNew, Abc_Lit2Var(iOutLit), pLits ); pLits[0] = Abc_LitNotCond( pLits[0], Abc_LitIsCompl(iOutLit) ); pLits[1] = Abc_LitNotCond( pLits[1], Abc_LitIsCompl(iOutLit) ); iOutLit = Gia_ManHashOr( pNew, pLits[0], pLits[1] ); pRes[0] = pRes[1] = Abc_Var2Lit( i+1, 0 ); Gia_ObjCopySetTwoArray( pNew, i+1, pRes ); } assert( pNew->iSuppPi == 0 ); Vec_IntAppend( vSide, vCis ); // transfer back Gia_ManAppendCo( pNew, iOutLit ); nAndsNew = Gia_ManAndNum(p0); Lit = Gia_ManDupConeBackObjs( p0, pNew, vSide ); nAndsNew = Gia_ManAndNum(p0) - nAndsNew; Vec_IntShrink( vSide, Vec_IntSize(vSide) - Vec_IntSize(vCis) ); // printf( "Performed quantification with %6d -> %6d nodes, %3d side-vars, %3d quant-vars, resulting in %5d new nodes. \n", // Vec_IntSize(vAnds), Gia_ManAndNum(pNew), Vec_IntSize(vSide), Vec_IntSize(vCis), nAndsNew ); Gia_ManStop( pNew ); return Lit; } int Gia_ManQuantExist( Gia_Man_t * p0, int iLit, int(*pFuncCiToKeep)(void *, int), void * pData ) { int Res; Vec_Int_t * vQuantCis = Vec_IntAlloc( 100 ); Vec_Int_t * vQuantSide = Vec_IntAlloc( 100 ); Vec_Int_t * vQuantAnds = Vec_IntAlloc( 100 ); Gia_ManQuantCollect( p0, Abc_Lit2Var(iLit), pFuncCiToKeep, pData, vQuantCis, vQuantSide, vQuantAnds ); Res = Gia_ManQuantExistInt( p0, iLit, vQuantCis, vQuantSide, vQuantAnds ); Vec_IntFree( vQuantCis ); Vec_IntFree( vQuantSide ); Vec_IntFree( vQuantAnds ); return Res; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaFalse.c000066400000000000000000000477741477524141600161710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaFalse.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Detection and elimination of false paths.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaFalse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/vec/vecQue.h" #include "misc/vec/vecWec.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reconstruct the AIG after detecting false paths.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFalseRebuildOne( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Int_t * vHook, int fVerbose, int fVeryVerbose ) { Gia_Obj_t * pObj, * pObj1, * pPrev = NULL; int i, CtrlValue = 0, iPrevValue = -1; pObj = Gia_ManObj( p, Vec_IntEntry(vHook, 0) ); if ( Vec_IntSize(vHook) == 1 ) { pObj->Value = 0; // what if stuck at 1??? return; } assert( Vec_IntSize(vHook) >= 2 ); // find controlling value pObj1 = Gia_ManObj( p, Vec_IntEntry(vHook, 1) ); if ( Gia_ObjFanin0(pObj1) == pObj ) CtrlValue = Gia_ObjFaninC0(pObj1); else if ( Gia_ObjFanin1(pObj1) == pObj ) CtrlValue = Gia_ObjFaninC1(pObj1); else assert( 0 ); // printf( "%d ", CtrlValue ); // rewrite the path Gia_ManForEachObjVec( vHook, p, pObj, i ) { int iObjValue = pObj->Value; pObj->Value = i ? Gia_ManHashAnd(pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj)) : CtrlValue; if ( pPrev ) pPrev->Value = iPrevValue; iPrevValue = iObjValue; pPrev = pObj; } if ( fVeryVerbose ) { printf( "Eliminated path: " ); Vec_IntPrint( vHook ); Gia_ManForEachObjVec( vHook, p, pObj, i ) { printf( "Level %3d : ", Gia_ObjLevel(p, pObj) ); Gia_ObjPrint( p, pObj ); } } } Gia_Man_t * Gia_ManFalseRebuild( Gia_Man_t * p, Vec_Wec_t * vHooks, int fVerbose, int fVeryVerbose ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, Counter = 0; pNew = Gia_ManStart( 4 * Gia_ManObjNum(p) / 3 ); 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_ObjIsAnd(pObj) ) { if ( Vec_WecLevelSize(vHooks, i) > 0 ) { if ( fVeryVerbose ) printf( "Path %d : ", Counter++ ); Gia_ManFalseRebuildOne( pNew, p, Vec_WecEntry(vHooks, i), fVerbose, fVeryVerbose ); } else 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) ); } Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Derive critical path by following minimum slacks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCollectPath_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPath ) { if ( Gia_ObjIsAnd(pObj) ) { if ( Gia_ObjLevel(p, Gia_ObjFanin0(pObj)) > Gia_ObjLevel(p, Gia_ObjFanin1(pObj)) ) Gia_ManCollectPath_rec( p, Gia_ObjFanin0(pObj), vPath ); else if ( Gia_ObjLevel(p, Gia_ObjFanin0(pObj)) < Gia_ObjLevel(p, Gia_ObjFanin1(pObj)) ) Gia_ManCollectPath_rec( p, Gia_ObjFanin1(pObj), vPath ); // else if ( rand() & 1 ) // Gia_ManCollectPath_rec( p, Gia_ObjFanin0(pObj), vPath ); else Gia_ManCollectPath_rec( p, Gia_ObjFanin1(pObj), vPath ); } Vec_IntPush( vPath, Gia_ObjId(p, pObj) ); } Vec_Int_t * Gia_ManCollectPath( Gia_Man_t * p, Gia_Obj_t * pObj ) { Vec_Int_t * vPath = Vec_IntAlloc( p->nLevels ); Gia_ManCollectPath_rec( p, Gia_ObjIsCo(pObj) ? Gia_ObjFanin0(pObj) : pObj, vPath ); return vPath; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCheckFalseOne( Gia_Man_t * p, int iOut, int nTimeOut, Vec_Wec_t * vHooks, int fVerbose, int fVeryVerbose ) { sat_solver * pSat; Gia_Obj_t * pObj, * pFanin; Gia_Obj_t * pPivot = Gia_ManCo( p, iOut ); Vec_Int_t * vLits = Vec_IntAlloc( p->nLevels ); Vec_Int_t * vPath = Gia_ManCollectPath( p, pPivot ); int nLits = 0, * pLits = NULL; int i, Shift[2], status; abctime clkStart = Abc_Clock(); // collect objects and assign SAT variables int iFanin = Gia_ObjFaninId0p( p, pPivot ); Vec_Int_t * vObjs = Gia_ManCollectNodesCis( p, &iFanin, 1 ); Gia_ManForEachObjVec( vObjs, p, pObj, i ) pObj->Value = Vec_IntSize(vObjs) - 1 - i; assert( Gia_ObjIsCo(pPivot) ); // create SAT solver pSat = sat_solver_new(); sat_solver_set_runtime_limit( pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); sat_solver_setnvars( pSat, 3 * Vec_IntSize(vPath) + 2 * Vec_IntSize(vObjs) ); Shift[0] = 3 * Vec_IntSize(vPath); Shift[1] = 3 * Vec_IntSize(vPath) + Vec_IntSize(vObjs); // add CNF for the cone Gia_ManForEachObjVec( vObjs, p, pObj, i ) { if ( !Gia_ObjIsAnd(pObj) ) continue; sat_solver_add_and( pSat, pObj->Value + Shift[0], Gia_ObjFanin0(pObj)->Value + Shift[0], Gia_ObjFanin1(pObj)->Value + Shift[0], Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); sat_solver_add_and( pSat, pObj->Value + Shift[1], Gia_ObjFanin0(pObj)->Value + Shift[1], Gia_ObjFanin1(pObj)->Value + Shift[1], Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); } // add CNF for the path Gia_ManForEachObjVec( vPath, p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) { assert( i > 0 ); pFanin = Gia_ManObj( p, Vec_IntEntry(vPath, i-1) ); if ( pFanin == Gia_ObjFanin0(pObj) ) { sat_solver_add_and( pSat, i + 1*Vec_IntSize(vPath), i-1 + 1*Vec_IntSize(vPath), Gia_ObjFanin1(pObj)->Value + Shift[0], Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); sat_solver_add_and( pSat, i + 2*Vec_IntSize(vPath), i-1 + 2*Vec_IntSize(vPath), Gia_ObjFanin1(pObj)->Value + Shift[1], Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); } else if ( pFanin == Gia_ObjFanin1(pObj) ) { sat_solver_add_and( pSat, i + 1*Vec_IntSize(vPath), Gia_ObjFanin0(pObj)->Value + Shift[0], i-1 + 1*Vec_IntSize(vPath), Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); sat_solver_add_and( pSat, i + 2*Vec_IntSize(vPath), Gia_ObjFanin0(pObj)->Value + Shift[1], i-1 + 2*Vec_IntSize(vPath), Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); } else assert( 0 ); sat_solver_add_xor( pSat, i, i + 1*Vec_IntSize(vPath), i + 2*Vec_IntSize(vPath), 0 ); } else if ( Gia_ObjIsCi(pObj) ) sat_solver_add_xor( pSat, i, pObj->Value + Shift[0], pObj->Value + Shift[1], 0 ); else assert( 0 ); Vec_IntPush( vLits, Abc_Var2Lit(i, 0) ); } // call the SAT solver status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), (ABC_INT64_T)nTimeOut, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( status == l_False ) { int iBeg, iEnd; nLits = sat_solver_final( pSat, &pLits ); iBeg = Abc_Lit2Var(pLits[nLits-1]); iEnd = Abc_Lit2Var(pLits[0]); if ( iEnd - iBeg < 20 ) { // check if nodes on the path are already used for ( i = Abc_MaxInt(iBeg-1, 0); i <= iEnd; i++ ) if ( Vec_WecLevelSize(vHooks, Vec_IntEntry(vPath, i)) > 0 ) break; if ( i > iEnd ) { Vec_Int_t * vHook = Vec_WecEntry(vHooks, Vec_IntEntry(vPath, iEnd)); for ( i = Abc_MaxInt(iBeg-1, 0); i <= iEnd; i++ ) Vec_IntPush( vHook, Vec_IntEntry(vPath, i) ); } } } if ( fVerbose ) { printf( "PO %6d : Level = %3d ", iOut, Gia_ObjLevel(p, pPivot) ); if ( status == l_Undef ) printf( "Timeout reached after %d seconds. ", nTimeOut ); else if ( status == l_True ) printf( "There is no false path. " ); else { printf( "False path contains %d nodes (out of %d): ", nLits, Vec_IntSize(vPath) ); printf( "top = %d ", Vec_IntEntry(vPath, Abc_Lit2Var(pLits[0])) ); if ( fVeryVerbose ) for ( i = 0; i < nLits; i++ ) printf( "%d ", Abc_Lit2Var(pLits[i]) ); printf( " " ); } Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); } sat_solver_delete( pSat ); Vec_IntFree( vObjs ); Vec_IntFree( vPath ); Vec_IntFree( vLits ); } Gia_Man_t * Gia_ManCheckFalse2( Gia_Man_t * p, int nSlackMax, int nTimeOut, int fVerbose, int fVeryVerbose ) { Gia_Man_t * pNew; Vec_Wec_t * vHooks; Vec_Que_t * vPrio; Vec_Flt_t * vWeights; Gia_Obj_t * pObj; int i; // srand( 111 ); Gia_ManLevelNum( p ); // create PO weights vWeights = Vec_FltAlloc( Gia_ManCoNum(p) ); Gia_ManForEachCo( p, pObj, i ) Vec_FltPush( vWeights, Gia_ObjLevel(p, pObj) ); // put POs into the queue vPrio = Vec_QueAlloc( Gia_ManCoNum(p) ); Vec_QueSetPriority( vPrio, Vec_FltArrayP(vWeights) ); Gia_ManForEachCo( p, pObj, i ) Vec_QuePush( vPrio, i ); // work on each PO in the queue vHooks = Vec_WecStart( Gia_ManObjNum(p) ); while ( Vec_QueTopPriority(vPrio) >= p->nLevels - nSlackMax ) Gia_ManCheckFalseOne( p, Vec_QuePop(vPrio), nTimeOut, vHooks, fVerbose, fVeryVerbose ); if ( fVerbose ) printf( "Collected %d non-overlapping false paths.\n", Vec_WecSizeUsed(vHooks) ); // reconstruct the AIG pNew = Gia_ManFalseRebuild( p, vHooks, fVerbose, fVeryVerbose ); // cleanup Vec_WecFree( vHooks ); Vec_FltFree( vWeights ); Vec_QueFree( vPrio ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFalseRebuildPath( Gia_Man_t * p, Vec_Int_t * vHooks, int fVerbose, int fVeryVerbose ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iPathEnd = Vec_IntEntryLast(vHooks); pNew = Gia_ManStart( 4 * Gia_ManObjNum(p) / 3 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManFillValue(p); Gia_ManConst0(p)->Value = 0; Gia_ManHashAlloc( pNew ); Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) { if ( iPathEnd == i ) Gia_ManFalseRebuildOne( pNew, p, vHooks, fVerbose, fVeryVerbose ); else 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) ); } Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } Gia_Man_t * Gia_ManCheckOne( Gia_Man_t * p, int iOut, int iObj, int nTimeOut, int fVerbose, int fVeryVerbose ) { sat_solver * pSat; Gia_Man_t * pNew; Gia_Obj_t * pObj, * pFanin; Vec_Int_t * vLits = Vec_IntAlloc( p->nLevels ); Vec_Int_t * vPath = Gia_ManCollectPath( p, Gia_ManObj(p, iObj) ); int nLits = 0, * pLits = NULL; int i, Shift[2], status; abctime clkStart = Abc_Clock(); // collect objects and assign SAT variables Vec_Int_t * vObjs = Gia_ManCollectNodesCis( p, &iObj, 1 ); Gia_ManForEachObjVec( vObjs, p, pObj, i ) pObj->Value = Vec_IntSize(vObjs) - 1 - i; // create SAT solver pSat = sat_solver_new(); sat_solver_set_runtime_limit( pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); sat_solver_setnvars( pSat, 3 * Vec_IntSize(vPath) + 2 * Vec_IntSize(vObjs) ); Shift[0] = 3 * Vec_IntSize(vPath); Shift[1] = 3 * Vec_IntSize(vPath) + Vec_IntSize(vObjs); // add CNF for the cone Gia_ManForEachObjVec( vObjs, p, pObj, i ) { if ( !Gia_ObjIsAnd(pObj) ) continue; sat_solver_add_and( pSat, pObj->Value + Shift[0], Gia_ObjFanin0(pObj)->Value + Shift[0], Gia_ObjFanin1(pObj)->Value + Shift[0], Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); sat_solver_add_and( pSat, pObj->Value + Shift[1], Gia_ObjFanin0(pObj)->Value + Shift[1], Gia_ObjFanin1(pObj)->Value + Shift[1], Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); } // add CNF for the path Gia_ManForEachObjVec( vPath, p, pObj, i ) { if ( !Gia_ObjIsAnd(pObj) ) continue; assert( i > 0 ); pFanin = Gia_ManObj( p, Vec_IntEntry(vPath, i-1) ); if ( pFanin == Gia_ObjFanin0(pObj) ) { sat_solver_add_and( pSat, i + 1*Vec_IntSize(vPath), i-1 + 1*Vec_IntSize(vPath), Gia_ObjFanin1(pObj)->Value + Shift[0], Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); sat_solver_add_and( pSat, i + 2*Vec_IntSize(vPath), i-1 + 2*Vec_IntSize(vPath), Gia_ObjFanin1(pObj)->Value + Shift[1], Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); } else if ( pFanin == Gia_ObjFanin1(pObj) ) { sat_solver_add_and( pSat, i + 1*Vec_IntSize(vPath), Gia_ObjFanin0(pObj)->Value + Shift[0], i-1 + 1*Vec_IntSize(vPath), Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); sat_solver_add_and( pSat, i + 2*Vec_IntSize(vPath), Gia_ObjFanin0(pObj)->Value + Shift[1], i-1 + 2*Vec_IntSize(vPath), Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); } else assert( 0 ); sat_solver_add_xor( pSat, i, i + 1*Vec_IntSize(vPath), i + 2*Vec_IntSize(vPath), 0 ); Vec_IntPush( vLits, Abc_Var2Lit(i, 0) ); } // call the SAT solver status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), (ABC_INT64_T)nTimeOut, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); Vec_IntClear( vLits ); if ( status == l_False ) { int iBeg, iEnd; nLits = sat_solver_final( pSat, &pLits ); iBeg = Abc_Lit2Var(pLits[nLits-1]); iEnd = Abc_Lit2Var(pLits[0]); assert( iBeg <= iEnd ); // collect path for ( i = Abc_MaxInt(iBeg-1, 0); i <= iEnd; i++ ) // for ( i = 0; i < Vec_IntSize(vPath); i++ ) Vec_IntPush( vLits, Vec_IntEntry(vPath, i) ); } if ( fVerbose ) { printf( "PO %6d : Level = %3d ", iOut, Gia_ObjLevelId(p, iObj) ); if ( status == l_Undef ) printf( "Timeout reached after %d seconds. ", nTimeOut ); else if ( status == l_True ) printf( "There is no false path. " ); else { printf( "False path contains %d nodes (out of %d): ", Vec_IntSize(vLits), Vec_IntSize(vPath) ); if ( fVeryVerbose ) for ( i = nLits-1; i >= 0; i-- ) printf( "%d ", Vec_IntEntry(vPath, Abc_Lit2Var(pLits[i])) ); printf( " " ); } Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); } sat_solver_delete( pSat ); Vec_IntFree( vObjs ); Vec_IntFree( vPath ); // update the AIG pNew = Vec_IntSize(vLits) ? Gia_ManFalseRebuildPath( p, vLits, fVerbose, fVeryVerbose ) : NULL; Vec_IntFree( vLits ); /* if ( pNew ) { Gia_Man_t * pTemp = Gia_ManDupDfsNode( p, Gia_ManObj(p, iObj) ); 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 ); } */ return pNew; } Gia_Man_t * Gia_ManCheckFalseAll( Gia_Man_t * p, int nSlackMax, int nTimeOut, int fVerbose, int fVeryVerbose ) { int Tried = 0, Changed = 0; p = Gia_ManDup( p ); while ( 1 ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, LevelMax, Changed0 = Changed; LevelMax = Gia_ManLevelNum( p ); Gia_ManForEachAnd( p, pObj, i ) { if ( Gia_ObjLevel(p, pObj) > nSlackMax ) continue; Tried++; pNew = Gia_ManCheckOne( p, -1, i, nTimeOut, fVerbose, fVeryVerbose ); if ( pNew == NULL ) continue; Changed++; Gia_ManStop( p ); p = pNew; LevelMax = Gia_ManLevelNum( p ); } if ( Changed0 == Changed ) break; } // if ( fVerbose ) printf( "Performed %d attempts and %d changes.\n", Tried, Changed ); return p; } Gia_Man_t * Gia_ManCheckFalse( Gia_Man_t * p, int nSlackMax, int nTimeOut, int fVerbose, int fVeryVerbose ) { int Tried = 0, Changed = 0; Vec_Int_t * vTried; // srand( 111 ); p = Gia_ManDup( p ); vTried = Vec_IntStart( Gia_ManCoNum(p) ); while ( 1 ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, LevelMax, Changed0 = Changed; LevelMax = Gia_ManLevelNum( p ); Gia_ManForEachCo( p, pObj, i ) { if ( !Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ) continue; if ( Gia_ObjLevel(p, Gia_ObjFanin0(pObj)) < LevelMax - nSlackMax ) continue; if ( Vec_IntEntry( vTried, i ) ) continue; Tried++; pNew = Gia_ManCheckOne( p, i, Gia_ObjFaninId0p(p, pObj), nTimeOut, fVerbose, fVeryVerbose ); /* if ( i != 126 && pNew ) { Gia_ManStop( pNew ); pNew = NULL; } */ if ( pNew == NULL ) { Vec_IntWriteEntry( vTried, i, 1 ); continue; } Changed++; Gia_ManStop( p ); p = pNew; LevelMax = Gia_ManLevelNum( p ); } if ( Changed0 == Changed ) break; } // if ( fVerbose ) printf( "Performed %d attempts and %d changes.\n", Tried, Changed ); Vec_IntFree( vTried ); return p; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaFanout.c000066400000000000000000000332741477524141600163610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaFanout.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: giaFanout.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // 0: first iFan // 1: prev iFan0 // 2: prev iFan1 // 3: next iFan0 // 4: next iFan1 static inline int Gia_FanoutCreate( int FanId, int Num ) { assert( Num < 2 ); return (FanId << 1) | Num; } static inline int * Gia_FanoutObj( int * pData, int ObjId ) { return pData + 5*ObjId; } static inline int * Gia_FanoutPrev( int * pData, int iFan ) { return pData + 5*(iFan >> 1) + 1 + (iFan & 1); } static inline int * Gia_FanoutNext( int * pData, int iFan ) { return pData + 5*(iFan >> 1) + 3 + (iFan & 1); } // these two procedures are only here for the use inside the iterator static inline int Gia_ObjFanout0Int( Gia_Man_t * p, int ObjId ) { assert(ObjId < p->nFansAlloc); return p->pFanData[5*ObjId]; } static inline int Gia_ObjFanoutNext( Gia_Man_t * p, int iFan ) { assert(iFan/2 < p->nFansAlloc); return p->pFanData[5*(iFan >> 1) + 3 + (iFan & 1)]; } // iterator over the fanouts #define Gia_ObjForEachFanout( p, pObj, pFanout, iFan, i ) \ for ( assert(p->pFanData), i = 0; (i < (int)(pObj)->nRefs) && \ (((iFan) = i? Gia_ObjFanoutNext(p, iFan) : Gia_ObjFanout0Int(p, Gia_ObjId(p, pObj))), 1) && \ (((pFanout) = Gia_ManObj(p, iFan>>1)), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Create fanout for all objects in the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFanoutStart( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; // allocate fanout datastructure assert( p->pFanData == NULL ); p->nFansAlloc = 2 * Gia_ManObjNum(p); if ( p->nFansAlloc < (1<<12) ) p->nFansAlloc = (1<<12); p->pFanData = ABC_ALLOC( int, 5 * p->nFansAlloc ); memset( p->pFanData, 0, sizeof(int) * 5 * p->nFansAlloc ); // add fanouts for all objects Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjChild0(pObj) ) Gia_ObjAddFanout( p, Gia_ObjFanin0(pObj), pObj ); if ( Gia_ObjChild1(pObj) ) Gia_ObjAddFanout( p, Gia_ObjFanin1(pObj), pObj ); } } /**Function************************************************************* Synopsis [Deletes fanout for all objects in the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFanoutStop( Gia_Man_t * p ) { assert( p->pFanData != NULL ); ABC_FREE( p->pFanData ); p->nFansAlloc = 0; } /**Function************************************************************* Synopsis [Adds fanout (pFanout) of node (pObj).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ObjAddFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout ) { int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext; assert( p->pFanData ); assert( !Gia_IsComplement(pObj) && !Gia_IsComplement(pFanout) ); assert( Gia_ObjId(p, pFanout) > 0 ); if ( Gia_ObjId(p, pObj) >= p->nFansAlloc || Gia_ObjId(p, pFanout) >= p->nFansAlloc ) { int nFansAlloc = 2 * Abc_MaxInt( Gia_ObjId(p, pObj), Gia_ObjId(p, pFanout) ); p->pFanData = ABC_REALLOC( int, p->pFanData, 5 * nFansAlloc ); memset( p->pFanData + 5 * p->nFansAlloc, 0, sizeof(int) * 5 * (nFansAlloc - p->nFansAlloc) ); p->nFansAlloc = nFansAlloc; } assert( Gia_ObjId(p, pObj) < p->nFansAlloc && Gia_ObjId(p, pFanout) < p->nFansAlloc ); iFan = Gia_FanoutCreate( Gia_ObjId(p, pFanout), Gia_ObjWhatFanin(p, pFanout, pObj) ); pPrevC = Gia_FanoutPrev( p->pFanData, iFan ); pNextC = Gia_FanoutNext( p->pFanData, iFan ); pFirst = Gia_FanoutObj( p->pFanData, Gia_ObjId(p, pObj) ); if ( *pFirst == 0 ) { *pFirst = iFan; *pPrevC = iFan; *pNextC = iFan; } else { pPrev = Gia_FanoutPrev( p->pFanData, *pFirst ); pNext = Gia_FanoutNext( p->pFanData, *pPrev ); assert( *pNext == *pFirst ); *pPrevC = *pPrev; *pNextC = *pFirst; *pPrev = iFan; *pNext = iFan; } } /**Function************************************************************* Synopsis [Removes fanout (pFanout) of node (pObj).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ObjRemoveFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout ) { int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext; assert( p->pFanData && Gia_ObjId(p, pObj) < p->nFansAlloc && Gia_ObjId(p, pFanout) < p->nFansAlloc ); assert( !Gia_IsComplement(pObj) && !Gia_IsComplement(pFanout) ); assert( Gia_ObjId(p, pFanout) > 0 ); iFan = Gia_FanoutCreate( Gia_ObjId(p, pFanout), Gia_ObjWhatFanin(p, pFanout, pObj) ); pPrevC = Gia_FanoutPrev( p->pFanData, iFan ); pNextC = Gia_FanoutNext( p->pFanData, iFan ); pPrev = Gia_FanoutPrev( p->pFanData, *pNextC ); pNext = Gia_FanoutNext( p->pFanData, *pPrevC ); assert( *pPrev == iFan ); assert( *pNext == iFan ); pFirst = Gia_FanoutObj( p->pFanData, Gia_ObjId(p, pObj) ); assert( *pFirst > 0 ); if ( *pFirst == iFan ) { if ( *pNextC == iFan ) { *pFirst = 0; *pPrev = 0; *pNext = 0; *pPrevC = 0; *pNextC = 0; return; } *pFirst = *pNextC; } *pPrev = *pPrevC; *pNext = *pNextC; *pPrevC = 0; *pNextC = 0; } /**Function************************************************************* Synopsis [Compute the map of all edges.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManStartFanoutMap( Gia_Man_t * p, Vec_Int_t * vFanoutNums ) { Vec_Int_t * vEdgeMap; 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) - Gia_ManBufNum(p) ); Gia_ManForEachObj( p, pObj, i ) { Vec_IntWriteEntry( vEdgeMap, i, iOffset ); iOffset += Vec_IntEntry( vFanoutNums, Gia_ObjId(p, pObj) ); } assert( iOffset <= Vec_IntSize(vEdgeMap) ); return vEdgeMap; } /**Function************************************************************* Synopsis [Allocates static fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManStaticFanoutStart( Gia_Man_t * p ) { Vec_Int_t * vCounts; int * pRefsOld; Gia_Obj_t * pObj, * pFanin; int i, iFanout; assert( p->vFanoutNums == NULL ); assert( p->vFanout == NULL ); // recompute reference counters pRefsOld = p->pRefs; p->pRefs = NULL; Gia_ManCreateRefs(p); p->vFanoutNums = Vec_IntAllocArray( p->pRefs, Gia_ManObjNum(p) ); p->pRefs = pRefsOld; // start the fanout maps p->vFanout = Gia_ManStartFanoutMap( p, p->vFanoutNums ); // incrementally add fanouts vCounts = Vec_IntStart( Gia_ManObjNum(p) ); Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) ) { pFanin = Gia_ObjFanin0(pObj); iFanout = Vec_IntEntry( vCounts, Gia_ObjId(p, pFanin) ); Gia_ObjSetFanout( p, pFanin, iFanout, pObj ); Vec_IntAddToEntry( vCounts, Gia_ObjId(p, pFanin), 1 ); } 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 ); Vec_IntAddToEntry( vCounts, Gia_ObjId(p, pFanin), 1 ); } if ( Gia_ObjIsMux(p, pObj) ) { pFanin = Gia_ObjFanin2(p, pObj); iFanout = Vec_IntEntry( vCounts, Gia_ObjId(p, pFanin) ); Gia_ObjSetFanout( p, pFanin, iFanout, pObj ); Vec_IntAddToEntry( vCounts, Gia_ObjId(p, pFanin), 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 [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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManStaticFanoutStop( Gia_Man_t * p ) { Vec_IntFreeP( &p->vFanoutNums ); Vec_IntFreeP( &p->vFanout ); } /**Function************************************************************* Synopsis [Tests static fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManStaticFanoutTest( Gia_Man_t * p ) { Gia_Obj_t * pObj, * pFanout; int i, k; Gia_ManStaticFanoutStart( p ); Gia_ManForEachObj( p, pObj, i ) { Gia_ObjPrint( p, pObj ); printf( " Fanouts : " ); Gia_ObjForEachFanoutStatic( p, pObj, pFanout, k ) printf( "%5d ", Gia_ObjId(p, pFanout) ); printf( "\n" ); } Gia_ManStaticFanoutStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaForce.c000066400000000000000000001073351477524141600161630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [gia.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 /* The code is based on the paper by F. A. Aloul, I. L. Markov, and K. A. Sakallah. "FORCE: A Fast and Easy-To-Implement Variable-Ordering Heuristic", Proc. GLSVLSI�03. http://www.eecs.umich.edu/~imarkov/pubs/conf/glsvlsi03-force.pdf */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Frc_Obj_t_ Frc_Obj_t; struct Frc_Obj_t_ { unsigned fCi : 1; // terminal node CI unsigned fCo : 1; // terminal node CO unsigned fMark0 : 1; // first user-controlled mark unsigned fMark1 : 1; // second user-controlled mark unsigned nFanins : 28; // the number of fanins unsigned nFanouts; // the number of fanouts unsigned iFanout; // the current number of fanouts int hHandle; // the handle of the node int pPlace; // the placement of each node union { float fEdgeCenter; // center-of-gravity of the edge unsigned iFanin; }; int Fanios[0]; // the array of fanins/fanouts }; typedef struct Frc_Man_t_ Frc_Man_t; struct Frc_Man_t_ { Gia_Man_t * pGia; // the original AIG manager Vec_Int_t * vCis; // the vector of CIs (PIs + LOs) Vec_Int_t * vCos; // the vector of COs (POs + LIs) int nObjs; // the number of objects int nRegs; // the number of registers int * pObjData; // the array containing data for objects int nObjData; // the size of array to store the logic network int fVerbose; // verbose output flag int nCutCur; // current cut int nCutMax; // max cut seen }; static inline int Frc_ManRegNum( Frc_Man_t * p ) { return p->nRegs; } static inline int Frc_ManCiNum( Frc_Man_t * p ) { return Vec_IntSize(p->vCis); } static inline int Frc_ManCoNum( Frc_Man_t * p ) { return Vec_IntSize(p->vCos); } static inline int Frc_ManPiNum( Frc_Man_t * p ) { return Vec_IntSize(p->vCis) - p->nRegs; } static inline int Frc_ManPoNum( Frc_Man_t * p ) { return Vec_IntSize(p->vCos) - p->nRegs; } static inline int Frc_ManObjNum( Frc_Man_t * p ) { return p->nObjs; } static inline int Frc_ManNodeNum( Frc_Man_t * p ) { return p->nObjs - Vec_IntSize(p->vCis) - Vec_IntSize(p->vCos); } static inline Frc_Obj_t * Frc_ManObj( Frc_Man_t * p, int hHandle ) { return (Frc_Obj_t *)(p->pObjData + hHandle); } static inline Frc_Obj_t * Frc_ManCi( Frc_Man_t * p, int i ) { return Frc_ManObj( p, Vec_IntEntry(p->vCis,i) ); } static inline Frc_Obj_t * Frc_ManCo( Frc_Man_t * p, int i ) { return Frc_ManObj( p, Vec_IntEntry(p->vCos,i) ); } static inline int Frc_ObjIsTerm( Frc_Obj_t * pObj ) { return pObj->fCi || pObj->fCo; } static inline int Frc_ObjIsCi( Frc_Obj_t * pObj ) { return pObj->fCi; } static inline int Frc_ObjIsCo( Frc_Obj_t * pObj ) { return pObj->fCo; } static inline int Frc_ObjIsPi( Frc_Obj_t * pObj ) { return pObj->fCi && pObj->nFanins == 0; } static inline int Frc_ObjIsPo( Frc_Obj_t * pObj ) { return pObj->fCo && pObj->nFanouts == 0; } static inline int Frc_ObjIsNode( Frc_Obj_t * pObj ) { return!Frc_ObjIsTerm(pObj) && pObj->nFanins > 0; } static inline int Frc_ObjIsConst0( Frc_Obj_t * pObj ) { return!Frc_ObjIsTerm(pObj) && pObj->nFanins == 0; } static inline int Frc_ObjSize( Frc_Obj_t * pObj ) { return sizeof(Frc_Obj_t) / 4 + pObj->nFanins + pObj->nFanouts; } static inline int Frc_ObjFaninNum( Frc_Obj_t * pObj ) { return pObj->nFanins; } static inline int Frc_ObjFanoutNum( Frc_Obj_t * pObj ) { return pObj->nFanouts; } static inline Frc_Obj_t * Frc_ObjFanin( Frc_Obj_t * pObj, int i ) { return (Frc_Obj_t *)(((int *)pObj) - pObj->Fanios[i]); } static inline Frc_Obj_t * Frc_ObjFanout( Frc_Obj_t * pObj, int i ) { return (Frc_Obj_t *)(((int *)pObj) + pObj->Fanios[pObj->nFanins+i]); } #define Frc_ManForEachObj( p, pObj, i ) \ for ( i = 0; (i < p->nObjData) && (pObj = Frc_ManObj(p,i)); i += Frc_ObjSize(pObj) ) #define Frc_ManForEachObjVec( vVec, p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Frc_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) #define Frc_ManForEachNode( p, pObj, i ) \ for ( i = 0; (i < p->nObjData) && (pObj = Frc_ManObj(p,i)); i += Frc_ObjSize(pObj) ) if ( Frc_ObjIsTerm(pObj) ) {} else #define Frc_ManForEachCi( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(p->vCis)) && (pObj = Frc_ManObj(p,Vec_IntEntry(p->vCis,i))); i++ ) #define Frc_ManForEachCo( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(p->vCos)) && (pObj = Frc_ManObj(p,Vec_IntEntry(p->vCos,i))); i++ ) #define Frc_ObjForEachFanin( pObj, pNext, i ) \ for ( i = 0; (i < (int)pObj->nFanins) && (pNext = Frc_ObjFanin(pObj,i)); i++ ) #define Frc_ObjForEachFaninReverse( pObj, pNext, i ) \ for ( i = (int)pObj->nFanins - 1; (i >= 0) && (pNext = Frc_ObjFanin(pObj,i)); i-- ) #define Frc_ObjForEachFanout( pObj, pNext, i ) \ for ( i = 0; (i < (int)pObj->nFanouts) && (pNext = Frc_ObjFanout(pObj,i)); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates fanin/fanout pair.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Frc_ObjAddFanin( Frc_Obj_t * pObj, Frc_Obj_t * pFanin ) { assert( pObj->iFanin < pObj->nFanins ); assert( pFanin->iFanout < pFanin->nFanouts ); pFanin->Fanios[pFanin->nFanins + pFanin->iFanout++] = pObj->Fanios[pObj->iFanin++] = pObj->hHandle - pFanin->hHandle; } /**Function************************************************************* Synopsis [Creates logic network isomorphic to the given AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Frc_Man_t * Frc_ManStartSimple( Gia_Man_t * pGia ) { Frc_Man_t * p; Frc_Obj_t * pObjLog, * pFanLog; Gia_Obj_t * pObj;//, * pObjRi, * pObjRo; int i, nNodes, hHandle = 0; // prepare the AIG Gia_ManCreateRefs( pGia ); // create logic network p = ABC_CALLOC( Frc_Man_t, 1 ); p->pGia = pGia; p->nRegs = Gia_ManRegNum(pGia); p->vCis = Vec_IntAlloc( Gia_ManCiNum(pGia) ); p->vCos = Vec_IntAlloc( Gia_ManCoNum(pGia) ); p->nObjData = (sizeof(Frc_Obj_t) / 4) * Gia_ManObjNum(pGia) + 2 * (2 * Gia_ManAndNum(pGia) + Gia_ManCoNum(pGia)); p->pObjData = ABC_CALLOC( int, p->nObjData ); // create constant node Gia_ManConst0(pGia)->Value = hHandle; pObjLog = Frc_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = 0; pObjLog->nFanouts = Gia_ObjRefNum( pGia, Gia_ManConst0(pGia) ); // count objects hHandle += Frc_ObjSize( pObjLog ); nNodes = 1; p->nObjs++; // create the PIs Gia_ManForEachCi( pGia, pObj, i ) { // create PI object pObj->Value = hHandle; Vec_IntPush( p->vCis, hHandle ); pObjLog = Frc_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = 0; pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); pObjLog->fCi = 0; // count objects hHandle += Frc_ObjSize( pObjLog ); p->nObjs++; } // create internal nodes Gia_ManForEachAnd( pGia, pObj, i ) { assert( Gia_ObjRefNum( pGia, pObj ) > 0 ); // create node object pObj->Value = hHandle; pObjLog = Frc_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = 2; pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); // add fanins pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); Frc_ObjAddFanin( pObjLog, pFanLog ); pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin1(pObj)) ); Frc_ObjAddFanin( pObjLog, pFanLog ); // count objects hHandle += Frc_ObjSize( pObjLog ); nNodes++; p->nObjs++; } // create the POs Gia_ManForEachCo( pGia, pObj, i ) { // create PO object pObj->Value = hHandle; Vec_IntPush( p->vCos, hHandle ); pObjLog = Frc_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = 1; pObjLog->nFanouts = 0; pObjLog->fCo = 1; // add fanins pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); Frc_ObjAddFanin( pObjLog, pFanLog ); // count objects hHandle += Frc_ObjSize( pObjLog ); p->nObjs++; } // connect registers // Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, i ) // Frc_ObjAddFanin( Frc_ManObj(p,Gia_ObjValue(pObjRo)), Frc_ManObj(p,Gia_ObjValue(pObjRi)) ); assert( nNodes == Frc_ManNodeNum(p) ); assert( hHandle == p->nObjData ); if ( hHandle != p->nObjData ) printf( "Frc_ManStartSimple(): Fatal error in internal representation.\n" ); // make sure the fanin/fanout counters are correct Gia_ManForEachObj( pGia, pObj, i ) { if ( !~Gia_ObjValue(pObj) ) continue; pObjLog = Frc_ManObj( p, Gia_ObjValue(pObj) ); assert( pObjLog->nFanins == pObjLog->iFanin ); assert( pObjLog->nFanouts == pObjLog->iFanout ); pObjLog->iFanin = pObjLog->iFanout = 0; } ABC_FREE( pGia->pRefs ); return p; } /**Function************************************************************* Synopsis [Collect the fanin IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Frc_ManCollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, Vec_Int_t * vVisit ) { if ( pObj->fMark1 ) return; pObj->fMark1 = 1; Vec_IntPush( vVisit, Gia_ObjId(p, pObj) ); if ( pObj->fMark0 ) { Vec_IntPush( vSuper, Gia_ObjId(p, pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); Frc_ManCollectSuper_rec( p, Gia_ObjFanin0(pObj), vSuper, vVisit ); Frc_ManCollectSuper_rec( p, Gia_ObjFanin1(pObj), vSuper, vVisit ); } /**Function************************************************************* Synopsis [Collect the fanin IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Frc_ManCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, Vec_Int_t * vVisit ) { int Entry, i; Vec_IntClear( vSuper ); Vec_IntClear( vVisit ); assert( pObj->fMark0 == 1 ); pObj->fMark0 = 0; Frc_ManCollectSuper_rec( p, pObj, vSuper, vVisit ); pObj->fMark0 = 1; Vec_IntForEachEntry( vVisit, Entry, i ) Gia_ManObj(p, Entry)->fMark1 = 0; } /**Function************************************************************* Synopsis [Assigns references while removing the MUX/XOR ones.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Frc_ManCreateRefsSpecial( Gia_Man_t * p ) { Gia_Obj_t * pObj, * pFan0, * pFan1; Gia_Obj_t * pObjC, * pObjD0, * pObjD1; int i; assert( p->pRefs == NULL ); Gia_ManCleanMark0( p ); Gia_ManCreateRefs( p ); Gia_ManForEachAnd( p, pObj, i ) { assert( pObj->fMark0 == 0 ); pFan0 = Gia_ObjFanin0(pObj); pFan1 = Gia_ObjFanin1(pObj); // skip nodes whose fanins are PIs or are already marked if ( Gia_ObjIsCi(pFan0) || pFan0->fMark0 || Gia_ObjIsCi(pFan1) || pFan1->fMark0 ) continue; // skip nodes that are not MUX type if ( !Gia_ObjIsMuxType(pObj) ) continue; // the node is MUX type, mark it and its fanins pObj->fMark0 = 1; pFan0->fMark0 = 1; pFan1->fMark0 = 1; // deref the control pObjC = Gia_ObjRecognizeMux( pObj, &pObjD1, &pObjD0 ); Gia_ObjRefDec( p, Gia_Regular(pObjC) ); if ( Gia_Regular(pObjD0) == Gia_Regular(pObjD1) ) Gia_ObjRefDec( p, Gia_Regular(pObjD0) ); } Gia_ManForEachAnd( p, pObj, i ) assert( Gia_ObjRefNum(p, pObj) > 0 ); Gia_ManCleanMark0( p ); } /**Function************************************************************* Synopsis [Assigns references while removing the MUX/XOR ones.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Frc_ManTransformRefs( Gia_Man_t * p, int * pnObjs, int * pnFanios ) { Vec_Int_t * vSuper, * vVisit; Gia_Obj_t * pObj, * pFanin; int i, k, Counter; assert( p->pRefs != NULL ); // mark nodes to be used in the logic network Gia_ManCleanMark0( p ); Gia_ManConst0(p)->fMark0 = 1; // mark the inputs Gia_ManForEachCi( p, pObj, i ) pObj->fMark0 = 1; // mark those nodes that have ref count more than 1 Gia_ManForEachAnd( p, pObj, i ) pObj->fMark0 = (Gia_ObjRefNum(p, pObj) > 1); // mark the output drivers Gia_ManForEachCoDriver( p, pObj, i ) pObj->fMark0 = 1; // count the number of nodes Counter = 0; Gia_ManForEachObj( p, pObj, i ) Counter += pObj->fMark0; *pnObjs = Counter + Gia_ManCoNum(p); // reset the references ABC_FREE( p->pRefs ); p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); // reference from internal nodes Counter = 0; vSuper = Vec_IntAlloc( 100 ); vVisit = Vec_IntAlloc( 100 ); Gia_ManCleanMark1( p ); Gia_ManForEachAnd( p, pObj, i ) { if ( pObj->fMark0 == 0 ) continue; Frc_ManCollectSuper( p, pObj, vSuper, vVisit ); Gia_ManForEachObjVec( vSuper, p, pFanin, k ) { assert( pFanin->fMark0 ); Gia_ObjRefInc( p, pFanin ); } Counter += Vec_IntSize( vSuper ); } Gia_ManCheckMark1( p ); Vec_IntFree( vSuper ); Vec_IntFree( vVisit ); // reference from outputs Gia_ManForEachCoDriver( p, pObj, i ) { assert( pObj->fMark0 ); Gia_ObjRefInc( p, pObj ); } *pnFanios = Counter + Gia_ManCoNum(p); } /**Function************************************************************* Synopsis [Creates logic network isomorphic to the given AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Frc_Man_t * Frc_ManStart( Gia_Man_t * pGia ) { Frc_Man_t * p; Frc_Obj_t * pObjLog, * pFanLog; Gia_Obj_t * pObj, * pFanin;//, * pObjRi, * pObjRo; Vec_Int_t * vSuper, * vVisit; int nObjs, nFanios, nNodes = 0; int i, k, hHandle = 0; // prepare the AIG // Gia_ManCreateRefs( pGia ); Frc_ManCreateRefsSpecial( pGia ); Frc_ManTransformRefs( pGia, &nObjs, &nFanios ); Gia_ManFillValue( pGia ); // create logic network p = ABC_CALLOC( Frc_Man_t, 1 ); p->pGia = pGia; p->nRegs = Gia_ManRegNum(pGia); p->vCis = Vec_IntAlloc( Gia_ManCiNum(pGia) ); p->vCos = Vec_IntAlloc( Gia_ManCoNum(pGia) ); p->nObjData = (sizeof(Frc_Obj_t) / 4) * nObjs + 2 * nFanios; p->pObjData = ABC_CALLOC( int, p->nObjData ); // create constant node Gia_ManConst0(pGia)->Value = hHandle; pObjLog = Frc_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = 0; pObjLog->nFanouts = Gia_ObjRefNum( pGia, Gia_ManConst0(pGia) ); // count objects hHandle += Frc_ObjSize( pObjLog ); nNodes++; p->nObjs++; // create the PIs Gia_ManForEachCi( pGia, pObj, i ) { // create PI object pObj->Value = hHandle; Vec_IntPush( p->vCis, hHandle ); pObjLog = Frc_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = 0; pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); pObjLog->fCi = 1; // count objects hHandle += Frc_ObjSize( pObjLog ); p->nObjs++; } // create internal nodes vSuper = Vec_IntAlloc( 100 ); vVisit = Vec_IntAlloc( 100 ); Gia_ManForEachAnd( pGia, pObj, i ) { if ( pObj->fMark0 == 0 ) { assert( Gia_ObjRefNum( pGia, pObj ) == 0 ); continue; } assert( Gia_ObjRefNum( pGia, pObj ) > 0 ); Frc_ManCollectSuper( pGia, pObj, vSuper, vVisit ); // create node object pObj->Value = hHandle; pObjLog = Frc_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = Vec_IntSize( vSuper ); pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); // add fanins Gia_ManForEachObjVec( vSuper, pGia, pFanin, k ) { pFanLog = Frc_ManObj( p, Gia_ObjValue(pFanin) ); Frc_ObjAddFanin( pObjLog, pFanLog ); } // count objects hHandle += Frc_ObjSize( pObjLog ); nNodes++; p->nObjs++; } Vec_IntFree( vSuper ); Vec_IntFree( vVisit ); // create the POs Gia_ManForEachCo( pGia, pObj, i ) { // create PO object pObj->Value = hHandle; Vec_IntPush( p->vCos, hHandle ); pObjLog = Frc_ManObj( p, hHandle ); pObjLog->hHandle = hHandle; pObjLog->nFanins = 1; pObjLog->nFanouts = 0; pObjLog->fCo = 1; // add fanins pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); Frc_ObjAddFanin( pObjLog, pFanLog ); // count objects hHandle += Frc_ObjSize( pObjLog ); p->nObjs++; } // connect registers // Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, i ) // Frc_ObjAddFanin( Frc_ManObj(p,Gia_ObjValue(pObjRo)), Frc_ManObj(p,Gia_ObjValue(pObjRi)) ); Gia_ManCleanMark0( pGia ); assert( nNodes == Frc_ManNodeNum(p) ); assert( nObjs == p->nObjs ); assert( hHandle == p->nObjData ); if ( hHandle != p->nObjData ) printf( "Frc_ManStart(): Fatal error in internal representation.\n" ); // make sure the fanin/fanout counters are correct Gia_ManForEachObj( pGia, pObj, i ) { if ( !~Gia_ObjValue(pObj) ) continue; pObjLog = Frc_ManObj( p, Gia_ObjValue(pObj) ); assert( pObjLog->nFanins == pObjLog->iFanin ); assert( pObjLog->nFanouts == pObjLog->iFanout ); pObjLog->iFanin = pObjLog->iFanout = 0; } ABC_FREE( pGia->pRefs ); return p; } /**Function************************************************************* Synopsis [Creates logic network isomorphic to the given AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Frc_ManPrintStats( Frc_Man_t * p ) { // if ( p->pName ) // printf( "%8s : ", p->pName ); printf( "i/o =%7d/%7d ", Frc_ManPiNum(p), Frc_ManPoNum(p) ); if ( Frc_ManRegNum(p) ) printf( "ff =%7d ", Frc_ManRegNum(p) ); printf( "node =%8d ", Frc_ManNodeNum(p) ); printf( "obj =%8d ", Frc_ManObjNum(p) ); // printf( "lev =%5d ", Frc_ManLevelNum(p) ); // printf( "cut =%5d ", Frc_ManCrossCut(p) ); printf( "mem =%5.2f MB", 4.0*p->nObjData/(1<<20) ); // printf( "obj =%5d ", Frc_ManObjNum(p) ); printf( "\n" ); } /**Function************************************************************* Synopsis [Creates logic network isomorphic to the given AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Frc_ManStop( Frc_Man_t * p ) { Vec_IntFree( p->vCis ); Vec_IntFree( p->vCos ); ABC_FREE( p->pObjData ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Computes cross cut size for the given order of POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Frc_ManCrossCut_rec( Frc_Man_t * p, Frc_Obj_t * pObj ) { assert( pObj->iFanout > 0 ); if ( pObj->iFanout-- == pObj->nFanouts ) { Frc_Obj_t * pFanin; int i; p->nCutCur++; p->nCutMax = Abc_MaxInt( p->nCutMax, p->nCutCur ); if ( !Frc_ObjIsCi(pObj) ) Frc_ObjForEachFanin( pObj, pFanin, i ) p->nCutCur -= Frc_ManCrossCut_rec( p, pFanin ); } return pObj->iFanout == 0; } /**Function************************************************************* Synopsis [Computes cross cut size for the given order of POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Frc_ManCrossCut2_rec( Frc_Man_t * p, Frc_Obj_t * pObj ) { assert( pObj->iFanout > 0 ); if ( pObj->iFanout-- == pObj->nFanouts ) { Frc_Obj_t * pFanin; int i; p->nCutCur++; p->nCutMax = Abc_MaxInt( p->nCutMax, p->nCutCur ); if ( !Frc_ObjIsCi(pObj) ) Frc_ObjForEachFaninReverse( pObj, pFanin, i ) p->nCutCur -= Frc_ManCrossCut2_rec( p, pFanin ); } return pObj->iFanout == 0; } /**Function************************************************************* Synopsis [Computes cross cut size for the given order of POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Frc_ManCrossCut( Frc_Man_t * p, Vec_Int_t * vOrder, int fReverse ) { Frc_Obj_t * pObj; int i; assert( Vec_IntSize(vOrder) == Frc_ManCoNum(p) ); p->nCutCur = 0; p->nCutMax = 0; Frc_ManForEachObj( p, pObj, i ) pObj->iFanout = pObj->nFanouts; Frc_ManForEachObjVec( vOrder, p, pObj, i ) { assert( Frc_ObjIsCo(pObj) ); if ( fReverse ) p->nCutCur -= Frc_ManCrossCut2_rec( p, Frc_ObjFanin(pObj,0) ); else p->nCutCur -= Frc_ManCrossCut_rec( p, Frc_ObjFanin(pObj,0) ); } assert( p->nCutCur == 0 ); // Frc_ManForEachObj( p, pObj, i ) // assert( pObj->iFanout == 0 ); return p->nCutMax; } /**Function************************************************************* Synopsis [Collects CO handles.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Frc_ManCollectCos( Frc_Man_t * p ) { Vec_Int_t * vCoOrder; Frc_Obj_t * pObj; int i; vCoOrder = Vec_IntAlloc( Frc_ManCoNum(p) ); Frc_ManForEachCo( p, pObj, i ) Vec_IntPush( vCoOrder, pObj->hHandle ); return vCoOrder; } /**Function************************************************************* Synopsis [Computes cross cut size for the given order of POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Frc_ManCrossCutTest( Frc_Man_t * p, Vec_Int_t * vOrderInit ) { Vec_Int_t * vOrder; // abctime clk = Abc_Clock(); vOrder = vOrderInit? vOrderInit : Frc_ManCollectCos( p ); printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 0 ) ); printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 1 ) ); Vec_IntReverseOrder( vOrder ); printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 0 ) ); printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 1 ) ); Vec_IntReverseOrder( vOrder ); if ( vOrder != vOrderInit ) Vec_IntFree( vOrder ); // ABC_PRT( "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Generates random placement.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Frc_ManPlaceRandom( Frc_Man_t * p ) { Frc_Obj_t * pThis; int * pPlacement; int i, h, Temp, iNext, Counter; pPlacement = ABC_ALLOC( int, p->nObjs ); for ( i = 0; i < p->nObjs; i++ ) pPlacement[i] = i; for ( i = 0; i < p->nObjs; i++ ) { iNext = Gia_ManRandom( 0 ) % p->nObjs; Temp = pPlacement[i]; pPlacement[i] = pPlacement[iNext]; pPlacement[iNext] = Temp; } Counter = 0; Frc_ManForEachObj( p, pThis, h ) pThis->pPlace = pPlacement[Counter++]; ABC_FREE( pPlacement ); } /**Function************************************************************* Synopsis [Shuffles array of random integers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Frc_ManArrayShuffle( Vec_Int_t * vArray ) { int i, iNext, Temp; for ( i = 0; i < vArray->nSize; i++ ) { iNext = Gia_ManRandom( 0 ) % vArray->nSize; Temp = vArray->pArray[i]; vArray->pArray[i] = vArray->pArray[iNext]; vArray->pArray[iNext] = Temp; } } /**Function************************************************************* Synopsis [Computes cross cut size for the given order of POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Frc_ManPlaceDfs_rec( Frc_Man_t * p, Frc_Obj_t * pObj, int * piPlace ) { assert( pObj->iFanout > 0 ); if ( pObj->iFanout-- == pObj->nFanouts ) { Frc_Obj_t * pFanin; int i; if ( !Frc_ObjIsCi(pObj) ) Frc_ObjForEachFanin( pObj, pFanin, i ) Frc_ManPlaceDfs_rec( p, pFanin, piPlace ); pObj->pPlace = (*piPlace)++; } } /**Function************************************************************* Synopsis [Generates DFS placement.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Frc_ManPlaceDfs( Frc_Man_t * p, Vec_Int_t * vCoOrder ) { Frc_Obj_t * pObj; int i, nPlaces = 0; Frc_ManForEachObj( p, pObj, i ) { pObj->iFanout = pObj->nFanouts; if ( pObj->nFanouts == 0 && !Frc_ObjIsCo(pObj) ) pObj->pPlace = nPlaces++; } Frc_ManForEachObjVec( vCoOrder, p, pObj, i ) { assert( Frc_ObjIsCo(pObj) ); Frc_ManPlaceDfs_rec( p, Frc_ObjFanin(pObj,0), &nPlaces ); pObj->pPlace = nPlaces++; } assert( nPlaces == p->nObjs ); } /**Function************************************************************* Synopsis [Generates DFS placement by trying both orders.] Description [Returns the cross cut size of the best order. ] SideEffects [] SeeAlso [] ***********************************************************************/ int Frc_ManPlaceDfsBoth( Frc_Man_t * p, Vec_Int_t * vCoOrder, int * piCutSize2 ) { int nCutStart1, nCutStart2; nCutStart1 = Frc_ManCrossCut( p, vCoOrder, 0 ); Vec_IntReverseOrder( vCoOrder ); nCutStart2 = Frc_ManCrossCut( p, vCoOrder, 0 ); if ( nCutStart1 <= nCutStart2 ) { Vec_IntReverseOrder( vCoOrder ); // undo Frc_ManPlaceDfs( p, vCoOrder ); *piCutSize2 = nCutStart2; return nCutStart1; } else { Frc_ManPlaceDfs( p, vCoOrder ); Vec_IntReverseOrder( vCoOrder ); // undo *piCutSize2 = nCutStart1; return nCutStart2; } } /**Function************************************************************* Synopsis [Performs iterative refinement of the given placement.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Frc_ManPlacementRefine( Frc_Man_t * p, int nIters, int fVerbose ) { int fRandomize = 0; Vec_Int_t * vCoOrder; Frc_Obj_t * pThis, * pNext; double CostThis, CostPrev; float * pVertX, VertX; int * pPermX, * pHandles; int k, h, Iter, iMinX, iMaxX, Counter, nCutStart, nCutCur, nCutCur2, nCutPrev; abctime clk = Abc_Clock(), clk2, clk2Total = 0; // create starting one-dimensional placement vCoOrder = Frc_ManCollectCos( p ); if ( fRandomize ) Frc_ManArrayShuffle( vCoOrder ); nCutStart = Frc_ManPlaceDfsBoth( p, vCoOrder, &nCutCur2 ); // refine placement CostPrev = 0.0; nCutPrev = nCutStart; pHandles = ABC_ALLOC( int, p->nObjs ); pVertX = ABC_ALLOC( float, p->nObjs ); for ( Iter = 0; Iter < nIters; Iter++ ) { // compute centers of hyperedges CostThis = 0.0; Frc_ManForEachObj( p, pThis, h ) { iMinX = iMaxX = pThis->pPlace; Frc_ObjForEachFanout( pThis, pNext, k ) { iMinX = Abc_MinInt( iMinX, pNext->pPlace ); iMaxX = Abc_MaxInt( iMaxX, pNext->pPlace ); } pThis->fEdgeCenter = 0.5 * (iMaxX + iMinX); CostThis += (iMaxX - iMinX); } // compute new centers of objects Counter = 0; Frc_ManForEachObj( p, pThis, h ) { VertX = pThis->fEdgeCenter; Frc_ObjForEachFanin( pThis, pNext, k ) VertX += pNext->fEdgeCenter; pVertX[Counter] = VertX / (Frc_ObjFaninNum(pThis) + 1); pHandles[Counter++] = h; } assert( Counter == Frc_ManObjNum(p) ); // sort these numbers clk2 = Abc_Clock(); pPermX = Gia_SortFloats( pVertX, pHandles, p->nObjs ); clk2Total += Abc_Clock() - clk2; assert( pPermX == pHandles ); Vec_IntClear( vCoOrder ); for ( k = 0; k < p->nObjs; k++ ) { pThis = Frc_ManObj( p, pPermX[k] ); pThis->pPlace = k; if ( Frc_ObjIsCo(pThis) ) Vec_IntPush( vCoOrder, pThis->hHandle ); } /* printf( "Ordering of PIs:\n" ); Frc_ManForEachCi( p, pThis, k ) printf( "PI number = %7d. Object handle = %7d, Coordinate = %7d.\n", k, pThis->hHandle, pThis->pPlace ); */ nCutCur = Frc_ManPlaceDfsBoth( p, vCoOrder, &nCutCur2 ); // evaluate cost if ( fVerbose ) { printf( "%2d : Span = %e ", Iter+1, CostThis ); printf( "Cut = %6d (%5.2f %%) CutR = %6d ", nCutCur, 100.0*(nCutStart-nCutCur)/nCutStart, nCutCur2 ); ABC_PRTn( "Total", Abc_Clock() - clk ); ABC_PRT( "Sort", clk2Total ); // Frc_ManCrossCutTest( p, vCoOrder ); } // if ( 1.0 * nCutPrev / nCutCur < 1.001 ) // break; nCutPrev = nCutCur; } ABC_FREE( pHandles ); ABC_FREE( pVertX ); Vec_IntFree( vCoOrder ); } /**Function************************************************************* Synopsis [Returns 1 if all fanouts are COsw.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Frc_ObjFanoutsAreCos( Frc_Obj_t * pThis ) { Frc_Obj_t * pNext; int i; Frc_ObjForEachFanout( pThis, pNext, i ) if ( !Frc_ObjIsCo(pNext) ) return 0; return 1; } /**Function************************************************************* Synopsis [Computes the distances from the given set of objects.] Description [Returns one of the most distant objects.] SideEffects [] SeeAlso [] ***********************************************************************/ void Frc_DumpGraphIntoFile( Frc_Man_t * p ) { FILE * pFile; Frc_Obj_t * pThis, * pNext; int i, k, Counter = 0; // assign numbers to CIs and internal nodes Frc_ManForEachObj( p, pThis, i ) { if ( i && ((Frc_ObjIsCi(pThis) && !Frc_ObjFanoutsAreCos(pThis)) || Frc_ObjIsNode(pThis)) ) pThis->iFanin = Counter++; else pThis->iFanin = ~0; } // assign numbers to all other nodes pFile = fopen( "x\\large\\aig\\dg1.g", "w" ); Frc_ManForEachObj( p, pThis, i ) { Frc_ObjForEachFanout( pThis, pNext, k ) { if ( ~pThis->iFanin && ~pNext->iFanin ) fprintf( pFile, "%d %d\n", pThis->iFanin, pNext->iFanin ); } } fclose( pFile ); } /**Function************************************************************* Synopsis [Experiment with the FORCE algorithm.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void For_ManExperiment( Gia_Man_t * pGia, int nIters, int fClustered, int fVerbose ) { Frc_Man_t * p; Gia_ManRandom( 1 ); if ( fClustered ) p = Frc_ManStart( pGia ); else p = Frc_ManStartSimple( pGia ); // Frc_DumpGraphIntoFile( p ); if ( fVerbose ) Frc_ManPrintStats( p ); // Frc_ManCrossCutTest( p, NULL ); Frc_ManPlacementRefine( p, nIters, fVerbose ); Frc_ManStop( p ); } /**Function************************************************************* Synopsis [Experiment with the FORCE algorithm.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void For_ManFileExperiment() { FILE * pFile; int * pBuffer; int i, Size, Exp = 25; abctime clk = Abc_Clock(); int RetValue; Size = (1 << Exp); printf( "2^%d machine words (%d bytes).\n", Exp, (int)sizeof(int) * Size ); pBuffer = ABC_ALLOC( int, Size ); for ( i = 0; i < Size; i++ ) pBuffer[i] = i; ABC_PRT( "Fillup", Abc_Clock() - clk ); clk = Abc_Clock(); pFile = fopen( "test.txt", "rb" ); RetValue = fread( pBuffer, 1, sizeof(int) * Size, pFile ); fclose( pFile ); ABC_PRT( "Read ", Abc_Clock() - clk ); clk = Abc_Clock(); pFile = fopen( "test.txt", "wb" ); fwrite( pBuffer, 1, sizeof(int) * Size, pFile ); fclose( pFile ); ABC_PRT( "Write ", Abc_Clock() - clk ); /* 2^25 machine words (134217728 bytes). Fillup = 0.06 sec Read = 0.08 sec Write = 1.81 sec */ } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaFrames.c000066400000000000000000001006761477524141600163430ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaFrames.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Timeframe unrolling.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaFrames.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Gia_ManFra_t_ Gia_ManFra_t; struct Gia_ManFra_t_ { Gia_ParFra_t * pPars; // parameters Gia_Man_t * pAig; // AIG to unroll Vec_Ptr_t * vIns; // inputs of each timeframe Vec_Ptr_t * vAnds; // nodes of each timeframe Vec_Ptr_t * vOuts; // outputs of each timeframe }; typedef struct Gia_ManUnr_t_ Gia_ManUnr_t; struct Gia_ManUnr_t_ { Gia_ParFra_t * pPars; // parameters Gia_Man_t * pAig; // AIG to unroll (points to pOrder) // internal data Gia_Man_t * pOrder; // AIG reordered (points to pAig) Vec_Int_t * vLimit; // limits of each timeframe // data for each ordered node Vec_Int_t * vRank; // rank of each node Vec_Int_t * vDegree; // degree of each node Vec_Int_t * vDegDiff; // degree of each node Vec_Int_t * vFirst; // first entry in the store Vec_Int_t * vStore; // store for saved data // the resulting AIG Gia_Man_t * pNew; // the resulting AIG int LastLit; // the place to store the last literal }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Duplicates AIG for unrolling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManUnrollDup_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj, int Id ) { if ( ~pObj->Value ) return; if ( Gia_ObjIsCi(pObj) ) pObj->Value = Gia_ManAppendCi(pNew); else if ( Gia_ObjIsCo(pObj) ) { Gia_ManUnrollDup_rec( pNew, Gia_ObjFanin0(pObj), Gia_ObjFaninId0(pObj, Id) ); pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } else if ( Gia_ObjIsAnd(pObj) ) { Gia_ManUnrollDup_rec( pNew, Gia_ObjFanin0(pObj), Gia_ObjFaninId0(pObj, Id) ); Gia_ManUnrollDup_rec( pNew, Gia_ObjFanin1(pObj), Gia_ObjFaninId1(pObj, Id) ); pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } else assert( 0 ); Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value))->Value = Id; } /**Function************************************************************* Synopsis [Duplicates AIG for unrolling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManUnrollDup( Gia_Man_t * p, Vec_Int_t * vLimit ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; assert( Vec_IntSize(vLimit) == 0 ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // save constant class Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Vec_IntPush( vLimit, Gia_ManObjNum(pNew) ); // create first class Gia_ManForEachPo( p, pObj, i ) Gia_ManUnrollDup_rec( pNew, pObj, Gia_ObjId(p, pObj) ); Vec_IntPush( vLimit, Gia_ManObjNum(pNew) ); // create next classes for ( i = 1; i < Gia_ManObjNum(pNew); i++ ) { if ( i == Vec_IntEntryLast(vLimit) ) Vec_IntPush( vLimit, Gia_ManObjNum(pNew) ); pObj = Gia_ManObj( p, Gia_ManObj(pNew, i)->Value ); if ( Gia_ObjIsRo(p, pObj) ) { pObj = Gia_ObjRoToRi(p, pObj); assert( !~pObj->Value ); Gia_ManUnrollDup_rec( pNew, pObj, Gia_ObjId(p, pObj) ); } } Gia_ManSetRegNum( pNew, 0 ); return pNew; } /**Function************************************************************* Synopsis [Duplicates AIG for unrolling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Gia_ManUnrollAbs( Gia_Man_t * p, int nFrames ) { int fVerbose = 0; Vec_Ptr_t * vFrames; Vec_Int_t * vLimit, * vOne; Gia_Man_t * pNew; Gia_Obj_t * pObj; int nObjBits, nObjMask; int f, fMax, k, Entry, Prev, iStart, iStop, Size; // get the bitmasks nObjBits = Abc_Base2Log( Gia_ManObjNum(p) ); nObjMask = (1 << nObjBits) - 1; assert( Gia_ManObjNum(p) <= nObjMask ); // derive the tents vLimit = Vec_IntAlloc( 1000 ); pNew = Gia_ManUnrollDup( p, vLimit ); // debug printout if ( fVerbose ) { Prev = 1; printf( "Tents: " ); Vec_IntForEachEntryStart( vLimit, Entry, k, 1 ) printf( "%d=%d ", k, Entry-Prev ), Prev = Entry; printf( " Unused=%d", Gia_ManObjNum(p) - Gia_ManObjNum(pNew) ); printf( "\n" ); } // create abstraction vFrames = Vec_PtrAlloc( Vec_IntSize(vLimit) ); for ( fMax = 0; fMax < nFrames; fMax++ ) { Size = (fMax+1 < Vec_IntSize(vLimit)) ? Vec_IntEntry(vLimit, fMax+1) : Gia_ManObjNum(pNew); vOne = Vec_IntAlloc( Size ); for ( f = 0; f <= fMax; f++ ) { iStart = (f < Vec_IntSize(vLimit)) ? Vec_IntEntry(vLimit, f ) : 0; iStop = (f+1 < Vec_IntSize(vLimit)) ? Vec_IntEntry(vLimit, f+1) : 0; for ( k = iStop - 1; k >= iStart; k-- ) { assert( Gia_ManObj(pNew, k)->Value > 0 ); pObj = Gia_ManObj(p, Gia_ManObj(pNew, k)->Value); if ( Gia_ObjIsCo(pObj) || Gia_ObjIsPi(p, pObj) ) continue; assert( Gia_ObjIsRo(p, pObj) || Gia_ObjIsAnd(pObj) ); Entry = ((fMax-f) << nObjBits) | Gia_ObjId(p, pObj); Vec_IntPush( vOne, Entry ); // printf( "%d ", Gia_ManObj(pNew, k)->Value ); } // printf( "\n" ); } // add in reverse topological order Vec_IntSort( vOne, 1 ); Vec_PtrPush( vFrames, vOne ); assert( Vec_IntSize(vOne) <= Size - 1 ); } Vec_IntFree( vLimit ); Gia_ManStop( pNew ); return vFrames; } /**Function************************************************************* Synopsis [Creates manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_ManUnr_t * Gia_ManUnrStart( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) { Gia_ManUnr_t * p; Gia_Obj_t * pObj; int i, k, iRank, iFanin, Degree, Shift; abctime clk = Abc_Clock(); p = ABC_CALLOC( Gia_ManUnr_t, 1 ); p->pAig = pAig; p->pPars = pPars; // create order p->vLimit = Vec_IntAlloc( 0 ); p->pOrder = Gia_ManUnrollDup( pAig, p->vLimit ); /* Vec_IntForEachEntryStart( p->vLimit, Shift, i, 1 ) printf( "%d=%d ", i, Shift-Vec_IntEntry(p->vLimit, i-1) ); printf( "\n" ); */ // assign rank p->vRank = Vec_IntAlloc( Gia_ManObjNum(p->pOrder) ); for ( iRank = i = 0; i < Gia_ManObjNum(p->pOrder); Vec_IntPush(p->vRank, iRank), i++ ) if ( Vec_IntEntry(p->vLimit, iRank) == i ) iRank++; assert( iRank == Vec_IntSize(p->vLimit)-1 ); assert( Vec_IntSize(p->vRank) == Gia_ManObjNum(p->pOrder) ); // assign degree p->vDegree = Vec_IntStart( Gia_ManObjNum(p->pOrder) ); p->vDegDiff= Vec_IntStart( 2* Gia_ManObjNum(p->pOrder) ); Gia_ManForEachAnd( p->pOrder, pObj, i ) { for ( k = 0; k < 2; k++ ) { iFanin = k ? Gia_ObjFaninId1(pObj, i) : Gia_ObjFaninId0(pObj, i); Degree = Vec_IntEntry(p->vRank, i) - Vec_IntEntry(p->vRank, iFanin); Vec_IntWriteEntry( p->vDegDiff, 2*i + k, Degree ); if ( Vec_IntEntry(p->vDegree, iFanin) < Degree ) Vec_IntWriteEntry( p->vDegree, iFanin, Degree ); } } Gia_ManForEachCo( p->pOrder, pObj, k ) { i = Gia_ObjId( p->pOrder, pObj ); iFanin = Gia_ObjFaninId0(pObj, i); Degree = Vec_IntEntry(p->vRank, i) - Vec_IntEntry(p->vRank, iFanin); Vec_IntWriteEntry( p->vDegDiff, 2*i, Degree ); if ( Vec_IntEntry(p->vDegree, iFanin) < Degree ) Vec_IntWriteEntry( p->vDegree, iFanin, Degree ); } // assign first p->vFirst = Vec_IntAlloc( Gia_ManObjNum(p->pOrder) ); p->vStore = Vec_IntStartFull( 2* Gia_ManObjNum(p->pOrder) + Vec_IntSum(p->vDegree) ); for ( Shift = i = 0; i < Gia_ManObjNum(p->pOrder); i++ ) { Vec_IntPush( p->vFirst, Shift ); Vec_IntWriteEntry( p->vStore, Shift, 1 + Vec_IntEntry(p->vDegree, i) ); Shift += 2 + Vec_IntEntry(p->vDegree, i); } assert( Shift == Vec_IntSize(p->vStore) ); // cleanup Vec_IntFreeP( &p->vRank ); Vec_IntFreeP( &p->vDegree ); // print verbose output if ( pPars->fVerbose ) { printf( "Convergence = %d. Dangling objects = %d. Average degree = %.3f ", Vec_IntSize(p->vLimit) - 1, Gia_ManObjNum(pAig) - Gia_ManObjNum(p->pOrder), 1.0*Vec_IntSize(p->vStore)/Gia_ManObjNum(p->pOrder) - 1.0 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } return p; } /**Function************************************************************* Synopsis [Deletes manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManUnrollStop( void * pMan ) { Gia_ManUnr_t * p = (Gia_ManUnr_t *)pMan; Gia_ManStopP( &p->pOrder ); Vec_IntFreeP( &p->vLimit ); Vec_IntFreeP( &p->vRank ); Vec_IntFreeP( &p->vDegree ); Vec_IntFreeP( &p->vDegDiff ); Vec_IntFreeP( &p->vFirst ); Vec_IntFreeP( &p->vStore ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Reading/writing entry from storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ObjUnrWrite( Gia_ManUnr_t * p, int Id, int Entry ) { int i, * pArray = Vec_IntEntryP( p->vStore, Vec_IntEntry(p->vFirst, Id) ); for ( i = pArray[0]; i > 1; i-- ) pArray[i] = pArray[i-1]; pArray[1] = Entry; } static inline int Gia_ObjUnrRead( Gia_ManUnr_t * p, int Id, int Degree ) { int * pArray = Vec_IntEntryP( p->vStore, Vec_IntEntry(p->vFirst, Id) ); if ( Id == 0 ) return 0; assert( Degree >= 0 && Degree < pArray[0] ); if ( Degree ) Degree--; return pArray[Degree + 1]; } static inline int Gia_ObjUnrReadCopy0( Gia_ManUnr_t * p, Gia_Obj_t * pObj, int Id ) { int Lit = Gia_ObjUnrRead(p, Gia_ObjFaninId0(pObj, Id), Vec_IntEntry(p->vDegDiff, 2*Id)); return Abc_LitNotCond( Lit, Gia_ObjFaninC0(pObj) ); } static inline int Gia_ObjUnrReadCopy1( Gia_ManUnr_t * p, Gia_Obj_t * pObj, int Id ) { int Lit = Gia_ObjUnrRead(p, Gia_ObjFaninId1(pObj, Id), Vec_IntEntry(p->vDegDiff, 2*Id+1)); return Abc_LitNotCond( Lit, Gia_ObjFaninC1(pObj) ); } static inline int Gia_ObjUnrReadCi( Gia_ManUnr_t * p, int Id, int f, Gia_Man_t * pNew ) { Gia_Obj_t * pObj = Gia_ManObj( p->pOrder, Id ); Gia_Obj_t * pObjReal = Gia_ManObj( p->pAig, pObj->Value ); assert( Gia_ObjIsCi(pObjReal) ); if ( Gia_ObjIsPi(p->pAig, pObjReal) ) { if ( !p->pPars->fSaveLastLit ) pObj = Gia_ManPi( pNew, Gia_ManPiNum(p->pAig) * f + Gia_ObjCioId(pObjReal) ); else pObj = Gia_ManPi( pNew, Gia_ManRegNum(p->pAig) + Gia_ManPiNum(p->pAig) * f + Gia_ObjCioId(pObjReal) ); return Abc_Var2Lit( Gia_ObjId(pNew, pObj), 0 ); } if ( f == 0 ) // initialize! { if ( p->pPars->fInit ) return 0; assert( Gia_ObjCioId(pObjReal) >= Gia_ManPiNum(p->pAig) ); if ( !p->pPars->fSaveLastLit ) pObj = Gia_ManPi( pNew, Gia_ManPiNum(p->pAig) * p->pPars->nFrames + Gia_ObjCioId(pObjReal)-Gia_ManPiNum(p->pAig) ); else pObj = Gia_ManPi( pNew, Gia_ObjCioId(pObjReal)-Gia_ManPiNum(p->pAig) ); return Abc_Var2Lit( Gia_ObjId(pNew, pObj), 0 ); } pObj = Gia_ManObj( p->pOrder, Abc_Lit2Var(Gia_ObjRoToRi(p->pAig, pObjReal)->Value) ); assert( Gia_ObjIsCo(pObj) ); return Gia_ObjUnrRead( p, Gia_ObjId(p->pOrder, pObj), 0 ); } /**Function************************************************************* Synopsis [Computes init/non-init unrolling without flops.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Gia_ManUnrollStart( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) { Gia_ManUnr_t * p; int f, i; // start p = Gia_ManUnrStart( pAig, pPars ); // start timeframes assert( p->pNew == NULL ); p->pNew = Gia_ManStart( 10000 ); p->pNew->pName = Abc_UtilStrsav( p->pAig->pName ); p->pNew->pSpec = Abc_UtilStrsav( p->pAig->pSpec ); Gia_ManHashAlloc( p->pNew ); // create combinational inputs if ( !p->pPars->fSaveLastLit ) // only in the case when unrolling depth is known for ( f = 0; f < p->pPars->nFrames; f++ ) for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ ) Gia_ManAppendCi(p->pNew); // create flop outputs if ( !p->pPars->fInit ) // only in the case when initialization is not performed for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) Gia_ManAppendCi(p->pNew); return p; } /**Function************************************************************* Synopsis [Computes init/non-init unrolling without flops.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Gia_ManUnrollAdd( void * pMan, int fMax ) { Gia_ManUnr_t * p = (Gia_ManUnr_t *)pMan; Gia_Obj_t * pObj; int f, i, Lit = 0, Beg, End; // create PIs on demand if ( p->pPars->fSaveLastLit ) for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ ) Gia_ManAppendCi(p->pNew); // unroll another timeframe for ( f = 0; f < fMax; f++ ) { if ( Vec_IntSize(p->vLimit) <= fMax-f ) continue; Beg = Vec_IntEntry( p->vLimit, fMax-f-1 ); End = Vec_IntEntry( p->vLimit, fMax-f ); for ( i = Beg; i < End; i++ ) { pObj = Gia_ManObj( p->pOrder, i ); if ( Gia_ObjIsAnd(pObj) ) Lit = Gia_ManHashAnd( p->pNew, Gia_ObjUnrReadCopy0(p, pObj, i), Gia_ObjUnrReadCopy1(p, pObj, i) ); else if ( Gia_ObjIsCo(pObj) ) { Lit = Gia_ObjUnrReadCopy0(p, pObj, i); if ( f == fMax-1 ) { if ( p->pPars->fSaveLastLit ) p->LastLit = Lit; else Gia_ManAppendCo( p->pNew, Lit ); } } else if ( Gia_ObjIsCi(pObj) ) Lit = Gia_ObjUnrReadCi( p, i, f, p->pNew ); else assert( 0 ); assert( Lit >= 0 ); Gia_ObjUnrWrite( p, i, Lit ); // should be exactly one call for each obj! } } return p->pNew; } /**Function************************************************************* Synopsis [Read the last literal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManUnrollLastLit( void * pMan ) { Gia_ManUnr_t * p = (Gia_ManUnr_t *)pMan; return p->LastLit; } /**Function************************************************************* Synopsis [Computes init/non-init unrolling without flops.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManUnroll( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) { Gia_ManUnr_t * p; Gia_Man_t * pNew, * pTemp; int fMax; p = (Gia_ManUnr_t *)Gia_ManUnrollStart( pAig, pPars ); for ( fMax = 1; fMax <= p->pPars->nFrames; fMax++ ) Gia_ManUnrollAdd( p, fMax ); assert( Gia_ManPoNum(p->pNew) == p->pPars->nFrames * Gia_ManPoNum(p->pAig) ); Gia_ManHashStop( p->pNew ); Gia_ManSetRegNum( p->pNew, 0 ); // Gia_ManPrintStats( pNew, 0 ); // cleanup p->pNew = Gia_ManCleanup( pTemp = p->pNew ); Gia_ManStop( pTemp ); // Gia_ManPrintStats( pNew, 0 ); pNew = p->pNew; p->pNew = NULL; Gia_ManUnrollStop( p ); return pNew; } /**Function************************************************************* Synopsis [Computes init/non-init unrolling without flops.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* Gia_Man_t * Gia_ManUnroll( Gia_ManUnr_t * p ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int fMax, f, i, Lit, Beg, End; // start timeframes pNew = Gia_ManStart( 10000 ); pNew->pName = Abc_UtilStrsav( p->pAig->pName ); pNew->pSpec = Abc_UtilStrsav( p->pAig->pSpec ); Gia_ManHashAlloc( pNew ); // create combinational inputs for ( f = 0; f < p->pPars->nFrames; f++ ) for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ ) Gia_ManAppendCi(pNew); if ( !p->pPars->fInit ) for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) Gia_ManAppendCi(pNew); // add nodes to each time-frame // Gia_ObjUnrWrite( p, 0, 0 ); for ( fMax = 1; fMax <= p->pPars->nFrames; fMax++ ) for ( f = 0; f < fMax; f++ ) { if ( Vec_IntSize(p->vLimit) <= fMax-f ) continue; Beg = Vec_IntEntry( p->vLimit, fMax-f-1 ); End = Vec_IntEntry( p->vLimit, fMax-f ); for ( i = Beg; i < End; i++ ) { pObj = Gia_ManObj( p->pOrder, i ); if ( Gia_ObjIsAnd(pObj) ) Lit = Gia_ManHashAnd( pNew, Gia_ObjUnrReadCopy0(p, pObj, i), Gia_ObjUnrReadCopy1(p, pObj, i) ); else if ( Gia_ObjIsCo(pObj) ) { Lit = Gia_ObjUnrReadCopy0(p, pObj, i); if ( f == fMax-1 ) Gia_ManAppendCo( pNew, Lit ); } else if ( Gia_ObjIsCi(pObj) ) Lit = Gia_ObjUnrReadCi( p, i, f, pNew ); else assert( 0 ); assert( Lit >= 0 ); Gia_ObjUnrWrite( p, i, Lit ); // should be exactly one call for each obj! } } assert( Gia_ManPoNum(pNew) == p->pPars->nFrames * Gia_ManPoNum(p->pAig) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, 0 ); // Gia_ManPrintStats( pNew, 0 ); // cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); // Gia_ManPrintStats( pNew, 0 ); return pNew; } */ /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFrames2( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) { Gia_Man_t * pNew; abctime clk = Abc_Clock(); pNew = Gia_ManUnroll( pAig, pPars ); if ( pPars->fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return pNew; } /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFraSetDefaultParams( Gia_ParFra_t * p ) { memset( p, 0, sizeof(Gia_ParFra_t) ); p->nFrames = 32; // the number of frames to unroll p->fInit = 0; // initialize the timeframes p->fVerbose = 0; // enables verbose output } /**Function************************************************************* Synopsis [Creates manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_ManFra_t * Gia_ManFraStart( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) { Gia_ManFra_t * p; p = ABC_ALLOC( Gia_ManFra_t, 1 ); memset( p, 0, sizeof(Gia_ManFra_t) ); p->pAig = pAig; p->pPars = pPars; return p; } /**Function************************************************************* Synopsis [Deletes manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFraStop( Gia_ManFra_t * p ) { Vec_VecFree( (Vec_Vec_t *)p->vIns ); Vec_VecFree( (Vec_Vec_t *)p->vAnds ); Vec_VecFree( (Vec_Vec_t *)p->vOuts ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Computes supports of all timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFraSupports( Gia_ManFra_t * p ) { Vec_Int_t * vIns = NULL, * vAnds, * vOuts; Gia_Obj_t * pObj; int f, i; p->vIns = Vec_PtrStart( p->pPars->nFrames ); p->vAnds = Vec_PtrStart( p->pPars->nFrames ); p->vOuts = Vec_PtrStart( p->pPars->nFrames ); Gia_ManIncrementTravId( p->pAig ); for ( f = p->pPars->nFrames - 1; f >= 0; f-- ) { vOuts = Gia_ManCollectPoIds( p->pAig ); if ( vIns ) Gia_ManForEachObjVec( vIns, p->pAig, pObj, i ) if ( Gia_ObjIsRo(p->pAig, pObj) ) Vec_IntPush( vOuts, Gia_ObjId( p->pAig, Gia_ObjRoToRi(p->pAig, pObj) ) ); vIns = Vec_IntAlloc( 100 ); Gia_ManCollectCis( p->pAig, Vec_IntArray(vOuts), Vec_IntSize(vOuts), vIns ); vAnds = Vec_IntAlloc( 100 ); Gia_ManCollectAnds( p->pAig, Vec_IntArray(vOuts), Vec_IntSize(vOuts), vAnds, NULL ); Vec_PtrWriteEntry( p->vIns, f, vIns ); Vec_PtrWriteEntry( p->vAnds, f, vAnds ); Vec_PtrWriteEntry( p->vOuts, f, vOuts ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFramesInit( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) { int fUseAllPis = 1; Gia_Man_t * pFrames, * pTemp; Gia_ManFra_t * p; Gia_Obj_t * pObj; Vec_Int_t * vIns, * vAnds, * vOuts; int i, f; p = Gia_ManFraStart( pAig, pPars ); Gia_ManFraSupports( p ); pFrames = Gia_ManStart( Vec_VecSizeSize((Vec_Vec_t*)p->vIns)+ Vec_VecSizeSize((Vec_Vec_t*)p->vAnds)+Vec_VecSizeSize((Vec_Vec_t*)p->vOuts) ); pFrames->pName = Abc_UtilStrsav( pAig->pName ); pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); Gia_ManHashAlloc( pFrames ); Gia_ManConst0(pAig)->Value = 0; for ( f = 0; f < pPars->nFrames; f++ ) { vIns = (Vec_Int_t *)Vec_PtrEntry( p->vIns, f ); vAnds = (Vec_Int_t *)Vec_PtrEntry( p->vAnds, f ); vOuts = (Vec_Int_t *)Vec_PtrEntry( p->vOuts, f ); if ( pPars->fVerbose ) printf( "Frame %3d : CI = %6d. AND = %6d. CO = %6d.\n", f, Vec_IntSize(vIns), Vec_IntSize(vAnds), Vec_IntSize(vOuts) ); if ( fUseAllPis ) { Gia_ManForEachPi( pAig, pObj, i ) pObj->Value = Gia_ManAppendCi( pFrames ); if ( f == 0 ) { Gia_ManForEachObjVec( vIns, pAig, pObj, i ) { assert( Gia_ObjIsCi(pObj) ); if ( !Gia_ObjIsPi(pAig, pObj) ) pObj->Value = 0; } } else { Gia_ManForEachObjVec( vIns, pAig, pObj, i ) { assert( Gia_ObjIsCi(pObj) ); if ( !Gia_ObjIsPi(pAig, pObj) ) pObj->Value = Gia_ObjRoToRi(pAig, pObj)->Value; } } } else { if ( f == 0 ) { Gia_ManForEachObjVec( vIns, pAig, pObj, i ) { assert( Gia_ObjIsCi(pObj) ); if ( Gia_ObjIsPi(pAig, pObj) ) pObj->Value = Gia_ManAppendCi( pFrames ); else pObj->Value = 0; } } else { Gia_ManForEachObjVec( vIns, pAig, pObj, i ) { assert( Gia_ObjIsCi(pObj) ); if ( Gia_ObjIsPi(pAig, pObj) ) pObj->Value = Gia_ManAppendCi( pFrames ); else pObj->Value = Gia_ObjRoToRi(pAig, pObj)->Value; } } } Gia_ManForEachObjVec( vAnds, pAig, pObj, i ) { assert( Gia_ObjIsAnd(pObj) ); pObj->Value = Gia_ManHashAnd( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } Gia_ManForEachObjVec( vOuts, pAig, pObj, i ) { assert( Gia_ObjIsCo(pObj) ); if ( Gia_ObjIsPo(pAig, pObj) ) pObj->Value = Gia_ManAppendCo( pFrames, Gia_ObjFanin0Copy(pObj) ); else pObj->Value = Gia_ObjFanin0Copy(pObj); } } Gia_ManFraStop( p ); Gia_ManHashStop( pFrames ); if ( Gia_ManCombMarkUsed(pFrames) < Gia_ManAndNum(pFrames) ) { pFrames = Gia_ManDupMarked( pTemp = pFrames ); if ( pPars->fVerbose ) printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", Gia_ManAndNum(pTemp), Gia_ManAndNum(pFrames) ); Gia_ManStop( pTemp ); } else if ( pPars->fVerbose ) printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", Gia_ManAndNum(pFrames), Gia_ManAndNum(pFrames) ); return pFrames; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFrames( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) { Gia_Man_t * pFrames, * pTemp; Gia_Obj_t * pObj; Vec_Int_t * vPoLits = NULL; int i, f; assert( Gia_ManRegNum(pAig) > 0 ); assert( pPars->nFrames > 0 ); if ( pPars->fInit ) return Gia_ManFramesInit( pAig, pPars ); if ( pPars->fOrPos ) vPoLits = Vec_IntStart( Gia_ManPoNum(pAig) ); pFrames = Gia_ManStart( pPars->nFrames * Gia_ManObjNum(pAig) ); pFrames->pName = Abc_UtilStrsav( pAig->pName ); pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); if ( !pPars->fDisableSt ) Gia_ManHashAlloc( pFrames ); Gia_ManConst0(pAig)->Value = 0; // create primary inputs for ( f = 0; f < pPars->nFrames; f++ ) Gia_ManForEachPi( pAig, pObj, i ) pObj->Value = Gia_ManAppendCi( pFrames ); // add internal nodes for each timeframe for ( f = 0; f < pPars->nFrames; f++ ) { if ( f == 0 ) { Gia_ManForEachRo( pAig, pObj, i ) pObj->Value = Gia_ManAppendCi( pFrames ); } else { Gia_ManForEachRo( pAig, pObj, i ) pObj->Value = Gia_ObjRoToRi( pAig, pObj )->Value; } Gia_ManForEachPi( pAig, pObj, i ) pObj->Value = Gia_Obj2Lit( pFrames, Gia_ManPi(pFrames, f * Gia_ManPiNum(pAig) + i) ); if ( !pPars->fDisableSt ) Gia_ManForEachAnd( pAig, pObj, i ) pObj->Value = Gia_ManHashAnd( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else Gia_ManForEachAnd( pAig, pObj, i ) pObj->Value = Gia_ManAppendAnd2( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( vPoLits ) { if ( !pPars->fDisableSt ) Gia_ManForEachPo( pAig, pObj, i ) Vec_IntWriteEntry( vPoLits, i, Gia_ManHashOr(pFrames, Vec_IntEntry(vPoLits, i), Gia_ObjFanin0Copy(pObj)) ); else Gia_ManForEachPo( pAig, pObj, i ) Vec_IntWriteEntry( vPoLits, i, Abc_LitNot(Gia_ManAppendAnd2(pFrames, Abc_LitNot(Vec_IntEntry(vPoLits, i)), Abc_LitNot(Gia_ObjFanin0Copy(pObj)))) ); } else { Gia_ManForEachPo( pAig, pObj, i ) pObj->Value = Gia_ManAppendCo( pFrames, Gia_ObjFanin0Copy(pObj) ); } if ( f == pPars->nFrames - 1 ) { if ( vPoLits ) Gia_ManForEachPo( pAig, pObj, i ) pObj->Value = Gia_ManAppendCo( pFrames, Vec_IntEntry(vPoLits, i) ); Gia_ManForEachRi( pAig, pObj, i ) pObj->Value = Gia_ManAppendCo( pFrames, Gia_ObjFanin0Copy(pObj) ); } else { Gia_ManForEachRi( pAig, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); } } Vec_IntFreeP( &vPoLits ); if ( !pPars->fDisableSt ) Gia_ManHashStop( pFrames ); Gia_ManSetRegNum( pFrames, Gia_ManRegNum(pAig) ); if ( Gia_ManCombMarkUsed(pFrames) < Gia_ManAndNum(pFrames) ) { pFrames = Gia_ManDupMarked( pTemp = pFrames ); if ( pPars->fVerbose ) printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", Gia_ManAndNum(pTemp), Gia_ManAndNum(pFrames) ); Gia_ManStop( pTemp ); } else if ( pPars->fVerbose ) printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", Gia_ManAndNum(pFrames), Gia_ManAndNum(pFrames) ); return pFrames; } /**Function************************************************************* Synopsis [Perform init unrolling as long as PO(s) are constant 0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFramesInitSpecial( Gia_Man_t * pAig, int nFrames, int fVerbose ) { Gia_Man_t * pFrames, * pTemp; Gia_Obj_t * pObj; int i, f; assert( Gia_ManRegNum(pAig) > 0 ); if ( nFrames > 0 ) printf( "Computing specialized unrolling with %d frames...\n", nFrames ); pFrames = Gia_ManStart( Gia_ManObjNum(pAig) ); pFrames->pName = Abc_UtilStrsav( pAig->pName ); pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); Gia_ManHashAlloc( pFrames ); Gia_ManConst0(pAig)->Value = 0; for ( f = 0; nFrames == 0 || f < nFrames; f++ ) { if ( fVerbose && (f % 100 == 0) ) { printf( "%6d : ", f ); Gia_ManPrintStats( pFrames, NULL ); } Gia_ManForEachRo( pAig, pObj, i ) pObj->Value = f ? Gia_ObjRoToRi( pAig, pObj )->Value : 0; Gia_ManForEachPi( pAig, pObj, i ) pObj->Value = Gia_ManAppendCi( pFrames ); Gia_ManForEachAnd( pAig, pObj, i ) pObj->Value = Gia_ManHashAnd( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachPo( pAig, pObj, i ) if ( Gia_ObjFanin0Copy(pObj) != 0 ) break; if ( i < Gia_ManPoNum(pAig) ) break; Gia_ManForEachRi( pAig, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); } if ( fVerbose ) printf( "Computed prefix of %d frames.\n", f ); Gia_ManForEachRi( pAig, pObj, i ) Gia_ManAppendCo( pFrames, pObj->Value ); Gia_ManHashStop( pFrames ); pFrames = Gia_ManCleanup( pTemp = pFrames ); if ( fVerbose ) printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", Gia_ManAndNum(pTemp), Gia_ManAndNum(pFrames) ); Gia_ManStop( pTemp ); return pFrames; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaFront.c000066400000000000000000000220371477524141600162100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaFront.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Frontier representation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaFront.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Find the next place on the frontier.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManFrontFindNext( char * pFront, int nFront, int iFront ) { assert( iFront < nFront ); for ( ; pFront[iFront]; iFront = (iFront + 1) % nFront ); assert( pFront[iFront] == 0 ); pFront[iFront] = 1; return iFront; } /**Function************************************************************* Synopsis [Transforms the frontier manager to its initial state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFrontTransform( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, * pFrontToId; // mapping of nodes into frontier variables assert( p->nFront > 0 ); pFrontToId = ABC_FALLOC( int, p->nFront ); Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjIsCo(pObj) ) { assert( pObj->Value == GIA_NONE ); pObj->iDiff0 = i - pFrontToId[Gia_ObjDiff0(pObj)]; } else if ( Gia_ObjIsAnd(pObj) ) { assert( (int)pObj->Value < p->nFront ); pObj->iDiff0 = i - pFrontToId[Gia_ObjDiff0(pObj)]; pObj->iDiff1 = i - pFrontToId[Gia_ObjDiff1(pObj)]; pFrontToId[pObj->Value] = i; } else { assert( (int)pObj->Value < p->nFront ); pFrontToId[pObj->Value] = i; } pObj->Value = 0; } ABC_FREE( pFrontToId ); } /**Function************************************************************* Synopsis [Determine the frontier.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCrossCutSimple( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, nCutCur = 0, nCutMax = 0; Gia_ManCreateValueRefs( p ); Gia_ManForEachObj( p, pObj, i ) { if ( pObj->Value ) nCutCur++; if ( nCutMax < nCutCur ) nCutMax = nCutCur; if ( Gia_ObjIsAnd(pObj) ) { if ( --Gia_ObjFanin0(pObj)->Value == 0 ) nCutCur--; if ( --Gia_ObjFanin1(pObj)->Value == 0 ) nCutCur--; } else if ( Gia_ObjIsCo(pObj) ) { if ( --Gia_ObjFanin0(pObj)->Value == 0 ) nCutCur--; } } // Gia_ManForEachObj( p, pObj, i ) // assert( pObj->Value == 0 ); return nCutMax; } /**Function************************************************************* Synopsis [Determine the frontier.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFront( Gia_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj, * pFanin0New, * pFanin1New, * pObjNew; char * pFront; // places used for the frontier int i, iLit, nCrossCut = 0, nCrossCutMax = 0; int nCrossCutMaxInit = Gia_ManCrossCutSimple( p ); int iFront = 0;//, clk = Abc_Clock(); // set references for all objects Gia_ManCreateValueRefs( p ); // start the new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nFront = 1 + (int)((float)1.1 * nCrossCutMaxInit); // start the frontier pFront = ABC_CALLOC( char, pNew->nFront ); // add constant node Gia_ManConst0(pNew)->Value = iFront = Gia_ManFrontFindNext( pFront, pNew->nFront, iFront ); if ( Gia_ObjValue(Gia_ManConst0(p)) == 0 ) pFront[iFront] = 0; else nCrossCut = 1; // iterate through the objects Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsCi(pObj) ) { if ( Gia_ObjValue(pObj) && nCrossCutMax < ++nCrossCut ) nCrossCutMax = nCrossCut; // create new node iLit = Gia_ManAppendCi( pNew ); pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(iLit) ); assert( Gia_ObjId(pNew, pObjNew) == Gia_ObjId(p, pObj) ); pObjNew->Value = iFront = Gia_ManFrontFindNext( pFront, pNew->nFront, iFront ); // handle CIs without fanout if ( Gia_ObjValue(pObj) == 0 ) pFront[iFront] = 0; continue; } if ( Gia_ObjIsCo(pObj) ) { assert( Gia_ObjValue(pObj) == 0 ); // create new node iLit = Gia_ManAppendCo( pNew, 0 ); pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(iLit) ); assert( Gia_ObjId(pNew, pObjNew) == Gia_ObjId(p, pObj) ); // get the fanin pFanin0New = Gia_ManObj( pNew, Gia_ObjFaninId0(pObj, i) ); assert( pFanin0New->Value != GIA_NONE ); pObjNew->Value = GIA_NONE; pObjNew->iDiff0 = pFanin0New->Value; pObjNew->fCompl0 = Gia_ObjFaninC0(pObj); // deref the fanin if ( --Gia_ObjFanin0(pObj)->Value == 0 ) { pFront[pFanin0New->Value] = 0; nCrossCut--; } continue; } if ( Gia_ObjValue(pObj) && nCrossCutMax < ++nCrossCut ) nCrossCutMax = nCrossCut; // create new node pObjNew = Gia_ManAppendObj( pNew ); assert( Gia_ObjId(pNew, pObjNew) == Gia_ObjId(p, pObj) ); // assign the first fanin pFanin0New = Gia_ManObj( pNew, Gia_ObjFaninId0(pObj, i) ); assert( pFanin0New->Value != GIA_NONE ); pObjNew->iDiff0 = pFanin0New->Value; pObjNew->fCompl0 = Gia_ObjFaninC0(pObj); // assign the second fanin pFanin1New = Gia_ManObj( pNew, Gia_ObjFaninId1(pObj, i) ); assert( pFanin1New->Value != GIA_NONE ); pObjNew->iDiff1 = pFanin1New->Value; pObjNew->fCompl1 = Gia_ObjFaninC1(pObj); // assign the frontier number pObjNew->Value = iFront = Gia_ManFrontFindNext( pFront, pNew->nFront, iFront ); // deref the fanins if ( --Gia_ObjFanin0(pObj)->Value == 0 ) { pFront[pFanin0New->Value] = 0; nCrossCut--; } if ( --Gia_ObjFanin1(pObj)->Value == 0 ) { pFront[pFanin1New->Value] = 0; nCrossCut--; } // handle nodes without fanout (choice nodes) if ( Gia_ObjValue(pObj) == 0 ) pFront[iFront] = 0; } assert( pNew->nObjs == p->nObjs ); assert( nCrossCut == 0 || nCrossCutMax == nCrossCutMaxInit ); for ( i = 0; i < pNew->nFront; i++ ) assert( pFront[i] == 0 ); ABC_FREE( pFront ); //printf( "Crosscut = %6d. Frontier = %6d. ", nCrossCutMaxInit, pNew->nFront ); //ABC_PRT( "Time", Abc_Clock() - clk ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFrontTest( Gia_Man_t * p ) { Gia_Man_t * pNew; pNew = Gia_ManFront( p ); Gia_ManFrontTransform( pNew ); // Gia_ManCleanValue( p ); // Gia_ManCleanValue( pNew ); if ( memcmp( pNew->pObjs, p->pObjs, sizeof(Gia_Obj_t) * p->nObjs ) ) { /* Gia_Obj_t * pObj, * pObjNew; int i; Gia_ManForEachObj( p, pObj, i ) { pObjNew = Gia_ManObj( pNew, i ); printf( "%5d %5d %5d %5d\n", pObj->iDiff0, pObjNew->iDiff0, pObj->iDiff1, pObjNew->iDiff1 ); } */ printf( "Verification failed.\n" ); } else printf( "Verification successful.\n" ); Gia_ManStop( pNew ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaFx.c000066400000000000000000000437371477524141600155070ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaFx.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Interface to fast_extract package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaFx.c,v 1.00 2013/09/29 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "bool/kit/kit.h" #include "misc/vec/vecWec.h" #include "bool/dec/dec.h" #include "opt/dau/dau.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Create GIA for SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManGraphToAig( Gia_Man_t * p, Dec_Graph_t * pGraph ) { Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" int i, iAnd0, iAnd1; // check for constant function if ( Dec_GraphIsConst(pGraph) ) return Abc_LitNotCond( 1, Dec_GraphIsComplement(pGraph) ); // check for a literal if ( Dec_GraphIsVar(pGraph) ) return Abc_LitNotCond( Dec_GraphVar(pGraph)->iFunc, Dec_GraphIsComplement(pGraph) ); // build the AIG nodes corresponding to the AND gates of the graph Dec_GraphForEachNode( pGraph, pNode, i ) { iAnd0 = Abc_LitNotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->iFunc, pNode->eEdge0.fCompl ); iAnd1 = Abc_LitNotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->iFunc, pNode->eEdge1.fCompl ); pNode->iFunc = Gia_ManHashAnd( p, iAnd0, iAnd1 ); } // complement the result if necessary return Abc_LitNotCond( pNode->iFunc, Dec_GraphIsComplement(pGraph) ); } int Gia_ManSopToAig( Gia_Man_t * p, char * pSop, Vec_Int_t * vLeaves ) { int i, iAnd, iSum, Value, nFanins; char * pCube; // get the number of variables nFanins = Kit_PlaGetVarNum(pSop); // go through the cubes of the node's SOP iSum = 0; Kit_PlaForEachCube( pSop, nFanins, pCube ) { // create the AND of literals iAnd = 1; Kit_PlaCubeForEachVar( pCube, Value, i ) { assert( Vec_IntEntry(vLeaves, i) >= 0 ); if ( Value == '1' ) iAnd = Gia_ManHashAnd( p, iAnd, Vec_IntEntry(vLeaves, i) ); else if ( Value == '0' ) iAnd = Gia_ManHashAnd( p, iAnd, Abc_LitNot(Vec_IntEntry(vLeaves, i)) ); else assert( Value == '-' ); } // add to the sum of cubes iSum = Gia_ManHashOr( p, iSum, iAnd ); } // decide whether to complement the result if ( Kit_PlaIsComplement(pSop) ) iSum = Abc_LitNot(iSum); return iSum; } int Gia_ManFactorGraph( Gia_Man_t * p, Dec_Graph_t * pFForm, Vec_Int_t * vLeaves ) { Dec_Node_t * pFFNode; int i, Lit; // assign fanins Dec_GraphForEachLeaf( pFForm, pFFNode, i ) { assert( Vec_IntEntry(vLeaves, i) >= 0 ); pFFNode->iFunc = Vec_IntEntry(vLeaves, i); } // perform strashing Lit = Gia_ManGraphToAig( p, pFForm ); return Lit; } int Gia_ManFactorNode( Gia_Man_t * p, char * pSop, Vec_Int_t * vLeaves ) { if ( Kit_PlaGetVarNum(pSop) == 0 ) return Abc_LitNotCond( 1, Kit_PlaIsConst0(pSop) ); assert( Kit_PlaGetVarNum(pSop) == Vec_IntSize(vLeaves) ); if ( Kit_PlaGetVarNum(pSop) > 2 && Kit_PlaGetCubeNum(pSop) > 1 ) { Dec_Graph_t * pFForm = Dec_Factor( pSop ); int Lit = Gia_ManFactorGraph( p, pFForm, vLeaves ); Dec_GraphFree( pFForm ); return Lit; } return Gia_ManSopToAig( p, pSop, vLeaves ); } /**Function************************************************************* Synopsis [Computing truth tables for the mapped network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wrd_t * Gia_ManComputeTruths( Gia_Man_t * p, int nCutSize, int nLutNum, int fReverse ) { Vec_Wrd_t * vTruths; Vec_Int_t vLeaves; word * pTruth; int i, k, nWords; nWords = Abc_Truth6WordNum( nCutSize ); vTruths = Vec_WrdAlloc( nWords * nLutNum ); Gia_ObjComputeTruthTableStart( p, nCutSize ); Gia_ManForEachLut( p, i ) { // collect and sort fanins vLeaves.nCap = vLeaves.nSize = Gia_ObjLutSize( p, i ); vLeaves.pArray = Gia_ObjLutFanins( p, i ); if( !Vec_IntCheckUniqueSmall(&vLeaves) ) { Vec_IntUniqify(&vLeaves); Vec_IntWriteEntry(p->vMapping, Vec_IntEntry(p->vMapping, i), vLeaves.nSize); for ( k = 0; k < vLeaves.nSize; k++ ) Vec_IntWriteEntry(p->vMapping, Vec_IntEntry(p->vMapping, i) + 1 + k, vLeaves.pArray[k]); } assert( Vec_IntCheckUniqueSmall(&vLeaves) ); Vec_IntSelectSort( Vec_IntArray(&vLeaves), Vec_IntSize(&vLeaves) ); if ( !fReverse ) Vec_IntReverseOrder( &vLeaves ); // compute truth table pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, i), &vLeaves ); for ( k = 0; k < nWords; k++ ) Vec_WrdPush( vTruths, pTruth[k] ); // Kit_DsdPrintFromTruth( (unsigned *)pTruth, 6 ); printf( "\n" ); } Gia_ObjComputeTruthTableStop( p ); assert( Vec_WrdCap(vTruths) == 16 || Vec_WrdSize(vTruths) == Vec_WrdCap(vTruths) ); return vTruths; } /**Function************************************************************* Synopsis [Extracts information about the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManAssignNumbers( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, Counter = 0; Gia_ManFillValue( p ); Gia_ManForEachCi( p, pObj, i ) pObj->Value = Counter++; Gia_ManForEachLut( p, i ) Gia_ManObj(p, i)->Value = Counter++; return Counter; } Vec_Wec_t * Gia_ManFxRetrieve( Gia_Man_t * p, Vec_Str_t ** pvCompl, int fReverse ) { Vec_Wec_t * vCubes; Vec_Wrd_t * vTruths; Vec_Int_t * vCube, * vCover; int nItems, nCutSize, nWords; int i, c, v, Lit, Cube, Counter = 0; // abctime clk = Abc_Clock(); nItems = Gia_ManAssignNumbers( p ); // compute truth tables nCutSize = Gia_ManLutSizeMax( p ); nWords = Abc_Truth6WordNum( nCutSize ); vTruths = Gia_ManComputeTruths( p, nCutSize, nItems - Gia_ManCiNum(p), fReverse ); vCover = Vec_IntAlloc( 1 << 16 ); // collect cubes vCubes = Vec_WecAlloc( 1000 ); *pvCompl = Vec_StrStart( nItems ); Gia_ManForEachLut( p, i ) { Gia_Obj_t * pObj = Gia_ManObj( p, i ); int nVars = Gia_ObjLutSize( p, i ); int * pVars = Gia_ObjLutFanins( p, i ); word * pTruth = Vec_WrdEntryP( vTruths, Counter++ * nWords ); Abc_TtFlipVar5( pTruth, nVars ); int Status = Kit_TruthIsop( (unsigned *)pTruth, nVars, vCover, 1 ); Abc_TtFlipVar5( pTruth, nVars ); if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) ) { Vec_StrWriteEntry( *pvCompl, pObj->Value, (char)(Vec_IntSize(vCover) == 0) ); vCube = Vec_WecPushLevel( vCubes ); Vec_IntPush( vCube, pObj->Value ); continue; } Vec_StrWriteEntry( *pvCompl, pObj->Value, (char)Status ); Vec_IntForEachEntry( vCover, Cube, c ) { vCube = Vec_WecPushLevel( vCubes ); Vec_IntPush( vCube, pObj->Value ); for ( v = 0; v < nVars; v++ ) { Lit = 3 & (Cube >> (v << 1)); if ( Lit == 1 ) Vec_IntPush( vCube, Abc_Var2Lit(Gia_ManObj(p, pVars[v])->Value, 1) ); else if ( Lit == 2 ) Vec_IntPush( vCube, Abc_Var2Lit(Gia_ManObj(p, pVars[v])->Value, 0) ); else if ( Lit != 0 ) assert( 0 ); } Vec_IntSelectSort( Vec_IntArray(vCube) + 1, Vec_IntSize(vCube) - 1 ); } } assert( Counter * nWords == Vec_WrdSize(vTruths) ); Vec_WrdFree( vTruths ); Vec_IntFree( vCover ); // Abc_PrintTime( 1, "Setup time", Abc_Clock() - clk ); return vCubes; } /**Function************************************************************* Synopsis [Generates GIA after factoring the resulting SOPs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFxTopoOrder_rec( Vec_Wec_t * vCubes, Vec_Int_t * vFirst, Vec_Int_t * vCount, Vec_Int_t * vVisit, Vec_Int_t * vOrder, int iObj ) { int c, v, Lit; int iFirst = Vec_IntEntry( vFirst, iObj ); int nCubes = Vec_IntEntry( vCount, iObj ); assert( !Vec_IntEntry( vVisit, iObj ) ); Vec_IntWriteEntry( vVisit, iObj, 1 ); for ( c = 0; c < nCubes; c++ ) { Vec_Int_t * vCube = Vec_WecEntry( vCubes, iFirst + c ); assert( Vec_IntEntry(vCube, 0) == iObj ); Vec_IntForEachEntryStart( vCube, Lit, v, 1 ) if ( !Vec_IntEntry( vVisit, Abc_Lit2Var(Lit) ) ) Gia_ManFxTopoOrder_rec( vCubes, vFirst, vCount, vVisit, vOrder, Abc_Lit2Var(Lit) ); } Vec_IntPush( vOrder, iObj ); } Vec_Int_t * Gia_ManFxTopoOrder( Vec_Wec_t * vCubes, int nInputs, int nStart, Vec_Int_t ** pvFirst, Vec_Int_t ** pvCount ) { Vec_Int_t * vOrder, * vFirst, * vCount, * vVisit, * vCube; int i, iFanin, nNodeMax = -1; // find the largest index Vec_WecForEachLevel( vCubes, vCube, i ) nNodeMax = Abc_MaxInt( nNodeMax, Vec_IntEntry(vCube, 0) ); nNodeMax++; // quit if there is no new nodes if ( nNodeMax == nStart ) { //printf( "The network is unchanged by fast extract.\n" ); return NULL; } // find first cube and how many cubes vFirst = Vec_IntStart( nNodeMax ); vCount = Vec_IntStart( nNodeMax ); Vec_WecForEachLevel( vCubes, vCube, i ) { iFanin = Vec_IntEntry( vCube, 0 ); assert( iFanin >= nInputs ); if ( Vec_IntEntry(vCount, iFanin) == 0 ) Vec_IntWriteEntry( vFirst, iFanin, i ); Vec_IntAddToEntry( vCount, iFanin, 1 ); } // put all of them in a topo order vOrder = Vec_IntStart( nInputs ); vVisit = Vec_IntStart( nNodeMax ); for ( i = 0; i < nInputs; i++ ) Vec_IntWriteEntry( vVisit, i, 1 ); for ( i = nInputs; i < nNodeMax; i++ ) if ( !Vec_IntEntry( vVisit, i ) ) Gia_ManFxTopoOrder_rec( vCubes, vFirst, vCount, vVisit, vOrder, i ); assert( Vec_IntSize(vOrder) == nNodeMax ); Vec_IntFree( vVisit ); // return topological order of new nodes *pvFirst = vFirst; *pvCount = vCount; return vOrder; } Gia_Man_t * Gia_ManFxInsert( Gia_Man_t * p, Vec_Wec_t * vCubes, Vec_Str_t * vCompls ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; Vec_Str_t * vSop; Vec_Int_t * vOrder, * vFirst, * vCount, * vFanins, * vCover; Vec_Int_t * vCopies, * vCube, * vMap; int k, c, v, Lit, Var, iItem; // abctime clk = Abc_Clock(); // prepare the cubes vOrder = Gia_ManFxTopoOrder( vCubes, Gia_ManCiNum(p), Vec_StrSize(vCompls), &vFirst, &vCount ); if ( vOrder == NULL ) return Gia_ManDup( p ); assert( Vec_IntSize(vOrder) > Vec_StrSize(vCompls) ); // create new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->vLevels = Vec_IntStart( 6*Gia_ManObjNum(p)/5 + 100 ); Gia_ManHashStart( pNew ); // create primary inputs vMap = Vec_IntStartFull( Vec_IntSize(vOrder) ); vCopies = Vec_IntAlloc( Vec_IntSize(vOrder) ); Gia_ManForEachCi( p, pObj, k ) Vec_IntPush( vCopies, Gia_ManAppendCi(pNew) ); Vec_IntFillExtra( vCopies, Vec_IntSize(vOrder), -1 ); // add AIG nodes in the topological order vSop = Vec_StrAlloc( 1000 ); vCover = Vec_IntAlloc( 1 << 16 ); vFanins = Vec_IntAlloc( 100 ); Vec_IntForEachEntryStart( vOrder, iItem, k, Gia_ManCiNum(p) ) { int iFirst = Vec_IntEntry( vFirst, iItem ); int nCubes = Vec_IntEntry( vCount, iItem ); // collect fanins Vec_IntClear( vFanins ); for ( c = 0; c < nCubes; c++ ) { vCube = Vec_WecEntry( vCubes, iFirst + c ); Vec_IntForEachEntryStart( vCube, Lit, v, 1 ) if ( Vec_IntEntry(vMap, Abc_Lit2Var(Lit)) == -1 ) { Vec_IntWriteEntry( vMap, Abc_Lit2Var(Lit), Vec_IntSize(vFanins) ); Vec_IntPush( vFanins, Abc_Lit2Var(Lit) ); } } if ( Vec_IntSize(vFanins) > 6 ) { // create SOP Vec_StrClear( vSop ); for ( c = 0; c < nCubes; c++ ) { for ( v = 0; v < Vec_IntSize(vFanins); v++ ) Vec_StrPush( vSop, '-' ); vCube = Vec_WecEntry( vCubes, iFirst + c ); Vec_IntForEachEntryStart( vCube, Lit, v, 1 ) { Lit = Abc_Lit2LitV( Vec_IntArray(vMap), Lit ); assert( Lit >= 0 && Abc_Lit2Var(Lit) < Vec_IntSize(vFanins) ); Vec_StrWriteEntry( vSop, Vec_StrSize(vSop) - Vec_IntSize(vFanins) + Abc_Lit2Var(Lit), (char)(Abc_LitIsCompl(Lit)? '0' : '1') ); } Vec_StrPush( vSop, ' ' ); Vec_StrPush( vSop, '1' ); Vec_StrPush( vSop, '\n' ); } Vec_StrPush( vSop, '\0' ); // collect fanins Vec_IntForEachEntry( vFanins, Var, v ) { Vec_IntWriteEntry( vMap, Var, -1 ); Vec_IntWriteEntry( vFanins, v, Vec_IntEntry(vCopies, Var) ); } // derive new AIG Lit = Gia_ManFactorNode( pNew, Vec_StrArray(vSop), vFanins ); } else { word uTruth = 0, uCube; for ( c = 0; c < nCubes; c++ ) { uCube = ~(word)0; vCube = Vec_WecEntry( vCubes, iFirst + c ); Vec_IntForEachEntryStart( vCube, Lit, v, 1 ) { Lit = Abc_Lit2LitV( Vec_IntArray(vMap), Lit ); assert( Lit >= 0 && Abc_Lit2Var(Lit) < Vec_IntSize(vFanins) ); uCube &= Abc_LitIsCompl(Lit) ? ~s_Truths6[Abc_Lit2Var(Lit)] : s_Truths6[Abc_Lit2Var(Lit)]; } uTruth |= uCube; } // complement constant if ( uTruth == 0 ) uTruth = ~uTruth; // collect fanins Vec_IntForEachEntry( vFanins, Var, v ) { Vec_IntWriteEntry( vMap, Var, -1 ); Vec_IntWriteEntry( vFanins, v, Vec_IntEntry(vCopies, Var) ); } // create truth table Lit = Dsm_ManTruthToGia( pNew, &uTruth, vFanins, vCover ); } // complement if the original SOP was complemented Lit = Abc_LitNotCond( Lit, (iItem < Vec_StrSize(vCompls)) && (Vec_StrEntry(vCompls, iItem) > 0) ); // remeber this literal assert( Vec_IntEntry(vCopies, iItem) == -1 ); Vec_IntWriteEntry( vCopies, iItem, Lit ); } Gia_ManHashStop( pNew ); // create primary outputs Gia_ManForEachCo( p, pObj, k ) { Lit = Gia_ObjFaninId0p(p, pObj) ? Vec_IntEntry(vCopies, Gia_ObjFanin0(pObj)->Value) : 0; Gia_ManAppendCo( pNew, Abc_LitNotCond( Lit, Gia_ObjFaninC0(pObj) ) ); } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // cleanup Vec_IntFree( vOrder ); Vec_IntFree( vFirst ); Vec_IntFree( vCount ); Vec_IntFree( vFanins ); Vec_IntFree( vCopies ); Vec_IntFree( vMap ); Vec_StrFree( vSop ); Vec_IntFree( vCover ); // remove dangling nodes pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); // Abc_PrintTime( 1, "Setdn time", Abc_Clock() - clk ); return pNew; } /**Function************************************************************* Synopsis [Performs classical fast_extract on logic functions.] Description [] SideEffects [Sorts the fanins of each cut in the increasing order.] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManPerformFx( Gia_Man_t * p, int nNewNodesMax, int LitCountMax, int fReverse, int fVerbose, int fVeryVerbose ) { extern int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose ); Gia_Man_t * pNew = NULL; Vec_Wec_t * vCubes; Vec_Str_t * vCompl; if ( Gia_ManAndNum(p) == 0 ) { pNew = Gia_ManDup(p); Gia_ManTransferTiming( pNew, p ); return pNew; } // abctime clk; assert( Gia_ManHasMapping(p) ); // collect information vCubes = Gia_ManFxRetrieve( p, &vCompl, fReverse ); // call the fast extract procedure // clk = Abc_Clock(); Fx_FastExtract( vCubes, Vec_StrSize(vCompl), nNewNodesMax, LitCountMax, 0, fVerbose, fVeryVerbose ); // Abc_PrintTime( 1, "Fx runtime", Abc_Clock() - clk ); // insert information pNew = Gia_ManFxInsert( p, vCubes, vCompl ); Gia_ManTransferTiming( pNew, p ); // cleanup Vec_WecFree( vCubes ); Vec_StrFree( vCompl ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaGen.c000066400000000000000000001413631477524141600156350ustar00rootroot00000000000000/**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 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSumCount( char * p, Vec_Int_t * vDec, int b ) { int i, Ent, Count = 0, Sum = 0; for ( i = 0; p[i]; i++ ) { Ent = (p[i] >= '0' && p[i] <= '9') ? p[i]-'0' : p[i]-'A'+10; Count += Vec_IntEntry(vDec, Ent) + b * (1 << (Sum += Ent)); } return Count + b * ((1 << Sum) - 1); } Vec_Str_t * Gia_ManSumEnum_rec( int Num ) { if ( Num == 1 ) { Vec_Str_t * vRes = Vec_StrAlloc(2); Vec_StrPush( vRes, '1' ); Vec_StrPush( vRes, '\0' ); return vRes; } Vec_Str_t * vRes = Vec_StrAlloc( 16 ); for ( int i = 1; i < Num; i++ ) { Vec_Str_t * vRes0 = Gia_ManSumEnum_rec(i); Vec_Str_t * vRes1 = Gia_ManSumEnum_rec(Num-i); for ( int c0 = 0; c0 < Vec_StrSize(vRes0); c0 += strlen(Vec_StrEntryP(vRes0,c0))+1 ) for ( int c1 = 0; c1 < Vec_StrSize(vRes1); c1 += strlen(Vec_StrEntryP(vRes1,c1))+1 ) Vec_StrPrintF( vRes, "%s%s%c", Vec_StrEntryP(vRes0,c0), Vec_StrEntryP(vRes1,c1), '\0' ); Vec_StrPrintF( vRes, "%c%c", Num < 10 ? '0'+Num : 'A'+Num-10, '\0' ); Vec_StrFree( vRes0 ); Vec_StrFree( vRes1 ); } return vRes; } void Gia_ManSumEnum( int n, Vec_Int_t * vDec ) { Vec_Str_t * vRes = Gia_ManSumEnum_rec( n ); for ( int b = 1; b <= 256; b <<= 1 ) { int iBest = -1, CountCur, CountBest = ABC_INFINITY; for ( int c0 = 0; c0 < Vec_StrSize(vRes); c0 += strlen(Vec_StrEntryP(vRes,c0))+1 ) { CountCur = Gia_ManSumCount( Vec_StrEntryP(vRes,c0), vDec, b ); if ( CountBest > CountCur ) CountBest = CountCur, iBest = c0; } printf( " %8d", CountBest ); //printf( " %8s", Vec_StrEntryP(vRes,iBest) ); //printf( " %.3f", (float)CountBest/(3*b*((1<> b) & 1 ) Vec_IntWriteEntry( vLev, b, 1 ); Vec_WrdForEachEntryStop( vData, Data, i, Vec_WrdSize(vData)-1 ) { for ( n = 0; n < nIBits; n++, nLits += 2 ) { Vec_Int_t * vLev = Vec_WecPushLevel( vArgs ); Vec_IntFill( vLev, nOBits, 0 ); for ( b = 0; b < nOBits; b++ ) if ( ((Data >> b) & 1) && b+n < nOBits ) Vec_IntWriteEntry( vLev, b+n, nLits ); } } return vArgs; } Vec_Wec_t * Gia_ManGenNeuronTransformArgs( Gia_Man_t * pNew, Vec_Wec_t * vArgs, int nLutSize, int nOBits ) { int i, nParts = (Vec_WecSize(vArgs) + nLutSize - 2) / nLutSize; while ( Vec_WecSize(vArgs) < nLutSize*nParts+1 ) Vec_IntFill( Vec_WecPushLevel(vArgs), nOBits, 0 ); assert( Vec_WecSize(vArgs) == nLutSize*nParts+1 ); Vec_Wec_t * vNew = Vec_WecAlloc( nParts ); Vec_Int_t * vRes = Vec_WecPushLevel( vNew ), * vArg; Vec_IntAppend( vRes, Vec_WecEntry(vArgs, 0) ); Vec_WecForEachLevelStart( vArgs, vArg, i, 1 ) { Gia_ManGenNeuronAdder( pNew, nOBits, Vec_IntArray(vArg), Vec_IntArray(vRes), 0, vRes ); if ( (i-1) % nLutSize == nLutSize-1 && i < Vec_WecSize(vArgs)-1 ) { vRes = Vec_WecPushLevel( vNew ); Vec_IntFill( vRes, nOBits, 0 ); } } assert( Vec_WecSize(vNew) == nParts ); return vNew; } Vec_Wec_t * Gia_ManGenNeuronCompactArgs( Gia_Man_t * pNew, Vec_Wec_t * vArgs, int nLutSize, int nOBits ) { int i, nParts = Vec_WecSize(vArgs) / 3; Vec_Wec_t * vNew = Vec_WecAlloc( 2 * nParts + Vec_WecSize(vArgs) % 3 ); for ( i = 0; i < nParts; i++ ) { Vec_Int_t * vIn0 = Vec_WecEntry(vArgs, 3*i+0); Vec_Int_t * vIn1 = Vec_WecEntry(vArgs, 3*i+1); Vec_Int_t * vIn2 = Vec_WecEntry(vArgs, 3*i+2); Vec_Int_t * vOut0 = Vec_WecPushLevel(vNew); Vec_Int_t * vOut1 = Vec_WecPushLevel(vNew); Gia_ManGenCompact( pNew, vIn0, vIn1, vIn2, vOut0, vOut1 ); } for ( i = 3*nParts; i < Vec_WecSize(vArgs); i++ ) Vec_IntAppend( Vec_WecPushLevel(vNew), Vec_WecEntry(vArgs, i) ); assert( Vec_WecSize(vNew) == 2 * nParts + Vec_WecSize(vArgs) % 3 ); return vNew; } Vec_Int_t * Gia_ManGenNeuronFinal( Gia_Man_t * pNew, Vec_Wec_t * vArgs, int nOBits ) { Vec_Int_t * vRes = Vec_IntAlloc( nOBits ), * vArg; int i; Vec_IntAppend( vRes, Vec_WecEntry(vArgs, 0) ); Vec_WecForEachLevelStart( vArgs, vArg, i, 1 ) Gia_ManGenNeuronAdder( pNew, nOBits, Vec_IntArray(vArg), Vec_IntArray(vRes), 0, vRes ); return vRes; } int Gia_ManGenNeuronBitWidth( Vec_Wrd_t * vData, int nIBits ) { int i, InMask = (1<pName = Abc_UtilStrsav( "neuron" ); for ( i = 0; i < nIBits * (Vec_WrdSize(vData)-1); i++ ) Gia_ManAppendCi( pNew ); Gia_ManHashAlloc( pNew ); Vec_Wec_t * vTemp, * vArgs = Gia_ManGenNeuronCreateArgs( vData, nIBits, nOBits ); Vec_WrdFree( vData ); if ( nLutSize ) { vArgs = Gia_ManGenNeuronTransformArgs( pNew, vTemp = vArgs, nLutSize, nOBits ); Vec_WecFree( vTemp ); while ( Vec_WecSize(vArgs) > 2 ) { vArgs = Gia_ManGenNeuronCompactArgs( pNew, vTemp = vArgs, nLutSize, nOBits ); Vec_WecFree( vTemp ); } } Vec_Int_t * vRes = Gia_ManGenNeuronFinal( pNew, vArgs, nOBits ); Vec_IntForEachEntry( vRes, Lit, i ) Gia_ManAppendCo( pNew, Lit ); Vec_IntFree( vRes ); Vec_WecFree( vArgs ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Generates minimum-node AIG for n-bit comparator (a > b).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupGenComp( int nBits, int fInterleave ) { Gia_Man_t * pNew, * pTemp; int i, iLit = 1; Vec_Int_t * vBitsA = Vec_IntAlloc( nBits + 1 ); Vec_Int_t * vBitsB = Vec_IntAlloc( nBits + 1 ); pNew = Gia_ManStart( 6*nBits+10 ); pNew->pName = Abc_UtilStrsav( "comp" ); Gia_ManHashAlloc( pNew ); if ( fInterleave ) { for ( i = 0; i < nBits; i++ ) Vec_IntPush( vBitsA, Gia_ManAppendCi(pNew) ), Vec_IntPush( vBitsB, Gia_ManAppendCi(pNew) ); } else { for ( i = 0; i < nBits; i++ ) Vec_IntPush( vBitsA, Gia_ManAppendCi(pNew) ); for ( i = 0; i < nBits; i++ ) Vec_IntPush( vBitsB, Gia_ManAppendCi(pNew) ); } Vec_IntPush( vBitsA, 0 ); Vec_IntPush( vBitsB, 0 ); for ( i = 0; i < nBits; i++ ) { int iLitA0 = Vec_IntEntry(vBitsA, i); int iLitA1 = Vec_IntEntry(vBitsA, i+1); int iLitB0 = Vec_IntEntry(vBitsB, i); int iLitB1 = Vec_IntEntry(vBitsB, i+1); int iOrLit0; if ( i == 0 ) iOrLit0 = Gia_ManHashOr(pNew, Abc_LitNotCond(iLitA0, !(i&1)), Abc_LitNotCond(iLitB0, i&1)); else iOrLit0 = Gia_ManHashAnd(pNew, Abc_LitNotCond(iLitA0, !(i&1)), Abc_LitNotCond(iLitB0, i&1)); int iOrLit1 = Gia_ManHashAnd(pNew, Abc_LitNotCond(iLitA1, !(i&1)), Abc_LitNotCond(iLitB1, i&1)); int iOrLit = Gia_ManHashOr(pNew, iOrLit0, iOrLit1 ); iLit = Gia_ManHashOr(pNew, Abc_LitNot(iLit), iOrLit ); } Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, nBits&1) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); Vec_IntFree( vBitsA ); Vec_IntFree( vBitsB ); return pNew; } /**Function************************************************************* Synopsis [Generates optimized AIG for the decoder and the multiplexer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_GenDecoder( Gia_Man_t * p, int * pLits, int nLits ) { if ( nLits == 1 ) { Vec_Int_t * vRes = Vec_IntAlloc( 2 ); Vec_IntPush( vRes, Abc_LitNot(pLits[0]) ); Vec_IntPush( vRes, pLits[0] ); return vRes; } assert( nLits > 1 ); int nPart1 = nLits / 2; int nPart2 = nLits - nPart1; Vec_Int_t * vRes1 = Gia_GenDecoder( p, pLits, nPart1 ); Vec_Int_t * vRes2 = Gia_GenDecoder( p, pLits+nPart1, nPart2 ); Vec_Int_t * vRes = Vec_IntAlloc( Vec_IntSize(vRes1) * Vec_IntSize(vRes2) ); int i, k, Lit1, Lit2; Vec_IntForEachEntry( vRes2, Lit2, k ) Vec_IntForEachEntry( vRes1, Lit1, i ) Vec_IntPush( vRes, Gia_ManHashAnd(p, Lit1, Lit2) ); Vec_IntFree( vRes1 ); Vec_IntFree( vRes2 ); return vRes; } Gia_Man_t * Gia_ManGenMux( int nIns, char * pNums ) { Vec_Int_t * vIns = Vec_IntAlloc( nIns ); Vec_Int_t * vData = Vec_IntAlloc( 1 << nIns ); Gia_Man_t * p = Gia_ManStart( 4*(1 << nIns) + nIns ), * pTemp; int i, iStart = 0, nSize = 1 << nIns; p->pName = Abc_UtilStrsav( "mux" ); for ( i = 0; i < nIns; i++ ) Vec_IntPush( vIns, Gia_ManAppendCi(p) ); for ( i = 0; i < nSize; i++ ) Vec_IntPush( vData, Gia_ManAppendCi(p) ); Gia_ManHashAlloc( p ); for ( i = (int)strlen(pNums)-1; i >= 0; i-- ) { int k, b, nBits = (int)(pNums[i] - '0'); Vec_Int_t * vDec = Gia_GenDecoder( p, Vec_IntEntryP(vIns, iStart), nBits ); for ( k = 0; k < nSize; k++ ) Vec_IntWriteEntry( vData, k, Gia_ManHashAnd(p, Vec_IntEntry(vData, k), Vec_IntEntry(vDec, k%Vec_IntSize(vDec))) ); for ( b = 0; b < nBits; b++, nSize /= 2 ) for ( k = 0; k < nSize/2; k++ ) Vec_IntWriteEntry( vData, k, Gia_ManHashOr(p, Vec_IntEntry(vData, 2*k), Vec_IntEntry(vData, 2*k+1)) ); Vec_IntFree( vDec ); iStart += nBits; } assert( nSize == 1 ); Gia_ManAppendCo( p, Vec_IntEntry(vData, 0) ); Vec_IntFree( vIns ); Vec_IntFree( vData ); p = Gia_ManCleanup( pTemp = p ); Gia_ManStop( pTemp ); return p; } /**Function************************************************************* Synopsis [Generates N-bit sorter using pair-wise sorting algorithm.] Description [https://en.wikipedia.org/wiki/Pairwise_sorting_network] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManGenSorterOne( Gia_Man_t * p, int * pLits, int i, int k ) { int Lit1 = Gia_ManAppendAnd( p, pLits[i], pLits[k] ); int Lit2 = Gia_ManAppendOr ( p, pLits[i], pLits[k] ); pLits[i] = Lit1; pLits[k] = Lit2; } static inline void Gia_ManGenSorterConstrMerge( Gia_Man_t * p, int * pLits, int lo, int hi, int r ) { int i, step = r * 2; if ( step < hi - lo ) { Gia_ManGenSorterConstrMerge( p, pLits, lo, hi-r, step ); Gia_ManGenSorterConstrMerge( p, pLits, lo+r, hi, step ); for ( i = lo+r; i < hi-r; i += step ) Gia_ManGenSorterOne( p, pLits, i, i+r ); } } static inline void Gia_ManGenSorterConstrRange( Gia_Man_t * p, int * pLits, int lo, int hi ) { if ( hi - lo >= 1 ) { int i, mid = lo + (hi - lo) / 2; for ( i = lo; i <= mid; i++ ) Gia_ManGenSorterOne( p, pLits, i, i + (hi - lo + 1) / 2 ); Gia_ManGenSorterConstrRange( p, pLits, lo, mid ); Gia_ManGenSorterConstrRange( p, pLits, mid+1, hi ); Gia_ManGenSorterConstrMerge( p, pLits, lo, hi, 1 ); } } Gia_Man_t * Gia_ManGenSorter( int LogN ) { int i, nVars = 1 << LogN; int nVarsAlloc = nVars + 2 * (nVars * LogN * (LogN-1) / 4 + nVars - 1); Vec_Int_t * vLits = Vec_IntAlloc( nVars ); Gia_Man_t * p = Gia_ManStart( 1 + 2*nVars + nVarsAlloc ); p->pName = Abc_UtilStrsav( "sorter" ); for ( i = 0; i < nVars; i++ ) Vec_IntPush( vLits, Gia_ManAppendCi(p) ); Gia_ManGenSorterConstrRange( p, Vec_IntArray(vLits), 0, nVars - 1 ); for ( i = 0; i < nVars; i++ ) Gia_ManAppendCo( p, Vec_IntEntry(vLits, i) ); Vec_IntFree( vLits ); return p; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaGiarf.c000066400000000000000000001035531477524141600161530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [gia.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 /// //////////////////////////////////////////////////////////////////////// // combinational simulation manager typedef struct Hcd_Man_t_ Hcd_Man_t; struct Hcd_Man_t_ { // parameters Gia_Man_t * pGia; // the AIG to be used for simulation int nBTLimit; // internal backtrack limit int fVerbose; // internal verbose flag // internal variables unsigned * pSimInfo; // simulation info for each object Vec_Ptr_t * vSimInfo; // pointers to the CI simulation info Vec_Ptr_t * vSimPres; // pointers to the presense of simulation info // temporaries Vec_Int_t * vClassOld; // old class numbers Vec_Int_t * vClassNew; // new class numbers Vec_Int_t * vClassTemp; // temporary storage Vec_Int_t * vRefinedC; // refined const reprs }; static inline unsigned Hcd_ObjSim( Hcd_Man_t * p, int Id ) { return p->pSimInfo[Id]; } static inline unsigned * Hcd_ObjSimP( Hcd_Man_t * p, int Id ) { return p->pSimInfo + Id; } static inline unsigned Hcd_ObjSetSim( Hcd_Man_t * p, int Id, unsigned n ) { return p->pSimInfo[Id] = n; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the fraiging manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hcd_Man_t * Gia_ManEquivStart( Gia_Man_t * pGia, int nBTLimit, int fVerbose ) { Hcd_Man_t * p; Gia_Obj_t * pObj; int i; p = ABC_CALLOC( Hcd_Man_t, 1 ); p->pGia = pGia; p->nBTLimit = nBTLimit; p->fVerbose = fVerbose; p->pSimInfo = ABC_ALLOC( unsigned, Gia_ManObjNum(pGia) ); p->vClassOld = Vec_IntAlloc( 100 ); p->vClassNew = Vec_IntAlloc( 100 ); p->vClassTemp = Vec_IntAlloc( 100 ); p->vRefinedC = Vec_IntAlloc( 100 ); // collect simulation info p->vSimInfo = Vec_PtrAlloc( 1000 ); Gia_ManForEachCi( pGia, pObj, i ) Vec_PtrPush( p->vSimInfo, Hcd_ObjSimP(p, Gia_ObjId(pGia,pObj)) ); p->vSimPres = Vec_PtrAllocSimInfo( Gia_ManCiNum(pGia), 1 ); return p; } /**Function************************************************************* Synopsis [Starts the fraiging manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManEquivStop( Hcd_Man_t * p ) { Vec_PtrFree( p->vSimInfo ); Vec_PtrFree( p->vSimPres ); Vec_IntFree( p->vClassOld ); Vec_IntFree( p->vClassNew ); Vec_IntFree( p->vClassTemp ); Vec_IntFree( p->vRefinedC ); ABC_FREE( p->pSimInfo ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Compared two simulation infos.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Hcd_ManCompareEqual( unsigned s0, unsigned s1 ) { if ( (s0 & 1) == (s1 & 1) ) return s0 == s1; else return s0 ==~s1; } /**Function************************************************************* Synopsis [Compares one simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Hcd_ManCompareConst( unsigned s ) { if ( s & 1 ) return s ==~0; else return s == 0; } /**Function************************************************************* Synopsis [Creates one equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hcd_ManClassCreate( Gia_Man_t * pGia, Vec_Int_t * vClass ) { int Repr = -1, EntPrev = -1, Ent, i; assert( Vec_IntSize(vClass) > 0 ); Vec_IntForEachEntry( vClass, Ent, i ) { if ( i == 0 ) { Repr = Ent; Gia_ObjSetRepr( pGia, Ent, -1 ); EntPrev = Ent; } else { Gia_ObjSetRepr( pGia, Ent, Repr ); Gia_ObjSetNext( pGia, EntPrev, Ent ); EntPrev = Ent; } } Gia_ObjSetNext( pGia, EntPrev, 0 ); } /**Function************************************************************* Synopsis [Refines one equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hcd_ManClassClassRemoveOne( Hcd_Man_t * p, int i ) { int iRepr, Ent; if ( Gia_ObjIsConst(p->pGia, i) ) { Gia_ObjSetRepr( p->pGia, i, GIA_VOID ); return 1; } if ( !Gia_ObjIsClass(p->pGia, i) ) return 0; assert( Gia_ObjIsClass(p->pGia, i) ); iRepr = Gia_ObjRepr( p->pGia, i ); if ( iRepr == GIA_VOID ) iRepr = i; // collect nodes Vec_IntClear( p->vClassOld ); Vec_IntClear( p->vClassNew ); Gia_ClassForEachObj( p->pGia, iRepr, Ent ) { if ( Ent == i ) Vec_IntPush( p->vClassNew, Ent ); else Vec_IntPush( p->vClassOld, Ent ); } assert( Vec_IntSize( p->vClassNew ) == 1 ); Hcd_ManClassCreate( p->pGia, p->vClassOld ); Hcd_ManClassCreate( p->pGia, p->vClassNew ); assert( !Gia_ObjIsClass(p->pGia, i) ); return 1; } /**Function************************************************************* Synopsis [Refines one equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hcd_ManClassRefineOne( Hcd_Man_t * p, int i ) { unsigned Sim0, Sim1; int Ent; Vec_IntClear( p->vClassOld ); Vec_IntClear( p->vClassNew ); Vec_IntPush( p->vClassOld, i ); Sim0 = Hcd_ObjSim(p, i); Gia_ClassForEachObj1( p->pGia, i, Ent ) { Sim1 = Hcd_ObjSim(p, Ent); if ( Hcd_ManCompareEqual( Sim0, Sim1 ) ) Vec_IntPush( p->vClassOld, Ent ); else Vec_IntPush( p->vClassNew, Ent ); } if ( Vec_IntSize( p->vClassNew ) == 0 ) return 0; Hcd_ManClassCreate( p->pGia, p->vClassOld ); Hcd_ManClassCreate( p->pGia, p->vClassNew ); if ( Vec_IntSize(p->vClassNew) > 1 ) return 1 + Hcd_ManClassRefineOne( p, Vec_IntEntry(p->vClassNew,0) ); return 1; } /**Function************************************************************* Synopsis [Computes hash key of the simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hcd_ManHashKey( unsigned * pSim, int nWords, int nTableSize ) { static int s_Primes[16] = { 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 }; unsigned uHash = 0; int i; if ( pSim[0] & 1 ) for ( i = 0; i < nWords; i++ ) uHash ^= ~pSim[i] * s_Primes[i & 0xf]; else for ( i = 0; i < nWords; i++ ) uHash ^= pSim[i] * s_Primes[i & 0xf]; return (int)(uHash % nTableSize); } /**Function************************************************************* Synopsis [Rehashes the refined classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hcd_ManClassesRehash( Hcd_Man_t * p, Vec_Int_t * vRefined ) { int * pTable, nTableSize, Key, i, k; nTableSize = Abc_PrimeCudd( 100 + Vec_IntSize(vRefined) / 5 ); pTable = ABC_CALLOC( int, nTableSize ); Vec_IntForEachEntry( vRefined, i, k ) { assert( !Hcd_ManCompareConst( Hcd_ObjSim(p, i) ) ); Key = Hcd_ManHashKey( Hcd_ObjSimP(p, i), 1, nTableSize ); if ( pTable[Key] == 0 ) Gia_ObjSetRepr( p->pGia, i, GIA_VOID ); else { Gia_ObjSetNext( p->pGia, pTable[Key], i ); Gia_ObjSetRepr( p->pGia, i, Gia_ObjRepr(p->pGia, pTable[Key]) ); if ( Gia_ObjRepr(p->pGia, i) == GIA_VOID ) Gia_ObjSetRepr( p->pGia, i, pTable[Key] ); } pTable[Key] = i; } ABC_FREE( pTable ); // Gia_ManEquivPrintClasses( p->pGia, 0, 0.0 ); // refine classes in the table Vec_IntForEachEntry( vRefined, i, k ) { if ( Gia_ObjIsHead( p->pGia, i ) ) Hcd_ManClassRefineOne( p, i ); } Gia_ManEquivPrintClasses( p->pGia, 0, 0.0 ); } /**Function************************************************************* Synopsis [Refines equivalence classes after simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hcd_ManClassesRefine( Hcd_Man_t * p ) { Gia_Obj_t * pObj; int i; Vec_IntClear( p->vRefinedC ); Gia_ManForEachAnd( p->pGia, pObj, i ) { if ( Gia_ObjIsTail(p->pGia, i) ) // add check for the class level { Hcd_ManClassRefineOne( p, Gia_ObjRepr(p->pGia, i) ); } else if ( Gia_ObjIsConst(p->pGia, i) ) { if ( !Hcd_ManCompareConst( Hcd_ObjSim(p, i) ) ) Vec_IntPush( p->vRefinedC, i ); } } Hcd_ManClassesRehash( p, p->vRefinedC ); } /**Function************************************************************* Synopsis [Creates equivalence classes for the first time.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hcd_ManClassesCreate( Hcd_Man_t * p ) { Gia_Obj_t * pObj; int i; assert( p->pGia->pReprs == NULL ); p->pGia->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p->pGia) ); p->pGia->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p->pGia) ); Gia_ManForEachObj( p->pGia, pObj, i ) Gia_ObjSetRepr( p->pGia, i, Gia_ObjIsAnd(pObj) ? 0 : GIA_VOID ); } /**Function************************************************************* Synopsis [Initializes simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hcd_ManSimulationInit( Hcd_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachCi( p->pGia, pObj, i ) Hcd_ObjSetSim( p, i, (Gia_ManRandom(0) << 1) ); } /**Function************************************************************* Synopsis [Performs one round of simple combinational simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hcd_ManSimulateSimple( Hcd_Man_t * p ) { Gia_Obj_t * pObj; unsigned Res0, Res1; int i; Gia_ManForEachAnd( p->pGia, pObj, i ) { Res0 = Hcd_ObjSim( p, Gia_ObjFaninId0(pObj, i) ); Res1 = Hcd_ObjSim( p, Gia_ObjFaninId1(pObj, i) ); Hcd_ObjSetSim( p, i, (Gia_ObjFaninC0(pObj)? ~Res0: Res0) & (Gia_ObjFaninC1(pObj)? ~Res1: Res1) ); } } /**Function************************************************************* Synopsis [Resimulate and refine one equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Gia_Resimulate_rec( Hcd_Man_t * p, int iObj ) { Gia_Obj_t * pObj; unsigned Res0, Res1; if ( Gia_ObjIsTravIdCurrentId( p->pGia, iObj ) ) return Hcd_ObjSim( p, iObj ); Gia_ObjSetTravIdCurrentId( p->pGia, iObj ); pObj = Gia_ManObj(p->pGia, iObj); if ( Gia_ObjIsCi(pObj) ) return Hcd_ObjSim( p, iObj ); assert( Gia_ObjIsAnd(pObj) ); Res0 = Gia_Resimulate_rec( p, Gia_ObjFaninId0(pObj, iObj) ); Res1 = Gia_Resimulate_rec( p, Gia_ObjFaninId1(pObj, iObj) ); return Hcd_ObjSetSim( p, iObj, (Gia_ObjFaninC0(pObj)? ~Res0: Res0) & (Gia_ObjFaninC1(pObj)? ~Res1: Res1) ); } /**Function************************************************************* Synopsis [Resimulate and refine one equivalence class.] Description [Assumes that the counter-example is assigned at the PIs. The counter-example should have the first bit set to 0 at each PI.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ResimulateAndRefine( Hcd_Man_t * p, int i ) { int RetValue, iObj; Gia_ManIncrementTravId( p->pGia ); Gia_ClassForEachObj( p->pGia, i, iObj ) Gia_Resimulate_rec( p, iObj ); RetValue = Hcd_ManClassRefineOne( p, i ); if ( RetValue == 0 ) printf( "!!! no refinement !!!\n" ); // assert( RetValue ); } /**Function************************************************************* Synopsis [Returns temporary representative of the node.] Description [The temp repr is the first node among the nodes in the class that (a) precedes the given node, and (b) whose level is lower than the given node.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_Obj_t * Gia_ObjTempRepr( Gia_Man_t * p, int i, int Level ) { int iRepr, iMember; iRepr = Gia_ObjRepr( p, i ); if ( !Gia_ObjProved(p, i) ) return NULL; if ( Gia_ObjFailed(p, i) ) return NULL; if ( iRepr == GIA_VOID ) return NULL; if ( iRepr == 0 ) return Gia_ManConst0( p ); // if ( p->pLevels[iRepr] < Level ) // return Gia_ManObj( p, iRepr ); Gia_ClassForEachObj( p, iRepr, iMember ) { if ( Gia_ObjFailed(p, iMember) ) continue; if ( iMember >= i ) return NULL; if ( Gia_ObjLevelId(p, iMember) < Level ) return Gia_ManObj( p, iMember ); } assert( 0 ); return NULL; } /**Function************************************************************* Synopsis [Generates reduced AIG for the given level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_GenerateReducedLevel( Gia_Man_t * p, int Level, Vec_Ptr_t ** pvRoots ) { Gia_Man_t * pNew; Gia_Obj_t * pObj, * pRepr; Vec_Ptr_t * vRoots; int i; vRoots = Vec_PtrAlloc( 100 ); // copy unmarked nodes 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_ManHashAlloc( pNew ); Gia_ManForEachAnd( p, pObj, i ) { if ( Gia_ObjLevelId(p, i) > Level ) continue; if ( Gia_ObjLevelId(p, i) == Level ) Vec_PtrPush( vRoots, pObj ); if ( Gia_ObjLevelId(p, i) < Level && (pRepr = Gia_ObjTempRepr(p, i, Level)) ) { // printf( "Substituting %d <--- %d\n", Gia_ObjId(p, pRepr), Gia_ObjId(p, pObj) ); assert( pRepr < pObj ); pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); continue; } pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } *pvRoots = vRoots; // required by SAT solving Gia_ManCreateRefs( pNew ); Gia_ManFillValue( pNew ); Gia_ManIncrementTravId( pNew ); // needed for MiniSat to record cexes // Gia_ManSetPhase( pNew ); // needed if MiniSat is using polarity -- should not be enabled for TAS because fPhase is used to label return pNew; } /**Function************************************************************* Synopsis [Collects relevant classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Gia_CollectRelatedClasses( Gia_Man_t * pGia, Vec_Ptr_t * vRoots ) { Vec_Ptr_t * vClasses; Gia_Obj_t * pRoot, * pRepr; int i; vClasses = Vec_PtrAlloc( 100 ); Gia_ManConst0( pGia )->fMark0 = 1; Vec_PtrForEachEntry( Gia_Obj_t *, vRoots, pRoot, i ) { pRepr = Gia_ObjReprObj( pGia, Gia_ObjId(pGia, pRoot) ); if ( pRepr == NULL || pRepr->fMark0 ) continue; pRepr->fMark0 = 1; Vec_PtrPush( vClasses, pRepr ); } Gia_ManConst0( pGia )->fMark0 = 0; Vec_PtrForEachEntry( Gia_Obj_t *, vClasses, pRepr, i ) pRepr->fMark0 = 0; return vClasses; } /**Function************************************************************* Synopsis [Collects class members.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Obj_t * Gia_CollectClassMembers( Gia_Man_t * p, Gia_Obj_t * pRepr, Vec_Ptr_t * vMembers, int Level ) { Gia_Obj_t * pTempRepr = NULL; int iRepr, iMember; iRepr = Gia_ObjId( p, pRepr ); Vec_PtrClear( vMembers ); Gia_ClassForEachObj( p, iRepr, iMember ) { if ( Gia_ObjLevelId(p, iMember) == Level ) Vec_PtrPush( vMembers, Gia_ManObj( p, iMember ) ); if ( pTempRepr == NULL && Gia_ObjLevelId(p, iMember) < Level ) pTempRepr = Gia_ManObj( p, iMember ); } return pTempRepr; } /**Function************************************************************* Synopsis [Packs patterns into array of simulation info.] Description [] SideEffects [] SeeAlso [] *************************************`**********************************/ int Gia_GiarfStorePatternTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits ) { unsigned * pInfo, * pPres; int i; for ( i = 0; i < nLits; i++ ) { pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); if ( Abc_InfoHasBit( pPres, iBit ) && Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) return 0; } for ( i = 0; i < nLits; i++ ) { pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); Abc_InfoSetBit( pPres, iBit ); if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) Abc_InfoXorBit( pInfo, iBit ); } return 1; } /**Function************************************************************* Synopsis [Procedure to test the new SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_GiarfStorePattern( Vec_Ptr_t * vSimInfo, Vec_Ptr_t * vPres, Vec_Int_t * vCex ) { int k; for ( k = 1; k < 32; k++ ) if ( Gia_GiarfStorePatternTry( vSimInfo, vPres, k, (int *)Vec_IntArray(vCex), Vec_IntSize(vCex) ) ) break; return (int)(k < 32); } /**Function************************************************************* Synopsis [Inserts pattern into simulation info for the PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_GiarfInsertPattern( Hcd_Man_t * p, Vec_Int_t * vCex, int k ) { Gia_Obj_t * pObj; unsigned * pInfo; int Lit, i; Vec_IntForEachEntry( vCex, Lit, i ) { pObj = Gia_ManCi( p->pGia, Abc_Lit2Var(Lit) ); pInfo = Hcd_ObjSimP( p, Gia_ObjId( p->pGia, pObj ) ); if ( Abc_InfoHasBit( pInfo, k ) == Abc_LitIsCompl(Lit) ) Abc_InfoXorBit( pInfo, k ); } } /**Function************************************************************* Synopsis [Inserts pattern into simulation info for the PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_GiarfPrintClasses( Gia_Man_t * pGia ) { int nFails = 0; int nProves = 0; int nTotal = 0; int nBoth = 0; int i; for ( i = 0; i < Gia_ManObjNum(pGia); i++ ) { nFails += Gia_ObjFailed(pGia, i); nProves += Gia_ObjProved(pGia, i); nTotal += Gia_ObjReprObj(pGia, i) != NULL; nBoth += Gia_ObjFailed(pGia, i) && Gia_ObjProved(pGia, i); } printf( "nFails = %7d. nProves = %7d. nBoth = %7d. nTotal = %7d.\n", nFails, nProves, nBoth, nTotal ); } ABC_NAMESPACE_IMPL_END #include "proof/cec/cecInt.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [Performs computation of AIGs with choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ComputeEquivalencesLevel( Hcd_Man_t * p, Gia_Man_t * pGiaLev, Vec_Ptr_t * vOldRoots, int Level, int fUseMiniSat ) { int fUse2Solver = 0; Cec_ManSat_t * pSat; Cec_ParSat_t Pars; Tas_Man_t * pTas; Vec_Int_t * vCex; Vec_Ptr_t * vClasses, * vMembers, * vOldRootsNew; Gia_Obj_t * pRoot, * pMember, * pMemberPrev, * pRepr, * pTempRepr; int i, k, nIter, iRoot, iRootNew, iMember, iMemberPrev, status, fOneFailed;//, iRepr;//, fTwoMember; int nSaved = 0, nRecords = 0, nUndec = 0, nClassRefs = 0, nTsat = 0, nMiniSat = 0; clock_t clk, timeTsat = 0, timeMiniSat = 0, timeSim = 0, timeTotal = clock(); if ( Vec_PtrSize(vOldRoots) == 0 ) return 0; // start SAT solvers Cec_ManSatSetDefaultParams( &Pars ); Pars.fPolarFlip = 0; Pars.nBTLimit = p->nBTLimit; pSat = Cec_ManSatCreate( pGiaLev, &Pars ); pTas = Tas_ManAlloc( pGiaLev, p->nBTLimit ); if ( fUseMiniSat ) vCex = Cec_ManSatReadCex( pSat ); else vCex = Tas_ReadModel( pTas ); vMembers = Vec_PtrAlloc( 100 ); Vec_PtrCleanSimInfo( p->vSimPres, 0, 1 ); // resolve constants Vec_PtrForEachEntry( Gia_Obj_t *, vOldRoots, pRoot, i ) { iRoot = Gia_ObjId( p->pGia, pRoot ); if ( !Gia_ObjIsConst( p->pGia, iRoot ) ) continue; iRootNew = Abc_LitNotCond( pRoot->Value, pRoot->fPhase ); assert( iRootNew != 1 ); if ( fUse2Solver ) { nTsat++; clk = clock(); status = Tas_ManSolve( pTas, Gia_ObjFromLit(pGiaLev, iRootNew), NULL ); timeTsat += clock() - clk; if ( status == -1 ) { nMiniSat++; clk = clock(); status = Cec_ManSatCheckNode( pSat, Gia_ObjFromLit(pGiaLev, iRootNew) ); timeMiniSat += clock() - clk; if ( status == 0 ) { Cec_ManSavePattern( pSat, Gia_ObjFromLit(pGiaLev, iRootNew), NULL ); vCex = Cec_ManSatReadCex( pSat ); } } else if ( status == 0 ) vCex = Tas_ReadModel( pTas ); } else if ( fUseMiniSat ) { nMiniSat++; clk = clock(); status = Cec_ManSatCheckNode( pSat, Gia_ObjFromLit(pGiaLev, iRootNew) ); timeMiniSat += clock() - clk; if ( status == 0 ) Cec_ManSavePattern( pSat, Gia_ObjFromLit(pGiaLev, iRootNew), NULL ); } else { nTsat++; clk = clock(); status = Tas_ManSolve( pTas, Gia_ObjFromLit(pGiaLev, iRootNew), NULL ); timeTsat += clock() - clk; } if ( status == -1 ) // undec { // Gia_ObjSetFailed( p->pGia, iRoot ); nUndec++; // Hcd_ManClassClassRemoveOne( p, iRoot ); Gia_ObjSetFailed( p->pGia, iRoot ); } else if ( status == 1 ) // unsat { Gia_ObjSetProved( p->pGia, iRoot ); // printf( "proved constant %d\n", iRoot ); } else // sat { // printf( "Disproved constant %d\n", iRoot ); Gia_ObjUnsetRepr( p->pGia, iRoot ); // do we need this? nRecords++; nSaved += Gia_GiarfStorePattern( p->vSimInfo, p->vSimPres, vCex ); } } vClasses = Vec_PtrAlloc( 100 ); vOldRootsNew = Vec_PtrAlloc( 100 ); for ( nIter = 0; Vec_PtrSize(vOldRoots) > 0; nIter++ ) { // printf( "Iter = %d (Size = %d)\n", nIter, Vec_PtrSize(vOldRoots) ); // resolve equivalences Vec_PtrClear( vClasses ); Vec_PtrClear( vOldRootsNew ); Gia_ManConst0( p->pGia )->fMark0 = 1; Vec_PtrForEachEntry( Gia_Obj_t *, vOldRoots, pRoot, i ) { iRoot = Gia_ObjId( p->pGia, pRoot ); if ( Gia_ObjIsHead( p->pGia, iRoot ) ) pRepr = pRoot; else if ( Gia_ObjIsClass( p->pGia, iRoot ) ) pRepr = Gia_ObjReprObj( p->pGia, iRoot ); else continue; if ( pRepr->fMark0 ) continue; pRepr->fMark0 = 1; Vec_PtrPush( vClasses, pRepr ); // iRepr = Gia_ObjId( p->pGia, pRepr ); // fTwoMember = Gia_ClassIsPair(p->pGia, iRepr) // derive temp repr and members on this level pTempRepr = Gia_CollectClassMembers( p->pGia, pRepr, vMembers, Level ); if ( pTempRepr ) Vec_PtrPush( vMembers, pTempRepr ); if ( Vec_PtrSize(vMembers) < 2 ) continue; // try proving the members fOneFailed = 0; pMemberPrev = (Gia_Obj_t *)Vec_PtrEntryLast( vMembers ); Vec_PtrForEachEntry( Gia_Obj_t *, vMembers, pMember, k ) { iMemberPrev = Abc_LitNotCond( pMemberPrev->Value, pMemberPrev->fPhase ); iMember = Abc_LitNotCond( pMember->Value, !pMember->fPhase ); assert( iMemberPrev != iMember ); if ( fUse2Solver ) { nTsat++; clk = clock(); status = Tas_ManSolve( pTas, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) ); timeTsat += clock() - clk; if ( status == -1 ) { nMiniSat++; clk = clock(); status = Cec_ManSatCheckNodeTwo( pSat, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) ); timeMiniSat += clock() - clk; if ( status == 0 ) { Cec_ManSavePattern( pSat, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) ); vCex = Cec_ManSatReadCex( pSat ); } } else if ( status == 0 ) vCex = Tas_ReadModel( pTas ); } else if ( fUseMiniSat ) { nMiniSat++; clk = clock(); status = Cec_ManSatCheckNodeTwo( pSat, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) ); timeMiniSat += clock() - clk; if ( status == 0 ) Cec_ManSavePattern( pSat, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) ); } else { nTsat++; clk = clock(); status = Tas_ManSolve( pTas, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) ); timeTsat += clock() - clk; } if ( status == -1 ) // undec { // Gia_ObjSetFailed( p->pGia, iRoot ); nUndec++; if ( Gia_ObjLevel(p->pGia, pMemberPrev) > Gia_ObjLevel(p->pGia, pMember) ) { // Hcd_ManClassClassRemoveOne( p, Gia_ObjId(p->pGia, pMemberPrev) ); Gia_ObjSetFailed( p->pGia, Gia_ObjId(p->pGia, pMemberPrev) ); Gia_ObjSetFailed( p->pGia, Gia_ObjId(p->pGia, pMember) ); } else { // Hcd_ManClassClassRemoveOne( p, Gia_ObjId(p->pGia, pMember) ); Gia_ObjSetFailed( p->pGia, Gia_ObjId(p->pGia, pMemberPrev) ); Gia_ObjSetFailed( p->pGia, Gia_ObjId(p->pGia, pMember) ); } } else if ( status == 1 ) // unsat { // Gia_ObjSetProved( p->pGia, iRoot ); } else // sat { // iRepr = Gia_ObjId( p->pGia, pRepr ); // if ( Gia_ClassIsPair(p->pGia, iRepr) ) // Gia_ClassUndoPair(p->pGia, iRepr); // else { fOneFailed = 1; nRecords++; nSaved += Gia_GiarfStorePattern( p->vSimInfo, p->vSimPres, vCex ); Gia_GiarfInsertPattern( p, vCex, (k % 31) + 1 ); } } pMemberPrev = pMember; // if ( fOneFailed ) // k += Vec_PtrSize(vMembers) / 4; } // if fail, quit this class if ( fOneFailed ) { nClassRefs++; Vec_PtrForEachEntry( Gia_Obj_t *, vMembers, pMember, k ) if ( pMember != pTempRepr && !Gia_ObjFailed(p->pGia, Gia_ObjId(p->pGia, pMember)) ) Vec_PtrPush( vOldRootsNew, pMember ); clk = clock(); Gia_ResimulateAndRefine( p, Gia_ObjId(p->pGia, pRepr) ); timeSim += clock() - clk; } else { Vec_PtrForEachEntry( Gia_Obj_t *, vMembers, pMember, k ) Gia_ObjSetProved( p->pGia, Gia_ObjId(p->pGia, pMember) ); /* // } // else // { printf( "Proved equivalent: " ); Vec_PtrForEachEntry( Gia_Obj_t *, vMembers, pMember, k ) printf( "%d(L=%d) ", Gia_ObjId(p->pGia, pMember), p->pGia->pLevels[Gia_ObjId(p->pGia, pMember)] ); printf( "\n" ); */ } } Vec_PtrClear( vOldRoots ); Vec_PtrForEachEntry( Gia_Obj_t *, vOldRootsNew, pMember, i ) Vec_PtrPush( vOldRoots, pMember ); // clean up Gia_ManConst0( p->pGia )->fMark0 = 0; Vec_PtrForEachEntry( Gia_Obj_t *, vClasses, pRepr, i ) pRepr->fMark0 = 0; } Vec_PtrFree( vClasses ); Vec_PtrFree( vOldRootsNew ); printf( "nSaved = %d nRecords = %d nUndec = %d nClassRefs = %d nMiniSat = %d nTas = %d\n", nSaved, nRecords, nUndec, nClassRefs, nMiniSat, nTsat ); ABC_PRT( "Tas ", timeTsat ); ABC_PRT( "MiniSat", timeMiniSat ); ABC_PRT( "Sim ", timeSim ); ABC_PRT( "Total ", clock() - timeTotal ); // resimulate // clk = clock(); Hcd_ManSimulateSimple( p ); Hcd_ManClassesRefine( p ); // ABC_PRT( "Simulate/refine", clock() - clk ); // verify the results Vec_PtrFree( vMembers ); Tas_ManStop( pTas ); Cec_ManSatStop( pSat ); return nIter; } /**Function************************************************************* Synopsis [Performs computation of AIGs with choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ComputeEquivalences( Gia_Man_t * pGia, int nBTLimit, int fUseMiniSat, int fVerbose ) { Hcd_Man_t * p; Vec_Ptr_t * vRoots; Gia_Man_t * pGiaLev; int i, Lev, nLevels, nIters; clock_t clk; Gia_ManRandom( 1 ); Gia_ManSetPhase( pGia ); nLevels = Gia_ManLevelNum( pGia ); Gia_ManIncrementTravId( pGia ); // start the manager p = Gia_ManEquivStart( pGia, nBTLimit, fVerbose ); // create trivial classes Hcd_ManClassesCreate( p ); // refine for ( i = 0; i < 3; i++ ) { clk = clock(); Hcd_ManSimulationInit( p ); Hcd_ManSimulateSimple( p ); ABC_PRT( "Sim", clock() - clk ); clk = clock(); Hcd_ManClassesRefine( p ); ABC_PRT( "Ref", clock() - clk ); } // process in the levelized order for ( Lev = 1; Lev < nLevels; Lev++ ) { clk = clock(); printf( "LEVEL %3d (out of %3d) ", Lev, nLevels ); pGiaLev = Gia_GenerateReducedLevel( pGia, Lev, &vRoots ); nIters = Gia_ComputeEquivalencesLevel( p, pGiaLev, vRoots, Lev, fUseMiniSat ); Gia_ManStop( pGiaLev ); Vec_PtrFree( vRoots ); printf( "Iters = %3d " ); ABC_PRT( "Time", clock() - clk ); } Gia_GiarfPrintClasses( pGia ); // clean up Gia_ManEquivStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaGig.c000066400000000000000000000412031477524141600156220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaGig.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Parser for Gate-Inverter Graph by Niklas Een.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaGig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/extra/extra.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define MAX_LINE 1000000 // network types enum { GLS_NONE = -1, // not used GLS_ZERO = 0, // zero GLS_ONE = 1, // one GLS_PI = 2, // primary input GLS_PO = 3, // primary output GLS_BAR = 4, // barrier GLS_SEQ = 5, // sequential GLS_SEL = 6, // fan GLS_LUT4 = 7, // LUT4 GLS_LUT6 = 8, // LUT6 GLS_BOX = 9, // sequential box GLS_DEL = 10, // delay box GLS_FINAL }; static char * s_Strs[GLS_FINAL] = { "0", // GLS_ZERO = 0, // zero "1", // GLS_ONE = 1, // one "PI", // GLS_PI = 2, // primary input "PO", // GLS_PO = 3, // primary output "Bar", // GLS_BAR = 4, // barrier "Seq", // GLS_SEQ = 5, // sequential "Sel", // GLS_SEL = 6, // fan "Lut4", // GLS_LUT4 = 7, // LUT4 "Lut6", // GLS_LUT6 = 8, // LUT6 "Box", // GLS_BOX = 9, // sequential box "Del" // GLS_DEL = 10, // delay box }; typedef struct Gls_Man_t_ Gls_Man_t; struct Gls_Man_t_ { // general Vec_Str_t * vLines; // line types Vec_Str_t * vTypes; // gate types Vec_Int_t * vIndexes; // gate indexes // specific types Vec_Int_t * vLut4s; // 4-LUTs (4-tuples) Vec_Int_t * vLut4TTs; // truth tables Vec_Int_t * vLut6s; // 6-LUTs (6-tuples) Vec_Wrd_t * vLut6TTs; // truth tables Vec_Int_t * vBoxes; // boxes (5-tuples) Vec_Wec_t * vDelayIns; // delay fanins Vec_Wec_t * vDelayOuts; // delay fanouts Vec_Int_t * vDelays; // delay values // ordering Vec_Int_t * vOrderPis; Vec_Int_t * vOrderPos; Vec_Int_t * vOrderBoxes; Vec_Int_t * vOrderDelays; Vec_Int_t * vOrderLuts; Vec_Int_t * vOrderSeqs; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gls_Man_t * Gls_ManAlloc( Vec_Str_t * vLines, int * pCounts ) { Gls_Man_t * p = ABC_CALLOC( Gls_Man_t, 1 ); p->vLines = vLines; p->vTypes = Vec_StrStart( Vec_StrSize(vLines)+100 ); p->vIndexes = Vec_IntStart( Vec_StrSize(vLines)+100 ); p->vLut4s = Vec_IntAlloc( 4 * pCounts[GLS_LUT4] ); p->vLut4TTs = Vec_IntAlloc( pCounts[GLS_LUT4] ); p->vLut6s = Vec_IntAlloc( 6 * pCounts[GLS_LUT6] ); p->vLut6TTs = Vec_WrdAlloc( pCounts[GLS_LUT6] ); p->vBoxes = Vec_IntAlloc( 5 * pCounts[GLS_BOX] ); p->vDelays = Vec_IntAlloc( pCounts[GLS_DEL] ); p->vDelayIns = Vec_WecAlloc( pCounts[GLS_DEL] ); p->vDelayOuts = Vec_WecAlloc( pCounts[GLS_DEL] ); // ordering p->vOrderPis = Vec_IntAlloc( pCounts[GLS_PI] ); p->vOrderPos = Vec_IntAlloc( pCounts[GLS_PO] ); p->vOrderBoxes = Vec_IntAlloc( pCounts[GLS_BOX] ); p->vOrderDelays = Vec_IntAlloc( pCounts[GLS_DEL] ); p->vOrderLuts = Vec_IntAlloc( pCounts[GLS_LUT4] + pCounts[GLS_LUT6] + 2*pCounts[GLS_BAR] ); p->vOrderSeqs = Vec_IntAlloc( pCounts[GLS_SEQ] ); return p; } void Gls_ManStop( Gls_Man_t * p ) { Vec_StrFree( p->vLines ); Vec_StrFree( p->vTypes ); Vec_IntFree( p->vIndexes ); Vec_IntFree( p->vLut4s ); Vec_IntFree( p->vLut4TTs ); Vec_IntFree( p->vLut6s ); Vec_WrdFree( p->vLut6TTs ); Vec_IntFree( p->vBoxes ); Vec_IntFree( p->vDelays ); Vec_WecFree( p->vDelayIns ); Vec_WecFree( p->vDelayOuts ); // ordering Vec_IntFree( p->vOrderPis ); Vec_IntFree( p->vOrderPos ); Vec_IntFree( p->vOrderBoxes ); Vec_IntFree( p->vOrderDelays ); Vec_IntFree( p->vOrderLuts ); Vec_IntFree( p->vOrderSeqs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Gls_ManCount( FILE * pFile, int pCounts[GLS_FINAL] ) { char * pLine, * pBuffer = ABC_ALLOC(char, MAX_LINE); int Type; Vec_Str_t * vLines = Vec_StrAlloc( 10000 ); memset( pCounts, 0, sizeof(int)*GLS_FINAL ); while ( fgets( pBuffer, MAX_LINE, pFile ) != NULL ) { pLine = pBuffer; while ( *pLine ) if ( *pLine++ == '=' ) break; while ( *pLine == ' ' ) pLine++; if ( *pLine == 'L' ) { if ( pLine[3] == '4' ) Type = GLS_LUT4; else if ( pLine[3] == '6' ) Type = GLS_LUT6; else assert( 0 ); } else if ( *pLine == 'P' ) { if ( pLine[1] == 'I' ) Type = GLS_PI; else if ( pLine[1] == 'O' ) Type = GLS_PO; else assert( 0 ); } else if ( *pLine == 'B' ) { if ( pLine[1] == 'o' ) Type = GLS_BOX; else if ( pLine[1] == 'a' ) Type = GLS_BAR; else assert( 0 ); } else if ( *pLine == 'S' ) { if ( pLine[2] == 'l' ) Type = GLS_SEL; else if ( pLine[2] == 'q' ) Type = GLS_SEQ; else assert( 0 ); } else if ( *pLine == 'D' ) Type = GLS_DEL; else assert( 0 ); Vec_StrPush( vLines, (char)Type ); pCounts[Type]++; } ABC_FREE( pBuffer ); return vLines; } int Gls_ManParseOne( char ** ppLine ) { int Entry; char * pLine = *ppLine; while ( *pLine == ' ' ) pLine++; if ( *pLine == '-' ) Entry = GLS_NONE; else if ( *pLine == '0' ) Entry = 0; else if ( *pLine == '1' ) Entry = 1; else if ( *pLine == 'w' ) Entry = atoi(++pLine); else assert( 0 ); while ( *pLine == '-' || (*pLine >= '0' && *pLine <= '9') ) pLine++; while ( *pLine == ' ' ) pLine++; *ppLine = pLine; return Entry; } int Gls_ManParse( FILE * pFile, Gls_Man_t * p ) { char * pLine, * pBuffer = ABC_ALLOC(char, MAX_LINE); int i, k, Type, iObj, Entry, iItem; word Truth; for ( i = 0; fgets( pBuffer, MAX_LINE, pFile ) != NULL; i++ ) { pLine = pBuffer; Type = Vec_StrEntry( p->vLines, i ); iObj = Gls_ManParseOne( &pLine ); Vec_StrWriteEntry( p->vTypes, iObj, (char)Type ); if ( Type == GLS_PI ) { Vec_IntPush( p->vOrderPis, iObj ); Vec_IntWriteEntry( p->vIndexes, iObj, -1 ); continue; } while ( *pLine ) if ( *pLine++ == '(' ) break; Entry = Gls_ManParseOne( &pLine ); if ( Type == GLS_PO || Type == GLS_BAR || Type == GLS_SEQ || Type == GLS_SEL ) { if ( Type == GLS_PO ) Vec_IntPush( p->vOrderPos, iObj ); else if ( Type == GLS_BAR ) Vec_IntPush( p->vOrderLuts, iObj ); else if ( Type == GLS_SEQ ) Vec_IntPush( p->vOrderSeqs, iObj ); else if ( Type == GLS_SEL ) { if ( (int)Vec_StrEntry(p->vTypes, Entry) == GLS_DEL ) { Vec_Int_t * vOuts = Vec_WecEntry( p->vDelayOuts, Vec_IntEntry(p->vIndexes, Entry) ); Vec_IntPush( vOuts, iObj ); } else if ( (int)Vec_StrEntry(p->vTypes, Entry) == GLS_BAR ) Vec_IntPush( p->vOrderLuts, iObj ); else assert( 0 ); } Vec_IntWriteEntry( p->vIndexes, iObj, Entry ); continue; } if ( Type == GLS_LUT4 ) { Vec_IntWriteEntry( p->vIndexes, iObj, Vec_IntSize(p->vLut4TTs) ); Vec_IntPush( p->vLut4s, Entry ); for ( k = 1; ; k++ ) { if ( *pLine != ',' ) break; pLine++; Entry = Gls_ManParseOne( &pLine ); Vec_IntPush( p->vLut4s, Entry ); } assert( *pLine == ')' ); assert( k == 4 ); pLine++; while ( *pLine ) if ( *pLine++ == '[' ) break; Abc_TtReadHex( &Truth, pLine ); Vec_IntPush( p->vLut4TTs, (unsigned)Truth ); Vec_IntPush( p->vOrderLuts, iObj ); } else if ( Type == GLS_LUT6 ) { Vec_IntWriteEntry( p->vIndexes, iObj, Vec_WrdSize(p->vLut6TTs) ); Vec_IntPush( p->vLut6s, Entry ); for ( k = 1; ; k++ ) { if ( *pLine != ',' ) break; pLine++; Entry = Gls_ManParseOne( &pLine ); Vec_IntPush( p->vLut6s, Entry ); } assert( *pLine == ')' ); assert( k == 4 ); pLine++; while ( *pLine ) if ( *pLine++ == '[' ) break; Abc_TtReadHex( &Truth, pLine ); Vec_WrdPush( p->vLut6TTs, Truth ); Vec_IntPush( p->vOrderLuts, iObj ); } else if ( Type == GLS_BOX ) { Vec_IntWriteEntry( p->vIndexes, iObj, Vec_IntSize(p->vBoxes)/5 ); Vec_IntPush( p->vBoxes, Entry ); for ( k = 1; ; k++ ) { if ( *pLine != ',' ) break; pLine++; Entry = Gls_ManParseOne( &pLine ); Vec_IntPush( p->vBoxes, Entry ); } assert( *pLine == ')' ); assert( k == 4 || k == 5 ); if ( k == 4 ) Vec_IntPush( p->vBoxes, GLS_NONE ); Vec_IntPush( p->vOrderBoxes, iObj ); } else if ( Type == GLS_DEL ) { Vec_Int_t * vIns = Vec_WecPushLevel( p->vDelayIns ); Vec_Int_t * vOuts = Vec_WecPushLevel( p->vDelayOuts ); Vec_IntWriteEntry( p->vIndexes, iObj, Vec_IntSize(p->vDelays) ); Vec_IntPush( vIns, Entry ); if ( *pLine != ')' ) { for ( k = 1; ; k++ ) { if ( *pLine != ',' ) break; pLine++; Entry = Gls_ManParseOne( &pLine ); Vec_IntPush( vIns, Entry ); } } assert( *pLine == ')' ); pLine++; while ( *pLine ) if ( *pLine++ == '[' ) break; iItem = atoi(pLine); Vec_IntPush( p->vDelays, iItem ); Vec_IntPush( p->vOrderDelays, iObj ); vOuts = vIns; // harmless use to prevent a compiler warning } else assert( 0 ); } ABC_FREE( pBuffer ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gls_ManConstruct( Gls_Man_t * p, char * pFileName ) { extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); Gia_Man_t * pGia = NULL; Vec_Int_t * vMap, * vArray; Vec_Int_t * vCover = Vec_IntAlloc(0); Vec_Int_t * vLeaves = Vec_IntAlloc(6); int k, iObj, iLit, Index; char Type; // create new manager pGia = Gia_ManStart( Vec_StrSize(p->vTypes) ); pGia->pName = Abc_UtilStrsav( pFileName ); pGia->pSpec = Abc_UtilStrsav( pFileName ); // create constants vMap = Vec_IntStartFull( Vec_StrSize(p->vTypes) ); Vec_IntWriteEntry( vMap, 0, 0 ); Vec_IntWriteEntry( vMap, 1, 1 ); // create primary inputs Vec_IntForEachEntry( p->vOrderPis, iObj, k ) Vec_IntWriteEntry( vMap, iObj, Gia_ManAppendCi(pGia) ); // create box outputs Vec_IntForEachEntry( p->vOrderBoxes, iObj, k ) Vec_IntWriteEntry( vMap, iObj, Gia_ManAppendCi(pGia) ); // create delay outputs Vec_IntForEachEntry( p->vOrderDelays, iObj, Index ) { assert( Index == Vec_IntEntry(p->vIndexes, iObj) ); vArray = Vec_WecEntry(p->vDelayOuts, Index); if ( Vec_IntSize(vArray) == 0 ) Vec_IntWriteEntry( vMap, iObj, Gia_ManAppendCi(pGia) ); else Vec_IntForEachEntry( vArray, iObj, k ) Vec_IntWriteEntry( vMap, iObj, Gia_ManAppendCi(pGia) ); } // construct LUTs Vec_IntForEachEntry( p->vOrderLuts, iObj, Index ) { Type = Vec_StrEntry( p->vTypes, iObj ); if ( Type == GLS_LUT4 || Type == GLS_LUT6 ) { int Limit = Type == GLS_LUT4 ? 4 : 6; int Index = Vec_IntEntry(p->vIndexes, iObj); int * pFanins = Type == GLS_LUT4 ? Vec_IntEntryP(p->vLut4s, 4*Index) : Vec_IntEntryP(p->vLut6s, 6*Index); word Truth = Type == GLS_LUT4 ? (word)Vec_IntEntry(p->vLut4TTs, Index) : Vec_WrdEntry(p->vLut6TTs, Index); Vec_IntClear( vLeaves ); for ( k = 0; k < Limit; k++ ) Vec_IntPush( vLeaves, pFanins[k] == GLS_NONE ? 0 : Vec_IntEntry(vMap, pFanins[k]) ); iLit = Kit_TruthToGia( pGia, (unsigned *)&Truth, Vec_IntSize(vLeaves), vCover, vLeaves, 0 ); Vec_IntWriteEntry( vMap, iObj, iLit ); } else if ( Type == GLS_BAR || Type == GLS_SEL ) { iLit = Vec_IntEntry( vMap, Vec_IntEntry(p->vIndexes, iObj) ); Vec_IntWriteEntry( vMap, iObj, iLit ); } } // delay inputs Vec_IntForEachEntry( p->vOrderDelays, iObj, Index ) { vArray = Vec_WecEntry(p->vDelayIns, Index); assert( Vec_IntSize(vArray) > 0 ); Vec_IntForEachEntry( vArray, iObj, k ) Gia_ManAppendCo( pGia, Vec_IntEntry(vMap, iObj) ); } // create primary outputs Vec_IntForEachEntry( p->vOrderPos, iObj, k ) Gia_ManAppendCo( pGia, Vec_IntEntry(vMap, Vec_IntEntry(p->vIndexes, iObj)) ); // create sequential nodes Vec_IntForEachEntry( p->vOrderSeqs, iObj, k ) Gia_ManAppendCo( pGia, Vec_IntEntry(vMap, Vec_IntEntry(p->vIndexes, iObj)) ); Vec_IntFree( vMap ); Vec_IntFree( vCover ); Vec_IntFree( vLeaves ); // print delay boxes // for ( k = 0; k < Vec_IntSize(p->vDelays); k++ ) // printf( "%d:%d ", Vec_IntSize(Vec_WecEntry(p->vDelayIns, k)), Vec_IntSize(Vec_WecEntry(p->vDelayOuts, k)) ); // printf( "\n" ); return pGia; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManReadGig( char * pFileName ) { abctime clk = Abc_Clock(); Gls_Man_t * p = NULL; Gia_Man_t * pGia = NULL; Vec_Str_t * vLines; int i, pCounts[GLS_FINAL]; FILE * pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot read file \"%s\".\n", pFileName ); return NULL; } vLines = Gls_ManCount( pFile, pCounts ); rewind( pFile ); // statistics for ( i = 0; i < GLS_FINAL; i++ ) if ( pCounts[i] ) printf( "%s=%d ", s_Strs[i], pCounts[i] ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // collect data and derive AIG p = Gls_ManAlloc( vLines, pCounts ); if ( Gls_ManParse( pFile, p ) ) pGia = Gls_ManConstruct( p, pFileName ); Gls_ManStop( p ); fclose( pFile ); //printf( "\n" ); return pGia; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaGlitch.c000066400000000000000000000625011477524141600163320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaGlitch.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Glitch simulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaGlitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Gli_Obj_t_ Gli_Obj_t; struct Gli_Obj_t_ { unsigned fTerm : 1; // terminal node unsigned fPhase : 1; // value under 000 pattern unsigned fPhase2 : 1; // value under 000 pattern unsigned fMark : 1; // user-controlled mark unsigned nFanins : 3; // the number of fanins unsigned nFanouts : 25; // total number of fanouts unsigned Handle; // ID of the node word * pTruth; // truth table of the node unsigned uSimInfo; // simulation info of the node union { int iFanin; // the number of fanins added int nSwitches; // the number of switches }; union { int iFanout; // the number of fanouts added int nGlitches; // the number of glitches ( nGlitches >= nSwitches ) }; int Fanios[0]; // the array of fanins/fanouts }; typedef struct Gli_Man_t_ Gli_Man_t; struct Gli_Man_t_ { Vec_Int_t * vCis; // the vector of CIs (PIs + LOs) Vec_Int_t * vCos; // the vector of COs (POs + LIs) Vec_Int_t * vCisChanged; // the changed CIs Vec_Int_t * vAffected; // the affected nodes Vec_Int_t * vFrontier; // the fanouts of these nodes int nObjs; // the number of objects int nRegs; // the number of registers int nTravIds; // traversal ID of the network int iObjData; // pointer to the current data int nObjData; // the size of array to store the logic network int * pObjData; // the internal nodes unsigned * pSimInfoPrev; // previous values of the CIs }; static inline int Gli_ManCiNum( Gli_Man_t * p ) { return Vec_IntSize(p->vCis); } static inline int Gli_ManCoNum( Gli_Man_t * p ) { return Vec_IntSize(p->vCos); } static inline int Gli_ManPiNum( Gli_Man_t * p ) { return Vec_IntSize(p->vCis) - p->nRegs; } static inline int Gli_ManPoNum( Gli_Man_t * p ) { return Vec_IntSize(p->vCos) - p->nRegs; } static inline int Gli_ManRegNum( Gli_Man_t * p ) { return p->nRegs; } static inline int Gli_ManObjNum( Gli_Man_t * p ) { return p->nObjs; } static inline int Gli_ManNodeNum( Gli_Man_t * p ) { return p->nObjs - Vec_IntSize(p->vCis) - Vec_IntSize(p->vCos); } static inline Gli_Obj_t * Gli_ManObj( Gli_Man_t * p, int v ) { return (Gli_Obj_t *)(p->pObjData + v); } static inline Gli_Obj_t * Gli_ManCi( Gli_Man_t * p, int v ) { return Gli_ManObj( p, Vec_IntEntry(p->vCis,v) ); } static inline Gli_Obj_t * Gli_ManCo( Gli_Man_t * p, int v ) { return Gli_ManObj( p, Vec_IntEntry(p->vCos,v) ); } static inline Gli_Obj_t * Gli_ManPi( Gli_Man_t * p, int v ) { assert( v < Gli_ManPiNum(p) ); return Gli_ManCi( p, v ); } static inline Gli_Obj_t * Gli_ManPo( Gli_Man_t * p, int v ) { assert( v < Gli_ManPoNum(p) ); return Gli_ManCo( p, v ); } static inline Gli_Obj_t * Gli_ManRo( Gli_Man_t * p, int v ) { assert( v < Gli_ManRegNum(p) ); return Gli_ManCi( p, Gli_ManRegNum(p)+v ); } static inline Gli_Obj_t * Gli_ManRi( Gli_Man_t * p, int v ) { assert( v < Gli_ManRegNum(p) ); return Gli_ManCo( p, Gli_ManRegNum(p)+v ); } static inline int Gli_ObjIsTerm( Gli_Obj_t * pObj ) { return pObj->fTerm; } static inline int Gli_ObjIsCi( Gli_Obj_t * pObj ) { return pObj->fTerm && pObj->nFanins == 0; } static inline int Gli_ObjIsCo( Gli_Obj_t * pObj ) { return pObj->fTerm && pObj->nFanins == 1; } static inline int Gli_ObjIsNode( Gli_Obj_t * pObj ) { return!pObj->fTerm; } static inline int Gli_ObjFaninNum( Gli_Obj_t * pObj ) { return pObj->nFanins; } static inline int Gli_ObjFanoutNum( Gli_Obj_t * pObj ) { return pObj->nFanouts; } static inline int Gli_ObjSize( Gli_Obj_t * pObj ) { return sizeof(Gli_Obj_t) / 4 + pObj->nFanins + pObj->nFanouts; } static inline Gli_Obj_t * Gli_ObjFanin( Gli_Obj_t * pObj, int i ) { return (Gli_Obj_t *)(((int *)pObj) - pObj->Fanios[i]); } static inline Gli_Obj_t * Gli_ObjFanout( Gli_Obj_t * pObj, int i ) { return (Gli_Obj_t *)(((int *)pObj) + pObj->Fanios[pObj->nFanins+i]); } #define Gli_ManForEachObj( p, pObj, i ) \ for ( i = 0; (i < p->nObjData) && (pObj = Gli_ManObj(p,i)); i += Gli_ObjSize(pObj) ) #define Gli_ManForEachNode( p, pObj, i ) \ for ( i = 0; (i < p->nObjData) && (pObj = Gli_ManObj(p,i)); i += Gli_ObjSize(pObj) ) if ( Gli_ObjIsTerm(pObj) ) {} else #define Gli_ManForEachEntry( vVec, p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && (pObj = Gli_ManObj(p,Vec_IntEntry(vVec,i))); i++ ) #define Gli_ManForEachCi( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(p->vCis)) && (pObj = Gli_ManObj(p,Vec_IntEntry(p->vCis,i))); i++ ) #define Gli_ManForEachCo( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(p->vCos)) && (pObj = Gli_ManObj(p,Vec_IntEntry(p->vCos,i))); i++ ) #define Gli_ManForEachPi( p, pObj, i ) \ for ( i = 0; (i < Gli_ManPiNum(p)) && ((pObj) = Gli_ManCi(p, i)); i++ ) #define Gli_ManForEachPo( p, pObj, i ) \ for ( i = 0; (i < Gli_ManPoNum(p)) && ((pObj) = Gli_ManCo(p, i)); i++ ) #define Gli_ManForEachRo( p, pObj, i ) \ for ( i = 0; (i < Gli_ManRegNum(p)) && ((pObj) = Gli_ManCi(p, Gli_ManPiNum(p)+i)); i++ ) #define Gli_ManForEachRi( p, pObj, i ) \ for ( i = 0; (i < Gli_ManRegNum(p)) && ((pObj) = Gli_ManCo(p, Gli_ManPoNum(p)+i)); i++ ) #define Gli_ManForEachRiRo( p, pObjRi, pObjRo, i ) \ for ( i = 0; (i < Gli_ManRegNum(p)) && ((pObjRi) = Gli_ManCo(p, Gli_ManPoNum(p)+i)) && ((pObjRo) = Gli_ManCi(p, Gli_ManPiNum(p)+i)); i++ ) #define Gli_ObjForEachFanin( pObj, pNext, i ) \ for ( i = 0; (i < (int)pObj->nFanins) && (pNext = Gli_ObjFanin(pObj,i)); i++ ) #define Gli_ObjForEachFanout( pObj, pNext, i ) \ for ( i = 0; (i < (int)pObj->nFanouts) && (pNext = Gli_ObjFanout(pObj,i)); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates logic network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gli_Man_t * Gli_ManAlloc( int nObjs, int nRegs, int nFanioPairs ) { Gli_Man_t * p; p = (Gli_Man_t *)ABC_CALLOC( int, (sizeof(Gli_Man_t) / 4) + (sizeof(Gli_Obj_t) / 4) * nObjs + 2 * nFanioPairs ); p->nRegs = nRegs; p->vCis = Vec_IntAlloc( 1000 ); p->vCos = Vec_IntAlloc( 1000 ); p->vCisChanged = Vec_IntAlloc( 1000 ); p->vAffected = Vec_IntAlloc( 1000 ); p->vFrontier = Vec_IntAlloc( 1000 ); p->nObjData = (sizeof(Gli_Obj_t) / 4) * nObjs + 2 * nFanioPairs; p->pObjData = (int *)(p + 1); return p; } /**Function************************************************************* Synopsis [Deletes logic network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gli_ManStop( Gli_Man_t * p ) { Vec_IntFree( p->vCis ); Vec_IntFree( p->vCos ); Vec_IntFree( p->vCisChanged ); Vec_IntFree( p->vAffected ); Vec_IntFree( p->vFrontier ); ABC_FREE( p->pSimInfoPrev ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Checks logic network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gli_ManPrintObjects( Gli_Man_t * p ) { Gli_Obj_t * pObj, * pNext; int i, k; Gli_ManForEachObj( p, pObj, i ) { printf( "Node %d \n", pObj->Handle ); printf( "Fanins: " ); Gli_ObjForEachFanin( pObj, pNext, k ) printf( "%d ", pNext->Handle ); printf( "\n" ); printf( "Fanouts: " ); Gli_ObjForEachFanout( pObj, pNext, k ) printf( "%d ", pNext->Handle ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Checks logic network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gli_ManFinalize( Gli_Man_t * p ) { Gli_Obj_t * pObj; int i; assert( p->iObjData == p->nObjData ); Gli_ManForEachObj( p, pObj, i ) { assert( pObj->iFanin == (int)pObj->nFanins ); assert( pObj->iFanout == (int)pObj->nFanouts ); pObj->iFanin = 0; pObj->iFanout = 0; } } /**Function************************************************************* Synopsis [Creates fanin/fanout pair.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gli_ObjAddFanin( Gli_Obj_t * pObj, Gli_Obj_t * pFanin ) { assert( pObj->iFanin < (int)pObj->nFanins ); assert( pFanin->iFanout < (int)pFanin->nFanouts ); pFanin->Fanios[pFanin->nFanins + pFanin->iFanout++] = pObj->Fanios[pObj->iFanin++] = pObj->Handle - pFanin->Handle; } /**Function************************************************************* Synopsis [Allocates object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gli_Obj_t * Gli_ObjAlloc( Gli_Man_t * p, int nFanins, int nFanouts ) { Gli_Obj_t * pObj; pObj = Gli_ManObj( p, p->iObjData ); pObj->Handle = p->iObjData; pObj->nFanins = nFanins; pObj->nFanouts = nFanouts; p->iObjData += Gli_ObjSize( pObj ); p->nObjs++; return pObj; } /**Function************************************************************* Synopsis [Creates CI.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gli_ManCreateCi( Gli_Man_t * p, int nFanouts ) { Gli_Obj_t * pObj; pObj = Gli_ObjAlloc( p, 0, nFanouts ); pObj->fTerm = 1; Vec_IntPush( p->vCis, pObj->Handle ); return pObj->Handle; } /**Function************************************************************* Synopsis [Creates CO.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gli_ManCreateCo( Gli_Man_t * p, int iFanin ) { Gli_Obj_t * pObj, * pFanin; pObj = Gli_ObjAlloc( p, 1, 0 ); pObj->fTerm = 1; pFanin = Gli_ManObj( p, iFanin ); Gli_ObjAddFanin( pObj, pFanin ); pObj->fPhase = pObj->fPhase2 = pFanin->fPhase; Vec_IntPush( p->vCos, pObj->Handle ); return pObj->Handle; } /**Function************************************************************* Synopsis [Creates node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gli_NodeComputeValue( Gli_Obj_t * pNode ) { int i, Phase = 0; for ( i = 0; i < (int)pNode->nFanins; i++ ) Phase |= (Gli_ObjFanin(pNode, i)->fPhase << i); return Abc_InfoHasBit( (unsigned *)pNode->pTruth, Phase ); } /**Function************************************************************* Synopsis [Creates node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gli_NodeComputeValue2( Gli_Obj_t * pNode ) { int i, Phase = 0; for ( i = 0; i < (int)pNode->nFanins; i++ ) Phase |= (Gli_ObjFanin(pNode, i)->fPhase2 << i); return Abc_InfoHasBit( (unsigned *)pNode->pTruth, Phase ); } /**Function************************************************************* Synopsis [Creates node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gli_ManCreateNode( Gli_Man_t * p, Vec_Int_t * vFanins, int nFanouts, word * pGateTruth ) { Gli_Obj_t * pObj, * pFanin; int i; assert( Vec_IntSize(vFanins) <= 16 ); pObj = Gli_ObjAlloc( p, Vec_IntSize(vFanins), nFanouts ); Gli_ManForEachEntry( vFanins, p, pFanin, i ) Gli_ObjAddFanin( pObj, pFanin ); pObj->pTruth = pGateTruth; pObj->fPhase = pObj->fPhase2 = Gli_NodeComputeValue( pObj ); return pObj->Handle; } /**Function************************************************************* Synopsis [Returns the number of switches of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gli_ObjNumSwitches( Gli_Man_t * p, int iNode ) { return Gli_ManObj( p, iNode )->nSwitches; } /**Function************************************************************* Synopsis [Returns the number of glitches of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gli_ObjNumGlitches( Gli_Man_t * p, int iNode ) { return Gli_ManObj( p, iNode )->nGlitches; } /**Function************************************************************* Synopsis [Sets random info at the PIs and collects changed PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gli_ManSetPiRandom( Gli_Man_t * p, float PiTransProb ) { Gli_Obj_t * pObj; float Multi = 1.0 / (1 << 16); int i; assert( 0.0 < PiTransProb && PiTransProb < 1.0 ); Vec_IntClear( p->vCisChanged ); Gli_ManForEachCi( p, pObj, i ) if ( Multi * (Gia_ManRandom(0) & 0xffff) < PiTransProb ) { Vec_IntPush( p->vCisChanged, pObj->Handle ); pObj->fPhase ^= 1; pObj->fPhase2 ^= 1; pObj->nSwitches++; pObj->nGlitches++; } } /**Function************************************************************* Synopsis [Sets random info at the PIs and collects changed PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gli_ManSetPiFromSaved( Gli_Man_t * p, int iBit ) { Gli_Obj_t * pObj; int i; Vec_IntClear( p->vCisChanged ); Gli_ManForEachCi( p, pObj, i ) if ( (p->pSimInfoPrev[i] ^ pObj->uSimInfo) & (1 << iBit) ) { Vec_IntPush( p->vCisChanged, pObj->Handle ); pObj->fPhase ^= 1; pObj->fPhase2 ^= 1; pObj->nSwitches++; pObj->nGlitches++; } } /**Function************************************************************* Synopsis [Computes switching activity of each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gli_ManSwitching( Gli_Man_t * p ) { Gli_Obj_t * pThis; int i; Gli_ManForEachNode( p, pThis, i ) { if ( ((int)pThis->fPhase) == Gli_NodeComputeValue(pThis) ) continue; pThis->fPhase ^= 1; pThis->nSwitches++; } } /**Function************************************************************* Synopsis [Computes glitching activity of each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gli_ManGlitching( Gli_Man_t * p ) { Gli_Obj_t * pThis, * pFanout;//, * pOther = Gli_ManObj(p, 41); int i, k, Handle; // Gli_ManForEachObj( p, pThis, i ) // assert( pThis->fMark == 0 ); // start the array of affected nodes Vec_IntClear( p->vAffected ); Vec_IntForEachEntry( p->vCisChanged, Handle, i ) Vec_IntPush( p->vAffected, Handle ); // iteration propagation while ( Vec_IntSize(p->vAffected) > 0 ) { // compute the frontier Vec_IntClear( p->vFrontier ); Gli_ManForEachEntry( p->vAffected, p, pThis, i ) { Gli_ObjForEachFanout( pThis, pFanout, k ) { if ( Gli_ObjIsCo(pFanout) ) continue; if ( pFanout->fMark ) continue; pFanout->fMark = 1; Vec_IntPush( p->vFrontier, pFanout->Handle ); } } // compute the next set of affected nodes Vec_IntClear( p->vAffected ); Gli_ManForEachEntry( p->vFrontier, p, pThis, i ) { pThis->fMark = 0; if ( ((int)pThis->fPhase2) == Gli_NodeComputeValue2(pThis) ) continue; pThis->fPhase2 ^= 1; pThis->nGlitches++; Vec_IntPush( p->vAffected, pThis->Handle ); } } } /**Function************************************************************* Synopsis [Checks that the resulting values are the same.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gli_ManVerify( Gli_Man_t * p ) { Gli_Obj_t * pObj; int i; Gli_ManForEachObj( p, pObj, i ) { assert( pObj->fPhase == pObj->fPhase2 ); assert( pObj->nGlitches >= pObj->nSwitches ); } } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Gli_ManSimulateSeqNode( Gli_Man_t * p, Gli_Obj_t * pNode ) { unsigned pSimInfos[6], Result = 0; int nFanins = Gli_ObjFaninNum(pNode); int i, k, Phase; Gli_Obj_t * pFanin; assert( nFanins <= 16 ); Gli_ObjForEachFanin( pNode, pFanin, i ) pSimInfos[i] = pFanin->uSimInfo; for ( i = 0; i < 32; i++ ) { Phase = 0; for ( k = 0; k < nFanins; k++ ) if ( (pSimInfos[k] >> i) & 1 ) Phase |= (1 << k); if ( Abc_InfoHasBit( (unsigned *)pNode->pTruth, Phase ) ) Result |= (1 << i); } return Result; } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Gli_ManUpdateRandomInput( unsigned uInfo, float PiTransProb ) { float Multi = 1.0 / (1 << 16); int i; if ( PiTransProb == 0.5 ) return Gia_ManRandom(0); for ( i = 0; i < 32; i++ ) if ( Multi * (Gia_ManRandom(0) & 0xffff) < PiTransProb ) uInfo ^= (1 << i); return uInfo; } /**Function************************************************************* Synopsis [Simulates sequential network randomly for the given number of frames.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gli_ManSimulateSeqPref( Gli_Man_t * p, int nPref ) { Gli_Obj_t * pObj, * pObjRi, * pObjRo; int i, f; // initialize simulation data Gli_ManForEachPi( p, pObj, i ) pObj->uSimInfo = Gli_ManUpdateRandomInput( pObj->uSimInfo, 0.5 ); Gli_ManForEachRo( p, pObj, i ) pObj->uSimInfo = 0; for ( f = 0; f < nPref; f++ ) { // simulate one frame Gli_ManForEachNode( p, pObj, i ) pObj->uSimInfo = Gli_ManSimulateSeqNode( p, pObj ); Gli_ManForEachRi( p, pObj, i ) pObj->uSimInfo = Gli_ObjFanin(pObj, 0)->uSimInfo; // initialize the next frame Gli_ManForEachPi( p, pObj, i ) pObj->uSimInfo = Gli_ManUpdateRandomInput( pObj->uSimInfo, 0.5 ); Gli_ManForEachRiRo( p, pObjRi, pObjRo, i ) pObjRo->uSimInfo = pObjRi->uSimInfo; } // save simulation data after nPref timeframes if ( p->pSimInfoPrev == NULL ) p->pSimInfoPrev = ABC_ALLOC( unsigned, Gli_ManCiNum(p) ); Gli_ManForEachCi( p, pObj, i ) p->pSimInfoPrev[i] = pObj->uSimInfo; } /**Function************************************************************* Synopsis [Initialized object values to be one pattern in the saved data.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gli_ManSetDataSaved( Gli_Man_t * p, int iBit ) { Gli_Obj_t * pObj; int i; Gli_ManForEachCi( p, pObj, i ) pObj->fPhase = pObj->fPhase2 = ((p->pSimInfoPrev[i] >> iBit) & 1); Gli_ManForEachNode( p, pObj, i ) pObj->fPhase = pObj->fPhase2 = Gli_NodeComputeValue( pObj ); } /**Function************************************************************* Synopsis [Sets random info at the PIs and collects changed PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gli_ManSetPiRandomSeq( Gli_Man_t * p, float PiTransProb ) { Gli_Obj_t * pObj, * pObjRi; float Multi = 1.0 / (1 << 16); int i; assert( 0.0 < PiTransProb && PiTransProb < 1.0 ); // transfer data to the COs Gli_ManForEachCo( p, pObj, i ) pObj->fPhase = pObj->fPhase2 = Gli_ObjFanin(pObj, 0)->fPhase; // set changed PIs Vec_IntClear( p->vCisChanged ); Gli_ManForEachPi( p, pObj, i ) if ( Multi * (Gia_ManRandom(0) & 0xffff) < PiTransProb ) { Vec_IntPush( p->vCisChanged, pObj->Handle ); pObj->fPhase ^= 1; pObj->fPhase2 ^= 1; pObj->nSwitches++; pObj->nGlitches++; } // set changed ROs Gli_ManForEachRiRo( p, pObjRi, pObj, i ) if ( pObjRi->fPhase != pObj->fPhase ) { Vec_IntPush( p->vCisChanged, pObj->Handle ); pObj->fPhase ^= 1; pObj->fPhase2 ^= 1; pObj->nSwitches++; pObj->nGlitches++; } } /**Function************************************************************* Synopsis [Computes glitching activity of each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gli_ManSwitchesAndGlitches( Gli_Man_t * p, int nPatterns, float PiTransProb, int fVerbose ) { int i, k; abctime clk = Abc_Clock(); Gia_ManRandom( 1 ); Gli_ManFinalize( p ); if ( p->nRegs == 0 ) { for ( i = 0; i < nPatterns; i++ ) { Gli_ManSetPiRandom( p, PiTransProb ); Gli_ManSwitching( p ); Gli_ManGlitching( p ); // Gli_ManVerify( p ); } } else { int nIters = Abc_BitWordNum(nPatterns); Gli_ManSimulateSeqPref( p, 16 ); for ( i = 0; i < 32; i++ ) { Gli_ManSetDataSaved( p, i ); for ( k = 0; k < nIters; k++ ) { Gli_ManSetPiRandomSeq( p, PiTransProb ); Gli_ManSwitching( p ); Gli_ManGlitching( p ); // Gli_ManVerify( p ); } } } if ( fVerbose ) { printf( "Simulated %d patterns. Input transition probability %.2f. ", nPatterns, PiTransProb ); ABC_PRMn( "Memory", 4*p->nObjData ); ABC_PRT( "Time", Abc_Clock() - clk ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaHash.c000066400000000000000000001134641477524141600160100ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaHash.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Structural hashing.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaHash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the place where this node is stored (or should be stored).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManHashOne( int iLit0, int iLit1, int iLitC, int TableSize ) { unsigned Key = iLitC * 2011; Key += Abc_Lit2Var(iLit0) * 7937; Key += Abc_Lit2Var(iLit1) * 2971; Key += Abc_LitIsCompl(iLit0) * 911; Key += Abc_LitIsCompl(iLit1) * 353; return (int)(Key % TableSize); } static inline int * Gia_ManHashFind( Gia_Man_t * p, int iLit0, int iLit1, int iLitC ) { int iThis, * pPlace = Vec_IntEntryP( &p->vHTable, Gia_ManHashOne( iLit0, iLit1, iLitC, Vec_IntSize(&p->vHTable) ) ); assert( Vec_IntSize(&p->vHash) == Gia_ManObjNum(p) ); assert( p->pMuxes || iLit0 < iLit1 ); assert( iLit0 < iLit1 || (!Abc_LitIsCompl(iLit0) && !Abc_LitIsCompl(iLit1)) ); assert( iLitC == -1 || !Abc_LitIsCompl(iLit1) ); for ( ; (iThis = *pPlace); pPlace = Vec_IntEntryP(&p->vHash, iThis) ) { Gia_Obj_t * pThis = Gia_ManObj( p, iThis ); if ( Gia_ObjFaninLit0(pThis, iThis) == iLit0 && Gia_ObjFaninLit1(pThis, iThis) == iLit1 && (p->pMuxes == NULL || Gia_ObjFaninLit2p(p, pThis) == iLitC) ) break; } return pPlace; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManHashLookupInt( Gia_Man_t * p, int iLit0, int iLit1 ) { if ( iLit0 > iLit1 ) iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1; return Abc_Var2Lit( *Gia_ManHashFind( p, iLit0, iLit1, -1 ), 0 ); } int Gia_ManHashLookup( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 ) { int iLit0 = Gia_ObjToLit( p, p0 ); int iLit1 = Gia_ObjToLit( p, p1 ); return Gia_ManHashLookupInt( p, iLit0, iLit1 ); } /**Function************************************************************* Synopsis [Starts the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManHashAlloc( Gia_Man_t * p ) { assert( Vec_IntSize(&p->vHTable) == 0 ); Vec_IntFill( &p->vHTable, Abc_PrimeCudd( Gia_ManAndNum(p) ? Gia_ManAndNum(p) + 1000 : p->nObjsAlloc ), 0 ); Vec_IntGrow( &p->vHash, Abc_MaxInt(Vec_IntSize(&p->vHTable), Gia_ManObjNum(p)) ); Vec_IntFill( &p->vHash, Gia_ManObjNum(p), 0 ); //printf( "Alloced table with %d entries.\n", Vec_IntSize(&p->vHTable) ); } /**Function************************************************************* Synopsis [Starts the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManHashStart( Gia_Man_t * p ) { Gia_Obj_t * pObj; int * pPlace, i; Gia_ManHashAlloc( p ); Gia_ManForEachAnd( p, pObj, i ) { pPlace = Gia_ManHashFind( p, Gia_ObjFaninLit0(pObj, i), Gia_ObjFaninLit1(pObj, i), Gia_ObjFaninLit2(p, i) ); assert( *pPlace == 0 ); *pPlace = i; } } /**Function************************************************************* Synopsis [Stops the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManHashStop( Gia_Man_t * p ) { Vec_IntErase( &p->vHTable ); Vec_IntErase( &p->vHash ); } /**Function************************************************************* Synopsis [Resizes the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManHashResize( Gia_Man_t * p ) { int i, iThis, iNext, Counter, Counter2, * pPlace; Vec_Int_t vOld = p->vHTable; assert( Vec_IntSize(&vOld) > 0 ); // replace the table Vec_IntZero( &p->vHTable ); Vec_IntFill( &p->vHTable, Abc_PrimeCudd( 2 * Gia_ManAndNum(p) ), 0 ); // rehash the entries from the old table Counter = 0; Vec_IntForEachEntry( &vOld, iThis, i ) for ( iNext = Vec_IntEntry(&p->vHash, iThis); iThis; iThis = iNext, iNext = Vec_IntEntry(&p->vHash, iThis) ) { Gia_Obj_t * pThis0 = Gia_ManObj( p, iThis ); Vec_IntWriteEntry( &p->vHash, iThis, 0 ); pPlace = Gia_ManHashFind( p, Gia_ObjFaninLit0(pThis0, iThis), Gia_ObjFaninLit1(pThis0, iThis), Gia_ObjFaninLit2p(p, pThis0) ); assert( *pPlace == 0 ); // should not be there *pPlace = iThis; assert( *pPlace != 0 ); Counter++; } Counter2 = Gia_ManAndNum(p) - Gia_ManBufNum(p); assert( Counter == Counter2 ); // if ( p->fVerbose ) // printf( "Resizing GIA hash table: %d -> %d.\n", Vec_IntSize(&vOld), Vec_IntSize(&p->vHTable) ); Vec_IntErase( &vOld ); } /**Function******************************************************************** Synopsis [Profiles the hash table.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Gia_ManHashProfile( Gia_Man_t * p ) { int iEntry; int i, Counter, Limit; printf( "Table size = %d. Entries = %d. ", Vec_IntSize(&p->vHTable), Gia_ManAndNum(p) ); printf( "Hits = %d. Misses = %d.\n", (int)p->nHashHit, (int)p->nHashMiss ); Limit = Abc_MinInt( 1000, Vec_IntSize(&p->vHTable) ); for ( i = 0; i < Limit; i++ ) { Counter = 0; for ( iEntry = Vec_IntEntry(&p->vHTable, i); iEntry; iEntry = iEntry? Vec_IntEntry(&p->vHash, iEntry) : 0 ) Counter++; if ( Counter ) printf( "%d ", Counter ); } printf( "\n" ); } /**Function************************************************************* Synopsis [Recognizes what nodes are control and data inputs of a MUX.] Description [If the node is a MUX, returns the control variable C. Assigns nodes T and E to be the then and else variables of the MUX. Node C is never complemented. Nodes T and E can be complemented. This function also recognizes EXOR/NEXOR gates as MUXes.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_Obj_t * Gia_ObjRecognizeMuxTwo( Gia_Obj_t * pNode0, Gia_Obj_t * pNode1, Gia_Obj_t ** ppNodeT, Gia_Obj_t ** ppNodeE ) { assert( !Gia_IsComplement(pNode0) ); assert( !Gia_IsComplement(pNode1) ); // find the control variable if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1)) ) { // if ( FrGia_IsComplement(pNode1->p2) ) if ( Gia_ObjFaninC1(pNode0) ) { // pNode2->p2 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); *ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); return Gia_ObjChild1(pNode1);//pNode2->p2; } else { // pNode1->p2 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); *ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); return Gia_ObjChild1(pNode0);//pNode1->p2; } } else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1)) ) { // if ( FrGia_IsComplement(pNode1->p1) ) if ( Gia_ObjFaninC0(pNode0) ) { // pNode2->p1 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); *ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); return Gia_ObjChild0(pNode1);//pNode2->p1; } else { // pNode1->p1 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); *ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); return Gia_ObjChild0(pNode0);//pNode1->p1; } } else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1)) ) { // if ( FrGia_IsComplement(pNode1->p1) ) if ( Gia_ObjFaninC0(pNode0) ) { // pNode2->p2 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); *ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); return Gia_ObjChild1(pNode1);//pNode2->p2; } else { // pNode1->p1 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); *ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); return Gia_ObjChild0(pNode0);//pNode1->p1; } } else if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1)) ) { // if ( FrGia_IsComplement(pNode1->p2) ) if ( Gia_ObjFaninC1(pNode0) ) { // pNode2->p1 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); *ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); return Gia_ObjChild0(pNode1);//pNode2->p1; } else { // pNode1->p2 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); *ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); return Gia_ObjChild1(pNode0);//pNode1->p2; } } assert( 0 ); // this is not MUX return NULL; } /**Function************************************************************* Synopsis [Rehashes AIG with mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_Obj_t * Gia_ManHashAndP( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 ) { return Gia_ObjFromLit( p, Gia_ManHashAnd( p, Gia_ObjToLit(p, p0), Gia_ObjToLit(p, p1) ) ); } /**Function************************************************************* Synopsis [Rehashes AIG with mapping.] Description [http://fmv.jku.at/papers/BrummayerBiere-MEMICS06.pdf] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Gia_Obj_t * Gia_ManAddStrash( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 ) { Gia_Obj_t * pNode0, * pNode1, * pFanA, * pFanB, * pFanC, * pFanD; assert( p->fAddStrash ); pNode0 = Gia_Regular(p0); pNode1 = Gia_Regular(p1); if ( !Gia_ObjIsAnd(pNode0) && !Gia_ObjIsAnd(pNode1) ) return NULL; pFanA = Gia_ObjIsAnd(pNode0) ? Gia_ObjChild0(pNode0) : NULL; pFanB = Gia_ObjIsAnd(pNode0) ? Gia_ObjChild1(pNode0) : NULL; pFanC = Gia_ObjIsAnd(pNode1) ? Gia_ObjChild0(pNode1) : NULL; pFanD = Gia_ObjIsAnd(pNode1) ? Gia_ObjChild1(pNode1) : NULL; if ( Gia_IsComplement(p0) ) { if ( pFanA == Gia_Not(p1) || pFanB == Gia_Not(p1) ) return p1; if ( pFanB == p1 ) return Gia_ManHashAndP( p, Gia_Not(pFanA), pFanB ); if ( pFanA == p1 ) return Gia_ManHashAndP( p, Gia_Not(pFanB), pFanA ); } else { if ( pFanA == Gia_Not(p1) || pFanB == Gia_Not(p1) ) return Gia_ManConst0(p); if ( pFanA == p1 || pFanB == p1 ) return p0; } if ( Gia_IsComplement(p1) ) { if ( pFanC == Gia_Not(p0) || pFanD == Gia_Not(p0) ) return p0; if ( pFanD == p0 ) return Gia_ManHashAndP( p, Gia_Not(pFanC), pFanD ); if ( pFanC == p0 ) return Gia_ManHashAndP( p, Gia_Not(pFanD), pFanC ); } else { if ( pFanC == Gia_Not(p0) || pFanD == Gia_Not(p0) ) return Gia_ManConst0(p); if ( pFanC == p0 || pFanD == p0 ) return p1; } if ( !Gia_IsComplement(p0) && !Gia_IsComplement(p1) ) { if ( pFanA == Gia_Not(pFanC) || pFanA == Gia_Not(pFanD) || pFanB == Gia_Not(pFanC) || pFanB == Gia_Not(pFanD) ) return Gia_ManConst0(p); if ( pFanA == pFanC || pFanB == pFanC ) return Gia_ManHashAndP( p, p0, pFanD ); if ( pFanB == pFanC || pFanB == pFanD ) return Gia_ManHashAndP( p, pFanA, p1 ); if ( pFanA == pFanD || pFanB == pFanD ) return Gia_ManHashAndP( p, p0, pFanC ); if ( pFanA == pFanC || pFanA == pFanD ) return Gia_ManHashAndP( p, pFanB, p1 ); } else if ( Gia_IsComplement(p0) && !Gia_IsComplement(p1) ) { if ( pFanA == Gia_Not(pFanC) || pFanA == Gia_Not(pFanD) || pFanB == Gia_Not(pFanC) || pFanB == Gia_Not(pFanD) ) return p1; if ( pFanB == pFanC || pFanB == pFanD ) return Gia_ManHashAndP( p, Gia_Not(pFanA), p1 ); if ( pFanA == pFanC || pFanA == pFanD ) return Gia_ManHashAndP( p, Gia_Not(pFanB), p1 ); } else if ( !Gia_IsComplement(p0) && Gia_IsComplement(p1) ) { if ( pFanC == Gia_Not(pFanA) || pFanC == Gia_Not(pFanB) || pFanD == Gia_Not(pFanA) || pFanD == Gia_Not(pFanB) ) return p0; if ( pFanD == pFanA || pFanD == pFanB ) return Gia_ManHashAndP( p, Gia_Not(pFanC), p0 ); if ( pFanC == pFanA || pFanC == pFanB ) return Gia_ManHashAndP( p, Gia_Not(pFanD), p0 ); } else // if ( Gia_IsComplement(p0) && Gia_IsComplement(p1) ) { if ( pFanA == pFanD && pFanB == Gia_Not(pFanC) ) return Gia_Not(pFanA); if ( pFanB == pFanC && pFanA == Gia_Not(pFanD) ) return Gia_Not(pFanB); if ( pFanA == pFanC && pFanB == Gia_Not(pFanD) ) return Gia_Not(pFanA); if ( pFanB == pFanD && pFanA == Gia_Not(pFanC) ) return Gia_Not(pFanB); } /* if ( !Gia_IsComplement(p0) || !Gia_IsComplement(p1) ) return NULL; if ( !Gia_ObjIsAnd(pNode0) || !Gia_ObjIsAnd(pNode1) ) return NULL; if ( (Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1))) || (Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1))) || (Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1))) || (Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1))) ) { Gia_Obj_t * pNodeC, * pNodeT, * pNodeE; int fCompl; pNodeC = Gia_ObjRecognizeMuxTwo( pNode0, pNode1, &pNodeT, &pNodeE ); // using non-standard canonical rule for MUX (d0 is not compl; d1 may be compl) if ( (fCompl = Gia_IsComplement(pNodeE)) ) { pNodeE = Gia_Not(pNodeE); pNodeT = Gia_Not(pNodeT); } pNode0 = Gia_ManHashAndP( p, Gia_Not(pNodeC), pNodeE ); pNode1 = Gia_ManHashAndP( p, pNodeC, pNodeT ); p->fAddStrash = 0; pNodeC = Gia_NotCond( Gia_ManHashAndP( p, Gia_Not(pNode0), Gia_Not(pNode1) ), !fCompl ); p->fAddStrash = 1; return pNodeC; } */ return NULL; } /**Function************************************************************* Synopsis [Hashes XOR gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManHashXorReal( Gia_Man_t * p, int iLit0, int iLit1 ) { int fCompl = 0; assert( p->fAddStrash == 0 ); 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; if ( (p->nObjs & 0xFF) == 0 && 2 * Vec_IntSize(&p->vHTable) < Gia_ManAndNum(p) ) Gia_ManHashResize( p ); if ( iLit0 < iLit1 ) iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1; if ( Abc_LitIsCompl(iLit0) ) iLit0 = Abc_LitNot(iLit0), fCompl ^= 1; if ( Abc_LitIsCompl(iLit1) ) iLit1 = Abc_LitNot(iLit1), fCompl ^= 1; { int *pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 ); if ( *pPlace ) { p->nHashHit++; return Abc_Var2Lit( *pPlace, fCompl ); } p->nHashMiss++; if ( Vec_IntSize(&p->vHash) < Vec_IntCap(&p->vHash) ) *pPlace = Abc_Lit2Var( Gia_ManAppendXorReal( p, iLit0, iLit1 ) ); else { int iNode = Gia_ManAppendXorReal( p, iLit0, iLit1 ); pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 ); assert( *pPlace == 0 ); *pPlace = Abc_Lit2Var( iNode ); } return Abc_Var2Lit( *pPlace, fCompl ); } } /**Function************************************************************* Synopsis [Hashes MUX gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManHashMuxReal( Gia_Man_t * p, int iLitC, int iLit1, int iLit0 ) { int fCompl = 0; assert( p->fAddStrash == 0 ); if ( iLitC < 2 ) return iLitC ? iLit1 : iLit0; if ( iLit0 < 2 ) return iLit0 ? Gia_ManHashOr(p, Abc_LitNot(iLitC), iLit1) : Gia_ManHashAnd(p, iLitC, iLit1); if ( iLit1 < 2 ) return iLit1 ? Gia_ManHashOr(p, iLitC, iLit0) : Gia_ManHashAnd(p, Abc_LitNot(iLitC), iLit0); assert( iLit0 > 1 && iLit1 > 1 && iLitC > 1 ); if ( iLit0 == iLit1 ) return iLit0; if ( iLitC == iLit0 || iLitC == Abc_LitNot(iLit1) ) return Gia_ManHashAnd(p, iLit0, iLit1); if ( iLitC == iLit1 || iLitC == Abc_LitNot(iLit0) ) return Gia_ManHashOr(p, iLit0, iLit1); if ( Abc_Lit2Var(iLit0) == Abc_Lit2Var(iLit1) ) return Gia_ManHashXorReal( p, iLitC, iLit0 ); if ( iLit0 > iLit1 ) iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1, iLitC = Abc_LitNot(iLitC); if ( Abc_LitIsCompl(iLit1) ) iLit0 = Abc_LitNot(iLit0), iLit1 = Abc_LitNot(iLit1), fCompl = 1; { int *pPlace = Gia_ManHashFind( p, iLit0, iLit1, iLitC ); if ( *pPlace ) { p->nHashHit++; return Abc_Var2Lit( *pPlace, fCompl ); } p->nHashMiss++; if ( Vec_IntSize(&p->vHash) < Vec_IntCap(&p->vHash) ) *pPlace = Abc_Lit2Var( Gia_ManAppendMuxReal( p, iLitC, iLit1, iLit0 ) ); else { int iNode = Gia_ManAppendMuxReal( p, iLitC, iLit1, iLit0 ); pPlace = Gia_ManHashFind( p, iLit0, iLit1, iLitC ); assert( *pPlace == 0 ); *pPlace = Abc_Lit2Var( iNode ); } return Abc_Var2Lit( *pPlace, fCompl ); } } /**Function************************************************************* Synopsis [Hashes AND gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManHashAnd( Gia_Man_t * p, int iLit0, int iLit1 ) { if ( iLit0 < 2 ) return iLit0 ? iLit1 : 0; if ( iLit1 < 2 ) return iLit1 ? iLit0 : 0; if ( iLit0 == iLit1 ) return iLit1; if ( iLit0 == Abc_LitNot(iLit1) ) return 0; if ( p->fGiaSimple ) { assert( Vec_IntSize(&p->vHTable) == 0 ); return Gia_ManAppendAnd( p, iLit0, iLit1 ); } if ( (p->nObjs & 0xFF) == 0 && 2 * Vec_IntSize(&p->vHTable) < Gia_ManAndNum(p) ) Gia_ManHashResize( p ); if ( p->fAddStrash ) { Gia_Obj_t * pObj = Gia_ManAddStrash( p, Gia_ObjFromLit(p, iLit0), Gia_ObjFromLit(p, iLit1) ); if ( pObj != NULL ) return Gia_ObjToLit( p, pObj ); } if ( iLit0 > iLit1 ) iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1; { int * pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 ); if ( *pPlace ) { p->nHashHit++; return Abc_Var2Lit( *pPlace, 0 ); } p->nHashMiss++; if ( Vec_IntSize(&p->vHash) < Vec_IntCap(&p->vHash) ) *pPlace = Abc_Lit2Var( Gia_ManAppendAnd( p, iLit0, iLit1 ) ); else { int iNode = Gia_ManAppendAnd( p, iLit0, iLit1 ); pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 ); assert( *pPlace == 0 ); *pPlace = Abc_Lit2Var( iNode ); } return Abc_Var2Lit( *pPlace, 0 ); } } int Gia_ManHashOr( Gia_Man_t * p, int iLit0, int iLit1 ) { return Abc_LitNot(Gia_ManHashAnd( p, Abc_LitNot(iLit0), Abc_LitNot(iLit1) )); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManHashAndTry( Gia_Man_t * p, int iLit0, int iLit1 ) { if ( iLit0 < 2 ) return iLit0 ? iLit1 : 0; if ( iLit1 < 2 ) return iLit1 ? iLit0 : 0; if ( iLit0 == iLit1 ) return iLit1; if ( iLit0 == Abc_LitNot(iLit1) ) return 0; if ( iLit0 > iLit1 ) iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1; { int * pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 ); if ( *pPlace ) return Abc_Var2Lit( *pPlace, 0 ); return -1; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManHashXor( Gia_Man_t * p, int iLit0, int iLit1 ) { if ( p->fGiaSimple ) return Gia_ManHashOr(p, Gia_ManHashAnd(p, iLit0, Abc_LitNot(iLit1)), Gia_ManHashAnd(p, Abc_LitNot(iLit0), iLit1) ); else { int fCompl = Abc_LitIsCompl(iLit0) ^ Abc_LitIsCompl(iLit1); int iTemp0 = Gia_ManHashAnd( p, Abc_LitRegular(iLit0), Abc_LitNot(Abc_LitRegular(iLit1)) ); int iTemp1 = Gia_ManHashAnd( p, Abc_LitRegular(iLit1), Abc_LitNot(Abc_LitRegular(iLit0)) ); return Abc_LitNotCond( Gia_ManHashAnd( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), !fCompl ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManHashMux( Gia_Man_t * p, int iCtrl, int iData1, int iData0 ) { if ( p->fGiaSimple ) return Gia_ManHashOr(p, Gia_ManHashAnd(p, iCtrl, iData1), Gia_ManHashAnd(p, Abc_LitNot(iCtrl), iData0) ); else { int iTemp0, iTemp1, fCompl = 0; if ( iData0 > iData1 ) iData0 ^= iData1, iData1 ^= iData0, iData0 ^= iData1, iCtrl = Abc_LitNot(iCtrl); if ( Abc_LitIsCompl(iData1) ) iData0 = Abc_LitNot(iData0), iData1 = Abc_LitNot(iData1), fCompl = 1; iTemp0 = Gia_ManHashAnd( p, Abc_LitNot(iCtrl), iData0 ); iTemp1 = Gia_ManHashAnd( p, iCtrl, iData1 ); return Abc_LitNotCond( Gia_ManHashAnd( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), !fCompl ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManHashMaj( Gia_Man_t * p, int iData0, int iData1, int iData2 ) { int iTemp0 = Gia_ManHashOr( p, iData1, iData2 ); int iTemp1 = Gia_ManHashAnd( p, iData0, iTemp0 ); int iTemp2 = Gia_ManHashAnd( p, iData1, iData2 ); return Gia_ManHashOr( p, iTemp1, iTemp2 ); } /**Function************************************************************* Synopsis [Rehashes AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManRehash( Gia_Man_t * p, int fAddStrash ) { 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 ); pNew->fAddStrash = fAddStrash; Gia_ManHashAlloc( pNew ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObj( 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_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } Gia_ManHashStop( pNew ); pNew->fAddStrash = 0; Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // printf( "Top gate is %s\n", Gia_ObjFaninC0(Gia_ManCo(pNew, 0))? "OR" : "AND" ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Creates well-balanced AND gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManHashAndMulti( Gia_Man_t * p, Vec_Int_t * vLits ) { if ( Vec_IntSize(vLits) == 0 ) return 0; while ( Vec_IntSize(vLits) > 1 ) { int i, k = 0, Lit1, Lit2, LitRes; Vec_IntForEachEntryDouble( vLits, Lit1, Lit2, i ) { LitRes = Gia_ManHashAnd( p, Lit1, Lit2 ); Vec_IntWriteEntry( vLits, k++, LitRes ); } if ( Vec_IntSize(vLits) & 1 ) Vec_IntWriteEntry( vLits, k++, Vec_IntEntryLast(vLits) ); Vec_IntShrink( vLits, k ); } assert( Vec_IntSize(vLits) == 1 ); return Vec_IntEntry(vLits, 0); } int Gia_ManHashAndMulti2( Gia_Man_t * p, Vec_Int_t * vLits ) { int i, iLit, iRes = 1; Vec_IntForEachEntry( vLits, iLit, i ) 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 /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaHcd.c000066400000000000000000000524451477524141600156240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaHcd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [New choice computation package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaHcd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "giaAig.h" #include "aig/aig/aig.h" #include "opt/dar/dar.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // choicing parameters typedef struct Hcd_Pars_t_ Hcd_Pars_t; struct Hcd_Pars_t_ { int nWords; // the number of simulation words int nBTLimit; // conflict limit at a node int nSatVarMax; // the max number of SAT variables int fSynthesis; // set to 1 to perform synthesis int fPolarFlip; // uses polarity adjustment int fSimulateTfo; // uses simulation of TFO classes int fPower; // uses power-aware rewriting int fUseGia; // uses GIA package int fUseCSat; // uses circuit-based solver int fVerbose; // verbose stats clock_t timeSynth; // synthesis runtime int nNodesAhead; // the lookahead in terms of nodes int nCallsRecycle; // calls to perform before recycling SAT solver }; extern void Gia_ComputeEquivalences( Gia_Man_t * pMiter, int nBTLimit, int fUseMiniSat, int fVerbose ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hcd_ManSetDefaultParams( Hcd_Pars_t * p ) { memset( p, 0, sizeof(Hcd_Pars_t) ); p->nWords = 8; // the number of simulation words p->nBTLimit = 1000; // conflict limit at a node p->nSatVarMax = 5000; // the max number of SAT variables p->fSynthesis = 1; // derives three snapshots p->fPolarFlip = 1; // uses polarity adjustment p->fSimulateTfo = 1; // simulate TFO p->fPower = 0; // power-aware rewriting p->fVerbose = 0; // verbose stats p->nNodesAhead = 1000; // the lookahead in terms of nodes p->nCallsRecycle = 100; // calls to perform before recycling SAT solver } /**Function************************************************************* Synopsis [Reproduces script "compress".] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Hcd_Compress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose ) //alias compress2 "b -l; rw -l; rwz -l; b -l; rwz -l; b -l" { Aig_Man_t * pTemp; Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr; Dar_RefPar_t ParsRef, * pParsRef = &ParsRef; Dar_ManDefaultRwrParams( pParsRwr ); Dar_ManDefaultRefParams( pParsRef ); pParsRwr->fUpdateLevel = fUpdateLevel; pParsRef->fUpdateLevel = fUpdateLevel; pParsRwr->fPower = fPower; pParsRwr->fVerbose = 0;//fVerbose; pParsRef->fVerbose = 0;//fVerbose; // pAig = Aig_ManDupDfs( pAig ); if ( fVerbose ) Aig_ManPrintStats( pAig ); // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) Aig_ManPrintStats( pAig ); // refactor Dar_ManRefactor( pAig, pParsRef ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) Aig_ManPrintStats( pAig ); // balance if ( fBalance ) { pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); Aig_ManStop( pTemp ); if ( fVerbose ) Aig_ManPrintStats( pAig ); } pParsRwr->fUseZeros = 1; pParsRef->fUseZeros = 1; // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) Aig_ManPrintStats( pAig ); return pAig; } /**Function************************************************************* Synopsis [Reproduces script "compress2".] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Hcd_Compress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose ) //alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l" { Aig_Man_t * pTemp; Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr; Dar_RefPar_t ParsRef, * pParsRef = &ParsRef; Dar_ManDefaultRwrParams( pParsRwr ); Dar_ManDefaultRefParams( pParsRef ); pParsRwr->fUpdateLevel = fUpdateLevel; pParsRef->fUpdateLevel = fUpdateLevel; pParsRwr->fFanout = fFanout; pParsRwr->fPower = fPower; pParsRwr->fVerbose = 0;//fVerbose; pParsRef->fVerbose = 0;//fVerbose; // pAig = Aig_ManDupDfs( pAig ); if ( fVerbose ) Aig_ManPrintStats( pAig ); // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) Aig_ManPrintStats( pAig ); // refactor Dar_ManRefactor( pAig, pParsRef ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) Aig_ManPrintStats( pAig ); // balance // if ( fBalance ) { pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); Aig_ManStop( pTemp ); if ( fVerbose ) Aig_ManPrintStats( pAig ); } // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) Aig_ManPrintStats( pAig ); pParsRwr->fUseZeros = 1; pParsRef->fUseZeros = 1; // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) Aig_ManPrintStats( pAig ); // balance if ( fBalance ) { pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); Aig_ManStop( pTemp ); if ( fVerbose ) Aig_ManPrintStats( pAig ); } // refactor Dar_ManRefactor( pAig, pParsRef ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) Aig_ManPrintStats( pAig ); // rewrite Dar_ManRewrite( pAig, pParsRwr ); pAig = Aig_ManDupDfs( pTemp = pAig ); Aig_ManStop( pTemp ); if ( fVerbose ) Aig_ManPrintStats( pAig ); // balance if ( fBalance ) { pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); Aig_ManStop( pTemp ); if ( fVerbose ) Aig_ManPrintStats( pAig ); } return pAig; } /**Function************************************************************* Synopsis [Reproduces script "compress2".] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Hcd_ChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose ) //alias resyn "b; rw; rwz; b; rwz; b" //alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b" { Vec_Ptr_t * vGias; Gia_Man_t * pGia; vGias = Vec_PtrAlloc( 3 ); pGia = Gia_ManFromAig(pAig); Vec_PtrPush( vGias, pGia ); pAig = Hcd_Compress( pAig, fBalance, fUpdateLevel, fPower, fVerbose ); pGia = Gia_ManFromAig(pAig); Vec_PtrPush( vGias, pGia ); //Aig_ManPrintStats( pAig ); pAig = Hcd_Compress2( pAig, fBalance, fUpdateLevel, 1, fPower, fVerbose ); pGia = Gia_ManFromAig(pAig); Vec_PtrPush( vGias, pGia ); //Aig_ManPrintStats( pAig ); Aig_ManStop( pAig ); return vGias; } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hcd_ManChoiceMiter_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( ~pObj->Value ) return pObj->Value; Hcd_ManChoiceMiter_rec( pNew, p, Gia_ObjFanin0(pObj) ); if ( Gia_ObjIsCo(pObj) ) return pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Hcd_ManChoiceMiter_rec( pNew, p, Gia_ObjFanin1(pObj) ); return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } /**Function************************************************************* Synopsis [Derives the miter of several AIGs for choice computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Hcd_ManChoiceMiter( Vec_Ptr_t * vGias ) { Gia_Man_t * pNew, * pGia, * pGia0; int i, k, iNode, nNodes; // make sure they have equal parameters assert( Vec_PtrSize(vGias) > 0 ); pGia0 = (Gia_Man_t *)Vec_PtrEntry( vGias, 0 ); Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) { assert( Gia_ManCiNum(pGia) == Gia_ManCiNum(pGia0) ); assert( Gia_ManCoNum(pGia) == Gia_ManCoNum(pGia0) ); assert( Gia_ManRegNum(pGia) == Gia_ManRegNum(pGia0) ); Gia_ManFillValue( pGia ); Gia_ManConst0(pGia)->Value = 0; } // start the new manager pNew = Gia_ManStart( Vec_PtrSize(vGias) * Gia_ManObjNum(pGia0) ); pNew->pName = Abc_UtilStrsav( pGia0->pName ); pNew->pSpec = Abc_UtilStrsav( pGia0->pSpec ); // create new CIs and assign them to the old manager CIs for ( k = 0; k < Gia_ManCiNum(pGia0); k++ ) { iNode = Gia_ManAppendCi(pNew); Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) Gia_ManCi( pGia, k )->Value = iNode; } // create internal nodes Gia_ManHashAlloc( pNew ); for ( k = 0; k < Gia_ManCoNum(pGia0); k++ ) { Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) Hcd_ManChoiceMiter_rec( pNew, pGia, Gia_ManCo( pGia, k ) ); } Gia_ManHashStop( pNew ); // check the presence of dangling nodes nNodes = Gia_ManHasDangling( pNew ); assert( nNodes == 0 ); return pNew; } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNode.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hcd_ObjCheckTfi_rec( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode, Vec_Ptr_t * vVisited ) { // check the trivial cases if ( pNode == NULL ) return 0; if ( Gia_ObjIsCi(pNode) ) return 0; // if ( pNode->Id < pOld->Id ) // cannot use because of choices of pNode // return 0; if ( pNode == pOld ) return 1; // skip the visited node if ( pNode->fMark0 ) return 0; pNode->fMark0 = 1; Vec_PtrPush( vVisited, pNode ); // check the children if ( Hcd_ObjCheckTfi_rec( p, pOld, Gia_ObjFanin0(pNode), vVisited ) ) return 1; if ( Hcd_ObjCheckTfi_rec( p, pOld, Gia_ObjFanin1(pNode), vVisited ) ) return 1; // check equivalent nodes return Hcd_ObjCheckTfi_rec( p, pOld, Gia_ObjNextObj(p, Gia_ObjId(p, pNode)), vVisited ); } /**Function************************************************************* Synopsis [Returns 1 if pOld is in the TFI of pNode.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hcd_ObjCheckTfi( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode ) { Vec_Ptr_t * vVisited; Gia_Obj_t * pObj; int RetValue, i; assert( !Gia_IsComplement(pOld) ); assert( !Gia_IsComplement(pNode) ); vVisited = Vec_PtrAlloc( 100 ); RetValue = Hcd_ObjCheckTfi_rec( p, pOld, pNode, vVisited ); Vec_PtrForEachEntry( Gia_Obj_t *, vVisited, pObj, i ) pObj->fMark0 = 0; Vec_PtrFree( vVisited ); return RetValue; } /**Function************************************************************* Synopsis [Adds the next entry while making choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hcd_ManAddNextEntry_rec( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode ) { if ( Gia_ObjNext(p, Gia_ObjId(p, pOld)) == 0 ) { Gia_ObjSetNext( p, Gia_ObjId(p, pOld), Gia_ObjId(p, pNode) ); return; } Hcd_ManAddNextEntry_rec( p, Gia_ObjNextObj(p, Gia_ObjId(p, pOld)), pNode ); } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hcd_ManEquivToChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pRepr, * pReprNew, * pObjNew; if ( ~pObj->Value ) return; if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) { if ( Gia_ObjIsConst0(pRepr) ) { pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); return; } Hcd_ManEquivToChoices_rec( pNew, p, pRepr ); assert( Gia_ObjIsAnd(pObj) ); Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin1(pObj) ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( Abc_LitRegular(pObj->Value) == Abc_LitRegular(pRepr->Value) ) { assert( (int)pObj->Value == Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ) ); return; } if ( pRepr->Value > pObj->Value ) // should never happen with high resource limit return; assert( pRepr->Value < pObj->Value ); pReprNew = Gia_ManObj( pNew, Abc_Lit2Var(pRepr->Value) ); pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); if ( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) ) { assert( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) == pReprNew ); pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); return; } if ( !Hcd_ObjCheckTfi( pNew, pReprNew, pObjNew ) ) { assert( Gia_ObjNext(pNew, Gia_ObjId(pNew, pObjNew)) == 0 ); Gia_ObjSetRepr( pNew, Gia_ObjId(pNew, pObjNew), Gia_ObjId(pNew, pReprNew) ); Hcd_ManAddNextEntry_rec( pNew, pReprNew, pObjNew ); } pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin1(pObj) ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } /**Function************************************************************* Synopsis [Removes choices, which contain fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hcd_ManRemoveBadChoices( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, iObj, iPrev, Counter = 0; // mark nodes with fanout Gia_ManForEachObj( p, pObj, i ) { pObj->fMark0 = 0; if ( Gia_ObjIsAnd(pObj) ) { Gia_ObjFanin0(pObj)->fMark0 = 1; Gia_ObjFanin1(pObj)->fMark0 = 1; } else if ( Gia_ObjIsCo(pObj) ) Gia_ObjFanin0(pObj)->fMark0 = 1; } // go through the classes and remove Gia_ManForEachClass( p, i ) { for ( iPrev = i, iObj = Gia_ObjNext(p, i); iObj; iObj = Gia_ObjNext(p, iPrev) ) { if ( !Gia_ManObj(p, iObj)->fMark0 ) { iPrev = iObj; continue; } Gia_ObjSetRepr( p, iObj, GIA_VOID ); Gia_ObjSetNext( p, iPrev, Gia_ObjNext(p, iObj) ); Gia_ObjSetNext( p, iObj, 0 ); Counter++; } } // remove the marks Gia_ManCleanMark0( p ); // printf( "Removed %d bad choices.\n", Counter ); } /**Function************************************************************* Synopsis [Reduces AIG using equivalence classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Hcd_ManEquivToChoices( Gia_Man_t * p, int nSnapshots ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pRepr; int i; assert( (Gia_ManCoNum(p) % nSnapshots) == 0 ); Gia_ManSetPhase( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); 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 ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManForEachRo( p, pObj, i ) if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) { assert( Gia_ObjIsConst0(pRepr) || Gia_ObjIsRo(p, pRepr) ); pObj->Value = pRepr->Value; } Gia_ManHashAlloc( pNew ); Gia_ManForEachCo( p, pObj, i ) Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); Gia_ManForEachCo( p, pObj, i ) if ( i % nSnapshots == 0 ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); Hcd_ManRemoveBadChoices( pNew ); // Gia_ManEquivPrintClasses( pNew, 0, 0 ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); // Gia_ManEquivPrintClasses( pNew, 0, 0 ); return pNew; } /**Function************************************************************* Synopsis [Performs computation of AIGs with choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Hcd_ComputeChoices( Aig_Man_t * pAig, int nBTLimit, int fSynthesis, int fUseMiniSat, int fVerbose ) { Vec_Ptr_t * vGias; Gia_Man_t * pGia, * pMiter; Aig_Man_t * pAigNew; int i; clock_t clk = clock(); // perform synthesis if ( fSynthesis ) { vGias = Hcd_ChoiceSynthesis( Aig_ManDupDfs(pAig), 1, 1, 0, 0 ); if ( fVerbose ) ABC_PRT( "Synthesis time", clock() - clk ); // create choices clk = clock(); pMiter = Hcd_ManChoiceMiter( vGias ); Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) Gia_ManStop( pGia ); Gia_AigerWrite( pMiter, "m3.aig", 0, 0, 0 ); } else { vGias = Vec_PtrStart( 3 ); pMiter = Gia_ManFromAig(pAig); } // perform choicing Gia_ComputeEquivalences( pMiter, nBTLimit, fUseMiniSat, fVerbose ); // derive AIG with choices pGia = Hcd_ManEquivToChoices( pMiter, Vec_PtrSize(vGias) ); Gia_ManSetRegNum( pGia, Aig_ManRegNum(pAig) ); Gia_ManStop( pMiter ); Vec_PtrFree( vGias ); if ( fVerbose ) ABC_PRT( "Choicing time", clock() - clk ); // Gia_ManHasChoices_very_old( pGia ); // transform back pAigNew = Gia_ManToAig( pGia, 1 ); Gia_ManStop( pGia ); if ( fVerbose ) { extern int Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig ); extern int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig ); printf( "Choices : Reprs = %5d. Equivs = %5d. Choices = %5d.\n", Dch_DeriveChoiceCountReprs( pAigNew ), Dch_DeriveChoiceCountEquivs( pAigNew ), Aig_ManChoiceNum( pAigNew ) ); } return pAigNew; } /**Function************************************************************* Synopsis [Performs computation of AIGs with choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hcd_ComputeChoicesTest( Gia_Man_t * pGia, int nBTLimit, int fSynthesis, int fUseMiniSat, int fVerbose ) { Aig_Man_t * pAig, * pAigNew; pAig = Gia_ManToAig( pGia, 0 ); pAigNew = Hcd_ComputeChoices( pAig, nBTLimit, fSynthesis, fUseMiniSat, fVerbose ); Aig_ManStop( pAigNew ); Aig_ManStop( pAig ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaIf.c000066400000000000000000003132051477524141600154560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaMap.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Manipulation of mapping associated with the AIG.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "aig/aig/aig.h" #include "map/if/if.h" #include "bool/kit/kit.h" #include "base/main/main.h" #include "sat/bsat/satSolver.h" #ifdef WIN32 #include #endif 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 ); 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 /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Load the network into FPGA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSetIfParsDefault( void * pp ) { If_Par_t * pPars = (If_Par_t *)pp; // extern void * Abc_FrameReadLibLut(); If_Par_t * p = (If_Par_t *)pPars; // set defaults memset( p, 0, sizeof(If_Par_t) ); // user-controlable paramters p->nLutSize = -1; // p->nLutSize = 6; p->nCutsMax = 8; p->nFlowIters = 1; p->nAreaIters = 2; p->DelayTarget = -1; p->Epsilon = (float)0.005; p->fPreprocess = 1; p->fArea = 0; p->fFancy = 0; p->fExpRed = 1; //// p->fLatchPaths = 0; p->fEdge = 1; p->fPower = 0; p->fCutMin = 0; p->fVerbose = 0; p->pLutStruct = NULL; // internal parameters p->fTruth = 0; p->nLatchesCi = 0; p->nLatchesCo = 0; p->fLiftLeaves = 0; p->fUseCoAttrs = 1; // use CO attributes p->pLutLib = NULL; p->pTimesArr = NULL; p->pTimesReq = NULL; p->pFuncCost = NULL; } /**Function************************************************************* Synopsis [Prints mapping statistics.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManLutFaninCount( Gia_Man_t * p ) { int i, Counter = 0; Gia_ManForEachLut( p, i ) Counter += Gia_ObjLutSize(p, i); return Counter; } /**Function************************************************************* Synopsis [Prints mapping statistics.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManLutSizeMax( Gia_Man_t * p ) { int i, nSizeMax = -1; Gia_ManForEachLut( p, i ) nSizeMax = Abc_MaxInt( nSizeMax, Gia_ObjLutSize(p, i) ); return nSizeMax; } /**Function************************************************************* Synopsis [Prints mapping statistics.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManLutNum( Gia_Man_t * p ) { int i, Counter = 0; Gia_ManForEachLut( p, i ) Counter ++; return Counter; } /**Function************************************************************* Synopsis [Prints mapping statistics.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManLutLevel( Gia_Man_t * p, int ** ppLevels ) { Gia_Obj_t * pObj; int i, k, iFan, Level; int * pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachLut( p, i ) { Level = 0; Gia_LutForEachFanin( p, i, iFan, k ) if ( Level < pLevels[iFan] ) Level = pLevels[iFan]; pLevels[i] = Level + 1; } Level = 0; Gia_ManForEachCo( p, pObj, k ) { int LevelFan = pLevels[Gia_ObjFaninId0p(p, pObj)]; Level = Abc_MaxInt( Level, LevelFan ); pLevels[Gia_ObjId(p, pObj)] = LevelFan; } if ( ppLevels ) *ppLevels = pLevels; else ABC_FREE( pLevels ); return Level; } /**Function************************************************************* Synopsis [Prints mapping statistics.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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; *pnCurLuts = 0; *pnCurEdges = 0; Gia_ManForEachLut( p, i ) { (*pnCurLuts)++; (*pnCurEdges) += Gia_ObjLutSize(p, i); } *pnCurLevels = Gia_ManLutLevelWithBoxes( p ); } else { Gia_Obj_t * pObj; int i, k, iFan; int * pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); *pnCurLuts = 0; *pnCurEdges = 0; *pnCurLevels = 0; Gia_ManForEachLut( p, i ) { 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 ) pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[iFan] ); pLevels[i]++; *pnCurLevels = Abc_MaxInt( *pnCurLevels, pLevels[i] ); } ABC_FREE( pLevels ); } } /**Function************************************************************* Synopsis [Assigns levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSetRefsMapped( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, k, iFan; ABC_FREE( p->pRefs ); p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachCo( p, pObj, i ) Gia_ObjRefIncId( p, Gia_ObjFaninId0p(p, pObj) ); Gia_ManForEachLut( p, i ) Gia_LutForEachFanin( p, i, iFan, k ) Gia_ObjRefIncId( p, iFan ); } /**Function************************************************************* Synopsis [Assigns levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSetLutRefs( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, k, iFan; ABC_FREE( p->pLutRefs ); p->pLutRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachCo( p, pObj, i ) Gia_ObjLutRefIncId( p, Gia_ObjFaninId0p(p, pObj) ); Gia_ManForEachLut( p, i ) Gia_LutForEachFanin( p, i, iFan, k ) Gia_ObjLutRefIncId( p, iFan ); } /**Function************************************************************* Synopsis [Calculate mapping overlap.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManComputeOverlap2One_rec( Gia_Man_t * p, int iObj, Vec_Str_t * vLabel, Vec_Int_t * vVisit ) { Gia_Obj_t * pObj; int Counter; if ( Vec_StrEntry(vLabel, iObj) ) return 0; Vec_StrWriteEntry( vLabel, iObj, 1 ); pObj = Gia_ManObj( p, iObj ); assert( Gia_ObjIsAnd(pObj) ); Counter = Gia_ManComputeOverlap2One_rec( p, Gia_ObjFaninId0(pObj, iObj), vLabel, vVisit ); Counter += Gia_ManComputeOverlap2One_rec( p, Gia_ObjFaninId1(pObj, iObj), vLabel, vVisit ); Vec_IntPush( vVisit, iObj ); return Counter + 1; } int Gia_ManComputeOverlap2One( Gia_Man_t * p, int iObj, Vec_Str_t * vLabel, Vec_Int_t * vVisit ) { int iFan, k, Counter; Vec_IntClear( vVisit ); Gia_LutForEachFanin( p, iObj, iFan, k ) Vec_StrWriteEntry( vLabel, iFan, 1 ); Counter = Gia_ManComputeOverlap2One_rec( p, iObj, vLabel, vVisit ); Gia_LutForEachFanin( p, iObj, iFan, k ) Vec_StrWriteEntry( vLabel, iFan, 0 ); Vec_IntForEachEntry( vVisit, iFan, k ) Vec_StrWriteEntry( vLabel, iFan, 0 ); return Counter; } int Gia_ManComputeOverlap2( Gia_Man_t * p ) { Vec_Int_t * vVisit; Vec_Str_t * vLabel; int i, Count = -Gia_ManAndNum(p); assert( Gia_ManHasMapping(p) ); vVisit = Vec_IntAlloc( 100 ); vLabel = Vec_StrStart( Gia_ManObjNum(p) ); Gia_ManForEachLut( p, i ) Count += Gia_ManComputeOverlap2One( p, i, vLabel, vVisit ); Vec_StrFree( vLabel ); Vec_IntFree( vVisit ); return Count; } /**Function************************************************************* Synopsis [Calculate mapping overlap.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManComputeOverlapOne_rec( Gia_Man_t * p, int iObj ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) return 0; Gia_ObjSetTravIdCurrentId( p, iObj ); pObj = Gia_ManObj( p, iObj ); assert( Gia_ObjIsAnd(pObj) ); return 1 + Gia_ManComputeOverlapOne_rec( p, Gia_ObjFaninId0(pObj, iObj) ) + Gia_ManComputeOverlapOne_rec( p, Gia_ObjFaninId1(pObj, iObj) ); } int Gia_ManComputeOverlapOne( Gia_Man_t * p, int iObj ) { int iFan, k; Gia_ManIncrementTravId(p); Gia_LutForEachFanin( p, iObj, iFan, k ) Gia_ObjSetTravIdCurrentId( p, iFan ); return Gia_ManComputeOverlapOne_rec( p, iObj ); } int Gia_ManComputeOverlap( Gia_Man_t * p ) { int i, Count = -Gia_ManAndNum(p); assert( Gia_ManHasMapping(p) ); Gia_ManForEachLut( p, i ) Count += Gia_ManComputeOverlapOne( p, i ); return Count; } /**Function************************************************************* Synopsis [Prints mapping statistics.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintGetMuxFanins( Gia_Man_t * p, Gia_Obj_t * pObj, int * pFanins ) { Gia_Obj_t * pData0, * pData1; Gia_Obj_t * pCtrl = Gia_ObjRecognizeMux( pObj, &pData1, &pData0 ); pFanins[0] = Gia_ObjId(p, Gia_Regular(pCtrl)); pFanins[1] = Gia_ObjId(p, Gia_Regular(pData1)); pFanins[2] = Gia_ObjId(p, Gia_Regular(pData0)); } int Gia_ManCountDupLut( Gia_Man_t * p ) { Gia_Obj_t * pObj, * pFanin; int i, pFanins[3], nCountDup = 0, nCountPis = 0, nCountMux = 0; Gia_ManCleanMark01( p ); Gia_ManForEachLut( p, i ) if ( Gia_ObjLutIsMux(p, i) ) { pObj = Gia_ManObj( p, i ); pObj->fMark1 = 1; if ( Gia_ObjLutSize(p, i) == 3 ) { Gia_ManPrintGetMuxFanins( p, pObj, pFanins ); pFanin = Gia_ManObj(p, pFanins[1]); nCountPis += Gia_ObjIsCi(pFanin); nCountDup += pFanin->fMark0; nCountMux += pFanin->fMark1; pFanin->fMark0 = 1; pFanin = Gia_ManObj(p, pFanins[2]); nCountPis += Gia_ObjIsCi(pFanin); nCountDup += pFanin->fMark0; nCountMux += pFanin->fMark1; pFanin->fMark0 = 1; } else if ( Gia_ObjLutSize(p, i) == 2 ) { pFanin = Gia_ObjFanin0(pObj); if ( pFanin->fMark0 || pFanin->fMark1 ) { pFanin = Gia_ObjFanin1(pObj); nCountPis += Gia_ObjIsCi(pFanin); nCountDup += pFanin->fMark0; nCountMux += pFanin->fMark1; pFanin->fMark0 = 1; } else { nCountPis += Gia_ObjIsCi(pFanin); nCountDup += pFanin->fMark0; nCountMux += pFanin->fMark1; pFanin->fMark0 = 1; } } else assert( 0 ); } Gia_ManCleanMark01( p ); if ( nCountDup + nCountPis + nCountMux ) printf( "Dup fanins = %d. CI fanins = %d. MUX fanins = %d. Total = %d. (%.2f %%)\n", nCountDup, nCountPis, nCountMux, nCountDup + nCountPis, 100.0 * (nCountDup + nCountPis + nCountMux) / Gia_ManLutNum(p) ); return nCountDup + nCountPis; } 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; if ( !Gia_ManHasMapping(p) ) return; pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachLut( p, i ) { 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)] ); } LevelMax = Abc_MaxInt( LevelMax, pLevels[i] ); nFanins++; nMuxF++; continue; } nLuts++; nFanins += Gia_ObjLutSize(p, i); nLutSize = Abc_MaxInt( nLutSize, Gia_ObjLutSize(p, i) ); Gia_LutForEachFanin( p, i, iFan, k ) pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[iFan] ); pLevels[i]++; LevelMax = Abc_MaxInt( LevelMax, pLevels[i] ); } Gia_ManForEachCo( p, pObj, i ) Ave += pLevels[Gia_ObjFaninId0p(p, pObj)]; ABC_FREE( pLevels ); #ifdef WIN32 { HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); Abc_Print( 1, "Mapping (K=%d) : ", nLutSize ); SetConsoleTextAttribute( hConsole, 14 ); // yellow Abc_Print( 1, "lut =%7d ", nLuts ); if ( nMuxF ) Abc_Print( 1, "muxF =%7d ", nMuxF ); SetConsoleTextAttribute( hConsole, 10 ); // green Abc_Print( 1, "edge =%8d ", nFanins ); SetConsoleTextAttribute( hConsole, 12 ); // red Abc_Print( 1, "lev =%5d ", LevelMax ); Abc_Print( 1, "(%.2f) ", (float)Ave / Gia_ManCoNum(p) ); // Abc_Print( 1, "over =%5.1f %% ", 100.0 * Gia_ManComputeOverlap(p) / Gia_ManAndNum(p) ); if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t *)p->pManTime) ) Abc_Print( 1, "levB =%5d ", Gia_ManLutLevelWithBoxes(p) ); SetConsoleTextAttribute( hConsole, 7 ); // normal Abc_Print( 1, "mem =%5.2f MB", 4.0*(Gia_ManObjNum(p) + 2*nLuts + nFanins)/(1<<20) ); Abc_Print( 1, "\n" ); } #else Abc_Print( 1, "Mapping (K=%d) : ", nLutSize ); Abc_Print( 1, "%slut =%7d%s ", "\033[1;33m", nLuts, "\033[0m" ); // yellow Abc_Print( 1, "%sedge =%8d%s ", "\033[1;32m", nFanins, "\033[0m" ); // green Abc_Print( 1, "%slev =%5d%s ", "\033[1;31m", LevelMax, "\033[0m" ); // red Abc_Print( 1, "%s(%.2f)%s ", "\033[1;31m", (float)Ave / Gia_ManCoNum(p), "\033[0m" ); // Abc_Print( 1, "over =%5.1f %% ", 100.0 * Gia_ManComputeOverlap(p) / Gia_ManAndNum(p) ); if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t *)p->pManTime) ) Abc_Print( 1, "%slevB =%5d%s ", "\033[1;31m", Gia_ManLutLevelWithBoxes(p), "\033[0m" ); Abc_Print( 1, "mem =%5.2f MB", 4.0*(Gia_ManObjNum(p) + 2*nLuts + nFanins)/(1<<20) ); Abc_Print( 1, "\n" ); #endif if ( nMuxF ) Gia_ManCountDupLut( p ); //return; if ( pDumpFile ) { static char FileNameOld[1000] = {0}; static abctime clk = 0; FILE * pTable = fopen( pDumpFile, "a+" ); if ( strcmp( FileNameOld, 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_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 ); clk = Abc_Clock(); } else { //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 ); clk = Abc_Clock(); } fclose( pTable ); } } /**Function************************************************************* Synopsis [Prints mapping statistics.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintPackingStats( Gia_Man_t * p ) { int fVerbose = 0; int nObjToShow = 200; int nNumStr[5] = {0}; int i, k, Entry, nEntries, nEntries2, MaxSize = -1, Count = 0; if ( p->vPacking == NULL ) return; nEntries = Vec_IntEntry( p->vPacking, 0 ); nEntries2 = 0; Vec_IntForEachEntryStart( p->vPacking, Entry, i, 1 ) { assert( Entry > 0 && Entry < 4 ); nNumStr[Entry]++; i++; if ( fVerbose && nEntries2 < nObjToShow ) Abc_Print( 1, "{ " ); for ( k = 0; k < Entry; k++, i++ ) if ( fVerbose && nEntries2 < nObjToShow ) Abc_Print( 1, "%d ", Vec_IntEntry(p->vPacking, i) ); if ( fVerbose && nEntries2 < nObjToShow ) Abc_Print( 1, "}\n" ); i--; nEntries2++; } assert( nEntries == nEntries2 ); if ( nNumStr[3] > 0 ) MaxSize = 3; else if ( nNumStr[2] > 0 ) MaxSize = 2; else if ( nNumStr[1] > 0 ) MaxSize = 1; Abc_Print( 1, "Packing (N=%d) : ", MaxSize ); for ( i = 1; i <= MaxSize; i++ ) { Abc_Print( 1, "%d x LUT = %d ", i, nNumStr[i] ); Count += i * nNumStr[i]; } Abc_Print( 1, "Total = %d ", nEntries2 ); Abc_Print( 1, "Total LUT = %d", Count ); Abc_Print( 1, "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintNodeProfile( int * pCounts, int nSizeMax ) { int i, SizeAll = 0, NodeAll = 0; for ( i = 0; i <= nSizeMax; i++ ) { SizeAll += i * pCounts[i]; NodeAll += pCounts[i]; } Abc_Print( 1, "LUT = %d : ", NodeAll ); for ( i = 2; i <= nSizeMax; i++ ) Abc_Print( 1, "%d=%d %.1f %% ", i, pCounts[i], 100.0*pCounts[i]/NodeAll ); Abc_Print( 1, "Ave = %.2f\n", 1.0*SizeAll/(NodeAll ? NodeAll : 1) ); } void Gia_ManPrintLutStats( Gia_Man_t * p ) { int i, nSizeMax, pCounts[33] = {0}; nSizeMax = Gia_ManLutSizeMax( p ); if ( nSizeMax > 32 ) { Abc_Print( 1, "The max LUT size (%d) is too large.\n", nSizeMax ); return; } Gia_ManForEachLut( p, i ) pCounts[ Gia_ObjLutSize(p, i) ]++; Gia_ManPrintNodeProfile( pCounts, nSizeMax ); } /**Function************************************************************* Synopsis [Computes levels for AIG with choices and white boxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManChoiceLevel_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; Gia_Obj_t * pNext; int i, iBox, iTerm1, nTerms, LevelMax = 0; if ( Gia_ObjIsTravIdCurrent( p, pObj ) ) return; Gia_ObjSetTravIdCurrent( p, pObj ); if ( Gia_ObjIsCi(pObj) ) { if ( pManTime ) { iBox = Tim_ManBoxForCi( pManTime, Gia_ObjCioId(pObj) ); if ( iBox >= 0 ) // this is not a true PI { iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox ); nTerms = Tim_ManBoxInputNum( pManTime, iBox ); for ( i = 0; i < nTerms; i++ ) { pNext = Gia_ManCo( p, iTerm1 + i ); Gia_ManChoiceLevel_rec( p, pNext ); if ( LevelMax < Gia_ObjLevel(p, pNext) ) LevelMax = Gia_ObjLevel(p, pNext); } LevelMax++; } } // Abc_Print( 1, "%d ", pObj->Level ); } else if ( Gia_ObjIsCo(pObj) ) { pNext = Gia_ObjFanin0(pObj); Gia_ManChoiceLevel_rec( p, pNext ); if ( LevelMax < Gia_ObjLevel(p, pNext) ) LevelMax = Gia_ObjLevel(p, pNext); } else if ( Gia_ObjIsAnd(pObj) ) { // get the maximum level of the two fanins pNext = Gia_ObjFanin0(pObj); Gia_ManChoiceLevel_rec( p, pNext ); if ( LevelMax < Gia_ObjLevel(p, pNext) ) LevelMax = Gia_ObjLevel(p, pNext); pNext = Gia_ObjFanin1(pObj); Gia_ManChoiceLevel_rec( p, pNext ); if ( LevelMax < Gia_ObjLevel(p, pNext) ) LevelMax = Gia_ObjLevel(p, pNext); LevelMax++; // get the level of the nodes in the choice node if ( (pNext = Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))) ) { Gia_ManChoiceLevel_rec( p, pNext ); if ( LevelMax < Gia_ObjLevel(p, pNext) ) LevelMax = Gia_ObjLevel(p, pNext); } } else if ( !Gia_ObjIsConst0(pObj) ) assert( 0 ); Gia_ObjSetLevel( p, pObj, LevelMax ); } int Gia_ManChoiceLevel( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, LevelMax = 0; // assert( Gia_ManRegNum(p) == 0 ); Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); Gia_ManIncrementTravId( p ); Gia_ManForEachCo( p, pObj, i ) { Gia_ManChoiceLevel_rec( p, pObj ); if ( LevelMax < Gia_ObjLevel(p, pObj) ) LevelMax = Gia_ObjLevel(p, pObj); } // account for dangling boxes Gia_ManForEachCi( p, pObj, i ) { Gia_ManChoiceLevel_rec( p, pObj ); if ( LevelMax < Gia_ObjLevel(p, pObj) ) LevelMax = Gia_ObjLevel(p, pObj); // Abc_Print( 1, "%d ", Gia_ObjLevel(p, pObj) ); } // Abc_Print( 1, "\n" ); Gia_ManForEachAnd( p, pObj, i ) assert( Gia_ObjLevel(p, pObj) > 0 ); // printf( "Max level %d\n", LevelMax ); return LevelMax; } /**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************************************************************* Synopsis [Converts GIA into IF manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline If_Obj_t * If_ManFanin0Copy( If_Man_t * pIfMan, Gia_Obj_t * pObj ) { return If_NotCond( If_ManObj(pIfMan, Gia_ObjValue(Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj) ); } static inline If_Obj_t * If_ManFanin1Copy( If_Man_t * pIfMan, Gia_Obj_t * pObj ) { return If_NotCond( If_ManObj(pIfMan, Gia_ObjValue(Gia_ObjFanin1(pObj))), Gia_ObjFaninC1(pObj) ); } If_Man_t * Gia_ManToIf( Gia_Man_t * p, If_Par_t * pPars ) { If_Man_t * pIfMan; If_Obj_t * pIfObj = NULL; Gia_Obj_t * pObj; int i; // create levels with choices Gia_ManChoiceLevel( p ); // mark representative nodes if ( Gia_ManHasChoices(p) ) Gia_ManMarkFanoutDrivers( p ); // start the mapping manager and set its parameters pIfMan = If_ManStart( pPars ); pIfMan->pName = Abc_UtilStrsav( Gia_ManName(p) ); // print warning about excessive memory usage if ( 1.0 * Gia_ManObjNum(p) * pIfMan->nObjBytes / (1<<30) > 1.0 ) printf( "Warning: The mapper will allocate %.1f GB for to represent the subject graph with %d AIG nodes.\n", 1.0 * Gia_ManObjNum(p) * pIfMan->nObjBytes / (1<<30), Gia_ManObjNum(p) ); // load the AIG into the mapper Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = If_ObjId( If_ManConst1(pIfMan) ); Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) pIfObj = If_ManCreateAnd( pIfMan, If_ManFanin0Copy(pIfMan, pObj), If_ManFanin1Copy(pIfMan, pObj) ); else if ( Gia_ObjIsCi(pObj) ) { pIfObj = If_ManCreateCi( pIfMan ); If_ObjSetLevel( pIfObj, Gia_ObjLevel(p, pObj) ); // Abc_Print( 1, "pi%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); if ( pIfMan->nLevelMax < (int)pIfObj->Level ) pIfMan->nLevelMax = (int)pIfObj->Level; } else if ( Gia_ObjIsCo(pObj) ) { pIfObj = If_ManCreateCo( pIfMan, If_NotCond( If_ManFanin0Copy(pIfMan, pObj), Gia_ObjIsConst0(Gia_ObjFanin0(pObj))) ); // Abc_Print( 1, "po%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); } else assert( 0 ); assert( i == If_ObjId(pIfObj) ); Gia_ObjSetValue( pObj, If_ObjId(pIfObj) ); // set up the choice node if ( Gia_ObjSibl(p, i) && pObj->fMark0 ) { Gia_Obj_t * pSibl, * pPrev; for ( pPrev = pObj, pSibl = Gia_ObjSiblObj(p, i); pSibl; pPrev = pSibl, pSibl = Gia_ObjSiblObj(p, Gia_ObjId(p, pSibl)) ) If_ObjSetChoice( If_ManObj(pIfMan, Gia_ObjValue(pPrev)), If_ManObj(pIfMan, Gia_ObjValue(pSibl)) ); If_ManCreateChoice( pIfMan, If_ManObj(pIfMan, Gia_ObjValue(pObj)) ); pPars->fExpRed = 0; } // assert( If_ObjLevel(pIfObj) == Gia_ObjLevel(pNode) ); } if ( Gia_ManHasChoices(p) ) Gia_ManCleanMark0( p ); //If_ManCheckChoices( pIfMan ); return pIfMan; } /**Function************************************************************* Synopsis [Rebuilds GIA from mini AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManBuildFromMiniInt( Gia_Man_t * pNew, Vec_Int_t * vLeaves, Vec_Int_t * vAig, int fHash ) { assert( Vec_IntSize(vAig) > 0 ); assert( Vec_IntEntryLast(vAig) < 2 ); if ( Vec_IntSize(vAig) == 1 ) // const return Vec_IntEntry(vAig, 0); if ( Vec_IntSize(vAig) == 2 ) // variable { assert( Vec_IntEntry(vAig, 0) == 0 ); assert( Vec_IntSize(vLeaves) == 1 ); return Abc_LitNotCond( Vec_IntEntry(vLeaves, 0), Vec_IntEntry(vAig, 1) ); } else { int nLeaves = Vec_IntSize(vLeaves); int i, iVar0, iVar1, iLit0, iLit1, iLit = 0; assert( Vec_IntSize(vAig) & 1 ); Vec_IntForEachEntryDouble( vAig, iLit0, iLit1, i ) { iVar0 = Abc_Lit2Var( iLit0 ); iVar1 = Abc_Lit2Var( iLit1 ); iLit0 = Abc_LitNotCond( iVar0 < nLeaves ? Vec_IntEntry(vLeaves, iVar0) : Vec_IntEntry(vAig, iVar0 - nLeaves), Abc_LitIsCompl(iLit0) ); iLit1 = Abc_LitNotCond( iVar1 < nLeaves ? Vec_IntEntry(vLeaves, iVar1) : Vec_IntEntry(vAig, iVar1 - nLeaves), Abc_LitIsCompl(iLit1) ); if ( fHash ) iLit = Gia_ManHashAnd( pNew, iLit0, iLit1 ); else if ( iLit0 == iLit1 ) iLit = iLit0; else iLit = Gia_ManAppendAnd( pNew, iLit0, iLit1 ); assert( (i & 1) == 0 ); Vec_IntWriteEntry( vAig, Abc_Lit2Var(i), iLit ); // overwriting entries } assert( i == Vec_IntSize(vAig) - 1 ); iLit = Abc_LitNotCond( iLit, Vec_IntEntry(vAig, i) ); Vec_IntClear( vAig ); // useless return iLit; } } int Gia_ManBuildFromMini( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Cut_t * pCut, Vec_Int_t * vLeaves, Vec_Int_t * vAig, int fHash, int fUseDsd ) { if ( fUseDsd ) If_CutDsdBalanceEval( pIfMan, pCut, vAig ); else If_CutSopBalanceEval( pIfMan, pCut, vAig ); return Gia_ManBuildFromMiniInt( pNew, vLeaves, vAig, fHash ); } /**Function************************************************************* Synopsis [Converts IF into GIA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFromIfAig_rec( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Obj_t * pIfObj ) { int iLit0, iLit1; if ( pIfObj->iCopy ) return pIfObj->iCopy; iLit0 = Gia_ManFromIfAig_rec( pNew, pIfMan, pIfObj->pFanin0 ); iLit1 = Gia_ManFromIfAig_rec( pNew, pIfMan, pIfObj->pFanin1 ); iLit0 = Abc_LitNotCond( iLit0, pIfObj->fCompl0 ); iLit1 = Abc_LitNotCond( iLit1, pIfObj->fCompl1 ); pIfObj->iCopy = Gia_ManHashAnd( pNew, iLit0, iLit1 ); return pIfObj->iCopy; } Gia_Man_t * Gia_ManFromIfAig( If_Man_t * pIfMan ) { int fHash = 0; Gia_Man_t * pNew, * pTemp; If_Obj_t * pIfObj, * pIfLeaf; If_Cut_t * pCutBest; Vec_Int_t * vLeaves; Vec_Int_t * vAig; int i, k; assert( pIfMan->pPars->pLutStruct == NULL ); assert( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib || pIfMan->pPars->fUserSesLib ); // create new manager pNew = Gia_ManStart( If_ManObjNum(pIfMan) ); Gia_ManHashAlloc( pNew ); // iterate through nodes used in the mapping vAig = Vec_IntAlloc( 1 << 16 ); vLeaves = Vec_IntAlloc( 16 ); // If_ManForEachObj( pIfMan, pIfObj, i ) // pIfObj->iCopy = 0; If_ManForEachObj( pIfMan, pIfObj, i ) { if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) ) continue; if ( If_ObjIsAnd(pIfObj) ) { pCutBest = If_ObjCutBest( pIfObj ); // if the cut does not offer delay improvement // if ( (int)pIfObj->Level <= (int)pCutBest->Delay ) // { // Gia_ManFromIfAig_rec( pNew, pIfMan, pIfObj ); // continue; // } // collect leaves of the best cut Vec_IntClear( vLeaves ); If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, k ) Vec_IntPush( vLeaves, pIfLeaf->iCopy ); // get the functionality if ( pIfMan->pPars->fDelayOpt ) pIfObj->iCopy = Gia_ManBuildFromMini( pNew, pIfMan, pCutBest, vLeaves, vAig, fHash, 0 ); else if ( pIfMan->pPars->fDsdBalance ) pIfObj->iCopy = Gia_ManBuildFromMini( pNew, pIfMan, pCutBest, vLeaves, vAig, fHash, 1 ); else if ( pIfMan->pPars->fUserRecLib ) pIfObj->iCopy = Abc_RecToGia3( pNew, pIfMan, pCutBest, vLeaves, fHash ); else assert( 0 ); } else if ( If_ObjIsCi(pIfObj) ) pIfObj->iCopy = Gia_ManAppendCi(pNew); else if ( If_ObjIsCo(pIfObj) ) pIfObj->iCopy = Gia_ManAppendCo( pNew, Abc_LitNotCond(If_ObjFanin0(pIfObj)->iCopy, If_ObjFaninC0(pIfObj)) ); else if ( If_ObjIsConst1(pIfObj) ) pIfObj->iCopy = 1; else assert( 0 ); } Vec_IntFree( vAig ); Vec_IntFree( vLeaves ); pNew = Gia_ManRehash( pTemp = pNew, 0 ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Write mapping for LUT with given fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFromIfLogicCreateLut( Gia_Man_t * pNew, word * pRes, Vec_Int_t * vLeaves, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 ) { int i, iLit, iObjLit1; iObjLit1 = Kit_TruthToGia( pNew, (unsigned *)pRes, Vec_IntSize(vLeaves), vCover, vLeaves, 0 ); // do not create LUT in the simple case if ( Abc_Lit2Var(iObjLit1) == 0 ) return iObjLit1; Vec_IntForEachEntry( vLeaves, iLit, i ) if ( Abc_Lit2Var(iObjLit1) == Abc_Lit2Var(iLit) ) return iObjLit1; // write mapping Vec_IntSetEntry( vMapping, Abc_Lit2Var(iObjLit1), Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); // Vec_IntForEachEntry( vLeaves, iLit, i ) // assert( Abc_Lit2Var(iLit) < Abc_Lit2Var(iObjLit1) ); Vec_IntForEachEntry( vLeaves, iLit, i ) Vec_IntPush( vMapping2, Abc_Lit2Var(iLit) ); Vec_IntPush( vMapping2, Abc_Lit2Var(iObjLit1) ); return iObjLit1; } /**Function************************************************************* Synopsis [Write mapping for LUT with given fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFromIfLogicCreateLutSpecial( Gia_Man_t * pNew, word * pRes, Vec_Int_t * vLeaves, Vec_Int_t * vLeavesTemp, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vPacking ) { word z = If_CutPerformDerive07( NULL, (unsigned *)pRes, Vec_IntSize(vLeaves), Vec_IntSize(vLeaves), NULL ); word Truth; int i, iObjLit1, iObjLit2; // create first LUT Vec_IntClear( vLeavesTemp ); for ( i = 0; i < 4; i++ ) { int v = (int)((z >> (16+(i<<2))) & 7); if ( v == 6 && Vec_IntSize(vLeaves) == 5 ) continue; Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, v) ); } Truth = (z & 0xffff); Truth |= (Truth << 16); Truth |= (Truth << 32); iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, &Truth, vLeavesTemp, vCover, vMapping, vMapping2 ); // create second LUT Vec_IntClear( vLeavesTemp ); for ( i = 0; i < 4; i++ ) { int v = (int)((z >> (48+(i<<2))) & 7); if ( v == 6 && Vec_IntSize(vLeaves) == 5 ) continue; if ( v == 7 ) Vec_IntPush( vLeavesTemp, iObjLit1 ); else Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, v) ); } Truth = ((z >> 32) & 0xffff); Truth |= (Truth << 16); Truth |= (Truth << 32); iObjLit2 = Gia_ManFromIfLogicCreateLut( pNew, &Truth, vLeavesTemp, vCover, vMapping, vMapping2 ); // write packing Vec_IntPush( vPacking, 2 ); Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) ); Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit2) ); Vec_IntAddToEntry( vPacking, 0, 1 ); return iObjLit2; } /**Function************************************************************* Synopsis [Write the node into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFromIfLogicNode( void * pIfMan, Gia_Man_t * pNew, int iObj, Vec_Int_t * vLeaves, Vec_Int_t * vLeavesTemp, word * pRes, char * pStr, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vPacking, int fCheck75, int fCheck44e ) { int nLeaves = Vec_IntSize(vLeaves); int i, Length, nLutLeaf, nLutLeaf2, nLutRoot, iObjLit1, iObjLit2, iObjLit3; // workaround for the special case if ( fCheck75 ) pStr = "54"; // perform special case matching for 44 if ( fCheck44e ) { if ( Vec_IntSize(vLeaves) <= 4 ) { // create mapping iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, pRes, vLeaves, vCover, vMapping, vMapping2 ); // write packing if ( !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(iObjLit1))) && iObjLit1 > 1 ) { Vec_IntPush( vPacking, 1 ); Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) ); Vec_IntAddToEntry( vPacking, 0, 1 ); } return iObjLit1; } 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 ); // quit if parameters are wrong Length = strlen(pStr); if ( Length != 2 && Length != 3 ) { printf( "Wrong LUT struct (%s)\n", pStr ); return -1; } for ( i = 0; i < Length; i++ ) if ( pStr[i] - '0' < 3 || pStr[i] - '0' > 6 ) { printf( "The LUT size (%d) should belong to {3,4,5,6}.\n", pStr[i] - '0' ); return -1; } nLutLeaf = pStr[0] - '0'; nLutLeaf2 = ( Length == 3 ) ? pStr[1] - '0' : 0; nLutRoot = pStr[Length-1] - '0'; if ( nLeaves > nLutLeaf - 1 + (nLutLeaf2 ? nLutLeaf2 - 1 : 0) + nLutRoot ) { printf( "The node size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr ); return -1; } // consider easy case if ( nLeaves <= Abc_MaxInt( nLutLeaf2, Abc_MaxInt(nLutLeaf, nLutRoot) ) ) { // create mapping iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, pRes, vLeaves, vCover, vMapping, vMapping2 ); // write packing if ( !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(iObjLit1))) && iObjLit1 > 1 ) { Vec_IntPush( vPacking, 1 ); Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) ); Vec_IntAddToEntry( vPacking, 0, 1 ); } return iObjLit1; } else { extern int If_CluMinimumBase( word * t, int * pSupp, int nVarsAll, int * pnVars ); static word TruthStore[16][1<<10] = {{0}}, * pTruths[16]; word Func0, Func1, Func2; char pLut0[32], pLut1[32], pLut2[32] = {0}; if ( TruthStore[0][0] == 0 ) { static word Truth6[6] = { 0xAAAAAAAAAAAAAAAA, 0xCCCCCCCCCCCCCCCC, 0xF0F0F0F0F0F0F0F0, 0xFF00FF00FF00FF00, 0xFFFF0000FFFF0000, 0xFFFFFFFF00000000 }; int nVarsMax = 16; int nWordsMax = (1 << 10); int i, k; assert( nVarsMax <= 16 ); for ( i = 0; i < nVarsMax; i++ ) pTruths[i] = TruthStore[i]; for ( i = 0; i < 6; i++ ) for ( k = 0; k < nWordsMax; k++ ) pTruths[i][k] = Truth6[i]; for ( i = 6; i < nVarsMax; i++ ) for ( k = 0; k < nWordsMax; k++ ) pTruths[i][k] = ((k >> (i-6)) & 1) ? ~(word)0 : 0; } // derive truth table if ( Kit_TruthIsConst0((unsigned *)pRes, nLeaves) || Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ) { // fprintf( pFile, ".names %s\n %d\n", Abc_ObjName(Abc_ObjFanout0(pObj)), Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ); iObjLit1 = Abc_LitNotCond( 0, Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ); // write mapping if ( Vec_IntEntry(vMapping, 0) == 0 ) { Vec_IntSetEntry( vMapping, 0, Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, 0 ); Vec_IntPush( vMapping2, 0 ); } return iObjLit1; } // check for elementary truth table for ( i = 0; i < nLeaves; i++ ) { if ( Kit_TruthIsEqual((unsigned *)pRes, (unsigned *)pTruths[i], nLeaves) ) return Vec_IntEntry(vLeaves, i); if ( Kit_TruthIsOpposite((unsigned *)pRes, (unsigned *)pTruths[i], nLeaves) ) return Abc_LitNot(Vec_IntEntry(vLeaves, i)); } // perform decomposition if ( fCheck75 ) { // if ( nLeaves < 8 && If_CutPerformCheck16( p, (unsigned *)pTruth, nVars, nLeaves, "44" ) ) if ( nLeaves < 8 && If_CluCheckExt( NULL, pRes, nLeaves, 4, 4, pLut0, pLut1, &Func0, &Func1 ) ) { nLutLeaf = 4; nLutRoot = 4; } // if ( If_CutPerformCheck45( p, (unsigned *)pTruth, nVars, nLeaves, pStr ) ) else if ( If_CluCheckExt( NULL, pRes, nLeaves, 5, 4, pLut0, pLut1, &Func0, &Func1 ) ) { nLutLeaf = 5; nLutRoot = 4; } // if ( If_CutPerformCheck54( p, (unsigned *)pTruth, nVars, nLeaves, pStr ) ) else if ( If_CluCheckExt( NULL, pRes, nLeaves, 4, 5, pLut0, pLut1, &Func0, &Func1 ) ) { nLutLeaf = 4; nLutRoot = 5; } else { Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj ); return -1; } } else { if ( Length == 2 ) { if ( ((If_Man_t *)pIfMan)->pPars->fEnableStructN ) { if ( !If_CluCheckXXExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) ) { Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj ); return -1; } } else { if ( !If_CluCheckExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) ) { Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj ); return -1; } } } else { if ( !If_CluCheckExt3( pIfMan, pRes, nLeaves, nLutLeaf, nLutLeaf2, nLutRoot, pLut0, pLut1, pLut2, &Func0, &Func1, &Func2 ) ) { Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj ); return -1; } } } /* // write leaf node Id = Abc2_NtkAllocObj( pNew, pLut1[0], Abc2_ObjType(pObj) ); iObjLit1 = Abc_Var2Lit( Id, 0 ); pObjNew = Abc2_NtkObj( pNew, Id ); for ( i = 0; i < pLut1[0]; i++ ) Abc2_ObjSetFaninLit( pObjNew, i, Abc2_ObjFaninCopy(pObj, pLut1[2+i]) ); Abc2_ObjSetTruth( pObjNew, Func1 ); */ // write leaf node Vec_IntClear( vLeavesTemp ); for ( i = 0; i < pLut1[0]; i++ ) Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, pLut1[2+i]) ); iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, &Func1, vLeavesTemp, vCover, vMapping, vMapping2 ); if ( Length == 3 && pLut2[0] > 0 ) { /* Id = Abc2_NtkAllocObj( pNew, pLut2[0], Abc2_ObjType(pObj) ); iObjLit2 = Abc_Var2Lit( Id, 0 ); pObjNew = Abc2_NtkObj( pNew, Id ); for ( i = 0; i < pLut2[0]; i++ ) if ( pLut2[2+i] == nLeaves ) Abc2_ObjSetFaninLit( pObjNew, i, iObjLit1 ); else Abc2_ObjSetFaninLit( pObjNew, i, Abc2_ObjFaninCopy(pObj, pLut2[2+i]) ); Abc2_ObjSetTruth( pObjNew, Func2 ); */ // write leaf node Vec_IntClear( vLeavesTemp ); for ( i = 0; i < pLut2[0]; i++ ) if ( pLut2[2+i] == nLeaves ) Vec_IntPush( vLeavesTemp, iObjLit1 ); else Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, pLut2[2+i]) ); iObjLit2 = Gia_ManFromIfLogicCreateLut( pNew, &Func2, vLeavesTemp, vCover, vMapping, vMapping2 ); // write packing Vec_IntPush( vPacking, 3 ); Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) ); Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit2) ); } else { // write packing Vec_IntPush( vPacking, 2 ); Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) ); iObjLit2 = -1; } /* // write root node Id = Abc2_NtkAllocObj( pNew, pLut0[0], Abc2_ObjType(pObj) ); iObjLit3 = Abc_Var2Lit( Id, 0 ); pObjNew = Abc2_NtkObj( pNew, Id ); for ( i = 0; i < pLut0[0]; i++ ) if ( pLut0[2+i] == nLeaves ) Abc2_ObjSetFaninLit( pObjNew, i, iObjLit1 ); else if ( pLut0[2+i] == nLeaves+1 ) Abc2_ObjSetFaninLit( pObjNew, i, iObjLit2 ); else Abc2_ObjSetFaninLit( pObjNew, i, Abc2_ObjFaninCopy(pObj, pLut0[2+i]) ); Abc2_ObjSetTruth( pObjNew, Func0 ); Abc2_ObjSetCopy( pObj, iObjLit3 ); */ // write root node Vec_IntClear( vLeavesTemp ); for ( i = 0; i < pLut0[0]; i++ ) if ( pLut0[2+i] == nLeaves ) Vec_IntPush( vLeavesTemp, iObjLit1 ); else if ( pLut0[2+i] == nLeaves+1 ) Vec_IntPush( vLeavesTemp, iObjLit2 ); else Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, pLut0[2+i]) ); iObjLit3 = Gia_ManFromIfLogicCreateLut( pNew, &Func0, vLeavesTemp, vCover, vMapping, vMapping2 ); // write packing Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit3) ); Vec_IntAddToEntry( vPacking, 0, 1 ); } return iObjLit3; } /**Function************************************************************* Synopsis [Implements delay-driven decomposition of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFromIfLogicHop( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, Vec_Int_t * vLeaves, Vec_Int_t * vLeavesTemp, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 ) { word * pTruth = If_CutTruthW(pIfMan, pCutBest); unsigned char decompArray[92]; int val; assert( pCutBest->nLeaves > pIfMan->pPars->nLutDecSize ); unsigned delayProfile = pCutBest->decDelay; val = acd_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); assert( val == 0 ); // convert the LUT-structure into a set of logic nodes in Gia_Man_t unsigned char bytes_check = decompArray[0]; assert( bytes_check <= 92 ); int byte_p = 2; unsigned char i, j, k, num_fanins, num_words, num_bytes; int iObjLits[5]; int fanin; word *tt; for ( i = 0; i < decompArray[1]; ++i ) { num_fanins = decompArray[byte_p++]; Vec_IntClear( vLeavesTemp ); for ( j = 0; j < num_fanins; ++j ) { fanin = (int)decompArray[byte_p++]; if ( fanin < If_CutLeaveNum(pCutBest) ) { Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, fanin) ); } else { Vec_IntPush( vLeavesTemp, iObjLits[fanin - If_CutLeaveNum(pCutBest)] ); } } /* extract the truth table */ tt = pIfMan->puTempW; num_words = ( num_fanins <= 6 ) ? 1 : ( 1 << ( num_fanins - 6 ) ); num_bytes = ( num_fanins <= 3 ) ? 1 : ( 1 << ( Abc_MinInt( (int)num_fanins, 6 ) - 3 ) ); for ( j = 0; j < num_words; ++j ) { tt[j] = 0; for ( k = 0; k < num_bytes; ++k ) { tt[j] |= ( (word)(decompArray[byte_p++]) ) << ( k << 3 ); } } /* extend truth table if size < 5 */ assert( num_fanins != 1 ); if ( num_fanins == 2 ) { tt[0] |= tt[0] << 4; } while ( num_bytes < 4 ) { tt[0] |= tt[0] << ( num_bytes << 3 ); num_bytes <<= 1; } iObjLits[i] = Gia_ManFromIfLogicCreateLut( pNew, tt, vLeavesTemp, vCover, vMapping, vMapping2 ); } /* check correct read */ assert( byte_p == decompArray[0] ); return iObjLits[i-1]; } /**Function************************************************************* Synopsis [Recursively derives the local AIG for the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManNodeIfToGia_rec( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited, int fHash ) { If_Cut_t * pCut; If_Obj_t * pTemp; int iFunc, iFunc0, iFunc1; // get the best cut pCut = If_ObjCutBest(pIfObj); // if the cut is visited, return the result if ( If_CutDataInt(pCut) ) return If_CutDataInt(pCut); // mark the node as visited Vec_PtrPush( vVisited, pCut ); // insert the worst case If_CutSetDataInt( pCut, ~0 ); // skip in case of primary input if ( If_ObjIsCi(pIfObj) ) return If_CutDataInt(pCut); // compute the functions of the children for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv ) { iFunc0 = Gia_ManNodeIfToGia_rec( pNew, pIfMan, pTemp->pFanin0, vVisited, fHash ); if ( iFunc0 == ~0 ) continue; iFunc1 = Gia_ManNodeIfToGia_rec( pNew, pIfMan, pTemp->pFanin1, vVisited, fHash ); if ( iFunc1 == ~0 ) continue; // both branches are solved if ( fHash ) iFunc = Gia_ManHashAnd( pNew, Abc_LitNotCond(iFunc0, pTemp->fCompl0), Abc_LitNotCond(iFunc1, pTemp->fCompl1) ); else iFunc = Gia_ManAppendAnd( pNew, Abc_LitNotCond(iFunc0, pTemp->fCompl0), Abc_LitNotCond(iFunc1, pTemp->fCompl1) ); if ( pTemp->fPhase != pIfObj->fPhase ) iFunc = Abc_LitNot(iFunc); If_CutSetDataInt( pCut, iFunc ); break; } return If_CutDataInt(pCut); } int Gia_ManNodeIfToGia( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vLeaves, int fHash ) { If_Cut_t * pCut; If_Obj_t * pLeaf; int i, iRes; // get the best cut pCut = If_ObjCutBest(pIfObj); assert( pCut->nLeaves > 1 ); // set the leaf variables If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) If_CutSetDataInt( If_ObjCutBest(pLeaf), Vec_IntEntry(vLeaves, i) ); // recursively compute the function while collecting visited cuts Vec_PtrClear( pIfMan->vTemp ); iRes = Gia_ManNodeIfToGia_rec( pNew, pIfMan, pIfObj, pIfMan->vTemp, fHash ); if ( iRes == ~0 ) { Abc_Print( -1, "Gia_ManNodeIfToGia(): Computing local AIG has failed.\n" ); return ~0; } // clean the cuts If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) If_CutSetDataInt( If_ObjCutBest(pLeaf), 0 ); Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i ) If_CutSetDataInt( pCut, 0 ); return iRes; } /**Function************************************************************* Synopsis [Converts IF into GIA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFromIfLogicFindLut( If_Man_t * pIfMan, Gia_Man_t * pNew, If_Cut_t * pCutBest, sat_solver * pSat, Vec_Int_t * vLeaves, Vec_Int_t * vLits, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vPacking ) { word uBound, uFree; int nLutSize = (int)(pIfMan->pPars->pLutStruct[0] - '0'); int nVarsF = 0, pVarsF[IF_MAX_FUNC_LUTSIZE]; int nVarsB = 0, pVarsB[IF_MAX_FUNC_LUTSIZE]; int nVarsS = 0, pVarsS[IF_MAX_FUNC_LUTSIZE]; unsigned uSetNew, uSetOld; int RetValue, RetValue2, k; char * pPerm; if ( Vec_IntSize(vLeaves) <= nLutSize ) { RetValue = Gia_ManFromIfLogicCreateLut( pNew, If_CutTruthW(pIfMan, pCutBest), vLeaves, vCover, vMapping, vMapping2 ); // write packing if ( !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(RetValue))) && RetValue > 1 ) { Vec_IntPush( vPacking, 1 ); Vec_IntPush( vPacking, Abc_Lit2Var(RetValue) ); Vec_IntAddToEntry( vPacking, 0, 1 ); } return RetValue; } assert( If_DsdManSuppSize(pIfMan->pIfDsdMan, If_CutDsdLit(pIfMan, pCutBest)) == (int)pCutBest->nLeaves ); // find the bound set if ( pIfMan->pPars->fDelayOptLut ) uSetOld = pCutBest->uMaskFunc; else uSetOld = If_DsdManCheckXY( pIfMan->pIfDsdMan, If_CutDsdLit(pIfMan, pCutBest), nLutSize, 1, 0, 1, 0 ); // remap bound set uSetNew = 0; pPerm = If_CutDsdPerm( pIfMan, pCutBest ); for ( k = 0; k < If_CutLeaveNum(pCutBest); k++ ) { int iVar = Abc_Lit2Var((int)pPerm[k]); int Value = ((uSetOld >> (k << 1)) & 3); if ( Value == 1 ) uSetNew |= (1 << (2*iVar)); else if ( Value == 3 ) uSetNew |= (3 << (2*iVar)); else assert( Value == 0 ); } RetValue = If_ManSatCheckXY( pSat, nLutSize, If_CutTruthW(pIfMan, pCutBest), pCutBest->nLeaves, uSetNew, &uBound, &uFree, vLits ); assert( RetValue ); // collect variables for ( k = 0; k < If_CutLeaveNum(pCutBest); k++ ) { int Value = ((uSetNew >> (k << 1)) & 3); if ( Value == 0 ) pVarsF[nVarsF++] = k; else if ( Value == 1 ) pVarsB[nVarsB++] = k; else if ( Value == 3 ) pVarsS[nVarsS++] = k; else assert( Value == 0 ); } // collect bound set variables Vec_IntClear( vLits ); for ( k = 0; k < nVarsS; k++ ) Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsS[k]) ); for ( k = 0; k < nVarsB; k++ ) Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsB[k]) ); RetValue = Gia_ManFromIfLogicCreateLut( pNew, &uBound, vLits, vCover, vMapping, vMapping2 ); // collecct free set variables Vec_IntClear( vLits ); Vec_IntPush( vLits, RetValue ); for ( k = 0; k < nVarsS; k++ ) Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsS[k]) ); for ( k = 0; k < nVarsF; k++ ) Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsF[k]) ); // add packing RetValue2 = Gia_ManFromIfLogicCreateLut( pNew, &uFree, vLits, vCover, vMapping, vMapping2 ); // write packing Vec_IntPush( vPacking, 2 ); Vec_IntPush( vPacking, Abc_Lit2Var(RetValue) ); Vec_IntPush( vPacking, Abc_Lit2Var(RetValue2) ); Vec_IntAddToEntry( vPacking, 0, 1 ); return RetValue2; } /**Function************************************************************* Synopsis [Converts IF into GIA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFromIfGetConfig( Vec_Int_t * vConfigs, If_Man_t * pIfMan, If_Cut_t * pCutBest, int iLit, Vec_Str_t * vConfigsStr ) { If_Obj_t * pIfObj = NULL; word * pPerm = If_DsdManGetFuncConfig( pIfMan->pIfDsdMan, If_CutDsdLit(pIfMan, pCutBest) ); // cell input -> DSD input char * pCutPerm = If_CutDsdPerm( pIfMan, pCutBest ); // DSD input -> cut input word * pArray; int v, i, Lit, Var; int nVarNum = If_DsdManVarNum(pIfMan->pIfDsdMan); int nTtBitNum = If_DsdManTtBitNum(pIfMan->pIfDsdMan); int nPermBitNum = If_DsdManPermBitNum(pIfMan->pIfDsdMan); int nPermBitOne = nPermBitNum / nVarNum; // prepare storage int nIntNum = Vec_IntEntry( vConfigs, 1 ); for ( i = 0; i < nIntNum; i++ ) Vec_IntPush( vConfigs, 0 ); pArray = (word *)Vec_IntEntryP( vConfigs, Vec_IntSize(vConfigs) - nIntNum ); assert( nPermBitNum % nVarNum == 0 ); // set truth table bits for ( i = 0; i < nTtBitNum; i++ ) if ( Abc_TtGetBit(pPerm + 1, i) ) Abc_TtSetBit( pArray, i ); // set permutation bits for ( v = 0; v < nVarNum; v++ ) { // get DSD variable Var = ((pPerm[0] >> (v * 4)) & 0xF); assert( Var < (int)pCutBest->nLeaves ); // get AIG literal Lit = (int)pCutPerm[Var]; assert( Abc_Lit2Var(Lit) < (int)pCutBest->nLeaves ); // complement if polarity has changed pIfObj = If_ManObj( pIfMan, pCutBest->pLeaves[Abc_Lit2Var(Lit)] ); Lit = Abc_LitNotCond( Lit, Abc_LitIsCompl(pIfObj->iCopy) ); // create config literal for ( i = 0; i < nPermBitOne; i++ ) if ( (Lit >> i) & 1 ) Abc_TtSetBit( pArray, nTtBitNum + v * nPermBitOne + i ); } // remember complementation assert( nTtBitNum + nPermBitNum < 32 * nIntNum ); if ( Abc_LitIsCompl(If_CutDsdLit(pIfMan, pCutBest)) ^ pCutBest->fCompl ^ Abc_LitIsCompl(iLit) ) Abc_TtSetBit( pArray, nTtBitNum + nPermBitNum ); // update count Vec_IntAddToEntry( vConfigs, 0, 1 ); // write configs if ( vConfigsStr ) { Vec_StrPrintF( vConfigsStr, "%d", Abc_Lit2Var(iLit) ); Vec_StrPush( vConfigsStr, ' ' ); for ( i = 0; i < nTtBitNum; i++ ) Vec_StrPush( vConfigsStr, (char)(Abc_TtGetBit(pArray, i) ? '1' : '0') ); Vec_StrPush( vConfigsStr, ' ' ); Vec_StrPush( vConfigsStr, ' ' ); for ( v = 0; v < nVarNum; v++ ) { for ( i = 0; i < nPermBitOne; i++ ) { Vec_StrPush( vConfigsStr, (char)(Abc_TtGetBit(pArray, nTtBitNum + v * nPermBitOne + i) ? '1' : '0') ); if ( i == 0 ) Vec_StrPush( vConfigsStr, ' ' ); } Vec_StrPush( vConfigsStr, ' ' ); Vec_StrPush( vConfigsStr, ' ' ); } Vec_StrPush( vConfigsStr, (char)(Abc_TtGetBit(pArray, nTtBitNum + nPermBitNum) ? '1' : '0') ); Vec_StrPush( vConfigsStr, '\n' ); } } int Gia_ManFromIfLogicFindCell( If_Man_t * pIfMan, Gia_Man_t * pNew, Gia_Man_t * pTemp, If_Cut_t * pCutBest, Ifn_Ntk_t * pNtkCell, int nLutMax, Vec_Int_t * vLeaves, Vec_Int_t * vLits, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vConfigs ) { int iLit; assert( 0 ); if ( Vec_IntSize(vLeaves) <= nLutMax ) iLit = Gia_ManFromIfLogicCreateLut( pNew, If_CutTruthW(pIfMan, pCutBest), vLeaves, vCover, vMapping, vMapping2 ); else { Gia_Obj_t * pObj; int i, Id, iLitTemp; // extract variable permutation //char * pCutPerm = If_CutDsdPerm( pIfMan, pCutBest ); // DSD input -> cut input word * pPerm = If_DsdManGetFuncConfig( pIfMan->pIfDsdMan, If_CutDsdLit(pIfMan, pCutBest) ); // cell input -> DSD input //int nBits = If_DsdManTtBitNum( pIfMan->pIfDsdMan ); // use config bits to generate the network iLit = If_ManSatDeriveGiaFromBits( pTemp, pNtkCell, pPerm + 1, vLeaves, vCover ); // copy GIA back into the manager Vec_IntFillExtra( &pTemp->vCopies, Gia_ManObjNum(pTemp), -1 ); Gia_ObjSetCopyArray( pTemp, 0, 0 ); Vec_IntForEachEntry( vLeaves, iLitTemp, i ) Gia_ObjSetCopyArray( pTemp, Gia_ManCiIdToId(pTemp, i), iLitTemp ); // collect nodes Gia_ManIncrementTravId( pTemp ); Id = Abc_Lit2Var( iLit ); Gia_ManCollectAnds( pTemp, &Id, 1, vCover, NULL ); Vec_IntPrint( vCover ); Gia_ManForEachObjVec( vCover, pTemp, pObj, i ) Gia_ObjPrint( pTemp, pObj ); // copy GIA Gia_ManForEachObjVec( vCover, pTemp, pObj, i ) { iLit = Gia_ManAppendAnd( pNew, Gia_ObjFanin0CopyArray(pTemp, pObj), Gia_ObjFanin1CopyArray(pTemp, pObj) ); Gia_ObjSetCopyArray( pTemp, Gia_ObjId(pTemp, pObj), iLit ); } iLit = Abc_LitNotCond( Gia_ObjCopyArray(pTemp, Id), Abc_LitIsCompl(iLit) ); } // write packing // if ( vConfigs && !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(iLit))) && iLit > 1 ) // Gia_ManFromIfGetConfig( vConfigs, pIfMan, pCutBest ); return iLit; } /**Function************************************************************* Synopsis [Converts IF into GIA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFromIfLogicCofVars( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, Vec_Int_t * vLeaves, Vec_Int_t * vLeaves2, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 ) { word pTruthCof[128], * pTruth = If_CutTruthW(pIfMan, pCutBest); int pVarsNew[16], nVarsNew, iLitCofs[3]; int nLeaves = pCutBest->nLeaves; int nWords = Abc_Truth6WordNum(nLeaves); int truthId = Abc_Lit2Var(pCutBest->iCutFunc); int c, iVar = Vec_StrEntry(pIfMan->vTtVars[nLeaves], truthId), iTemp, iTopLit; int k, RetValue = -1; assert( iVar >= 0 && iVar < nLeaves && pIfMan->pPars->nLutSize <= 13 ); for ( c = 0; c < 2; c++ ) { for ( k = 0; k < nLeaves; k++ ) pVarsNew[k] = k; if ( c ) Abc_TtCofactor1p( pTruthCof, pTruth, nWords, iVar ); else Abc_TtCofactor0p( pTruthCof, pTruth, nWords, iVar ); nVarsNew = Abc_TtMinBase( pTruthCof, pVarsNew, pCutBest->nLeaves, Abc_MaxInt(6, pCutBest->nLeaves) ); // derive LUT Vec_IntClear( vLeaves2 ); for ( k = 0; k < nVarsNew; k++ ) Vec_IntPush( vLeaves2, Vec_IntEntry(vLeaves, pVarsNew[k]) ); iLitCofs[c] = Kit_TruthToGia( pNew, (unsigned *)pTruthCof, nVarsNew, vCover, vLeaves2, 0 ); if ( nVarsNew < 2 ) continue; // create mapping assert( Gia_ObjIsAnd(Gia_ManObj(pNew, Abc_Lit2Var(iLitCofs[c]))) ); Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLitCofs[c]), Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, Vec_IntSize(vLeaves2) ); Vec_IntForEachEntry( vLeaves2, iTemp, k ) Vec_IntPush( vMapping2, Abc_Lit2Var(iTemp) ); Vec_IntPush( vMapping2, Abc_Lit2Var(iLitCofs[c]) ); } iLitCofs[2] = Vec_IntEntry(vLeaves, iVar); // derive MUX if ( iLitCofs[0] > 1 && iLitCofs[1] > 1 ) { pTruthCof[0] = ABC_CONST(0xCACACACACACACACA); Vec_IntClear( vLeaves2 ); Vec_IntPush( vLeaves2, iLitCofs[0] ); Vec_IntPush( vLeaves2, iLitCofs[1] ); Vec_IntPush( vLeaves2, iLitCofs[2] ); RetValue = Kit_TruthToGia( pNew, (unsigned *)pTruthCof, Vec_IntSize(vLeaves2), vCover, vLeaves2, 0 ); iTopLit = RetValue; } else { assert( iLitCofs[0] > 1 || iLitCofs[1] > 1 ); // collect leaves Vec_IntClear( vLeaves2 ); for ( k = 0; k < 3; k++ ) if ( iLitCofs[k] > 1 ) Vec_IntPush( vLeaves2, iLitCofs[k] ); assert( Vec_IntSize(vLeaves2) == 2 ); // consider three possibilities if ( iLitCofs[0] == 0 ) RetValue = Gia_ManAppendAnd( pNew, iLitCofs[2], iLitCofs[1] ); else if ( iLitCofs[0] == 1 ) RetValue = Gia_ManAppendOr( pNew, Abc_LitNot(iLitCofs[2]), iLitCofs[1] ); else if ( iLitCofs[1] == 0 ) RetValue = Gia_ManAppendAnd( pNew, Abc_LitNot(iLitCofs[2]), iLitCofs[0] ); else if ( iLitCofs[1] == 1 ) RetValue = Gia_ManAppendOr( pNew, iLitCofs[2], iLitCofs[0] ); else assert( 0 ); iTopLit = iLitCofs[2]; } // create mapping Vec_IntSetEntry( vMapping, Abc_Lit2Var(RetValue), Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, Vec_IntSize(vLeaves2) ); Vec_IntForEachEntry( vLeaves2, iTemp, k ) Vec_IntPush( vMapping2, Abc_Lit2Var(iTemp) ); Vec_IntPush( vMapping2, -Abc_Lit2Var(iTopLit) ); RetValue = Abc_LitNotCond( RetValue, pCutBest->fCompl ); return RetValue; } int Gia_ManFromIfLogicAndVars( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, Vec_Int_t * vLeaves, Vec_Int_t * vLeaves2, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 ) { word pFunc[64], uTruth[2]; int nLeaves = pCutBest->nLeaves; int truthId = Abc_Lit2Var(pCutBest->iCutFunc); int c, k, Mask = Vec_IntEntry(pIfMan->vTtDecs[nLeaves], truthId); int MaskOne[2] = { Mask & 0xFFFF, (Mask >> 16) & 0x3FFF }; int iLitCofs[2], iTemp, fOrDec = (Mask >> 30) & 1, RetValue = -1; assert( Mask > 0 && nLeaves <= 2 * (pIfMan->pPars->nLutSize/2) && pIfMan->pPars->nLutSize <= 13 ); Abc_TtCopy( pFunc, If_CutTruthWR(pIfMan, pCutBest), pIfMan->nTruth6Words[nLeaves], fOrDec ); Abc_TtDeriveBiDec( pFunc, nLeaves, MaskOne[0], MaskOne[1], pIfMan->pPars->nLutSize/2, &uTruth[0], &uTruth[1] ); uTruth[0] = fOrDec ? ~uTruth[0] : uTruth[0]; uTruth[1] = fOrDec ? ~uTruth[1] : uTruth[1]; for ( c = 0; c < 2; c++ ) { Vec_IntClear( vLeaves2 ); for ( k = 0; k < nLeaves; k++ ) if ( (MaskOne[c] >> k) & 1 ) Vec_IntPush( vLeaves2, Vec_IntEntry(vLeaves, k) ); assert( Vec_IntSize(vLeaves2) >= 1 ); iLitCofs[c] = Kit_TruthToGia( pNew, (unsigned *)&uTruth[c], Vec_IntSize(vLeaves2), vCover, vLeaves2, 0 ); if ( Vec_IntSize(vLeaves2) == 1 ) continue; // create mapping assert( Gia_ObjIsAnd(Gia_ManObj(pNew, Abc_Lit2Var(iLitCofs[c]))) ); Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLitCofs[c]), Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, Vec_IntSize(vLeaves2) ); Vec_IntForEachEntry( vLeaves2, iTemp, k ) Vec_IntPush( vMapping2, Abc_Lit2Var(iTemp) ); Vec_IntPush( vMapping2, Abc_Lit2Var(iLitCofs[c]) ); } iLitCofs[0] = Abc_LitNotCond( iLitCofs[0], fOrDec ); iLitCofs[1] = Abc_LitNotCond( iLitCofs[1], fOrDec ); RetValue = Gia_ManAppendAnd( pNew, iLitCofs[0], iLitCofs[1] ); RetValue = Abc_LitNotCond( RetValue, fOrDec ^ Abc_LitIsCompl(pCutBest->iCutFunc) ); // create mapping Vec_IntSetEntry( vMapping, Abc_Lit2Var(RetValue), Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, 2 ); Vec_IntPush( vMapping2, Abc_Lit2Var(iLitCofs[0]) ); Vec_IntPush( vMapping2, Abc_Lit2Var(iLitCofs[1]) ); Vec_IntPush( vMapping2, -Abc_Lit2Var(RetValue) ); RetValue = Abc_LitNotCond( RetValue, pCutBest->fCompl ); return RetValue; } /**Function************************************************************* Synopsis [Converts IF into GIA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan ) { int fWriteConfigs = 1; Gia_Man_t * pNew, * pHashed = NULL; If_Cut_t * pCutBest; If_Obj_t * pIfObj, * pIfLeaf; Vec_Int_t * vMapping, * vMapping2, * vPacking = NULL, * vConfigs = NULL; Vec_Int_t * vLeaves, * vLeaves2, * vCover, * vLits; Vec_Str_t * vConfigsStr = NULL; Ifn_Ntk_t * pNtkCell = NULL; sat_solver * pSat = NULL; int i, k, Entry; assert( !pIfMan->pPars->fDeriveLuts || pIfMan->pPars->fTruth ); // if ( pIfMan->pPars->fEnableCheck07 ) // pIfMan->pPars->fDeriveLuts = 0; // start mapping and packing vMapping = Vec_IntStart( If_ManObjNum(pIfMan) ); vMapping2 = Vec_IntStart( 1 ); if ( pIfMan->pPars->fDeriveLuts && (pIfMan->pPars->pLutStruct || pIfMan->pPars->fEnableCheck75 || pIfMan->pPars->fEnableCheck75u || pIfMan->pPars->fEnableCheck07) ) { vPacking = Vec_IntAlloc( 1000 ); Vec_IntPush( vPacking, 0 ); } if ( pIfMan->pPars->fUseDsdTune ) { int nTtBitNum = If_DsdManTtBitNum(pIfMan->pIfDsdMan); int nPermBitNum = If_DsdManPermBitNum(pIfMan->pIfDsdMan); int nConfigInts = Abc_BitWordNum(nTtBitNum + nPermBitNum + 1); vConfigs = Vec_IntAlloc( 1000 ); Vec_IntPush( vConfigs, 0 ); Vec_IntPush( vConfigs, nConfigInts ); if ( fWriteConfigs ) vConfigsStr = Vec_StrAlloc( 1000 ); } // create new manager pNew = Gia_ManStart( If_ManObjNum(pIfMan) ); // iterate through nodes used in the mapping vLits = Vec_IntAlloc( 1000 ); vCover = Vec_IntAlloc( 1 << 16 ); vLeaves = Vec_IntAlloc( 16 ); vLeaves2 = Vec_IntAlloc( 16 ); If_ManCleanCutData( pIfMan ); If_ManForEachObj( pIfMan, pIfObj, i ) { if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) ) continue; if ( If_ObjIsAnd(pIfObj) ) { pCutBest = If_ObjCutBest( pIfObj ); // perform sorting of cut leaves by delay, so that the slowest pin drives the fastest input of the LUT if ( !pIfMan->pPars->fUseTtPerm && !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize && !pIfMan->pPars->fEnableCheck75 && !pIfMan->pPars->fEnableCheck75u && !pIfMan->pPars->fEnableCheck07 && !pIfMan->pPars->fUseDsdTune && !pIfMan->pPars->fUseCofVars && !pIfMan->pPars->fUseAndVars && !pIfMan->pPars->fUseCheck1 && !pIfMan->pPars->fUseCheck2 && !pIfMan->pPars->fUserLutDec ) If_CutRotatePins( pIfMan, pCutBest ); // collect leaves of the best cut Vec_IntClear( vLeaves ); If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, k ) Vec_IntPush( vLeaves, pIfLeaf->iCopy ); // perform one of the two types of mapping: with and without structures if ( pIfMan->pPars->fUseDsd && pIfMan->pPars->pLutStruct ) { if ( pSat == NULL ) pSat = (sat_solver *)If_ManSatBuildXY( (int)(pIfMan->pPars->pLutStruct[0] - '0') ); if ( pIfMan->pPars->pLutStruct && pIfMan->pPars->fDeriveLuts ) pIfObj->iCopy = Gia_ManFromIfLogicFindLut( pIfMan, pNew, pCutBest, pSat, vLeaves, vLits, vCover, vMapping, vMapping2, vPacking ); else pIfObj->iCopy = Gia_ManFromIfLogicCreateLut( pNew, If_CutTruthW(pIfMan, pCutBest), vLeaves, vCover, vMapping, vMapping2 ); pIfObj->iCopy = Abc_LitNotCond( pIfObj->iCopy, pCutBest->fCompl ); } /* else if ( pIfMan->pPars->fUseDsd && pIfMan->pPars->fUseDsdTune && pIfMan->pPars->fDeriveLuts ) { if ( pNtkCell == NULL ) { assert( If_DsdManGetCellStr(pIfMan->pIfDsdMan) != NULL ); pNtkCell = Ifn_NtkParse( If_DsdManGetCellStr(pIfMan->pIfDsdMan) ); nLutMax = Ifn_NtkLutSizeMax( pNtkCell ); pHashed = Gia_ManStart( 10000 ); Vec_IntFillExtra( &pHashed->vCopies, 10000, -1 ); for ( k = 0; k < pIfMan->pPars->nLutSize; k++ ) Gia_ManAppendCi( pHashed ); Gia_ManHashAlloc( pHashed ); } pIfObj->iCopy = Gia_ManFromIfLogicFindCell( pIfMan, pNew, pHashed, pCutBest, pNtkCell, nLutMax, vLeaves, vLits, vCover, vMapping, vMapping2, vConfigs ); pIfObj->iCopy = Abc_LitNotCond( pIfObj->iCopy, pCutBest->fCompl ); } */ else if ( pIfMan->pPars->fUseAndVars && pIfMan->pPars->fUseCofVars && pIfMan->pPars->fDeriveLuts && (int)pCutBest->nLeaves > pIfMan->pPars->nLutSize/2 ) { int truthId = Abc_Lit2Var(pCutBest->iCutFunc); int Mask = Vec_IntEntry(pIfMan->vTtDecs[pCutBest->nLeaves], truthId); if ( Mask ) pIfObj->iCopy = Gia_ManFromIfLogicAndVars( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 ); else pIfObj->iCopy = Gia_ManFromIfLogicCofVars( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 ); } else if ( pIfMan->pPars->fUseAndVars && pIfMan->pPars->fDeriveLuts && (int)pCutBest->nLeaves > pIfMan->pPars->nLutSize/2 ) { pIfObj->iCopy = Gia_ManFromIfLogicAndVars( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 ); } else if ( pIfMan->pPars->fUseCofVars && pIfMan->pPars->fDeriveLuts && (int)pCutBest->nLeaves > pIfMan->pPars->nLutSize/2 ) { pIfObj->iCopy = Gia_ManFromIfLogicCofVars( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 ); } else if ( pIfMan->pPars->fUserLutDec && (int)pCutBest->nLeaves > pIfMan->pPars->nLutDecSize ) { pIfObj->iCopy = Gia_ManFromIfLogicHop( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 ); } else if ( (pIfMan->pPars->fDeriveLuts && pIfMan->pPars->fTruth) || pIfMan->pPars->fUseDsd || pIfMan->pPars->fUseTtPerm || pIfMan->pPars->pFuncCell2 ) { word * pTruth = If_CutTruthW(pIfMan, pCutBest); if ( pIfMan->pPars->fUseTtPerm ) for ( k = 0; k < (int)pCutBest->nLeaves; k++ ) if ( If_CutLeafBit(pCutBest, k) ) Abc_TtFlip( pTruth, Abc_TtWordNum(pCutBest->nLeaves), k ); // perform decomposition of the cut pIfObj->iCopy = Gia_ManFromIfLogicNode( pIfMan, pNew, i, vLeaves, vLeaves2, pTruth, pIfMan->pPars->pLutStruct, vCover, vMapping, vMapping2, vPacking, (pIfMan->pPars->fEnableCheck75 || pIfMan->pPars->fEnableCheck75u), pIfMan->pPars->fEnableCheck07 ); pIfObj->iCopy = Abc_LitNotCond( pIfObj->iCopy, pCutBest->fCompl ); if ( vConfigs && Vec_IntSize(vLeaves) > 1 && !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(pIfObj->iCopy))) && pIfObj->iCopy > 1 ) Gia_ManFromIfGetConfig( vConfigs, pIfMan, pCutBest, pIfObj->iCopy, vConfigsStr ); } else { pIfObj->iCopy = Gia_ManNodeIfToGia( pNew, pIfMan, pIfObj, vLeaves, 0 ); // write mapping Vec_IntSetEntry( vMapping, Abc_Lit2Var(pIfObj->iCopy), Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); Vec_IntForEachEntry( vLeaves, Entry, k ) assert( Abc_Lit2Var(Entry) < Abc_Lit2Var(pIfObj->iCopy) ); Vec_IntForEachEntry( vLeaves, Entry, k ) Vec_IntPush( vMapping2, Abc_Lit2Var(Entry) ); Vec_IntPush( vMapping2, Abc_Lit2Var(pIfObj->iCopy) ); } } else if ( If_ObjIsCi(pIfObj) ) pIfObj->iCopy = Gia_ManAppendCi(pNew); else if ( If_ObjIsCo(pIfObj) ) pIfObj->iCopy = Gia_ManAppendCo( pNew, Abc_LitNotCond(If_ObjFanin0(pIfObj)->iCopy, If_ObjFaninC0(pIfObj)) ); else if ( If_ObjIsConst1(pIfObj) ) { pIfObj->iCopy = 1; // create const LUT Vec_IntWriteEntry( vMapping, 0, Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, 0 ); Vec_IntPush( vMapping2, 0 ); } else assert( 0 ); } Vec_IntFree( vLits ); Vec_IntFree( vCover ); Vec_IntFree( vLeaves ); Vec_IntFree( vLeaves2 ); if ( pNtkCell ) ABC_FREE( pNtkCell ); if ( pSat ) sat_solver_delete(pSat); if ( pHashed ) Gia_ManStop( pHashed ); // printf( "Mapping array size: IfMan = %d. Gia = %d. Increase = %.2f\n", // If_ManObjNum(pIfMan), Gia_ManObjNum(pNew), 1.0 * Gia_ManObjNum(pNew) / If_ManObjNum(pIfMan) ); // finish mapping if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) ) Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) ); else Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 ); assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) ); Vec_IntForEachEntry( vMapping, Entry, i ) if ( Entry > 0 ) Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) ); Vec_IntAppend( vMapping, vMapping2 ); Vec_IntFree( vMapping2 ); // attach mapping and packing assert( pNew->vMapping == NULL ); assert( pNew->vPacking == NULL ); assert( pNew->vConfigs == NULL ); assert( pNew->pCellStr == NULL ); pNew->vMapping = vMapping; pNew->vPacking = vPacking; pNew->vConfigs = vConfigs; pNew->pCellStr = vConfigs ? Abc_UtilStrsav( If_DsdManGetCellStr(pIfMan->pIfDsdMan) ) : NULL; assert( !vConfigs || Vec_IntSize(vConfigs) == 2 + Vec_IntEntry(vConfigs, 0) * Vec_IntEntry(vConfigs, 1) ); // verify that COs have mapping { Gia_Obj_t * pObj; Gia_ManForEachCo( pNew, pObj, i ) assert( !Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) || Gia_ObjIsLut(pNew, Gia_ObjFaninId0p(pNew, pObj)) ); } // verify that internal nodes have mapping { Gia_Obj_t * pFanin; Gia_ManForEachLut( pNew, i ) Gia_LutForEachFaninObj( pNew, i, pFanin, k ) assert( !Gia_ObjIsAnd(pFanin) || Gia_ObjIsLut(pNew, Gia_ObjId(pNew, pFanin)) ); } // verify that CIs have no mapping { Gia_Obj_t * pObj; Gia_ManForEachCi( pNew, pObj, i ) assert( !Gia_ObjIsLut(pNew, Gia_ObjId(pNew, pObj)) ); } // dump configuration strings if ( vConfigsStr ) { FILE * pFile; int status; char * pStr, Buffer[1000] = {0}; const char * pNameGen = pIfMan->pName? Extra_FileNameGeneric( pIfMan->pName ) : "nameless_"; sprintf( Buffer, "%s_configs.txt", pNameGen ); ABC_FREE( pNameGen ); pFile = fopen( Buffer, "wb" ); if ( pFile == NULL ) { Vec_StrFree( vConfigsStr ); printf( "Cannot open file \"%s\".\n", Buffer ); return pNew; } Vec_StrPush( vConfigsStr, '\0' ); pStr = Vec_StrArray(vConfigsStr); status = fwrite( pStr, strlen(pStr), 1, pFile ); Vec_StrFree( vConfigsStr ); fclose( pFile ); printf( "Finished dumping configs into file \"%s\".\n", Buffer ); } return pNew; } /**Function************************************************************* Synopsis [Verifies mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManMappingVerify_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { int Id, iFan, k, Result = 1; if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 1; Gia_ObjSetTravIdCurrent(p, pObj); if ( !Gia_ObjIsAndNotBuf(pObj) ) return 1; if ( !Gia_ObjIsLut(p, Gia_ObjId(p, pObj)) ) { Abc_Print( -1, "Gia_ManMappingVerify: Internal node %d does not have mapping.\n", Gia_ObjId(p, pObj) ); return 0; } Id = Gia_ObjId(p, pObj); Gia_LutForEachFanin( p, Id, iFan, k ) if ( Result ) Result &= Gia_ManMappingVerify_rec( p, Gia_ManObj(p, iFan) ); return Result; } void Gia_ManMappingVerify( Gia_Man_t * p ) { Gia_Obj_t * pObj, * pFanin; int i, Result = 1; assert( Gia_ManHasMapping(p) ); Gia_ManIncrementTravId( p ); Gia_ManForEachBuf( p, pObj, i ) { pFanin = Gia_ObjFanin0(pObj); if ( !Gia_ObjIsAndNotBuf(pFanin) ) continue; if ( !Gia_ObjIsLut(p, Gia_ObjId(p, pFanin)) ) { Abc_Print( -1, "Gia_ManMappingVerify: Buffer driver %d does not have mapping.\n", Gia_ObjId(p, pFanin) ); Result = 0; continue; } Result &= Gia_ManMappingVerify_rec( p, pFanin ); } Gia_ManForEachCo( p, pObj, i ) { pFanin = Gia_ObjFanin0(pObj); if ( !Gia_ObjIsAndNotBuf(pFanin) ) continue; if ( !Gia_ObjIsLut(p, Gia_ObjId(p, pFanin)) ) { Abc_Print( -1, "Gia_ManMappingVerify: CO driver %d does not have mapping.\n", Gia_ObjId(p, pFanin) ); Result = 0; continue; } Result &= Gia_ManMappingVerify_rec( p, pFanin ); } // if ( Result && Gia_NtkIsRoot(p) ) // Abc_Print( 1, "Mapping verified correctly.\n" ); } /**Function************************************************************* Synopsis [Transfers mapping from hie GIA to normalized GIA.] Description [Hie GIA (pGia) points to normalized GIA (p).] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManTransferMapping( Gia_Man_t * p, Gia_Man_t * pGia ) { Gia_Obj_t * pObj; int i, k, iFan, iPlace; if ( !Gia_ManHasMapping(pGia) ) return; Gia_ManMappingVerify( pGia ); Vec_IntFreeP( &p->vMapping ); p->vMapping = Vec_IntAlloc( 2 * Gia_ManObjNum(p) ); Vec_IntFill( p->vMapping, Gia_ManObjNum(p), 0 ); Gia_ManForEachLut( pGia, i ) { if ( Gia_ObjValue(Gia_ManObj(pGia, i)) == ~0 ) // handle dangling LUT continue; assert( !Abc_LitIsCompl(Gia_ObjValue(Gia_ManObj(pGia, i))) ); pObj = Gia_ManObj( p, Abc_Lit2Var(Gia_ObjValue(Gia_ManObj(pGia, i))) ); Vec_IntWriteEntry( p->vMapping, Gia_ObjId(p, pObj), Vec_IntSize(p->vMapping) ); iPlace = Vec_IntSize( p->vMapping ); Vec_IntPush( p->vMapping, Gia_ObjLutSize(pGia, i) ); Gia_LutForEachFanin( pGia, i, iFan, k ) { if ( Gia_ObjValue(Gia_ManObj(pGia, iFan)) == ~0 ) // handle dangling LUT fanin Vec_IntAddToEntry( p->vMapping, iPlace, -1 ); else Vec_IntPush( p->vMapping, Abc_Lit2Var(Gia_ObjValue(Gia_ManObj(pGia, iFan))) ); } iFan = Abc_Lit2Var( Gia_ObjValue(Gia_ManObj(pGia, Abc_AbsInt(Gia_ObjLutMuxId(pGia, i)))) ); Vec_IntPush( p->vMapping, Gia_ObjLutIsMux(pGia, i) ? -iFan : iFan ); } Gia_ManMappingVerify( p ); } void Gia_ManTransferPacking( Gia_Man_t * p, Gia_Man_t * pGia ) { Vec_Int_t * vPackingNew; Gia_Obj_t * pObj, * pObjNew; int i, k, Entry, nEntries, nEntries2; if ( pGia->vPacking == NULL ) return; nEntries = Vec_IntEntry( pGia->vPacking, 0 ); nEntries2 = 0; // create new packing info vPackingNew = Vec_IntAlloc( Vec_IntSize(pGia->vPacking) ); Vec_IntPush( vPackingNew, nEntries ); Vec_IntForEachEntryStart( pGia->vPacking, Entry, i, 1 ) { assert( Entry > 0 && Entry < 4 ); Vec_IntPush( vPackingNew, Entry ); i++; for ( k = 0; k < Entry; k++, i++ ) { pObj = Gia_ManObj(pGia, Vec_IntEntry(pGia->vPacking, i)); pObjNew = Gia_ManObj(p, Abc_Lit2Var(Gia_ObjValue(pObj))); assert( Gia_ObjIsLut(pGia, Gia_ObjId(pGia, pObj)) ); assert( Gia_ObjIsLut(p, Gia_ObjId(p, pObjNew)) ); Vec_IntPush( vPackingNew, Gia_ObjId(p, pObjNew) ); // printf( "%d -> %d ", Vec_IntEntry(pGia->vPacking, i), Gia_ObjId(p, pObjNew) ); } i--; nEntries2++; } assert( nEntries == nEntries2 ); // attach packing info assert( p->vPacking == NULL ); p->vPacking = vPackingNew; } void Gia_ManTransferTiming( Gia_Man_t * p, Gia_Man_t * pGia ) { if ( p == pGia ) return; if ( pGia->vCiArrs || pGia->vCoReqs || pGia->vCoArrs || pGia->vCoAttrs ) { p->vCiArrs = pGia->vCiArrs; pGia->vCiArrs = NULL; p->vCoReqs = pGia->vCoReqs; pGia->vCoReqs = NULL; p->vCoArrs = pGia->vCoArrs; pGia->vCoArrs = NULL; p->vCoAttrs = pGia->vCoAttrs; pGia->vCoAttrs = NULL; p->And2Delay = pGia->And2Delay; } if ( pGia->vInArrs || pGia->vOutReqs ) { p->vInArrs = pGia->vInArrs; pGia->vInArrs = NULL; p->vOutReqs = pGia->vOutReqs; pGia->vOutReqs = NULL; p->DefInArrs = pGia->DefInArrs; p->DefOutReqs = pGia->DefOutReqs; p->And2Delay = pGia->And2Delay; } 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 ) { p->vConfigs = pGia->vConfigs; pGia->vConfigs = NULL; p->pCellStr = pGia->pCellStr; pGia->pCellStr = NULL; } if ( pGia->pManTime == NULL ) return; p->pManTime = pGia->pManTime; pGia->pManTime = NULL; p->pAigExtra = pGia->pAigExtra; pGia->pAigExtra = NULL; p->vRegClasses = pGia->vRegClasses; pGia->vRegClasses = NULL; p->vRegInits = pGia->vRegInits; pGia->vRegInits = NULL; p->nAnd2Delay = pGia->nAnd2Delay; pGia->nAnd2Delay = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameMiniAigSetCiArrivals( Abc_Frame_t * pAbc, int * pArrivals ) { Gia_Man_t * pGia; if ( pArrivals == NULL ) { printf( "Arrival times are not given.\n" ); return; } if ( pAbc == NULL ) { printf( "ABC framework is not initialized by calling Abc_Start().\n" ); return; } pGia = Abc_FrameReadGia( pAbc ); if ( pGia == NULL ) { printf( "Current network in ABC framework is not defined.\n" ); return; } Vec_IntFreeP( &pGia->vCiArrs ); pGia->vCiArrs = Vec_IntAllocArrayCopy( pArrivals, Gia_ManCiNum(pGia) ); } void Abc_FrameMiniAigSetCoRequireds( Abc_Frame_t * pAbc, int * pRequireds ) { Gia_Man_t * pGia; if ( pRequireds == NULL ) { printf( "Required times are not given.\n" ); return; } if ( pAbc == NULL ) { printf( "ABC framework is not initialized by calling Abc_Start().\n" ); return; } pGia = Abc_FrameReadGia( pAbc ); if ( pGia == NULL ) { printf( "Current network in ABC framework is not defined.\n" ); return; } Vec_IntFreeP( &pGia->vCoReqs ); pGia->vCoReqs = Vec_IntAllocArrayCopy( pRequireds, Gia_ManCoNum(pGia) ); } int * Abc_FrameMiniAigReadCoArrivals( Abc_Frame_t * pAbc ) { Vec_Int_t * vArrs; int * pArrs; Gia_Man_t * pGia; if ( pAbc == NULL ) { printf( "ABC framework is not initialized by calling Abc_Start()\n" ); return NULL; } pGia = Abc_FrameReadGia( pAbc ); if ( pGia == NULL ) { printf( "Current network in ABC framework is not defined.\n" ); return NULL; } if ( pGia->vCoArrs == NULL ) { printf( "Current network in ABC framework has no CO arrival times.\n" ); return NULL; } vArrs = Vec_IntDup( pGia->vCoArrs ); pArrs = Vec_IntReleaseArray( vArrs ); Vec_IntFree( vArrs ); return pArrs; } void Abc_FrameMiniAigSetAndGateDelay( Abc_Frame_t * pAbc, int Delay ) { Gia_Man_t * pGia; if ( pAbc == NULL ) printf( "ABC framework is not initialized by calling Abc_Start()\n" ); pGia = Abc_FrameReadGia( pAbc ); if ( pGia == NULL ) printf( "Current network in ABC framework is not defined.\n" ); pGia->And2Delay = Delay; } /**Function************************************************************* Synopsis [Interface of LUT mapping package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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;//, Id, EntryF; assert( pPars->pTimesArr == NULL ); assert( pPars->pTimesReq == NULL ); if ( p->vCiArrs ) { assert( Vec_IntSize(p->vCiArrs) == Gia_ManCiNum(p) ); pPars->pTimesArr = ABC_CALLOC( float, Gia_ManCiNum(p) ); 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) ); pPars->pTimesReq = ABC_CALLOC( float, Gia_ManCoNum(p) ); 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 if ( !pPars->fDelayOpt && !pPars->fDelayOptLut && !pPars->fDsdBalance && !pPars->fUserRecLib && !pPars->fUserSesLib && !pPars->fDeriveLuts && !pPars->fUseDsd && !pPars->fUseTtPerm && !pPars->pFuncCell2 ) pPars->fCutMin = 0; // translate into the mapper pIfMan = Gia_ManToIf( p, pPars ); if ( pIfMan == NULL ) return NULL; // create DSD manager if ( pPars->fUseDsd ) { If_DsdMan_t * p = (If_DsdMan_t *)Abc_FrameReadManDsd(); assert( pPars->nLutSize <= If_DsdManVarNum(p) ); assert( (pPars->pLutStruct == NULL && If_DsdManLutSize(p) == 0) || (pPars->pLutStruct && pPars->pLutStruct[0] - '0' == If_DsdManLutSize(p)) ); pIfMan->pIfDsdMan = (If_DsdMan_t *)Abc_FrameReadManDsd(); if ( pPars->fDsdBalance ) If_DsdManAllocIsops( pIfMan->pIfDsdMan, pPars->nLutSize ); } // compute switching for the IF objects if ( pPars->fPower ) { if ( p->pManTime == NULL ) If_ManComputeSwitching( pIfMan ); else Abc_Print( 0, "Switching activity computation for designs with boxes is disabled.\n" ); } if ( pPars->pReoMan ) pIfMan->pUserMan = pPars->pReoMan; if ( p->pManTime ) pIfMan->pManTim = Tim_ManDup( (Tim_Man_t *)p->pManTime, pPars->fDelayOpt || pPars->fDelayOptLut || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib ); // Tim_ManPrint( pIfMan->pManTim ); if ( p->vCoAttrs ) { assert( If_ManCoNum(pIfMan) == Vec_IntSize(p->vCoAttrs) ); Vec_IntForEachEntry( p->vCoAttrs, Entry, i ) If_ObjFanin0( If_ManCo(pIfMan, i) )->fSpec = (Entry != 0); } if ( !If_ManPerformMapping( pIfMan ) ) { If_ManStop( pIfMan ); return NULL; } if ( pPars->pFuncWrite ) pPars->pFuncWrite( pIfMan ); // transform the result of mapping into the new network if ( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib || pIfMan->pPars->fUserSesLib ) pNew = Gia_ManFromIfAig( pIfMan ); else pNew = Gia_ManFromIfLogic( pIfMan ); if ( p->vCiArrs || p->vCoReqs ) { If_Obj_t * pIfObj = NULL; Vec_IntFreeP( &p->vCoArrs ); p->vCoArrs = Vec_IntAlloc( Gia_ManCoNum(p) ); If_ManForEachCo( pIfMan, pIfObj, i ) Vec_IntPush( p->vCoArrs, (int)If_ObjArrTime(If_ObjFanin0(pIfObj)) ); } If_ManStop( pIfMan ); // 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 ) { Gia_Man_t * pNew; if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) && Gia_ManIsNormalized(p) ) { pNew = Gia_ManDupUnnormalize( p ); if ( pNew == NULL ) return NULL; Gia_ManTransferTiming( pNew, p ); p = pNew; // mapping pNew = Gia_ManPerformMappingInt( p, (If_Par_t *)pp ); if ( pNew != p ) { Gia_ManTransferTiming( pNew, p ); Gia_ManStop( p ); } // normalize pNew = Gia_ManDupNormalize( p = pNew, ((If_Par_t *)pp)->fHashMapping ); Gia_ManTransferMapping( pNew, p ); Gia_ManTransferPacking( pNew, p ); Gia_ManTransferTiming( pNew, p ); Gia_ManStop( p ); assert( Gia_ManIsNormalized(pNew) ); } else { pNew = Gia_ManPerformMappingInt( p, (If_Par_t *)pp ); Gia_ManTransferTiming( pNew, p ); if ( ((If_Par_t *)pp)->fHashMapping ) { pNew = Gia_ManDupHashMapping( p = pNew ); Gia_ManTransferPacking( pNew, p ); Gia_ManTransferTiming( pNew, p ); Gia_ManStop( p ); } } pNew->MappedDelay = (int)((If_Par_t *)pp)->FinalDelay; pNew->MappedArea = (int)((If_Par_t *)pp)->FinalArea; return pNew; } /**Function************************************************************* Synopsis [Interface of other mapping-based procedures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManPerformSopBalance( Gia_Man_t * p, int nCutNum, int nRelaxRatio, int fVerbose ) { Gia_Man_t * pNew; If_Man_t * pIfMan; If_Par_t Pars, * pPars = &Pars; If_ManSetDefaultPars( pPars ); pPars->nCutsMax = nCutNum; pPars->nRelaxRatio = nRelaxRatio; pPars->fVerbose = fVerbose; pPars->nLutSize = 6; pPars->fDelayOpt = 1; pPars->fCutMin = 1; pPars->fTruth = 1; pPars->fExpRed = 0; // perform mapping pIfMan = Gia_ManToIf( p, pPars ); If_ManPerformMapping( pIfMan ); pNew = Gia_ManFromIfAig( pIfMan ); If_ManStop( pIfMan ); Gia_ManTransferTiming( pNew, p ); // transfer name assert( pNew->pName == NULL ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } Gia_Man_t * Gia_ManPerformDsdBalance( Gia_Man_t * p, int nLutSize, int nCutNum, int nRelaxRatio, int fVerbose ) { Gia_Man_t * pNew; If_Man_t * pIfMan; If_Par_t Pars, * pPars = &Pars; If_ManSetDefaultPars( pPars ); pPars->nCutsMax = nCutNum; pPars->nRelaxRatio = nRelaxRatio; pPars->fVerbose = fVerbose; pPars->nLutSize = nLutSize; pPars->fDsdBalance = 1; pPars->fUseDsd = 1; pPars->fCutMin = 1; pPars->fTruth = 1; pPars->fExpRed = 0; if ( Abc_FrameReadManDsd2() == NULL ) Abc_FrameSetManDsd2( If_DsdManAlloc(pPars->nLutSize, 0) ); // perform mapping pIfMan = Gia_ManToIf( p, pPars ); pIfMan->pIfDsdMan = (If_DsdMan_t *)Abc_FrameReadManDsd2(); if ( pPars->fDsdBalance ) If_DsdManAllocIsops( pIfMan->pIfDsdMan, pPars->nLutSize ); If_ManPerformMapping( pIfMan ); pNew = Gia_ManFromIfAig( pIfMan ); If_ManStop( pIfMan ); Gia_ManTransferTiming( pNew, p ); // transfer name assert( pNew->pName == NULL ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Tests decomposition structures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManTestStruct( Gia_Man_t * p ) { int nCutMax = 7; int LutCount[8] = {0}, LutNDecomp[8] = {0}; int i, k, iFan, nFanins, Status; Vec_Int_t * vLeaves; word * pTruth; vLeaves = Vec_IntAlloc( 100 ); Gia_ObjComputeTruthTableStart( p, nCutMax ); Gia_ManForEachLut( p, i ) { nFanins = Gia_ObjLutSize(p, i); assert( nFanins <= 7 ); LutCount[Abc_MaxInt(nFanins, 5)]++; if ( nFanins <= 5 ) continue; Vec_IntClear( vLeaves ); Gia_LutForEachFanin( p, i, iFan, k ) Vec_IntPush( vLeaves, iFan ); pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, i), vLeaves ); // check if it is decomposable Status = If_CutPerformCheck07( NULL, (unsigned *)pTruth, 7, nFanins, NULL ); if ( Status == 1 ) continue; LutNDecomp[nFanins]++; if ( LutNDecomp[nFanins] > 10 ) continue; Kit_DsdPrintFromTruth( (unsigned *)pTruth, nFanins ); printf( "\n" ); } Gia_ObjComputeTruthTableStop( p ); printf( "LUT5 = %d ", LutCount[5] ); printf( "LUT6 = %d NonDec = %d (%.2f %%) ", LutCount[6], LutNDecomp[6], 100.0 * LutNDecomp[6]/Abc_MaxInt(LutCount[6], 1) ); printf( "LUT7 = %d NonDec = %d (%.2f %%) ", LutCount[7], LutNDecomp[7], 100.0 * LutNDecomp[7]/Abc_MaxInt(LutCount[7], 1) ); printf( "\n" ); } /**Function************************************************************* Synopsis [Performs hashing for a mapped AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupHashMapping( Gia_Man_t * p ) { Gia_Man_t * pNew; Vec_Int_t * vMapping; Gia_Obj_t * pObj, * pFanin; int i, k; assert( Gia_ManHasMapping(p) ); // copy the old manager with hashing pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // recreate mapping vMapping = Vec_IntAlloc( Vec_IntSize(p->vMapping) ); 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; return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaIff.c000066400000000000000000000361241477524141600156260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaIff.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Hierarchical mapping of AIG with white boxes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaIff.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "map/if/if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Iff_Man_t_ Iff_Man_t; struct Iff_Man_t_ { Gia_Man_t * pGia; // mapped GIA If_LibLut_t * pLib; // LUT library int nLutSize; // LUT size int nDegree; // degree Vec_Flt_t * vTimes; // arrival times Vec_Int_t * vMatch[4]; // matches }; static inline float Iff_ObjTimeId( Iff_Man_t * p, int iObj ) { return Vec_FltEntry( p->vTimes, iObj ); } static inline float Iff_ObjTime( Iff_Man_t * p, Gia_Obj_t * pObj ) { return Iff_ObjTimeId( p, Gia_ObjId(p->pGia, pObj) ); } static inline void Iff_ObjSetTimeId( Iff_Man_t * p, int iObj, float Time ) { Vec_FltWriteEntry( p->vTimes, iObj, Time ); } static inline void Iff_ObjSetTime( Iff_Man_t * p, Gia_Obj_t * pObj, float Time ) { Iff_ObjSetTimeId( p, Gia_ObjId(p->pGia, pObj), Time ); } static inline int Iff_ObjMatchId( Iff_Man_t * p, int iObj, int Type ) { return Vec_IntEntry( p->vMatch[Type], iObj ); } static inline int Iff_ObjMatch( Iff_Man_t * p, Gia_Obj_t * pObj, int Type ) { return Iff_ObjMatchId( p, Gia_ObjId(p->pGia, pObj), Type ); } static inline void Iff_ObjSetMatchId( Iff_Man_t * p, int iObj, int Type, int Match ) { Vec_IntWriteEntry( p->vMatch[Type], iObj, Match ); } static inline void Iff_ObjSetMatch( Iff_Man_t * p, Gia_Obj_t * pObj, int Type, int Match ) { Iff_ObjSetMatchId( p, Gia_ObjId(p->pGia, pObj), Type, Match );} //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Iff_Man_t * Gia_ManIffStart( Gia_Man_t * pGia ) { Iff_Man_t * p = ABC_CALLOC( Iff_Man_t, 1 ); p->vTimes = Vec_FltStartFull( Gia_ManObjNum(pGia) ); p->vMatch[2] = Vec_IntStartFull( Gia_ManObjNum(pGia) ); p->vMatch[3] = Vec_IntStartFull( Gia_ManObjNum(pGia) ); return p; } void Gia_ManIffStop( Iff_Man_t * p ) { Vec_FltFree( p->vTimes ); Vec_IntFree( p->vMatch[2] ); Vec_IntFree( p->vMatch[3] ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Count the number of unique fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_IffObjCount( Gia_Man_t * pGia, int iObj, int iFaninSkip2, int iFaninSkip3 ) { int i, iFanin, Count = 0; Gia_ManIncrementTravId( pGia ); Gia_LutForEachFanin( pGia, iObj, iFanin, i ) { if ( iFanin == iFaninSkip2 || iFanin == iFaninSkip3 ) continue; if ( Gia_ObjIsTravIdCurrentId( pGia, iFanin ) ) continue; Gia_ObjSetTravIdCurrentId( pGia, iFanin ); Count++; } if ( iFaninSkip2 >= 0 ) { Gia_LutForEachFanin( pGia, iFaninSkip2, iFanin, i ) { if ( iFanin == iFaninSkip3 ) continue; if ( Gia_ObjIsTravIdCurrentId( pGia, iFanin ) ) continue; Gia_ObjSetTravIdCurrentId( pGia, iFanin ); Count++; } } if ( iFaninSkip3 >= 0 ) { Gia_LutForEachFanin( pGia, iFaninSkip3, iFanin, i ) { if ( iFanin == iFaninSkip2 ) continue; if ( Gia_ObjIsTravIdCurrentId( pGia, iFanin ) ) continue; Gia_ObjSetTravIdCurrentId( pGia, iFanin ); Count++; } } return Count; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Gia_IffObjTimeOne( Iff_Man_t * p, int iObj, int iFaninSkip2, int iFaninSkip3 ) { int i, iFanin; float DelayMax = -ABC_INFINITY; Gia_LutForEachFanin( p->pGia, iObj, iFanin, i ) if ( iFanin != iFaninSkip2 && iFanin != iFaninSkip3 && DelayMax < Iff_ObjTimeId(p, iFanin) ) DelayMax = Iff_ObjTimeId(p, iFanin); assert( i == Gia_ObjLutSize(p->pGia, iObj) ); if ( iFaninSkip2 == -1 ) return DelayMax; Gia_LutForEachFanin( p->pGia, iFaninSkip2, iFanin, i ) if ( iFanin != iFaninSkip3 && DelayMax < Iff_ObjTimeId(p, iFanin) ) DelayMax = Iff_ObjTimeId(p, iFanin); if ( iFaninSkip3 == -1 ) return DelayMax; Gia_LutForEachFanin( p->pGia, iFaninSkip3, iFanin, i ) if ( iFanin != iFaninSkip2 && DelayMax < Iff_ObjTimeId(p, iFanin) ) DelayMax = Iff_ObjTimeId(p, iFanin); assert( DelayMax >= 0 ); return DelayMax; } float Gia_IffObjTimeTwo( Iff_Man_t * p, int iObj, int * piFanin, float DelayMin ) { int i, iFanin, nSize; float This; *piFanin = -1; Gia_LutForEachFanin( p->pGia, iObj, iFanin, i ) { if ( Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin)) ) continue; This = Gia_IffObjTimeOne( p, iObj, iFanin, -1 ); nSize = Gia_IffObjCount( p->pGia, iObj, iFanin, -1 ); assert( nSize <= p->pLib->LutMax ); This += p->pLib->pLutDelays[nSize][0]; if ( DelayMin > This ) { DelayMin = This; *piFanin = iFanin; } } return DelayMin; } float Gia_IffObjTimeThree( Iff_Man_t * p, int iObj, int * piFanin, int * piFanin2, float DelayMin ) { int i, k, iFanin, iFanin2, nSize; float This; *piFanin = -1; *piFanin2 = -1; Gia_LutForEachFanin( p->pGia, iObj, iFanin, i ) Gia_LutForEachFanin( p->pGia, iObj, iFanin2, k ) { if ( iFanin == iFanin2 ) continue; if ( Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin)) ) continue; if ( Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin2)) ) continue; This = Gia_IffObjTimeOne( p, iObj, iFanin, iFanin2 ); nSize = Gia_IffObjCount( p->pGia, iObj, iFanin, iFanin2 ); assert( nSize <= p->pLib->LutMax ); This += p->pLib->pLutDelays[nSize][0]; if ( DelayMin > This ) { DelayMin = This; *piFanin = iFanin; *piFanin2 = iFanin2; } } return DelayMin; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Iff_Man_t * Gia_ManIffPerform( Gia_Man_t * pGia, If_LibLut_t * pLib, Tim_Man_t * pTime, int nLutSize, int nDegree ) { Iff_Man_t * p; Gia_Obj_t * pObj; int iObj, iFanin, iFanin1, iFanin2; int CountAll = 0, Count2 = 0, Count3 = 0; float arrTime1, arrTime2, arrTime3, arrMax = -ABC_INFINITY; assert( nDegree == 2 || nDegree == 3 ); // start the mapping manager and set its parameters p = Gia_ManIffStart( pGia ); p->pGia = pGia; p->pLib = pLib; p->nLutSize = nLutSize; p->nDegree = nDegree; // compute arrival times of each node Iff_ObjSetTimeId( p, 0, 0 ); Tim_ManIncrementTravId( pTime ); Gia_ManForEachObj1( pGia, pObj, iObj ) { if ( Gia_ObjIsAnd(pObj) ) { if ( !Gia_ObjIsLut(pGia, iObj) ) continue; CountAll++; // compute arrival times of LUT inputs arrTime1 = Gia_IffObjTimeOne( p, iObj, -1, -1 ); arrTime1 += p->pLib->pLutDelays[Gia_ObjLutSize(pGia, iObj)][0]; // compute arrival times of LUT pairs arrTime2 = Gia_IffObjTimeTwo( p, iObj, &iFanin, arrTime1 ); if ( nDegree == 2 ) { // set arrival times Iff_ObjSetTimeId( p, iObj, arrTime2 ); if ( arrTime2 < arrTime1 ) Iff_ObjSetMatchId( p, iObj, 2, iFanin ), Count2++; } else if ( nDegree == 3 ) { // compute arrival times of LUT triples arrTime3 = Gia_IffObjTimeThree( p, iObj, &iFanin1, &iFanin2, arrTime2 ); // set arrival times Iff_ObjSetTimeId( p, iObj, arrTime3 ); if ( arrTime3 == arrTime1 ) continue; if ( arrTime3 == arrTime2 ) Iff_ObjSetMatchId( p, iObj, 2, iFanin ), Count2++; else { assert( arrTime3 < arrTime2 ); Iff_ObjSetMatchId( p, iObj, 2, iFanin1 ); Iff_ObjSetMatchId( p, iObj, 3, iFanin2 ), Count3++; } } else assert( 0 ); } else if ( Gia_ObjIsCi(pObj) ) { arrTime1 = Tim_ManGetCiArrival( pTime, Gia_ObjCioId(pObj) ); Iff_ObjSetTime( p, pObj, arrTime1 ); } else if ( Gia_ObjIsCo(pObj) ) { arrTime1 = Iff_ObjTimeId( p, Gia_ObjFaninId0p(pGia, pObj) ); Tim_ManSetCoArrival( pTime, Gia_ObjCioId(pObj), arrTime1 ); Iff_ObjSetTime( p, pObj, arrTime1 ); arrMax = Abc_MaxFloat( arrMax, arrTime1 ); } else assert( 0 ); } printf( "Max delay = %.2f. Count1 = %d. Count2 = %d. Count3 = %d.\n", arrMax, CountAll - Count2 - Count3, Count2, Count3 ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManIffSelect_rec( Iff_Man_t * p, int iObj, Vec_Int_t * vPacking ) { int i, iFanin, iFaninSkip2, iFaninSkip3; if ( Gia_ObjIsTravIdCurrentId( p->pGia, iObj ) ) return; Gia_ObjSetTravIdCurrentId( p->pGia, iObj ); assert( Gia_ObjIsLut(p->pGia, iObj) ); iFaninSkip2 = Iff_ObjMatchId(p, iObj, 2); iFaninSkip3 = Iff_ObjMatchId(p, iObj, 3); if ( iFaninSkip2 == -1 ) { assert( iFaninSkip3 == -1 ); Gia_LutForEachFanin( p->pGia, iObj, iFanin, i ) Gia_ManIffSelect_rec( p, iFanin, vPacking ); Vec_IntPush( vPacking, 1 ); Vec_IntPush( vPacking, iObj ); } else if ( iFaninSkip3 == -1 ) { assert( iFaninSkip2 > 0 ); Gia_LutForEachFanin( p->pGia, iObj, iFanin, i ) if ( iFanin != iFaninSkip2 ) Gia_ManIffSelect_rec( p, iFanin, vPacking ); Gia_LutForEachFanin( p->pGia, iFaninSkip2, iFanin, i ) Gia_ManIffSelect_rec( p, iFanin, vPacking ); Vec_IntPush( vPacking, 2 ); Vec_IntPush( vPacking, iFaninSkip2 ); Vec_IntPush( vPacking, iObj ); } else { assert( iFaninSkip2 > 0 && iFaninSkip3 > 0 ); Gia_LutForEachFanin( p->pGia, iObj, iFanin, i ) if ( iFanin != iFaninSkip2 && iFanin != iFaninSkip3 ) Gia_ManIffSelect_rec( p, iFanin, vPacking ); Gia_LutForEachFanin( p->pGia, iFaninSkip2, iFanin, i ) if ( iFanin != iFaninSkip3 ) Gia_ManIffSelect_rec( p, iFanin, vPacking ); Gia_LutForEachFanin( p->pGia, iFaninSkip3, iFanin, i ) if ( iFanin != iFaninSkip2 ) Gia_ManIffSelect_rec( p, iFanin, vPacking ); Vec_IntPush( vPacking, 3 ); Vec_IntPush( vPacking, iFaninSkip2 ); Vec_IntPush( vPacking, iFaninSkip3 ); Vec_IntPush( vPacking, iObj ); } Vec_IntAddToEntry( vPacking, 0, 1 ); } Vec_Int_t * Gia_ManIffSelect( Iff_Man_t * p ) { Vec_Int_t * vPacking; Gia_Obj_t * pObj; int i; vPacking = Vec_IntAlloc( Gia_ManObjNum(p->pGia) ); Vec_IntPush( vPacking, 0 ); // mark const0 and PIs Gia_ManIncrementTravId( p->pGia ); Gia_ObjSetTravIdCurrentId( p->pGia, 0 ); Gia_ManForEachCi( p->pGia, pObj, i ) Gia_ObjSetTravIdCurrent( p->pGia, pObj ); // recursively collect internal nodes Gia_ManForEachCo( p->pGia, pObj, i ) Gia_ManIffSelect_rec( p, Gia_ObjFaninId0p(p->pGia, pObj), vPacking ); return vPacking; } /**Function************************************************************* Synopsis [This command performs hierarhical mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManIffTest( Gia_Man_t * pGia, If_LibLut_t * pLib, int fVerbose ) { Iff_Man_t * p; Tim_Man_t * pTemp = NULL; int nDegree = -1; int nLutSize = Gia_ManLutSizeMax( pGia ); if ( nLutSize <= 4 ) { nLutSize = 4; if ( pLib->LutMax == 7 ) nDegree = 2; else if ( pLib->LutMax == 10 ) nDegree = 3; else { printf( "LUT library for packing 4-LUTs should have 7 or 10 inputs.\n" ); return; } } else if ( nLutSize <= 6 ) { nLutSize = 6; if ( pLib->LutMax == 11 ) nDegree = 2; else if ( pLib->LutMax == 16 ) nDegree = 3; else { printf( "LUT library for packing 6-LUTs should have 11 or 16 inputs.\n" ); return; } } else { printf( "The LUT size is more than 6.\n" ); return; } if ( fVerbose ) printf( "Performing %d-clustering with %d-LUTs:\n", nDegree, nLutSize ); // create timing manager if ( pGia->pManTime == NULL ) pGia->pManTime = pTemp = Tim_ManStart( Gia_ManCiNum(pGia), Gia_ManCoNum(pGia) ); // perform timing computation p = Gia_ManIffPerform( pGia, pLib, (Tim_Man_t *)pGia->pManTime, nLutSize, nDegree ); // remove timing manager if ( pGia->pManTime == pTemp ) pGia->pManTime = NULL; Tim_ManStopP( (Tim_Man_t **)&pTemp ); // derive clustering Vec_IntFreeP( &pGia->vPacking ); pGia->vPacking = Gia_ManIffSelect( p ); Gia_ManIffStop( p ); // print statistics if ( fVerbose ) Gia_ManPrintPackingStats( pGia ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaIiff.c000066400000000000000000000035301477524141600157720ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaIiff.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Boolean matching.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaIiff.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/st/st.h" #include "map/mio/mio.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManDeriveMatches( Vec_Ptr_t ** pvNames, Vec_Wrd_t ** pvTruths, Vec_Int_t ** pvTt2Match4, Vec_Int_t ** pvConfigs, Vec_Mem_t * pvTtMem2[3], Vec_Int_t * pvTt2Match2[3] ) { return 0; } Gia_Man_t * Gia_ManIiffTest( char * pFileName, Gia_Man_t * pGia, int nLutSize, int nNumCuts, int fUseGates, int fUseCells, int fUseLuts, int fVerbose ) { return NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaIiff.h000066400000000000000000000036451477524141600160060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaIiff.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaIiff.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__gia__giaIiff_h #define ABC__aig__gia__giaIiff_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/aig/gia/giaIso.c000066400000000000000000001276321477524141600156610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaIso.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Graph isomorphism.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaIso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START #define ISO_MASK 0xFF static unsigned int s_256Primes[ISO_MASK+1] = { 0x984b6ad9,0x18a6eed3,0x950353e2,0x6222f6eb,0xdfbedd47,0xef0f9023,0xac932a26,0x590eaf55, 0x97d0a034,0xdc36cd2e,0x22736b37,0xdc9066b0,0x2eb2f98b,0x5d9c7baf,0x85747c9e,0x8aca1055, 0x50d66b74,0x2f01ae9e,0xa1a80123,0x3e1ce2dc,0xebedbc57,0x4e68bc34,0x855ee0cf,0x17275120, 0x2ae7f2df,0xf71039eb,0x7c283eec,0x70cd1137,0x7cf651f3,0xa87bfa7a,0x14d87f02,0xe82e197d, 0x8d8a5ebe,0x1e6a15dc,0x197d49db,0x5bab9c89,0x4b55dea7,0x55dede49,0x9a6a8080,0xe5e51035, 0xe148d658,0x8a17eb3b,0xe22e4b38,0xe5be2a9a,0xbe938cbb,0x3b981069,0x7f9c0c8e,0xf756df10, 0x8fa783f7,0x252062ce,0x3dc46b4b,0xf70f6432,0x3f378276,0x44b137a1,0x2bf74b77,0x04892ed6, 0xfd318de1,0xd58c235e,0x94c6d25b,0x7aa5f218,0x35c9e921,0x5732fbbb,0x06026481,0xf584a44f, 0x946e1b5f,0x8463d5b2,0x4ebca7b2,0x54887b15,0x08d1e804,0x5b22067d,0x794580f6,0xb351ea43, 0xbce555b9,0x19ae2194,0xd32f1396,0x6fc1a7f1,0x1fd8a867,0x3a89fdb0,0xea49c61c,0x25f8a879, 0xde1e6437,0x7c74afca,0x8ba63e50,0xb1572074,0xe4655092,0xdb6f8b1c,0xc2955f3c,0x327f85ba, 0x60a17021,0x95bd261d,0xdea94f28,0x04528b65,0xbe0109cc,0x26dd5688,0x6ab2729d,0xc4f029ce, 0xacf7a0be,0x4c912f55,0x34c06e65,0x4fbb938e,0x1533fb5f,0x03da06bd,0x48262889,0xc2523d7d, 0x28a71d57,0x89f9713a,0xf574c551,0x7a99deb5,0x52834d91,0x5a6f4484,0xc67ba946,0x13ae698f, 0x3e390f34,0x34fc9593,0x894c7932,0x6cf414a3,0xdb7928ab,0x13a3b8a3,0x4b381c1d,0xa10b54cb, 0x55359d9d,0x35a3422a,0x58d1b551,0x0fd4de20,0x199eb3f4,0x167e09e2,0x3ee6a956,0x5371a7fa, 0xd424efda,0x74f521c5,0xcb899ff6,0x4a42e4f4,0x747917b6,0x4b08df0b,0x090c7a39,0x11e909e4, 0x258e2e32,0xd9fad92d,0x48fe5f69,0x0545cde6,0x55937b37,0x9b4ae4e4,0x1332b40e,0xc3792351, 0xaff982ef,0x4dba132a,0x38b81ef1,0x28e641bf,0x227208c1,0xec4bbe37,0xc4e1821c,0x512c9d09, 0xdaef1257,0xb63e7784,0x043e04d7,0x9c2cea47,0x45a0e59a,0x281315ca,0x849f0aac,0xa4071ed3, 0x0ef707b3,0xfe8dac02,0x12173864,0x471f6d46,0x24a53c0a,0x35ab9265,0xbbf77406,0xa2144e79, 0xb39a884a,0x0baf5b6d,0xcccee3dd,0x12c77584,0x2907325b,0xfd1adcd2,0xd16ee972,0x345ad6c1, 0x315ebe66,0xc7ad2b8d,0x99e82c8d,0xe52da8c8,0xba50f1d3,0x66689cd8,0x2e8e9138,0x43e15e74, 0xf1ced14d,0x188ec52a,0xe0ef3cbb,0xa958aedc,0x4107a1bc,0x5a9e7a3e,0x3bde939f,0xb5b28d5a, 0x596fe848,0xe85ad00c,0x0b6b3aae,0x44503086,0x25b5695c,0xc0c31dcd,0x5ee617f0,0x74d40c3a, 0xd2cb2b9f,0x1e19f5fa,0x81e24faf,0xa01ed68f,0xcee172fc,0x7fdf2e4d,0x002f4774,0x664f82dd, 0xc569c39a,0xa2d4dcbe,0xaadea306,0xa4c947bf,0xa413e4e3,0x81fb5486,0x8a404970,0x752c980c, 0x98d1d881,0x5c932c1e,0xeee65dfb,0x37592cdd,0x0fd4e65b,0xad1d383f,0x62a1452f,0x8872f68d, 0xb58c919b,0x345c8ee3,0xb583a6d6,0x43d72cb3,0x77aaa0aa,0xeb508242,0xf2db64f8,0x86294328, 0x82211731,0x1239a9d5,0x673ba5de,0xaf4af007,0x44203b19,0x2399d955,0xa175cd12,0x595928a7, 0x6918928b,0xde3126bb,0x6c99835c,0x63ba1fa2,0xdebbdff0,0x3d02e541,0xd6f7aac6,0xe80b4cd0, 0xd0fa29f1,0x804cac5e,0x2c226798,0x462f624c,0xad05b377,0x22924fcd,0xfbea205c,0x1b47586d }; //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Gia_IsoMan_t_ Gia_IsoMan_t; struct Gia_IsoMan_t_ { Gia_Man_t * pGia; int nObjs; int nUniques; int nSingles; int nEntries; // internal data int * pLevels; int * pUniques; word * pStoreW; unsigned * pStoreU; // equivalence classes Vec_Int_t * vLevCounts; Vec_Int_t * vClasses; Vec_Int_t * vClasses2; // statistics abctime timeStart; abctime timeSim; abctime timeRefine; abctime timeSort; abctime timeOther; abctime timeTotal; }; static inline unsigned Gia_IsoGetValue( Gia_IsoMan_t * p, int i ) { return (unsigned)(p->pStoreW[i]); } static inline unsigned Gia_IsoGetItem( Gia_IsoMan_t * p, int i ) { return (unsigned)(p->pStoreW[i] >> 32); } static inline void Gia_IsoSetValue( Gia_IsoMan_t * p, int i, unsigned v ) { ((unsigned *)(p->pStoreW + i))[0] = v; } static inline void Gia_IsoSetItem( Gia_IsoMan_t * p, int i, unsigned v ) { ((unsigned *)(p->pStoreW + i))[1] = v; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_IsoMan_t * Gia_IsoManStart( Gia_Man_t * pGia ) { Gia_IsoMan_t * p; p = ABC_CALLOC( Gia_IsoMan_t, 1 ); p->pGia = pGia; p->nObjs = Gia_ManObjNum( pGia ); p->nUniques = 1; p->nEntries = p->nObjs; // internal data p->pLevels = ABC_CALLOC( int, p->nObjs ); p->pUniques = ABC_CALLOC( int, p->nObjs ); p->pStoreW = ABC_CALLOC( word, p->nObjs ); // class representation p->vClasses = Vec_IntAlloc( p->nObjs/4 ); p->vClasses2 = Vec_IntAlloc( p->nObjs/4 ); return p; } void Gia_IsoManStop( Gia_IsoMan_t * p ) { // class representation Vec_IntFree( p->vClasses ); Vec_IntFree( p->vClasses2 ); // internal data ABC_FREE( p->pLevels ); ABC_FREE( p->pUniques ); ABC_FREE( p->pStoreW ); ABC_FREE( p ); } void Gia_IsoManTransferUnique( Gia_IsoMan_t * p ) { Gia_Obj_t * pObj; int i; // copy unique numbers into the nodes Gia_ManForEachObj( p->pGia, pObj, i ) pObj->Value = p->pUniques[i]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoPrintClasses( Gia_IsoMan_t * p ) { int fVerbose = 0; int i, k, iBegin, nSize; printf( "The total of %d classes:\n", Vec_IntSize(p->vClasses)/2 ); Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i ) { printf( "%5d : (%3d,%3d) ", i/2, iBegin, nSize ); if ( fVerbose ) { printf( "{" ); for ( k = 0; k < nSize; k++ ) printf( " %3d,%08x", Gia_IsoGetItem(p, iBegin+k), Gia_IsoGetValue(p, iBegin+k) ); printf( " }" ); } printf( "\n" ); } } void Gia_IsoPrint( Gia_IsoMan_t * p, int Iter, abctime Time ) { printf( "Iter %4d : ", Iter ); printf( "Entries =%8d. ", p->nEntries ); // printf( "Classes =%8d. ", Vec_IntSize(p->vClasses)/2 ); printf( "Uniques =%8d. ", p->nUniques ); printf( "Singles =%8d. ", p->nSingles ); printf( "%9.2f sec", (float)(Time)/(float)(CLOCKS_PER_SEC) ); printf( "\n" ); fflush( stdout ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoPrepare( Gia_IsoMan_t * p ) { Gia_Obj_t * pObj; int * pLevBegins, * pLevSizes; int i, iObj, MaxLev = 0; // assign levels p->pLevels[0] = 0; Gia_ManForEachCi( p->pGia, pObj, i ) p->pLevels[Gia_ObjId(p->pGia, pObj)] = 0; Gia_ManForEachAnd( p->pGia, pObj, i ) p->pLevels[i] = 1 + Abc_MaxInt( p->pLevels[Gia_ObjFaninId0(pObj, i)], p->pLevels[Gia_ObjFaninId1(pObj, i)] ); Gia_ManForEachCo( p->pGia, pObj, i ) { iObj = Gia_ObjId(p->pGia, pObj); p->pLevels[iObj] = 1 + p->pLevels[Gia_ObjFaninId0(pObj, iObj)]; // "1 +" is different! MaxLev = Abc_MaxInt( MaxLev, p->pLevels[Gia_ObjId(p->pGia, pObj)] ); } // count nodes on each level pLevSizes = ABC_CALLOC( int, MaxLev+1 ); for ( i = 1; i < p->nObjs; i++ ) pLevSizes[p->pLevels[i]]++; // start classes Vec_IntClear( p->vClasses ); Vec_IntPush( p->vClasses, 0 ); Vec_IntPush( p->vClasses, 1 ); // find beginning of each level pLevBegins = ABC_CALLOC( int, MaxLev+2 ); pLevBegins[0] = 1; for ( i = 0; i <= MaxLev; i++ ) { assert( pLevSizes[i] > 0 ); // we do not allow AIG with a const node and no PIs Vec_IntPush( p->vClasses, pLevBegins[i] ); Vec_IntPush( p->vClasses, pLevSizes[i] ); pLevBegins[i+1] = pLevBegins[i] + pLevSizes[i]; } assert( pLevBegins[MaxLev+1] == p->nObjs ); // put them into the structure for ( i = 1; i < p->nObjs; i++ ) Gia_IsoSetItem( p, pLevBegins[p->pLevels[i]]++, i ); ABC_FREE( pLevBegins ); ABC_FREE( pLevSizes ); /* // print the results for ( i = 0; i < p->nObjs; i++ ) printf( "%3d : (%d,%d)\n", i, Gia_IsoGetItem(p, i), Gia_IsoGetValue(p, i) ); printf( "\n" ); */ } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoAssignUnique( Gia_IsoMan_t * p ) { int i, iBegin, nSize; p->nSingles = 0; Vec_IntClear( p->vClasses2 ); Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i ) { if ( nSize == 1 ) { assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 ); p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++; p->nSingles++; } else { Vec_IntPush( p->vClasses2, iBegin ); Vec_IntPush( p->vClasses2, nSize ); } } ABC_SWAP( Vec_Int_t *, p->vClasses, p->vClasses2 ); p->nEntries -= p->nSingles; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_IsoSort( Gia_IsoMan_t * p ) { Gia_Obj_t * pObj, * pObj0; int i, k, fSameValue, iBegin, iBeginOld, nSize, nSizeNew; int fRefined = 0; abctime clk; // go through the equiv classes p->nSingles = 0; Vec_IntClear( p->vClasses2 ); Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i ) { assert( nSize > 1 ); fSameValue = 1; pObj0 = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin) ); for ( k = 0; k < nSize; k++ ) { pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) ); Gia_IsoSetValue( p, iBegin+k, pObj->Value ); if ( pObj->Value != pObj0->Value ) fSameValue = 0; } if ( fSameValue ) { Vec_IntPush( p->vClasses2, iBegin ); Vec_IntPush( p->vClasses2, nSize ); continue; } fRefined = 1; // sort objects clk = Abc_Clock(); Abc_QuickSort3( p->pStoreW + iBegin, nSize, 0 ); p->timeSort += Abc_Clock() - clk; // divide into new classes iBeginOld = iBegin; pObj0 = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin) ); for ( k = 1; k < nSize; k++ ) { pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) ); if ( pObj0->Value == pObj->Value ) continue; nSizeNew = iBegin + k - iBeginOld; if ( nSizeNew == 1 ) { assert( p->pUniques[Gia_IsoGetItem(p, iBeginOld)] == 0 ); p->pUniques[Gia_IsoGetItem(p, iBeginOld)] = p->nUniques++; p->nSingles++; } else { Vec_IntPush( p->vClasses2, iBeginOld ); Vec_IntPush( p->vClasses2, nSizeNew ); } iBeginOld = iBegin + k; pObj0 = pObj; } // add the last one nSizeNew = iBegin + k - iBeginOld; if ( nSizeNew == 1 ) { assert( p->pUniques[Gia_IsoGetItem(p, iBeginOld)] == 0 ); p->pUniques[Gia_IsoGetItem(p, iBeginOld)] = p->nUniques++; p->nSingles++; } else { Vec_IntPush( p->vClasses2, iBeginOld ); Vec_IntPush( p->vClasses2, nSizeNew ); } } ABC_SWAP( Vec_Int_t *, p->vClasses, p->vClasses2 ); p->nEntries -= p->nSingles; return fRefined; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Gia_IsoCollectCosClasses( Gia_IsoMan_t * p, int fVerbose ) { Vec_Ptr_t * vGroups; Vec_Int_t * vLevel; Gia_Obj_t * pObj; int i, k, iBegin, nSize; // add singletons vGroups = Vec_PtrAlloc( 1000 ); Gia_ManForEachPo( p->pGia, pObj, i ) if ( p->pUniques[Gia_ObjId(p->pGia, pObj)] > 0 ) { vLevel = Vec_IntAlloc( 1 ); Vec_IntPush( vLevel, i ); Vec_PtrPush( vGroups, vLevel ); } // add groups Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i ) { for ( k = 0; k < nSize; k++ ) { pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) ); if ( Gia_ObjIsPo(p->pGia, pObj) ) break; } if ( k == nSize ) continue; vLevel = Vec_IntAlloc( 8 ); for ( k = 0; k < nSize; k++ ) { pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) ); if ( Gia_ObjIsPo(p->pGia, pObj) ) Vec_IntPush( vLevel, Gia_ObjCioId(pObj) ); } Vec_PtrPush( vGroups, vLevel ); } // canonicize order Vec_PtrForEachEntry( Vec_Int_t *, vGroups, vLevel, i ) Vec_IntSort( vLevel, 0 ); Vec_VecSortByFirstInt( (Vec_Vec_t *)vGroups, 0 ); // Vec_VecFree( (Vec_Vec_t *)vGroups ); // return NULL; return vGroups; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Gia_IsoUpdateValue( int Value, int fCompl ) { return (Value+1) * s_256Primes[Abc_Var2Lit(Value, fCompl) & ISO_MASK]; } static inline unsigned Gia_IsoUpdate( Gia_IsoMan_t * p, int Iter, int iObj, int fCompl ) { if ( Iter == 0 ) return Gia_IsoUpdateValue( p->pLevels[iObj], fCompl ); if ( p->pUniques[iObj] > 0 ) return Gia_IsoUpdateValue( p->pUniques[iObj], fCompl ); // if ( p->pUniques[iObj] > 0 ) return Gia_IsoUpdateValue( 11, fCompl ); return 0; } void Gia_IsoSimulate( Gia_IsoMan_t * p, int Iter ) { Gia_Obj_t * pObj, * pObjF; int i, iObj; // initialize constant, inputs, and flops in the first frame Gia_ManConst0(p->pGia)->Value += s_256Primes[ISO_MASK]; Gia_ManForEachPi( p->pGia, pObj, i ) pObj->Value += s_256Primes[ISO_MASK-1]; if ( Iter == 0 ) Gia_ManForEachRo( p->pGia, pObj, i ) pObj->Value += s_256Primes[ISO_MASK-2]; // simulate nodes Gia_ManForEachAnd( p->pGia, pObj, i ) { pObj->Value += Gia_ObjFanin0(pObj)->Value + Gia_IsoUpdate(p, Iter, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj)); pObj->Value += Gia_ObjFanin1(pObj)->Value + Gia_IsoUpdate(p, Iter, Gia_ObjFaninId1(pObj, i), Gia_ObjFaninC1(pObj)); } // simulate COs Gia_ManForEachCo( p->pGia, pObj, i ) { iObj = Gia_ObjId(p->pGia, pObj); pObj->Value += Gia_ObjFanin0(pObj)->Value + Gia_IsoUpdate(p, Iter, Gia_ObjFaninId0(pObj, iObj), Gia_ObjFaninC0(pObj)); } // transfer flop values Gia_ManForEachRiRo( p->pGia, pObjF, pObj, i ) pObj->Value += pObjF->Value; } void Gia_IsoSimulateBack( Gia_IsoMan_t * p, int Iter ) { Gia_Obj_t * pObj, * pObjF; int i, iObj; // simulate COs Gia_ManForEachCo( p->pGia, pObj, i ) { iObj = Gia_ObjId(p->pGia, pObj); Gia_ObjFanin0(pObj)->Value += pObj->Value + Gia_IsoUpdate(p, Iter, iObj, Gia_ObjFaninC0(pObj)); } // simulate objects Gia_ManForEachAndReverse( p->pGia, pObj, i ) { Gia_ObjFanin0(pObj)->Value += pObj->Value + Gia_IsoUpdate(p, Iter, i, Gia_ObjFaninC0(pObj)); Gia_ObjFanin1(pObj)->Value += pObj->Value + Gia_IsoUpdate(p, Iter, i, Gia_ObjFaninC1(pObj)); } // transfer flop values Gia_ManForEachRiRo( p->pGia, pObjF, pObj, i ) pObjF->Value += pObj->Value; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoAssignOneClass2( Gia_IsoMan_t * p ) { int i, iBegin = -1, nSize = -1; // find two variable class assert( Vec_IntSize(p->vClasses) > 0 ); Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i ) { if ( nSize == 2 ) break; } assert( nSize > 1 ); if ( nSize == 2 ) { assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 ); p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++; p->nSingles++; p->nEntries--; assert( p->pUniques[Gia_IsoGetItem(p, iBegin+1)] == 0 ); p->pUniques[Gia_IsoGetItem(p, iBegin+1)] = p->nUniques++; p->nSingles++; p->nEntries--; } else { assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 ); p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++; p->nSingles++; p->nEntries--; } for ( ; i < Vec_IntSize(p->vClasses) - 2; i += 2 ) { p->vClasses->pArray[i+0] = p->vClasses->pArray[i+2]; p->vClasses->pArray[i+1] = p->vClasses->pArray[i+3]; } Vec_IntShrink( p->vClasses, Vec_IntSize(p->vClasses) - 2 ); printf( "Broke ties in class %d of size %d at level %d.\n", i/2, nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] ); } void Gia_IsoAssignOneClass3( Gia_IsoMan_t * p ) { int iBegin, nSize; // find the last class assert( Vec_IntSize(p->vClasses) > 0 ); iBegin = Vec_IntEntry( p->vClasses, Vec_IntSize(p->vClasses) - 2 ); nSize = Vec_IntEntry( p->vClasses, Vec_IntSize(p->vClasses) - 1 ); Vec_IntShrink( p->vClasses, Vec_IntSize(p->vClasses) - 2 ); // assign the class assert( nSize > 1 ); if ( nSize == 2 ) { assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 ); p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++; p->nSingles++; p->nEntries--; assert( p->pUniques[Gia_IsoGetItem(p, iBegin+1)] == 0 ); p->pUniques[Gia_IsoGetItem(p, iBegin+1)] = p->nUniques++; p->nSingles++; p->nEntries--; } else { assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 ); p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++; p->nSingles++; p->nEntries--; } printf( "Broke ties in last class of size %d at level %d.\n", nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] ); } void Gia_IsoAssignOneClass( Gia_IsoMan_t * p, int fVerbose ) { int i, k, iBegin0, iBegin, nSize, Shrink; // find the classes with the highest level assert( Vec_IntSize(p->vClasses) > 0 ); iBegin0 = Vec_IntEntry( p->vClasses, Vec_IntSize(p->vClasses) - 2 ); for ( i = Vec_IntSize(p->vClasses) - 2; i >= 0; i -= 2 ) { iBegin = Vec_IntEntry( p->vClasses, i ); if ( p->pLevels[Gia_IsoGetItem(p, iBegin)] != p->pLevels[Gia_IsoGetItem(p, iBegin0)] ) break; } i += 2; assert( i >= 0 ); // assign all classes starting with this one for ( Shrink = i; i < Vec_IntSize(p->vClasses); i += 2 ) { iBegin = Vec_IntEntry( p->vClasses, i ); nSize = Vec_IntEntry( p->vClasses, i + 1 ); for ( k = 0; k < nSize; k++ ) { assert( p->pUniques[Gia_IsoGetItem(p, iBegin+k)] == 0 ); p->pUniques[Gia_IsoGetItem(p, iBegin+k)] = p->nUniques++; // Gia_ManObj(p->pGia, Gia_IsoGetItem(p, iBegin+k))->Value += s_256Primes[0]; /// new addition!!! p->nSingles++; p->nEntries--; } if ( fVerbose ) printf( "Broke ties in class of size %d at level %d.\n", nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] ); } Vec_IntShrink( p->vClasses, Shrink ); } /**Function************************************************************* Synopsis [Report topmost equiv nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoReportTopmost( Gia_IsoMan_t * p ) { Gia_Obj_t * pObj; int i, k, iBegin, nSize, Counter = 0; // go through equivalence classes Gia_ManIncrementTravId( p->pGia ); Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i ) { // printf( "%d(%d) ", nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] ); for ( k = 0; k < nSize; k++ ) { pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p, iBegin+k) ); if ( Gia_ObjIsAnd(pObj) ) { Gia_ObjSetTravIdCurrent( p->pGia, Gia_ObjFanin0(pObj) ); Gia_ObjSetTravIdCurrent( p->pGia, Gia_ObjFanin1(pObj) ); } else if ( Gia_ObjIsRo(p->pGia, pObj) ) Gia_ObjSetTravIdCurrent( p->pGia, Gia_ObjFanin0(Gia_ObjRoToRi(p->pGia, pObj)) ); } } // printf( "\n" ); // report non-labeled nodes Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i ) { for ( k = 0; k < nSize; k++ ) { pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p, iBegin+k) ); if ( !Gia_ObjIsTravIdCurrent(p->pGia, pObj) ) { printf( "%5d : ", ++Counter ); printf( "Obj %6d : Level = %4d. iBegin = %4d. Size = %4d.\n", Gia_ObjId(p->pGia, pObj), p->pLevels[Gia_ObjId(p->pGia, pObj)], iBegin, nSize ); break; } } } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoRecognizeMuxes( Gia_Man_t * pGia ) { Gia_Obj_t * pObj, * pObjC, * pObj1, * pObj0; int i; Gia_ManForEachAnd( pGia, pObj, i ) { if ( !Gia_ObjIsMuxType(pObj) ) continue; pObjC = Gia_ObjRecognizeMux( pObj, &pObj1, &pObj0 ); if ( Gia_Regular(pObj0) == Gia_Regular(pObj1) ) { // this is XOR Gia_Regular(pObj)->Value += s_256Primes[233]; Gia_Regular(pObjC)->Value += s_256Primes[234]; Gia_Regular(pObj0)->Value += s_256Primes[234]; } else { // this is MUX Gia_Regular(pObj)->Value += s_256Primes[235]; Gia_Regular(pObjC)->Value += s_256Primes[236]; Gia_Regular(pObj0)->Value += s_256Primes[237]; Gia_Regular(pObj1)->Value += s_256Primes[237]; } } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Gia_IsoDeriveEquivPos( Gia_Man_t * pGia, int fForward, int fVerbose ) { int nIterMax = 10000; int nFixedPoint = 1; Gia_IsoMan_t * p; Vec_Ptr_t * vEquivs = NULL; int fRefined, fRefinedAll; int i, c; abctime clk = Abc_Clock(), clkTotal = Abc_Clock(); assert( Gia_ManCiNum(pGia) > 0 ); assert( Gia_ManPoNum(pGia) > 0 ); Gia_ManCleanValue( pGia ); p = Gia_IsoManStart( pGia ); Gia_IsoPrepare( p ); Gia_IsoAssignUnique( p ); p->timeStart = Abc_Clock() - clk; if ( fVerbose ) Gia_IsoPrint( p, 0, Abc_Clock() - clkTotal ); // Gia_IsoRecognizeMuxes( pGia ); i = 0; if ( fForward ) { for ( c = 0; i < nIterMax && c < nFixedPoint+1; i++, c = fRefined ? 0 : c+1 ) { clk = Abc_Clock(); Gia_IsoSimulate( p, i ); p->timeSim += Abc_Clock() - clk; clk = Abc_Clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += Abc_Clock() - clk; if ( fVerbose ) Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal ); } } else { while ( Vec_IntSize(p->vClasses) > 0 ) { for ( fRefinedAll = 1; i < nIterMax && fRefinedAll; ) { fRefinedAll = 0; for ( c = 0; i < nIterMax && c < nFixedPoint+1; i++, c = fRefined ? 0 : c+1 ) { clk = Abc_Clock(); Gia_IsoSimulate( p, i ); p->timeSim += Abc_Clock() - clk; clk = Abc_Clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += Abc_Clock() - clk; if ( fVerbose ) Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal ); fRefinedAll |= fRefined; } for ( c = 0; i < nIterMax && c < nFixedPoint+1; i++, c = fRefined ? 0 : c+1 ) { clk = Abc_Clock(); Gia_IsoSimulateBack( p, i ); p->timeSim += Abc_Clock() - clk; clk = Abc_Clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += Abc_Clock() - clk; if ( fVerbose ) Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal ); fRefinedAll |= fRefined; } } if ( !fRefinedAll ) break; } // Gia_IsoReportTopmost( p ); while ( Vec_IntSize(p->vClasses) > 0 ) { Gia_IsoAssignOneClass( p, fVerbose ); for ( fRefinedAll = 1; i < nIterMax && fRefinedAll; ) { fRefinedAll = 0; for ( c = 0; i < nIterMax && c < nFixedPoint; i++, c = fRefined ? 0 : c+1 ) { clk = Abc_Clock(); Gia_IsoSimulateBack( p, i ); p->timeSim += Abc_Clock() - clk; clk = Abc_Clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += Abc_Clock() - clk; if ( fVerbose ) Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal ); fRefinedAll |= fRefined; } for ( c = 0; i < nIterMax && c < nFixedPoint; i++, c = fRefined ? 0 : c+1 ) { clk = Abc_Clock(); Gia_IsoSimulate( p, i ); p->timeSim += Abc_Clock() - clk; clk = Abc_Clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += Abc_Clock() - clk; if ( fVerbose ) Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal ); fRefinedAll |= fRefined; // if ( fRefined ) // printf( "Refinedment happened.\n" ); } } } if ( fVerbose ) Gia_IsoPrint( p, i+2, Abc_Clock() - clkTotal ); } // Gia_IsoPrintClasses( p ); if ( fVerbose ) { p->timeTotal = Abc_Clock() - clkTotal; p->timeOther = p->timeTotal - p->timeStart - p->timeSim - p->timeRefine; ABC_PRTP( "Start ", p->timeStart, p->timeTotal ); ABC_PRTP( "Simulate ", p->timeSim, p->timeTotal ); ABC_PRTP( "Refine ", p->timeRefine-p->timeSort, p->timeTotal ); ABC_PRTP( "Sort ", p->timeSort, p->timeTotal ); ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); } if ( Gia_ManPoNum(p->pGia) > 1 ) vEquivs = Gia_IsoCollectCosClasses( p, fVerbose ); Gia_IsoManTransferUnique( p ); Gia_IsoManStop( p ); return vEquivs; } /**Function************************************************************* Synopsis [Finds canonical ordering of CIs/COs/nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ObjCompareByValue( Gia_Obj_t ** pp1, Gia_Obj_t ** pp2 ) { Gia_Obj_t * pObj1 = *pp1; Gia_Obj_t * pObj2 = *pp2; // assert( pObj1->Value != pObj2->Value ); return (int)pObj1->Value - (int)pObj2->Value; } void Gia_ManFindCaninicalOrder_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vAnds ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); assert( Gia_ObjIsAnd(pObj) ); if ( !Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) || !Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) ) { Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds ); Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin1(pObj), vAnds ); } else { assert( Gia_ObjFanin0(pObj)->Value != Gia_ObjFanin1(pObj)->Value ); if ( Gia_ObjFanin0(pObj)->Value < Gia_ObjFanin1(pObj)->Value ) { Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds ); Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin1(pObj), vAnds ); } else { Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin1(pObj), vAnds ); Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds ); } } Vec_IntPush( vAnds, Gia_ObjId(p, pObj) ); } void Gia_ManFindCaninicalOrder( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, Vec_Int_t ** pvPiPerm ) { Vec_Ptr_t * vTemp; Gia_Obj_t * pObj; int i; vTemp = Vec_PtrAlloc( 1000 ); Vec_IntClear( vCis ); Vec_IntClear( vAnds ); Vec_IntClear( vCos ); // assign unique IDs to PIs Vec_PtrClear( vTemp ); Gia_ManForEachPi( p, pObj, i ) Vec_PtrPush( vTemp, pObj ); 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) ); // remember PI permutation if ( pvPiPerm ) { *pvPiPerm = Vec_IntAlloc( Gia_ManPiNum(p) ); Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i ) Vec_IntPush( *pvPiPerm, Gia_ObjCioId(pObj) ); } // assign unique IDs to POs if ( Gia_ManPoNum(p) == 1 ) Vec_IntPush( vCos, Gia_ObjId(p, Gia_ManPo(p, 0)) ); else { Vec_PtrClear( vTemp ); Gia_ManForEachPo( p, pObj, i ) { pObj->Value = Abc_Var2Lit( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); Vec_PtrPush( vTemp, pObj ); } 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) ); } // assign unique IDs to ROs Vec_PtrClear( vTemp ); Gia_ManForEachRo( p, pObj, i ) Vec_PtrPush( vTemp, pObj ); 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) ); Vec_IntPush( vCos, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) ); } Vec_PtrFree( vTemp ); // assign unique IDs to internal nodes Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); Gia_ManForEachObjVec( vCis, p, pObj, i ) Gia_ObjSetTravIdCurrent( p, pObj ); Gia_ManForEachObjVec( vCos, p, pObj, i ) Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManIsoCanonicize( Gia_Man_t * p, int fVerbose ) { Gia_Man_t * pRes = NULL; Vec_Int_t * vCis, * vAnds, * vCos; Vec_Ptr_t * vEquiv; if ( Gia_ManCiNum(p) == 0 ) // const AIG { assert( Gia_ManPoNum(p) == 1 ); assert( Gia_ManObjNum(p) == 2 ); return Gia_ManDup(p); } // derive canonical values vEquiv = Gia_IsoDeriveEquivPos( p, 0, fVerbose ); Vec_VecFreeP( (Vec_Vec_t **)&vEquiv ); // find canonical order of CIs/COs/nodes // find canonical order vCis = Vec_IntAlloc( Gia_ManCiNum(p) ); vAnds = Vec_IntAlloc( Gia_ManAndNum(p) ); vCos = Vec_IntAlloc( Gia_ManCoNum(p) ); Gia_ManFindCaninicalOrder( p, vCis, vAnds, vCos, NULL ); // derive the new AIG pRes = Gia_ManDupFromVecs( p, vCis, vAnds, vCos, Gia_ManRegNum(p) ); // cleanup Vec_IntFree( vCis ); Vec_IntFree( vAnds ); Vec_IntFree( vCos ); return pRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Gia_ManIsoFindString( Gia_Man_t * p, int iPo, int fVerbose, Vec_Int_t ** pvPiPerm ) { Gia_Man_t * pPart; Vec_Ptr_t * vEquiv; Vec_Int_t * vCis, * vAnds, * vCos; Vec_Str_t * vStr; // duplicate pPart = Gia_ManDupCones( p, &iPo, 1, 1 ); //Gia_ManPrint( pPart ); assert( Gia_ManPoNum(pPart) == 1 ); if ( Gia_ManCiNum(pPart) == 0 ) // const AIG { assert( Gia_ManPoNum(pPart) == 1 ); assert( Gia_ManObjNum(pPart) == 2 ); vStr = Gia_AigerWriteIntoMemoryStr( pPart ); Gia_ManStop( pPart ); if ( pvPiPerm ) *pvPiPerm = Vec_IntAlloc( 0 ); return vStr; } // derive canonical values vEquiv = Gia_IsoDeriveEquivPos( pPart, 0, fVerbose ); Vec_VecFreeP( (Vec_Vec_t **)&vEquiv ); // find canonical order vCis = Vec_IntAlloc( Gia_ManCiNum(pPart) ); vAnds = Vec_IntAlloc( Gia_ManAndNum(pPart) ); vCos = Vec_IntAlloc( Gia_ManCoNum(pPart) ); Gia_ManFindCaninicalOrder( pPart, vCis, vAnds, vCos, pvPiPerm ); //printf( "Internal: " ); //Vec_IntPrint( vCis ); // derive the AIGER string vStr = Gia_AigerWriteIntoMemoryStrPart( pPart, vCis, vAnds, vCos, Gia_ManRegNum(pPart) ); // cleanup Vec_IntFree( vCis ); Vec_IntFree( vAnds ); Vec_IntFree( vCos ); Gia_ManStop( pPart ); return vStr; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Vec_IntCountNonTrivial( Vec_Ptr_t * vEquivs, int * pnUsed ) { Vec_Int_t * vClass; int i, nClasses = 0; *pnUsed = 0; Vec_PtrForEachEntry( Vec_Int_t *, vEquivs, vClass, i ) { if ( Vec_IntSize(vClass) < 2 ) continue; nClasses++; (*pnUsed) += Vec_IntSize(vClass); } return nClasses; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManIsoReduce( Gia_Man_t * pInit, Vec_Ptr_t ** pvPosEquivs, Vec_Ptr_t ** pvPiPerms, int fEstimate, int fDualOut, int fVerbose, int fVeryVerbose ) { Gia_Man_t * p, * pPart; Vec_Ptr_t * vEquivs, * vEquivs2, * vStrings; Vec_Int_t * vRemain, * vLevel, * vLevel2; Vec_Str_t * vStr, * vStr2; int i, k, s, sStart, iPo, Counter; int nClasses, nUsedPos; abctime clk = Abc_Clock(); if ( pvPosEquivs ) *pvPosEquivs = NULL; if ( pvPiPerms ) *pvPiPerms = Vec_PtrStart( Gia_ManPoNum(pInit) ); if ( fDualOut ) { assert( (Gia_ManPoNum(pInit) & 1) == 0 ); if ( Gia_ManPoNum(pInit) == 2 ) return Gia_ManDup(pInit); p = Gia_ManTransformMiter( pInit ); p = Gia_ManSeqStructSweep( pPart = p, 1, 1, 0 ); Gia_ManStop( pPart ); } else { if ( Gia_ManPoNum(pInit) == 1 ) return Gia_ManDup(pInit); p = pInit; } // create preliminary equivalences vEquivs = Gia_IsoDeriveEquivPos( p, 1, fVeryVerbose ); if ( vEquivs == NULL ) { if ( fDualOut ) Gia_ManStop( p ); return NULL; } nClasses = Vec_IntCountNonTrivial( vEquivs, &nUsedPos ); printf( "Reduced %d outputs to %d candidate classes (%d outputs are in %d non-trivial classes). ", Gia_ManPoNum(p), Vec_PtrSize(vEquivs), nUsedPos, nClasses ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( fEstimate ) { Vec_VecFree( (Vec_Vec_t *)vEquivs ); return Gia_ManDup(pInit); } // perform refinement of equivalence classes Counter = 0; vEquivs2 = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Vec_Int_t *, vEquivs, vLevel, i ) { if ( Vec_IntSize(vLevel) < 2 ) { Vec_PtrPush( vEquivs2, Vec_IntDup(vLevel) ); for ( k = 0; k < Vec_IntSize(vLevel); k++ ) if ( ++Counter % 100 == 0 ) printf( "%6d finished...\r", Counter ); continue; } if ( fVerbose ) { iPo = Vec_IntEntry(vLevel, 0); printf( "%6d %6d %6d : ", i, Vec_IntSize(vLevel), iPo ); pPart = Gia_ManDupCones( p, &iPo, 1, 1 ); Gia_ManPrintStats(pPart, NULL); Gia_ManStop( pPart ); } sStart = Vec_PtrSize( vEquivs2 ); vStrings = Vec_PtrAlloc( 100 ); Vec_IntForEachEntry( vLevel, iPo, k ) { if ( ++Counter % 100 == 0 ) printf( "%6d finished...\r", Counter ); assert( pvPiPerms == NULL || Vec_PtrArray(*pvPiPerms)[iPo] == NULL ); vStr = Gia_ManIsoFindString( p, iPo, 0, pvPiPerms ? (Vec_Int_t **)Vec_PtrArray(*pvPiPerms) + iPo : NULL ); // printf( "Output %2d : ", iPo ); // Vec_IntPrint( Vec_PtrArray(*pvPiPerms)[iPo] ); // check if this string already exists Vec_PtrForEachEntry( Vec_Str_t *, vStrings, vStr2, s ) if ( Vec_StrCompareVec(vStr, vStr2) == 0 ) break; if ( s == Vec_PtrSize(vStrings) ) { Vec_PtrPush( vStrings, vStr ); Vec_PtrPush( vEquivs2, Vec_IntAlloc(8) ); } else Vec_StrFree( vStr ); // add this entry to the corresponding level vLevel2 = (Vec_Int_t *)Vec_PtrEntry( vEquivs2, sStart + s ); Vec_IntPush( vLevel2, iPo ); } // if ( Vec_PtrSize(vEquivs2) - sStart > 1 ) // printf( "Refined class %d into %d classes.\n", i, Vec_PtrSize(vEquivs2) - sStart ); Vec_VecFree( (Vec_Vec_t *)vStrings ); } assert( Counter == Gia_ManPoNum(p) ); Vec_VecSortByFirstInt( (Vec_Vec_t *)vEquivs2, 0 ); Vec_VecFree( (Vec_Vec_t *)vEquivs ); vEquivs = vEquivs2; // collect the first ones vRemain = Vec_IntAlloc( 100 ); Vec_PtrForEachEntry( Vec_Int_t *, vEquivs, vLevel, i ) Vec_IntPush( vRemain, Vec_IntEntry(vLevel, 0) ); if ( fDualOut ) { Vec_Int_t * vTemp = Vec_IntAlloc( Vec_IntSize(vRemain) ); int i, Entry; Vec_IntForEachEntry( vRemain, Entry, i ) { // printf( "%d ", Entry ); Vec_IntPush( vTemp, 2*Entry ); Vec_IntPush( vTemp, 2*Entry+1 ); } // printf( "\n" ); Vec_IntFree( vRemain ); vRemain = vTemp; Gia_ManStop( p ); p = pInit; } // derive the resulting AIG pPart = Gia_ManDupCones( p, Vec_IntArray(vRemain), Vec_IntSize(vRemain), 0 ); Vec_IntFree( vRemain ); // report the results nClasses = Vec_IntCountNonTrivial( vEquivs, &nUsedPos ); if ( !fDualOut ) printf( "Reduced %d outputs to %d equivalence classes (%d outputs are in %d non-trivial classes). ", Gia_ManPoNum(p), Vec_PtrSize(vEquivs), nUsedPos, nClasses ); else printf( "Reduced %d dual outputs to %d dual outputs. ", Gia_ManPoNum(p)/2, Gia_ManPoNum(pPart)/2 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( fVerbose ) { printf( "Nontrivial classes:\n" ); Vec_VecPrintInt( (Vec_Vec_t *)vEquivs, 1 ); } if ( pvPosEquivs ) *pvPosEquivs = vEquivs; else Vec_VecFree( (Vec_Vec_t *)vEquivs ); // Gia_ManStopP( &pPart ); return pPart; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_IsoTestOld( Gia_Man_t * p, int fVerbose ) { Vec_Ptr_t * vEquivs; abctime clk = Abc_Clock(); vEquivs = Gia_IsoDeriveEquivPos( p, 0, fVerbose ); printf( "Reduced %d outputs to %d. ", Gia_ManPoNum(p), vEquivs ? Vec_PtrSize(vEquivs) : 1 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( fVerbose && vEquivs && Gia_ManPoNum(p) != Vec_PtrSize(vEquivs) ) { printf( "Nontrivial classes:\n" ); // Vec_VecPrintInt( (Vec_Vec_t *)vEquivs, 1 ); } Vec_VecFreeP( (Vec_Vec_t **)&vEquivs ); } /**Function************************************************************* Synopsis [Test remapping of CEXes for isomorphic POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_IsoTestGenPerm( int nPis ) { Vec_Int_t * vPerm; int i, * pArray; vPerm = Vec_IntStartNatural( nPis ); pArray = Vec_IntArray( vPerm ); for ( i = 0; i < nPis; i++ ) { int iNew = rand() % nPis; ABC_SWAP( int, pArray[i], pArray[iNew] ); } return vPerm; } void Gia_IsoTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose ) { Abc_Cex_t * pCexNew; Vec_Int_t * vPiPerm; Vec_Ptr_t * vPosEquivs, * vPisPerm; Vec_Int_t * vPerm0, * vPerm1; Gia_Man_t * pPerm, * pDouble, * pAig; assert( Gia_ManPoNum(p) == 1 ); assert( Gia_ManRegNum(p) > 0 ); // generate random permutation of PIs vPiPerm = Gia_IsoTestGenPerm( Gia_ManPiNum(p) ); printf( "Considering random permutation of the primary inputs of the AIG:\n" ); Vec_IntPrint( vPiPerm ); // 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, 0 ); // analyze the two-output miter pAig = Gia_ManIsoReduce( pDouble, &vPosEquivs, &vPisPerm, 0, 0, 0, 0 ); Vec_VecFree( (Vec_Vec_t *)vPosEquivs ); // given CEX for output 0, derive CEX for output 1 vPerm0 = (Vec_Int_t *)Vec_PtrEntry( vPisPerm, 0 ); vPerm1 = (Vec_Int_t *)Vec_PtrEntry( vPisPerm, 1 ); pCexNew = Abc_CexPermuteTwo( pCex, vPerm0, vPerm1 ); Vec_VecFree( (Vec_Vec_t *)vPisPerm ); // check that original CEX and the resulting CEX is valid if ( Gia_ManVerifyCex(p, pCex, 0) ) printf( "CEX for the init AIG is valid.\n" ); else printf( "CEX for the init AIG is not valid.\n" ); if ( Gia_ManVerifyCex(pPerm, pCexNew, 0) ) printf( "CEX for the perm AIG is valid.\n" ); else printf( "CEX for the perm AIG is not valid.\n" ); // delete Gia_ManStop( pAig ); Gia_ManStop( pDouble ); Gia_ManStop( pPerm ); Vec_IntFree( vPiPerm ); Abc_CexFree( pCexNew ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaIso2.c000066400000000000000000000665161477524141600157460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [gia.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" #include "misc/vec/vecHsh.h" #include "misc/vec/vecWec.h" ABC_NAMESPACE_IMPL_START #define ISO_MASK 0xFF static unsigned int s_256Primes[ISO_MASK+1] = { 0x984b6ad9,0x18a6eed3,0x950353e2,0x6222f6eb,0xdfbedd47,0xef0f9023,0xac932a26,0x590eaf55, 0x97d0a034,0xdc36cd2e,0x22736b37,0xdc9066b0,0x2eb2f98b,0x5d9c7baf,0x85747c9e,0x8aca1055, 0x50d66b74,0x2f01ae9e,0xa1a80123,0x3e1ce2dc,0xebedbc57,0x4e68bc34,0x855ee0cf,0x17275120, 0x2ae7f2df,0xf71039eb,0x7c283eec,0x70cd1137,0x7cf651f3,0xa87bfa7a,0x14d87f02,0xe82e197d, 0x8d8a5ebe,0x1e6a15dc,0x197d49db,0x5bab9c89,0x4b55dea7,0x55dede49,0x9a6a8080,0xe5e51035, 0xe148d658,0x8a17eb3b,0xe22e4b38,0xe5be2a9a,0xbe938cbb,0x3b981069,0x7f9c0c8e,0xf756df10, 0x8fa783f7,0x252062ce,0x3dc46b4b,0xf70f6432,0x3f378276,0x44b137a1,0x2bf74b77,0x04892ed6, 0xfd318de1,0xd58c235e,0x94c6d25b,0x7aa5f218,0x35c9e921,0x5732fbbb,0x06026481,0xf584a44f, 0x946e1b5f,0x8463d5b2,0x4ebca7b2,0x54887b15,0x08d1e804,0x5b22067d,0x794580f6,0xb351ea43, 0xbce555b9,0x19ae2194,0xd32f1396,0x6fc1a7f1,0x1fd8a867,0x3a89fdb0,0xea49c61c,0x25f8a879, 0xde1e6437,0x7c74afca,0x8ba63e50,0xb1572074,0xe4655092,0xdb6f8b1c,0xc2955f3c,0x327f85ba, 0x60a17021,0x95bd261d,0xdea94f28,0x04528b65,0xbe0109cc,0x26dd5688,0x6ab2729d,0xc4f029ce, 0xacf7a0be,0x4c912f55,0x34c06e65,0x4fbb938e,0x1533fb5f,0x03da06bd,0x48262889,0xc2523d7d, 0x28a71d57,0x89f9713a,0xf574c551,0x7a99deb5,0x52834d91,0x5a6f4484,0xc67ba946,0x13ae698f, 0x3e390f34,0x34fc9593,0x894c7932,0x6cf414a3,0xdb7928ab,0x13a3b8a3,0x4b381c1d,0xa10b54cb, 0x55359d9d,0x35a3422a,0x58d1b551,0x0fd4de20,0x199eb3f4,0x167e09e2,0x3ee6a956,0x5371a7fa, 0xd424efda,0x74f521c5,0xcb899ff6,0x4a42e4f4,0x747917b6,0x4b08df0b,0x090c7a39,0x11e909e4, 0x258e2e32,0xd9fad92d,0x48fe5f69,0x0545cde6,0x55937b37,0x9b4ae4e4,0x1332b40e,0xc3792351, 0xaff982ef,0x4dba132a,0x38b81ef1,0x28e641bf,0x227208c1,0xec4bbe37,0xc4e1821c,0x512c9d09, 0xdaef1257,0xb63e7784,0x043e04d7,0x9c2cea47,0x45a0e59a,0x281315ca,0x849f0aac,0xa4071ed3, 0x0ef707b3,0xfe8dac02,0x12173864,0x471f6d46,0x24a53c0a,0x35ab9265,0xbbf77406,0xa2144e79, 0xb39a884a,0x0baf5b6d,0xcccee3dd,0x12c77584,0x2907325b,0xfd1adcd2,0xd16ee972,0x345ad6c1, 0x315ebe66,0xc7ad2b8d,0x99e82c8d,0xe52da8c8,0xba50f1d3,0x66689cd8,0x2e8e9138,0x43e15e74, 0xf1ced14d,0x188ec52a,0xe0ef3cbb,0xa958aedc,0x4107a1bc,0x5a9e7a3e,0x3bde939f,0xb5b28d5a, 0x596fe848,0xe85ad00c,0x0b6b3aae,0x44503086,0x25b5695c,0xc0c31dcd,0x5ee617f0,0x74d40c3a, 0xd2cb2b9f,0x1e19f5fa,0x81e24faf,0xa01ed68f,0xcee172fc,0x7fdf2e4d,0x002f4774,0x664f82dd, 0xc569c39a,0xa2d4dcbe,0xaadea306,0xa4c947bf,0xa413e4e3,0x81fb5486,0x8a404970,0x752c980c, 0x98d1d881,0x5c932c1e,0xeee65dfb,0x37592cdd,0x0fd4e65b,0xad1d383f,0x62a1452f,0x8872f68d, 0xb58c919b,0x345c8ee3,0xb583a6d6,0x43d72cb3,0x77aaa0aa,0xeb508242,0xf2db64f8,0x86294328, 0x82211731,0x1239a9d5,0x673ba5de,0xaf4af007,0x44203b19,0x2399d955,0xa175cd12,0x595928a7, 0x6918928b,0xde3126bb,0x6c99835c,0x63ba1fa2,0xdebbdff0,0x3d02e541,0xd6f7aac6,0xe80b4cd0, 0xd0fa29f1,0x804cac5e,0x2c226798,0x462f624c,0xad05b377,0x22924fcd,0xfbea205c,0x1b47586d }; static int s_PrimeC = 49; //static int s_PrimeC = 1; //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Gia_Iso2Man_t_ Gia_Iso2Man_t; struct Gia_Iso2Man_t_ { Gia_Man_t * pGia; int nObjs; int nUniques; // internal data Vec_Int_t * vUniques; // unique numbers Vec_Int_t * vTied; // tied objects Vec_Int_t * vTable; // hash table Vec_Int_t * vPlaces; // used places in the table Vec_Ptr_t * vSingles; // singleton objects // isomorphism check Vec_Int_t * vVec0; // isomorphism map Vec_Int_t * vVec1; // isomorphism map Vec_Int_t * vMap0; // isomorphism map Vec_Int_t * vMap1; // isomorphism map // statistics int nIters; abctime timeStart; abctime timeSim; abctime timeRefine; abctime timeSort; abctime timeOther; abctime timeTotal; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_Iso2ManCollectTies( Gia_Man_t * p ) { Vec_Int_t * vTies; Gia_Obj_t * pObj; int i; vTies = Vec_IntAlloc( Gia_ManCandNum(p) ); Gia_ManForEachCand( p, pObj, i ) Vec_IntPush( vTies, i ); return vTies; } void Gia_Iso2ManPrepare( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) pObj->Value = Gia_ObjIsAnd(pObj) ? 1 + Abc_MaxInt(Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value) : 0; Gia_ManConst0(p)->Value = s_256Primes[ISO_MASK]; Gia_ManForEachObj1( p, pObj, i ) if ( Gia_ObjIsAnd(pObj) ) pObj->Value = s_256Primes[pObj->Value & ISO_MASK] + s_256Primes[ISO_MASK - 10 + Gia_ObjFaninC0(pObj) + Gia_ObjFaninC1(pObj)]; else if ( Gia_ObjIsPi(p, pObj) ) pObj->Value = s_256Primes[ISO_MASK-1]; else if ( Gia_ObjIsRo(p, pObj) ) pObj->Value = s_256Primes[ISO_MASK-2]; } void Gia_Iso2ManPropagate( Gia_Man_t * p ) { Gia_Obj_t * pObj, * pObjRo; int i; Gia_ManForEachObj1( p, pObj, i ) if ( Gia_ObjIsAnd(pObj) ) { pObj->Value += (Gia_ObjFaninC0(pObj) + s_PrimeC) * Gia_ObjFanin0(pObj)->Value + (Gia_ObjFaninC1(pObj) + s_PrimeC) * Gia_ObjFanin1(pObj)->Value; if ( Gia_ObjFaninC0(pObj) == Gia_ObjFaninC1(pObj) && Gia_ObjFanin0(pObj)->Value == Gia_ObjFanin1(pObj)->Value ) pObj->Value += s_256Primes[ISO_MASK - 11]; } else if ( Gia_ObjIsCo(pObj) ) pObj->Value += (Gia_ObjFaninC0(pObj) + s_PrimeC) * Gia_ObjFanin0(pObj)->Value; Gia_ManForEachRiRo( p, pObj, pObjRo, i ) { pObjRo->Value += pObj->Value; if ( pObjRo == Gia_ObjFanin0(pObj) ) pObjRo->Value += s_256Primes[ISO_MASK - 12]; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Gia_Iso2ManCone_rec( Gia_Man_t * p, int Id, int Level ) { Gia_Obj_t * pObj; if ( Level == 0 ) return 0; if ( Gia_ObjIsTravIdCurrentId(p, Id) ) return 0; Gia_ObjSetTravIdCurrentId(p, Id); pObj = Gia_ManObj( p, Id ); if ( Gia_ObjIsAnd(pObj) ) return pObj->Value + Gia_Iso2ManCone_rec( p, Gia_ObjFaninId0(pObj, Id), Level-1 ) + Gia_Iso2ManCone_rec( p, Gia_ObjFaninId1(pObj, Id), Level-1 ); if ( Gia_ObjIsPi(p, pObj) ) return pObj->Value; if ( Gia_ObjIsRo(p, pObj) ) return pObj->Value + Gia_Iso2ManCone_rec( p, Gia_ObjId(p, Gia_ObjFanin0(Gia_ObjRoToRi(p, pObj))), Level ); assert( Gia_ObjIsConst0(pObj) ); return pObj->Value; } unsigned Gia_Iso2ManCone( Gia_Man_t * p, int Id, int Level ) { Gia_ManIncrementTravId( p ); return Gia_Iso2ManCone_rec( p, Id, Level ); } void Gia_Iso2ManUpdate( Gia_Iso2Man_t * p, int Level ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i ) pObj->Value += Gia_Iso2ManCone( p->pGia, Gia_ObjId(p->pGia, pObj), Level ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Iso2Man_t * Gia_Iso2ManStart( Gia_Man_t * pGia ) { Gia_Iso2Man_t * p; p = ABC_CALLOC( Gia_Iso2Man_t, 1 ); p->pGia = pGia; p->nObjs = Gia_ManObjNum( pGia ); p->nUniques = 0; // internal data p->vUniques = Vec_IntStartFull( p->nObjs ); p->vTied = Gia_Iso2ManCollectTies( pGia ); p->vTable = Vec_IntStart( Abc_PrimeCudd(1*p->nObjs) ); p->vPlaces = Vec_IntAlloc( 1000 ); p->vSingles = Vec_PtrAlloc( 1000 ); p->vVec0 = Vec_IntAlloc( 10000 ); p->vVec1 = Vec_IntAlloc( 10000 ); p->vMap0 = Vec_IntStart( p->nObjs ); p->vMap1 = Vec_IntStart( p->nObjs ); // add constant 0 object Vec_IntWriteEntry( p->vUniques, 0, p->nUniques++ ); return p; } void Gia_Iso2ManStop( Gia_Iso2Man_t * p ) { Vec_IntFree( p->vUniques ); Vec_IntFree( p->vTied ); Vec_IntFree( p->vTable ); Vec_IntFree( p->vPlaces ); Vec_PtrFree( p->vSingles ); Vec_IntFree( p->vMap0 ); Vec_IntFree( p->vMap1 ); Vec_IntFree( p->vVec0 ); Vec_IntFree( p->vVec1 ); ABC_FREE( p ); } void Gia_Iso2ManPrint( Gia_Iso2Man_t * p, abctime Time, int fVerbose ) { if ( !fVerbose ) return; printf( "Iter %4d : ", p->nIters++ ); printf( "Entries =%8d. ", Vec_IntSize(p->vTied) ); printf( "Uniques =%8d. ", p->nUniques ); printf( "Singles =%8d. ", Vec_PtrSize(p->vSingles) ); printf( "%9.2f sec", (float)(Time)/(float)(CLOCKS_PER_SEC) ); printf( "\n" ); fflush( stdout ); } /**Function************************************************************* Synopsis [Uniqifies objects using their signature.] Description [Assumes the tied objects are in p->vTied. Assumes that updated signature (pObj->Value) is assigned to these objects. Returns the array of unique objects p->vSingles sorted by signature. Compacts the array of tied objects p->vTied.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ObjCompareByValue2( Gia_Obj_t ** pp1, Gia_Obj_t ** pp2 ) { return (int)(*pp1)->Value - (int)(*pp2)->Value; } int Gia_Iso2ManUniqify( Gia_Iso2Man_t * p ) { int fVerify = 0; Gia_Obj_t * pObj, * pTemp; int * pTable = Vec_IntArray(p->vTable); int i, k, nSize = Vec_IntSize(p->vTable); if ( fVerify ) for ( k = 0; k < nSize; k++ ) assert( pTable[k] == 0 ); if ( fVerify ) Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i ) assert( pObj->fMark0 == 0 ); #if 0 Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i ) { printf( "%3d : ", Gia_ObjId(p->pGia, pObj) ); Extra_PrintBinary( stdout, &pObj->Value, 32 ); printf( "\n" ); } #endif // add objects to the table Vec_IntClear( p->vPlaces ); Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i ) { for ( k = pObj->Value % nSize; (pTemp = pTable[k] ? Gia_ManObj(p->pGia, pTable[k]) : NULL); k = (k + 1) % nSize ) if ( pTemp->Value == pObj->Value ) { pTemp->fMark0 = 1; pObj->fMark0 = 1; break; } if ( pTemp != NULL ) continue; pTable[k] = Gia_ObjId(p->pGia, pObj); Vec_IntPush( p->vPlaces, k ); } // clean the table Vec_IntForEachEntry( p->vPlaces, k, i ) pTable[k] = 0; // collect singleton objects and compact tied objects k = 0; Vec_PtrClear( p->vSingles ); Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i ) if ( pObj->fMark0 == 0 ) Vec_PtrPush( p->vSingles, pObj ); else { pObj->fMark0 = 0; Vec_IntWriteEntry( p->vTied, k++, Gia_ObjId(p->pGia, pObj) ); } Vec_IntShrink( p->vTied, k ); // sort singletons 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 ) { pObj->Value += s_256Primes[p->nUniques & ISO_MASK]; assert( Vec_IntEntry(p->vUniques, Gia_ObjId(p->pGia, pObj)) == -1 ); Vec_IntWriteEntry( p->vUniques, Gia_ObjId(p->pGia, pObj), p->nUniques++ ); } return Vec_PtrSize( p->vSingles ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wec_t * Gia_Iso2ManDerivePoClasses( Gia_Man_t * pGia ) { Vec_Wec_t * vEquivs; Vec_Int_t * vValues; Vec_Int_t * vMap; Gia_Obj_t * pObj; int i; vValues = Vec_IntAlloc( Gia_ManPoNum(pGia) ); Gia_ManForEachPo( pGia, pObj, i ) Vec_IntPush( vValues, pObj->Value ); vMap = Hsh_IntManHashArray( vValues, 1 ); Vec_IntFree( vValues ); vEquivs = Vec_WecCreateClasses( vMap ); Vec_IntFree( vMap ); return vEquivs; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_Iso2ManCollectOrder2_rec( Gia_Man_t * p, int Id, Vec_Int_t * vVec ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId(p, Id) ) return; Gia_ObjSetTravIdCurrentId(p, Id); pObj = Gia_ManObj( p, Id ); if ( Gia_ObjIsAnd(pObj) ) { if ( Gia_ObjFanin0(pObj)->Value <= Gia_ObjFanin1(pObj)->Value ) { Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId0(pObj, Id), vVec ); Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId1(pObj, Id), vVec ); } else { Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId1(pObj, Id), vVec ); Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId0(pObj, Id), vVec ); } } else if ( Gia_ObjIsCo(pObj) ) { Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId0(pObj, Id), vVec ); } else if ( Gia_ObjIsPi(p, pObj) ) { } else assert( Gia_ObjIsConst0(pObj) ); Vec_IntPush( vVec, Id ); } Vec_Int_t * Gia_Iso2ManCollectOrder2( Gia_Man_t * pGia, int * pPos, int nPos ) { Vec_Int_t * vVec; int i; vVec = Vec_IntAlloc( 1000 ); Gia_ManIncrementTravId( pGia ); for ( i = 0; i < nPos; i++ ) Gia_Iso2ManCollectOrder2_rec( pGia, Gia_ObjId(pGia, Gia_ManPo(pGia, pPos[i])), vVec ); return vVec; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_Iso2ManCollectOrder_rec( Gia_Man_t * p, int Id, Vec_Int_t * vRoots, Vec_Int_t * vVec, Vec_Int_t * vMap ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId(p, Id) ) return; Gia_ObjSetTravIdCurrentId(p, Id); pObj = Gia_ManObj( p, Id ); if ( Gia_ObjIsAnd(pObj) ) { if ( Gia_ObjFanin0(pObj)->Value <= Gia_ObjFanin1(pObj)->Value ) { Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vVec, vMap ); Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId1(pObj, Id), vRoots, vVec, vMap ); } else { Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId1(pObj, Id), vRoots, vVec, vMap ); Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vVec, vMap ); } } else if ( Gia_ObjIsCo(pObj) ) { Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vVec, vMap ); } else if ( Gia_ObjIsCi(pObj) ) { if ( Gia_ObjIsRo(p, pObj) ) Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) ); } else assert( Gia_ObjIsConst0(pObj) ); Vec_IntWriteEntry( vMap, Id, Vec_IntSize(vVec) ); Vec_IntPush( vVec, Id ); } void Gia_Iso2ManCollectOrder( Gia_Man_t * pGia, int * pPos, int nPos, Vec_Int_t * vRoots, Vec_Int_t * vVec, Vec_Int_t * vMap ) { int i, iRoot; Vec_IntClear( vRoots ); for ( i = 0; i < nPos; i++ ) Vec_IntPush( vRoots, Gia_ObjId(pGia, Gia_ManPo(pGia, pPos[i])) ); Vec_IntClear( vVec ); Gia_ManIncrementTravId( pGia ); Vec_IntForEachEntry( vRoots, iRoot, i ) Gia_Iso2ManCollectOrder_rec( pGia, iRoot, vRoots, vVec, vMap ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_Iso2ManCheckIsoPair( Gia_Man_t * p, Vec_Int_t * vVec0, Vec_Int_t * vVec1, Vec_Int_t * vMap0, Vec_Int_t * vMap1 ) { Gia_Obj_t * pObj0, * pObj1; int k, iObj0, iObj1; Vec_IntForEachEntryTwo( vVec0, vVec1, iObj0, iObj1, k ) { if ( iObj0 == iObj1 ) continue; pObj0 = Gia_ManObj(p, iObj0); pObj1 = Gia_ManObj(p, iObj1); if ( pObj0->Value != pObj1->Value ) return 0; assert( pObj0->Value == pObj1->Value ); if ( !Gia_ObjIsAnd(pObj0) ) continue; if ( Gia_ObjFanin0(pObj0)->Value <= Gia_ObjFanin1(pObj0)->Value ) { if ( Gia_ObjFanin0(pObj1)->Value <= Gia_ObjFanin1(pObj1)->Value ) { if ( Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC0(pObj1) || Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC1(pObj1) || Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) || Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) ) return 0; } else { if ( Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC1(pObj1) || Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC0(pObj1) || Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) || Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) ) return 0; } } else { if ( Gia_ObjFanin0(pObj1)->Value <= Gia_ObjFanin1(pObj1)->Value ) { if ( Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC0(pObj1) || Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC1(pObj1) || Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) || Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) ) return 0; } else { if ( Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC1(pObj1) || Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC0(pObj1) || Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) || Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) ) return 0; } } } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_Iso2ManCheckIsoClassOneSkip( Gia_Man_t * p, Vec_Int_t * vClass, Vec_Int_t * vRoots, Vec_Int_t * vVec0, Vec_Int_t * vVec1, Vec_Int_t * vMap0, Vec_Int_t * vMap1 ) { int i, iPo; assert( Vec_IntSize(vClass) > 1 ); iPo = Vec_IntEntry( vClass, 0 ); Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec0, vMap0 ); Vec_IntForEachEntryStart( vClass, iPo, i, 1 ) { Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec1, vMap1 ); if ( Vec_IntSize(vVec0) != Vec_IntSize(vVec1) ) return 0; if ( !Gia_Iso2ManCheckIsoPair( p, vVec0, vVec1, vMap0, vMap1 ) ) return 0; } return 1; } Vec_Wec_t * Gia_Iso2ManCheckIsoClassesSkip( Gia_Man_t * p, Vec_Wec_t * vEquivs ) { Vec_Wec_t * vEquivs2; Vec_Int_t * vRoots = Vec_IntAlloc( 10000 ); Vec_Int_t * vVec0 = Vec_IntAlloc( 10000 ); Vec_Int_t * vVec1 = Vec_IntAlloc( 10000 ); Vec_Int_t * vMap0 = Vec_IntStart( Gia_ManObjNum(p) ); Vec_Int_t * vMap1 = Vec_IntStart( Gia_ManObjNum(p) ); Vec_Int_t * vClass, * vClass2; int i, k, Entry, Counter = 0; vEquivs2 = Vec_WecAlloc( 2 * Vec_WecSize(vEquivs) ); Vec_WecForEachLevel( vEquivs, vClass, i ) { if ( i % 50 == 0 ) printf( "Finished %8d outputs (out of %8d)...\r", Counter, Gia_ManPoNum(p) ), fflush(stdout); Counter += Vec_IntSize(vClass); if ( Vec_IntSize(vClass) < 2 || Gia_Iso2ManCheckIsoClassOneSkip(p, vClass, vRoots, vVec0, vVec1, vMap0, vMap1) ) { vClass2 = Vec_WecPushLevel( vEquivs2 ); *vClass2 = *vClass; vClass->pArray = NULL; vClass->nSize = vClass->nCap = 0; } else { Vec_IntForEachEntry( vClass, Entry, k ) { vClass2 = Vec_WecPushLevel( vEquivs2 ); Vec_IntPush( vClass2, Entry ); } } } Vec_IntFree( vRoots ); Vec_IntFree( vVec0 ); Vec_IntFree( vVec1 ); Vec_IntFree( vMap0 ); Vec_IntFree( vMap1 ); return vEquivs2; } void Gia_Iso2ManCheckIsoClassOne( Gia_Man_t * p, Vec_Int_t * vClass, Vec_Int_t * vRoots, Vec_Int_t * vVec0, Vec_Int_t * vVec1, Vec_Int_t * vMap0, Vec_Int_t * vMap1, Vec_Int_t * vNewClass ) { int i, k = 1, iPo; Vec_IntClear( vNewClass ); if ( Vec_IntSize(vClass) <= 1 ) return; assert( Vec_IntSize(vClass) > 1 ); iPo = Vec_IntEntry( vClass, 0 ); Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec0, vMap0 ); Vec_IntForEachEntryStart( vClass, iPo, i, 1 ) { Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec1, vMap1 ); if ( Vec_IntSize(vVec0) == Vec_IntSize(vVec1) && Gia_Iso2ManCheckIsoPair(p, vVec0, vVec1, vMap0, vMap1) ) Vec_IntWriteEntry( vClass, k++, iPo ); else Vec_IntPush( vNewClass, iPo ); } Vec_IntShrink( vClass, k ); } Vec_Wec_t * Gia_Iso2ManCheckIsoClasses( Gia_Man_t * p, Vec_Wec_t * vEquivs ) { Vec_Wec_t * vEquivs2; Vec_Int_t * vRoots = Vec_IntAlloc( 10000 ); Vec_Int_t * vVec0 = Vec_IntAlloc( 10000 ); Vec_Int_t * vVec1 = Vec_IntAlloc( 10000 ); Vec_Int_t * vMap0 = Vec_IntStart( Gia_ManObjNum(p) ); Vec_Int_t * vMap1 = Vec_IntStart( Gia_ManObjNum(p) ); Vec_Int_t * vClass, * vClass2, * vNewClass; int i, Counter = 0; vNewClass = Vec_IntAlloc( 100 ); vEquivs2 = Vec_WecAlloc( 2 * Vec_WecSize(vEquivs) ); Vec_WecForEachLevel( vEquivs, vClass, i ) { if ( i % 50 == 0 ) printf( "Finished %8d outputs (out of %8d)...\r", Counter, Gia_ManPoNum(p) ), fflush(stdout); // split this class Gia_Iso2ManCheckIsoClassOne( p, vClass, vRoots, vVec0, vVec1, vMap0, vMap1, vNewClass ); Counter += Vec_IntSize(vClass); // add remaining class vClass2 = Vec_WecPushLevel( vEquivs2 ); *vClass2 = *vClass; vClass->pArray = NULL; vClass->nSize = vClass->nCap = 0; // add new class if ( Vec_IntSize(vNewClass) == 0 ) continue; vClass = Vec_WecPushLevel( vEquivs ); Vec_IntAppend( vClass, vNewClass ); } Vec_IntFree( vNewClass ); Vec_IntFree( vRoots ); Vec_IntFree( vVec0 ); Vec_IntFree( vVec1 ); Vec_IntFree( vMap0 ); Vec_IntFree( vMap1 ); return vEquivs2; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wec_t * Gia_Iso2ManPerform( Gia_Man_t * pGia, int fVerbose ) { Gia_Iso2Man_t * p; abctime clk = Abc_Clock(); p = Gia_Iso2ManStart( pGia ); Gia_Iso2ManPrepare( pGia ); Gia_Iso2ManPropagate( pGia ); Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose ); while ( Gia_Iso2ManUniqify( p ) ) { Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose ); Gia_Iso2ManPropagate( pGia ); } Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose ); /* Gia_Iso2ManUpdate( p, 20 ); while ( Gia_Iso2ManUniqify( p ) ) { Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose ); Gia_Iso2ManPropagate( pGia ); } Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose ); */ Gia_Iso2ManStop( p ); return Gia_Iso2ManDerivePoClasses( pGia ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManIsoReduce2( Gia_Man_t * pGia, Vec_Ptr_t ** pvPosEquivs, Vec_Ptr_t ** pvPiPerms, int fEstimate, int fBetterQual, int fDualOut, int fVerbose, int fVeryVerbose ) { Gia_Man_t * pPart; Vec_Wec_t * vEquivs, * vEquivs2; Vec_Int_t * vRemains; int nClasses, nUsedPos; abctime clk = Abc_Clock(); vEquivs = Gia_Iso2ManPerform( pGia, fVeryVerbose ); // report class stats nClasses = Vec_WecCountNonTrivial( vEquivs, &nUsedPos ); printf( "Reduced %d outputs to %d candidate classes (%d outputs are in %d non-trivial classes). ", Gia_ManPoNum(pGia), Vec_WecSize(vEquivs), nUsedPos, nClasses ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( fEstimate ) { Vec_WecFree( vEquivs ); return Gia_ManDup(pGia); } // verify classes if ( fBetterQual ) vEquivs2 = Gia_Iso2ManCheckIsoClasses( pGia, vEquivs ); else vEquivs2 = Gia_Iso2ManCheckIsoClassesSkip( pGia, vEquivs ); Vec_WecFree( vEquivs ); vEquivs = vEquivs2; // sort equiv classes by the first integer Vec_WecSortByFirstInt( vEquivs, 0 ); // find the first outputs vRemains = Vec_WecCollectFirsts( vEquivs ); // derive the final GIA pPart = Gia_ManDupCones( pGia, Vec_IntArray(vRemains), Vec_IntSize(vRemains), 0 ); Vec_IntFree( vRemains ); // report class stats nClasses = Vec_WecCountNonTrivial( vEquivs, &nUsedPos ); printf( "Reduced %d outputs to %d equivalence classes (%d outputs are in %d non-trivial classes). ", Gia_ManPoNum(pGia), Vec_WecSize(vEquivs), nUsedPos, nClasses ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( fVerbose ) { printf( "Nontrivial classes:\n" ); Vec_WecPrint( vEquivs, 1 ); } if ( pvPiPerms ) *pvPiPerms = NULL; if ( pvPosEquivs ) *pvPosEquivs = Vec_WecConvertToVecPtr( vEquivs ); Vec_WecFree( vEquivs ); // Gia_ManStopP( &pPart ); return pPart; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaIso3.c000066400000000000000000000172451477524141600157420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaIso3.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: giaIso3.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static unsigned Iso_Nodes[6] = { 0x04892ed6, 0xc2523d7d, 0xdc36cd2e, 0xf2db64f8, 0xde3126bb, 0xdebbdff0 }; // ab, a!b, !a!b, pi, po, const0 static unsigned Iso_Fanio[2] = { 0x855ee0cf, 0x946e1b5f }; // fanin, fanout static unsigned Iso_Compl[2] = { 0x8ba63e50, 0x14d87f02 }; // non-compl, compl //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Gia_Iso3Node( Gia_Obj_t * pObj ) { if ( Gia_ObjIsAnd(pObj) ) return Iso_Nodes[Gia_ObjFaninC0(pObj) + Gia_ObjFaninC1(pObj)]; if ( Gia_ObjIsCi(pObj) ) return Iso_Nodes[3]; if ( Gia_ObjIsCo(pObj) ) return Iso_Nodes[4]; return Iso_Nodes[5]; } void Gia_Iso3Init( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) pObj->Value = Gia_Iso3Node( pObj ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_Iso3ComputeEdge( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanin, int fCompl, Vec_Int_t * vSign ) { pObj->Value += Vec_IntEntry(vSign, Gia_ObjId(p, pFanin)) + Iso_Compl[fCompl] + Iso_Fanio[0]; pFanin->Value += Vec_IntEntry(vSign, Gia_ObjId(p, pObj)) + Iso_Compl[fCompl] + Iso_Fanio[1]; } void Gia_Iso3Compute( Gia_Man_t * p, Vec_Int_t * vSign ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) ) Gia_Iso3ComputeEdge( p, pObj, Gia_ObjFanin0(pObj), Gia_ObjFaninC0(pObj), vSign ); if ( Gia_ObjIsAnd(pObj) ) Gia_Iso3ComputeEdge( p, pObj, Gia_ObjFanin1(pObj), Gia_ObjFaninC1(pObj), vSign ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Gia_Iso3Save( Gia_Man_t * p ) { Vec_Int_t * vSign; Gia_Obj_t * pObj; int i; vSign = Vec_IntAlloc( Gia_ManObjNum(p) ); Gia_ManForEachObj( p, pObj, i ) Vec_IntPush( vSign, pObj->Value ); return vSign; } int Gia_Iso3Unique( Vec_Int_t * vSign ) { int nUnique; Vec_Int_t * vCopy = Vec_IntDup( vSign ); Vec_IntUniqify( vCopy ); nUnique = Vec_IntSize(vCopy); Vec_IntFree( vCopy ); return nUnique; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_Iso3Test( Gia_Man_t * p ) { int nIterMax = 500; int i, Prev = -1, This; abctime clk = Abc_Clock(); Vec_Int_t * vSign = NULL; Gia_Iso3Init( p ); for ( i = 0; i < nIterMax; i++ ) { vSign = Gia_Iso3Save( p ); // This = Gia_Iso3Unique( vSign ); This = Vec_IntUniqueCount( vSign, 1, NULL ); printf( "Iter %3d : %6d out of %6d ", i, This, Vec_IntSize(vSign) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( This == Prev ) break; Prev = This; Gia_Iso3Compute( p, vSign ); Vec_IntFreeP( &vSign ); } 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; unsigned 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 /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaJf.c000066400000000000000000001774171477524141600154740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaJf.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: giaJf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/vec/vecSet.h" #include "misc/vec/vecMem.h" #include "misc/extra/extra.h" #include "bool/kit/kit.h" #include "misc/util/utilTruth.h" #include "opt/dau/dau.h" #include "sat/cnf/cnf.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define JF_LEAF_MAX 8 #define JF_WORD_MAX ((JF_LEAF_MAX > 6) ? 1 << (JF_LEAF_MAX-6) : 1) #define JF_CUT_MAX 16 #define JF_EPSILON 0.005 typedef struct Jf_Cut_t_ Jf_Cut_t; struct Jf_Cut_t_ { word Sign; // signature float Flow; // flow int Time; // arrival time int iFunc; // function int Cost; // cut cost int pCut[JF_LEAF_MAX+2]; // cut }; typedef struct Jf_Man_t_ Jf_Man_t; struct Jf_Man_t_ { Gia_Man_t * pGia; // user's manager Jf_Par_t * pPars; // users parameter Sdm_Man_t * pDsd; // extern DSD manager Vec_Int_t * vCnfs; // costs of elementary CNFs Vec_Mem_t * vTtMem; // truth table memory and hash table Vec_Int_t vCuts; // cuts for each node Vec_Int_t vArr; // arrival time Vec_Int_t vDep; // departure time Vec_Flt_t vFlow; // area flow Vec_Flt_t vRefs; // ref counters Vec_Set_t pMem; // cut storage Vec_Int_t * vTemp; // temporary float (*pCutCmp) (Jf_Cut_t *, Jf_Cut_t *);// procedure to compare cuts abctime clkStart; // starting time word CutCount[4]; // statistics int nCoarse; // coarse nodes }; static inline int Jf_ObjIsUnit( Gia_Obj_t * p ) { return !p->fMark0; } static inline void Jf_ObjCleanUnit( Gia_Obj_t * p ) { assert(Jf_ObjIsUnit(p)); p->fMark0 = 1; } static inline void Jf_ObjSetUnit( Gia_Obj_t * p ) { p->fMark0 = 0; } static inline int Jf_ObjCutH( Jf_Man_t * p, int i ) { return Vec_IntEntry(&p->vCuts, i); } static inline int * Jf_ObjCuts( Jf_Man_t * p, int i ) { return (int *)Vec_SetEntry(&p->pMem, Jf_ObjCutH(p, i)); } static inline int * Jf_ObjCutBest( Jf_Man_t * p, int i ) { return Jf_ObjCuts(p, i) + 1; } static inline int Jf_ObjArr( Jf_Man_t * p, int i ) { return Vec_IntEntry(&p->vArr, i); } static inline int Jf_ObjDep( Jf_Man_t * p, int i ) { return Vec_IntEntry(&p->vDep, i); } static inline float Jf_ObjFlow( Jf_Man_t * p, int i ) { return Vec_FltEntry(&p->vFlow, i); } static inline float Jf_ObjRefs( Jf_Man_t * p, int i ) { return Vec_FltEntry(&p->vRefs, i); } //static inline int Jf_ObjLit( int i, int c ) { return i; } static inline int Jf_ObjLit( int i, int c ) { return Abc_Var2Lit( i, c ); } static inline int Jf_CutSize( int * pCut ) { return pCut[0] & 0xF; } // 4 bits static inline int Jf_CutCost( int * pCut ) { return (pCut[0] >> 4) & 0xF; } // 4 bits static inline int Jf_CutFunc( int * pCut ) { return ((unsigned)pCut[0] >> 8); } // 24 bits static inline int Jf_CutSetAll( int f, int c, int s ) { return (f << 8) | (c << 4) | s; } static inline void Jf_CutSetSize( int * pCut, int s ) { assert(s>=0 && s<16); pCut[0] ^= (Jf_CutSize(pCut) ^ s); } static inline void Jf_CutSetCost( int * pCut, int c ) { assert(c>=0 && c<16); pCut[0] ^=((Jf_CutCost(pCut) ^ c) << 4); } static inline void Jf_CutSetFunc( int * pCut, int f ) { assert(f>=0); pCut[0] ^=((Jf_CutFunc(pCut) ^ f) << 8); } static inline int Jf_CutFuncClass( int * pCut ) { return Abc_Lit2Var(Jf_CutFunc(pCut)); } static inline int Jf_CutFuncCompl( int * pCut ) { return Abc_LitIsCompl(Jf_CutFunc(pCut)); } static inline int * Jf_CutLits( int * pCut ) { return pCut + 1; } static inline int Jf_CutLit( int * pCut, int i ) { assert(i);return pCut[i]; } //static inline int Jf_CutVar( int * pCut, int i ) { assert(i); return pCut[i]; } static inline int Jf_CutVar( int * pCut, int i ) { assert(i);return Abc_Lit2Var(pCut[i]); } static inline int Jf_CutIsTriv( int * pCut, int i ) { return Jf_CutSize(pCut) == 1 && Jf_CutVar(pCut, 1) == i; } static inline int Jf_CutCnfSizeF( Jf_Man_t * p, int f ) { return Vec_IntEntry( p->vCnfs, f ); } static inline int Jf_CutCnfSize( Jf_Man_t * p, int * c ) { return Jf_CutCnfSizeF( p, Jf_CutFuncClass(c) ); } static inline int Jf_ObjFunc0( Gia_Obj_t * p, int * c ) { return Abc_LitNotCond(Jf_CutFunc(c), Gia_ObjFaninC0(p)); } static inline int Jf_ObjFunc1( Gia_Obj_t * p, int * c ) { return Abc_LitNotCond(Jf_CutFunc(c), Gia_ObjFaninC1(p)); } #define Jf_ObjForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += Jf_CutSize(pCut) + 1 ) #define Jf_CutForEachLit( pCut, Lit, i ) for ( i = 1; i <= Jf_CutSize(pCut) && (Lit = Jf_CutLit(pCut, i)); i++ ) #define Jf_CutForEachVar( pCut, Var, i ) for ( i = 1; i <= Jf_CutSize(pCut) && (Var = Jf_CutVar(pCut, i)); i++ ) extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives CNF for the mapped GIA.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Jf_ManGenCnf( word uTruth, int iLitOut, Vec_Int_t * vLeaves, Vec_Int_t * vLits, Vec_Int_t * vClas, Vec_Int_t * vCover ) { if ( uTruth == 0 || ~uTruth == 0 ) { Vec_IntPush( vClas, Vec_IntSize(vLits) ); Vec_IntPush( vLits, Abc_LitNotCond(iLitOut, (uTruth == 0)) ); } else { int i, k, c, Literal, Cube; assert( Vec_IntSize(vLeaves) > 0 ); for ( c = 0; c < 2; c ++ ) { int RetValue = Kit_TruthIsop( (unsigned *)&uTruth, Vec_IntSize(vLeaves), vCover, 0 ); assert( RetValue == 0 ); Vec_IntForEachEntry( vCover, Cube, i ) { Vec_IntPush( vClas, Vec_IntSize(vLits) ); Vec_IntPush( vLits, Abc_LitNotCond(iLitOut, c) ); for ( k = 0; k < Vec_IntSize(vLeaves); k++ ) { Literal = 3 & (Cube >> (k << 1)); if ( Literal == 1 ) // '0' -> pos lit Vec_IntPush( vLits, Abc_LitNotCond(Vec_IntEntry(vLeaves, k), 0) ); else if ( Literal == 2 ) // '1' -> neg lit Vec_IntPush( vLits, Abc_LitNotCond(Vec_IntEntry(vLeaves, k), 1) ); else if ( Literal != 0 ) assert( 0 ); } } uTruth = ~uTruth; } } } Cnf_Dat_t * Jf_ManCreateCnfRemap( Gia_Man_t * p, Vec_Int_t * vLits, Vec_Int_t * vClas, int fAddOrCla ) { Cnf_Dat_t * pCnf; Gia_Obj_t * pObj; int i, Entry, * pMap, nVars = 0; if ( fAddOrCla ) { Vec_IntPush( vClas, Vec_IntSize(vLits) ); Gia_ManForEachPo( p, pObj, i ) Vec_IntPush( vLits, Abc_Var2Lit(Gia_ObjId(p, pObj), 0) ); } // label nodes present in the mapping Vec_IntForEachEntry( vLits, Entry, i ) Gia_ManObj(p, Abc_Lit2Var(Entry))->fMark0 = 1; // create variable map pMap = ABC_FALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachObjReverse( p, pObj, i ) if ( pObj->fMark0 ) pObj->fMark0 = 0, pMap[i] = nVars++; // relabel literals Vec_IntForEachEntry( vLits, Entry, i ) Vec_IntWriteEntry( vLits, i, Abc_Lit2LitV(pMap, Entry) ); // generate CNF pCnf = ABC_CALLOC( Cnf_Dat_t, 1 ); pCnf->pMan = (Aig_Man_t *)p; pCnf->nVars = nVars; pCnf->nLiterals = Vec_IntSize(vLits); pCnf->nClauses = Vec_IntSize(vClas); pCnf->pClauses = ABC_ALLOC( int *, pCnf->nClauses+1 ); pCnf->pClauses[0] = Vec_IntReleaseArray(vLits); Vec_IntForEachEntry( vClas, Entry, i ) pCnf->pClauses[i] = pCnf->pClauses[0] + Entry; pCnf->pClauses[i] = pCnf->pClauses[0] + pCnf->nLiterals; pCnf->pVarNums = pMap; return pCnf; } Cnf_Dat_t * Jf_ManCreateCnf( Gia_Man_t * p, Vec_Int_t * vLits, Vec_Int_t * vClas ) { Cnf_Dat_t * pCnf; int i, Entry, iOut; // generate CNF pCnf = ABC_CALLOC( Cnf_Dat_t, 1 ); pCnf->pMan = (Aig_Man_t *)p; pCnf->nVars = Gia_ManObjNum(p); pCnf->nLiterals = Vec_IntSize(vLits); pCnf->nClauses = Vec_IntSize(vClas); pCnf->pClauses = ABC_ALLOC( int *, pCnf->nClauses+1 ); pCnf->pClauses[0] = Vec_IntReleaseArray(vLits); Vec_IntForEachEntry( vClas, Entry, i ) pCnf->pClauses[i] = pCnf->pClauses[0] + Entry; pCnf->pClauses[i] = pCnf->pClauses[0] + pCnf->nLiterals; // create mapping of objects into their clauses pCnf->pObj2Clause = ABC_FALLOC( int, Gia_ManObjNum(p) ); pCnf->pObj2Count = ABC_FALLOC( int, Gia_ManObjNum(p) ); for ( i = 0; i < pCnf->nClauses; i++ ) { iOut = Abc_Lit2Var(pCnf->pClauses[i][0]); if ( pCnf->pObj2Clause[iOut] == -1 ) { pCnf->pObj2Clause[iOut] = i; pCnf->pObj2Count[iOut] = 1; } else { assert( pCnf->pObj2Count[iOut] > 0 ); pCnf->pObj2Count[iOut]++; } } return pCnf; } /**Function************************************************************* Synopsis [Computing references while discounting XOR/MUX.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float * Jf_ManInitRefs( Jf_Man_t * pMan ) { Gia_Man_t * p = pMan->pGia; Gia_Obj_t * pObj, * pCtrl, * pData0, * pData1; float * pRes; int i; assert( p->pRefs == NULL ); p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachAnd( p, pObj, i ) { Gia_ObjRefFanin0Inc( p, pObj ); if ( Gia_ObjIsBuf(pObj) ) continue; Gia_ObjRefFanin1Inc( p, pObj ); if ( !Gia_ObjIsMuxType(pObj) ) continue; // discount XOR/MUX pCtrl = Gia_ObjRecognizeMux( pObj, &pData1, &pData0 ); Gia_ObjRefDec( p, Gia_Regular(pCtrl) ); if ( Gia_Regular(pData1) == Gia_Regular(pData0) ) Gia_ObjRefDec( p, Gia_Regular(pData1) ); } Gia_ManForEachCo( p, pObj, i ) Gia_ObjRefFanin0Inc( p, pObj ); // mark XOR/MUX internal nodes, which are not used elsewhere if ( pMan->pPars->fCoarsen ) { pMan->nCoarse = 0; Gia_ManForEachAnd( p, pObj, i ) { if ( !Gia_ObjIsMuxType(pObj) ) continue; if ( Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 ) { Jf_ObjSetUnit(Gia_ObjFanin0(Gia_ObjFanin0(pObj))); Jf_ObjSetUnit(Gia_ObjFanin0(Gia_ObjFanin1(pObj))); Jf_ObjCleanUnit(Gia_ObjFanin0(pObj)), pMan->nCoarse++; } if ( Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1 ) { Jf_ObjSetUnit(Gia_ObjFanin1(Gia_ObjFanin0(pObj))); Jf_ObjSetUnit(Gia_ObjFanin1(Gia_ObjFanin1(pObj))); Jf_ObjCleanUnit(Gia_ObjFanin1(pObj)), pMan->nCoarse++; } } } // multiply by factor pRes = ABC_ALLOC( float, Gia_ManObjNum(p) ); for ( i = 0; i < Gia_ManObjNum(p); i++ ) pRes[i] = Abc_MaxInt( 1, p->pRefs[i] ); return pRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Jf_ManProfileClasses( Jf_Man_t * p ) { Gia_Obj_t * pObj; int Counts[595] = {0}, Costs[595] = {0}; int i, iFunc, Total = 0, CostTotal = 0, Other = 0, CostOther = 0; printf( "DSD classes that appear in more than %.1f %% of mapped nodes:\n", 0.1 * p->pPars->nVerbLimit ); Gia_ManForEachAnd( p->pGia, pObj, i ) if ( !Gia_ObjIsBuf(pObj) && Gia_ObjRefNumId(p->pGia, i) ) { iFunc = Jf_CutFuncClass( Jf_ObjCutBest(p, i) ); assert( iFunc < 595 ); if ( p->pPars->fGenCnf ) { Costs[iFunc] += Jf_CutCnfSizeF(p, iFunc); CostTotal += Jf_CutCnfSizeF(p, iFunc); } Counts[iFunc]++; Total++; } CostTotal = Abc_MaxInt(CostTotal, 1); Total = Abc_MaxInt(Total, 1); for ( i = 0; i < 595; i++ ) if ( Counts[i] && 100.0 * Counts[i] / Total >= 0.1 * p->pPars->nVerbLimit ) { printf( "%5d : ", i ); printf( "%-20s ", Sdm_ManReadDsdStr(p->pDsd, i) ); printf( "%8d ", Counts[i] ); printf( "%5.1f %% ", 100.0 * Counts[i] / Total ); printf( "%8d ", Costs[i] ); printf( "%5.1f %%", 100.0 * Costs[i] / CostTotal ); printf( "\n" ); } else { Other += Counts[i]; CostOther += Costs[i]; } printf( "Other : " ); printf( "%-20s ", "" ); printf( "%8d ", Other ); printf( "%5.1f %% ", 100.0 * Other / Total ); printf( "%8d ", CostOther ); printf( "%5.1f %%", 100.0 * CostOther / CostTotal ); printf( "\n" ); } /**Function************************************************************* Synopsis [Manager manipulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Jf_Man_t * Jf_ManAlloc( Gia_Man_t * pGia, Jf_Par_t * pPars ) { Jf_Man_t * p; assert( pPars->nLutSize <= JF_LEAF_MAX ); assert( pPars->nCutNum <= JF_CUT_MAX ); Vec_IntFreeP( &pGia->vMapping ); p = ABC_CALLOC( Jf_Man_t, 1 ); p->pGia = pGia; p->pPars = pPars; if ( pPars->fCutMin && !pPars->fFuncDsd ) p->vTtMem = Vec_MemAllocForTT( pPars->nLutSize, 0 ); else if ( pPars->fCutMin && pPars->fFuncDsd ) { p->pDsd = Sdm_ManRead(); if ( pPars->fGenCnf ) { p->vCnfs = Vec_IntStart( 595 ); Sdm_ManReadCnfCosts( p->pDsd, Vec_IntArray(p->vCnfs), Vec_IntSize(p->vCnfs) ); } } Vec_IntFill( &p->vCuts, Gia_ManObjNum(pGia), 0 ); Vec_IntFill( &p->vArr, Gia_ManObjNum(pGia), 0 ); Vec_IntFill( &p->vDep, Gia_ManObjNum(pGia), 0 ); Vec_FltFill( &p->vFlow, Gia_ManObjNum(pGia), 0 ); p->vRefs.nCap = p->vRefs.nSize = Gia_ManObjNum(pGia); p->vRefs.pArray = Jf_ManInitRefs( p ); Vec_SetAlloc_( &p->pMem, 20 ); p->vTemp = Vec_IntAlloc( 1000 ); p->clkStart = Abc_Clock(); return p; } void Jf_ManFree( Jf_Man_t * p ) { if ( p->pPars->fVerbose && p->pDsd ) Sdm_ManPrintDsdStats( p->pDsd, 0 ); if ( p->pPars->fVerbose && p->vTtMem ) { printf( "Unique truth tables = %d. Memory = %.2f MB ", Vec_MemEntryNum(p->vTtMem), Vec_MemMemory(p->vTtMem) / (1<<20) ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); } if ( p->pPars->fVeryVerbose && p->pPars->fCutMin && p->pPars->fFuncDsd ) Jf_ManProfileClasses( p ); if ( p->pPars->fCoarsen ) Gia_ManCleanMark0( p->pGia ); ABC_FREE( p->pGia->pRefs ); ABC_FREE( p->vCuts.pArray ); ABC_FREE( p->vArr.pArray ); ABC_FREE( p->vDep.pArray ); ABC_FREE( p->vFlow.pArray ); ABC_FREE( p->vRefs.pArray ); if ( p->pPars->fCutMin && !p->pPars->fFuncDsd ) { Vec_MemHashFree( p->vTtMem ); Vec_MemFree( p->vTtMem ); } Vec_IntFreeP( &p->vCnfs ); Vec_SetFree_( &p->pMem ); Vec_IntFreeP( &p->vTemp ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Cut functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Jf_CutPrint( int * pCut ) { int i; printf( "%d {", Jf_CutSize(pCut) ); for ( i = 1; i <= Jf_CutSize(pCut); i++ ) printf( " %d", Jf_CutLit(pCut, i) ); printf( " } Func = %d\n", Jf_CutFunc(pCut) ); } static inline void Jf_ObjCutPrint( int * pCuts ) { int i, * pCut; Jf_ObjForEachCut( pCuts, pCut, i ) Jf_CutPrint( pCut ); printf( "\n" ); } static inline void Jf_ObjBestCutConePrint( Jf_Man_t * p, Gia_Obj_t * pObj ) { int * pCut = Jf_ObjCutBest( p, Gia_ObjId(p->pGia, pObj) ); printf( "Best cut of node %d : ", Gia_ObjId(p->pGia, pObj) ); Jf_CutPrint( pCut ); Gia_ManPrintCone( p->pGia, pObj, Jf_CutLits(pCut), Jf_CutSize(pCut), p->vTemp ); } static inline void Jf_CutCheck( int * pCut ) { int i, k; for ( i = 2; i <= Jf_CutSize(pCut); i++ ) for ( k = 1; k < i; k++ ) assert( Jf_CutLit(pCut, i) != Jf_CutLit(pCut, k) ); } static inline int Jf_CountBitsSimple( unsigned n ) { int i, Count = 0; for ( i = 0; i < 32; i++ ) Count += ((n >> i) & 1); return Count; } static inline int Jf_CountBits32( unsigned i ) { i = i - ((i >> 1) & 0x55555555); i = (i & 0x33333333) + ((i >> 2) & 0x33333333); i = ((i + (i >> 4)) & 0x0F0F0F0F); return (i*(0x01010101))>>24; } static inline int Jf_CountBits( word i ) { i = i - ((i >> 1) & 0x5555555555555555); i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); return (i*(0x0101010101010101))>>56; } static inline unsigned Jf_CutGetSign32( int * pCut ) { unsigned Sign = 0; int i; for ( i = 1; i <= Jf_CutSize(pCut); i++ ) Sign |= 1 << (Jf_CutVar(pCut, i) & 0x1F); return Sign; } static inline word Jf_CutGetSign( int * pCut ) { word Sign = 0; int i; for ( i = 1; i <= Jf_CutSize(pCut); i++ ) Sign |= ((word)1) << (Jf_CutVar(pCut, i) & 0x3F); return Sign; } static inline int Jf_CutArr( Jf_Man_t * p, int * pCut ) { int i, Time = 0; for ( i = 1; i <= Jf_CutSize(pCut); i++ ) Time = Abc_MaxInt( Time, Jf_ObjArr(p, Jf_CutVar(pCut, i)) ); return Time + 1; } static inline void Jf_ObjSetBestCut( int * pCuts, int * pCut, Vec_Int_t * vTemp ) { assert( pCuts < pCut ); if ( ++pCuts < pCut ) { int nBlock = pCut - pCuts; int nSize = Jf_CutSize(pCut) + 1; Vec_IntGrow( vTemp, nBlock ); memmove( Vec_IntArray(vTemp), pCuts, sizeof(int) * nBlock ); memmove( pCuts, pCut, sizeof(int) * nSize ); memmove( pCuts + nSize, Vec_IntArray(vTemp), sizeof(int) * nBlock ); } } static inline void Jf_CutRef( Jf_Man_t * p, int * pCut ) { int i; for ( i = 1; i <= Jf_CutSize(pCut); i++ ) Gia_ObjRefIncId( p->pGia, Jf_CutVar(pCut, i) ); } static inline void Jf_CutDeref( Jf_Man_t * p, int * pCut ) { int i; for ( i = 1; i <= Jf_CutSize(pCut); i++ ) Gia_ObjRefDecId( p->pGia, Jf_CutVar(pCut, i) ); } static inline float Jf_CutFlow( Jf_Man_t * p, int * pCut ) { float Flow = 0; int i; for ( i = 1; i <= Jf_CutSize(pCut); i++ ) Flow += Jf_ObjFlow( p, Jf_CutVar(pCut, i) ); assert( Flow >= 0 ); return Flow; } /**Function************************************************************* Synopsis [Cut merging.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Jf_CutIsContainedOrder( int * pBase, int * pCut ) // check if pCut is contained pBase { int nSizeB = Jf_CutSize(pBase); int nSizeC = Jf_CutSize(pCut); int i, k; if ( nSizeB == nSizeC ) { for ( i = 1; i <= nSizeB; i++ ) if ( pBase[i] != pCut[i] ) return 0; return 1; } assert( nSizeB > nSizeC ); for ( i = k = 1; i <= nSizeB; i++ ) { if ( pBase[i] > pCut[k] ) return 0; if ( pBase[i] == pCut[k] ) { if ( k++ == nSizeC ) return 1; } } return 0; } static inline int Jf_CutMergeOrder( int * pCut0, int * pCut1, int * pCut, int LutSize ) { int nSize0 = Jf_CutSize(pCut0); int nSize1 = Jf_CutSize(pCut1); int * pC0 = pCut0 + 1; int * pC1 = pCut1 + 1; int * pC = pCut + 1; int i, k, c, s; // the case of the largest cut sizes if ( nSize0 == LutSize && nSize1 == LutSize ) { for ( i = 0; i < nSize0; i++ ) { if ( pC0[i] != pC1[i] ) return 0; pC[i] = pC0[i]; } pCut[0] = LutSize; return 1; } // compare two cuts with different numbers i = k = c = s = 0; if ( nSize0 == 0 ) goto FlushCut1; if ( nSize1 == 0 ) goto FlushCut0; while ( 1 ) { if ( c == LutSize ) return 0; if ( pC0[i] < pC1[k] ) { pC[c++] = pC0[i++]; if ( i >= nSize0 ) goto FlushCut1; } else if ( pC0[i] > pC1[k] ) { pC[c++] = pC1[k++]; if ( k >= nSize1 ) goto FlushCut0; } else { pC[c++] = pC0[i++]; k++; if ( i >= nSize0 ) goto FlushCut1; if ( k >= nSize1 ) goto FlushCut0; } } FlushCut0: if ( c + nSize0 > LutSize + i ) return 0; while ( i < nSize0 ) pC[c++] = pC0[i++]; pCut[0] = c; return 1; FlushCut1: if ( c + nSize1 > LutSize + k ) return 0; while ( k < nSize1 ) pC[c++] = pC1[k++]; pCut[0] = c; return 1; } /**Function************************************************************* Synopsis [Cut merging.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Jf_CutFindLeaf0( int * pCut, int iObj ) { int i, nLits = Jf_CutSize(pCut); for ( i = 1; i <= nLits; i++ ) if ( pCut[i] == iObj ) return i; return i; } static inline int Jf_CutIsContained0( int * pBase, int * pCut ) // check if pCut is contained pBase { int i, nLits = Jf_CutSize(pCut); for ( i = 1; i <= nLits; i++ ) if ( Jf_CutFindLeaf0(pBase, pCut[i]) > pBase[0] ) return 0; return 1; } static inline int Jf_CutMerge0( int * pCut0, int * pCut1, int * pCut, int LutSize ) { int nSize0 = Jf_CutSize(pCut0); int nSize1 = Jf_CutSize(pCut1), i; pCut[0] = nSize0; for ( i = 1; i <= nSize1; i++ ) if ( Jf_CutFindLeaf0(pCut0, pCut1[i]) > nSize0 ) { if ( pCut[0] == LutSize ) return 0; pCut[++pCut[0]] = pCut1[i]; } memcpy( pCut + 1, pCut0 + 1, sizeof(int) * nSize0 ); return 1; } /**Function************************************************************* Synopsis [Cut merging.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Jf_CutFindLeaf1( int * pCut, int iLit ) { int i, nLits = Jf_CutSize(pCut); for ( i = 1; i <= nLits; i++ ) if ( Abc_Lit2Var(pCut[i]) == iLit ) return i; return i; } static inline int Jf_CutIsContained1( int * pBase, int * pCut ) // check if pCut is contained pBase { int i, nLits = Jf_CutSize(pCut); for ( i = 1; i <= nLits; i++ ) if ( Jf_CutFindLeaf1(pBase, Abc_Lit2Var(pCut[i])) > pBase[0] ) return 0; return 1; } static inline int Jf_CutMerge1( int * pCut0, int * pCut1, int * pCut, int LutSize ) { int nSize0 = Jf_CutSize(pCut0); int nSize1 = Jf_CutSize(pCut1), i; pCut[0] = nSize0; for ( i = 1; i <= nSize1; i++ ) if ( Jf_CutFindLeaf1(pCut0, Abc_Lit2Var(pCut1[i])) > nSize0 ) { if ( pCut[0] == LutSize ) return 0; pCut[++pCut[0]] = pCut1[i]; } memcpy( pCut + 1, pCut0 + 1, sizeof(int) * nSize0 ); return 1; } static inline int Jf_CutMerge2( int * pCut0, int * pCut1, int * pCut, int LutSize ) { int ConfigMask = 0x3FFFF; // 18 bits int nSize0 = Jf_CutSize(pCut0); int nSize1 = Jf_CutSize(pCut1); int i, iPlace; pCut[0] = nSize0; for ( i = 1; i <= nSize1; i++ ) { iPlace = Jf_CutFindLeaf1(pCut0, Abc_Lit2Var(pCut1[i])); if ( iPlace > nSize0 ) { if ( pCut[0] == LutSize ) return 0; pCut[(iPlace = ++pCut[0])] = pCut1[i]; } else if ( pCut0[iPlace] != pCut1[i] ) ConfigMask |= (1 << (iPlace+17)); ConfigMask ^= (((i-1) ^ 7) << (3*(iPlace-1))); } memcpy( pCut + 1, pCut0 + 1, sizeof(int) * nSize0 ); return ConfigMask; } /**Function************************************************************* Synopsis [Cut filtering.] Description [Returns the number of cuts after filtering and the last cut in the last entry. If the cut is filtered, its size is set to -1.] SideEffects [This was found to be 15% slower.] SeeAlso [] ***********************************************************************/ int Jf_ObjCutFilterBoth( Jf_Man_t * p, Jf_Cut_t ** pSto, int c ) { int k, last; // filter this cut using other cuts for ( k = 0; k < c; k++ ) if ( pSto[c]->pCut[0] >= pSto[k]->pCut[0] && (pSto[c]->Sign & pSto[k]->Sign) == pSto[k]->Sign && Jf_CutIsContained1(pSto[c]->pCut, pSto[k]->pCut) ) { pSto[c]->pCut[0] = -1; return c; } // filter other cuts using this cut for ( k = last = 0; k < c; k++ ) if ( !(pSto[c]->pCut[0] < pSto[k]->pCut[0] && (pSto[c]->Sign & pSto[k]->Sign) == pSto[c]->Sign && Jf_CutIsContained1(pSto[k]->pCut, pSto[c]->pCut)) ) { if ( last++ == k ) continue; ABC_SWAP( Jf_Cut_t *, pSto[last-1], pSto[k] ); } assert( last <= c ); if ( last < c ) ABC_SWAP( Jf_Cut_t *, pSto[last], pSto[c] ); return last; } int Jf_ObjCutFilter( Jf_Man_t * p, Jf_Cut_t ** pSto, int c ) { int k; if ( p->pPars->fCutMin ) { for ( k = 0; k < c; k++ ) if ( pSto[c]->pCut[0] >= pSto[k]->pCut[0] && (pSto[c]->Sign & pSto[k]->Sign) == pSto[k]->Sign && Jf_CutIsContained1(pSto[c]->pCut, pSto[k]->pCut) ) return 0; } else { for ( k = 0; k < c; k++ ) if ( pSto[c]->pCut[0] >= pSto[k]->pCut[0] && (pSto[c]->Sign & pSto[k]->Sign) == pSto[k]->Sign && Jf_CutIsContainedOrder(pSto[c]->pCut, pSto[k]->pCut) ) return 0; } return 1; } /**Function************************************************************* Synopsis [Sorting cuts by size.] Description [] SideEffects [Did not really help.] SeeAlso [] ***********************************************************************/ static inline void Jf_ObjSortCuts( Jf_Cut_t ** pSto, int nSize ) { int i, j, best_i; for ( i = 0; i < nSize-1; i++ ) { best_i = i; for ( j = i+1; j < nSize; j++ ) if ( pSto[j]->pCut[0] < pSto[best_i]->pCut[0] ) best_i = j; ABC_SWAP( Jf_Cut_t *, pSto[i], pSto[best_i] ); } } /**Function************************************************************* Synopsis [Reference counting.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Jf_CutRef_rec( Jf_Man_t * p, int * pCut ) { int i, Var, Count = Jf_CutCost(pCut); Jf_CutForEachVar( pCut, Var, i ) if ( !Gia_ObjRefIncId(p->pGia, Var) && !Jf_CutIsTriv(Jf_ObjCutBest(p, Var), Var) ) Count += Jf_CutRef_rec( p, Jf_ObjCutBest(p, Var) ); return Count; } int Jf_CutDeref_rec( Jf_Man_t * p, int * pCut ) { int i, Var, Count = Jf_CutCost(pCut); Jf_CutForEachVar( pCut, Var, i ) if ( !Gia_ObjRefDecId(p->pGia, Var) && !Jf_CutIsTriv(Jf_ObjCutBest(p, Var), Var) ) Count += Jf_CutDeref_rec( p, Jf_ObjCutBest(p, Var) ); return Count; } static inline int Jf_CutAreaOld( Jf_Man_t * p, int * pCut ) { int Ela1, Ela2; Ela1 = Jf_CutRef_rec( p, pCut ); Ela2 = Jf_CutDeref_rec( p, pCut ); assert( Ela1 == Ela2 ); return Ela1; } int Jf_CutAreaRef_rec( Jf_Man_t * p, int * pCut ) { int i, Var, Count = Jf_CutCost(pCut); Jf_CutForEachVar( pCut, Var, i ) { if ( !Gia_ObjRefIncId(p->pGia, Var) && !Jf_CutIsTriv(Jf_ObjCutBest(p, Var), Var) ) Count += Jf_CutAreaRef_rec( p, Jf_ObjCutBest(p, Var) ); Vec_IntPush( p->vTemp, Var ); } return Count; } int Jf_CutAreaRefEdge_rec( Jf_Man_t * p, int * pCut ) { int i, Var, Count = (Jf_CutCost(pCut) << 4) | Jf_CutSize(pCut); Jf_CutForEachVar( pCut, Var, i ) { if ( !Gia_ObjRefIncId(p->pGia, Var) && !Jf_CutIsTriv(Jf_ObjCutBest(p, Var), Var) ) Count += Jf_CutAreaRefEdge_rec( p, Jf_ObjCutBest(p, Var) ); Vec_IntPush( p->vTemp, Var ); } return Count; } static inline int Jf_CutArea( Jf_Man_t * p, int * pCut, int fEdge ) { int Ela, Entry, i; Vec_IntClear( p->vTemp ); if ( fEdge ) Ela = Jf_CutAreaRefEdge_rec( p, pCut ); else Ela = Jf_CutAreaRef_rec( p, pCut ); Vec_IntForEachEntry( p->vTemp, Entry, i ) Gia_ObjRefDecId( p->pGia, Entry ); return Ela; } // returns 1 if MFFC size is less than limit int Jf_CutCheckMffc_rec( Jf_Man_t * p, int * pCut, int Limit ) { int i, Var; Jf_CutForEachVar( pCut, Var, i ) { int fRecur = (!Gia_ObjRefDecId(p->pGia, Var) && !Jf_CutIsTriv(Jf_ObjCutBest(p, Var), Var)); Vec_IntPush( p->vTemp, Var ); if ( Vec_IntSize(p->vTemp) >= Limit ) return 0; if ( fRecur && !Jf_CutCheckMffc_rec( p, Jf_ObjCutBest(p, Var), Limit ) ) return 0; } return 1; } static inline int Jf_CutCheckMffc( Jf_Man_t * p, int * pCut, int Limit ) { int RetValue, Entry, i; Vec_IntClear( p->vTemp ); RetValue = Jf_CutCheckMffc_rec( p, pCut, Limit ); Vec_IntForEachEntry( p->vTemp, Entry, i ) Gia_ObjRefIncId( p->pGia, Entry ); return RetValue; } /**Function************************************************************* Synopsis [Comparison procedures.] Description [Return positive value if the new cut is better than the old cut.] SideEffects [] SeeAlso [] ***********************************************************************/ float Jf_CutCompareDelay( Jf_Cut_t * pOld, Jf_Cut_t * pNew ) { if ( pOld->Time != pNew->Time ) return pOld->Time - pNew->Time; if ( pOld->pCut[0] != pNew->pCut[0] ) return pOld->pCut[0] - pNew->pCut[0]; // if ( pOld->Flow != pNew->Flow ) return pOld->Flow - pNew->Flow; if ( pOld->Flow < pNew->Flow - JF_EPSILON ) return -1; if ( pOld->Flow > pNew->Flow + JF_EPSILON ) return 1; return 0; } float Jf_CutCompareArea( Jf_Cut_t * pOld, Jf_Cut_t * pNew ) { // if ( pOld->Flow != pNew->Flow ) return pOld->Flow - pNew->Flow; if ( pOld->Flow < pNew->Flow - JF_EPSILON ) return -1; if ( pOld->Flow > pNew->Flow + JF_EPSILON ) return 1; if ( pOld->pCut[0] != pNew->pCut[0] ) return pOld->pCut[0] - pNew->pCut[0]; if ( pOld->Time != pNew->Time ) return pOld->Time - pNew->Time; return 0; } static inline int Jf_ObjAddCutToStore( Jf_Man_t * p, Jf_Cut_t ** pSto, int c, int cMax ) { Jf_Cut_t * pTemp; int k, last, iPivot; // if the store is empty, add anything if ( c == 0 ) return 1; // special case when the cut store is full and last cut is better than new cut if ( c == cMax && p->pCutCmp(pSto[c-1], pSto[c]) <= 0 ) return c; // find place of the given cut in the store assert( c <= cMax ); for ( iPivot = c-1; iPivot >= 0; iPivot-- ) if ( p->pCutCmp(pSto[iPivot], pSto[c]) < 0 ) // iPivot-th cut is better than new cut break; // filter this cut using other cuts if ( p->pPars->fCutMin ) { for ( k = 0; k <= iPivot; k++ ) if ( pSto[c]->pCut[0] >= pSto[k]->pCut[0] && (pSto[c]->Sign & pSto[k]->Sign) == pSto[k]->Sign && Jf_CutIsContained1(pSto[c]->pCut, pSto[k]->pCut) ) return c; } else { for ( k = 0; k <= iPivot; k++ ) if ( pSto[c]->pCut[0] >= pSto[k]->pCut[0] && (pSto[c]->Sign & pSto[k]->Sign) == pSto[k]->Sign && Jf_CutIsContainedOrder(pSto[c]->pCut, pSto[k]->pCut) ) return c; } // insert this cut after iPivot pTemp = pSto[c]; for ( ++iPivot, k = c++; k > iPivot; k-- ) pSto[k] = pSto[k-1]; pSto[iPivot] = pTemp; // filter other cuts using this cut if ( p->pPars->fCutMin ) { for ( k = last = iPivot+1; k < c; k++ ) if ( !(pSto[iPivot]->pCut[0] <= pSto[k]->pCut[0] && (pSto[iPivot]->Sign & pSto[k]->Sign) == pSto[iPivot]->Sign && Jf_CutIsContained1(pSto[k]->pCut, pSto[iPivot]->pCut)) ) { if ( last++ == k ) continue; ABC_SWAP( Jf_Cut_t *, pSto[last-1], pSto[k] ); } } else { for ( k = last = iPivot+1; k < c; k++ ) if ( !(pSto[iPivot]->pCut[0] <= pSto[k]->pCut[0] && (pSto[iPivot]->Sign & pSto[k]->Sign) == pSto[iPivot]->Sign && Jf_CutIsContainedOrder(pSto[k]->pCut, pSto[iPivot]->pCut)) ) { if ( last++ == k ) continue; ABC_SWAP( Jf_Cut_t *, pSto[last-1], pSto[k] ); } } c = last; // remove the last cut if too many if ( c == cMax + 1 ) return c - 1; return c; } static inline void Jf_ObjPrintStore( Jf_Man_t * p, Jf_Cut_t ** pSto, int c ) { int i; for ( i = 0; i < c; i++ ) { printf( "Flow =%9.5f ", pSto[i]->Flow ); printf( "Time = %5d ", pSto[i]->Time ); printf( "Func = %5d ", pSto[i]->iFunc ); printf( " " ); Jf_CutPrint( pSto[i]->pCut ); } printf( "\n" ); } static inline void Jf_ObjCheckPtrs( Jf_Cut_t ** pSto, int c ) { int i, k; for ( i = 1; i < c; i++ ) for ( k = 0; k < i; k++ ) assert( pSto[k] != pSto[i] ); } static inline void Jf_ObjCheckStore( Jf_Man_t * p, Jf_Cut_t ** pSto, int c, int iObj ) { int i, k; for ( i = 1; i < c; i++ ) assert( p->pCutCmp(pSto[i-1], pSto[i]) <= 0 ); for ( i = 1; i < c; i++ ) for ( k = 0; k < i; k++ ) { assert( !Jf_CutIsContained1(pSto[k]->pCut, pSto[i]->pCut) ); assert( !Jf_CutIsContained1(pSto[i]->pCut, pSto[k]->pCut) ); } } /**Function************************************************************* Synopsis [Cut minimization.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Jf_TtComputeForCut( Jf_Man_t * p, int iFuncLit0, int iFuncLit1, int * pCut0, int * pCut1, int * pCutOut ) { word uTruth[JF_WORD_MAX], uTruth0[JF_WORD_MAX], uTruth1[JF_WORD_MAX]; int fCompl, truthId; int LutSize = p->pPars->nLutSize; int nWords = Abc_Truth6WordNum(p->pPars->nLutSize); word * pTruth0 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(iFuncLit0)); word * pTruth1 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(iFuncLit1)); Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(iFuncLit0) ); Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(iFuncLit1) ); Abc_TtExpand( uTruth0, LutSize, pCut0 + 1, Jf_CutSize(pCut0), pCutOut + 1, Jf_CutSize(pCutOut) ); Abc_TtExpand( uTruth1, LutSize, pCut1 + 1, Jf_CutSize(pCut1), pCutOut + 1, Jf_CutSize(pCutOut) ); fCompl = (int)(uTruth0[0] & uTruth1[0] & 1); Abc_TtAnd( uTruth, uTruth0, uTruth1, nWords, fCompl ); pCutOut[0] = Abc_TtMinBase( uTruth, pCutOut + 1, pCutOut[0], LutSize ); assert( (uTruth[0] & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, uTruth); return Abc_Var2Lit( truthId, fCompl ); } /**Function************************************************************* Synopsis [Cut enumeration.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Jf_ObjAssignCut( Jf_Man_t * p, Gia_Obj_t * pObj ) { int iObj = Gia_ObjId(p->pGia, pObj); int pClause[3] = { 1, Jf_CutSetAll(2, 0, 1), Jf_ObjLit(iObj, 0) }; // set function assert( Gia_ObjIsCi(pObj) || Gia_ObjIsBuf(pObj) ); Vec_IntWriteEntry( &p->vCuts, iObj, Vec_SetAppend( &p->pMem, pClause, 3 ) ); } static inline void Jf_ObjPropagateBuf( Jf_Man_t * p, Gia_Obj_t * pObj, int fReverse ) { int iObj = Gia_ObjId( p->pGia, pObj ); int iFanin = Gia_ObjFaninId0( pObj, iObj ); assert( 0 ); assert( Gia_ObjIsBuf(pObj) ); if ( fReverse ) ABC_SWAP( int, iObj, iFanin ); Vec_IntWriteEntry( &p->vArr, iObj, Jf_ObjArr(p, iFanin) ); Vec_FltWriteEntry( &p->vFlow, iObj, Jf_ObjFlow(p, iFanin) ); } static inline int Jf_ObjHasCutWithSize( Jf_Cut_t ** pSto, int c, int nSize ) { int i; for ( i = 0; i < c; i++ ) if ( pSto[i]->pCut[0] <= nSize ) return 1; return 0; } void Jf_ObjComputeCuts( Jf_Man_t * p, Gia_Obj_t * pObj, int fEdge ) { int LutSize = p->pPars->nLutSize; int CutNum = p->pPars->nCutNum; int iObj = Gia_ObjId(p->pGia, pObj); word Sign0[JF_CUT_MAX+2]; // signatures of the first cut word Sign1[JF_CUT_MAX+2]; // signatures of the second cut Jf_Cut_t Sto[JF_CUT_MAX+2]; // cut storage Jf_Cut_t * pSto[JF_CUT_MAX+2]; // pointers to cut storage int * pCut0, * pCut1, * pCuts0, * pCuts1; int nOldSupp, Config, i, k, c = 0; // prepare cuts for ( i = 0; i <= CutNum+1; i++ ) pSto[i] = Sto + i, pSto[i]->Cost = 0, pSto[i]->iFunc = ~0; // compute signatures pCuts0 = Jf_ObjCuts( p, Gia_ObjFaninId0(pObj, iObj) ); Jf_ObjForEachCut( pCuts0, pCut0, i ) Sign0[i] = Jf_CutGetSign( pCut0 ); // compute signatures pCuts1 = Jf_ObjCuts( p, Gia_ObjFaninId1(pObj, iObj) ); Jf_ObjForEachCut( pCuts1, pCut1, i ) Sign1[i] = Jf_CutGetSign( pCut1 ); // merge cuts p->CutCount[0] += pCuts0[0] * pCuts1[0]; Jf_ObjForEachCut( pCuts0, pCut0, i ) Jf_ObjForEachCut( pCuts1, pCut1, k ) { if ( Jf_CountBits(Sign0[i] | Sign1[k]) > LutSize ) continue; p->CutCount[1]++; if ( !p->pPars->fCutMin ) { if ( !Jf_CutMergeOrder(pCut0, pCut1, pSto[c]->pCut, LutSize) ) continue; pSto[c]->Sign = Sign0[i] | Sign1[k]; } else if ( p->pPars->fFuncDsd ) { if ( !(Config = Jf_CutMerge2(pCut0, pCut1, pSto[c]->pCut, LutSize)) ) continue; pSto[c]->Sign = Sign0[i] | Sign1[k]; nOldSupp = pSto[c]->pCut[0]; pSto[c]->iFunc = Sdm_ManComputeFunc( p->pDsd, Jf_ObjFunc0(pObj, pCut0), Jf_ObjFunc1(pObj, pCut1), pSto[c]->pCut, Config, 0 ); if ( pSto[c]->iFunc == -1 ) continue; if ( p->pPars->fGenCnf && Jf_CutCnfSizeF(p, Abc_Lit2Var(pSto[c]->iFunc)) >= 12 ) // no more than 15 continue; assert( pSto[c]->pCut[0] <= nOldSupp ); if ( pSto[c]->pCut[0] < nOldSupp ) pSto[c]->Sign = Jf_CutGetSign( pSto[c]->pCut ); } else { if ( !Jf_CutMergeOrder(pCut0, pCut1, pSto[c]->pCut, LutSize) ) continue; pSto[c]->Sign = Sign0[i] | Sign1[k]; nOldSupp = pSto[c]->pCut[0]; pSto[c]->iFunc = Jf_TtComputeForCut( p, Jf_ObjFunc0(pObj, pCut0), Jf_ObjFunc1(pObj, pCut1), pCut0, pCut1, pSto[c]->pCut ); assert( pSto[c]->pCut[0] <= nOldSupp ); if ( pSto[c]->pCut[0] < nOldSupp ) pSto[c]->Sign = Jf_CutGetSign( pSto[c]->pCut ); if ( pSto[c]->iFunc >= (1 << 24) ) printf( "Hard limit on the number of different Boolean functions (2^23) is reached. Quitting...\n" ), exit(1); } p->CutCount[2]++; pSto[c]->Time = p->pPars->fAreaOnly ? 0 : Jf_CutArr(p, pSto[c]->pCut); pSto[c]->Flow = Jf_CutFlow(p, pSto[c]->pCut); c = Jf_ObjAddCutToStore( p, pSto, c, CutNum ); assert( c <= CutNum ); } // Jf_ObjPrintStore( p, pSto, c ); // Jf_ObjCheckStore( p, pSto, c, iObj ); // add two variable cut if ( !Jf_ObjIsUnit(pObj) && !Jf_ObjHasCutWithSize(pSto, c, 2) ) { assert( Jf_ObjIsUnit(Gia_ObjFanin0(pObj)) && Jf_ObjIsUnit(Gia_ObjFanin1(pObj)) ); if ( p->pPars->fCutMin ) pSto[c]->iFunc = 4; // set function (DSD only!) pSto[c]->pCut[0] = 2; pSto[c]->pCut[1] = Jf_ObjLit(Gia_ObjFaninId0(pObj, iObj), Gia_ObjFaninC0(pObj)); pSto[c]->pCut[2] = Jf_ObjLit(Gia_ObjFaninId1(pObj, iObj), Gia_ObjFaninC1(pObj)); c++; } // add elementary cut if ( Jf_ObjIsUnit(pObj) && !(p->pPars->fCutMin && Jf_ObjHasCutWithSize(pSto, c, 1)) ) { if ( p->pPars->fCutMin ) pSto[c]->iFunc = 2; // set function pSto[c]->pCut[0] = 1; pSto[c]->pCut[1] = Jf_ObjLit(iObj, 0); c++; } // reorder cuts // Jf_ObjSortCuts( pSto + 1, c - 1 ); // Jf_ObjCheckPtrs( pSto, CutNum ); // find cost of the best cut pSto[0]->Cost = p->pPars->fGenCnf ? Jf_CutCnfSizeF(p, Abc_Lit2Var(pSto[0]->iFunc)) : 1; assert( pSto[0]->Cost >= 0 ); // save best info assert( pSto[0]->Flow >= 0 ); Vec_IntWriteEntry( &p->vArr, iObj, pSto[0]->Time ); Vec_FltWriteEntry( &p->vFlow, iObj, (pSto[0]->Flow + (fEdge ? pSto[0]->pCut[0] : pSto[0]->Cost)) / Jf_ObjRefs(p, iObj) ); // add cuts to storage cuts Vec_IntClear( p->vTemp ); Vec_IntPush( p->vTemp, c ); for ( i = 0; i < c; i++ ) { pSto[i]->Cost = p->pPars->fGenCnf ? Jf_CutCnfSizeF(p, Abc_Lit2Var(pSto[i]->iFunc)) : 1; Vec_IntPush( p->vTemp, Jf_CutSetAll(pSto[i]->iFunc, pSto[i]->Cost, pSto[i]->pCut[0]) ); for ( k = 1; k <= pSto[i]->pCut[0]; k++ ) Vec_IntPush( p->vTemp, pSto[i]->pCut[k] ); } Vec_IntWriteEntry( &p->vCuts, iObj, Vec_SetAppend(&p->pMem, Vec_IntArray(p->vTemp), Vec_IntSize(p->vTemp)) ); p->CutCount[3] += c; } void Jf_ManComputeCuts( Jf_Man_t * p, int fEdge ) { Gia_Obj_t * pObj; int i; if ( p->pPars->fVerbose ) { printf( "Aig: CI = %d CO = %d AND = %d ", Gia_ManCiNum(p->pGia), Gia_ManCoNum(p->pGia), Gia_ManAndNum(p->pGia) ); printf( "LutSize = %d CutMax = %d Rounds = %d\n", p->pPars->nLutSize, p->pPars->nCutNum, p->pPars->nRounds ); printf( "Computing cuts...\r" ); fflush( stdout ); } Gia_ManForEachObj( p->pGia, pObj, i ) { if ( Gia_ObjIsCi(pObj) || Gia_ObjIsBuf(pObj) ) Jf_ObjAssignCut( p, pObj ); if ( Gia_ObjIsBuf(pObj) ) Jf_ObjPropagateBuf( p, pObj, 0 ); else if ( Gia_ObjIsAnd(pObj) ) Jf_ObjComputeCuts( p, pObj, fEdge ); } if ( p->pPars->fVerbose ) { printf( "CutPair = %lu ", (long)p->CutCount[0] ); printf( "Merge = %lu ", (long)p->CutCount[1] ); printf( "Eval = %lu ", (long)p->CutCount[2] ); printf( "Cut = %lu ", (long)p->CutCount[3] ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); printf( "Memory: " ); printf( "Gia = %.2f MB ", Gia_ManMemory(p->pGia) / (1<<20) ); printf( "Man = %.2f MB ", 6.0 * sizeof(int) * Gia_ManObjNum(p->pGia) / (1<<20) ); printf( "Cuts = %.2f MB", Vec_ReportMemory(&p->pMem) / (1<<20) ); if ( p->nCoarse ) printf( " Coarse = %d (%.1f %%)", p->nCoarse, 100.0 * p->nCoarse / Gia_ManObjNum(p->pGia) ); printf( "\n" ); fflush( stdout ); } } /**Function************************************************************* Synopsis [Computing delay/area.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Jf_ManComputeDelay( Jf_Man_t * p, int fEval ) { Gia_Obj_t * pObj; int i, Delay = 0; if ( fEval ) { Gia_ManForEachObj( p->pGia, pObj, i ) if ( Gia_ObjIsBuf(pObj) ) Jf_ObjPropagateBuf( p, pObj, 0 ); else if ( Gia_ObjIsAnd(pObj) && Gia_ObjRefNum(p->pGia, pObj) > 0 ) Vec_IntWriteEntry( &p->vArr, i, Jf_CutArr(p, Jf_ObjCutBest(p, i)) ); } Gia_ManForEachCoDriver( p->pGia, pObj, i ) { assert( Gia_ObjRefNum(p->pGia, pObj) > 0 ); Delay = Abc_MaxInt( Delay, Jf_ObjArr(p, Gia_ObjId(p->pGia, pObj)) ); } return Delay; } int Jf_ManComputeRefs( Jf_Man_t * p ) { Gia_Obj_t * pObj; float nRefsNew; int i, * pCut; float * pRefs = Vec_FltArray(&p->vRefs); float * pFlow = Vec_FltArray(&p->vFlow); assert( p->pGia->pRefs != NULL ); memset( p->pGia->pRefs, 0, sizeof(int) * Gia_ManObjNum(p->pGia) ); p->pPars->Area = p->pPars->Edge = 0; Gia_ManForEachObjReverse( p->pGia, pObj, i ) { if ( Gia_ObjIsCo(pObj) || Gia_ObjIsBuf(pObj) ) Gia_ObjRefInc( p->pGia, Gia_ObjFanin0(pObj) ); else if ( Gia_ObjIsAnd(pObj) && Gia_ObjRefNum(p->pGia, pObj) > 0 ) { assert( Jf_ObjIsUnit(pObj) ); pCut = Jf_ObjCutBest(p, i); Jf_CutRef( p, pCut ); if ( p->pPars->fGenCnf ) p->pPars->Clause += Jf_CutCnfSize(p, pCut); p->pPars->Edge += Jf_CutSize(pCut); p->pPars->Area++; } } // blend references and normalize flow for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ ) { if ( p->pPars->fOptEdge ) nRefsNew = Abc_MaxFloat( 1, 0.8 * pRefs[i] + 0.2 * p->pGia->pRefs[i] ); else nRefsNew = Abc_MaxFloat( 1, 0.2 * pRefs[i] + 0.8 * p->pGia->pRefs[i] ); pFlow[i] = pFlow[i] * pRefs[i] / nRefsNew; pRefs[i] = nRefsNew; assert( pFlow[i] >= 0 ); } // compute delay p->pPars->Delay = Jf_ManComputeDelay( p, 1 ); return p->pPars->Area; } /**Function************************************************************* Synopsis [Mapping rounds.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Jf_ObjComputeBestCut( Jf_Man_t * p, Gia_Obj_t * pObj, int fEdge, int fEla ) { int i, iObj = Gia_ObjId( p->pGia, pObj ); int * pCuts = Jf_ObjCuts( p, iObj ); int * pCut, * pCutBest = NULL; int Time = ABC_INFINITY, TimeBest = ABC_INFINITY; float Area, AreaBest = ABC_INFINITY; Jf_ObjForEachCut( pCuts, pCut, i ) { if ( Jf_CutIsTriv(pCut, iObj) ) continue; if ( fEdge && !fEla ) Jf_CutSetCost(pCut, Jf_CutSize(pCut)); Area = fEla ? Jf_CutArea(p, pCut, fEdge) : Jf_CutFlow(p, pCut) + Jf_CutCost(pCut); if ( pCutBest == NULL || AreaBest > Area + JF_EPSILON || (AreaBest > Area - JF_EPSILON && TimeBest > (Time = Jf_CutArr(p, pCut))) ) pCutBest = pCut, AreaBest = Area, TimeBest = Time; } Vec_IntWriteEntry( &p->vArr, iObj, Jf_CutArr(p, pCutBest) ); if ( !fEla ) Vec_FltWriteEntry( &p->vFlow, iObj, AreaBest / Jf_ObjRefs(p, iObj) ); Jf_ObjSetBestCut( pCuts, pCutBest, p->vTemp ); // Jf_CutPrint( Jf_ObjCutBest(p, iObj) ); printf( "\n" ); } void Jf_ManPropagateFlow( Jf_Man_t * p, int fEdge ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p->pGia, pObj, i ) if ( Gia_ObjIsBuf(pObj) ) Jf_ObjPropagateBuf( p, pObj, 0 ); else if ( Gia_ObjIsAnd(pObj) && Jf_ObjIsUnit(pObj) ) Jf_ObjComputeBestCut( p, pObj, fEdge, 0 ); Jf_ManComputeRefs( p ); } void Jf_ManPropagateEla( Jf_Man_t * p, int fEdge ) { Gia_Obj_t * pObj; int i, CostBef, CostAft; p->pPars->Area = p->pPars->Edge = p->pPars->Clause = 0; Gia_ManForEachObjReverse( p->pGia, pObj, i ) if ( Gia_ObjIsBuf(pObj) ) Jf_ObjPropagateBuf( p, pObj, 1 ); else if ( Gia_ObjIsAnd(pObj) && Gia_ObjRefNum(p->pGia, pObj) > 0 ) { assert( Jf_ObjIsUnit(pObj) ); if ( Jf_CutCheckMffc(p, Jf_ObjCutBest(p, i), 50) ) { CostBef = Jf_CutDeref_rec( p, Jf_ObjCutBest(p, i) ); Jf_ObjComputeBestCut( p, pObj, fEdge, 1 ); CostAft = Jf_CutRef_rec( p, Jf_ObjCutBest(p, i) ); // if ( CostBef != CostAft ) printf( "%d -> %d ", CostBef, CostAft ); assert( CostBef >= CostAft ); // does not hold because of JF_EDGE_LIM } if ( p->pPars->fGenCnf ) p->pPars->Clause += Jf_CutCnfSize(p, Jf_ObjCutBest(p, i)); p->pPars->Edge += Jf_CutSize(Jf_ObjCutBest(p, i)); p->pPars->Area++; } p->pPars->Delay = Jf_ManComputeDelay( p, 1 ); // printf( "\n" ); } /**Function************************************************************* Synopsis [Derives the result of mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Jf_ManDeriveMappingGia( Jf_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; Vec_Int_t * vCopies = Vec_IntStartFull( Gia_ManObjNum(p->pGia) ); Vec_Int_t * vMapping = Vec_IntStart( 2 * Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + 2 * (int)p->pPars->Area ); Vec_Int_t * vMapping2 = Vec_IntStart( (int)p->pPars->Edge + 2 * (int)p->pPars->Area + 1000 ); Vec_Int_t * vCover = Vec_IntAlloc( 1 << 16 ); Vec_Int_t * vLeaves = Vec_IntAlloc( 16 ); Vec_Int_t * vLits = NULL, * vClas = NULL; int i, k, iLit, Class, * pCut; word uTruth = 0, * pTruth = &uTruth; assert( p->pPars->fCutMin ); if ( p->pPars->fGenCnf ) { vLits = Vec_IntAlloc( 1000 ); vClas = Vec_IntAlloc( 1000 ); Vec_IntPush( vClas, Vec_IntSize(vLits) ); Vec_IntPush( vLits, 1 ); } // create new manager pNew = Gia_ManStart( Gia_ManObjNum(p->pGia) ); pNew->pName = Abc_UtilStrsav( p->pGia->pName ); pNew->pSpec = Abc_UtilStrsav( p->pGia->pSpec ); // map primary inputs Vec_IntWriteEntry( vCopies, 0, 0 ); Gia_ManForEachCi( p->pGia, pObj, i ) Vec_IntWriteEntry( vCopies, Gia_ObjId(p->pGia, pObj), Gia_ManAppendCi(pNew) ); // iterate through nodes used in the mapping Gia_ManForEachAnd( p->pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) || Gia_ObjRefNum(p->pGia, pObj) == 0 ) continue; pCut = Jf_ObjCutBest( p, i ); // printf( "Best cut of node %d: ", i ); Jf_CutPrint(pCut); Class = Jf_CutFuncClass( pCut ); if ( Jf_CutSize(pCut) == 0 ) { assert( Class == 0 ); Vec_IntWriteEntry( vCopies, i, Jf_CutFunc(pCut) ); continue; } if ( Jf_CutSize(pCut) == 1 ) { assert( Class == 1 ); iLit = Abc_LitNotCond( Jf_CutLit(pCut, 1) , Jf_CutFuncCompl(pCut) ); iLit = Abc_Lit2LitL( Vec_IntArray(vCopies), iLit ); Vec_IntWriteEntry( vCopies, i, iLit ); continue; } if ( p->pPars->fFuncDsd ) uTruth = Sdm_ManReadDsdTruth(p->pDsd, Class); else pTruth = Vec_MemReadEntry(p->vTtMem, Class); assert( p->pDsd == NULL || Sdm_ManReadDsdVarNum(p->pDsd, Class) == Jf_CutSize(pCut) ); // collect leaves Vec_IntClear( vLeaves ); Jf_CutForEachLit( pCut, iLit, k ) Vec_IntPush( vLeaves, Abc_Lit2LitL(Vec_IntArray(vCopies), iLit) ); // create GIA iLit = Kit_TruthToGia( pNew, (unsigned *)pTruth, Vec_IntSize(vLeaves), vCover, vLeaves, 0 ); if ( p->pPars->fGenCnf ) Jf_ManGenCnf( uTruth, iLit, vLeaves, vLits, vClas, vCover ); iLit = Abc_LitNotCond( iLit, Jf_CutFuncCompl(pCut) ); Vec_IntWriteEntry( vCopies, i, iLit ); // create mapping Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLit), Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); Vec_IntForEachEntry( vLeaves, iLit, k ) Vec_IntPush( vMapping2, Abc_Lit2Var(iLit) ); Vec_IntPush( vMapping2, Abc_Lit2Var(Vec_IntEntry(vCopies, i)) ); } Gia_ManForEachCo( p->pGia, pObj, i ) { if ( p->pPars->fGenCnf ) Vec_IntClear( vLeaves ); iLit = Vec_IntEntry( vCopies, Gia_ObjFaninId0p(p->pGia, pObj) ); if ( p->pPars->fGenCnf ) Vec_IntPush( vLeaves, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); iLit = Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); if ( p->pPars->fGenCnf ) Jf_ManGenCnf( ABC_CONST(0xAAAAAAAAAAAAAAAA), iLit, vLeaves, vLits, vClas, vCover ); } Vec_IntFree( vCopies ); Vec_IntFree( vCover ); Vec_IntFree( vLeaves ); // finish mapping if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) ) Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) ); else Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 ); assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) ); Vec_IntForEachEntry( vMapping, iLit, i ) if ( iLit > 0 ) Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) ); Vec_IntAppend( vMapping, vMapping2 ); Vec_IntFree( vMapping2 ); // attach mapping and packing assert( pNew->vMapping == NULL ); pNew->vMapping = vMapping; Gia_ManSetRegNum( pNew, Gia_ManRegNum(p->pGia) ); // derive CNF if ( p->pPars->fGenCnf ) { if ( p->pPars->fCnfObjIds ) pNew->pData = Jf_ManCreateCnf( pNew, vLits, vClas ); else pNew->pData = Jf_ManCreateCnfRemap( pNew, vLits, vClas, p->pPars->fAddOrCla ); } Vec_IntFreeP( &vLits ); Vec_IntFreeP( &vClas ); return pNew; } void Jf_ManDeriveMapping( Jf_Man_t * p ) { Vec_Int_t * vMapping; Gia_Obj_t * pObj; int i, k, * pCut; assert( !p->pPars->fCutMin ); vMapping = Vec_IntAlloc( Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); Vec_IntFill( vMapping, Gia_ManObjNum(p->pGia), 0 ); Gia_ManForEachAnd( p->pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) || Gia_ObjRefNum(p->pGia, pObj) == 0 ) continue; pCut = Jf_ObjCutBest( p, i ); Vec_IntWriteEntry( vMapping, i, Vec_IntSize(vMapping) ); assert( !p->pPars->fCutMin || Jf_CutSize(pCut) <= 6 ); Vec_IntPush( vMapping, Jf_CutSize(pCut) ); for ( k = 1; k <= Jf_CutSize(pCut); k++ ) Vec_IntPush( vMapping, Jf_CutVar(pCut, k) ); Vec_IntPush( vMapping, i ); } assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); p->pGia->vMapping = vMapping; // Gia_ManMappingVerify( p->pGia ); } /**Function************************************************************* Synopsis [Derive GIA without mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Jf_ManDeriveGia( Jf_Man_t * p ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; Vec_Int_t * vCopies = Vec_IntStartFull( Gia_ManObjNum(p->pGia) ); Vec_Int_t * vCover = Vec_IntAlloc( 1 << 16 ); Vec_Int_t * vLeaves = Vec_IntAlloc( 16 ); int i, k, iLit, Class, * pCut; int nWords = Abc_Truth6WordNum(p->pPars->nLutSize); word uTruth = 0, * pTruth = &uTruth, Truth[JF_WORD_MAX]; // create new manager pNew = Gia_ManStart( Gia_ManObjNum(p->pGia) ); pNew->pName = Abc_UtilStrsav( p->pGia->pName ); pNew->pSpec = Abc_UtilStrsav( p->pGia->pSpec ); pNew->vLevels = Vec_IntStart( 6*Gia_ManObjNum(p->pGia)/5 + 100 ); // map primary inputs Vec_IntWriteEntry( vCopies, 0, 0 ); Gia_ManForEachCi( p->pGia, pObj, i ) Vec_IntWriteEntry( vCopies, Gia_ObjId(p->pGia, pObj), Gia_ManAppendCi(pNew) ); // iterate through nodes used in the mapping if ( !p->pPars->fCutMin ) Gia_ObjComputeTruthTableStart( p->pGia, p->pPars->nLutSize ); Gia_ManHashStart( pNew ); Gia_ManForEachAnd( p->pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) || Gia_ObjRefNum(p->pGia, pObj) == 0 ) continue; pCut = Jf_ObjCutBest( p, i ); // printf( "Best cut of node %d: ", i ); Jf_CutPrint(pCut); // get the truth table if ( p->pPars->fCutMin ) { Class = Jf_CutFuncClass( pCut ); if ( Jf_CutSize(pCut) == 0 ) { assert( Class == 0 ); Vec_IntWriteEntry( vCopies, i, Jf_CutFunc(pCut) ); continue; } if ( Jf_CutSize(pCut) == 1 ) { assert( Class == 1 ); iLit = Abc_LitNotCond( Jf_CutLit(pCut, 1) , Jf_CutFuncCompl(pCut) ); iLit = Abc_Lit2LitL( Vec_IntArray(vCopies), iLit ); Vec_IntWriteEntry( vCopies, i, iLit ); continue; } if ( p->pPars->fFuncDsd ) uTruth = Sdm_ManReadDsdTruth(p->pDsd, Class); else Abc_TtCopy( (pTruth = Truth), Vec_MemReadEntry(p->vTtMem, Class), nWords, 0 ); assert( p->pDsd == NULL || Sdm_ManReadDsdVarNum(p->pDsd, Class) == Jf_CutSize(pCut) ); } else { Vec_IntClear( vLeaves ); Jf_CutForEachLit( pCut, iLit, k ) Vec_IntPush( vLeaves, Abc_Lit2Var(iLit) ); pTruth = Gia_ObjComputeTruthTableCut( p->pGia, pObj, vLeaves ); } // collect incoming literals Vec_IntClear( vLeaves ); Jf_CutForEachLit( pCut, iLit, k ) Vec_IntPush( vLeaves, Abc_Lit2LitL(Vec_IntArray(vCopies), iLit) ); // create GIA iLit = Dsm_ManTruthToGia( pNew, pTruth, vLeaves, vCover ); iLit = Abc_LitNotCond( iLit, (p->pPars->fCutMin && Jf_CutFuncCompl(pCut)) ); Vec_IntWriteEntry( vCopies, i, iLit ); } Gia_ManForEachCo( p->pGia, pObj, i ) { iLit = Vec_IntEntry( vCopies, Gia_ObjFaninId0p(p->pGia, pObj) ); Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); } if ( !p->pPars->fCutMin ) Gia_ObjComputeTruthTableStop( p->pGia ); Vec_IntFree( vCopies ); Vec_IntFree( vLeaves ); Vec_IntFree( vCover ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p->pGia) ); // Dsm_ManReportStats(); // perform cleanup if ( !p->pPars->fCutMin ) { pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); } return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Jf_ManSetDefaultPars( Jf_Par_t * pPars ) { memset( pPars, 0, sizeof(Jf_Par_t) ); pPars->nLutSize = 6; pPars->nCutNum = 8; pPars->nRounds = 1; pPars->nVerbLimit = 5; pPars->DelayTarget = -1; pPars->fAreaOnly = 1; pPars->fOptEdge = 1; pPars->fCoarsen = 0; pPars->fCutMin = 0; pPars->fFuncDsd = 0; pPars->fGenCnf = 0; pPars->fPureAig = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; pPars->nLutSizeMax = JF_LEAF_MAX; pPars->nCutNumMax = JF_CUT_MAX; } void Jf_ManPrintStats( Jf_Man_t * p, char * pTitle ) { if ( !p->pPars->fVerbose ) return; printf( "%s : ", pTitle ); printf( "Level =%6lu ", (long)p->pPars->Delay ); printf( "Area =%9lu ", (long)p->pPars->Area ); printf( "Edge =%9lu ", (long)p->pPars->Edge ); if ( p->pPars->fGenCnf ) printf( "Cnf =%9lu ", (long)p->pPars->Clause ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); fflush( stdout ); } Gia_Man_t * Jf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) { Gia_Man_t * pNew = pGia; Jf_Man_t * p; int i; assert( !Gia_ManBufNum(pGia) ); assert( !pPars->fCutMin || !pPars->fFuncDsd || pPars->nLutSize <= 6 ); if ( pPars->fGenCnf ) pPars->fCutMin = 1, pPars->fFuncDsd = 1, pPars->fOptEdge = 0; if ( pPars->fCutMin && !pPars->fFuncDsd ) pPars->fCoarsen = 0; p = Jf_ManAlloc( pGia, pPars ); p->pCutCmp = pPars->fAreaOnly ? Jf_CutCompareArea : Jf_CutCompareDelay; Jf_ManComputeCuts( p, 0 ); Jf_ManComputeRefs( p ); Jf_ManPrintStats( p, "Start" ); for ( i = 0; i < pPars->nRounds; i++ ) { if ( !p->pPars->fGenCnf ) { Jf_ManPropagateFlow( p, pPars->fOptEdge ); Jf_ManPrintStats( p, "Flow " ); } Jf_ManPropagateEla( p, 0 ); Jf_ManPrintStats( p, "Area " ); Jf_ManPropagateEla( p, 1 ); Jf_ManPrintStats( p, "Edge " ); } if ( p->pPars->fVeryVerbose && p->pPars->fCutMin && !p->pPars->fFuncDsd ) Vec_MemDumpTruthTables( p->vTtMem, Gia_ManName(p->pGia), p->pPars->nLutSize ); if ( p->pPars->fPureAig ) pNew = Jf_ManDeriveGia(p); else if ( p->pPars->fCutMin ) pNew = Jf_ManDeriveMappingGia(p); else Jf_ManDeriveMapping(p); Jf_ManFree( p ); return pNew; } Gia_Man_t * Jf_ManDeriveCnf( Gia_Man_t * p, int fCnfObjIds ) { Jf_Par_t Pars, * pPars = &Pars; Jf_ManSetDefaultPars( pPars ); pPars->fGenCnf = 1; pPars->fCnfObjIds = fCnfObjIds; return Jf_ManPerformMapping( p, pPars ); } Gia_Man_t * Jf_ManDeriveCnfMiter( Gia_Man_t * p, int fVerbose ) { Jf_Par_t Pars, * pPars = &Pars; Jf_ManSetDefaultPars( pPars ); pPars->fGenCnf = 1; pPars->fCnfObjIds = 0; pPars->fAddOrCla = 1; pPars->fVerbose = fVerbose; return Jf_ManPerformMapping( p, pPars ); } void Jf_ManDumpCnf( Gia_Man_t * p, char * pFileName, int fVerbose ) { abctime clk = Abc_Clock(); Gia_Man_t * pNew; Cnf_Dat_t * pCnf; pNew = Jf_ManDeriveCnfMiter( p, fVerbose ); pCnf = (Cnf_Dat_t *)pNew->pData; pNew->pData = NULL; Cnf_DataWriteIntoFile( pCnf, pFileName, 0, NULL, NULL ); Gia_ManStop( pNew ); // if ( fVerbose ) { printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } Cnf_DataFree(pCnf); } void Jf_ManTestCnf( Gia_Man_t * p ) { Gia_Man_t * pNew; Cnf_Dat_t * pCnf; int i; // Cnf_Dat_t * pCnf = Cnf_DeriveGia( p ); pNew = Jf_ManDeriveCnf( p, 1 ); pCnf = (Cnf_Dat_t *)pNew->pData; pNew->pData = NULL; Cnf_DataWriteIntoFile( pCnf, "test.cnf", 0, NULL, NULL ); for ( i = 0; i < pCnf->nVars; i++ ) printf( "%d : %d %d\n", i, pCnf->pObj2Count[i], pCnf->pObj2Clause[i] ); Gia_ManStop( pNew ); Cnf_DataFree(pCnf); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaKf.c000066400000000000000000001321671477524141600154660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaKf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Cut computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaKf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #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 #endif #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifndef ABC_USE_PTHREADS void Kf_ManSetDefaultPars( Jf_Par_t * pPars ) {} Gia_Man_t * Kf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) { return NULL; } #else // pthreads are used #define KF_LEAF_MAX 16 #define KF_CUT_MAX 32 #define KF_PROC_MAX 32 #define KF_WORD_MAX ((KF_LEAF_MAX > 6) ? 1 << (KF_LEAF_MAX-6) : 1) #define KF_LOG_TABLE 8 #define KF_ADD_ON1 2 // offset in cut storage for each node (cut count; best cut) #define KF_ADD_ON2 4 // offset in cut storage for each cut (leaf count; function, cut delay; cut area) typedef struct Kf_Cut_t_ Kf_Cut_t; typedef struct Kf_Set_t_ Kf_Set_t; typedef struct Kf_Man_t_ Kf_Man_t; struct Kf_Cut_t_ { word Sign; // signature int Polar; // polarity int Delay; // delay float Area; // area int iFunc; // function int iNext; // next cut int nLeaves; // number of leaves int pLeaves[KF_LEAF_MAX]; }; struct Kf_Set_t_ { Kf_Man_t * pMan; // manager unsigned short nLutSize; // lut size unsigned short nCutNum; // cut count int nCuts0; // fanin0 cut count int nCuts1; // fanin1 cut count int nCuts; // resulting cut count int nTEntries; // hash table entries int TableMask; // hash table mask int pTable[1 << KF_LOG_TABLE]; int pValue[1 << KF_LOG_TABLE]; int pPlace[KF_LEAF_MAX]; int pList [KF_LEAF_MAX+1]; Kf_Cut_t pCuts0[KF_CUT_MAX]; Kf_Cut_t pCuts1[KF_CUT_MAX]; Kf_Cut_t pCutsR[KF_CUT_MAX*KF_CUT_MAX]; Kf_Cut_t * ppCuts[KF_CUT_MAX]; Kf_Cut_t * pCutBest; word CutCount[4]; // statistics }; struct Kf_Man_t_ { Gia_Man_t * pGia; // user's manager Jf_Par_t * pPars; // user's parameters Vec_Set_t pMem; // cut storage Vec_Int_t vCuts; // node params Vec_Int_t vTime; // node params Vec_Flt_t vArea; // node params Vec_Flt_t vRefs; // node params Vec_Int_t * vTemp; // temporary abctime clkStart; // starting time Kf_Set_t pSett[KF_PROC_MAX]; }; static inline int Kf_SetCutId( Kf_Set_t * p, Kf_Cut_t * pCut ) { return pCut - p->pCutsR; } static inline Kf_Cut_t * Kf_SetCut( Kf_Set_t * p, int i ) { return i >= 0 ? p->pCutsR + i : NULL; } static inline int Kf_ObjTime( Kf_Man_t * p, int i ) { return Vec_IntEntry(&p->vTime, i); } static inline float Kf_ObjArea( Kf_Man_t * p, int i ) { return Vec_FltEntry(&p->vArea, i); } static inline float Kf_ObjRefs( Kf_Man_t * p, int i ) { return Vec_FltEntry(&p->vRefs, i); } static inline void Kf_ObjSetCuts( Kf_Man_t * p, int i, Vec_Int_t * vVec ) { Vec_IntWriteEntry(&p->vCuts, i, Vec_SetAppend(&p->pMem, Vec_IntArray(vVec), Vec_IntSize(vVec))); } static inline int * Kf_ObjCuts( Kf_Man_t * p, int i ) { return (int *)Vec_SetEntry(&p->pMem, Vec_IntEntry(&p->vCuts, i)); } static inline int * Kf_ObjCuts0( Kf_Man_t * p, int i ) { return Kf_ObjCuts(p, Gia_ObjFaninId0(Gia_ManObj(p->pGia, i), i)); } static inline int * Kf_ObjCuts1( Kf_Man_t * p, int i ) { return Kf_ObjCuts(p, Gia_ObjFaninId1(Gia_ManObj(p->pGia, i), i)); } static inline int * Kf_ObjCutBest( Kf_Man_t * p, int i ) { int * pCuts = Kf_ObjCuts(p, i); return pCuts + pCuts[1]; } #define Kf_ObjForEachCutInt( pList, pCut, i ) for ( i = 0, pCut = pList + KF_ADD_ON1; i < pList[0]; i++, pCut += pCut[0] + KF_ADD_ON2 ) #define Kf_ListForEachCut( p, iList, pCut ) for ( pCut = Kf_SetCut(p, p->pList[iList]); pCut; pCut = Kf_SetCut(p, pCut->iNext) ) #define Kf_ListForEachCutP( p, iList, pCut, pPlace ) for ( pPlace = p->pList+iList, pCut = Kf_SetCut(p, *pPlace); pCut; pCut = Kf_SetCut(p, *pPlace) ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Kf_SetLoadCuts( Kf_Cut_t * pCuts, int * pIntCuts ) { Kf_Cut_t * pCut; int k, * pIntCut, nCuts = 0; Kf_ObjForEachCutInt( pIntCuts, pIntCut, nCuts ) { pCut = pCuts + nCuts; pCut->Sign = 0; pCut->Polar = 0; pCut->iFunc = pIntCut[pIntCut[0] + 1]; pCut->Delay = pIntCut[pIntCut[0] + 2]; pCut->Area = Abc_Int2Float(pIntCut[pIntCut[0] + 3]); pCut->nLeaves = pIntCut[0]; for ( k = 0; k < pIntCut[0]; k++ ) { pCut->pLeaves[k] = Abc_Lit2Var(pIntCut[k+1]); pCut->Sign |= ((word)1) << (pCut->pLeaves[k] & 0x3F); if ( Abc_LitIsCompl(pIntCut[k+1]) ) pCut->Polar |= (1 << k); } } return nCuts; } static inline void Kf_SetPrepare( Kf_Set_t * p, int * pCuts0, int * pCuts1 ) { int i; // prepare hash table // for ( i = 0; i <= p->TableMask; i++ ) // assert( p->pTable[i] == 0 ); // prepare cut storage for ( i = 0; i <= p->nLutSize; i++ ) p->pList[i] = -1; // transfer cuts p->nCuts0 = Kf_SetLoadCuts( p->pCuts0, pCuts0 ); p->nCuts1 = Kf_SetLoadCuts( p->pCuts1, pCuts1 ); p->nCuts = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Kf_ManStoreStart( Vec_Int_t * vTemp, int nCuts ) { Vec_IntClear( vTemp ); Vec_IntPush( vTemp, nCuts ); // cut count Vec_IntPush( vTemp, -1 ); // best offset } static inline void Kf_ManStoreAddUnit( Vec_Int_t * vTemp, int iObj, int Time, float Area ) { Vec_IntAddToEntry( vTemp, 0, 1 ); Vec_IntPush( vTemp, 1 ); // cut size Vec_IntPush( vTemp, Abc_Var2Lit(iObj, 0) ); // leaf Vec_IntPush( vTemp, 2 ); // function Vec_IntPush( vTemp, Time ); // delay Vec_IntPush( vTemp, Abc_Float2Int(Area) ); // area } static inline void Kf_ManSaveResults( Kf_Cut_t ** ppCuts, int nCuts, Kf_Cut_t * pCutBest, Vec_Int_t * vTemp ) { int i, k; assert( nCuts > 0 && nCuts < KF_CUT_MAX ); Kf_ManStoreStart( vTemp, nCuts ); for ( i = 0; i < nCuts; i++ ) { if ( ppCuts[i] == pCutBest ) Vec_IntWriteEntry( vTemp, 1, Vec_IntSize(vTemp) ); Vec_IntPush( vTemp, ppCuts[i]->nLeaves ); // Vec_IntPushArray( vTemp, ppCuts[i]->pLeaves, ppCuts[i]->nLeaves ); for ( k = 0; k < ppCuts[i]->nLeaves; k++ ) Vec_IntPush( vTemp, Abc_Var2Lit(ppCuts[i]->pLeaves[k], 0) ); Vec_IntPush( vTemp, ppCuts[i]->iFunc ); Vec_IntPush( vTemp, ppCuts[i]->Delay ); Vec_IntPush( vTemp, Abc_Float2Int(ppCuts[i]->Area) ); } assert( Vec_IntEntry(vTemp, 1) > 0 ); } static inline int Kf_SetCompareCuts( Kf_Cut_t * p1, Kf_Cut_t * p2 ) { if ( p1 == NULL || p2 == NULL ) return (p1 != NULL) - (p2 != NULL); if ( p1->nLeaves != p2->nLeaves ) return p1->nLeaves - p2->nLeaves; return memcmp( p1->pLeaves, p2->pLeaves, sizeof(int)*p1->nLeaves ); } static inline void Kf_SetAddToList( Kf_Set_t * p, Kf_Cut_t * pCut, int fSort ) { if ( !fSort ) pCut->iNext = p->pList[pCut->nLeaves], p->pList[pCut->nLeaves] = Kf_SetCutId(p, pCut); else { int Value, * pPlace; Kf_Cut_t * pTemp; Vec_IntSelectSort( pCut->pLeaves, pCut->nLeaves ); Kf_ListForEachCutP( p, pCut->nLeaves, pTemp, pPlace ) { if ( (Value = Kf_SetCompareCuts(pTemp, pCut)) > 0 ) break; assert( Value < 0 ); pPlace = &pTemp->iNext; } pCut->iNext = *pPlace, *pPlace = Kf_SetCutId(p, pCut); } } static inline int Kf_CutCompare( Kf_Cut_t * pCut0, Kf_Cut_t * pCut1, int fArea ) { if ( fArea ) { if ( pCut0->Area < pCut1->Area ) return -1; if ( pCut0->Area > pCut1->Area ) return 1; if ( pCut0->Delay < pCut1->Delay ) return -1; if ( pCut0->Delay > pCut1->Delay ) return 1; if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; } else { if ( pCut0->Delay < pCut1->Delay ) return -1; if ( pCut0->Delay > pCut1->Delay ) return 1; if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; if ( pCut0->Area < pCut1->Area ) return -1; if ( pCut0->Area > pCut1->Area ) return 1; } return 0; } static inline int Kf_SetStoreAddOne( Kf_Set_t * p, int nCuts, int nCutNum, Kf_Cut_t * pCut, int fArea ) { int i; p->ppCuts[nCuts] = pCut; if ( nCuts == 0 ) return 1; for ( i = nCuts; i > 0; i-- ) if ( Kf_CutCompare(p->ppCuts[i-1], p->ppCuts[i], fArea) > 0 ) ABC_SWAP( Kf_Cut_t *, p->ppCuts[i-1], p->ppCuts[i] ) else break; return Abc_MinInt( nCuts+1, nCutNum ); } static inline void Kf_SetSelectBest( Kf_Set_t * p, int fArea, int fSort ) { // int fArea = p->pMan->pPars->fArea; Kf_Cut_t * pCut; int i, nCuts = 0; for ( i = 0; i <= p->nLutSize; i++ ) Kf_ListForEachCut( p, i, pCut ) nCuts = Kf_SetStoreAddOne( p, nCuts, p->nCutNum-1, pCut, fArea ); assert( nCuts > 0 && nCuts < p->nCutNum ); p->nCuts = nCuts; p->pCutBest = p->ppCuts[0]; if ( !fSort ) return; // sort by size in the reverse order for ( i = 0; i <= p->nLutSize; i++ ) p->pList[i] = -1; for ( i = 0; i < nCuts; i++ ) Kf_SetAddToList( p, p->ppCuts[i], 0 ); p->nCuts = 0; for ( i = p->nLutSize; i >= 0; i-- ) Kf_ListForEachCut( p, i, pCut ) p->ppCuts[p->nCuts++] = pCut; assert( p->nCuts == nCuts ); } /**Function************************************************************* Synopsis [Check correctness of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Kf_CheckCut( Kf_Cut_t * pBase, Kf_Cut_t * pCut ) // check if pCut is contained in pBase { int nSizeB = pBase->nLeaves; int nSizeC = pCut->nLeaves; int * pB = pBase->pLeaves; int * pC = pCut->pLeaves; int i, k; for ( i = 0; i < nSizeC; i++ ) { for ( k = 0; k < nSizeB; k++ ) if ( pC[i] == pB[k] ) break; if ( k == nSizeB ) return 0; } return 1; } static inline int Kf_CheckCuts( Kf_Set_t * p ) { Kf_Cut_t * pCut0, * pCut1; int i, k, m, n, Value; assert( p->nCuts > 0 ); for ( i = 0; i <= p->nLutSize; i++ ) Kf_ListForEachCut( p, i, pCut0 ) { // check duplicates for ( m = 0; m < pCut0->nLeaves; m++ ) for ( n = m+1; n < pCut0->nLeaves; n++ ) assert( pCut0->pLeaves[m] != pCut0->pLeaves[n] ); // check pairs for ( k = 0; k <= p->nLutSize; k++ ) Kf_ListForEachCut( p, k, pCut1 ) { if ( pCut0 == pCut1 ) continue; // check containments Value = Kf_CheckCut( pCut0, pCut1 ); assert( Value == 0 ); } } return 1; } /**Function************************************************************* Synopsis [Hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Kf_HashLookup( Kf_Set_t * p, int i ) { int k; assert( i > 0 ); for ( k = i & p->TableMask; p->pTable[k]; k = (k + 1) & p->TableMask ) if ( p->pTable[k] == i ) return -1; return k; } static inline int Kf_HashFindOrAdd( Kf_Set_t * p, int i ) { int k = Kf_HashLookup( p, i ); if ( k == -1 ) return 0; if ( p->nTEntries == p->nLutSize ) return 1; assert( p->pTable[k] == 0 ); p->pTable[k] = i; p->pPlace[p->nTEntries] = k; p->pValue[k] = p->nTEntries++; return 0; } static inline void Kf_HashPopulate( Kf_Set_t * p, Kf_Cut_t * pCut ) { int i; assert( p->nTEntries == 0 ); for ( i = 0; i < pCut->nLeaves; i++ ) Kf_HashFindOrAdd( p, pCut->pLeaves[i] ); assert( p->nTEntries == pCut->nLeaves ); } static inline void Kf_HashCleanup( Kf_Set_t * p, int iStart ) { int i; for ( i = iStart; i < p->nTEntries; i++ ) p->pTable[p->pPlace[i]] = 0; p->nTEntries = iStart; } /**Function************************************************************* Synopsis [Cut merging with arbitary order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Kf_SetCountBits( word i ) { i = i - ((i >> 1) & 0x5555555555555555); i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); return (i*(0x0101010101010101))>>56; } static inline word Kf_SetCutGetSign( Kf_Cut_t * p ) { word Sign = 0; int i; for ( i = 0; i < p->nLeaves; i++ ) Sign |= ((word)1) << (p->pLeaves[i] & 0x3F); return Sign; } // returns 1 if the cut in hash table is dominated by the given one static inline int Kf_SetCutDominatedByThis( Kf_Set_t * p, Kf_Cut_t * pCut ) { int i; for ( i = 0; i < pCut->nLeaves; i++ ) if ( Kf_HashLookup(p, pCut->pLeaves[i]) >= 0 ) return 0; return 1; } static inline int Kf_SetRemoveDuplicates( Kf_Set_t * p, int nLeaves, word Sign ) { Kf_Cut_t * pCut; Kf_ListForEachCut( p, nLeaves, pCut ) if ( pCut->Sign == Sign && Kf_SetCutDominatedByThis(p, pCut) ) return 1; return 0; } static inline void Kf_SetFilter( Kf_Set_t * p ) { Kf_Cut_t * pCut0, * pCut1; int i, k, * pPlace; assert( p->nCuts > 0 ); for ( i = 0; i <= p->nLutSize; i++ ) Kf_ListForEachCutP( p, i, pCut0, pPlace ) { Kf_HashPopulate( p, pCut0 ); for ( k = 0; k < pCut0->nLeaves; k++ ) Kf_ListForEachCut( p, k, pCut1 ) if ( (pCut0->Sign & pCut1->Sign) == pCut1->Sign && Kf_SetCutDominatedByThis(p, pCut1) ) { k = pCut0->nLeaves; p->nCuts--; break; } if ( k == pCut0->nLeaves + 1 ) // remove pCut0 *pPlace = pCut0->iNext; else pPlace = &pCut0->iNext; Kf_HashCleanup( p, 0 ); } assert( p->nCuts > 0 ); } static inline void Kf_SetMergePairs( Kf_Set_t * p, Kf_Cut_t * pCut0, Kf_Cut_t * pCuts, int nCuts, int fArea ) { Kf_Cut_t * pCut1, * pCutR; int i; Kf_HashPopulate( p, pCut0 ); for ( pCut1 = pCuts; pCut1 < pCuts + nCuts; pCut1++ ) { if ( pCut0->nLeaves + pCut1->nLeaves > p->nLutSize && Kf_SetCountBits(pCut0->Sign | pCut1->Sign) > p->nLutSize ) continue; Kf_HashCleanup( p, pCut0->nLeaves ); for ( i = 0; i < pCut1->nLeaves; i++ ) if ( Kf_HashFindOrAdd(p, pCut1->pLeaves[i]) ) break; if ( i < pCut1->nLeaves ) continue; p->CutCount[1]++; if ( Kf_SetRemoveDuplicates(p, p->nTEntries, pCut0->Sign | pCut1->Sign) ) continue; // create new cut pCutR = p->pCutsR + p->nCuts++; pCutR->nLeaves = p->nTEntries; for ( i = 0; i < p->nTEntries; i++ ) pCutR->pLeaves[i] = p->pTable[p->pPlace[i]]; pCutR->Sign = pCut0->Sign | pCut1->Sign; pCutR->Delay = Abc_MaxInt(pCut0->Delay, pCut1->Delay); pCutR->Area = pCut0->Area + pCut1->Area; // add new cut Kf_SetAddToList( p, pCutR, 0 ); } Kf_HashCleanup( p, 0 ); } static inline void Kf_SetMerge( Kf_Set_t * p, int * pCuts0, int * pCuts1, int fArea, int fCutMin ) { int c0, c1; Kf_SetPrepare( p, pCuts0, pCuts1 ); p->CutCount[0] += p->nCuts0 * p->nCuts1; // for ( c0 = 1; c0 < p->nCuts0; c0++ ) // assert( p->pCuts0[c0-1].nLeaves >= p->pCuts0[c0].nLeaves ); for ( c0 = c1 = 0; c0 < p->nCuts0 && c1 < p->nCuts1; ) { if ( p->pCuts0[c0].nLeaves >= p->pCuts1[c1].nLeaves ) Kf_SetMergePairs( p, p->pCuts0 + c0++, p->pCuts1 + c1, p->nCuts1 - c1, fArea ); else Kf_SetMergePairs( p, p->pCuts1 + c1++, p->pCuts0 + c0, p->nCuts0 - c0, fArea ); } p->CutCount[2] += p->nCuts; Kf_SetFilter( p ); // Kf_CheckCuts( p ); p->CutCount[3] += Abc_MinInt( p->nCuts, p->nCutNum-1 ); Kf_SetSelectBest( p, fArea, 1 ); } /**Function************************************************************* Synopsis [Cut merging with fixed order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Kf_SetCutIsContainedSimple( Kf_Cut_t * pBase, Kf_Cut_t * pCut ) // check if pCut is contained in pBase { int nSizeB = pBase->nLeaves; int nSizeC = pCut->nLeaves; int * pB = pBase->pLeaves; int * pC = pCut->pLeaves; int i, k; assert( nSizeB >= nSizeC ); for ( i = 0; i < nSizeC; i++ ) { for ( k = 0; k < nSizeB; k++ ) if ( pC[i] == pB[k] ) break; if ( k == nSizeB ) return 0; } return 1; } static inline int Kf_SetMergeSimpleOne( Kf_Cut_t * pCut0, Kf_Cut_t * pCut1, Kf_Cut_t * pCut, int nLutSize ) { int nSize0 = pCut0->nLeaves; int nSize1 = pCut1->nLeaves; int * pC0 = pCut0->pLeaves; int * pC1 = pCut1->pLeaves; int * pC = pCut->pLeaves; int i, k, c; // compare two cuts with different numbers c = nSize0; for ( i = 0; i < nSize1; i++ ) { for ( k = 0; k < nSize0; k++ ) if ( pC1[i] == pC0[k] ) break; if ( k < nSize0 ) continue; if ( c == nLutSize ) return 0; pC[c++] = pC1[i]; } for ( i = 0; i < nSize0; i++ ) pC[i] = pC0[i]; pCut->nLeaves = c; return 1; } static inline int Kf_SetRemoveDuplicatesSimple( Kf_Set_t * p, Kf_Cut_t * pCutNew ) { Kf_Cut_t * pCut; Kf_ListForEachCut( p, pCutNew->nLeaves, pCut ) if ( pCut->Sign == pCutNew->Sign && Kf_SetCutIsContainedSimple(pCut, pCutNew) ) return 1; return 0; } static inline void Kf_SetFilterSimple( Kf_Set_t * p ) { Kf_Cut_t * pCut0, * pCut1; int i, k, * pPlace; assert( p->nCuts > 0 ); for ( i = 0; i <= p->nLutSize; i++ ) Kf_ListForEachCutP( p, i, pCut0, pPlace ) { for ( k = 0; k < pCut0->nLeaves; k++ ) Kf_ListForEachCut( p, k, pCut1 ) if ( (pCut0->Sign & pCut1->Sign) == pCut1->Sign && Kf_SetCutIsContainedSimple(pCut0, pCut1) ) { k = pCut0->nLeaves; p->nCuts--; break; } if ( k == pCut0->nLeaves + 1 ) // remove pCut0 *pPlace = pCut0->iNext; else pPlace = &pCut0->iNext; } assert( p->nCuts > 0 ); } static inline void Kf_SetMergeSimple( Kf_Set_t * p, int * pCuts0, int * pCuts1, int fArea, int fCutMin ) { Kf_Cut_t * pCut0, * pCut1, * pCutR; Kf_SetPrepare( p, pCuts0, pCuts1 ); p->CutCount[0] += p->nCuts0 * p->nCuts1; for ( pCut0 = p->pCuts0; pCut0 < p->pCuts0 + p->nCuts0; pCut0++ ) for ( pCut1 = p->pCuts1; pCut1 < p->pCuts1 + p->nCuts1; pCut1++ ) { if ( pCut0->nLeaves + pCut1->nLeaves > p->nLutSize && Kf_SetCountBits(pCut0->Sign | pCut1->Sign) > p->nLutSize ) continue; p->CutCount[1]++; pCutR = p->pCutsR + p->nCuts; if ( !Kf_SetMergeSimpleOne(pCut0, pCut1, pCutR, p->nLutSize) ) continue; p->CutCount[2]++; pCutR->Sign = pCut0->Sign | pCut1->Sign; if ( Kf_SetRemoveDuplicatesSimple(p, pCutR) ) continue; p->nCuts++; if ( fCutMin ) { int nOldSupp = pCutR->nLeaves; // pCutR->iFunc = Kf_SetComputeTruth( p, pCut0->iFunc, pCut1->iFunc, pCut0, pCut1, pCutR ); assert( pCutR->nLeaves <= nOldSupp ); if ( pCutR->nLeaves < nOldSupp ) pCutR->Sign = Kf_SetCutGetSign( pCutR ); // delay and area are inaccurate } assert( pCutR->nLeaves > 1 ); pCutR->Delay = Abc_MaxInt(pCut0->Delay, pCut1->Delay); pCutR->Area = pCut0->Area + pCut1->Area; // add new cut Kf_SetAddToList( p, pCutR, 0 ); } Kf_SetFilterSimple( p ); // Kf_CheckCuts( p ); p->CutCount[3] += Abc_MinInt( p->nCuts, p->nCutNum-1 ); Kf_SetSelectBest( p, fArea, 1 ); } /**Function************************************************************* Synopsis [Cut merging with fixed order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Kf_SetCutIsContainedOrder( Kf_Cut_t * pBase, Kf_Cut_t * pCut ) // check if pCut is contained in pBase { int nSizeB = pBase->nLeaves; int nSizeC = pCut->nLeaves; int i, k; if ( nSizeB == nSizeC ) { for ( i = 0; i < nSizeB; i++ ) if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) return 0; return 1; } assert( nSizeB > nSizeC ); for ( i = k = 0; i < nSizeB; i++ ) { if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) return 0; if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) { if ( ++k == nSizeC ) return 1; } } return 0; } static inline int Kf_SetMergeOrderOne( Kf_Cut_t * pCut0, Kf_Cut_t * pCut1, Kf_Cut_t * pCut, int nLutSize ) { int nSize0 = pCut0->nLeaves; int nSize1 = pCut1->nLeaves; int * pC0 = pCut0->pLeaves; int * pC1 = pCut1->pLeaves; int * pC = pCut->pLeaves; int i, k, c; // the case of the largest cut sizes if ( nSize0 == nLutSize && nSize1 == nLutSize ) { for ( i = 0; i < nSize0; i++ ) { if ( pC0[i] != pC1[i] ) return 0; pC[i] = pC0[i]; } pCut->nLeaves = nLutSize; return 1; } // compare two cuts with different numbers i = k = c = 0; while ( 1 ) { if ( c == nLutSize ) return 0; if ( pC0[i] < pC1[k] ) { pC[c++] = pC0[i++]; if ( i >= nSize0 ) goto FlushCut1; } else if ( pC0[i] > pC1[k] ) { pC[c++] = pC1[k++]; if ( k >= nSize1 ) goto FlushCut0; } else { pC[c++] = pC0[i++]; k++; if ( i >= nSize0 ) goto FlushCut1; if ( k >= nSize1 ) goto FlushCut0; } } FlushCut0: if ( c + nSize0 > nLutSize + i ) return 0; while ( i < nSize0 ) pC[c++] = pC0[i++]; pCut->nLeaves = c; return 1; FlushCut1: if ( c + nSize1 > nLutSize + k ) return 0; while ( k < nSize1 ) pC[c++] = pC1[k++]; pCut->nLeaves = c; return 1; } static inline int Kf_SetRemoveDuplicatesOrder( Kf_Set_t * p, Kf_Cut_t * pCutNew ) { Kf_Cut_t * pCut; Kf_ListForEachCut( p, pCutNew->nLeaves, pCut ) if ( pCut->Sign == pCutNew->Sign && Kf_SetCutIsContainedOrder(pCut, pCutNew) ) return 1; return 0; } static inline void Kf_SetFilterOrder( Kf_Set_t * p ) { Kf_Cut_t * pCut0, * pCut1; int i, k, * pPlace; assert( p->nCuts > 0 ); for ( i = 0; i <= p->nLutSize; i++ ) Kf_ListForEachCutP( p, i, pCut0, pPlace ) { for ( k = 0; k < pCut0->nLeaves; k++ ) Kf_ListForEachCut( p, k, pCut1 ) if ( (pCut0->Sign & pCut1->Sign) == pCut1->Sign && Kf_SetCutIsContainedOrder(pCut0, pCut1) ) { k = pCut0->nLeaves; p->nCuts--; break; } if ( k == pCut0->nLeaves + 1 ) // remove pCut0 *pPlace = pCut0->iNext; else pPlace = &pCut0->iNext; } assert( p->nCuts > 0 ); } /* int Kf_SetComputeTruth( Kf_Man_t * p, int iFuncLit0, int iFuncLit1, int * pCut0, int * pCut1, int * pCutOut ) { word uTruth[JF_WORD_MAX], uTruth0[JF_WORD_MAX], uTruth1[JF_WORD_MAX]; int fCompl, truthId; int LutSize = p->pPars->nLutSize; int nWords = Abc_Truth6WordNum(p->pPars->nLutSize); word * pTruth0 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(iFuncLit0)); word * pTruth1 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(iFuncLit1)); Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(iFuncLit0) ); Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(iFuncLit1) ); Abc_TtExpand( uTruth0, LutSize, pCut0 + 1, Kf_CutSize(pCut0), pCutOut + 1, Kf_CutSize(pCutOut) ); Abc_TtExpand( uTruth1, LutSize, pCut1 + 1, Kf_CutSize(pCut1), pCutOut + 1, Kf_CutSize(pCutOut) ); fCompl = (int)(uTruth0[0] & uTruth1[0] & 1); Abc_TtAnd( uTruth, uTruth0, uTruth1, nWords, fCompl ); pCutOut[0] = Abc_TtMinBase( uTruth, pCutOut + 1, pCutOut[0], LutSize ); assert( (uTruth[0] & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, uTruth); return Abc_Var2Lit( truthId, fCompl ); } */ static inline void Kf_SetMergeOrder( Kf_Set_t * p, int * pCuts0, int * pCuts1, int fArea, int fCutMin ) { Kf_Cut_t * pCut0, * pCut1, * pCutR; Kf_SetPrepare( p, pCuts0, pCuts1 ); p->CutCount[0] += p->nCuts0 * p->nCuts1; for ( pCut0 = p->pCuts0; pCut0 < p->pCuts0 + p->nCuts0; pCut0++ ) for ( pCut1 = p->pCuts1; pCut1 < p->pCuts1 + p->nCuts1; pCut1++ ) { if ( pCut0->nLeaves + pCut1->nLeaves > p->nLutSize && Kf_SetCountBits(pCut0->Sign | pCut1->Sign) > p->nLutSize ) continue; p->CutCount[1]++; pCutR = p->pCutsR + p->nCuts; if ( !Kf_SetMergeOrderOne(pCut0, pCut1, pCutR, p->nLutSize) ) continue; p->CutCount[2]++; pCutR->Sign = pCut0->Sign | pCut1->Sign; if ( Kf_SetRemoveDuplicatesOrder(p, pCutR) ) continue; p->nCuts++; if ( fCutMin ) { int nOldSupp = pCutR->nLeaves; // pCutR->iFunc = Kf_SetComputeTruth( p, pCut0->iFunc, pCut1->iFunc, pCut0, pCut1, pCutR ); assert( pCutR->nLeaves <= nOldSupp ); if ( pCutR->nLeaves < nOldSupp ) pCutR->Sign = Kf_SetCutGetSign( pCutR ); // delay and area are inaccurate } assert( pCutR->nLeaves > 1 ); pCutR->Delay = Abc_MaxInt(pCut0->Delay, pCut1->Delay); pCutR->Area = pCut0->Area + pCut1->Area; // add new cut Kf_SetAddToList( p, pCutR, 0 ); } Kf_SetFilterOrder( p ); // Kf_CheckCuts( p ); p->CutCount[3] += Abc_MinInt( p->nCuts, p->nCutNum-1 ); Kf_SetSelectBest( p, fArea, 1 ); } /**Function************************************************************* Synopsis [Cut operations.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Kf_CutSize( int * pCut ) { return pCut[0]; } static inline int Kf_CutFunc( int * pCut ) { return pCut[pCut[0] + 1]; } static inline int Kf_CutLeaf( int * pCut, int i ) { assert(i); return Abc_Lit2Var(pCut[i]); } static inline int Kf_CutTime( Kf_Man_t * p, int * pCut ) { int i, Time = 0; for ( i = 1; i <= Kf_CutSize(pCut); i++ ) Time = Abc_MaxInt( Time, Kf_ObjTime(p, Kf_CutLeaf(pCut, i)) ); return Time + 1; } static inline void Kf_CutRef( Kf_Man_t * p, int * pCut ) { int i; for ( i = 1; i <= Kf_CutSize(pCut); i++ ) Gia_ObjRefIncId( p->pGia, Kf_CutLeaf(pCut, i) ); } static inline void Kf_CutDeref( Kf_Man_t * p, int * pCut ) { int i; for ( i = 1; i <= Kf_CutSize(pCut); i++ ) Gia_ObjRefDecId( p->pGia, Kf_CutLeaf(pCut, i) ); } static inline void Kf_CutPrint( int * pCut ) { int i; printf( "%d {", Kf_CutSize(pCut) ); for ( i = 1; i <= Kf_CutSize(pCut); i++ ) printf( " %d", Kf_CutLeaf(pCut, i) ); printf( " } Func = %d\n", Kf_CutFunc(pCut) ); } static inline void Gia_CutSetPrint( int * pCuts ) { int i, * pCut; Kf_ObjForEachCutInt( pCuts, pCut, i ) Kf_CutPrint( pCut ); printf( "\n" ); } /**Function************************************************************* Synopsis [Computing delay/area.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Kf_ManComputeDelay( Kf_Man_t * p, int fEval ) { Gia_Obj_t * pObj; int i, Delay = 0; if ( fEval ) { Gia_ManForEachAnd( p->pGia, pObj, i ) if ( Gia_ObjRefNum(p->pGia, pObj) > 0 ) Vec_IntWriteEntry( &p->vTime, i, Kf_CutTime(p, Kf_ObjCutBest(p, i)) ); } Gia_ManForEachCoDriver( p->pGia, pObj, i ) { assert( Gia_ObjRefNum(p->pGia, pObj) > 0 ); Delay = Abc_MaxInt( Delay, Kf_ObjTime(p, Gia_ObjId(p->pGia, pObj)) ); } return Delay; } int Kf_ManComputeRefs( Kf_Man_t * p ) { Gia_Obj_t * pObj; float nRefsNew; int i, * pCut; float * pRefs = Vec_FltArray(&p->vRefs); float * pFlow = Vec_FltArray(&p->vArea); assert( p->pGia->pRefs != NULL ); memset( p->pGia->pRefs, 0, sizeof(int) * Gia_ManObjNum(p->pGia) ); p->pPars->Area = p->pPars->Edge = 0; Gia_ManForEachObjReverse( p->pGia, pObj, i ) { if ( Gia_ObjIsCo(pObj) || Gia_ObjIsBuf(pObj) ) Gia_ObjRefInc( p->pGia, Gia_ObjFanin0(pObj) ); else if ( Gia_ObjIsAnd(pObj) && Gia_ObjRefNum(p->pGia, pObj) > 0 ) { pCut = Kf_ObjCutBest(p, i); Kf_CutRef( p, pCut ); p->pPars->Edge += Kf_CutSize(pCut); p->pPars->Area++; } } // blend references and normalize flow for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ ) { if ( p->pPars->fOptEdge ) nRefsNew = Abc_MaxFloat( 1, 0.8 * pRefs[i] + 0.2 * p->pGia->pRefs[i] ); else nRefsNew = Abc_MaxFloat( 1, 0.2 * pRefs[i] + 0.8 * p->pGia->pRefs[i] ); pFlow[i] = pFlow[i] * pRefs[i] / nRefsNew; pRefs[i] = nRefsNew; assert( pFlow[i] >= 0 ); } // compute delay p->pPars->Delay = Kf_ManComputeDelay( p, 1 ); return p->pPars->Area; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ #define PAR_THR_MAX 100 typedef struct Kf_ThData_t_ { Kf_Set_t * pSett; int Id; int Status; abctime clkUsed; } Kf_ThData_t; void * Kf_WorkerThread( void * pArg ) { Kf_ThData_t * pThData = (Kf_ThData_t *)pArg; Kf_Man_t * pMan = pThData->pSett->pMan; int fAreaOnly = pThData->pSett->pMan->pPars->fAreaOnly; int fCutMin = pThData->pSett->pMan->pPars->fCutMin; volatile int * pPlace = &pThData->Status; abctime clk; while ( 1 ) { while ( *pPlace == 0 ); assert( pThData->Status == 1 ); if ( pThData->Id == -1 ) { pthread_exit( NULL ); assert( 0 ); return NULL; } assert( pThData->Id >= 0 ); clk = Abc_Clock(); Kf_SetMergeOrder( pThData->pSett, Kf_ObjCuts0(pMan, pThData->Id), Kf_ObjCuts1(pMan, pThData->Id), fAreaOnly, fCutMin ); pThData->clkUsed += Abc_Clock() - clk; pThData->Status = 0; // printf( "Finished object %d\n", pThData->Id ); } assert( 0 ); return NULL; } Vec_Int_t * Kf_ManCreateFaninCounts( Gia_Man_t * p ) { Vec_Int_t * vCounts; Gia_Obj_t * pObj; int i; vCounts = Vec_IntAlloc( Gia_ManObjNum(p) ); Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) Vec_IntPush( vCounts, 2 - Gia_ObjIsCi(Gia_ObjFanin0(pObj)) - Gia_ObjIsCi(Gia_ObjFanin1(pObj)) ); else Vec_IntPush( vCounts, 0 ); } assert( Vec_IntSize(vCounts) == Gia_ManObjNum(p) ); return vCounts; } void Kf_ManComputeCuts( Kf_Man_t * p ) { pthread_t WorkerThread[PAR_THR_MAX]; Kf_ThData_t ThData[PAR_THR_MAX]; Vec_Int_t * vStack, * vFanins; Gia_Obj_t * pObj; int nProcs = p->pPars->nProcNum; int i, k, iFan, status, nCountFanins, fRunning; abctime clk, clkUsed = 0; assert( nProcs <= PAR_THR_MAX ); // start fanins vFanins = Kf_ManCreateFaninCounts( p->pGia ); Gia_ManStaticFanoutStart( p->pGia ); // start the stack vStack = Vec_IntAlloc( 1000 ); Gia_ManForEachObjReverse( p->pGia, pObj, k ) if ( Gia_ObjIsAnd(pObj) && Vec_IntEntry(vFanins, k) == 0 ) Vec_IntPush( vStack, k ); // start the threads for ( i = 0; i < nProcs; i++ ) { ThData[i].pSett = p->pSett + i; ThData[i].Id = -1; ThData[i].Status = 0; ThData[i].clkUsed = 0; status = pthread_create( WorkerThread + i, NULL, Kf_WorkerThread, (void *)(ThData + i) ); assert( status == 0 ); } nCountFanins = Vec_IntSum(vFanins); fRunning = 1; while ( nCountFanins > 0 || Vec_IntSize(vStack) > 0 || fRunning ) { for ( i = 0; i < nProcs; i++ ) { if ( ThData[i].Status ) continue; assert( ThData[i].Status == 0 ); if ( ThData[i].Id >= 0 ) { int iObj = ThData[i].Id; Kf_Set_t * pSett = p->pSett + i; //printf( "Closing obj %d with Thread %d:\n", iObj, i ); clk = Abc_Clock(); // finalize the results Kf_ManSaveResults( pSett->ppCuts, pSett->nCuts, pSett->pCutBest, p->vTemp ); Vec_IntWriteEntry( &p->vTime, iObj, pSett->pCutBest->Delay + 1 ); Vec_FltWriteEntry( &p->vArea, iObj, (pSett->pCutBest->Area + 1)/Kf_ObjRefs(p, iObj) ); if ( pSett->pCutBest->nLeaves > 1 ) Kf_ManStoreAddUnit( p->vTemp, iObj, Kf_ObjTime(p, iObj), Kf_ObjArea(p, iObj) ); Kf_ObjSetCuts( p, iObj, p->vTemp ); //Gia_CutSetPrint( Kf_ObjCuts(p, iObj) ); clkUsed += Abc_Clock() - clk; // schedule other nodes Gia_ObjForEachFanoutStaticId( p->pGia, iObj, iFan, k ) { if ( !Gia_ObjIsAnd(Gia_ManObj(p->pGia, iFan)) ) continue; assert( Vec_IntEntry(vFanins, iFan) > 0 ); if ( Vec_IntAddToEntry(vFanins, iFan, -1) == 0 ) Vec_IntPush( vStack, iFan ); assert( nCountFanins > 0 ); nCountFanins--; } ThData[i].Id = -1; } if ( Vec_IntSize(vStack) > 0 ) { ThData[i].Id = Vec_IntPop( vStack ); ThData[i].Status = 1; //printf( "Scheduling %d for Thread %d\n", ThData[i].Id, i ); } } fRunning = 0; for ( i = 0; i < nProcs; i++ ) if ( ThData[i].Status == 1 || (ThData[i].Status == 0 && ThData[i].Id >= 0) ) fRunning = 1; // printf( "fRunning %d\n", fRunning ); } Vec_IntForEachEntry( vFanins, iFan, k ) if ( iFan != 0 ) { printf( "%d -> %d ", k, iFan ); Gia_ObjPrint( p->pGia, Gia_ManObj(p->pGia, k) ); } assert( Vec_IntSum(vFanins) == 0 ); // stop the threads for ( i = 0; i < nProcs; i++ ) { assert( ThData[i].Status == 0 ); ThData[i].Id = -1; ThData[i].Status = 1; } Gia_ManStaticFanoutStop( p->pGia ); Vec_IntFree( vStack ); Vec_IntFree( vFanins ); if ( !p->pPars->fVerbose ) return; // print runtime statistics printf( "Main : " ); Abc_PrintTime( 1, "Time", clkUsed ); for ( i = 0; i < nProcs; i++ ) { printf( "Thread %d : ", i ); Abc_PrintTime( 1, "Time", ThData[i].clkUsed ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kf_ManPrintStats( Kf_Man_t * p, char * pTitle ) { if ( !p->pPars->fVerbose ) return; printf( "%s : ", pTitle ); printf( "Level =%6lu ", (long)p->pPars->Delay ); printf( "Area =%9lu ", (long)p->pPars->Area ); printf( "Edge =%9lu ", (long)p->pPars->Edge ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); fflush( stdout ); } void Kf_ManComputeMapping( Kf_Man_t * p ) { Gia_Obj_t * pObj; int i, iPi; if ( p->pPars->fVerbose ) { printf( "Aig: CI = %d CO = %d AND = %d ", Gia_ManCiNum(p->pGia), Gia_ManCoNum(p->pGia), Gia_ManAndNum(p->pGia) ); printf( "LutSize = %d CutMax = %d Threads = %d\n", p->pPars->nLutSize, p->pPars->nCutNum, p->pPars->nProcNum ); printf( "Computing cuts...\r" ); fflush( stdout ); } Gia_ManForEachCi( p->pGia, pObj, iPi ) { i = Gia_ObjId(p->pGia, pObj); Kf_ManStoreStart( p->vTemp, 0 ); Kf_ManStoreAddUnit( p->vTemp, i, 0, 0 ); assert( Vec_IntSize(p->vTemp) == 1 + KF_ADD_ON1 + KF_ADD_ON2 ); Kf_ObjSetCuts( p, i, p->vTemp ); } if ( p->pPars->nProcNum > 0 ) Kf_ManComputeCuts( p ); else { Gia_ManForEachAnd( p->pGia, pObj, i ) { if ( p->pPars->fCutHashing ) Kf_SetMerge( p->pSett, Kf_ObjCuts0(p, i), Kf_ObjCuts1(p, i), p->pPars->fAreaOnly, p->pPars->fCutMin ); else if ( p->pPars->fCutSimple ) Kf_SetMergeSimple( p->pSett, Kf_ObjCuts0(p, i), Kf_ObjCuts1(p, i), p->pPars->fAreaOnly, p->pPars->fCutMin ); else Kf_SetMergeOrder( p->pSett, Kf_ObjCuts0(p, i), Kf_ObjCuts1(p, i), p->pPars->fAreaOnly, p->pPars->fCutMin ); Kf_ManSaveResults( p->pSett->ppCuts, p->pSett->nCuts, p->pSett->pCutBest, p->vTemp ); Vec_IntWriteEntry( &p->vTime, i, p->pSett->pCutBest->Delay + 1 ); Vec_FltWriteEntry( &p->vArea, i, (p->pSett->pCutBest->Area + 1)/Kf_ObjRefs(p, i) ); if ( p->pSett->pCutBest->nLeaves > 1 ) Kf_ManStoreAddUnit( p->vTemp, i, Kf_ObjTime(p, i), Kf_ObjArea(p, i) ); Kf_ObjSetCuts( p, i, p->vTemp ); //Gia_CutSetPrint( Kf_ObjCuts(p, i) ); } } Kf_ManComputeRefs( p ); if ( p->pPars->fVerbose ) { printf( "CutPair = %lu ", (long)p->pSett->CutCount[0] ); printf( "Merge = %lu ", (long)p->pSett->CutCount[1] ); printf( "Eval = %lu ", (long)p->pSett->CutCount[2] ); printf( "Cut = %lu ", (long)p->pSett->CutCount[3] ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); printf( "Memory: " ); printf( "Gia = %.2f MB ", Gia_ManMemory(p->pGia) / (1<<20) ); printf( "Man = %.2f MB ", 4.0 * sizeof(int) * Gia_ManObjNum(p->pGia) / (1<<20) ); printf( "Cuts = %.2f MB ",Vec_ReportMemory(&p->pMem) / (1<<20) ); printf( "Set = %.2f KB ", 1.0 * sizeof(Kf_Set_t) / (1<<10) ); printf( "\n" ); fflush( stdout ); Kf_ManPrintStats( p, "Start" ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kf_ManSetInitRefs( Gia_Man_t * p, Vec_Flt_t * vRefs ) { Gia_Obj_t * pObj, * pCtrl, * pData0, * pData1; int i; Vec_FltFill( vRefs, Gia_ManObjNum(p), 0 ); Gia_ManForEachAnd( p, pObj, i ) { Vec_FltAddToEntry( vRefs, Gia_ObjFaninId0(pObj, i), 1 ); Vec_FltAddToEntry( vRefs, Gia_ObjFaninId1(pObj, i), 1 ); if ( !Gia_ObjIsMuxType(pObj) ) continue; // discount XOR/MUX pCtrl = Gia_ObjRecognizeMux( pObj, &pData1, &pData0 ); Vec_FltAddToEntry( vRefs, Gia_ObjId(p, Gia_Regular(pCtrl)), -1 ); if ( Gia_Regular(pData0) == Gia_Regular(pData1) ) Vec_FltAddToEntry( vRefs, Gia_ObjId(p, Gia_Regular(pData0)), -1 ); } Gia_ManForEachCo( p, pObj, i ) Vec_FltAddToEntry( vRefs, Gia_ObjFaninId0(pObj, Gia_ObjId(p, pObj)), 1 ); for ( i = 0; i < Gia_ManObjNum(p); i++ ) Vec_FltUpdateEntry( vRefs, i, 1 ); } Kf_Man_t * Kf_ManAlloc( Gia_Man_t * pGia, Jf_Par_t * pPars ) { Kf_Man_t * p; int i; assert( pPars->nLutSize <= KF_LEAF_MAX ); assert( pPars->nCutNum <= KF_CUT_MAX ); assert( pPars->nProcNum <= KF_PROC_MAX ); Vec_IntFreeP( &pGia->vMapping ); p = ABC_CALLOC( Kf_Man_t, 1 ); p->clkStart = Abc_Clock(); p->pGia = pGia; p->pPars = pPars; Vec_SetAlloc_( &p->pMem, 20 ); Vec_IntFill( &p->vCuts, Gia_ManObjNum(pGia), 0 ); Vec_IntFill( &p->vTime, Gia_ManObjNum(pGia), 0 ); Vec_FltFill( &p->vArea, Gia_ManObjNum(pGia), 0 ); Kf_ManSetInitRefs( pGia, &p->vRefs ); p->vTemp = Vec_IntAlloc( 1000 ); pGia->pRefs = ABC_CALLOC( int, Gia_ManObjNum(pGia) ); // prepare cut sets for ( i = 0; i < Abc_MaxInt(1, pPars->nProcNum); i++ ) { (p->pSett + i)->pMan = p; (p->pSett + i)->nLutSize = (unsigned short)pPars->nLutSize; (p->pSett + i)->nCutNum = (unsigned short)pPars->nCutNum; (p->pSett + i)->TableMask = (1 << KF_LOG_TABLE) - 1; } return p; } void Kf_ManFree( Kf_Man_t * p ) { ABC_FREE( p->pGia->pRefs ); ABC_FREE( p->vCuts.pArray ); ABC_FREE( p->vTime.pArray ); ABC_FREE( p->vArea.pArray ); ABC_FREE( p->vRefs.pArray ); Vec_IntFreeP( &p->vTemp ); Vec_SetFree_( &p->pMem ); ABC_FREE( p ); } Gia_Man_t * Kf_ManDerive( Kf_Man_t * p ) { Vec_Int_t * vMapping; Gia_Obj_t * pObj; int i, k, * pCut; assert( !p->pPars->fCutMin ); vMapping = Vec_IntAlloc( Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); Vec_IntFill( vMapping, Gia_ManObjNum(p->pGia), 0 ); Gia_ManForEachAnd( p->pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) || Gia_ObjRefNum(p->pGia, pObj) == 0 ) continue; pCut = Kf_ObjCutBest( p, i ); Vec_IntWriteEntry( vMapping, i, Vec_IntSize(vMapping) ); Vec_IntPush( vMapping, Kf_CutSize(pCut) ); for ( k = 1; k <= Kf_CutSize(pCut); k++ ) Vec_IntPush( vMapping, Kf_CutLeaf(pCut, k) ); Vec_IntPush( vMapping, i ); } assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); p->pGia->vMapping = vMapping; // Gia_ManMappingVerify( p->pGia ); return p->pGia; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Kf_ManSetDefaultPars( Jf_Par_t * pPars ) { memset( pPars, 0, sizeof(Jf_Par_t) ); pPars->nLutSize = 6; pPars->nCutNum = 8; pPars->nProcNum = 0; pPars->nRounds = 1; pPars->nVerbLimit = 5; pPars->DelayTarget = -1; pPars->fAreaOnly = 0; pPars->fOptEdge = 1; pPars->fCoarsen = 0; pPars->fCutMin = 0; pPars->fFuncDsd = 0; pPars->fGenCnf = 0; pPars->fPureAig = 0; pPars->fCutHashing = 0; pPars->fCutSimple = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; pPars->nLutSizeMax = KF_LEAF_MAX; pPars->nCutNumMax = KF_CUT_MAX; pPars->nProcNumMax = KF_PROC_MAX; } Gia_Man_t * Kf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) { Kf_Man_t * p; Gia_Man_t * pNew; p = Kf_ManAlloc( pGia, pPars ); Kf_ManComputeMapping( p ); pNew = Kf_ManDerive( p ); Kf_ManFree( p ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// #endif // pthreads are used ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaLf.c000066400000000000000000002647351477524141600154760ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaLf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Cut computation.] Author [Alan Mishchenko]` Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaLf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/tim/tim.h" #include "misc/vec/vecSet.h" #include "misc/vec/vecMem.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define LF_LEAF_MAX 13 #define LF_CUT_MAX 32 #define LF_LOG_PAGE 12 #define LF_NO_LEAF 255 #define LF_CUT_WORDS (4+LF_LEAF_MAX/2) #define LF_TT_WORDS ((LF_LEAF_MAX > 6) ? 1 << (LF_LEAF_MAX-6) : 1) #define LF_EPSILON 0.005 typedef struct Lf_Cut_t_ Lf_Cut_t; struct Lf_Cut_t_ { word Sign; // signature int Delay; // delay float Flow; // flow int iFunc; // functionality unsigned Cost : 22; // misc cut cost unsigned fLate : 1; // fails timing unsigned fMux7 : 1; // specialized cut unsigned nLeaves : 8; // the number of leaves int pLeaves[0]; // leaves }; typedef struct Lf_Plc_t_ Lf_Plc_t; struct Lf_Plc_t_ { unsigned fUsed : 1; // the cut is used unsigned Handle : 31; // the cut handle }; typedef struct Lf_Bst_t_ Lf_Bst_t; struct Lf_Bst_t_ { int Delay[3]; // delay float Flow[3]; // flow Lf_Plc_t Cut[2]; // cut info }; typedef struct Lf_Mem_t_ Lf_Mem_t; struct Lf_Mem_t_ { int LogPage; // log size of memory page int MaskPage; // page mask int nCutWords; // cut size in words int iCur; // writing position Vec_Ptr_t vPages; // memory pages Vec_Ptr_t * vFree; // free pages }; typedef struct Lf_Man_t_ Lf_Man_t; struct Lf_Man_t_ { // user data Gia_Man_t * pGia; // manager Jf_Par_t * pPars; // parameters // cut data int nCutWords; // cut size in words int nSetWords; // set size in words Lf_Bst_t * pObjBests; // best cuts Vec_Ptr_t vMemSets; // memory for cutsets Vec_Int_t vFreeSets; // free cutsets Vec_Mem_t * vTtMem; // truth tables Vec_Ptr_t vFreePages; // free memory pages Lf_Mem_t vStoreOld; // previous cuts Lf_Mem_t vStoreNew; // current cuts // mapper data Vec_Int_t vOffsets; // offsets Vec_Int_t vRequired; // required times Vec_Int_t vCutSets; // cutsets (pObj->Value stores cut refs) Vec_Flt_t vFlowRefs; // flow refs Vec_Int_t vMapRefs; // mapping refs Vec_Flt_t vSwitches; // switching activity Vec_Int_t vCiArrivals; // arrival times of the CIs // statistics abctime clkStart; // starting time double CutCount[4]; // cut counts double Switches; // switching activity int nFrontMax; // frontier int nCoDrivers; // CO drivers int nInverters; // inverters int nTimeFails; // timing fails int Iter; // mapping iteration int fUseEla; // use exact local area int nCutMux; // non-trivial MUX cuts int nCutEqual; // equal two cuts int nCutCounts[LF_LEAF_MAX+1]; }; static inline void Lf_CutCopy( Lf_Cut_t * p, Lf_Cut_t * q, int n ) { memcpy(p, q, sizeof(word) * n); } static inline Lf_Cut_t * Lf_CutNext( Lf_Cut_t * p, int n ) { return (Lf_Cut_t *)((word *)p + n); } static inline word * Lf_CutTruth( Lf_Man_t * p, Lf_Cut_t * pCut ) { return Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut->iFunc)); } static inline int Lf_ObjOff( Lf_Man_t * p, int i ) { return Vec_IntEntry(&p->vOffsets, i); } static inline int Lf_ObjRequired( Lf_Man_t * p, int i ) { return Vec_IntEntry(&p->vRequired, i); } static inline void Lf_ObjSetRequired( Lf_Man_t * p, int i, int t ) { Vec_IntDowndateEntry(&p->vRequired, i, t); } static inline Lf_Bst_t * Lf_ObjReadBest( Lf_Man_t * p, int i ) { return p->pObjBests + Lf_ObjOff(p,i); } static inline float Lf_ObjFlowRefs( Lf_Man_t * p, int i ) { return Vec_FltEntry(&p->vFlowRefs, Lf_ObjOff(p,i)); } static inline int Lf_ObjMapRefNum( Lf_Man_t * p, int i ) { return Vec_IntEntry(&p->vMapRefs, Lf_ObjOff(p,i)); } static inline int Lf_ObjMapRefInc( Lf_Man_t * p, int i ) { return (*Vec_IntEntryP(&p->vMapRefs, Lf_ObjOff(p,i)))++; } static inline int Lf_ObjMapRefDec( Lf_Man_t * p, int i ) { return --(*Vec_IntEntryP(&p->vMapRefs, Lf_ObjOff(p,i))); } static inline float Lf_ObjSwitches( Lf_Man_t * p, int i ) { return Vec_FltEntry(&p->vSwitches, i); } static inline int Lf_BestDiffCuts( Lf_Bst_t * p ) { return p->Cut[0].Handle != p->Cut[1].Handle; } static inline int Lf_BestIsMapped( Lf_Bst_t * p ) { return (int)(p->Cut[0].fUsed ^ p->Cut[1].fUsed); } static inline int Lf_BestIndex( Lf_Bst_t * p ) { return p->Cut[1].fUsed; } static inline int Lf_BestCutIndex( Lf_Bst_t * p ) { if (p->Cut[0].fUsed) return 0; if (p->Cut[1].fUsed) return 1; return 2; } #define Lf_CutSetForEachCut( nWords, pCutSet, pCut, i, nCuts ) for ( i = 0, pCut = pCutSet; i < nCuts; pCut = Lf_CutNext(pCut, nWords), i++ ) #define Lf_CutForEachVar( pCut, Var, i ) for ( i = 0; i < (int)pCut->nLeaves && (Var = pCut->pLeaves[i]); i++ ) if ( Lf_ObjOff(p, Var) < 0 ) {} else extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Lf_ObjSetCiArrival( Lf_Man_t * p, int iCi, int Time ) { Vec_IntWriteEntry( &p->vCiArrivals, iCi, Time ); } static inline int Lf_ObjCiArrival( Lf_Man_t * p, int iCi ) { return Vec_IntEntry( &p->vCiArrivals, iCi ); } int Lf_ObjArrival_rec( Lf_Man_t * p, Gia_Obj_t * pDriver ) { if ( Gia_ObjIsBuf(pDriver) ) return Lf_ObjArrival_rec( p, Gia_ObjFanin0(pDriver) ); if ( Gia_ObjIsAnd(pDriver) ) return Lf_ObjReadBest(p, Gia_ObjId(p->pGia, pDriver))->Delay[0]; if ( Gia_ObjIsCi(pDriver) ) return Lf_ObjCiArrival(p, Gia_ObjCioId(pDriver)); return 0; } static inline int Lf_ObjCoArrival( Lf_Man_t * p, int iCo ) { Gia_Obj_t * pObj = Gia_ManCo(p->pGia, iCo); Gia_Obj_t * pDriver = Gia_ObjFanin0(pObj); return Lf_ObjArrival_rec( p, pDriver ); // if ( Gia_ObjIsAnd(pDriver) ) // return Lf_ObjReadBest(p, Gia_ObjId(p->pGia, pDriver))->Delay[0]; // if ( Gia_ObjIsCi(pDriver) ) // return Lf_ObjCiArrival(p, Gia_ObjCioId(pDriver)); // return 0; } int Lf_ObjCoArrival2_rec( Lf_Man_t * p, Gia_Obj_t * pDriver ) { if ( Gia_ObjIsBuf(pDriver) ) return Lf_ObjCoArrival2_rec( p, Gia_ObjFanin0(pDriver) ); if ( Gia_ObjIsAnd(pDriver) ) { Lf_Bst_t * pBest = Lf_ObjReadBest(p, Gia_ObjId(p->pGia, pDriver)); int Index = Lf_BestCutIndex( pBest ); assert( Index < 2 || Gia_ObjIsMux(p->pGia, pDriver) ); return pBest->Delay[Index]; } if ( Gia_ObjIsCi(pDriver) ) return Lf_ObjCiArrival(p, Gia_ObjCioId(pDriver)); return 0; } static inline int Lf_ObjCoArrival2( Lf_Man_t * p, int iCo ) { Gia_Obj_t * pObj = Gia_ManCo(p->pGia, iCo); Gia_Obj_t * pDriver = Gia_ObjFanin0(pObj); return Lf_ObjCoArrival2_rec( p, pDriver ); // if ( Gia_ObjIsAnd(pDriver) ) // { // Lf_Bst_t * pBest = Lf_ObjReadBest(p, Gia_ObjId(p->pGia, pDriver)); // int Index = Lf_BestCutIndex( pBest ); // assert( Index < 2 || Gia_ObjIsMux(p->pGia, pDriver) ); // return pBest->Delay[Index]; // } // if ( Gia_ObjIsCi(pDriver) ) // return Lf_ObjCiArrival(p, Gia_ObjCioId(pDriver)); // return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Lf_ManComputeCrossCut( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, nCutMax = 0, nCutCur = 0; assert( p->pMuxes == NULL ); Gia_ManForEachObj( p, pObj, i ) pObj->Value = 0; Gia_ManForEachAnd( p, pObj, i ) { if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ) Gia_ObjFanin0(pObj)->Value++; if ( Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) ) Gia_ObjFanin1(pObj)->Value++; } Gia_ManForEachAnd( p, pObj, i ) { if ( pObj->Value ) nCutCur++; if ( nCutMax < nCutCur ) nCutMax = nCutCur; if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) && --Gia_ObjFanin0(pObj)->Value == 0 ) nCutCur--; if ( Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) && --Gia_ObjFanin1(pObj)->Value == 0 ) nCutCur--; } assert( nCutCur == 0 ); if ( nCutCur ) printf( "Cutset is not 0\n" ); Gia_ManForEachObj( p, pObj, i ) assert( pObj->Value == 0 ); printf( "CutMax = %d\n", nCutMax ); return nCutMax; } /**Function************************************************************* Synopsis [Detect MUX truth tables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Lf_ManTtIsMux( word t ) { static unsigned s_Muxes[24] = { (~0xAAAAAAAA & ~0xCCCCCCCC) | ( 0xAAAAAAAA & ~0xF0F0F0F0), (~0xAAAAAAAA & ~0xCCCCCCCC) | ( 0xAAAAAAAA & 0xF0F0F0F0), (~0xAAAAAAAA & 0xCCCCCCCC) | ( 0xAAAAAAAA & ~0xF0F0F0F0), (~0xAAAAAAAA & 0xCCCCCCCC) | ( 0xAAAAAAAA & 0xF0F0F0F0), ( 0xAAAAAAAA & ~0xCCCCCCCC) | (~0xAAAAAAAA & ~0xF0F0F0F0), ( 0xAAAAAAAA & ~0xCCCCCCCC) | (~0xAAAAAAAA & 0xF0F0F0F0), ( 0xAAAAAAAA & 0xCCCCCCCC) | (~0xAAAAAAAA & ~0xF0F0F0F0), ( 0xAAAAAAAA & 0xCCCCCCCC) | (~0xAAAAAAAA & 0xF0F0F0F0), (~0xCCCCCCCC & ~0xAAAAAAAA) | ( 0xCCCCCCCC & ~0xF0F0F0F0), (~0xCCCCCCCC & ~0xAAAAAAAA) | ( 0xCCCCCCCC & 0xF0F0F0F0), (~0xCCCCCCCC & 0xAAAAAAAA) | ( 0xCCCCCCCC & ~0xF0F0F0F0), (~0xCCCCCCCC & 0xAAAAAAAA) | ( 0xCCCCCCCC & 0xF0F0F0F0), ( 0xCCCCCCCC & ~0xAAAAAAAA) | (~0xCCCCCCCC & ~0xF0F0F0F0), ( 0xCCCCCCCC & ~0xAAAAAAAA) | (~0xCCCCCCCC & 0xF0F0F0F0), ( 0xCCCCCCCC & 0xAAAAAAAA) | (~0xCCCCCCCC & ~0xF0F0F0F0), ( 0xCCCCCCCC & 0xAAAAAAAA) | (~0xCCCCCCCC & 0xF0F0F0F0), (~0xF0F0F0F0 & ~0xCCCCCCCC) | ( 0xF0F0F0F0 & ~0xAAAAAAAA), (~0xF0F0F0F0 & ~0xCCCCCCCC) | ( 0xF0F0F0F0 & 0xAAAAAAAA), (~0xF0F0F0F0 & 0xCCCCCCCC) | ( 0xF0F0F0F0 & ~0xAAAAAAAA), (~0xF0F0F0F0 & 0xCCCCCCCC) | ( 0xF0F0F0F0 & 0xAAAAAAAA), ( 0xF0F0F0F0 & ~0xCCCCCCCC) | (~0xF0F0F0F0 & ~0xAAAAAAAA), ( 0xF0F0F0F0 & ~0xCCCCCCCC) | (~0xF0F0F0F0 & 0xAAAAAAAA), ( 0xF0F0F0F0 & 0xCCCCCCCC) | (~0xF0F0F0F0 & ~0xAAAAAAAA), ( 0xF0F0F0F0 & 0xCCCCCCCC) | (~0xF0F0F0F0 & 0xAAAAAAAA) }; int i; for ( i = 0; i < 24; i++ ) if ( ((unsigned)t) == s_Muxes[i] ) return 1; return 0; } /**Function************************************************************* Synopsis [Count the number of unique drivers and invertors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lf_ManAnalyzeCoDrivers( Gia_Man_t * p, int * pnDrivers, int * pnInverts ) { Gia_Obj_t * pObj; int i, Entry, nDrivers, nInverts; Vec_Int_t * vMarks = Vec_IntStart( Gia_ManObjNum(p) ); nDrivers = nInverts = 0; Gia_ManForEachCo( p, pObj, i ) *Vec_IntEntryP( vMarks, Gia_ObjFaninId0p(p, pObj) ) |= Gia_ObjFaninC0(pObj) ? 2 : 1; Vec_IntForEachEntry( vMarks, Entry, i ) nDrivers += (int)(Entry != 0), nInverts += (int)(Entry == 3); Vec_IntFree( vMarks ); *pnDrivers = nDrivers; *pnInverts = nInverts; } void Lf_ManComputeSwitching( Gia_Man_t * p, Vec_Flt_t * vSwitches ) { // abctime clk = Abc_Clock(); Vec_Flt_t * vSwitching = (Vec_Flt_t *)Gia_ManComputeSwitchProbs( p, 48, 16, 0 ); assert( Vec_FltCap(vSwitches) == 0 ); *vSwitches = *vSwitching; ABC_FREE( vSwitching ); // Abc_PrintTime( 1, "Computing switching activity", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Lf_CutCreateUnit( Lf_Cut_t * p, int i ) { p->fLate = 0; p->fMux7 = 0; p->iFunc = 2; p->nLeaves = 1; p->pLeaves[0] = i; p->Sign = ((word)1) << (i & 0x3F); return 1; } static inline Lf_Cut_t * Lf_ManFetchSet( Lf_Man_t * p, int i ) { int uMaskPage = (1 << LF_LOG_PAGE) - 1; Gia_Obj_t * pObj = Gia_ManObj( p->pGia, i ); int iOffSet = Vec_IntEntry( &p->vOffsets, i ); int Entry = Vec_IntEntry( &p->vCutSets, iOffSet ); assert( Gia_ObjIsAndNotBuf(pObj) ); assert( pObj->Value > 0 ); if ( Entry == -1 ) // first visit { if ( Vec_IntSize(&p->vFreeSets) == 0 ) // add new { Lf_Cut_t * pCut = (Lf_Cut_t *)ABC_CALLOC( word, p->nSetWords * (1 << LF_LOG_PAGE) ); int uMaskShift = Vec_PtrSize(&p->vMemSets) << LF_LOG_PAGE; Vec_PtrPush( &p->vMemSets, pCut ); for ( Entry = uMaskPage; Entry >= 0; Entry-- ) { Vec_IntPush( &p->vFreeSets, uMaskShift | Entry ); pCut[Entry].nLeaves = LF_NO_LEAF; } } Entry = Vec_IntPop( &p->vFreeSets ); Vec_IntWriteEntry( &p->vCutSets, iOffSet, Entry ); p->nFrontMax = Abc_MaxInt( p->nFrontMax, Entry + 1 ); } else if ( --pObj->Value == 0 ) { Vec_IntPush( &p->vFreeSets, Entry ); Vec_IntWriteEntry( &p->vCutSets, iOffSet, -1 ); } return (Lf_Cut_t *)((word *)Vec_PtrEntry(&p->vMemSets, Entry >> LF_LOG_PAGE) + p->nSetWords * (Entry & uMaskPage)); } static inline int Lf_ManPrepareSet( Lf_Man_t * p, int iObj, int Index, Lf_Cut_t ** ppCutSet ) { static word CutTemp[3][LF_CUT_WORDS]; if ( Vec_IntEntry(&p->vOffsets, iObj) == -1 ) return Lf_CutCreateUnit( (*ppCutSet = (Lf_Cut_t *)CutTemp[Index]), iObj ); { Lf_Cut_t * pCut; int i, nCutNum = p->pPars->nCutNum; *ppCutSet = Lf_ManFetchSet(p, iObj); Lf_CutSetForEachCut( p->nCutWords, *ppCutSet, pCut, i, nCutNum ) if ( pCut->nLeaves == LF_NO_LEAF ) return i; return i; } } /**Function************************************************************* Synopsis [Cut manipulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Lf_CutGetSign( Lf_Cut_t * pCut ) { word Sign = 0; int i; for ( i = 0; i < (int)pCut->nLeaves; i++ ) Sign |= ((word)1) << (pCut->pLeaves[i] & 0x3F); return Sign; } static inline int Lf_CutCountBits( word i ) { i = i - ((i >> 1) & 0x5555555555555555); i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); return (i*(0x0101010101010101))>>56; } static inline int Lf_CutEqual( Lf_Cut_t * pCut0, Lf_Cut_t * pCut1 ) { int i; if ( pCut0->iFunc != pCut1->iFunc ) return 0; if ( pCut0->nLeaves != pCut1->nLeaves ) return 0; for ( i = 0; i < (int)pCut0->nLeaves; i++ ) if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] ) return 0; return 1; } static inline float Lf_CutSwitches( Lf_Man_t * p, Lf_Cut_t * pCut ) { float Switches = 0; int i; for ( i = 0; i < (int)pCut->nLeaves; i++ ) Switches += Lf_ObjSwitches(p, pCut->pLeaves[i]); //printf( "%.2f ", Switches ); return Switches; } static inline void Lf_CutPrint( Lf_Man_t * p, Lf_Cut_t * pCut ) { int i, nDigits = Abc_Base10Log(Gia_ManObjNum(p->pGia)); printf( "%d {", pCut->nLeaves ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) printf( " %*d", nDigits, pCut->pLeaves[i] ); for ( ; i < (int)p->pPars->nLutSize; i++ ) printf( " %*s", nDigits, " " ); printf( " } Late = %d D = %4d A = %9.4f F = %6d\n", pCut->fLate, pCut->Delay, pCut->Flow, pCut->iFunc ); } static inline float Lf_CutArea( Lf_Man_t * p, Lf_Cut_t * pCut ) { if ( pCut->nLeaves < 2 || pCut->fMux7 ) return 0; if ( p->pPars->fPower ) return 1.0 * pCut->nLeaves + Lf_CutSwitches( p, pCut ); if ( p->pPars->fOptEdge ) return (pCut->nLeaves + p->pPars->nAreaTuner) * (1 + (p->pPars->fCutGroup && (int)pCut->nLeaves > p->pPars->nLutSize/2)); return 1 + (p->pPars->fCutGroup && (int)pCut->nLeaves > p->pPars->nLutSize/2); } static inline int Lf_CutIsMux( Lf_Man_t * p, Lf_Cut_t * pCut, Gia_Obj_t * pMux ) { int i, Id; if ( pCut->nLeaves != 3 ) return 0; assert( Gia_ObjIsMux(p->pGia, pMux) ); if ( Gia_ObjIsCi(Gia_ObjFanin0(pMux)) || Gia_ObjIsCi(Gia_ObjFanin1(pMux)) ) return 0; Id = Gia_ObjFaninId0p( p->pGia, pMux ); for ( i = 0; i < 3; i++ ) if ( pCut->pLeaves[i] == Id ) break; if ( i == 3 ) return 0; Id = Gia_ObjFaninId1p( p->pGia, pMux ); for ( i = 0; i < 3; i++ ) if ( pCut->pLeaves[i] == Id ) break; if ( i == 3 ) return 0; Id = Gia_ObjFaninId2p( p->pGia, pMux ); for ( i = 0; i < 3; i++ ) if ( pCut->pLeaves[i] == Id ) break; if ( i == 3 ) return 0; return 1; } /**Function************************************************************* Synopsis [Cut packing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Lf_MemAlloc( Lf_Mem_t * p, int LogPage, Vec_Ptr_t * vFree, int nCutWords ) { memset( p, 0, sizeof(Lf_Mem_t) ); p->LogPage = LogPage; p->MaskPage = (1 << LogPage) - 1; p->nCutWords = nCutWords; p->vFree = vFree; } static inline int Lf_MemSaveCut( Lf_Mem_t * p, Lf_Cut_t * pCut, int iObj ) { unsigned char * pPlace; int i, iPlace, Prev = iObj, iCur = p->iCur; assert( !pCut->fMux7 ); if ( Vec_PtrSize(&p->vPages) == (p->iCur >> p->LogPage) ) Vec_PtrPush( &p->vPages, Vec_PtrSize(p->vFree) ? Vec_PtrPop(p->vFree) : ABC_ALLOC(char,p->MaskPage+1) ); assert( p->MaskPage - (p->iCur & p->MaskPage) >= 4 * (LF_LEAF_MAX + 2) ); iPlace = iCur & p->MaskPage; pPlace = (unsigned char *)Vec_PtrEntry(&p->vPages, p->iCur >> p->LogPage); iPlace = Gia_AigerWriteUnsignedBuffer( pPlace, iPlace, pCut->nLeaves ); for ( i = pCut->nLeaves - 1; i >= 0; i-- ) iPlace = Gia_AigerWriteUnsignedBuffer( pPlace, iPlace, Prev - pCut->pLeaves[i] ), Prev = pCut->pLeaves[i]; assert( pCut->nLeaves >= 2 || pCut->iFunc <= 3 ); if ( pCut->iFunc >= 0 ) iPlace = Gia_AigerWriteUnsignedBuffer( pPlace, iPlace, pCut->iFunc ); if ( p->MaskPage - (iPlace & p->MaskPage) < 4 * (LF_LEAF_MAX + 2) ) p->iCur = ((p->iCur >> p->LogPage) + 1) << p->LogPage; else p->iCur = (p->iCur & ~p->MaskPage) | iPlace; return iCur; } static inline Lf_Cut_t * Lf_MemLoadCut( Lf_Mem_t * p, int iCur, int iObj, Lf_Cut_t * pCut, int fTruth, int fRecycle ) { unsigned char * pPlace; int i, Prev = iObj, Page = iCur >> p->LogPage; assert( Page < Vec_PtrSize(&p->vPages) ); pPlace = (unsigned char *)Vec_PtrEntry(&p->vPages, Page) + (iCur & p->MaskPage); pCut->nLeaves = Gia_AigerReadUnsigned(&pPlace); assert( pCut->nLeaves <= LF_LEAF_MAX ); for ( i = pCut->nLeaves - 1; i >= 0; i-- ) pCut->pLeaves[i] = Prev - Gia_AigerReadUnsigned(&pPlace), Prev = pCut->pLeaves[i]; pCut->iFunc = fTruth ? Gia_AigerReadUnsigned(&pPlace) : -1; assert( pCut->nLeaves >= 2 || pCut->iFunc <= 3 ); if ( fRecycle && Page && Vec_PtrEntry(&p->vPages, Page-1) ) { Vec_PtrPush( p->vFree, Vec_PtrEntry(&p->vPages, Page-1) ); Vec_PtrWriteEntry( &p->vPages, Page-1, NULL ); } pCut->Sign = fRecycle ? Lf_CutGetSign(pCut) : 0; pCut->fMux7 = 0; return pCut; } static inline void Lf_MemRecycle( Lf_Mem_t * p ) { void * pPlace; int i; Vec_PtrForEachEntry( void *, &p->vPages, pPlace, i ) if ( pPlace ) Vec_PtrPush( p->vFree, pPlace ); Vec_PtrClear( &p->vPages ); p->iCur = 0; } static inline Lf_Cut_t * Lf_MemLoadMuxCut( Lf_Man_t * p, int iObj, Lf_Cut_t * pCut ) { Gia_Obj_t * pMux = Gia_ManObj( p->pGia, iObj ); assert( Gia_ObjIsMux(p->pGia, pMux) ); pCut->iFunc = p->pPars->fCutMin ? 4 : -1; pCut->pLeaves[0] = Gia_ObjFaninId0( pMux, iObj ); pCut->pLeaves[1] = Gia_ObjFaninId1( pMux, iObj ); pCut->pLeaves[2] = Gia_ObjFaninId2( p->pGia, iObj ); pCut->nLeaves = 3; pCut->fMux7 = 1; return pCut; } static inline Lf_Cut_t * Lf_ObjCutMux( Lf_Man_t * p, int i ) { static word CutSet[LF_CUT_WORDS]; return Lf_MemLoadMuxCut( p, i, (Lf_Cut_t *)CutSet ); } static inline Lf_Cut_t * Lf_ObjCutBest( Lf_Man_t * p, int i ) { static word CutSet[LF_CUT_WORDS]; Lf_Bst_t * pBest = Lf_ObjReadBest( p, i ); Lf_Cut_t * pCut = (Lf_Cut_t *)CutSet; int Index = Lf_BestCutIndex( pBest ); pCut->Delay = pBest->Delay[Index]; pCut->Flow = pBest->Flow[Index]; if ( Index == 2 ) return Lf_MemLoadMuxCut( p, i, pCut ); return Lf_MemLoadCut( &p->vStoreOld, pBest->Cut[Index].Handle, i, pCut, p->pPars->fCutMin, 0 ); } static inline Lf_Cut_t * Lf_ObjCutBestNew( Lf_Man_t * p, int i, Lf_Cut_t * pCut ) { Lf_Bst_t * pBest = Lf_ObjReadBest( p, i ); int Index = Lf_BestCutIndex( pBest ); pCut->Delay = pBest->Delay[Index]; pCut->Flow = pBest->Flow[Index]; if ( Index == 2 ) return Lf_MemLoadMuxCut( p, i, pCut ); return Lf_MemLoadCut( &p->vStoreNew, pBest->Cut[Index].Handle, i, pCut, 0, 0 ); } /**Function************************************************************* Synopsis [Check correctness of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Lf_CutCheck( Lf_Cut_t * pBase, Lf_Cut_t * pCut ) // check if pCut is contained in pBase { int nSizeB = pBase->nLeaves; int nSizeC = pCut->nLeaves; int i, * pB = pBase->pLeaves; int k, * pC = pCut->pLeaves; for ( i = 0; i < nSizeC; i++ ) { for ( k = 0; k < nSizeB; k++ ) if ( pC[i] == pB[k] ) break; if ( k == nSizeB ) return 0; } return 1; } static inline int Lf_SetCheckArray( Lf_Cut_t ** ppCuts, int nCuts ) { Lf_Cut_t * pCut0, * pCut1; int i, k, m, n, Value; assert( nCuts > 0 ); for ( i = 0; i < nCuts; i++ ) { pCut0 = ppCuts[i]; assert( !pCut0->fMux7 ); assert( pCut0->nLeaves < LF_LEAF_MAX ); assert( pCut0->Sign == Lf_CutGetSign(pCut0) ); // check duplicates for ( m = 0; m < (int)pCut0->nLeaves; m++ ) for ( n = m + 1; n < (int)pCut0->nLeaves; n++ ) assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] ); // check pairs for ( k = 0; k < nCuts; k++ ) { pCut1 = ppCuts[k]; if ( pCut0 == pCut1 ) continue; // check containments Value = Lf_CutCheck( pCut0, pCut1 ); assert( Value == 0 ); } } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Lf_CutMergeOrder( Lf_Cut_t * pCut0, Lf_Cut_t * pCut1, Lf_Cut_t * pCut, int nLutSize ) { int nSize0 = pCut0->nLeaves; int nSize1 = pCut1->nLeaves; int i, * pC0 = pCut0->pLeaves; int k, * pC1 = pCut1->pLeaves; int c, * pC = pCut->pLeaves; // the case of the largest cut sizes if ( nSize0 == nLutSize && nSize1 == nLutSize ) { for ( i = 0; i < nSize0; i++ ) { if ( pC0[i] != pC1[i] ) return 0; pC[i] = pC0[i]; } pCut->nLeaves = nLutSize; pCut->iFunc = -1; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; } // compare two cuts with different numbers i = k = c = 0; if ( nSize0 == 0 ) goto FlushCut1; if ( nSize1 == 0 ) goto FlushCut0; while ( 1 ) { if ( c == nLutSize ) return 0; if ( pC0[i] < pC1[k] ) { pC[c++] = pC0[i++]; if ( i >= nSize0 ) goto FlushCut1; } else if ( pC0[i] > pC1[k] ) { pC[c++] = pC1[k++]; if ( k >= nSize1 ) goto FlushCut0; } else { pC[c++] = pC0[i++]; k++; if ( i >= nSize0 ) goto FlushCut1; if ( k >= nSize1 ) goto FlushCut0; } } FlushCut0: if ( c + nSize0 > nLutSize + i ) return 0; while ( i < nSize0 ) pC[c++] = pC0[i++]; pCut->nLeaves = c; pCut->iFunc = -1; pCut->fMux7 = 0; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; FlushCut1: if ( c + nSize1 > nLutSize + k ) return 0; while ( k < nSize1 ) pC[c++] = pC1[k++]; pCut->nLeaves = c; pCut->iFunc = -1; pCut->fMux7 = 0; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; } static inline int Lf_CutMergeOrder2( Lf_Cut_t * pCut0, Lf_Cut_t * pCut1, Lf_Cut_t * pCut, int nLutSize ) { int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; int xMin, c = 0, * pC = pCut->pLeaves; while ( 1 ) { x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; xMin = Abc_MinInt(x0, x1); if ( xMin == ABC_INFINITY ) break; if ( c == nLutSize ) return 0; pC[c++] = xMin; if (x0 == xMin) i0++; if (x1 == xMin) i1++; } pCut->nLeaves = c; pCut->iFunc = -1; pCut->fMux7 = 0; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; } static inline int Lf_CutMergeOrderMux( Lf_Cut_t * pCut0, Lf_Cut_t * pCut1, Lf_Cut_t * pCut2, Lf_Cut_t * pCut, int nLutSize ) { int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; int x2, i2 = 0, nSize2 = pCut2->nLeaves, * pC2 = pCut2->pLeaves; int xMin, c = 0, * pC = pCut->pLeaves; while ( 1 ) { x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; x2 = (i2 == nSize2) ? ABC_INFINITY : pC2[i2]; xMin = Abc_MinInt( Abc_MinInt(x0, x1), x2 ); if ( xMin == ABC_INFINITY ) break; if ( c == nLutSize ) return 0; pC[c++] = xMin; if (x0 == xMin) i0++; if (x1 == xMin) i1++; if (x2 == xMin) i2++; } pCut->nLeaves = c; pCut->iFunc = -1; pCut->fMux7 = 0; pCut->Sign = pCut0->Sign | pCut1->Sign | pCut2->Sign; return 1; } static inline int Lf_SetCutIsContainedOrder( Lf_Cut_t * pBase, Lf_Cut_t * pCut ) // check if pCut is contained in pBase { int i, nSizeB = pBase->nLeaves; int k, nSizeC = pCut->nLeaves; if ( nSizeB == nSizeC ) { for ( i = 0; i < nSizeB; i++ ) if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) return 0; return 1; } assert( nSizeB > nSizeC ); if ( nSizeC == 0 ) return 1; for ( i = k = 0; i < nSizeB; i++ ) { if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) return 0; if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) { if ( ++k == nSizeC ) return 1; } } return 0; } static inline int Lf_SetLastCutIsContained( Lf_Cut_t ** pCuts, int nCuts ) { int i; for ( i = 0; i < nCuts; i++ ) if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Lf_SetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) ) return 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Lf_CutCompareDelay( Lf_Cut_t * pCut0, Lf_Cut_t * pCut1 ) { if ( pCut0->Delay < pCut1->Delay ) return -1; if ( pCut0->Delay > pCut1->Delay ) return 1; if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; if ( pCut0->Flow < pCut1->Flow - LF_EPSILON ) return -1; if ( pCut0->Flow > pCut1->Flow + LF_EPSILON ) return 1; return 0; } static inline int Lf_CutCompareArea( Lf_Cut_t * pCut0, Lf_Cut_t * pCut1 ) { if ( pCut0->fLate < pCut1->fLate ) return -1; if ( pCut0->fLate > pCut1->fLate ) return 1; if ( pCut0->Flow < pCut1->Flow - LF_EPSILON ) return -1; if ( pCut0->Flow > pCut1->Flow + LF_EPSILON ) return 1; if ( pCut0->Delay < pCut1->Delay ) return -1; if ( pCut0->Delay > pCut1->Delay ) return 1; if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; return 0; } static inline int Lf_SetLastCutContainsArea( Lf_Cut_t ** pCuts, int nCuts ) { int i, k, fChanges = 0; for ( i = 1; i < nCuts; i++ ) if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Lf_SetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) ) pCuts[i]->nLeaves = LF_NO_LEAF, fChanges = 1; if ( !fChanges ) return nCuts; for ( i = k = 1; i <= nCuts; i++ ) { if ( pCuts[i]->nLeaves == LF_NO_LEAF ) continue; if ( k < i ) ABC_SWAP( Lf_Cut_t *, pCuts[k], pCuts[i] ); k++; } return k - 1; } static inline void Lf_SetSortByArea( Lf_Cut_t ** pCuts, int nCuts ) { int i; for ( i = nCuts; i > 1; i-- ) { if ( Lf_CutCompareArea(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 ) return; ABC_SWAP( Lf_Cut_t *, pCuts[i - 1], pCuts[i] ); } } static inline int Lf_SetAddCut( Lf_Cut_t ** pCuts, int nCuts, int nCutNum ) { if ( nCuts == 0 ) return 1; nCuts = Lf_SetLastCutContainsArea(pCuts, nCuts); assert( nCuts >= 1 ); if ( Lf_CutCompareDelay(pCuts[0], pCuts[nCuts]) == 1 ) // new cut is better for delay { ABC_SWAP( Lf_Cut_t *, pCuts[0], pCuts[nCuts] ); // if old cut (now cut number nCuts) is contained - remove it if ( pCuts[0]->nLeaves < pCuts[nCuts]->nLeaves && (pCuts[0]->Sign & pCuts[nCuts]->Sign) == pCuts[0]->Sign && Lf_SetCutIsContainedOrder(pCuts[nCuts], pCuts[0]) ) return nCuts; } // sort area cuts by area Lf_SetSortByArea( pCuts, nCuts ); // add new cut if there is room return Abc_MinInt( nCuts + 1, nCutNum - 1 ); } static inline void Lf_SetSortBySize( Lf_Cut_t ** pCutsR, int nCutsR ) { int i, j, best_i; for ( i = 1; i < nCutsR-1; i++ ) { best_i = i; for ( j = i+1; j < nCutsR; j++ ) if ( pCutsR[j]->nLeaves > pCutsR[best_i]->nLeaves ) best_i = j; ABC_SWAP( Lf_Cut_t *, pCutsR[i], pCutsR[best_i] ); } } /**Function************************************************************* Synopsis [Check if truth table has non-const-cof cofactoring variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Lf_ManFindCofVar( word * pTruth, int nWords, int nVars ) { word uTruthCof[LF_TT_WORDS]; int iVar; for ( iVar = 0; iVar < nVars; iVar++ ) { Abc_TtCofactor0p( uTruthCof, pTruth, nWords, iVar ); if ( Abc_TtSupportSize(uTruthCof, nVars) < 2 ) continue; Abc_TtCofactor1p( uTruthCof, pTruth, nWords, iVar ); if ( Abc_TtSupportSize(uTruthCof, nVars) < 2 ) continue; return iVar; } return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Lf_CutComputeTruth6( Lf_Man_t * p, Lf_Cut_t * pCut0, Lf_Cut_t * pCut1, int fCompl0, int fCompl1, Lf_Cut_t * pCutR, int fIsXor ) { // extern int Mf_ManTruthCanonicize( word * t, int nVars ); int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; word t0 = *Lf_CutTruth(p, pCut0); word t1 = *Lf_CutTruth(p, pCut1); if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t = fIsXor ? t0 ^ t1 : t0 & t1; if ( (fCompl = (int)(t & 1)) ) t = ~t; pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); assert( (int)(t & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, &t); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); // p->nCutMux += Lf_ManTtIsMux( t ); assert( (int)pCutR->nLeaves <= nOldSupp ); // Mf_ManTruthCanonicize( &t, pCutR->nLeaves ); return (int)pCutR->nLeaves < nOldSupp; } static inline int Lf_CutComputeTruth( Lf_Man_t * p, Lf_Cut_t * pCut0, Lf_Cut_t * pCut1, int fCompl0, int fCompl1, Lf_Cut_t * pCutR, int fIsXor ) { if ( p->pPars->nLutSize <= 6 ) return Lf_CutComputeTruth6( p, pCut0, pCut1, fCompl0, fCompl1, pCutR, fIsXor ); { word uTruth[LF_TT_WORDS], uTruth0[LF_TT_WORDS], uTruth1[LF_TT_WORDS]; int nOldSupp = pCutR->nLeaves, truthId; int LutSize = p->pPars->nLutSize, fCompl; int nWords = Abc_Truth6WordNum(LutSize); word * pTruth0 = Lf_CutTruth(p, pCut0); word * pTruth1 = Lf_CutTruth(p, pCut1); Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ); Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ); Abc_TtExpand( uTruth0, LutSize, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); Abc_TtExpand( uTruth1, LutSize, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); if ( fIsXor ) Abc_TtXor( uTruth, uTruth0, uTruth1, nWords, (fCompl = (int)((uTruth0[0] ^ uTruth1[0]) & 1)) ); else Abc_TtAnd( uTruth, uTruth0, uTruth1, nWords, (fCompl = (int)((uTruth0[0] & uTruth1[0]) & 1)) ); pCutR->nLeaves = Abc_TtMinBase( uTruth, pCutR->pLeaves, pCutR->nLeaves, LutSize ); assert( (uTruth[0] & 1) == 0 ); //Kit_DsdPrintFromTruth( uTruth, pCutR->nLeaves ), printf("\n" ), printf("\n" ); truthId = Vec_MemHashInsert(p->vTtMem, uTruth); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } } static inline int Lf_CutComputeTruthMux6( Lf_Man_t * p, Lf_Cut_t * pCut0, Lf_Cut_t * pCut1, Lf_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Lf_Cut_t * pCutR ) { int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; word t0 = *Lf_CutTruth(p, pCut0); word t1 = *Lf_CutTruth(p, pCut1); word tC = *Lf_CutTruth(p, pCutC); if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; if ( Abc_LitIsCompl(pCutC->iFunc) ^ fComplC ) tC = ~tC; t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); tC = Abc_Tt6Expand( tC, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t = (tC & t1) | (~tC & t0); if ( (fCompl = (int)(t & 1)) ) t = ~t; pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); assert( (int)(t & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, &t); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } static inline int Lf_CutComputeTruthMux( Lf_Man_t * p, Lf_Cut_t * pCut0, Lf_Cut_t * pCut1, Lf_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Lf_Cut_t * pCutR ) { if ( p->pPars->nLutSize <= 6 ) return Lf_CutComputeTruthMux6( p, pCut0, pCut1, pCutC, fCompl0, fCompl1, fComplC, pCutR ); { word uTruth[LF_TT_WORDS], uTruth0[LF_TT_WORDS], uTruth1[LF_TT_WORDS], uTruthC[LF_TT_WORDS]; int nOldSupp = pCutR->nLeaves, truthId; int LutSize = p->pPars->nLutSize, fCompl; int nWords = Abc_Truth6WordNum(LutSize); word * pTruth0 = Lf_CutTruth(p, pCut0); word * pTruth1 = Lf_CutTruth(p, pCut1); word * pTruthC = Lf_CutTruth(p, pCutC); Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ); Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ); Abc_TtCopy( uTruthC, pTruthC, nWords, Abc_LitIsCompl(pCutC->iFunc) ^ fComplC ); Abc_TtExpand( uTruth0, LutSize, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); Abc_TtExpand( uTruth1, LutSize, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); Abc_TtExpand( uTruthC, LutSize, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); Abc_TtMux( uTruth, uTruthC, uTruth1, uTruth0, nWords ); fCompl = (int)(uTruth[0] & 1); if ( fCompl ) Abc_TtNot( uTruth, nWords ); pCutR->nLeaves = Abc_TtMinBase( uTruth, pCutR->pLeaves, pCutR->nLeaves, LutSize ); assert( (uTruth[0] & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, uTruth); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } } /**Function************************************************************* Synopsis [Exact local area.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Lf_CutRef_rec( Lf_Man_t * p, Lf_Cut_t * pCut ) { word CutTemp[LF_CUT_WORDS] = {0}; float Count = Lf_CutArea(p, pCut); int i, Var; Lf_CutForEachVar( pCut, Var, i ) if ( !Lf_ObjMapRefInc(p, Var) ) Count += Lf_CutRef_rec( p, Lf_ObjCutBestNew(p, Var, (Lf_Cut_t *)CutTemp) ); return Count; } float Lf_CutDeref_rec( Lf_Man_t * p, Lf_Cut_t * pCut ) { word CutTemp[LF_CUT_WORDS] = {0}; float Count = Lf_CutArea(p, pCut); int i, Var; Lf_CutForEachVar( pCut, Var, i ) if ( !Lf_ObjMapRefDec(p, Var) ) Count += Lf_CutDeref_rec( p, Lf_ObjCutBestNew(p, Var, (Lf_Cut_t *)CutTemp) ); return Count; } static inline float Lf_CutAreaDerefed( Lf_Man_t * p, Lf_Cut_t * pCut ) { float Ela1 = Lf_CutRef_rec( p, pCut ); Lf_CutDeref_rec( p, pCut ); // float Ela2 = Lf_CutDeref_rec( p, pCut ); // assert( Ela1 == Ela2 ); return Ela1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Lf_CutRequired( Lf_Man_t * p, Lf_Cut_t * pCut ) { int i, Arr, Req, Arrival = 0, Required = 0; for ( i = 0; i < (int)pCut->nLeaves; i++ ) { if ( Lf_ObjOff(p, pCut->pLeaves[i]) < 0 ) // Arr = Lf_ObjCiArrival( p, Gia_ObjCioId(Gia_ManObj(p->pGia, pCut->pLeaves[i])) ); Arr = Lf_ObjArrival_rec( p, Gia_ManObj(p->pGia, pCut->pLeaves[i]) ); else Arr = Lf_ObjReadBest(p, pCut->pLeaves[i])->Delay[0]; Arrival = Abc_MaxInt( Arrival, Arr ); Req = Lf_ObjRequired(p, pCut->pLeaves[i]); if ( Req < ABC_INFINITY ) Required = Abc_MaxInt( Required, Req ); } return Abc_MaxInt( Required + 2, Arrival + 1 ); } static inline void Lf_CutParams( Lf_Man_t * p, Lf_Cut_t * pCut, int Required, float FlowRefs, Gia_Obj_t * pMux ) { Lf_Bst_t * pBest; int i, Index, Delay; assert( !pCut->fMux7 || Gia_ObjIsMux(p->pGia, pMux) ); pCut->fLate = 0; pCut->Delay = 0; pCut->Flow = 0; assert( pCut->nLeaves < LF_NO_LEAF ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) { if ( Lf_ObjOff(p, pCut->pLeaves[i]) < 0 ) // Delay = Lf_ObjCiArrival( p, Gia_ObjCioId(Gia_ManObj(p->pGia, pCut->pLeaves[i])) ); Delay = Lf_ObjArrival_rec( p, Gia_ManObj(p->pGia, pCut->pLeaves[i]) ); else { pBest = Lf_ObjReadBest(p, pCut->pLeaves[i]); assert( pBest->Delay[0] <= pBest->Delay[1] ); assert( pBest->Flow[0] >= pBest->Flow[1] ); if ( p->fUseEla ) Index = Lf_BestIndex(pBest); else { Index = (int)(pBest->Delay[1] + 1 <= Required && Required != ABC_INFINITY); //pCut->Flow += pBest->Flow[Index]; 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]; } // if ( pCut->fMux7 && pCut->pLeaves[i] == Gia_ObjFaninId2p(p->pGia, pMux) ) // Delay += 1; pCut->Delay = Abc_MaxInt( pCut->Delay, Delay ); } pCut->Delay += (int)(pCut->nLeaves > 1);// && !pCut->fMux7; if ( pCut->Delay > Required ) pCut->fLate = 1; 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 ) { word CutSet[LF_CUT_MAX][LF_CUT_WORDS] = {{0}}; Lf_Cut_t * pCutSet0, * pCutSet1, * pCutSet2, * pCut0, * pCut1, * pCut2; Lf_Cut_t * pCutSet = (Lf_Cut_t *)CutSet, * pCutsR[LF_CUT_MAX]; Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); Lf_Bst_t * pBest = Lf_ObjReadBest(p, iObj); float FlowRefs = Lf_ObjFlowRefs(p, iObj); int Required = Lf_ObjRequired(p, iObj); int nLutSize = p->pPars->fCutGroup ? p->pPars->nLutSize/2 : p->pPars->nLutSize; int nCutNum = p->pPars->nCutNum; int nCutWords = p->nCutWords; int fComp0 = Gia_ObjFaninC0(pObj); int fComp1 = Gia_ObjFaninC1(pObj); int nCuts0 = Lf_ManPrepareSet( p, Gia_ObjFaninId0(pObj, iObj), 0, &pCutSet0 ); int nCuts1 = Lf_ManPrepareSet( p, Gia_ObjFaninId1(pObj, iObj), 1, &pCutSet1 ); int iSibl = Gia_ObjSibl(p->pGia, iObj); int i, k, n, iCutUsed, nCutsR = 0; float Value1 = -1, Value2 = -1; assert( !Gia_ObjIsBuf(pObj) ); Lf_CutSetForEachCut( nCutWords, pCutSet, pCut0, i, nCutNum ) pCutsR[i] = pCut0; if ( p->Iter ) { assert( nCutsR == 0 ); // load cuts Lf_MemLoadCut( &p->vStoreOld, pBest->Cut[0].Handle, iObj, pCutsR[0], p->pPars->fCutMin, 1 ); if ( Lf_BestDiffCuts(pBest) ) Lf_MemLoadCut( &p->vStoreOld, pBest->Cut[1].Handle, iObj, pCutsR[1], p->pPars->fCutMin, 1 ); // deref the cut if ( p->fUseEla && Lf_ObjMapRefNum(p, iObj) > 0 ) Value1 = Lf_CutDeref_rec( p, pCutsR[Lf_BestIndex(pBest)] ); // update required times if ( Required == ABC_INFINITY )//&& !p->fUseEla ) Required = Lf_CutRequired( p, pCutsR[0] ); // compute parameters Lf_CutParams( p, pCutsR[nCutsR++], Required, FlowRefs, pObj ); if ( Lf_BestDiffCuts(pBest) ) { assert( nCutsR == 1 ); Lf_CutParams( p, pCutsR[nCutsR], Required, FlowRefs, pObj ); nCutsR = Lf_SetAddCut( pCutsR, nCutsR, nCutNum ); } if ( pCutsR[0]->fLate ) p->nTimeFails++; } if ( iSibl ) { Gia_Obj_t * pObjE = Gia_ObjSiblObj(p->pGia, iObj); int fCompE = Gia_ObjPhase(pObj) ^ Gia_ObjPhase(pObjE); int nCutsE = Lf_ManPrepareSet( p, iSibl, 2, &pCutSet2 ); Lf_CutSetForEachCut( nCutWords, pCutSet2, pCut2, n, nCutsE ) { if ( pCut2->pLeaves[0] == iSibl ) continue; Lf_CutCopy( pCutsR[nCutsR], pCut2, nCutWords ); if ( pCutsR[nCutsR]->iFunc >= 0 ) pCutsR[nCutsR]->iFunc = Abc_LitNotCond( pCutsR[nCutsR]->iFunc, fCompE ); Lf_CutParams( p, pCutsR[nCutsR], Required, FlowRefs, pObj ); nCutsR = Lf_SetAddCut( pCutsR, nCutsR, nCutNum ); } } if ( Gia_ObjIsMuxId(p->pGia, iObj) ) { Lf_Cut_t * pCutSave = NULL; int fComp2 = Gia_ObjFaninC2(p->pGia, pObj); int nCuts2 = Lf_ManPrepareSet( p, Gia_ObjFaninId2(p->pGia, iObj), 2, &pCutSet2 ); p->CutCount[0] += nCuts0 * nCuts1 * nCuts2; Lf_CutSetForEachCut( nCutWords, pCutSet0, pCut0, i, nCuts0 ) if ( (int)pCut0->nLeaves <= nLutSize ) Lf_CutSetForEachCut( nCutWords, pCutSet1, pCut1, k, nCuts1 ) if ( (int)pCut1->nLeaves <= nLutSize ) Lf_CutSetForEachCut( nCutWords, pCutSet2, pCut2, n, nCuts2 ) if ( (int)pCut2->nLeaves <= nLutSize ) { pCutSave = pCut2; if ( Lf_CutCountBits(pCut0->Sign | pCut1->Sign | pCut2->Sign) > nLutSize ) continue; p->CutCount[1]++; if ( !Lf_CutMergeOrderMux(pCut0, pCut1, pCut2, pCutsR[nCutsR], nLutSize) ) continue; if ( Lf_SetLastCutIsContained(pCutsR, nCutsR) ) continue; p->CutCount[2]++; if ( p->pPars->fCutMin && Lf_CutComputeTruthMux(p, pCut0, pCut1, pCut2, fComp0, fComp1, fComp2, pCutsR[nCutsR]) ) pCutsR[nCutsR]->Sign = Lf_CutGetSign(pCutsR[nCutsR]); if ( p->pPars->nLutSizeMux && p->pPars->nLutSizeMux == (int)pCutsR[nCutsR]->nLeaves && Lf_ManFindCofVar(Lf_CutTruth(p,pCutsR[nCutsR]), Abc_Truth6WordNum(nLutSize), pCutsR[nCutsR]->nLeaves) == -1 ) continue; Lf_CutParams( p, pCutsR[nCutsR], Required, FlowRefs, pObj ); nCutsR = Lf_SetAddCut( pCutsR, nCutsR, nCutNum ); } if ( p->pPars->fCutGroup ) { assert( pCutSave->nLeaves == 1 ); assert( pCutSave->pLeaves[0] == Gia_ObjFaninId2(p->pGia, iObj) ); Lf_CutSetForEachCut( nCutWords, pCutSet0, pCut0, i, nCuts0 ) if ( (int)pCut0->nLeaves <= nLutSize ) Lf_CutSetForEachCut( nCutWords, pCutSet1, pCut1, k, nCuts1 ) if ( (int)pCut1->nLeaves <= nLutSize ) { assert( (int)pCut0->nLeaves + (int)pCut1->nLeaves + 1 <= p->pPars->nLutSize ); // if ( Lf_CutCountBits(pCut0->Sign | pCut1->Sign | pCutSave->Sign) > p->pPars->nLutSize ) // continue; p->CutCount[1]++; if ( !Lf_CutMergeOrderMux(pCut0, pCut1, pCutSave, pCutsR[nCutsR], p->pPars->nLutSize) ) continue; if ( Lf_SetLastCutIsContained(pCutsR, nCutsR) ) continue; p->CutCount[2]++; if ( p->pPars->fCutMin && Lf_CutComputeTruthMux(p, pCut0, pCut1, pCutSave, fComp0, fComp1, fComp2, pCutsR[nCutsR]) ) pCutsR[nCutsR]->Sign = Lf_CutGetSign(pCutsR[nCutsR]); // if ( p->pPars->nLutSizeMux && p->pPars->nLutSizeMux == (int)pCutsR[nCutsR]->nLeaves && // Lf_ManFindCofVar(Lf_CutTruth(p,pCutsR[nCutsR]), Abc_Truth6WordNum(nLutSize), pCutsR[nCutsR]->nLeaves) == -1 ) // continue; Lf_CutParams( p, pCutsR[nCutsR], Required, FlowRefs, pObj ); nCutsR = Lf_SetAddCut( pCutsR, nCutsR, nCutNum ); } } } else { int fIsXor = Gia_ObjIsXor(pObj); p->CutCount[0] += nCuts0 * nCuts1; Lf_CutSetForEachCut( nCutWords, pCutSet0, pCut0, i, nCuts0 ) if ( (int)pCut0->nLeaves <= nLutSize ) Lf_CutSetForEachCut( nCutWords, pCutSet1, pCut1, k, nCuts1 ) if ( (int)pCut1->nLeaves <= nLutSize ) { if ( (int)(pCut0->nLeaves + pCut1->nLeaves) > nLutSize && Lf_CutCountBits(pCut0->Sign | pCut1->Sign) > nLutSize ) continue; p->CutCount[1]++; if ( !Lf_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], nLutSize) ) continue; if ( Lf_SetLastCutIsContained(pCutsR, nCutsR) ) continue; p->CutCount[2]++; if ( p->pPars->fCutMin && Lf_CutComputeTruth(p, pCut0, pCut1, fComp0, fComp1, pCutsR[nCutsR], fIsXor) ) pCutsR[nCutsR]->Sign = Lf_CutGetSign(pCutsR[nCutsR]); if ( p->pPars->nLutSizeMux && p->pPars->nLutSizeMux == (int)pCutsR[nCutsR]->nLeaves && Lf_ManFindCofVar(Lf_CutTruth(p,pCutsR[nCutsR]), Abc_Truth6WordNum(nLutSize), pCutsR[nCutsR]->nLeaves) == -1 ) continue; Lf_CutParams( p, pCutsR[nCutsR], Required, FlowRefs, pObj ); nCutsR = Lf_SetAddCut( pCutsR, nCutsR, nCutNum ); } } // debug printout if ( 0 ) { printf( "*** Obj = %d FlowRefs = %.2f MapRefs = %2d Required = %2d\n", iObj, FlowRefs, Lf_ObjMapRefNum(p, iObj), Required ); for ( i = 0; i < nCutsR; i++ ) Lf_CutPrint( p, pCutsR[i] ); printf( "\n" ); } // verify assert( nCutsR > 0 && nCutsR < nCutNum ); // assert( Lf_SetCheckArray(pCutsR, nCutsR) ); // delay cut assert( nCutsR == 1 || pCutsR[0]->Delay <= pCutsR[1]->Delay ); pBest->Cut[0].fUsed = pBest->Cut[1].fUsed = 0; pBest->Cut[0].Handle = pBest->Cut[1].Handle = Lf_MemSaveCut(&p->vStoreNew, pCutsR[0], iObj); pBest->Delay[0] = pBest->Delay[1] = pCutsR[0]->Delay; pBest->Flow[0] = pBest->Flow[1] = pCutsR[0]->Flow; p->nCutCounts[pCutsR[0]->nLeaves]++; p->CutCount[3] += nCutsR; p->nCutEqual++; // area cut iCutUsed = 0; if ( nCutsR > 1 && pCutsR[0]->Flow > pCutsR[1]->Flow + LF_EPSILON )//&& !pCutsR[1]->fLate ) // can remove !fLate { pBest->Cut[1].Handle = Lf_MemSaveCut(&p->vStoreNew, pCutsR[1], iObj); pBest->Delay[1] = pCutsR[1]->Delay; pBest->Flow[1] = pCutsR[1]->Flow; p->nCutCounts[pCutsR[1]->nLeaves]++; p->nCutEqual--; if ( !pCutsR[1]->fLate ) iCutUsed = 1; } // mux cut if ( p->pPars->fUseMux7 && Gia_ObjIsMuxId(p->pGia, iObj) ) { pCut2 = Lf_ObjCutMux( p, iObj ); Lf_CutParams( p, pCut2, Required, FlowRefs, pObj ); pBest->Delay[2] = pCut2->Delay; pBest->Flow[2] = pCut2->Flow; // update area value of the best area cut // if ( !pCut2->fLate ) // pBest->Flow[1] = Abc_MinFloat( pBest->Flow[1], pBest->Flow[2] ); } // reference resulting cut if ( p->fUseEla ) { pBest->Cut[iCutUsed].fUsed = 1; if ( Lf_ObjMapRefNum(p, iObj) > 0 ) Value2 = Lf_CutRef_rec( p, pCutsR[iCutUsed] ); // if ( Value1 < Value2 ) // printf( "ELA degradated cost at node %d from %d to %d.\n", iObj, Value1, Value2 ), fflush(stdout); // assert( Value1 >= Value2 ); // if ( Value1 != -1 ) // printf( "%.2f -> %.2f ", Value1, Value2 ); } if ( pObj->Value == 0 ) return; // store the cutset pCutSet = Lf_ManFetchSet(p, iObj); Lf_CutSetForEachCut( nCutWords, pCutSet, pCut0, i, nCutNum ) { assert( !pCut0->fMux7 ); if ( i < nCutsR ) Lf_CutCopy( pCut0, pCutsR[i], nCutWords ); else if ( i == nCutsR && pCutsR[0]->nLeaves > 1 && (nCutsR == 1 || pCutsR[1]->nLeaves > 1) ) Lf_CutCreateUnit( pCut0, iObj ); else pCut0->nLeaves = LF_NO_LEAF; } } /**Function************************************************************* Synopsis [Computing delay/area.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Lf_ManSetFlowRefInc( Gia_Man_t * p, Vec_Flt_t * vRefs, Vec_Int_t * vOffsets, int i ) { if ( Gia_ObjIsAndNotBuf(Gia_ManObj(p, i)) ) Vec_FltAddToEntry( vRefs, Vec_IntEntry(vOffsets, i), 1 ); } void Lf_ManSetFlowRefs( Gia_Man_t * p, Vec_Flt_t * vRefs, Vec_Int_t * vOffsets ) { int fDiscount = 1; Gia_Obj_t * pObj, * pCtrl, * pData0, * pData1; int i, Id; Vec_FltFill( vRefs, Gia_ManAndNotBufNum(p), 0 ); Gia_ManForEachAnd( p, pObj, i ) { if ( Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) Vec_FltAddToEntry( vRefs, Vec_IntEntry(vOffsets, Gia_ObjFaninId0(pObj, i)), 1 ); if ( Gia_ObjIsBuf(pObj) ) continue; if ( Gia_ObjIsAndNotBuf(Gia_ObjFanin1(pObj)) ) Vec_FltAddToEntry( vRefs, Vec_IntEntry(vOffsets, Gia_ObjFaninId1(pObj, i)), 1 ); if ( p->pMuxes ) { if ( Gia_ObjIsMuxId(p, i) && Gia_ObjIsAndNotBuf(Gia_ObjFanin2(p, pObj)) ) Vec_FltAddToEntry( vRefs, Vec_IntEntry(vOffsets, Gia_ObjFaninId2(p, i)), 1 ); } else if ( fDiscount && Gia_ObjIsMuxType(pObj) ) // discount XOR/MUX { pCtrl = Gia_Regular(Gia_ObjRecognizeMux(pObj, &pData1, &pData0)); pData0 = Gia_Regular(pData0); pData1 = Gia_Regular(pData1); if ( Gia_ObjIsAndNotBuf(pCtrl) ) Vec_FltAddToEntry( vRefs, Vec_IntEntry(vOffsets, Gia_ObjId(p, pCtrl)), -1 ); if ( pData0 == pData1 && Gia_ObjIsAndNotBuf(pData0) ) Vec_FltAddToEntry( vRefs, Vec_IntEntry(vOffsets, Gia_ObjId(p, pData0)), -1 ); } } Gia_ManForEachCoDriverId( p, Id, i ) if ( Gia_ObjIsAndNotBuf(Gia_ManObj(p, Id)) ) Vec_FltAddToEntry( vRefs, Vec_IntEntry(vOffsets, Id), 1 ); for ( i = 0; i < Vec_FltSize(vRefs); i++ ) Vec_FltUpdateEntry( vRefs, i, 1 ); } void Lf_ManSetCutRefs( Lf_Man_t * p ) { Gia_Obj_t * pObj; int i; if ( Vec_PtrSize(&p->vMemSets) * (1 << LF_LOG_PAGE) != Vec_IntSize(&p->vFreeSets) ) printf( "The number of used cutsets = %d.\n", Vec_PtrSize(&p->vMemSets) * (1 << LF_LOG_PAGE) - Vec_IntSize(&p->vFreeSets) ); Gia_ManForEachAnd( p->pGia, pObj, i ) { assert( pObj->Value == 0 ); if ( Gia_ObjIsBuf(pObj) ) continue; if ( Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) Gia_ObjFanin0(pObj)->Value++; if ( Gia_ObjIsAndNotBuf(Gia_ObjFanin1(pObj)) ) Gia_ObjFanin1(pObj)->Value++; if ( Gia_ObjIsMuxId(p->pGia, i) && Gia_ObjIsAndNotBuf(Gia_ObjFanin2(p->pGia, pObj)) ) Gia_ObjFanin2(p->pGia, pObj)->Value++; if ( Gia_ObjSibl(p->pGia, i) && Gia_ObjIsAndNotBuf(Gia_ObjSiblObj(p->pGia, i)) ) Gia_ObjSiblObj(p->pGia, i)->Value++; } } static inline int Lf_ManSetMuxCut( Lf_Man_t * p, Lf_Bst_t * pBest, int iObj, int Required ) { Gia_Obj_t * pMux; if ( !Gia_ObjIsMuxId(p->pGia, iObj) ) return 0; if ( pBest->Delay[2] > Required ) return 0; if ( pBest->Flow[2] > 1.1 * pBest->Flow[1] ) return 0; pMux = Gia_ManObj(p->pGia, iObj); if ( pMux->fMark0 || Gia_ObjFanin0(pMux)->fMark0 || Gia_ObjFanin1(pMux)->fMark0 ) return 0; Gia_ObjFanin0(pMux)->fMark0 = 1; Gia_ObjFanin1(pMux)->fMark0 = 1; return 1; } void Lf_ManSetMapRefsOne( Lf_Man_t * p, int iObj ) { Lf_Cut_t * pCut; Lf_Bst_t * pBest = Lf_ObjReadBest( p, iObj ); int k, Index, Required = Lf_ObjRequired( p, iObj ); assert( Lf_ObjMapRefNum(p, iObj) > 0 ); assert( !pBest->Cut[0].fUsed && !pBest->Cut[1].fUsed ); if ( !p->pPars->fUseMux7 || !Lf_ManSetMuxCut(p, pBest, iObj, Required) ) { Index = (int)(Lf_BestDiffCuts(pBest) && pBest->Delay[1] <= Required); pBest->Cut[Index].fUsed = 1; } pCut = Lf_ObjCutBest( p, iObj ); assert( !pCut->fMux7 || pCut->nLeaves == 3 ); // assert( pCut->Delay <= Required ); for ( k = 0; k < (int)pCut->nLeaves; k++ ) { // if ( pCut->fMux7 && pCut->pLeaves[k] != Gia_ObjFaninId2(p->pGia, iObj) ) // Lf_ObjSetRequired( p, pCut->pLeaves[k], Required ); // else Lf_ObjSetRequired( p, pCut->pLeaves[k], Required - 1 ); if ( Gia_ObjIsAndNotBuf(Gia_ManObj(p->pGia, pCut->pLeaves[k])) ) Lf_ObjMapRefInc( p, pCut->pLeaves[k] ); } if ( pCut->fMux7 ) { p->pPars->Mux7++; p->pPars->Edge++; return; } if ( Vec_FltSize(&p->vSwitches) ) p->Switches += Lf_CutSwitches(p, pCut); p->pPars->Edge += pCut->nLeaves; p->pPars->Area++; } int Lf_ManSetMapRefs( Lf_Man_t * p ) { float Coef = 1.0 / (1.0 + (p->Iter + 1) * (p->Iter + 1)); float * pFlowRefs; int * pMapRefs, i; Gia_Obj_t * pObj; // compute delay int Delay = 0; for ( i = 0; i < Gia_ManCoNum(p->pGia); i++ ) Delay = Abc_MaxInt( Delay, Lf_ObjCoArrival(p, i) ); // check delay target if ( p->pPars->DelayTarget == -1 && p->pPars->nRelaxRatio ) p->pPars->DelayTarget = (int)((float)Delay * (100.0 + p->pPars->nRelaxRatio) / 100.0); if ( p->pPars->DelayTarget != -1 ) { if ( Delay < p->pPars->DelayTarget + 0.01 ) Delay = p->pPars->DelayTarget; else if ( p->pPars->nRelaxRatio == 0 ) Abc_Print( 0, "Relaxing user-specified delay target from %d to %d.\n", p->pPars->DelayTarget, Delay ); } p->pPars->Delay = Delay; // compute area/edges/required p->pPars->Mux7 = p->pPars->Area = p->pPars->Edge = p->Switches = 0; Vec_IntFill( &p->vMapRefs, Gia_ManAndNotBufNum(p->pGia), 0 ); Vec_IntFill( &p->vRequired, Gia_ManObjNum(p->pGia), ABC_INFINITY ); if ( p->pPars->fUseMux7 ) { Gia_ManCleanMark0(p->pGia); Gia_ManForEachCi( p->pGia, pObj, i ) pObj->fMark0 = 1; } if ( p->pGia->pManTime != NULL ) { 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++ ) Tim_ManSetCoRequired( (Tim_Man_t*)p->pGia->pManTime, i, (int)(Lf_ObjCoArrival(p, i) * (100.0 + p->pPars->nRelaxRatio) / 100.0) ); else Tim_ManInitPoRequiredAll( (Tim_Man_t*)p->pGia->pManTime, Delay ); Gia_ManForEachObjReverse1( p->pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) ) Lf_ObjSetRequired( p, Gia_ObjFaninId0(pObj, i), Lf_ObjRequired(p, i) ); else if ( Gia_ObjIsAnd(pObj) ) { if ( Lf_ObjMapRefNum(p, i) ) Lf_ManSetMapRefsOne( p, i ); } else if ( Gia_ObjIsCi(pObj) ) Tim_ManSetCiRequired( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj), Lf_ObjRequired(p, i) ); else if ( Gia_ObjIsCo(pObj) ) { int iDriverId = Gia_ObjFaninId0(pObj, i); int reqTime = Tim_ManGetCoRequired( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj) ); Lf_ObjSetRequired( p, iDriverId, reqTime ); if ( Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) Lf_ObjMapRefInc( p, iDriverId ); } else assert( 0 ); } } else { Gia_ManForEachCo( p->pGia, pObj, i ) { int iDriverId = Gia_ObjFaninId0p(p->pGia, pObj); int reqTime = p->pPars->fDoAverage ? (int)(Lf_ObjCoArrival(p, i) * (100.0 + p->pPars->nRelaxRatio) / 100.0) : Delay; Lf_ObjSetRequired( p, iDriverId, reqTime ); if ( Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) Lf_ObjMapRefInc( p, iDriverId ); } Gia_ManForEachAndReverse( p->pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) ) { Lf_ObjSetRequired( p, Gia_ObjFaninId0(pObj, i), Lf_ObjRequired(p, i) ); if ( Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) Lf_ObjMapRefInc( p, Gia_ObjFaninId0(pObj, i) ); } else if ( Lf_ObjMapRefNum(p, i) ) Lf_ManSetMapRefsOne( p, i ); } } if ( p->pPars->fUseMux7 ) Gia_ManCleanMark0(p->pGia); // blend references assert( Vec_IntSize(&p->vMapRefs) == Gia_ManAndNotBufNum(p->pGia) ); assert( Vec_FltSize(&p->vFlowRefs) == Gia_ManAndNotBufNum(p->pGia) ); pMapRefs = Vec_IntArray(&p->vMapRefs); pFlowRefs = Vec_FltArray(&p->vFlowRefs); for ( i = 0; i < Vec_IntSize(&p->vMapRefs); i++ ) pFlowRefs[i] = Coef * pFlowRefs[i] + (1.0 - Coef) * Abc_MaxFloat(1, pMapRefs[i]); // pFlowRefs[i] = 0.2 * pFlowRefs[i] + 0.8 * Abc_MaxFloat(1, pMapRefs[i]); return p->pPars->Area; } void Lf_ManCountMapRefsOne( Lf_Man_t * p, int iObj ) { Lf_Bst_t * pBest = Lf_ObjReadBest( p, iObj ); Lf_Cut_t * pCut = Lf_ObjCutBest( p, iObj ); int k ,Required = Lf_ObjRequired( p, iObj ); assert( Lf_ObjMapRefNum(p, iObj) > 0 ); assert( Lf_BestIsMapped(pBest) ); assert( !pCut->fMux7 ); // assert( pCut->Delay <= Required ); for ( k = 0; k < (int)pCut->nLeaves; k++ ) Lf_ObjSetRequired( p, pCut->pLeaves[k], Required - 1 ); if ( Vec_FltSize(&p->vSwitches) ) p->Switches += Lf_CutSwitches(p, pCut); p->pPars->Edge += pCut->nLeaves; p->pPars->Area++; } void Lf_ManCountMapRefs( Lf_Man_t * p ) { // compute delay Gia_Obj_t * pObj; int i, Id, Delay = 0; for ( i = 0; i < Gia_ManCoNum(p->pGia); i++ ) Delay = Abc_MaxInt( Delay, Lf_ObjCoArrival2(p, i) ); // check delay target if ( p->pPars->DelayTarget == -1 && p->pPars->nRelaxRatio ) p->pPars->DelayTarget = (int)((float)Delay * (100.0 + p->pPars->nRelaxRatio) / 100.0); if ( p->pPars->DelayTarget != -1 ) { if ( Delay < p->pPars->DelayTarget + 0.01 ) Delay = p->pPars->DelayTarget; else if ( p->pPars->nRelaxRatio == 0 ) Abc_Print( 0, "Relaxing user-specified delay target from %d to %d.\n", p->pPars->DelayTarget, Delay ); } p->pPars->Delay = Delay; // compute area/edges/required p->pPars->Mux7 = p->pPars->Area = p->pPars->Edge = p->Switches = 0; Vec_IntFill( &p->vRequired, Gia_ManObjNum(p->pGia), ABC_INFINITY ); if ( p->pPars->fUseMux7 ) Gia_ManCleanMark0(p->pGia); if ( p->pGia->pManTime != NULL ) { Tim_ManIncrementTravId( (Tim_Man_t*)p->pGia->pManTime ); if ( p->pPars->fDoAverage ) for ( i = 0; i < Gia_ManCoNum(p->pGia); i++ ) Tim_ManSetCoRequired( (Tim_Man_t*)p->pGia->pManTime, i, (int)(Lf_ObjCoArrival(p, i) * (100.0 + p->pPars->nRelaxRatio) / 100.0) ); else Tim_ManInitPoRequiredAll( (Tim_Man_t*)p->pGia->pManTime, Delay ); Gia_ManForEachObjReverse1( p->pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) ) Lf_ObjSetRequired( p, Gia_ObjFaninId0(pObj, i), Lf_ObjRequired(p, i) ); else if ( Gia_ObjIsAnd(pObj) ) { if ( Lf_ObjMapRefNum(p, i) ) Lf_ManCountMapRefsOne( p, i ); } else if ( Gia_ObjIsCi(pObj) ) Tim_ManSetCiRequired( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj), Lf_ObjRequired(p, i) ); else if ( Gia_ObjIsCo(pObj) ) { int reqTime = Tim_ManGetCoRequired( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj) ); Lf_ObjSetRequired( p, Gia_ObjFaninId0(pObj, i), reqTime ); } else assert( 0 ); } } else { Gia_ManForEachCoDriverId( p->pGia, Id, i ) Lf_ObjSetRequired( p, Id, p->pPars->fDoAverage ? (int)(Lf_ObjCoArrival(p, i) * (100.0 + p->pPars->nRelaxRatio) / 100.0) : Delay ); Gia_ManForEachAndReverse( p->pGia, pObj, i ) if ( Gia_ObjIsBuf(pObj) ) Lf_ObjSetRequired( p, Gia_ObjFaninId0(pObj, i), Lf_ObjRequired(p, i) ); else if ( Lf_ObjMapRefNum(p, i) ) Lf_ManCountMapRefsOne( p, i ); } if ( p->pPars->fUseMux7 ) Gia_ManCleanMark0(p->pGia); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Lf_ManDeriveMapping( Lf_Man_t * p ) { Vec_Int_t * vMapping; Lf_Cut_t * pCut; int i, k; assert( !p->pPars->fCutMin && p->pGia->vMapping == NULL ); vMapping = Vec_IntAlloc( Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); Vec_IntFill( vMapping, Gia_ManObjNum(p->pGia), 0 ); Gia_ManForEachAndId( p->pGia, i ) { if ( !Lf_ObjMapRefNum(p, i) ) continue; assert( !Gia_ObjIsBuf(Gia_ManObj(p->pGia,i)) ); pCut = Lf_ObjCutBest( p, i ); assert( !pCut->fMux7 ); Vec_IntWriteEntry( vMapping, i, Vec_IntSize(vMapping) ); Vec_IntPush( vMapping, pCut->nLeaves ); for ( k = 0; k < (int)pCut->nLeaves; k++ ) Vec_IntPush( vMapping, pCut->pLeaves[k] ); Vec_IntPush( vMapping, i ); } assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); p->pGia->vMapping = vMapping; return p->pGia; } Gia_Man_t * Lf_ManDeriveMappingCoarse( Lf_Man_t * p ) { Gia_Man_t * pNew, * pGia = p->pGia; Gia_Obj_t * pObj; Lf_Cut_t * pCut; int i, k; assert( !p->pPars->fCutMin && pGia->pMuxes ); // create new manager pNew = Gia_ManStart( Gia_ManObjNum(pGia) ); pNew->pName = Abc_UtilStrsav( pGia->pName ); pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); // start mapping pNew->vMapping = Vec_IntAlloc( Gia_ManObjNum(pGia) + 2*Gia_ManXorNum(pGia) + 2*Gia_ManMuxNum(pGia) + (int)p->pPars->Edge + 2*(int)p->pPars->Area + 4*(int)p->pPars->Mux7 ); Vec_IntFill( pNew->vMapping, Gia_ManObjNum(pGia) + 2*Gia_ManXorNum(pGia) + 2*Gia_ManMuxNum(pGia), 0 ); // process objects Gia_ManConst0(pGia)->Value = 0; Gia_ManForEachObj1( pGia, pObj, i ) { if ( Gia_ObjIsCi(pObj) ) { pObj->Value = Gia_ManAppendCi( pNew ); continue; } if ( Gia_ObjIsCo(pObj) ) { pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); continue; } if ( Gia_ObjIsBuf(pObj) ) { pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); continue; } if ( Gia_ObjIsMuxId(pGia, i) ) pObj->Value = Gia_ManAppendMux( pNew, Gia_ObjFanin2Copy(pGia, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); else 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) ); if ( !Lf_ObjMapRefNum(p, i) ) continue; pCut = Lf_ObjCutBest( p, i ); Vec_IntWriteEntry( pNew->vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(pNew->vMapping) ); Vec_IntPush( pNew->vMapping, pCut->nLeaves ); for ( k = 0; k < (int)pCut->nLeaves; k++ ) Vec_IntPush( pNew->vMapping, Abc_Lit2Var(Gia_ManObj(pGia, pCut->pLeaves[k])->Value) ); Vec_IntPush( pNew->vMapping, pCut->fMux7 ? -Abc_Lit2Var(pObj->Value) : Abc_Lit2Var(pObj->Value) ); } Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); assert( Vec_IntCap(pNew->vMapping) == 16 || Vec_IntSize(pNew->vMapping) == Vec_IntCap(pNew->vMapping) ); return pNew; } static inline int Lf_ManDerivePart( Lf_Man_t * p, Gia_Man_t * pNew, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vCopies, Lf_Cut_t * pCut, Vec_Int_t * vLeaves, Vec_Int_t * vCover, Gia_Obj_t * pObj ) { word * pTruth; int k, iLit, iTemp; if ( p->pPars->nLutSizeMux && p->pPars->nLutSizeMux == (int)pCut->nLeaves ) { word pTruthCof[LF_TT_WORDS], * pTruth = Lf_CutTruth( p, pCut ); int pVarsNew[LF_LEAF_MAX], nVarsNew, iLitCofs[2]; int LutSize = p->pPars->nLutSize; int nWords = Abc_Truth6WordNum(LutSize); int c, iVar = Lf_ManFindCofVar( pTruth, nWords, pCut->nLeaves ); assert( iVar >= 0 && iVar < (int)pCut->nLeaves ); for ( c = 0; c < 2; c++ ) { for ( k = 0; k < (int)pCut->nLeaves; k++ ) pVarsNew[k] = k; if ( c ) Abc_TtCofactor1p( pTruthCof, pTruth, nWords, iVar ); else Abc_TtCofactor0p( pTruthCof, pTruth, nWords, iVar ); nVarsNew = Abc_TtMinBase( pTruthCof, pVarsNew, pCut->nLeaves, LutSize ); assert( nVarsNew > 0 ); // derive LUT Vec_IntClear( vLeaves ); for ( k = 0; k < nVarsNew; k++ ) Vec_IntPush( vLeaves, Vec_IntEntry(vCopies, pCut->pLeaves[pVarsNew[k]]) ); iLitCofs[c] = Kit_TruthToGia( pNew, (unsigned *)pTruthCof, nVarsNew, vCover, vLeaves, 0 ); // create mapping Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLitCofs[c]), Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); Vec_IntForEachEntry( vLeaves, iTemp, k ) Vec_IntPush( vMapping2, Abc_Lit2Var(iTemp) ); Vec_IntPush( vMapping2, Abc_Lit2Var(iLitCofs[c]) ); } // derive MUX pTruthCof[0] = ABC_CONST(0xCACACACACACACACA); Vec_IntClear( vLeaves ); Vec_IntPush( vLeaves, iLitCofs[0] ); Vec_IntPush( vLeaves, iLitCofs[1] ); Vec_IntPush( vLeaves, Vec_IntEntry(vCopies, pCut->pLeaves[iVar]) ); iLit = Kit_TruthToGia( pNew, (unsigned *)pTruthCof, Vec_IntSize(vLeaves), vCover, vLeaves, 0 ); // create mapping Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLit), Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); Vec_IntForEachEntry( vLeaves, iTemp, k ) Vec_IntPush( vMapping2, Abc_Lit2Var(iTemp) ); Vec_IntPush( vMapping2, -Abc_Lit2Var(iLit) ); return iLit; } Vec_IntClear( vLeaves ); if ( pCut->fMux7 ) { assert( pCut->nLeaves == 3 ); Vec_IntPush( vLeaves, Abc_LitNotCond(Vec_IntEntry(vCopies, pCut->pLeaves[0]), Gia_ObjFaninC0(pObj)) ); Vec_IntPush( vLeaves, Abc_LitNotCond(Vec_IntEntry(vCopies, pCut->pLeaves[1]), Gia_ObjFaninC1(pObj)) ); Vec_IntPush( vLeaves, Abc_LitNotCond(Vec_IntEntry(vCopies, pCut->pLeaves[2]), Gia_ObjFaninC2(p->pGia,pObj)) ); } else { for ( k = 0; k < (int)pCut->nLeaves; k++ ) Vec_IntPush( vLeaves, Vec_IntEntry(vCopies, pCut->pLeaves[k]) ); } pTruth = Lf_CutTruth( p, pCut ); iLit = Kit_TruthToGia( pNew, (unsigned *)pTruth, Vec_IntSize(vLeaves), vCover, vLeaves, 0 ); // create mapping Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLit), Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); Vec_IntForEachEntry( vLeaves, iTemp, k ) Vec_IntPush( vMapping2, Abc_Lit2Var(iTemp) ); Vec_IntPush( vMapping2, pCut->fMux7 ? -Abc_Lit2Var(iLit) : Abc_Lit2Var(iLit) ); return iLit; } Gia_Man_t * Lf_ManDeriveMappingGia( Lf_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; Vec_Int_t * vCopies = Vec_IntStartFull( Gia_ManObjNum(p->pGia) ); Vec_Int_t * vMapping = Vec_IntStart( 2*Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + 2*(int)p->pPars->Area + 4*(int)p->pPars->Mux7 ); Vec_Int_t * vMapping2 = Vec_IntStart( (int)p->pPars->Edge + 2*(int)p->pPars->Area + 1000 ); Vec_Int_t * vCover = Vec_IntAlloc( 1 << 16 ); Vec_Int_t * vLeaves = Vec_IntAlloc( 16 ); Lf_Cut_t * pCut; int i, iLit; assert( p->pPars->fCutMin ); // create new manager pNew = Gia_ManStart( Gia_ManObjNum(p->pGia) ); pNew->pName = Abc_UtilStrsav( p->pGia->pName ); pNew->pSpec = Abc_UtilStrsav( p->pGia->pSpec ); Vec_IntWriteEntry( vCopies, 0, 0 ); Gia_ManForEachObj1( p->pGia, pObj, i ) { if ( Gia_ObjIsCi(pObj) ) { Vec_IntWriteEntry( vCopies, i, Gia_ManAppendCi(pNew) ); continue; } if ( Gia_ObjIsCo(pObj) ) { iLit = Vec_IntEntry( vCopies, Gia_ObjFaninId0p(p->pGia, pObj) ); iLit = Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); continue; } if ( Gia_ObjIsBuf(pObj) ) { iLit = Vec_IntEntry( vCopies, Gia_ObjFaninId0p(p->pGia, pObj) ); iLit = Gia_ManAppendBuf( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); Vec_IntWriteEntry( vCopies, i, iLit ); continue; } if ( !Lf_ObjMapRefNum(p, i) ) continue; pCut = Lf_ObjCutBest( p, i ); assert( pCut->iFunc >= 0 ); if ( pCut->nLeaves == 0 ) { assert( Abc_Lit2Var(pCut->iFunc) == 0 ); Vec_IntWriteEntry( vCopies, i, pCut->iFunc ); continue; } if ( pCut->nLeaves == 1 ) { assert( Abc_Lit2Var(pCut->iFunc) == 1 ); iLit = Vec_IntEntry( vCopies, pCut->pLeaves[0] ); Vec_IntWriteEntry( vCopies, i, Abc_LitNotCond(iLit, Abc_LitIsCompl(pCut->iFunc)) ); continue; } iLit = Lf_ManDerivePart( p, pNew, vMapping, vMapping2, vCopies, pCut, vLeaves, vCover, pObj ); Vec_IntWriteEntry( vCopies, i, Abc_LitNotCond(iLit, Abc_LitIsCompl(pCut->iFunc)) ); } Vec_IntFree( vCopies ); Vec_IntFree( vCover ); Vec_IntFree( vLeaves ); // finish mapping if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) ) Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) ); else Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 ); assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) ); Vec_IntForEachEntry( vMapping, iLit, i ) if ( iLit > 0 ) Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) ); Vec_IntAppend( vMapping, vMapping2 ); Vec_IntFree( vMapping2 ); // attach mapping and packing assert( pNew->vMapping == NULL ); pNew->vMapping = vMapping; Gia_ManSetRegNum( pNew, Gia_ManRegNum(p->pGia) ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Lf_Man_t * Lf_ManAlloc( Gia_Man_t * pGia, Jf_Par_t * pPars ) { Lf_Man_t * p; int i, k = 0; assert( pPars->nCutNum > 1 && pPars->nCutNum <= LF_CUT_MAX ); assert( pPars->nLutSize > 1 && pPars->nLutSize <= LF_LEAF_MAX ); ABC_FREE( pGia->pRefs ); Vec_IntFreeP( &pGia->vMapping ); Gia_ManCleanValue( pGia ); if ( Gia_ManHasChoices(pGia) ) Gia_ManSetPhase(pGia); p = ABC_CALLOC( Lf_Man_t, 1 ); Lf_ManAnalyzeCoDrivers( pGia, &p->nCoDrivers, &p->nInverters ); if ( pPars->fPower ) Lf_ManComputeSwitching( pGia, &p->vSwitches ); p->clkStart = Abc_Clock(); p->pGia = pGia; p->pPars = pPars; p->nCutWords = (sizeof(Lf_Cut_t)/sizeof(int) + pPars->nLutSize + 1) >> 1; p->nSetWords = p->nCutWords * pPars->nCutNum; p->vTtMem = pPars->fCutMin ? Vec_MemAllocForTT( pPars->nLutSize, 0 ) : NULL; if ( pPars->fCutMin && pPars->fUseMux7 ) Vec_MemAddMuxTT( p->vTtMem, pPars->nLutSize ); p->pObjBests = ABC_CALLOC( Lf_Bst_t, Gia_ManAndNotBufNum(pGia) ); Vec_IntGrow( &p->vFreeSets, (1<<14) ); Vec_PtrGrow( &p->vFreePages, 256 ); Lf_MemAlloc( &p->vStoreOld, 16, &p->vFreePages, p->nCutWords ); Lf_MemAlloc( &p->vStoreNew, 16, &p->vFreePages, p->nCutWords ); Vec_IntFill( &p->vOffsets, Gia_ManObjNum(pGia), -1 ); Vec_IntFill( &p->vRequired, Gia_ManObjNum(pGia), ABC_INFINITY ); Vec_IntFill( &p->vCutSets, Gia_ManAndNotBufNum(pGia), -1 ); Vec_FltFill( &p->vFlowRefs, Gia_ManAndNotBufNum(pGia), 0 ); Vec_IntFill( &p->vMapRefs, Gia_ManAndNotBufNum(pGia), 0 ); Vec_IntFill( &p->vCiArrivals, Gia_ManCiNum(pGia), 0 ); Gia_ManForEachAndId( pGia, i ) if ( !Gia_ObjIsBuf(Gia_ManObj(pGia, i)) ) Vec_IntWriteEntry( &p->vOffsets, i, k++ ); assert( k == Gia_ManAndNotBufNum(pGia) ); Lf_ManSetFlowRefs( pGia, &p->vFlowRefs, &p->vOffsets ); if ( pPars->pTimesArr ) for ( i = 0; i < Gia_ManPiNum(pGia); i++ ) Vec_IntWriteEntry( &p->vCiArrivals, i, pPars->pTimesArr[i] ); return p; } void Lf_ManFree( Lf_Man_t * p ) { ABC_FREE( p->pPars->pTimesArr ); ABC_FREE( p->pPars->pTimesReq ); if ( p->pPars->fCutMin ) Vec_MemHashFree( p->vTtMem ); if ( p->pPars->fCutMin ) Vec_MemFree( p->vTtMem ); Vec_PtrFreeData( &p->vMemSets ); Vec_PtrFreeData( &p->vFreePages ); Vec_PtrFreeData( &p->vStoreOld.vPages ); Vec_PtrFreeData( &p->vStoreNew.vPages ); ABC_FREE( p->vMemSets.pArray ); ABC_FREE( p->vFreePages.pArray ); ABC_FREE( p->vStoreOld.vPages.pArray ); ABC_FREE( p->vStoreNew.vPages.pArray ); ABC_FREE( p->vFreePages.pArray ); ABC_FREE( p->vFreeSets.pArray ); ABC_FREE( p->vOffsets.pArray ); ABC_FREE( p->vRequired.pArray ); ABC_FREE( p->vCutSets.pArray ); ABC_FREE( p->vFlowRefs.pArray ); ABC_FREE( p->vMapRefs.pArray ); ABC_FREE( p->vSwitches.pArray ); ABC_FREE( p->vCiArrivals.pArray ); ABC_FREE( p->pObjBests ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Lf_ManSetDefaultPars( Jf_Par_t * pPars ) { memset( pPars, 0, sizeof(Jf_Par_t) ); pPars->nLutSize = 6; pPars->nCutNum = 8; pPars->nProcNum = 0; pPars->nRounds = 4; pPars->nRoundsEla = 1; pPars->nRelaxRatio = 0; pPars->nCoarseLimit = 3; pPars->nAreaTuner = 1; pPars->nVerbLimit = 5; pPars->DelayTarget = -1; pPars->fAreaOnly = 0; pPars->fOptEdge = 1; pPars->fUseMux7 = 0; pPars->fPower = 0; pPars->fCoarsen = 1; pPars->fCutMin = 0; pPars->fFuncDsd = 0; pPars->fGenCnf = 0; pPars->fPureAig = 0; pPars->fCutHashing = 0; pPars->fCutSimple = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; pPars->nLutSizeMax = LF_LEAF_MAX; pPars->nCutNumMax = LF_CUT_MAX; } void Lf_ManPrintStats( Lf_Man_t * p, char * pTitle ) { if ( !p->pPars->fVerbose ) return; printf( "%s : ", pTitle ); printf( "Level =%6lu ", (long)p->pPars->Delay ); printf( "Area =%9lu ", (long)p->pPars->Area ); printf( "Edge =%9lu ", (long)p->pPars->Edge ); printf( "LUT =%9lu ", (long)p->pPars->Area+p->nInverters ); if ( Vec_FltSize(&p->vSwitches) ) printf( "Swt =%8.1f ", p->Switches ); if ( p->pPars->fUseMux7 ) printf( "Mux7 =%7lu ", (long)p->pPars->Mux7 ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); fflush( stdout ); } void Lf_ManPrintInit( Lf_Man_t * p ) { if ( !p->pPars->fVerbose ) return; printf( "LutSize = %d ", p->pPars->nLutSize ); printf( "CutNum = %d ", p->pPars->nCutNum ); printf( "Iter = %d ", p->pPars->nRounds + p->pPars->nRoundsEla ); if ( p->pPars->nRelaxRatio ) printf( "Ratio = %d ", p->pPars->nRelaxRatio ); printf( "Edge = %d ", p->pPars->fOptEdge ); if ( p->pPars->DelayTarget != -1 ) printf( "Delay = %d ", p->pPars->DelayTarget ); printf( "CutMin = %d ", p->pPars->fCutMin ); printf( "Coarse = %d ", p->pPars->fCoarsen ); printf( "Cut/Set = %d/%d Bytes", 8*p->nCutWords, 8*p->nSetWords ); printf( "\n" ); printf( "Computing cuts...\r" ); fflush( stdout ); } void Lf_ManPrintQuit( Lf_Man_t * p, Gia_Man_t * pNew ) { float MemGia = Gia_ManMemory(p->pGia) / (1<<20); float MemMan = 1.0 * sizeof(int) * (2 * Gia_ManObjNum(p->pGia) + 3 * Gia_ManAndNotBufNum(p->pGia)) / (1<<20); // offset, required, cutsets, maprefs, flowrefs float MemCutsB = 1.0 * (p->vStoreOld.MaskPage + 1) * (Vec_PtrSize(&p->vFreePages) + Vec_PtrSize(&p->vStoreOld.vPages)) / (1<<20) + 1.0 * sizeof(Lf_Bst_t) * Gia_ManAndNotBufNum(p->pGia) / (1<<20); float MemCutsF = 1.0 * sizeof(word) * p->nSetWords * (1<vMemSets) / (1<<20); float MemTt = p->vTtMem ? Vec_MemMemory(p->vTtMem) / (1<<20) : 0; float MemMap = Vec_IntMemory(pNew->vMapping) / (1<<20); if ( p->CutCount[0] == 0 ) p->CutCount[0] = 1; if ( !p->pPars->fVerbose ) { int i, CountOver[2] = {0}; int nLutSize = p->pPars->fCutGroup ? p->pPars->nLutSize/2 : p->pPars->nLutSize; Gia_ManForEachLut( pNew, i ) CountOver[Gia_ObjLutSize(pNew, i) > nLutSize]++; if ( p->pPars->fCutGroup ) printf( "Created %d regular %d-LUTs and %d dual %d-LUTs. The total of %d %d-LUTs.\n", CountOver[0], nLutSize, CountOver[1], nLutSize, CountOver[0] + 2*CountOver[1], nLutSize ); return; } 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( "\n" ); printf( "Gia = %.2f MB ", MemGia ); printf( "Man = %.2f MB ", MemMan ); printf( "Best = %.2f MB ", MemCutsB ); printf( "Front = %.2f MB ", MemCutsF ); printf( "Map = %.2f MB ", MemMap ); printf( "TT = %.2f MB ", MemTt ); printf( "Total = %.2f MB", MemGia + MemMan + MemCutsB + MemCutsF + MemMap + MemTt ); printf( "\n" ); if ( 1 ) { int i; for ( i = 0; i <= p->pPars->nLutSize; i++ ) printf( "%d:%d ", i, p->nCutCounts[i] ); printf( "Equal = %d (%.0f %%) ", p->nCutEqual, 100.0 * p->nCutEqual / p->Iter / Gia_ManAndNotBufNum(p->pGia) ); if ( p->vTtMem ) printf( "TT = %d (%.2f %%) ", Vec_MemEntryNum(p->vTtMem), 100.0 * Vec_MemEntryNum(p->vTtMem) / p->CutCount[2] ); if ( p->pGia->pMuxes && p->nCutMux ) printf( "MuxTT = %d (%.0f %%) ", p->nCutMux, 100.0 * p->nCutMux / p->Iter / Gia_ManMuxNum(p->pGia) ); printf( "\n" ); } printf( "CoDrvs = %d (%.2f %%) ", p->nCoDrivers, 100.0*p->nCoDrivers/Gia_ManCoNum(p->pGia) ); printf( "CoInvs = %d (%.2f %%) ", p->nInverters, 100.0*p->nInverters/Gia_ManCoNum(p->pGia) ); printf( "Front = %d (%.2f %%) ", p->nFrontMax, 100.0*p->nFrontMax/Gia_ManAndNum(p->pGia) ); printf( "TimeFails = %d ", p->nTimeFails ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); fflush( stdout ); } void Lf_ManComputeMapping( Lf_Man_t * p ) { Gia_Obj_t * pObj; int i, arrTime; assert( p->vStoreNew.iCur == 0 ); Lf_ManSetCutRefs( p ); if ( p->pGia->pManTime != NULL ) { assert( !Gia_ManBufNum(p->pGia) ); Tim_ManIncrementTravId( (Tim_Man_t*)p->pGia->pManTime ); Gia_ManForEachObj1( p->pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) ) continue; if ( Gia_ObjIsAnd(pObj) ) Lf_ObjMergeOrder( p, i ); else if ( Gia_ObjIsCi(pObj) ) { arrTime = Tim_ManGetCiArrival( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj) ); Lf_ObjSetCiArrival( p, Gia_ObjCioId(pObj), arrTime ); } else if ( Gia_ObjIsCo(pObj) ) { arrTime = Lf_ObjCoArrival( p, Gia_ObjCioId(pObj) ); Tim_ManSetCoArrival( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj), arrTime ); } else assert( 0 ); } // Tim_ManPrint( p->pGia->pManTime ); } else { Gia_ManForEachAnd( p->pGia, pObj, i ) if ( !Gia_ObjIsBuf(pObj) ) Lf_ObjMergeOrder( p, i ); } Lf_MemRecycle( &p->vStoreOld ); ABC_SWAP( Lf_Mem_t, p->vStoreOld, p->vStoreNew ); if ( p->fUseEla ) Lf_ManCountMapRefs( p ); else Lf_ManSetMapRefs( p ); Lf_ManPrintStats( p, (char *)(p->fUseEla ? "Ela " : (p->Iter ? "Area " : "Delay")) ); } Gia_Man_t * Lf_ManPerformMappingInt( Gia_Man_t * pGia, Jf_Par_t * pPars ) { int fUsePowerMode = 0; Lf_Man_t * p; Gia_Man_t * pNew, * pCls; if ( pPars->fUseMux7 ) pPars->fCoarsen = 1, pPars->nRoundsEla = 0; if ( Gia_ManHasChoices(pGia) || pPars->nLutSizeMux ) pPars->fCutMin = 1; if ( pPars->fCoarsen ) { pCls = Gia_ManDupMuxes(pGia, pPars->nCoarseLimit); pCls->pManTime = pGia->pManTime; pGia->pManTime = NULL; } else pCls = pGia; p = Lf_ManAlloc( pCls, pPars ); if ( pPars->fVerbose && pPars->fCoarsen ) { printf( "Initial " ); Gia_ManPrintMuxStats( pGia ); printf( "\n" ); printf( "Derived " ); Gia_ManPrintMuxStats( pCls ); printf( "\n" ); } Lf_ManPrintInit( p ); // power mode if ( fUsePowerMode && Vec_FltSize(&p->vSwitches) ) pPars->fPower = 0; // perform mapping for ( p->Iter = 0; p->Iter < p->pPars->nRounds; p->Iter++ ) Lf_ManComputeMapping( p ); p->fUseEla = 1; for ( ; p->Iter < p->pPars->nRounds + pPars->nRoundsEla; p->Iter++ ) Lf_ManComputeMapping( p ); // power mode if ( fUsePowerMode && Vec_FltSize(&p->vSwitches) ) { pPars->fPower = 1; for ( ; p->Iter < p->pPars->nRounds + pPars->nRoundsEla + 2; p->Iter++ ) Lf_ManComputeMapping( p ); } if ( pPars->fVeryVerbose && pPars->fCutMin ) Vec_MemDumpTruthTables( p->vTtMem, Gia_ManName(p->pGia), pPars->nLutSize ); if ( pPars->fCutMin ) pNew = Lf_ManDeriveMappingGia( p ); else if ( pPars->fCoarsen ) pNew = Lf_ManDeriveMappingCoarse( p ); else pNew = Lf_ManDeriveMapping( p ); Gia_ManMappingVerify( pNew ); Lf_ManPrintQuit( p, pNew ); Lf_ManFree( p ); if ( pCls != pGia ) { pGia->pManTime = pCls->pManTime; pCls->pManTime = NULL; Gia_ManStop( pCls ); } return pNew; } Gia_Man_t * Lf_ManPerformMapping( Gia_Man_t * p, Jf_Par_t * pPars ) { Gia_Man_t * pNew; if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) && Gia_ManIsNormalized(p) ) { Tim_Man_t * pTimOld = (Tim_Man_t *)p->pManTime; p->pManTime = Tim_ManDup( pTimOld, 1 ); pNew = Gia_ManDupUnnormalize( p ); if ( pNew == NULL ) return NULL; Gia_ManTransferTiming( pNew, p ); p = pNew; // mapping pNew = Lf_ManPerformMappingInt( p, pPars ); if ( pNew != p ) { Gia_ManTransferTiming( pNew, p ); Gia_ManStop( p ); } // normalize pNew = Gia_ManDupNormalize( p = pNew, 0 ); Gia_ManTransferMapping( pNew, p ); // Gia_ManTransferPacking( pNew, p ); Gia_ManTransferTiming( pNew, p ); Gia_ManStop( p ); // do not delete if the original one! // cleanup Tim_ManStop( (Tim_Man_t *)pNew->pManTime ); pNew->pManTime = pTimOld; assert( Gia_ManIsNormalized(pNew) ); } else { // mapping pNew = Lf_ManPerformMappingInt( p, pPars ); Gia_ManTransferTiming( pNew, p ); } return pNew; } /**Function************************************************************* Synopsis [Interface of LUT mapping package.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManPerformLfMapping( Gia_Man_t * p, Jf_Par_t * pPars, int fNormalized ) { Gia_Man_t * pNew; assert( !pPars->fCutGroup || pPars->nLutSize == 9 || pPars->nLutSize == 11 || pPars->nLutSize == 13 ); // reconstruct GIA according to the hierarchy manager assert( pPars->pTimesArr == NULL ); assert( pPars->pTimesReq == NULL ); if ( p->pManTime ) { if ( fNormalized ) { pNew = Gia_ManDupUnnormalize( p ); if ( pNew == NULL ) return NULL; Gia_ManTransferTiming( pNew, p ); p = pNew; // set arrival and required times pPars->pTimesArr = Tim_ManGetArrTimes( (Tim_Man_t *)p->pManTime ); pPars->pTimesReq = Tim_ManGetReqTimes( (Tim_Man_t *)p->pManTime ); } else p = Gia_ManDup( p ); } else p = Gia_ManDup( p ); // perform mapping pNew = Lf_ManPerformMappingInt( p, pPars ); if ( pNew != p ) { // transfer name ABC_FREE( pNew->pName ); ABC_FREE( pNew->pSpec ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // return the original (unmodified by the mapper) timing manager Gia_ManTransferTiming( pNew, p ); Gia_ManStop( p ); } // normalize and transfer mapping pNew = Gia_ManDupNormalize( p = pNew, 0 ); Gia_ManTransferMapping( pNew, p ); // Gia_ManTransferPacking( pNew, p ); Gia_ManTransferTiming( pNew, p ); Gia_ManStop( p ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaMan.c000066400000000000000000002363431477524141600156420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Package manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #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 #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern void Gia_ManDfsSlacksPrint( Gia_Man_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManStart( int nObjsMax ) { Gia_Man_t * p; assert( nObjsMax > 0 ); p = ABC_CALLOC( Gia_Man_t, 1 ); p->nObjsAlloc = nObjsMax; p->pObjs = ABC_CALLOC( Gia_Obj_t, nObjsMax ); p->pObjs->iDiff0 = p->pObjs->iDiff1 = GIA_NONE; p->nObjs = 1; p->vCis = Vec_IntAlloc( nObjsMax / 20 ); p->vCos = Vec_IntAlloc( nObjsMax / 20 ); return p; } /**Function************************************************************* Synopsis [Deletes AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManStop( Gia_Man_t * p ) { if ( p->vSeqModelVec ) Vec_PtrFreeFree( p->vSeqModelVec ); Gia_ManStaticFanoutStop( p ); Tim_ManStopP( (Tim_Man_t **)&p->pManTime ); 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 ); Vec_IntFreeP( &p->vCofVars ); Vec_IntFreeP( &p->vIdsOrig ); Vec_IntFreeP( &p->vIdsEquiv ); Vec_IntFreeP( &p->vLutConfigs ); Vec_IntFreeP( &p->vEdgeDelay ); Vec_IntFreeP( &p->vEdgeDelayR ); Vec_IntFreeP( &p->vEdge1 ); Vec_IntFreeP( &p->vEdge2 ); Vec_IntFreeP( &p->vUserPiIds ); Vec_IntFreeP( &p->vUserPoIds ); Vec_IntFreeP( &p->vUserFfIds ); Vec_IntFreeP( &p->vFlopClasses ); Vec_IntFreeP( &p->vGateClasses ); Vec_IntFreeP( &p->vObjClasses ); Vec_IntFreeP( &p->vInitClasses ); Vec_IntFreeP( &p->vRegClasses ); Vec_IntFreeP( &p->vRegInits ); Vec_IntFreeP( &p->vDoms ); Vec_IntFreeP( &p->vBarBufs ); Vec_IntFreeP( &p->vXors ); Vec_IntFreeP( &p->vLevels ); Vec_IntFreeP( &p->vTruths ); Vec_IntErase( &p->vCopies ); Vec_IntErase( &p->vCopies2 ); 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 ); Vec_WrdFreeP( &p->vTtMemory ); Vec_PtrFreeP( &p->vTtInputs ); Vec_IntFreeP( &p->vMapping ); Vec_WecFreeP( &p->vMapping2 ); Vec_WecFreeP( &p->vFanouts2 ); Vec_IntFreeP( &p->vCellMapping ); Vec_IntFreeP( &p->vPacking ); Vec_IntFreeP( &p->vConfigs ); ABC_FREE( p->pCellStr ); Vec_FltFreeP( &p->vInArrs ); Vec_FltFreeP( &p->vOutReqs ); Vec_IntFreeP( &p->vCiArrs ); 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 ); Vec_IntErase( &p->vHash ); Vec_IntErase( &p->vHTable ); Vec_IntErase( &p->vRefs ); Vec_StrFreeP( &p->vStopsF ); Vec_StrFreeP( &p->vStopsB ); ABC_FREE( p->pData2 ); ABC_FREE( p->pTravIds ); ABC_FREE( p->pPlacement ); ABC_FREE( p->pSwitching ); ABC_FREE( p->pCexSeq ); ABC_FREE( p->pCexComb ); ABC_FREE( p->pIso ); // ABC_FREE( p->pMapping ); ABC_FREE( p->pFanData ); ABC_FREE( p->pReprsOld ); ABC_FREE( p->pReprs ); ABC_FREE( p->pNexts ); ABC_FREE( p->pSibls ); ABC_FREE( p->pRefs ); ABC_FREE( p->pLutRefs ); ABC_FREE( p->pMuxes ); ABC_FREE( p->pObjs ); ABC_FREE( p->pSpec ); ABC_FREE( p->pName ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Returns memory used in megabytes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ double Gia_ManMemory( Gia_Man_t * p ) { double Memory = sizeof(Gia_Man_t); Memory += sizeof(Gia_Obj_t) * Gia_ManObjNum(p); Memory += sizeof(int) * Gia_ManCiNum(p); Memory += sizeof(int) * Gia_ManCoNum(p); Memory += sizeof(int) * Vec_IntSize(&p->vHTable); Memory += sizeof(int) * Gia_ManObjNum(p) * (p->pRefs != NULL); Memory += Vec_IntMemory( p->vLevels ); Memory += Vec_IntMemory( p->vCellMapping ); Memory += Vec_IntMemory( &p->vCopies ); Memory += Vec_FltMemory( p->vInArrs ); Memory += Vec_FltMemory( p->vOutReqs ); Memory += Vec_PtrMemory( p->vNamesIn ); Memory += Vec_PtrMemory( p->vNamesOut ); Memory += Vec_PtrMemory( p->vNamesNode ); return Memory; } /**Function************************************************************* Synopsis [Stops the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManStopP( Gia_Man_t ** p ) { if ( *p == NULL ) return; Gia_ManStop( *p ); *p = NULL; } /**Function************************************************************* Synopsis [Prints stats for the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintClasses_old( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; if ( p->vFlopClasses == NULL ) return; Gia_ManForEachRo( p, pObj, i ) Abc_Print( 1, "%d", Vec_IntEntry(p->vFlopClasses, i) ); Abc_Print( 1, "\n" ); { Gia_Man_t * pTemp; pTemp = Gia_ManDupFlopClass( p, 1 ); Gia_AigerWrite( pTemp, "dom1.aig", 0, 0, 0 ); Gia_ManStop( pTemp ); pTemp = Gia_ManDupFlopClass( p, 2 ); Gia_AigerWrite( pTemp, "dom2.aig", 0, 0, 0 ); Gia_ManStop( pTemp ); } } /**Function************************************************************* Synopsis [Prints stats for the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintPlacement( Gia_Man_t * p ) { int i, nFixed = 0, nUndef = 0; if ( p->pPlacement == NULL ) return; for ( i = 0; i < Gia_ManObjNum(p); i++ ) { nFixed += p->pPlacement[i].fFixed; nUndef += p->pPlacement[i].fUndef; } Abc_Print( 1, "Placement: Objects = %8d. Fixed = %8d. Undef = %8d.\n", Gia_ManObjNum(p), nFixed, nUndef ); } /**Function************************************************************* Synopsis [Duplicates AIG for unrolling.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintTents_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjs ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); Vec_IntPush( vObjs, Gia_ObjId(p, pObj) ); if ( Gia_ObjIsCi(pObj) ) return; Gia_ManPrintTents_rec( p, Gia_ObjFanin0(pObj), vObjs ); if ( Gia_ObjIsAnd(pObj) ) Gia_ManPrintTents_rec( p, Gia_ObjFanin1(pObj), vObjs ); } void Gia_ManPrintTents( Gia_Man_t * p ) { Vec_Int_t * vObjs; Gia_Obj_t * pObj; int t, i, iObjId, nSizePrev, nSizeCurr; assert( Gia_ManPoNum(p) > 0 ); vObjs = Vec_IntAlloc( 100 ); // save constant class Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); Vec_IntPush( vObjs, 0 ); // create starting root nSizePrev = Vec_IntSize(vObjs); Gia_ManForEachPo( p, pObj, i ) Gia_ManPrintTents_rec( p, pObj, vObjs ); // build tents Abc_Print( 1, "Tents: " ); for ( t = 1; nSizePrev < Vec_IntSize(vObjs); t++ ) { int nPis = 0; nSizeCurr = Vec_IntSize(vObjs); Vec_IntForEachEntryStartStop( vObjs, iObjId, i, nSizePrev, nSizeCurr ) { nPis += Gia_ObjIsPi(p, Gia_ManObj(p, iObjId)); if ( Gia_ObjIsRo(p, Gia_ManObj(p, iObjId)) ) Gia_ManPrintTents_rec( p, Gia_ObjRoToRi(p, Gia_ManObj(p, iObjId)), vObjs ); } Abc_Print( 1, "%d=%d(%d) ", t, nSizeCurr - nSizePrev, nPis ); nSizePrev = nSizeCurr; } Abc_Print( 1, " Unused=%d\n", Gia_ManObjNum(p) - Vec_IntSize(vObjs) ); Vec_IntFree( vObjs ); // the remaining objects are PIs without fanout // Gia_ManForEachObj( p, pObj, i ) // if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) // Gia_ObjPrint( p, pObj ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintInitClasses( Vec_Int_t * vInits ) { int i, Value; int Counts[6] = {0}; Vec_IntForEachEntry( vInits, Value, i ) Counts[Value]++; for ( i = 0; i < 6; i++ ) if ( Counts[i] ) printf( "%d = %d ", i, Counts[i] ); printf( " " ); printf( "B = %d ", Counts[0] + Counts[1] ); printf( "X = %d ", Counts[2] + Counts[3] ); printf( "Q = %d\n", Counts[4] + Counts[5] ); Vec_IntForEachEntry( vInits, Value, i ) { Counts[Value]++; if ( Value == 0 ) printf( "0" ); else if ( Value == 1 ) printf( "1" ); else if ( Value == 2 ) printf( "2" ); else if ( Value == 3 ) printf( "3" ); else if ( Value == 4 ) printf( "4" ); else if ( Value == 5 ) printf( "5" ); else assert( 0 ); } printf( "\n" ); } /**Function************************************************************* Synopsis [Prints stats for the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintChoiceStats( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, nEquivs = 0, nChoices = 0; Gia_ManMarkFanoutDrivers( p ); Gia_ManForEachAnd( p, pObj, i ) { if ( !Gia_ObjSibl(p, i) ) continue; nEquivs++; if ( pObj->fMark0 ) nChoices++; assert( !Gia_ObjSiblObj(p, i)->fMark0 ); assert( Gia_ObjIsAnd(Gia_ObjSiblObj(p, i)) ); } Abc_Print( 1, "Choice stats: Equivs =%7d. Choices =%7d.\n", nEquivs, nChoices ); Gia_ManCleanMark0( p ); } /**Function************************************************************* Synopsis [Prints stats for the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManPrintEdges( Gia_Man_t * p ) { printf( "Edges (Q=2) : " ); printf( "edge =%8d ", (Vec_IntCountPositive(p->vEdge1) + Vec_IntCountPositive(p->vEdge2))/2 ); printf( "lev =%5.1f", 0.1*Gia_ManEvalEdgeDelay(p) ); printf( "\n" ); 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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 ) Abc_Print( 1, "%-8s : ", p->pName ); SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 ); // normal #else 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) ); if ( Gia_ManConstrNum(p) ) Abc_Print( 1, "(c=%d)", Gia_ManConstrNum(p) ); if ( Gia_ManRegNum(p) ) 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); SetConsoleTextAttribute( hConsole, 11 ); // blue 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, " (%7.2f)", Gia_ManLevelAve(p) ); SetConsoleTextAttribute( hConsole, 7 ); // normal } #else Abc_Print( 1, " %s%s =%8d%s", "\033[1;36m", p->pMuxes? "nod" : "and", Gia_ManAndNum(p), "\033[0m" ); // blue 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 } 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) ); if ( Gia_ManHasChoices(p) ) Abc_Print( 1, " ch =%5d", Gia_ManChoiceNum(p) ); if ( p->pManTime ) Abc_Print( 1, " box = %d", Gia_ManNonRegBoxNum(p) ); if ( p->pManTime ) 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 ) { static int nPiPo = 0; static float PrevSwiTotal = 0; float SwiTotal = Gia_ManComputeSwitching( p, 48, 16, 0 ); Abc_Print( 1, " power =%8.1f", SwiTotal ); if ( PrevSwiTotal > 0 && nPiPo == Gia_ManCiNum(p) + Gia_ManCoNum(p) ) Abc_Print( 1, " %6.2f %%", 100.0*(PrevSwiTotal-SwiTotal)/PrevSwiTotal ); else if ( PrevSwiTotal == 0 || nPiPo != Gia_ManCiNum(p) + Gia_ManCoNum(p) ) PrevSwiTotal = SwiTotal, nPiPo = Gia_ManCiNum(p) + Gia_ManCoNum(p); } // Abc_Print( 1, "obj =%5d ", Gia_ManObjNum(p) ); Abc_Print( 1, "\n" ); // Gia_ManSatExperiment( p ); if ( p->pReprs && p->pNexts ) Gia_ManEquivPrintClasses( p, 0, 0.0 ); if ( Gia_ManHasMapping(p) && (pPars == NULL || !pPars->fSkipMap) ) Gia_ManPrintMappingStats( p, pPars ? pPars->pDumpFile : NULL ); else if ( pPars && pPars->pDumpFile ) Gia_ManLogAigStats( p, pPars->pDumpFile ); if ( pPars && pPars->fNpn && Gia_ManHasMapping(p) ) Gia_ManPrintNpnClasses( p ); if ( p->vPacking ) Gia_ManPrintPackingStats( p ); if ( p->vEdge1 ) Gia_ManPrintEdges( p ); if ( pPars && pPars->fLutProf && Gia_ManHasMapping(p) ) Gia_ManPrintLutStats( p ); if ( p->pPlacement ) Gia_ManPrintPlacement( p ); // if ( p->pManTime ) // Tim_ManPrintStats( (Tim_Man_t *)p->pManTime, p->nAnd2Delay ); Gia_ManPrintFlopClasses( p ); Gia_ManPrintGateClasses( p ); Gia_ManPrintObjClasses( p ); // if ( p->vRegClasses ) // { // printf( "The design has %d flops with the following class info: ", Vec_IntSize(p->vRegClasses) ); // Vec_IntPrint( p->vRegClasses ); // } if ( p->vInitClasses ) Gia_ManPrintInitClasses( p->vInitClasses ); // check integrity of boxes Gia_ManCheckIntegrityWithBoxes( p ); /* if ( Gia_ManRegBoxNum(p) ) { int i, Limit = Vec_IntFindMax(p->vRegClasses); for ( i = 1; i <= Limit; i++ ) printf( "%d ", Vec_IntCountEntry(p->vRegClasses, i) ); printf( "\n" ); } */ if ( pPars && pPars->fTents ) { /* int k, Entry, Prev = 1; Vec_Int_t * vLimit = Vec_IntAlloc( 1000 ); Gia_Man_t * pNew = Gia_ManUnrollDup( p, vLimit ); Abc_Print( 1, "Tents: " ); Vec_IntForEachEntryStart( vLimit, Entry, k, 1 ) Abc_Print( 1, "%d=%d ", k, Entry-Prev ), Prev = Entry; Abc_Print( 1, " Unused=%d.", Gia_ManObjNum(p) - Gia_ManObjNum(pNew) ); Abc_Print( 1, "\n" ); Vec_IntFree( vLimit ); Gia_ManStop( pNew ); */ Gia_ManPrintTents( p ); } if ( pPars && pPars->fSlacks ) Gia_ManDfsSlacksPrint( p ); } /**Function************************************************************* Synopsis [Prints stats for the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintStatsShort( Gia_Man_t * p ) { Abc_Print( 1, "i/o =%7d/%7d ", Gia_ManPiNum(p), Gia_ManPoNum(p) ); Abc_Print( 1, "ff =%7d ", Gia_ManRegNum(p) ); Abc_Print( 1, "and =%8d ", Gia_ManAndNum(p) ); Abc_Print( 1, "lev =%5d ", Gia_ManLevelNum(p) ); // Abc_Print( 1, "mem =%5.2f MB", 12.0*Gia_ManObjNum(p)/(1<<20) ); Abc_Print( 1, "\n" ); } /**Function************************************************************* Synopsis [Prints stats for the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintMiterStatus( Gia_Man_t * p ) { Gia_Obj_t * pObj, * pChild; int i, nSat = 0, nUnsat = 0, nUndec = 0, iOut = -1; Gia_ManForEachPo( p, pObj, i ) { pChild = Gia_ObjChild0(pObj); // check if the output is constant 0 if ( pChild == Gia_ManConst0(p) ) nUnsat++; // check if the output is constant 1 else if ( pChild == Gia_ManConst1(p) ) { nSat++; if ( iOut == -1 ) iOut = i; } // check if the output is a primary input else if ( Gia_ObjIsPi(p, Gia_Regular(pChild)) ) { nSat++; if ( iOut == -1 ) iOut = i; } /* // check if the output is 1 for the 0000 pattern else if ( Gia_Regular(pChild)->fPhase != (unsigned)Gia_IsComplement(pChild) ) { nSat++; if ( iOut == -1 ) iOut = i; } */ else nUndec++; } Abc_Print( 1, "Outputs = %7d. Unsat = %7d. Sat = %7d. Undec = %7d.\n", Gia_ManPoNum(p), nUnsat, nSat, nUndec ); } /**Function************************************************************* Synopsis [Statistics of the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintStatsMiter( Gia_Man_t * p, int fVerbose ) { Gia_Obj_t * pObj; Vec_Flt_t * vProb; int i, iObjId; Gia_ManLevelNum( p ); Gia_ManCreateRefs( p ); vProb = Gia_ManPrintOutputProb( p ); printf( "Statistics for each outputs of the miter:\n" ); Gia_ManForEachPo( p, pObj, i ) { iObjId = Gia_ObjId(p, pObj); printf( "%4d : ", i ); printf( "Level = %5d ", Gia_ObjLevelId(p, iObjId) ); printf( "Supp = %5d ", Gia_ManSuppSize(p, &iObjId, 1) ); printf( "Cone = %5d ", Gia_ManConeSize(p, &iObjId, 1) ); printf( "Mffc = %5d ", Gia_NodeMffcSize(p, Gia_ObjFanin0(pObj)) ); printf( "Prob = %8.4f ", Vec_FltEntry(vProb, iObjId) ); printf( "\n" ); } Vec_FltFree( vProb ); } /**Function************************************************************* Synopsis [Prints stats for the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSetRegNum( Gia_Man_t * p, int nRegs ) { assert( p->nRegs == 0 ); p->nRegs = nRegs; } /**Function************************************************************* Synopsis [Reports the reduction of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew ) { Abc_Print( 1, "REG: Beg = %5d. End = %5d. (R =%5.1f %%) ", Gia_ManRegNum(p), Gia_ManRegNum(pNew), Gia_ManRegNum(p)? 100.0*(Gia_ManRegNum(p)-Gia_ManRegNum(pNew))/Gia_ManRegNum(p) : 0.0 ); Abc_Print( 1, "AND: Beg = %6d. End = %6d. (R =%5.1f %%)", Gia_ManAndNum(p), Gia_ManAndNum(pNew), Gia_ManAndNum(p)? 100.0*(Gia_ManAndNum(p)-Gia_ManAndNum(pNew))/Gia_ManAndNum(p) : 0.0 ); Abc_Print( 1, "\n" ); } /**Function************************************************************* Synopsis [Prints NPN class statistics.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintNpnClasses( Gia_Man_t * p ) { extern char ** Kit_DsdNpn4ClassNames(); char ** pNames = Kit_DsdNpn4ClassNames(); Vec_Int_t * vLeaves, * vTruth, * vVisited; int * pLutClass, ClassCounts[222] = {0}; int i, k, iFan, Class, OtherClasses, OtherClasses2, nTotal, Counter, Counter2; unsigned * pTruth; int nLutSize = 0; assert( Gia_ManHasMapping(p) ); //assert( Gia_ManLutSizeMax( p ) <= 4 ); vLeaves = Vec_IntAlloc( 100 ); vVisited = Vec_IntAlloc( 100 ); vTruth = Vec_IntAlloc( (1<<16) ); pLutClass = ABC_CALLOC( int, Gia_ManObjNum(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 ); Gia_LutForEachFanin( p, i, iFan, k ) Vec_IntPush( vLeaves, iFan ); for ( ; k < 4; k++ ) Vec_IntPush( vLeaves, 0 ); pTruth = Gia_ManConvertAigToTruth( p, Gia_ManObj(p, i), vLeaves, vTruth, vVisited ); Class = Dar_LibReturnClass( *pTruth ); ClassCounts[ Class ]++; pLutClass[i] = Class; } Vec_IntFree( vLeaves ); Vec_IntFree( vTruth ); Vec_IntFree( vVisited ); Vec_IntFreeP( &p->vTruths ); nTotal = 0; for ( i = 0; i < 222; i++ ) nTotal += ClassCounts[i]; Abc_Print( 1, "NPN CLASS STATISTICS (for %d LUT4 present in the current mapping):\n", nTotal ); OtherClasses = 0; for ( i = k = 0; i < 222; i++ ) { if ( ClassCounts[i] == 0 ) continue; // if ( 100.0 * ClassCounts[i] / (nTotal+1) < 0.1 ) // do not show anything below 0.1 percent // continue; OtherClasses += ClassCounts[i]; Abc_Print( 1, "%3d: Class %3d : Count = %6d (%7.2f %%) %s\n", ++k, i, ClassCounts[i], 100.0 * ClassCounts[i] / (nTotal+1), pNames[i] ); } OtherClasses = nTotal - OtherClasses; Abc_Print( 1, "Other : Count = %6d (%7.2f %%)\n", OtherClasses, 100.0 * OtherClasses / (nTotal+1) ); // count the number of LUTs that have MUX function and two fanins with MUX functions OtherClasses = OtherClasses2 = 0; ABC_FREE( p->pRefs ); Gia_ManSetRefsMapped( p ); Gia_ManForEachLut( p, i ) { if ( pLutClass[i] != 109 ) continue; Counter = Counter2 = 0; Gia_LutForEachFanin( p, i, iFan, k ) { Counter += (pLutClass[iFan] == 109); Counter2 += (pLutClass[iFan] == 109) && (Gia_ObjRefNumId(p, iFan) == 1); } OtherClasses += (Counter > 1); OtherClasses2 += (Counter2 > 1); // Abc_Print( 1, "%d -- ", pLutClass[i] ); // Gia_LutForEachFanin( p, i, iFan, k ) // Abc_Print( 1, "%d ", pLutClass[iFan] ); // Abc_Print( 1, "\n" ); } ABC_FREE( p->pRefs ); 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 ); } /**Function************************************************************* Synopsis [Collects internal nodes and boxes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDfsCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjs ) { if ( Gia_ObjIsTravIdCurrent( p, pObj ) ) return; Gia_ObjSetTravIdCurrent( p, pObj ); if ( Gia_ObjIsCi(pObj) ) { Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; if ( pManTime ) { int i, iFirst, nTerms, iBox; iBox = Tim_ManBoxForCi( pManTime, Gia_ObjCioId(pObj) ); if ( iBox >= 0 ) // pObj is a box input { // mark box outputs iFirst = Tim_ManBoxOutputFirst( pManTime, iBox ); nTerms = Tim_ManBoxOutputNum( pManTime, iBox ); for ( i = 0; i < nTerms; i++ ) { pObj = Gia_ManCi( p, iFirst + i ); Gia_ObjSetTravIdCurrent( p, pObj ); } // traverse box inputs iFirst = Tim_ManBoxInputFirst( pManTime, iBox ); nTerms = Tim_ManBoxInputNum( pManTime, iBox ); for ( i = 0; i < nTerms; i++ ) { pObj = Gia_ManCo( p, iFirst + i ); Gia_ManDfsCollect_rec( p, pObj, vObjs ); } // save the box Vec_IntPush( vObjs, -iBox-1 ); } } return; } else if ( Gia_ObjIsCo(pObj) ) { Gia_ManDfsCollect_rec( p, Gia_ObjFanin0(pObj), vObjs ); } else if ( Gia_ObjIsAnd(pObj) ) { int iFan, k, iObj = Gia_ObjId(p, pObj); if ( Gia_ManHasMapping(p) ) { assert( Gia_ObjIsLut(p, iObj) ); Gia_LutForEachFanin( p, iObj, iFan, k ) Gia_ManDfsCollect_rec( p, Gia_ManObj(p, iFan), vObjs ); } else { Gia_ManDfsCollect_rec( p, Gia_ObjFanin0(pObj), vObjs ); Gia_ManDfsCollect_rec( p, Gia_ObjFanin1(pObj), vObjs ); } // save the object Vec_IntPush( vObjs, iObj ); } else if ( !Gia_ObjIsConst0(pObj) ) assert( 0 ); } Vec_Int_t * Gia_ManDfsCollect( Gia_Man_t * p ) { Vec_Int_t * vObjs = Vec_IntAlloc( Gia_ManObjNum(p) ); Gia_Obj_t * pObj; int i; Gia_ManIncrementTravId( p ); Gia_ManForEachCo( p, pObj, i ) Gia_ManDfsCollect_rec( p, pObj, vObjs ); Gia_ManForEachCi( p, pObj, i ) Gia_ManDfsCollect_rec( p, pObj, vObjs ); return vObjs; } /**Function************************************************************* Synopsis [Compute arrival/required times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManDfsArrivals( Gia_Man_t * p, Vec_Int_t * vObjs ) { Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; Vec_Int_t * vTimes = Vec_IntStartFull( Gia_ManObjNum(p) ); Gia_Obj_t * pObj; int j, Entry, k, iFan; Vec_IntWriteEntry( vTimes, 0, 0 ); if ( pManTime ) { Tim_ManIncrementTravId( pManTime ); Gia_ManForEachCi( p, pObj, j ) if ( j < Tim_ManPiNum(pManTime) ) { float arrTime = Tim_ManGetCiArrival( pManTime, j ); Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), (int)arrTime ); } } else { Gia_ManForEachCi( p, pObj, j ) Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), 0 ); } Vec_IntForEachEntry( vObjs, Entry, j ) { if ( Entry < 0 ) // box { int Time0, iFirst, nTerms, iBox = -Entry-1; assert( iBox >= 0 ); // set arrivals for box inputs iFirst = Tim_ManBoxInputFirst( pManTime, iBox ); nTerms = Tim_ManBoxInputNum( pManTime, iBox ); for ( k = 0; k < nTerms; k++ ) { pObj = Gia_ManCo( p, iFirst + k ); Time0 = Vec_IntEntry( vTimes, Gia_ObjFaninId0p(p, pObj) ); assert( Time0 >= 0 ); Tim_ManSetCoArrival( pManTime, Gia_ObjCioId(pObj), Time0 ); } // derive arrivals for box outputs iFirst = Tim_ManBoxOutputFirst( pManTime, iBox ); nTerms = Tim_ManBoxOutputNum( pManTime, iBox ); for ( k = 0; k < nTerms; k++ ) { pObj = Gia_ManCi( p, iFirst + k ); Time0 = Tim_ManGetCiArrival( pManTime, Gia_ObjCioId(pObj) ); assert( Time0 >= 0 ); Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), Time0 ); } } else if ( Entry > 0 ) // node { int Time0, Time1, TimeMax = 0; if ( Gia_ManHasMapping(p) ) { assert( Gia_ObjIsLut(p, Entry) ); Gia_LutForEachFanin( p, Entry, iFan, k ) { Time0 = Vec_IntEntry( vTimes, iFan ); assert( Time0 >= 0 ); TimeMax = Abc_MaxInt( TimeMax, Time0 ); } } else { pObj = Gia_ManObj( p, Entry ); Time0 = Vec_IntEntry( vTimes, Gia_ObjFaninId0(pObj, Entry) ); Time1 = Vec_IntEntry( vTimes, Gia_ObjFaninId1(pObj, Entry) ); assert( Time0 >= 0 && Time1 >= 0 ); TimeMax = Abc_MaxInt( Time0, Time1 ); } Vec_IntWriteEntry( vTimes, Entry, TimeMax + 10 ); } else assert( 0 ); } return vTimes; } static inline void Gia_ManDfsUpdateRequired( Vec_Int_t * vTimes, int iObj, int Req ) { int *pTime = Vec_IntEntryP( vTimes, iObj ); if (*pTime == -1 || *pTime > Req) *pTime = Req; } Vec_Int_t * Gia_ManDfsRequireds( Gia_Man_t * p, Vec_Int_t * vObjs, int ReqTime ) { Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; Vec_Int_t * vTimes = Vec_IntStartFull( Gia_ManObjNum(p) ); Gia_Obj_t * pObj; int j, Entry, k, iFan, Req; Vec_IntWriteEntry( vTimes, 0, 0 ); if ( pManTime ) { int nCoLimit = Gia_ManCoNum(p) - Tim_ManPoNum(pManTime); Tim_ManIncrementTravId( pManTime ); //Tim_ManInitPoRequiredAll( pManTime, (float)ReqTime ); Gia_ManForEachCo( p, pObj, j ) if ( j >= nCoLimit ) { Tim_ManSetCoRequired( pManTime, j, ReqTime ); Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId0p(p, pObj), ReqTime ); } } else { Gia_ManForEachCo( p, pObj, j ) Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId0p(p, pObj), ReqTime ); } Vec_IntForEachEntryReverse( vObjs, Entry, j ) { if ( Entry < 0 ) // box { int iFirst, nTerms, iBox = -Entry-1; assert( iBox >= 0 ); // set requireds for box outputs iFirst = Tim_ManBoxOutputFirst( pManTime, iBox ); nTerms = Tim_ManBoxOutputNum( pManTime, iBox ); for ( k = 0; k < nTerms; k++ ) { pObj = Gia_ManCi( p, iFirst + k ); Req = Vec_IntEntry( vTimes, Gia_ObjId(p, pObj) ); Req = Req == -1 ? ReqTime : Req; // dangling box output assert( Req >= 0 ); Tim_ManSetCiRequired( pManTime, Gia_ObjCioId(pObj), Req ); } // derive requireds for box inputs iFirst = Tim_ManBoxInputFirst( pManTime, iBox ); nTerms = Tim_ManBoxInputNum( pManTime, iBox ); for ( k = 0; k < nTerms; k++ ) { pObj = Gia_ManCo( p, iFirst + k ); Req = Tim_ManGetCoRequired( pManTime, Gia_ObjCioId(pObj) ); assert( Req >= 0 ); Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId0p(p, pObj), Req ); } } else if ( Entry > 0 ) // node { Req = Vec_IntEntry(vTimes, Entry) - 10; assert( Req >= 0 ); if ( Gia_ManHasMapping(p) ) { assert( Gia_ObjIsLut(p, Entry) ); Gia_LutForEachFanin( p, Entry, iFan, k ) Gia_ManDfsUpdateRequired( vTimes, iFan, Req ); } else { pObj = Gia_ManObj( p, Entry ); Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId0(pObj, Entry), Req ); Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId1(pObj, Entry), Req ); } } else assert( 0 ); } return vTimes; } Vec_Int_t * Gia_ManDfsSlacks( Gia_Man_t * p ) { Vec_Int_t * vSlack = Vec_IntStartFull( Gia_ManObjNum(p) ); Vec_Int_t * vObjs = Gia_ManDfsCollect( p ); if ( Vec_IntSize(vObjs) > 0 ) { Vec_Int_t * vArrs = Gia_ManDfsArrivals( p, vObjs ); int Required = Vec_IntFindMax( vArrs ); Vec_Int_t * vReqs = Gia_ManDfsRequireds( p, vObjs, Required ); int i, Arr, Req, Arrivals = ABC_INFINITY; Vec_IntForEachEntry( vReqs, Req, i ) if ( Req != -1 ) Arrivals = Abc_MinInt( Arrivals, Req ); //if ( Arrivals != 0 ) // printf( "\nGlobal timing check has failed.\n\n" ); //assert( Arrivals == 0 ); Vec_IntForEachEntryTwo( vArrs, vReqs, Arr, Req, i ) { if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) ) continue; if ( Gia_ManHasMapping(p) && !Gia_ObjIsLut(p, i) ) continue; assert( Arr <= Req ); Vec_IntWriteEntry( vSlack, i, Req - Arr ); } Vec_IntFree( vArrs ); Vec_IntFree( vReqs ); } Vec_IntFree( vObjs ); return vSlack; } void Gia_ManDfsSlacksPrint( Gia_Man_t * p ) { Vec_Int_t * vCounts, * vSlacks = Gia_ManDfsSlacks( p ); int i, Entry, nRange, nTotal; if ( Vec_IntSize(vSlacks) == 0 ) { printf( "Network contains no internal objects.\n" ); Vec_IntFree( vSlacks ); return; } // compute slacks Vec_IntForEachEntry( vSlacks, Entry, i ) if ( Entry != -1 ) Vec_IntWriteEntry( vSlacks, i, Entry/10 ); nRange = Vec_IntFindMax( vSlacks ); // count items vCounts = Vec_IntStart( nRange + 1 ); Vec_IntForEachEntry( vSlacks, Entry, i ) if ( Entry != -1 ) Vec_IntAddToEntry( vCounts, Entry, 1 ); // print slack ranges nTotal = Vec_IntSum( vCounts ); assert( nTotal > 0 ); Vec_IntForEachEntry( vCounts, Entry, i ) { printf( "Slack range %3d = ", i ); printf( "[%4d, %4d) ", 10*i, 10*(i+1) ); printf( "Nodes = %5d ", Entry ); printf( "(%6.2f %%) ", 100.0*Entry/nTotal ); printf( "\n" ); } Vec_IntFree( vSlacks ); Vec_IntFree( vCounts ); } /**Function************************************************************* Synopsis [Dump interface module] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManWriteNamesInter( FILE * pFile, char c, int n, int Start, int Skip, int nRegs, int fReverse ) { 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_ManDumpInterface2( 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), 0 ); fprintf( pFile, ",\n " ); Gia_ManWriteNamesInter( pFile, 'o', Gia_ManCoNum(p), 4, 4, Gia_ManRegNum(p), 0 ); 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 fReverse ) { int Digits = Abc_Base10Log( n ); int Length = Start, i, fFirst = 1; char * pName; for ( i = 0; i < n; i++ ) { int k = fReverse ? n-1-i : i; if ( vObjs && !Vec_BitEntry(vObjs, k) ) continue; pName = Gia_ObjGetDumpName( vNames, c, k, 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, int fInterComb, int fAssign, int fReverse ) { if ( fInterComb ) { if ( fAssign ) { extern void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ); Gia_ManDumpInterfaceAssign( p, pFileName ); } else { extern void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ); Gia_ManDumpInterface( p, pFileName ); } } else { if ( fAssign ) { extern void Gia_ManDumpVerilogNoInterAssign( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ); Gia_ManDumpVerilogNoInterAssign( p, pFileName, vObjs, fVerBufs, fInter ); } else { extern void Gia_ManDumpVerilogNoInter( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ); Gia_ManDumpVerilogNoInter( p, pFileName, vObjs, fVerBufs, fInter ); } } } void Gia_ManDumpVerilogNoInter( 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_ManDumpInterface2( 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, 0 ); fprintf( pFile, ",\n " ); Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 4, 4, NULL, 0 ); fprintf( pFile, "\n );\n\n" ); fprintf( pFile, " input " ); Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " output " ); Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); 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, 0 ); fprintf( pFile, ",\n " ); Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 4, 4, NULL, 0 ); fprintf( pFile, "\n );\n\n" ); fprintf( pFile, " input " ); Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " output " ); Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); } if ( Vec_BitCount(vUsed) ) { fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); fprintf( pFile, ";\n\n" ); } if ( Vec_BitCount(vInvs) ) { fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); 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 ); } void Gia_ManDumpVerilogNoInterAssign( 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_ManDumpInterface2( 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, 0 ); fprintf( pFile, ",\n " ); Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 4, 4, NULL, 0 ); fprintf( pFile, "\n );\n\n" ); fprintf( pFile, " input " ); Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " output " ); Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); Gia_ManForEachPi( p, pObj, i ) { fprintf( pFile, " assign %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, " assign %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, 0 ); fprintf( pFile, ",\n " ); Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 4, 4, NULL, 0 ); fprintf( pFile, "\n );\n\n" ); fprintf( pFile, " input " ); Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " output " ); Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); } if ( Vec_BitCount(vUsed) ) { fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); fprintf( pFile, ";\n\n" ); } if ( Vec_BitCount(vInvs) ) { fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); 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, " assign %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, " assign %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, " assign %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, " assign %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, " assign %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, 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 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintOneName( FILE * pFile, char * pName, int Size ) { int i; for ( i = 0; i < Size; i++ ) fprintf( pFile, "%c", pName[i] ); } int Gia_ManCountSymbs( char * pName ) { int i; for ( i = 0; pName[i]; i++ ) if ( pName[i] == '[' ) break; return i; } int Gia_ManReadRangeNum( char * pName, int Size ) { if ( pName[Size] == 0 ) return -1; assert( pName[Size] == '[' ); return atoi(pName+Size+1); } Vec_Int_t * Gia_ManCountSymbsAll( Vec_Ptr_t * vNames ) { char * pNameLast = (char *)Vec_PtrEntry(vNames, 0), * pName; int i, nSymbsLast = Gia_ManCountSymbs(pNameLast); Vec_Int_t * vArray = Vec_IntAlloc( Vec_PtrSize(vNames) * 2 ); Vec_IntPush( vArray, 0 ); Vec_IntPush( vArray, nSymbsLast ); Vec_PtrForEachEntryStart( char *, vNames, pName, i, 1 ) { int nSymbs = Gia_ManCountSymbs(pName); if ( nSymbs == nSymbsLast && !strncmp(pName, pNameLast, nSymbsLast) ) continue; Vec_IntPush( vArray, i ); Vec_IntPush( vArray, nSymbs ); pNameLast = pName; nSymbsLast = nSymbs; } return vArray; } void Gia_ManDumpIoList( Gia_Man_t * p, FILE * pFile, int fOuts, int fReverse ) { Vec_Ptr_t * vNames = fOuts ? p->vNamesOut : p->vNamesIn; if ( vNames == NULL ) fprintf( pFile, "_%c_", fOuts ? 'o' : 'i' ); else { Vec_Int_t * vArray = Gia_ManCountSymbsAll( vNames ); int iName, Size, i; Vec_IntForEachEntryDouble( vArray, iName, Size, i ) { if ( fReverse ) { iName = Vec_IntEntry(vArray, Vec_IntSize(vArray)-2-i); Size = Vec_IntEntry(vArray, Vec_IntSize(vArray)-1-i); } if ( i ) fprintf( pFile, ", " ); Gia_ManPrintOneName( pFile, (char *)Vec_PtrEntry(vNames, iName), Size ); } Vec_IntFree( vArray ); } } void Gia_ManDumpIoRanges( Gia_Man_t * p, FILE * pFile, int fOuts ) { Vec_Ptr_t * vNames = fOuts ? p->vNamesOut : p->vNamesIn; if ( p->vNamesOut == NULL ) fprintf( pFile, "%s [%d:0] _%c_;\n", fOuts ? "output" : "input", fOuts ? Gia_ManPoNum(p)-1 : Gia_ManPiNum(p)-1, fOuts ? 'o' : 'i' ); else { Vec_Int_t * vArray = Gia_ManCountSymbsAll( vNames ); int iName, Size, i; Vec_IntForEachEntryDouble( vArray, iName, Size, i ) { int iNameNext = Vec_IntSize(vArray) > i+2 ? Vec_IntEntry(vArray, i+2) : Vec_PtrSize(vNames); char * pName = (char *)Vec_PtrEntry(vNames, iName); char * pNameLast = (char *)Vec_PtrEntry(vNames, iNameNext-1); assert( !strncmp(pName, pNameLast, Size) ); int NumBeg = Gia_ManReadRangeNum( pName, Size ); int NumEnd = Gia_ManReadRangeNum( pNameLast, Size ); fprintf( pFile, " %s ", fOuts ? "output" : "input" ); if ( NumBeg != -1 && iName < iNameNext-1 ) fprintf( pFile, "[%d:%d] ", NumEnd, NumBeg ); Gia_ManPrintOneName( pFile, pName, Size ); fprintf( pFile, ";\n" ); } Vec_IntFree( vArray ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ) { 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; FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); return; } vInvs = Gia_ManGenUsed( p, 0 ); vUsed = Gia_ManGenUsed( p, 1 ); fprintf( pFile, "module " ); Gia_ManDumpModuleName( pFile, p->pName ); fprintf( pFile, "_wrapper" ); fprintf( pFile, " ( " ); Gia_ManDumpIoList( p, pFile, 0, 0 ); fprintf( pFile, ", " ); Gia_ManDumpIoList( p, pFile, 1, 0 ); fprintf( pFile, " );\n\n" ); Gia_ManDumpIoRanges( p, pFile, 0 ); Gia_ManDumpIoRanges( p, pFile, 1 ); fprintf( pFile, "\n" ); fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " assign { " ); Gia_ManWriteNames( pFile, 'x', Gia_ManCiNum(p), p->vNamesIn, 8, 4, NULL, 1 ); fprintf( pFile, " } = { " ); Gia_ManDumpIoList( p, pFile, 0, 1 ); fprintf( pFile, " };\n\n" ); fprintf( pFile, " assign { " ); Gia_ManDumpIoList( p, pFile, 1, 1 ); fprintf( pFile, " } = { " ); Gia_ManWriteNames( pFile, 'z', Gia_ManCoNum(p), p->vNamesOut, 9, 4, NULL, 1 ); fprintf( pFile, " };\n\n" ); if ( Vec_BitCount(vUsed) ) { fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); fprintf( pFile, ";\n\n" ); } if ( Vec_BitCount(vInvs) ) { fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); fprintf( pFile, ";\n\n" ); } // input inverters Gia_ManForEachCi( 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 ) { 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_ManForEachCo( p, pObj, i ) { 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 ); } void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ) { 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; FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); return; } vInvs = Gia_ManGenUsed( p, 0 ); vUsed = Gia_ManGenUsed( p, 1 ); fprintf( pFile, "module " ); Gia_ManDumpModuleName( pFile, p->pName ); fprintf( pFile, "_wrapper" ); fprintf( pFile, " ( " ); Gia_ManDumpIoList( p, pFile, 0, 0 ); fprintf( pFile, ", " ); Gia_ManDumpIoList( p, pFile, 1, 0 ); fprintf( pFile, " );\n\n" ); Gia_ManDumpIoRanges( p, pFile, 0 ); Gia_ManDumpIoRanges( p, pFile, 1 ); fprintf( pFile, "\n" ); fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); fprintf( pFile, ";\n\n" ); fprintf( pFile, " assign { " ); Gia_ManWriteNames( pFile, 'x', Gia_ManCiNum(p), p->vNamesIn, 8, 4, NULL, 1 ); fprintf( pFile, " } = { " ); Gia_ManDumpIoList( p, pFile, 0, 1 ); fprintf( pFile, " };\n\n" ); fprintf( pFile, " assign { " ); Gia_ManDumpIoList( p, pFile, 1, 1 ); fprintf( pFile, " } = { " ); Gia_ManWriteNames( pFile, 'z', Gia_ManCoNum(p), p->vNamesOut, 9, 4, NULL, 1 ); fprintf( pFile, " };\n\n" ); if ( Vec_BitCount(vUsed) ) { fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); fprintf( pFile, ";\n\n" ); } if ( Vec_BitCount(vInvs) ) { fprintf( pFile, " wire " ); Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); fprintf( pFile, ";\n\n" ); } // input inverters Gia_ManForEachCi( p, pObj, i ) { if ( Vec_BitEntry(vUsed, Gia_ObjId(p, pObj)) ) { fprintf( pFile, " assign %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, " assign %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 ) { fprintf( pFile, " assign %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, " assign %s =", Gia_ObjGetDumpName(NULL, 'i', i, nDigits) ); fprintf( pFile, " ~%s;\n", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); } } // output drivers fprintf( pFile, "\n" ); Gia_ManForEachCo( p, pObj, i ) { fprintf( pFile, " assign %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 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDumpNandLit( FILE * pFile, int nIns, int Lit, int nDigits ) { if ( Lit == 0 ) fprintf( pFile, "1\'b0" ); else if ( Lit == 1 ) fprintf( pFile, "1\'b1" ); else if ( Abc_Lit2Var(Lit) <= nIns ) fprintf( pFile, "%cn%0*d", (char)(Abc_LitIsCompl(Lit)? '~':' '), nDigits, Abc_Lit2Var(Lit) ); else fprintf( pFile, "%cn%0*d", (char)(Abc_LitIsCompl(Lit)? ' ':'~'), nDigits, Abc_Lit2Var(Lit) ); } void Gia_ManDumpVerilogNand( Gia_Man_t * p, char * pFileName ) { Gia_Obj_t * pObj; int i, nPis = Gia_ManPiNum(p); int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); return; } assert( Gia_ManRegNum(p) == 0 ); fprintf( pFile, "module " ); Gia_ManDumpModuleName( pFile, p->pName ); fprintf( pFile, "_wrapper" ); fprintf( pFile, " ( " ); if ( p->vNamesIn ) { Gia_ManDumpIoList( p, pFile, 0, 0 ); fprintf( pFile, ", " ); Gia_ManDumpIoList( p, pFile, 1, 0 ); fprintf( pFile, " );\n\n" ); Gia_ManDumpIoRanges( p, pFile, 0 ); Gia_ManDumpIoRanges( p, pFile, 1 ); } else { fprintf( pFile, "\n " ); Gia_ManForEachPi( p, pObj, i ) fprintf( pFile, "%s, ", Gia_ObjGetDumpName(NULL, 'x', i, nDigitsI) ); fprintf( pFile, "\n " ); Gia_ManForEachPo( p, pObj, i ) fprintf( pFile, "%s%s ", Gia_ObjGetDumpName(NULL, 'z', i, nDigitsO), i < Gia_ManPoNum(p)-1 ? ",":"" ); fprintf( pFile, "\n);\n\n" ); fprintf( pFile, " input" ); Gia_ManForEachPi( p, pObj, i ) fprintf( pFile, " %s%s", Gia_ObjGetDumpName(NULL, 'x', i, nDigitsI), i < Gia_ManPiNum(p)-1 ? ",":"" ); fprintf( pFile, ";\n" ); fprintf( pFile, " output" ); Gia_ManForEachPo( p, pObj, i ) fprintf( pFile, " %s%s", Gia_ObjGetDumpName(NULL, 'z', i, nDigitsO), i < Gia_ManPoNum(p)-1 ? ",":"" ); fprintf( pFile, ";\n" ); } fprintf( pFile, "\n" ); Gia_ManForEachPi( p, pObj, i ) fprintf( pFile, " wire n%0*d = %s;\n", nDigits, i+1, p->vNamesIn ? (char *)Vec_PtrEntry(p->vNamesIn, i) : Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); fprintf( pFile, "\n" ); Gia_ManForEachAnd( p, pObj, i ) { fprintf( pFile, " wire n%0*d = ~(", nDigits, i ); Gia_ManDumpNandLit( pFile, nPis, Gia_ObjFaninLit0(pObj, i), nDigits ); fprintf( pFile, " & " ); Gia_ManDumpNandLit( pFile, nPis, Gia_ObjFaninLit1(pObj, i), nDigits ); fprintf( pFile, ");\n" ); } fprintf( pFile, "\n" ); Gia_ManForEachPo( p, pObj, i ) { fprintf( pFile, " assign %s = ", p->vNamesOut ? (char *)Vec_PtrEntry(p->vNamesOut, i) : Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); Gia_ManDumpNandLit( pFile, nPis, Gia_ObjFaninLit0p(p, pObj), nDigits ); fprintf( pFile, ";\n" ); } fprintf( pFile, "\nendmodule\n\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [Generate hierarchical design.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_FreeMany( Gia_Man_t ** pGias, int nGias ) { int i; for ( i = 0; i < nGias; i++ ) Gia_ManStopP( &pGias[i] ); } void Gia_GenSandwich( char ** pFNames, int nFNames, char * pFileName ) { FILE * pFile = NULL; Gia_Man_t * pGias[16] = {0}; int i, k; assert( nFNames <= 16 ); for ( i = 0; i < nFNames; i++ ) { FILE * pFile = fopen( pFNames[i], "rb" ); if ( pFile == NULL ) { printf( "Cannot open input file \"%s\".\n", pFNames[i] ); Gia_FreeMany( pGias, nFNames ); return; } fclose( pFile ); pGias[i] = Gia_AigerRead( pFNames[i], 0, 0, 0 ); if ( pGias[i] == NULL ) { printf( "Failed to read an AIG from file \"%s\".\n", pFNames[i] ); Gia_FreeMany( pGias, nFNames ); return; } } for ( i = 0; i < nFNames-1; i++ ) if ( Gia_ManPoNum(pGias[i]) < Gia_ManPiNum(pGias[i+1]) ) { printf( "AIG in file \"%s\" has fewer outputs than inputs of AIG in file \"%s\".\n", pFNames[i], pFNames[i+1] ); Gia_FreeMany( pGias, nFNames ); return; } pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", pFileName ); Gia_FreeMany( pGias, nFNames ); return; } fprintf( pFile, "\n" ); for ( i = 0; i < nFNames; i++ ) fprintf( pFile, "`include \"%s\"\n", Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v") ); fprintf( pFile, "\n" ); fprintf( pFile, "module sandwich ( in, out );\n" ); fprintf( pFile, " input [%3d:0] in;\n", Gia_ManPiNum(pGias[0])-1 ); fprintf( pFile, " output [%3d:0] out;\n", Gia_ManPoNum(pGias[nFNames-1])-1 ); fprintf( pFile, " wire [%3d:0] tmp0 = in;\n", Gia_ManPiNum(pGias[0])-1 ); for ( i = 0; i < nFNames; i++ ) { fprintf( pFile, " wire [%3d:0] tmp%d; ", Gia_ManPoNum(pGias[i])-1, i+1 ); Gia_ManDumpModuleName( pFile, pGias[i]->pName ); fprintf( pFile, "_wrapper" ); for ( k = strlen(pGias[i]->pName); k < 24; k++ ) fprintf( pFile, " " ); fprintf( pFile, " i%d ( tmp%d, tmp%d );\n", i+1, i, i+1 ); } fprintf( pFile, " assign out = tmp%d;\n", nFNames ); fprintf( pFile, "endmodule\n" ); fclose( pFile ); for ( i = 0; i < nFNames; i++ ) { Vec_PtrFreeFree( pGias[i]->vNamesIn ); pGias[i]->vNamesIn = NULL; Vec_PtrFreeFree( pGias[i]->vNamesOut ); pGias[i]->vNamesOut = NULL; Gia_ManDumpVerilog( pGias[i], Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v"), NULL, 0, 0, 1, 0, 0 ); printf( "Dumped Verilog file \"%s\"\n", Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v") ); } Gia_FreeMany( pGias, nFNames ); printf( "Dumped hierarchical design into file \"%s\"\n", pFileName ); } /**Function************************************************************* Synopsis [Generate hierarchical design.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_GenPutOnTopOne( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Int_t * vLits ) { Gia_Obj_t * pObj; int i; Gia_ManConst0(p)->Value = 0; assert( Vec_IntSize(vLits) == Gia_ManCiNum(p) ); Gia_ManForEachCi( p, pObj, i ) pObj->Value = Vec_IntEntry(vLits, i); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Vec_IntClear( vLits ); Gia_ManForEachCo( p, pObj, i ) Vec_IntPush( vLits, Gia_ObjFanin0Copy(pObj) ); assert( Vec_IntSize(vLits) == Gia_ManCoNum(p) ); } Gia_Man_t * Gia_GenPutOnTop( char ** pFNames, int nFNames ) { Gia_Man_t * pNew, * pTemp; Gia_Man_t * pGias[16] = {0}; Vec_Int_t * vLits; int i, iLit, nObjs = 0; assert( nFNames <= 16 ); for ( i = 0; i < nFNames; i++ ) { FILE * pFile = fopen( pFNames[i], "rb" ); if ( pFile == NULL ) { printf( "Cannot open input file \"%s\".\n", pFNames[i] ); Gia_FreeMany( pGias, nFNames ); return NULL; } fclose( pFile ); pGias[i] = Gia_AigerRead( pFNames[i], 0, 0, 0 ); if ( pGias[i] == NULL ) { printf( "Failed to read an AIG from file \"%s\".\n", pFNames[i] ); Gia_FreeMany( pGias, nFNames ); return NULL; } nObjs += Gia_ManObjNum(pGias[i]); } // start new AIG pNew = Gia_ManStart( nObjs ); pNew->pName = Abc_UtilStrsav( "putontop" ); Gia_ManHashAlloc( pNew ); // collect inputs vLits = Vec_IntAlloc( Gia_ManCiNum(pGias[0]) ); for ( i = 0; i < Gia_ManCiNum(pGias[0]); i++ ) Vec_IntPush( vLits, Gia_ManAppendCi(pNew) ); // add parts for ( i = 0; i < nFNames; i++ ) { Gia_Man_t * p = pGias[i]; while ( Vec_IntSize(vLits) < Gia_ManCiNum(p) ) Vec_IntPush( vLits, Gia_ManAppendCi(pNew) ); while ( Vec_IntSize(vLits) > Gia_ManCiNum(p) ) Gia_ManAppendCo( pNew, Vec_IntPop(vLits) ); Gia_GenPutOnTopOne( pNew, p, vLits ); } // create outputs Vec_IntForEachEntry( vLits, iLit, i ) Gia_ManAppendCo( pNew, iLit ); Vec_IntFree( vLits ); // cleanup pNew = Gia_ManDupNormalize( pTemp = pNew, 0 ); Gia_ManStop( pTemp ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaMem.c000066400000000000000000000415051477524141600156370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaMem.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Memory managers.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: giaMem.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// struct Gia_MmFixed_t_ { // information about individual entries int nEntrySize; // the size of one entry int nEntriesAlloc; // the total number of entries allocated int nEntriesUsed; // the number of entries in use int nEntriesMax; // the max number of entries in use char * pEntriesFree; // the linked list of free entries // this is where the memory is stored int nChunkSize; // the size of one chunk int nChunksAlloc; // the maximum number of memory chunks int nChunks; // the current number of memory chunks char ** pChunks; // the allocated memory // statistics int nMemoryUsed; // memory used in the allocated entries int nMemoryAlloc; // memory allocated }; struct Gia_MmFlex_t_ { // information about individual entries int nEntriesUsed; // the number of entries allocated char * pCurrent; // the current pointer to free memory char * pEnd; // the first entry outside the free memory // this is where the memory is stored int nChunkSize; // the size of one chunk int nChunksAlloc; // the maximum number of memory chunks int nChunks; // the current number of memory chunks char ** pChunks; // the allocated memory // statistics int nMemoryUsed; // memory used in the allocated entries int nMemoryAlloc; // memory allocated }; struct Gia_MmStep_t_ { int nMems; // the number of fixed memory managers employed Gia_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc int nMapSize; // the size of the memory array Gia_MmFixed_t ** pMap; // maps the number of bytes into its memory manager // additional memory chunks int nChunksAlloc; // the maximum number of memory chunks int nChunks; // the current number of memory chunks char ** pChunks; // the allocated memory }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates memory pieces of fixed size.] Description [The size of the chunk is computed as the minimum of 1024 entries and 64K. Can only work with entry size at least 4 byte long.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_MmFixed_t * Gia_MmFixedStart( int nEntrySize, int nEntriesMax ) { Gia_MmFixed_t * p; p = ABC_ALLOC( Gia_MmFixed_t, 1 ); memset( p, 0, sizeof(Gia_MmFixed_t) ); p->nEntrySize = nEntrySize; p->nEntriesAlloc = 0; p->nEntriesUsed = 0; p->pEntriesFree = NULL; p->nChunkSize = nEntriesMax / 8; if ( p->nChunkSize < 8 ) p->nChunkSize = 8; p->nChunksAlloc = 64; p->nChunks = 0; p->pChunks = ABC_ALLOC( char *, p->nChunksAlloc ); p->nMemoryUsed = 0; p->nMemoryAlloc = 0; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_MmFixedStop( Gia_MmFixed_t * p, int fVerbose ) { int i; if ( p == NULL ) return; if ( fVerbose ) { printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", p->nEntrySize, p->nChunkSize, p->nChunks ); printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); } for ( i = 0; i < p->nChunks; i++ ) ABC_FREE( p->pChunks[i] ); ABC_FREE( p->pChunks ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Gia_MmFixedEntryFetch( Gia_MmFixed_t * p ) { char * pTemp; int i; // check if there are still free entries if ( p->nEntriesUsed == p->nEntriesAlloc ) { // need to allocate more entries assert( p->pEntriesFree == NULL ); if ( p->nChunks == p->nChunksAlloc ) { p->nChunksAlloc *= 2; p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); } p->pEntriesFree = ABC_ALLOC( char, p->nEntrySize * p->nChunkSize ); p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; // transform these entries into a linked list pTemp = p->pEntriesFree; for ( i = 1; i < p->nChunkSize; i++ ) { *((char **)pTemp) = pTemp + p->nEntrySize; pTemp += p->nEntrySize; } // set the last link *((char **)pTemp) = NULL; // add the chunk to the chunk storage p->pChunks[ p->nChunks++ ] = p->pEntriesFree; // add to the number of entries allocated p->nEntriesAlloc += p->nChunkSize; } // incrememt the counter of used entries p->nEntriesUsed++; if ( p->nEntriesMax < p->nEntriesUsed ) p->nEntriesMax = p->nEntriesUsed; // return the first entry in the free entry list pTemp = p->pEntriesFree; p->pEntriesFree = *((char **)pTemp); return pTemp; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_MmFixedEntryRecycle( Gia_MmFixed_t * p, char * pEntry ) { // decrement the counter of used entries p->nEntriesUsed--; // add the entry to the linked list of free entries *((char **)pEntry) = p->pEntriesFree; p->pEntriesFree = pEntry; } /**Function************************************************************* Synopsis [] Description [Relocates all the memory except the first chunk.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_MmFixedRestart( Gia_MmFixed_t * p ) { int i; char * pTemp; if ( p->nChunks == 0 ) return; // deallocate all chunks except the first one for ( i = 1; i < p->nChunks; i++ ) ABC_FREE( p->pChunks[i] ); p->nChunks = 1; // transform these entries into a linked list pTemp = p->pChunks[0]; for ( i = 1; i < p->nChunkSize; i++ ) { *((char **)pTemp) = pTemp + p->nEntrySize; pTemp += p->nEntrySize; } // set the last link *((char **)pTemp) = NULL; // set the free entry list p->pEntriesFree = p->pChunks[0]; // set the correct statistics p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; p->nMemoryUsed = 0; p->nEntriesAlloc = p->nChunkSize; p->nEntriesUsed = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_MmFixedReadMemUsage( Gia_MmFixed_t * p ) { return p->nMemoryAlloc; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_MmFixedReadMaxEntriesUsed( Gia_MmFixed_t * p ) { return p->nEntriesMax; } /**Function************************************************************* Synopsis [Allocates entries of flexible size.] Description [Can only work with entry size at least 4 byte long.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_MmFlex_t * Gia_MmFlexStart() { Gia_MmFlex_t * p; p = ABC_ALLOC( Gia_MmFlex_t, 1 ); memset( p, 0, sizeof(Gia_MmFlex_t) ); p->nEntriesUsed = 0; p->pCurrent = NULL; p->pEnd = NULL; p->nChunkSize = (1 << 18); p->nChunksAlloc = 64; p->nChunks = 0; p->pChunks = ABC_ALLOC( char *, p->nChunksAlloc ); p->nMemoryUsed = 0; p->nMemoryAlloc = 0; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_MmFlexStop( Gia_MmFlex_t * p, int fVerbose ) { int i; if ( p == NULL ) return; if ( fVerbose ) { printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", p->nChunkSize, p->nChunks ); printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); } for ( i = 0; i < p->nChunks; i++ ) ABC_FREE( p->pChunks[i] ); ABC_FREE( p->pChunks ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Gia_MmFlexEntryFetch( Gia_MmFlex_t * p, int nBytes ) { char * pTemp; // check if there are still free entries if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) { // need to allocate more entries if ( p->nChunks == p->nChunksAlloc ) { p->nChunksAlloc *= 2; p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); } if ( nBytes > p->nChunkSize ) { // resize the chunk size if more memory is requested than it can give // (ideally, this should never happen) p->nChunkSize = 2 * nBytes; } p->pCurrent = ABC_ALLOC( char, p->nChunkSize ); p->pEnd = p->pCurrent + p->nChunkSize; p->nMemoryAlloc += p->nChunkSize; // add the chunk to the chunk storage p->pChunks[ p->nChunks++ ] = p->pCurrent; } assert( p->pCurrent + nBytes <= p->pEnd ); // increment the counter of used entries p->nEntriesUsed++; // keep track of the memory used p->nMemoryUsed += nBytes; // return the next entry pTemp = p->pCurrent; p->pCurrent += nBytes; return pTemp; } /**Function************************************************************* Synopsis [] Description [Relocates all the memory except the first chunk.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_MmFlexRestart( Gia_MmFlex_t * p ) { int i; if ( p->nChunks == 0 ) return; // deallocate all chunks except the first one for ( i = 1; i < p->nChunks; i++ ) ABC_FREE( p->pChunks[i] ); p->nChunks = 1; p->nMemoryAlloc = p->nChunkSize; // transform these entries into a linked list p->pCurrent = p->pChunks[0]; p->pEnd = p->pCurrent + p->nChunkSize; p->nEntriesUsed = 0; p->nMemoryUsed = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_MmFlexReadMemUsage( Gia_MmFlex_t * p ) { return p->nMemoryUsed; } /**Function************************************************************* Synopsis [Starts the hierarchical memory manager.] Description [This manager can allocate entries of any size. Iternally they are mapped into the entries with the number of bytes equal to the power of 2. The smallest entry size is 8 bytes. The next one is 16 bytes etc. So, if the user requests 6 bytes, he gets 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. The input parameters "nSteps" says how many fixed memory managers are employed internally. Calling this procedure with nSteps equal to 10 results in 10 hierarchically arranged internal memory managers, which can allocate up to 4096 (1Kb) entries. Requests for larger entries are handed over to malloc() and then ABC_FREE()ed.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_MmStep_t * Gia_MmStepStart( int nSteps ) { Gia_MmStep_t * p; int i, k; p = ABC_ALLOC( Gia_MmStep_t, 1 ); memset( p, 0, sizeof(Gia_MmStep_t) ); p->nMems = nSteps; // start the fixed memory managers p->pMems = ABC_ALLOC( Gia_MmFixed_t *, p->nMems ); for ( i = 0; i < p->nMems; i++ ) p->pMems[i] = Gia_MmFixedStart( (8<nMapSize = (4<nMems); p->pMap = ABC_ALLOC( Gia_MmFixed_t *, p->nMapSize+1 ); p->pMap[0] = NULL; for ( k = 1; k <= 4; k++ ) p->pMap[k] = p->pMems[0]; for ( i = 0; i < p->nMems; i++ ) for ( k = (4<pMap[k] = p->pMems[i]; //for ( i = 1; i < 100; i ++ ) //printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); p->nChunksAlloc = 64; p->nChunks = 0; p->pChunks = ABC_ALLOC( char *, p->nChunksAlloc ); return p; } /**Function************************************************************* Synopsis [Stops the memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_MmStepStop( Gia_MmStep_t * p, int fVerbose ) { int i; for ( i = 0; i < p->nMems; i++ ) Gia_MmFixedStop( p->pMems[i], fVerbose ); if ( p->nChunksAlloc ) { for ( i = 0; i < p->nChunks; i++ ) ABC_FREE( p->pChunks[i] ); ABC_FREE( p->pChunks ); } ABC_FREE( p->pMems ); ABC_FREE( p->pMap ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates the entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Gia_MmStepEntryFetch( Gia_MmStep_t * p, int nBytes ) { if ( nBytes == 0 ) return NULL; if ( nBytes > p->nMapSize ) { if ( p->nChunks == p->nChunksAlloc ) { p->nChunksAlloc *= 2; p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); } p->pChunks[ p->nChunks++ ] = ABC_ALLOC( char, nBytes ); return p->pChunks[p->nChunks-1]; } return Gia_MmFixedEntryFetch( p->pMap[nBytes] ); } /**Function************************************************************* Synopsis [Recycles the entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_MmStepEntryRecycle( Gia_MmStep_t * p, char * pEntry, int nBytes ) { if ( nBytes == 0 ) return; if ( nBytes > p->nMapSize ) { // ABC_FREE( pEntry ); return; } Gia_MmFixedEntryRecycle( p->pMap[nBytes], pEntry ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_MmStepReadMemUsage( Gia_MmStep_t * p ) { int i, nMemTotal = 0; for ( i = 0; i < p->nMems; i++ ) nMemTotal += p->pMems[i]->nMemoryAlloc; return nMemTotal; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaMf.c000066400000000000000000002164511477524141600154670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaMf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Cut computation.] Author [Alan Mishchenko]` Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaMf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/vec/vecMem.h" #include "misc/util/utilTruth.h" #include "misc/extra/extra.h" #include "sat/cnf/cnf.h" #include "opt/dau/dau.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define MF_LEAF_MAX 10 #define MF_CUT_MAX 16 #define MF_LOG_PAGE 12 #define MF_NO_LEAF 31 #define MF_TT_WORDS ((MF_LEAF_MAX > 6) ? 1 << (MF_LEAF_MAX-6) : 1) #define MF_NO_FUNC 134217727 // (1<<27)-1 #define MF_EPSILON 0.005 typedef struct Mf_Cut_t_ Mf_Cut_t; struct Mf_Cut_t_ { word Sign; // signature int Delay; // delay float Flow; // flow unsigned iFunc : 27; // function (MF_NO_FUNC) unsigned nLeaves : 5; // leaf number (MF_NO_LEAF) int pLeaves[MF_LEAF_MAX+1]; // leaves }; typedef struct Mf_Obj_t_ Mf_Obj_t; struct Mf_Obj_t_ { int iCutSet; // cutset float Flow; // area float nFlowRefs; // flow references unsigned Delay : 16; // delay unsigned nMapRefs : 16; // map references }; typedef struct Mf_Man_t_ Mf_Man_t; struct Mf_Man_t_ { // user data Gia_Man_t * pGia0; // original manager Gia_Man_t * pGia; // derived manager Jf_Par_t * pPars; // parameters // cut data Mf_Obj_t * pLfObjs; // best cuts Vec_Ptr_t vPages; // cut memory Vec_Mem_t * vTtMem; // truth tables Vec_Int_t vCnfSizes; // handles to CNF Vec_Int_t vCnfMem; // memory for CNF Vec_Int_t vTemp; // temporary array int iCur; // current position int Iter; // mapping iterations int fUseEla; // use exact area // statistics abctime clkStart; // starting time double CutCount[4]; // cut counts int nCutCounts[MF_LEAF_MAX+1]; }; static inline Mf_Obj_t * Mf_ManObj( Mf_Man_t * p, int i ) { return p->pLfObjs + i; } static inline int * Mf_ManCutSet( Mf_Man_t * p, int i ) { return (int *)Vec_PtrEntry(&p->vPages, i >> 16) + (i & 0xFFFF); } static inline int * Mf_ObjCutSet( Mf_Man_t * p, int i ) { return Mf_ManCutSet(p, Mf_ManObj(p, i)->iCutSet); } static inline int * Mf_ObjCutBest( Mf_Man_t * p, int i ) { return Mf_ObjCutSet(p, i) + 1; } static inline int Mf_ObjMapRefNum( Mf_Man_t * p, int i ) { return Mf_ManObj(p, i)->nMapRefs; } static inline int Mf_ObjMapRefInc( Mf_Man_t * p, int i ) { return Mf_ManObj(p, i)->nMapRefs++; } static inline int Mf_ObjMapRefDec( Mf_Man_t * p, int i ) { return --Mf_ManObj(p, i)->nMapRefs; } static inline int Mf_CutSize( int * pCut ) { return pCut[0] & MF_NO_LEAF; } static inline int Mf_CutFunc( int * pCut ) { return ((unsigned)pCut[0] >> 5); } static inline int Mf_CutSetBoth( int n, int f ) { return n | (f << 5); } static inline int Mf_CutIsTriv( int * pCut, int i ) { return Mf_CutSize(pCut) == 1 && pCut[1] == i; } #define Mf_SetForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += Mf_CutSize(pCut) + 1 ) #define Mf_ObjForEachCut( pCuts, i, nCuts ) for ( i = 0, i < nCuts; i++ ) extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computing truth tables of useful DSD classes of 6-functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int s_nCalls = 0; static Vec_Mem_t * s_vTtMem = NULL; int Mf_ManTruthCanonicize( word * t, int nVars ) { word Temp, Best = *t; int r, i, Config = 0; for ( r = 0; r < 1; r++ ) { if ( Best > (Temp = ~Best) ) Best = Temp, Config ^= (1 << nVars); for ( i = 0; i < nVars; i++ ) if ( Best > (Temp = Abc_Tt6Flip(Best, i)) ) Best = Temp, Config ^= (1 << i); } *t = Best; if ( s_vTtMem == NULL ) s_vTtMem = Vec_MemAllocForTT( 6, 0 ); Vec_MemHashInsert( s_vTtMem, t ); s_nCalls++; return Config; } void Mf_ManTruthQuit() { if ( s_vTtMem == NULL ) return; printf( "TT = %d (%.2f %%)\n", Vec_MemEntryNum(s_vTtMem), 100.0 * Vec_MemEntryNum(s_vTtMem) / s_nCalls ); Vec_MemHashFree( s_vTtMem ); Vec_MemFree( s_vTtMem ); s_vTtMem = NULL; s_nCalls = 0; } Vec_Wrd_t * Mf_ManTruthCollect( int Limit ) { extern Vec_Wrd_t * Mpm_ManGetTruthWithCnf( int Limit ); int * pPerm = Extra_PermSchedule( 6 ); int * pComp = Extra_GreyCodeSchedule( 6 ); Vec_Wrd_t * vTruths = Mpm_ManGetTruthWithCnf( Limit ); Vec_Wrd_t * vResult = Vec_WrdAlloc( 1 << 20 ); word uTruth, tCur, tTemp1, tTemp2; int i, p, c, k; Vec_WrdForEachEntry( vTruths, uTruth, k ) { for ( i = 0; i < 2; i++ ) { tCur = i ? ~uTruth : uTruth; tTemp1 = tCur; for ( p = 0; p < 720; p++ ) { tTemp2 = tCur; for ( c = 0; c < 64; c++ ) { tCur = Abc_Tt6Flip( tCur, pComp[c] ); Vec_WrdPush( vResult, tCur ); } assert( tTemp2 == tCur ); tCur = Abc_Tt6SwapAdjacent( tCur, pPerm[p] ); } assert( tTemp1 == tCur ); } } ABC_FREE( pPerm ); ABC_FREE( pComp ); printf( "Original = %d. ", Vec_WrdSize(vTruths) ); Vec_WrdFree( vTruths ); printf( "Total = %d. ", Vec_WrdSize(vResult) ); vTruths = Vec_WrdUniqifyHash( vResult, 1 ); Vec_WrdFree( vResult ); printf( "Unique = %d. ", Vec_WrdSize(vTruths) ); Vec_WrdForEachEntry( vTruths, uTruth, k ) { Mf_ManTruthCanonicize( &uTruth, 6 ); Vec_WrdWriteEntry( vTruths, k, uTruth ); } vResult = Vec_WrdUniqifyHash( vTruths, 1 ); Vec_WrdFree( vTruths ); printf( "Unique = %d. \n", Vec_WrdSize(vResult) ); return vResult; } int Mf_ManTruthCount() { Vec_Wrd_t * vTruths = Mf_ManTruthCollect( 10 ); int RetValue = Vec_WrdSize( vTruths ); Vec_WrdFree( vTruths ); return RetValue; } /**Function************************************************************* Synopsis [Collect truth tables used by the mapper.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mf_ManProfileTruths( Mf_Man_t * p ) { Vec_Int_t * vCounts; int i, Entry, * pCut, Counter = 0; vCounts = Vec_IntStart( Vec_IntSize(&p->vCnfSizes) ); Gia_ManForEachAndId( p->pGia, i ) { if ( !Mf_ObjMapRefNum(p, i) ) continue; pCut = Mf_ObjCutBest( p, i ); Vec_IntAddToEntry( vCounts, Abc_Lit2Var(Mf_CutFunc(pCut)), 1 ); } Vec_IntForEachEntry( vCounts, Entry, i ) { if ( Entry == 0 ) continue; printf( "%6d : ", Counter++ ); printf( "%6d : ", i ); printf( "Occur = %4d ", Entry ); printf( "CNF size = %2d ", Vec_IntEntry(&p->vCnfSizes, i) ); Dau_DsdPrintFromTruth( Vec_MemReadEntry(p->vTtMem, i), p->pPars->nLutSize ); } Vec_IntFree( vCounts ); } /**Function************************************************************* Synopsis [Derives CNFs for each function used in the mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Mf_CutPrintOne( int * pCut ) { int i; printf( "%d {", Mf_CutSize(pCut) ); for ( i = 1; i <= Mf_CutSize(pCut); i++ ) printf( " %d", pCut[i] ); printf( " }\n" ); } static inline int Mf_CubeLit( int Cube, int iVar ) { return (Cube >> (iVar << 1)) & 3; } static inline int Mf_ManCountLits( int * pCnf, int nCubes, int nVars ) { int i, k, nLits = nCubes; for ( i = 0; i < nCubes; i++ ) for ( k = 0; k < nVars; k++ ) if ( Mf_CubeLit(pCnf[i], k) ) nLits++; return nLits; } Vec_Int_t * Mf_ManDeriveCnfs( Mf_Man_t * p, int * pnVars, int * pnClas, int * pnLits ) { int i, k, iFunc, nCubes, nLits, * pCut, pCnf[512]; Vec_Int_t * vLits = Vec_IntStart( Vec_IntSize(&p->vCnfSizes) ); Vec_Int_t * vCnfs = Vec_IntAlloc( 3 * Vec_IntSize(&p->vCnfSizes) ); Vec_IntFill( vCnfs, Vec_IntSize(&p->vCnfSizes), -1 ); assert( p->pPars->nLutSize <= 8 ); // constant/buffer for ( iFunc = 0; iFunc < 2; iFunc++ ) { if ( p->pPars->nLutSize <= 6 ) nCubes = Abc_Tt6Cnf( *Vec_MemReadEntry(p->vTtMem, iFunc), iFunc, pCnf ); else nCubes = Abc_Tt8Cnf( Vec_MemReadEntry(p->vTtMem, iFunc), iFunc, pCnf ); nLits = Mf_ManCountLits( pCnf, nCubes, iFunc ); Vec_IntWriteEntry( vLits, iFunc, nLits ); Vec_IntWriteEntry( vCnfs, iFunc, Vec_IntSize(vCnfs) ); Vec_IntPush( vCnfs, nCubes ); for ( k = 0; k < nCubes; k++ ) Vec_IntPush( vCnfs, pCnf[k] ); } // other functions *pnVars = 1 + Gia_ManCiNum(p->pGia) + Gia_ManCoNum(p->pGia); *pnClas = 1 + 2 * Gia_ManCoNum(p->pGia); *pnLits = 1 + 4 * Gia_ManCoNum(p->pGia); Gia_ManForEachAndId( p->pGia, i ) { if ( !Mf_ObjMapRefNum(p, i) ) continue; pCut = Mf_ObjCutBest( p, i ); //Mf_CutPrintOne( pCut ); iFunc = Abc_Lit2Var( Mf_CutFunc(pCut) ); if ( Vec_IntEntry(vCnfs, iFunc) == -1 ) { if ( p->pPars->nLutSize <= 6 ) nCubes = Abc_Tt6Cnf( *Vec_MemReadEntry(p->vTtMem, iFunc), Mf_CutSize(pCut), pCnf ); else nCubes = Abc_Tt8Cnf( Vec_MemReadEntry(p->vTtMem, iFunc), Mf_CutSize(pCut), pCnf ); assert( nCubes == Vec_IntEntry(&p->vCnfSizes, iFunc) ); nLits = Mf_ManCountLits( pCnf, nCubes, Mf_CutSize(pCut) ); // save CNF Vec_IntWriteEntry( vLits, iFunc, nLits ); Vec_IntWriteEntry( vCnfs, iFunc, Vec_IntSize(vCnfs) ); Vec_IntPush( vCnfs, nCubes ); for ( k = 0; k < nCubes; k++ ) Vec_IntPush( vCnfs, pCnf[k] ); } *pnVars += 1; *pnClas += Vec_IntEntry(&p->vCnfSizes, iFunc); *pnLits += Vec_IntEntry(vLits, iFunc); } Vec_IntFree( vLits ); return vCnfs; } /**Function************************************************************* Synopsis [Derives CNF for the AIG using the mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Cnf_Dat_t * Mf_ManDeriveCnf( Mf_Man_t * p, int fCnfObjIds, int fAddOrCla ) { Cnf_Dat_t * pCnf; Gia_Obj_t * pObj; int Id, DriId, nVars, nClas, nLits, iVar = 1, iCla = 0, iLit = 0; Vec_Int_t * vCnfs = Mf_ManDeriveCnfs( p, &nVars, &nClas, &nLits ); Vec_Int_t * vCnfIds = Vec_IntStartFull( Gia_ManObjNum(p->pGia) ); int pFanins[16], * pCut, * pCnfIds = Vec_IntArray( vCnfIds ); int i, k, c, iFunc, nCubes, * pCubes, fComplLast; nVars++; // zero-ID to remain unused if ( fAddOrCla ) { nClas++; nLits += Gia_ManCoNum(p->pGia); } // create CNF IDs if ( fCnfObjIds ) { iVar += 1 + Gia_ManCiNum(p->pGia) + Gia_ManCoNum(p->pGia); Gia_ManForEachCoId( p->pGia, Id, i ) Vec_IntWriteEntry( vCnfIds, Id, Id ); Gia_ManForEachAndReverseId( p->pGia, Id ) if ( Mf_ObjMapRefNum(p, Id) ) Vec_IntWriteEntry( vCnfIds, Id, Id ), iVar++; Vec_IntWriteEntry( vCnfIds, 0, 0 ); Gia_ManForEachCiId( p->pGia, Id, i ) Vec_IntWriteEntry( vCnfIds, Id, Id ); assert( iVar == nVars ); } else { Gia_ManForEachCoId( p->pGia, Id, i ) Vec_IntWriteEntry( vCnfIds, Id, iVar++ ); Gia_ManForEachAndReverseId( p->pGia, Id ) if ( Mf_ObjMapRefNum(p, Id) ) Vec_IntWriteEntry( vCnfIds, Id, iVar++ ); Vec_IntWriteEntry( vCnfIds, 0, iVar++ ); Gia_ManForEachCiId( p->pGia, Id, i ) Vec_IntWriteEntry( vCnfIds, Id, iVar++ ); assert( iVar == nVars ); } // generate CNF pCnf = ABC_CALLOC( Cnf_Dat_t, 1 ); pCnf->pMan = (Aig_Man_t *)p->pGia; pCnf->nVars = nVars; pCnf->nLiterals = nLits; pCnf->nClauses = nClas; pCnf->pClauses = ABC_ALLOC( int *, nClas+1 ); pCnf->pClauses[0] = ABC_ALLOC( int, nLits ); // add last clause if ( fAddOrCla ) { pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit; Gia_ManForEachCoId( p->pGia, Id, i ) pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[Id], 0); } if ( p->pPars->fCnfMapping ) pCnf->vMapping = Vec_IntStart( nVars ); // add clauses for the COs Gia_ManForEachCo( p->pGia, pObj, i ) { Id = Gia_ObjId( p->pGia, pObj ); DriId = Gia_ObjFaninId0( pObj, Id ); pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit; pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[Id], 0); pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[DriId], !Gia_ObjFaninC0(pObj)); pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit; pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[Id], 1); pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[DriId], Gia_ObjFaninC0(pObj)); // generate mapping if ( pCnf->vMapping ) { Vec_IntWriteEntry( pCnf->vMapping, pCnfIds[Id], Vec_IntSize(pCnf->vMapping) ); Vec_IntPush( pCnf->vMapping, 1 ); Vec_IntPush( pCnf->vMapping, pCnfIds[DriId] ); Vec_IntPush( pCnf->vMapping, Gia_ObjFaninC0(pObj) ? 0x55555555 : 0xAAAAAAAA ); } } // add clauses for the mapping Gia_ManForEachAndReverseId( p->pGia, Id ) { if ( !Mf_ObjMapRefNum(p, Id) ) continue; pCut = Mf_ObjCutBest( p, Id ); iFunc = Abc_Lit2Var( Mf_CutFunc(pCut) ); fComplLast = Abc_LitIsCompl( Mf_CutFunc(pCut) ); if ( iFunc == 0 ) // constant cut { pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit; pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[Id], !fComplLast); assert( pCnf->vMapping == NULL ); // bug fix does not handle generated mapping continue; } for ( k = 0; k < Mf_CutSize(pCut); k++ ) pFanins[k] = pCnfIds[pCut[k+1]]; pFanins[k++] = pCnfIds[Id]; // get clauses pCubes = Vec_IntEntryP( vCnfs, Vec_IntEntry(vCnfs, iFunc) ); nCubes = *pCubes++; for ( c = 0; c < nCubes; c++ ) { pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit; k = Mf_CutSize(pCut); assert( Mf_CubeLit(pCubes[c], k) ); pCnf->pClauses[0][iLit++] = Abc_Var2Lit( pFanins[k], (Mf_CubeLit(pCubes[c], k) == 2) ^ fComplLast ); for ( k = 0; k < Mf_CutSize(pCut); k++ ) if ( Mf_CubeLit(pCubes[c], k) ) pCnf->pClauses[0][iLit++] = Abc_Var2Lit( pFanins[k], Mf_CubeLit(pCubes[c], k) == 2 ); } // generate mapping if ( pCnf->vMapping ) { word pTruth[4], * pTruthP = Vec_MemReadEntry(p->vTtMem, iFunc); assert( p->pPars->nLutSize <= 8 ); Abc_TtCopy( pTruth, pTruthP, Abc_Truth6WordNum(p->pPars->nLutSize), Abc_LitIsCompl(iFunc) ); assert( pCnfIds[Id] >= 0 && pCnfIds[Id] < nVars ); Vec_IntWriteEntry( pCnf->vMapping, pCnfIds[Id], Vec_IntSize(pCnf->vMapping) ); Vec_IntPush( pCnf->vMapping, Mf_CutSize(pCut) ); for ( k = 0; k < Mf_CutSize(pCut); k++ ) Vec_IntPush( pCnf->vMapping, pCnfIds[pCut[k+1]] ); Vec_IntPush( pCnf->vMapping, (unsigned)pTruth[0] ); if ( Mf_CutSize(pCut) >= 6 ) { Vec_IntPush( pCnf->vMapping, (unsigned)(pTruth[0] >> 32) ); if ( Mf_CutSize(pCut) >= 7 ) { Vec_IntPush( pCnf->vMapping, (unsigned)(pTruth[1]) ); Vec_IntPush( pCnf->vMapping, (unsigned)(pTruth[1] >> 32) ); } if ( Mf_CutSize(pCut) >= 8 ) { Vec_IntPush( pCnf->vMapping, (unsigned)(pTruth[2]) ); Vec_IntPush( pCnf->vMapping, (unsigned)(pTruth[2] >> 32) ); Vec_IntPush( pCnf->vMapping, (unsigned)(pTruth[3]) ); Vec_IntPush( pCnf->vMapping, (unsigned)(pTruth[3] >> 32) ); } } } } // constant clause pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit; pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[0], 1); assert( iCla == nClas ); assert( iLit == nLits ); // add closing pointer pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit; // cleanup Vec_IntFree( vCnfs ); // create mapping of objects into their clauses if ( fCnfObjIds ) { pCnf->pObj2Clause = ABC_FALLOC( int, Gia_ManObjNum(p->pGia) ); pCnf->pObj2Count = ABC_FALLOC( int, Gia_ManObjNum(p->pGia) ); for ( i = 0; i < pCnf->nClauses; i++ ) { Id = Abc_Lit2Var(pCnf->pClauses[i][0]); if ( pCnf->pObj2Clause[Id] == -1 ) { pCnf->pObj2Clause[Id] = i; pCnf->pObj2Count[Id] = 1; } else { assert( pCnf->pObj2Count[Id] > 0 ); pCnf->pObj2Count[Id]++; } } } else { if ( p->pGia != p->pGia0 ) // diff managers - create map for CIs/COs { pCnf->pVarNums = ABC_FALLOC( int, Gia_ManObjNum(p->pGia0) ); Gia_ManForEachCiId( p->pGia0, Id, i ) pCnf->pVarNums[Id] = pCnfIds[Gia_ManCiIdToId(p->pGia, i)]; Gia_ManForEachCoId( p->pGia0, Id, i ) pCnf->pVarNums[Id] = pCnfIds[Gia_ManCoIdToId(p->pGia, i)]; /* // transform polarity of the internal nodes Gia_ManSetPhase( p->pGia ); Gia_ManForEachCo( p->pGia, pObj, i ) pObj->fPhase = 0; for ( i = 0; i < pCnf->nLiterals; i++ ) if ( Gia_ManObj(p->pGia, Abc_Lit2Var(pCnf->pClauses[0][i]))->fPhase ) pCnf->pClauses[0][i] = Abc_LitNot( pCnf->pClauses[0][i] ); */ } else pCnf->pVarNums = Vec_IntReleaseArray(vCnfIds); } Vec_IntFree( vCnfIds ); return pCnf; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Mf_CutComputeTruth6( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, int fCompl0, int fCompl1, Mf_Cut_t * pCutR, int fIsXor ) { // extern int Mf_ManTruthCanonicize( word * t, int nVars ); int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t = fIsXor ? t0 ^ t1 : t0 & t1; if ( (fCompl = (int)(t & 1)) ) t = ~t; if ( !p->pPars->fCnfObjIds ) pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); assert( (int)(t & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, &t); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); 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 ); return (int)pCutR->nLeaves < nOldSupp; } static inline int Mf_CutComputeTruth( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, int fCompl0, int fCompl1, Mf_Cut_t * pCutR, int fIsXor ) { if ( p->pPars->nLutSize <= 6 ) return Mf_CutComputeTruth6( p, pCut0, pCut1, fCompl0, fCompl1, pCutR, fIsXor ); { word uTruth[MF_TT_WORDS], uTruth0[MF_TT_WORDS], uTruth1[MF_TT_WORDS]; int nOldSupp = pCutR->nLeaves, truthId; int LutSize = p->pPars->nLutSize, fCompl; int nWords = Abc_Truth6WordNum(LutSize); word * pTruth0 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); word * pTruth1 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ); Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ); Abc_TtExpand( uTruth0, LutSize, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); Abc_TtExpand( uTruth1, LutSize, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); if ( fIsXor ) Abc_TtXor( uTruth, uTruth0, uTruth1, nWords, (fCompl = (int)((uTruth0[0] ^ uTruth1[0]) & 1)) ); else Abc_TtAnd( uTruth, uTruth0, uTruth1, nWords, (fCompl = (int)((uTruth0[0] & uTruth1[0]) & 1)) ); pCutR->nLeaves = Abc_TtMinBase( uTruth, pCutR->pLeaves, pCutR->nLeaves, LutSize ); assert( (uTruth[0] & 1) == 0 ); //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 || 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; } } static inline int Mf_CutComputeTruthMux6( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, Mf_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Mf_Cut_t * pCutR ) { int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); word tC = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCutC->iFunc)); if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; if ( Abc_LitIsCompl(pCutC->iFunc) ^ fComplC ) tC = ~tC; t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); tC = Abc_Tt6Expand( tC, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t = (tC & t1) | (~tC & t0); if ( (fCompl = (int)(t & 1)) ) t = ~t; pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); assert( (int)(t & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, &t); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); 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; } static inline int Mf_CutComputeTruthMux( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, Mf_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Mf_Cut_t * pCutR ) { if ( p->pPars->nLutSize <= 6 ) return Mf_CutComputeTruthMux6( p, pCut0, pCut1, pCutC, fCompl0, fCompl1, fComplC, pCutR ); { word uTruth[MF_TT_WORDS], uTruth0[MF_TT_WORDS], uTruth1[MF_TT_WORDS], uTruthC[MF_TT_WORDS]; int nOldSupp = pCutR->nLeaves, truthId; int LutSize = p->pPars->nLutSize, fCompl; int nWords = Abc_Truth6WordNum(LutSize); word * pTruth0 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); word * pTruth1 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); word * pTruthC = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCutC->iFunc)); Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ); Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ); Abc_TtCopy( uTruthC, pTruthC, nWords, Abc_LitIsCompl(pCutC->iFunc) ^ fComplC ); Abc_TtExpand( uTruth0, LutSize, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); Abc_TtExpand( uTruth1, LutSize, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); Abc_TtExpand( uTruthC, LutSize, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); Abc_TtMux( uTruth, uTruthC, uTruth1, uTruth0, nWords ); fCompl = (int)(uTruth[0] & 1); if ( fCompl ) Abc_TtNot( uTruth, nWords ); pCutR->nLeaves = Abc_TtMinBase( uTruth, pCutR->pLeaves, pCutR->nLeaves, LutSize ); assert( (uTruth[0] & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, uTruth); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); 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; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Mf_CutCountBits( word i ) { i = i - ((i >> 1) & 0x5555555555555555); i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); return (i*(0x0101010101010101))>>56; } static inline word Mf_CutGetSign( int * pLeaves, int nLeaves ) { word Sign = 0; int i; for ( i = 0; i < nLeaves; i++ ) Sign |= ((word)1) << (pLeaves[i] & 0x3F); return Sign; } static inline int Mf_CutCreateUnit( Mf_Cut_t * p, int i ) { p->Delay = 0; p->Flow = 0; p->iFunc = 2; p->nLeaves = 1; p->pLeaves[0] = i; p->Sign = ((word)1) << (i & 0x3F); return 1; } static inline void Mf_CutPrint( Mf_Man_t * p, Mf_Cut_t * pCut ) { int i, nDigits = Abc_Base10Log(Gia_ManObjNum(p->pGia)); printf( "%d {", pCut->nLeaves ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) printf( " %*d", nDigits, pCut->pLeaves[i] ); for ( ; i < (int)p->pPars->nLutSize; i++ ) printf( " %*s", nDigits, " " ); printf( " } D = %4d A = %9.4f F = %6d ", pCut->Delay, pCut->Flow, pCut->iFunc ); if ( p->vTtMem ) { 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 printf( "\n" ); } static inline int Mf_ManPrepareCuts( Mf_Cut_t * pCuts, Mf_Man_t * p, int iObj, int fAddUnit ) { if ( Mf_ManObj(p, iObj)->iCutSet ) { Mf_Cut_t * pMfCut = pCuts; int i, * pCut, * pList = Mf_ObjCutSet(p, iObj); Mf_SetForEachCut( pList, pCut, i ) { pMfCut->Delay = 0; pMfCut->Flow = 0; pMfCut->iFunc = Mf_CutFunc( pCut ); pMfCut->nLeaves = Mf_CutSize( pCut ); pMfCut->Sign = Mf_CutGetSign( pCut+1, Mf_CutSize(pCut) ); memcpy( pMfCut->pLeaves, pCut+1, sizeof(int) * Mf_CutSize(pCut) ); pMfCut++; } if ( fAddUnit && pCuts->nLeaves > 1 ) return pList[0] + Mf_CutCreateUnit( pMfCut, iObj ); return pList[0]; } return Mf_CutCreateUnit( pCuts, iObj ); } static inline int Mf_ManSaveCuts( Mf_Man_t * p, Mf_Cut_t ** pCuts, int nCuts ) { int i, * pPlace, iCur, nInts = 1; for ( i = 0; i < nCuts; i++ ) nInts += pCuts[i]->nLeaves + 1; if ( (p->iCur & 0xFFFF) + nInts > 0xFFFF ) p->iCur = ((p->iCur >> 16) + 1) << 16; if ( Vec_PtrSize(&p->vPages) == (p->iCur >> 16) ) Vec_PtrPush( &p->vPages, ABC_ALLOC(int, (1<<16)) ); iCur = p->iCur; p->iCur += nInts; pPlace = Mf_ManCutSet( p, iCur ); *pPlace++ = nCuts; for ( i = 0; i < nCuts; i++ ) { *pPlace++ = Mf_CutSetBoth(pCuts[i]->nLeaves, pCuts[i]->iFunc); memcpy( pPlace, pCuts[i]->pLeaves, sizeof(int) * pCuts[i]->nLeaves ); pPlace += pCuts[i]->nLeaves; } return iCur; } static inline void Mf_ObjSetBestCut( int * pCuts, int * pCut ) { assert( pCuts < pCut ); if ( ++pCuts < pCut ) { int pTemp[MF_CUT_MAX*(MF_LEAF_MAX+2)]; int nBlock = pCut - pCuts; int nSize = Mf_CutSize(pCut) + 1; memmove( pTemp, pCuts, sizeof(int) * nBlock ); memmove( pCuts, pCut, sizeof(int) * nSize ); memmove( pCuts + nSize, pTemp, sizeof(int) * nBlock ); } } /**Function************************************************************* Synopsis [Check correctness of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Mf_CutCheck( Mf_Cut_t * pBase, Mf_Cut_t * pCut ) // check if pCut is contained in pBase { int nSizeB = pBase->nLeaves; int nSizeC = pCut->nLeaves; int i, * pB = pBase->pLeaves; int k, * pC = pCut->pLeaves; for ( i = 0; i < nSizeC; i++ ) { for ( k = 0; k < nSizeB; k++ ) if ( pC[i] == pB[k] ) break; if ( k == nSizeB ) return 0; } return 1; } static inline int Mf_SetCheckArray( Mf_Cut_t ** ppCuts, int nCuts ) { Mf_Cut_t * pCut0, * pCut1; int i, k, m, n, Value; assert( nCuts > 0 ); for ( i = 0; i < nCuts; i++ ) { pCut0 = ppCuts[i]; assert( pCut0->nLeaves <= MF_LEAF_MAX ); assert( pCut0->Sign == Mf_CutGetSign(pCut0->pLeaves, pCut0->nLeaves) ); // check duplicates for ( m = 0; m < (int)pCut0->nLeaves; m++ ) for ( n = m + 1; n < (int)pCut0->nLeaves; n++ ) assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] ); // check pairs for ( k = 0; k < nCuts; k++ ) { pCut1 = ppCuts[k]; if ( pCut0 == pCut1 ) continue; // check containments Value = Mf_CutCheck( pCut0, pCut1 ); assert( Value == 0 ); } } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Mf_CutMergeOrder( Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, Mf_Cut_t * pCut, int nLutSize ) { int nSize0 = pCut0->nLeaves; int nSize1 = pCut1->nLeaves; int i, * pC0 = pCut0->pLeaves; int k, * pC1 = pCut1->pLeaves; int c, * pC = pCut->pLeaves; // the case of the largest cut sizes if ( nSize0 == nLutSize && nSize1 == nLutSize ) { for ( i = 0; i < nSize0; i++ ) { if ( pC0[i] != pC1[i] ) return 0; pC[i] = pC0[i]; } pCut->nLeaves = nLutSize; pCut->iFunc = MF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; } // compare two cuts with different numbers i = k = c = 0; if ( nSize0 == 0 ) goto FlushCut1; if ( nSize1 == 0 ) goto FlushCut0; while ( 1 ) { if ( c == nLutSize ) return 0; if ( pC0[i] < pC1[k] ) { pC[c++] = pC0[i++]; if ( i >= nSize0 ) goto FlushCut1; } else if ( pC0[i] > pC1[k] ) { pC[c++] = pC1[k++]; if ( k >= nSize1 ) goto FlushCut0; } else { pC[c++] = pC0[i++]; k++; if ( i >= nSize0 ) goto FlushCut1; if ( k >= nSize1 ) goto FlushCut0; } } FlushCut0: if ( c + nSize0 > nLutSize + i ) return 0; while ( i < nSize0 ) pC[c++] = pC0[i++]; pCut->nLeaves = c; pCut->iFunc = MF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; FlushCut1: if ( c + nSize1 > nLutSize + k ) return 0; while ( k < nSize1 ) pC[c++] = pC1[k++]; pCut->nLeaves = c; pCut->iFunc = MF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; } static inline int Mf_CutMergeOrderMux( Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, Mf_Cut_t * pCut2, Mf_Cut_t * pCut, int nLutSize ) { int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; int x2, i2 = 0, nSize2 = pCut2->nLeaves, * pC2 = pCut2->pLeaves; int xMin, c = 0, * pC = pCut->pLeaves; while ( 1 ) { x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; x2 = (i2 == nSize2) ? ABC_INFINITY : pC2[i2]; xMin = Abc_MinInt( Abc_MinInt(x0, x1), x2 ); if ( xMin == ABC_INFINITY ) break; if ( c == nLutSize ) return 0; pC[c++] = xMin; if (x0 == xMin) i0++; if (x1 == xMin) i1++; if (x2 == xMin) i2++; } pCut->nLeaves = c; pCut->iFunc = MF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign | pCut2->Sign; return 1; } static inline int Mf_SetCutIsContainedOrder( Mf_Cut_t * pBase, Mf_Cut_t * pCut ) // check if pCut is contained in pBase { int i, nSizeB = pBase->nLeaves; int k, nSizeC = pCut->nLeaves; if ( nSizeB == nSizeC ) { for ( i = 0; i < nSizeB; i++ ) if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) return 0; return 1; } assert( nSizeB > nSizeC ); if ( nSizeC == 0 ) return 1; for ( i = k = 0; i < nSizeB; i++ ) { if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) return 0; if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) { if ( ++k == nSizeC ) return 1; } } return 0; } static inline int Mf_SetLastCutIsContained( Mf_Cut_t ** pCuts, int nCuts ) { int i; for ( i = 0; i < nCuts; i++ ) if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Mf_SetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) ) return 1; return 0; } static inline int Mf_SetLastCutContainsArea( Mf_Cut_t ** pCuts, int nCuts ) { int i, k, fChanges = 0; for ( i = 0; i < nCuts; i++ ) if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Mf_SetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) ) pCuts[i]->nLeaves = MF_NO_LEAF, fChanges = 1; if ( !fChanges ) return nCuts; for ( i = k = 0; i <= nCuts; i++ ) { if ( pCuts[i]->nLeaves == MF_NO_LEAF ) continue; if ( k < i ) ABC_SWAP( Mf_Cut_t *, pCuts[k], pCuts[i] ); k++; } return k - 1; } static inline int Mf_CutCompareArea( Mf_Cut_t * pCut0, Mf_Cut_t * pCut1 ) { if ( pCut0->Flow < pCut1->Flow - MF_EPSILON ) return -1; if ( pCut0->Flow > pCut1->Flow + MF_EPSILON ) return 1; if ( pCut0->Delay < pCut1->Delay ) return -1; if ( pCut0->Delay > pCut1->Delay ) return 1; if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; return 0; } static inline void Mf_SetSortByArea( Mf_Cut_t ** pCuts, int nCuts ) { int i; for ( i = nCuts; i > 0; i-- ) { if ( Mf_CutCompareArea(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 ) return; ABC_SWAP( Mf_Cut_t *, pCuts[i - 1], pCuts[i] ); } } static inline int Mf_SetAddCut( Mf_Cut_t ** pCuts, int nCuts, int nCutNum ) { if ( nCuts == 0 ) return 1; nCuts = Mf_SetLastCutContainsArea(pCuts, nCuts); Mf_SetSortByArea( pCuts, nCuts ); return Abc_MinInt( nCuts + 1, nCutNum - 1 ); } static inline int Mf_CutArea( Mf_Man_t * p, int nLeaves, int iFunc ) { if ( nLeaves < 2 ) return 0; if ( p->pPars->fGenCnf || p->pPars->fGenLit ) return Vec_IntEntry(&p->vCnfSizes, Abc_Lit2Var(iFunc)); if ( p->pPars->fOptEdge ) return nLeaves + p->pPars->nAreaTuner; return 1; } static inline void Mf_CutParams( Mf_Man_t * p, Mf_Cut_t * pCut, float FlowRefs ) { Mf_Obj_t * pBest; int i, nLeaves = pCut->nLeaves; assert( nLeaves <= p->pPars->nLutSize ); pCut->Delay = 0; pCut->Flow = 0; for ( i = 0; i < nLeaves; i++ ) { pBest = Mf_ManObj(p, pCut->pLeaves[i]); pCut->Delay = Abc_MaxInt( pCut->Delay, pBest->Delay ); pCut->Flow += pBest->Flow; } pCut->Delay += (int)(nLeaves > 1); pCut->Flow = (pCut->Flow + Mf_CutArea(p, nLeaves, pCut->iFunc)) / FlowRefs; } void Mf_ObjMergeOrder( Mf_Man_t * p, int iObj ) { Mf_Cut_t pCuts0[MF_CUT_MAX], pCuts1[MF_CUT_MAX], pCuts[MF_CUT_MAX], * pCutsR[MF_CUT_MAX]; Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); Mf_Obj_t * pBest = Mf_ManObj(p, iObj); int nLutSize = p->pPars->nLutSize; int nCutNum = p->pPars->nCutNum; int nCuts0 = Mf_ManPrepareCuts(pCuts0, p, Gia_ObjFaninId0(pObj, iObj), 1); int nCuts1 = Mf_ManPrepareCuts(pCuts1, p, Gia_ObjFaninId1(pObj, iObj), 1); int fComp0 = Gia_ObjFaninC0(pObj); int fComp1 = Gia_ObjFaninC1(pObj); int iSibl = Gia_ObjSibl(p->pGia, iObj); Mf_Cut_t * pCut0, * pCut1, * pCut0Lim = pCuts0 + nCuts0, * pCut1Lim = pCuts1 + nCuts1; int i, nCutsR = 0; for ( i = 0; i < nCutNum; i++ ) pCutsR[i] = pCuts + i; if ( iSibl ) { Mf_Cut_t pCuts2[MF_CUT_MAX]; Gia_Obj_t * pObjE = Gia_ObjSiblObj(p->pGia, iObj); int fCompE = Gia_ObjPhase(pObj) ^ Gia_ObjPhase(pObjE); int nCuts2 = Mf_ManPrepareCuts(pCuts2, p, iSibl, 0); Mf_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) { *pCutsR[nCutsR] = *pCut2; if ( pCutsR[nCutsR]->iFunc >= 0 ) pCutsR[nCutsR]->iFunc = Abc_LitNotCond( pCutsR[nCutsR]->iFunc, fCompE ); Mf_CutParams( p, pCutsR[nCutsR], pBest->nFlowRefs ); nCutsR = Mf_SetAddCut( pCutsR, nCutsR, nCutNum ); } } if ( Gia_ObjIsMuxId(p->pGia, iObj) ) { Mf_Cut_t pCuts2[MF_CUT_MAX]; int nCuts2 = Mf_ManPrepareCuts(pCuts2, p, Gia_ObjFaninId2(p->pGia, iObj), 1); int fComp2 = Gia_ObjFaninC2(p->pGia, pObj); Mf_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; p->CutCount[0] += nCuts0 * nCuts1 * nCuts2; for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) { if ( Mf_CutCountBits(pCut0->Sign | pCut1->Sign | pCut2->Sign) > nLutSize ) continue; p->CutCount[1]++; if ( !Mf_CutMergeOrderMux(pCut0, pCut1, pCut2, pCutsR[nCutsR], nLutSize) ) continue; if ( Mf_SetLastCutIsContained(pCutsR, nCutsR) ) continue; p->CutCount[2]++; if ( p->pPars->fCutMin && Mf_CutComputeTruthMux(p, pCut0, pCut1, pCut2, fComp0, fComp1, fComp2, pCutsR[nCutsR]) ) pCutsR[nCutsR]->Sign = Mf_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); Mf_CutParams( p, pCutsR[nCutsR], pBest->nFlowRefs ); nCutsR = Mf_SetAddCut( pCutsR, nCutsR, nCutNum ); } } else { int fIsXor = Gia_ObjIsXor(pObj); p->CutCount[0] += nCuts0 * nCuts1; for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) { if ( (int)(pCut0->nLeaves + pCut1->nLeaves) > nLutSize && Mf_CutCountBits(pCut0->Sign | pCut1->Sign) > nLutSize ) continue; p->CutCount[1]++; if ( !Mf_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], nLutSize) ) continue; if ( Mf_SetLastCutIsContained(pCutsR, nCutsR) ) continue; p->CutCount[2]++; if ( p->pPars->fCutMin && Mf_CutComputeTruth(p, pCut0, pCut1, fComp0, fComp1, pCutsR[nCutsR], fIsXor) ) pCutsR[nCutsR]->Sign = Mf_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); Mf_CutParams( p, pCutsR[nCutsR], pBest->nFlowRefs ); nCutsR = Mf_SetAddCut( pCutsR, nCutsR, nCutNum ); } } // debug printout if ( 0 ) // if ( iObj % 1000 == 0 ) // if ( iObj == 474 ) { printf( "*** Obj = %d FlowRefs = %.2f MapRefs = %2d\n", iObj, pBest->nFlowRefs, pBest->nMapRefs ); for ( i = 0; i < nCutsR; i++ ) Mf_CutPrint( p, pCutsR[i] ); printf( "\n" ); } // store the cutset pBest->Flow = pCutsR[0]->Flow; pBest->Delay = pCutsR[0]->Delay; pBest->iCutSet = Mf_ManSaveCuts( p, pCutsR, nCutsR ); // verify assert( nCutsR > 0 && nCutsR < nCutNum ); // assert( Mf_SetCheckArray(pCutsR, nCutsR) ); p->nCutCounts[pCutsR[0]->nLeaves]++; p->CutCount[3] += nCutsR; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mf_ManSetFlowRefs( Gia_Man_t * p, Vec_Int_t * vRefs ) { int fDiscount = 1; Gia_Obj_t * pObj, * pCtrl, * pData0, * pData1; int i, Id; Vec_IntFill( vRefs, Gia_ManObjNum(p), 0 ); Gia_ManForEachAnd( p, pObj, i ) { if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ) Vec_IntAddToEntry( vRefs, Gia_ObjFaninId0(pObj, i), 1 ); if ( Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) ) Vec_IntAddToEntry( vRefs, Gia_ObjFaninId1(pObj, i), 1 ); if ( p->pMuxes ) { if ( Gia_ObjIsMuxId(p, i) && Gia_ObjIsAnd(Gia_ObjFanin2(p, pObj)) ) Vec_IntAddToEntry( vRefs, Gia_ObjFaninId2(p, i), 1 ); } else if ( fDiscount && Gia_ObjIsMuxType(pObj) ) // discount XOR/MUX { pCtrl = Gia_Regular(Gia_ObjRecognizeMux(pObj, &pData1, &pData0)); pData0 = Gia_Regular(pData0); pData1 = Gia_Regular(pData1); if ( Gia_ObjIsAnd(pCtrl) ) Vec_IntAddToEntry( vRefs, Gia_ObjId(p, pCtrl), -1 ); if ( pData0 == pData1 && Gia_ObjIsAnd(pData0) ) Vec_IntAddToEntry( vRefs, Gia_ObjId(p, pData0), -1 ); } } Gia_ManForEachCoDriverId( p, Id, i ) if ( Gia_ObjIsAnd(Gia_ManObj(p, Id)) ) Vec_IntAddToEntry( vRefs, Id, 1 ); for ( i = 0; i < Vec_IntSize(vRefs); i++ ) Vec_IntUpdateEntry( vRefs, i, 1 ); } int Mf_ManSetMapRefs( Mf_Man_t * p ) { float Coef = 1.0 / (1.0 + (p->Iter + 1) * (p->Iter + 1)); int * pCut, i, k, Id; // compute delay int Delay = 0; Gia_ManForEachCoDriverId( p->pGia, Id, i ) Delay = Abc_MaxInt( Delay, Mf_ManObj(p, Id)->Delay ); // check delay target if ( p->pPars->DelayTarget == -1 && p->pPars->nRelaxRatio ) p->pPars->DelayTarget = (int)((float)Delay * (100.0 + p->pPars->nRelaxRatio) / 100.0); if ( p->pPars->DelayTarget != -1 ) { if ( Delay < p->pPars->DelayTarget + 0.01 ) Delay = p->pPars->DelayTarget; else if ( p->pPars->nRelaxRatio == 0 ) Abc_Print( 0, "Relaxing user-specified delay target from %d to %d.\n", p->pPars->DelayTarget, Delay ); } p->pPars->Delay = Delay; // check references // Gia_ManForEachAndId( p->pGia, i ) // assert( Mf_ManObj(p, i)->nMapRefs == 0 ); // compute area and edges if ( !p->fUseEla ) Gia_ManForEachCoDriverId( p->pGia, Id, i ) Mf_ObjMapRefInc( p, Id ); p->pPars->Area = p->pPars->Edge = p->pPars->Clause = 0; Gia_ManForEachAndReverseId( p->pGia, i ) { if ( !Mf_ObjMapRefNum(p, i) ) continue; pCut = Mf_ObjCutBest( p, i ); if ( !p->fUseEla ) for ( k = 1; k <= Mf_CutSize(pCut); k++ ) Mf_ObjMapRefInc( p, pCut[k] ); p->pPars->Edge += Mf_CutSize(pCut); p->pPars->Area++; if ( p->pPars->fGenCnf || p->pPars->fGenLit ) p->pPars->Clause += Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); } // blend references for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ ) p->pLfObjs[i].nFlowRefs = Coef * p->pLfObjs[i].nFlowRefs + (1.0 - Coef) * Abc_MaxFloat(1, p->pLfObjs[i].nMapRefs); // p->pLfObjs[i]. = 0.2 * p->pLfObjs[i]. + 0.8 * Abc_MaxFloat(1, p->pLfObjs[i].nMapRefs); return p->pPars->Area; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Mf_ManDeriveMapping( Mf_Man_t * p ) { Vec_Int_t * vMapping; int i, k, * pCut; assert( !p->pPars->fCutMin && p->pGia->vMapping == NULL ); vMapping = Vec_IntAlloc( Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); Vec_IntFill( vMapping, Gia_ManObjNum(p->pGia), 0 ); Gia_ManForEachAndId( p->pGia, i ) { if ( !Mf_ObjMapRefNum(p, i) ) continue; pCut = Mf_ObjCutBest( p, i ); Vec_IntWriteEntry( vMapping, i, Vec_IntSize(vMapping) ); Vec_IntPush( vMapping, Mf_CutSize(pCut) ); for ( k = 1; k <= Mf_CutSize(pCut); k++ ) Vec_IntPush( vMapping, pCut[k] ); Vec_IntPush( vMapping, i ); } assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); p->pGia->vMapping = vMapping; return p->pGia; } Gia_Man_t * Mf_ManDeriveMappingCoarse( Mf_Man_t * p ) { Gia_Man_t * pNew, * pGia = p->pGia; Gia_Obj_t * pObj; int i, k, * pCut; assert( !p->pPars->fCutMin && pGia->pMuxes ); // create new manager pNew = Gia_ManStart( Gia_ManObjNum(pGia) ); pNew->pName = Abc_UtilStrsav( pGia->pName ); pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); // map primary inputs Gia_ManConst0(pGia)->Value = 0; Gia_ManForEachCi( pGia, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); // start mapping pNew->vMapping = Vec_IntAlloc( Gia_ManObjNum(pGia) + 2*Gia_ManXorNum(pGia) + 2*Gia_ManMuxNum(pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); Vec_IntFill( pNew->vMapping, Gia_ManObjNum(pGia) + 2*Gia_ManXorNum(pGia) + 2*Gia_ManMuxNum(pGia), 0 ); // iterate through nodes used in the mapping Gia_ManForEachAnd( pGia, pObj, i ) { if ( Gia_ObjIsMuxId(pGia, i) ) pObj->Value = Gia_ManAppendMux( pNew, Gia_ObjFanin2Copy(pGia, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); else 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) ); if ( !Mf_ObjMapRefNum(p, i) ) continue; pCut = Mf_ObjCutBest( p, i ); Vec_IntWriteEntry( pNew->vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(pNew->vMapping) ); Vec_IntPush( pNew->vMapping, Mf_CutSize(pCut)); for ( k = 1; k <= Mf_CutSize(pCut); k++ ) Vec_IntPush( pNew->vMapping, Abc_Lit2Var(Gia_ManObj(pGia, pCut[k])->Value) ); Vec_IntPush( pNew->vMapping, Abc_Lit2Var(pObj->Value) ); } Gia_ManForEachCo( pGia, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); assert( Vec_IntCap(pNew->vMapping) == 16 || Vec_IntSize(pNew->vMapping) == Vec_IntCap(pNew->vMapping) ); return pNew; } Gia_Man_t * Mf_ManDeriveMappingGia( Mf_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; Vec_Int_t * vCopies = Vec_IntStartFull( Gia_ManObjNum(p->pGia) ); Vec_Int_t * vMapping = Vec_IntStart( 2 * Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + 2 * (int)p->pPars->Area ); Vec_Int_t * vMapping2 = Vec_IntStart( (int)p->pPars->Edge + 2 * (int)p->pPars->Area + 1000 ); Vec_Int_t * vCover = Vec_IntAlloc( 1 << 16 ); Vec_Int_t * vLeaves = Vec_IntAlloc( 16 ); int i, k, Id, iLit, * pCut; word uTruth = 0, * pTruth = &uTruth; assert( p->pPars->fCutMin ); // create new manager pNew = Gia_ManStart( Gia_ManObjNum(p->pGia) ); pNew->pName = Abc_UtilStrsav( p->pGia->pName ); pNew->pSpec = Abc_UtilStrsav( p->pGia->pSpec ); // map primary inputs Vec_IntWriteEntry( vCopies, 0, 0 ); Gia_ManForEachCiId( p->pGia, Id, i ) Vec_IntWriteEntry( vCopies, Id, Gia_ManAppendCi(pNew) ); // iterate through nodes used in the mapping Gia_ManForEachAnd( p->pGia, pObj, i ) { if ( !Mf_ObjMapRefNum(p, i) ) continue; pCut = Mf_ObjCutBest( p, i ); if ( Mf_CutSize(pCut) == 0 ) { assert( Abc_Lit2Var(Mf_CutFunc(pCut)) == 0 ); Vec_IntWriteEntry( vCopies, i, Mf_CutFunc(pCut) ); continue; } if ( Mf_CutSize(pCut) == 1 ) { assert( Abc_Lit2Var(Mf_CutFunc(pCut)) == 1 ); iLit = Vec_IntEntry( vCopies, pCut[1] ); Vec_IntWriteEntry( vCopies, i, Abc_LitNotCond(iLit, Abc_LitIsCompl(Mf_CutFunc(pCut))) ); continue; } Vec_IntClear( vLeaves ); for ( k = 1; k <= Mf_CutSize(pCut); k++ ) Vec_IntPush( vLeaves, Vec_IntEntry(vCopies, pCut[k]) ); pTruth = Vec_MemReadEntry( p->vTtMem, Abc_Lit2Var(Mf_CutFunc(pCut)) ); iLit = Kit_TruthToGia( pNew, (unsigned *)pTruth, Vec_IntSize(vLeaves), vCover, vLeaves, 0 ); Vec_IntWriteEntry( vCopies, i, Abc_LitNotCond(iLit, Abc_LitIsCompl(Mf_CutFunc(pCut))) ); // create mapping Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLit), Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); Vec_IntForEachEntry( vLeaves, iLit, k ) Vec_IntPush( vMapping2, Abc_Lit2Var(iLit) ); Vec_IntPush( vMapping2, Abc_Lit2Var(Vec_IntEntry(vCopies, i)) ); } Gia_ManForEachCo( p->pGia, pObj, i ) { iLit = Vec_IntEntry( vCopies, Gia_ObjFaninId0p(p->pGia, pObj) ); iLit = Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); } Vec_IntFree( vCopies ); Vec_IntFree( vCover ); Vec_IntFree( vLeaves ); // finish mapping if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) ) Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) ); else Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 ); assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) ); Vec_IntForEachEntry( vMapping, iLit, i ) if ( iLit > 0 ) Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) ); Vec_IntAppend( vMapping, vMapping2 ); Vec_IntFree( vMapping2 ); // attach mapping and packing assert( pNew->vMapping == NULL ); pNew->vMapping = vMapping; Gia_ManSetRegNum( pNew, Gia_ManRegNum(p->pGia) ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mf_Man_t * Mf_ManAlloc( Gia_Man_t * pGia, Jf_Par_t * pPars ) { Mf_Man_t * p; Vec_Int_t * vFlowRefs; int i, Entry; assert( pPars->nCutNum > 1 && pPars->nCutNum <= MF_CUT_MAX ); assert( pPars->nLutSize > 1 && pPars->nLutSize <= MF_LEAF_MAX ); ABC_FREE( pGia->pRefs ); Vec_IntFreeP( &pGia->vMapping ); if ( Gia_ManHasChoices(pGia) ) Gia_ManSetPhase(pGia); p = ABC_CALLOC( Mf_Man_t, 1 ); p->clkStart = Abc_Clock(); p->pGia = pGia; p->pPars = pPars; p->vTtMem = pPars->fCutMin ? Vec_MemAllocForTT( pPars->nLutSize, 0 ) : NULL; p->pLfObjs = ABC_CALLOC( Mf_Obj_t, Gia_ManObjNum(pGia) ); p->iCur = 2; Vec_PtrGrow( &p->vPages, 256 ); if ( pPars->fGenCnf || pPars->fGenLit ) { Vec_IntGrow( &p->vCnfSizes, 10000 ); Vec_IntPush( &p->vCnfSizes, 1 ); Vec_IntPush( &p->vCnfSizes, 2 ); Vec_IntGrow( &p->vCnfMem, 10000 ); } vFlowRefs = Vec_IntAlloc(0); Mf_ManSetFlowRefs( pGia, vFlowRefs ); Vec_IntForEachEntry( vFlowRefs, Entry, i ) p->pLfObjs[i].nFlowRefs = Entry; Vec_IntFree(vFlowRefs); return p; } void Mf_ManFree( Mf_Man_t * p ) { 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 ) Vec_MemFree( p->vTtMem ); Vec_PtrFreeData( &p->vPages ); ABC_FREE( p->vCnfSizes.pArray ); ABC_FREE( p->vCnfMem.pArray ); ABC_FREE( p->vPages.pArray ); ABC_FREE( p->vTemp.pArray ); ABC_FREE( p->pLfObjs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mf_ManSetDefaultPars( Jf_Par_t * pPars ) { memset( pPars, 0, sizeof(Jf_Par_t) ); pPars->nLutSize = 6; pPars->nCutNum = 8; pPars->nProcNum = 0; pPars->nRounds = 2; pPars->nRoundsEla = 1; pPars->nRelaxRatio = 0; pPars->nCoarseLimit = 3; pPars->nAreaTuner = 1; pPars->nVerbLimit = 5; pPars->DelayTarget = -1; pPars->fAreaOnly = 0; pPars->fOptEdge = 1; pPars->fCoarsen = 1; pPars->fCutMin = 0; pPars->fGenCnf = 0; pPars->fGenLit = 0; pPars->fPureAig = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; pPars->nLutSizeMax = MF_LEAF_MAX; pPars->nCutNumMax = MF_CUT_MAX; } void Mf_ManPrintStats( Mf_Man_t * p, char * pTitle ) { if ( !p->pPars->fVerbose ) return; printf( "%s : ", pTitle ); printf( "Level =%6lu ", (long)p->pPars->Delay ); printf( "Area =%9lu ", (long)p->pPars->Area ); 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 ); } void Mf_ManPrintInit( Mf_Man_t * p ) { if ( !p->pPars->fVerbose ) return; printf( "LutSize = %d ", p->pPars->nLutSize ); printf( "CutNum = %d ", p->pPars->nCutNum ); printf( "Iter = %d ", p->pPars->nRounds + p->pPars->nRoundsEla ); printf( "Edge = %d ", p->pPars->fOptEdge ); 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 ); } void Mf_ManPrintQuit( Mf_Man_t * p, Gia_Man_t * pNew ) { float MemGia = Gia_ManMemory(p->pGia) / (1<<20); float MemMan = 1.0 * sizeof(Mf_Obj_t) * Gia_ManObjNum(p->pGia) / (1<<20); float MemCuts = 1.0 * sizeof(int) * (1 << 16) * Vec_PtrSize(&p->vPages) / (1<<20); float MemTt = p->vTtMem ? Vec_MemMemory(p->vTtMem) / (1<<20) : 0; float MemMap = Vec_IntMemory(pNew->vMapping) / (1<<20); if ( p->CutCount[0] == 0 ) p->CutCount[0] = 1; if ( !p->pPars->fVerbose ) return; 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( "\n" ); printf( "Gia = %.2f MB ", MemGia ); printf( "Man = %.2f MB ", MemMan ); printf( "Cut = %.2f MB ", MemCuts ); printf( "Map = %.2f MB ", MemMap ); printf( "TT = %.2f MB ", MemTt ); printf( "Total = %.2f MB", MemGia + MemMan + MemCuts + MemMap + MemTt ); printf( "\n" ); if ( 1 ) { int i; for ( i = 0; i <= p->pPars->nLutSize; i++ ) printf( "%d = %d ", i, p->nCutCounts[i] ); if ( p->vTtMem ) printf( "TT = %d (%.2f %%) ", Vec_MemEntryNum(p->vTtMem), 100.0 * Vec_MemEntryNum(p->vTtMem) / p->CutCount[2] ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); } fflush( stdout ); } void Mf_ManComputeCuts( Mf_Man_t * p ) { int i; Gia_ManForEachAndId( p->pGia, i ) Mf_ObjMergeOrder( p, i ); Mf_ManSetMapRefs( p ); Mf_ManPrintStats( p, (char *)(p->fUseEla ? "Ela " : (p->Iter ? "Area " : "Delay")) ); } /**Function************************************************************* Synopsis [Flow and area.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Mf_CutRef_rec( Mf_Man_t * p, int * pCut ) { int i, Count = Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); for ( i = 1; i <= Mf_CutSize(pCut); i++ ) if ( !Mf_ObjMapRefInc(p, pCut[i]) && Mf_ManObj(p, pCut[i])->iCutSet ) Count += Mf_CutRef_rec( p, Mf_ObjCutBest(p, pCut[i]) ); return Count; } int Mf_CutDeref_rec( Mf_Man_t * p, int * pCut ) { 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_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_CutRef2_rec( p, Mf_ObjCutBest(p, pCut[i]), vTemp, Limit-1 ); } return Count; } 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_CutDeref2_rec( p, Mf_ObjCutBest(p, pCut[i]), vTemp, Limit-1 ); } return Count; } static inline int Mf_CutAreaRefed2( Mf_Man_t * p, int * pCut ) { 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; float Flow = 0; int i, Time = 0; for ( i = 1; i <= Mf_CutSize(pCut); i++ ) { pObj = Mf_ManObj( p, pCut[i] ); Time = Abc_MaxInt( Time, pObj->Delay ); Flow += pObj->Flow; } *pTime = Time + 1; return Flow + Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); } static inline void Mf_ObjComputeBestCut( Mf_Man_t * p, int iObj ) { Mf_Obj_t * pBest = Mf_ManObj(p, iObj); int * pCutSet = Mf_ObjCutSet( p, iObj ); int * pCut, * pCutBest = NULL; int Value1 = -1, Value2 = -1; int i, Time = 0, TimeBest = ABC_INFINITY; float Flow, FlowBest = ABC_INFINITY; if ( p->fUseEla && pBest->nMapRefs ) Value1 = Mf_CutDeref_rec( p, Mf_ObjCutBest(p, iObj) ); Mf_SetForEachCut( pCutSet, pCut, i ) { assert( !Mf_CutIsTriv(pCut, iObj) ); assert( Mf_CutSize(pCut) <= p->pPars->nLutSize ); Flow = p->fUseEla ? Mf_CutAreaDerefed2(p, pCut) : Mf_CutFlow(p, pCut, &Time); if ( pCutBest == NULL || FlowBest > Flow + MF_EPSILON || (FlowBest > Flow - MF_EPSILON && TimeBest > Time) ) pCutBest = pCut, FlowBest = Flow, TimeBest = Time; } assert( pCutBest != NULL ); if ( p->fUseEla && pBest->nMapRefs ) Value1 = Mf_CutRef_rec( p, pCutBest ); else pBest->nMapRefs = 0; assert( Value1 >= Value2 ); if ( p->fUseEla ) Mf_CutFlow( p, pCutBest, &TimeBest ); pBest->Delay = TimeBest; pBest->Flow = FlowBest / Mf_ManObj(p, iObj)->nFlowRefs; Mf_ObjSetBestCut( pCutSet, pCutBest ); // Mf_CutPrint( Mf_ObjCutBest(p, iObj) ); printf( "\n" ); } /**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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mf_ManComputeMapping( Mf_Man_t * p ) { int i; Gia_ManForEachAndId( p->pGia, i ) Mf_ObjComputeBestCut( p, i ); Mf_ManSetMapRefs( p ); Mf_ManPrintStats( p, (char *)(p->fUseEla ? "Ela " : (p->Iter ? "Area " : "Delay")) ); } 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 || pPars->fGenLit ) pPars->fCutMin = 1; if ( Gia_ManHasChoices(pGia) ) pPars->fCutMin = 1, pPars->fCoarsen = 0; pCls = pPars->fCoarsen ? Gia_ManDupMuxes(pGia, pPars->nCoarseLimit) : pGia; p = Mf_ManAlloc( pCls, pPars ); p->pGia0 = pGia; if ( pPars->fVerbose && pPars->fCoarsen ) { printf( "Initial " ); Gia_ManPrintMuxStats( pGia ); printf( "\n" ); printf( "Derived " ); Gia_ManPrintMuxStats( pCls ); printf( "\n" ); } Mf_ManPrintInit( p ); Mf_ManComputeCuts( p ); for ( p->Iter = 1; p->Iter < p->pPars->nRounds; p->Iter++ ) Mf_ManComputeMapping( p ); 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 ) pNew = Mf_ManDeriveMappingGia( p ); else if ( pPars->fCoarsen ) pNew = Mf_ManDeriveMappingCoarse( p ); else pNew = Mf_ManDeriveMapping( p ); if ( p->pPars->fGenCnf ) pGia->pData = Mf_ManDeriveCnf( p, p->pPars->fCnfObjIds, p->pPars->fAddOrCla ); //if ( p->pPars->fGenCnf || p->pPars->fGenLit ) // Mf_ManProfileTruths( p ); Gia_ManMappingVerify( pNew ); Mf_ManPrintQuit( p, pNew ); Mf_ManFree( p ); if ( pCls != pGia ) Gia_ManStop( pCls ); return pNew; } /**Function************************************************************* Synopsis [CNF generation] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fMapping, int fVerbose ) { Gia_Man_t * pNew; Jf_Par_t Pars, * pPars = &Pars; assert( nLutSize >= 3 && nLutSize <= 8 ); Mf_ManSetDefaultPars( pPars ); pPars->fGenCnf = 1; pPars->fCoarsen = !fCnfObjIds; pPars->nLutSize = nLutSize; pPars->fCnfObjIds = fCnfObjIds; pPars->fAddOrCla = fAddOrCla; pPars->fCnfMapping = fMapping; pPars->fVerbose = fVerbose; pNew = Mf_ManPerformMapping( pGia, pPars ); Gia_ManStopP( &pNew ); // Cnf_DataPrint( (Cnf_Dat_t *)pGia->pData, 1 ); return pGia->pData; } void Mf_ManDumpCnf( Gia_Man_t * p, char * pFileName, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ) { abctime clk = Abc_Clock(); Cnf_Dat_t * pCnf; pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, nLutSize, fCnfObjIds, fAddOrCla, 0, fVerbose ); Cnf_DataWriteIntoFile( pCnf, pFileName, 0, NULL, NULL ); // if ( fVerbose ) { printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } Cnf_DataFree(pCnf); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaMffc.c000066400000000000000000000232371477524141600157760ustar00rootroot00000000000000/**CFile**************************************************************** FileName [gia.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 /// //////////////////////////////////////////////////////////////////////// static inline int Gia_ObjDom( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Vec_IntEntry(p->vDoms, Gia_ObjId(p, pObj)); } static inline void Gia_ObjSetDom( Gia_Man_t * p, Gia_Obj_t * pObj, int d ) { Vec_IntWriteEntry(p->vDoms, Gia_ObjId(p, pObj), d); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes one-node dominators.] Description [For each node, computes the closest one-node dominator, which can be the node itself if the node has no other dominators.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManAddDom( Gia_Man_t * p, Gia_Obj_t * pObj, int iDom0 ) { int iDom1, iDomNext; if ( Gia_ObjDom(p, pObj) == -1 ) { Gia_ObjSetDom( p, pObj, iDom0 ); return; } iDom1 = Gia_ObjDom( p, pObj ); while ( 1 ) { if ( iDom0 > iDom1 ) { iDomNext = Gia_ObjDom( p, Gia_ManObj(p, iDom1) ); if ( iDomNext == iDom1 ) break; iDom1 = iDomNext; continue; } if ( iDom1 > iDom0 ) { iDomNext = Gia_ObjDom( p, Gia_ManObj(p, iDom0) ); if ( iDomNext == iDom0 ) break; iDom0 = iDomNext; continue; } assert( iDom0 == iDom1 ); Gia_ObjSetDom( p, pObj, iDom0 ); return; } Gia_ObjSetDom( p, pObj, Gia_ObjId(p, pObj) ); } static inline void Gia_ManComputeDoms( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; if ( p->vDoms == NULL ) p->vDoms = Vec_IntAlloc( 0 ); Vec_IntFill( p->vDoms, Gia_ManObjNum(p), -1 ); Gia_ManForEachObjReverse( p, pObj, i ) { if ( i == 0 || Gia_ObjIsCi(pObj) ) continue; if ( Gia_ObjIsCo(pObj) ) { Gia_ObjSetDom( p, pObj, i ); Gia_ManAddDom( p, Gia_ObjFanin0(pObj), i ); continue; } assert( Gia_ObjIsAnd(pObj) ); Gia_ManAddDom( p, Gia_ObjFanin0(pObj), i ); Gia_ManAddDom( p, Gia_ObjFanin1(pObj), i ); } } /**Function************************************************************* Synopsis [Returns the number of internal nodes in the MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_NodeDeref_rec( Gia_Man_t * p, Gia_Obj_t * pNode ) { Gia_Obj_t * pFanin; int Counter = 0; if ( Gia_ObjIsCi(pNode) ) return 0; assert( Gia_ObjIsAnd(pNode) ); pFanin = Gia_ObjFanin0(pNode); assert( Gia_ObjRefNum(p, pFanin) > 0 ); if ( Gia_ObjRefDec(p, pFanin) == 0 ) Counter += Gia_NodeDeref_rec( p, pFanin ); pFanin = Gia_ObjFanin1(pNode); assert( Gia_ObjRefNum(p, pFanin) > 0 ); if ( Gia_ObjRefDec(p, pFanin) == 0 ) Counter += Gia_NodeDeref_rec( p, pFanin ); return Counter + 1; } static inline int Gia_NodeRef_rec( Gia_Man_t * p, Gia_Obj_t * pNode ) { Gia_Obj_t * pFanin; int Counter = 0; if ( Gia_ObjIsCi(pNode) ) return 0; assert( Gia_ObjIsAnd(pNode) ); pFanin = Gia_ObjFanin0(pNode); if ( Gia_ObjRefInc(p, pFanin) == 0 ) Counter += Gia_NodeRef_rec( p, pFanin ); pFanin = Gia_ObjFanin1(pNode); if ( Gia_ObjRefInc(p, pFanin) == 0 ) Counter += Gia_NodeRef_rec( p, pFanin ); return Counter + 1; } static inline void Gia_NodeCollect_rec( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp, Vec_Int_t * vSuppRefs ) { if ( Gia_ObjIsTravIdCurrent(p, pNode) ) return; Gia_ObjSetTravIdCurrent(p, pNode); if ( Gia_ObjRefNum(p, pNode) || Gia_ObjIsCi(pNode) ) { Vec_IntPush( vSupp, Gia_ObjId(p, pNode) ); Vec_IntPush( vSuppRefs, Gia_ObjRefNum(p, pNode) ); return; } assert( Gia_ObjIsAnd(pNode) ); Gia_NodeCollect_rec( p, Gia_ObjFanin0(pNode), vSupp, vSuppRefs ); Gia_NodeCollect_rec( p, Gia_ObjFanin1(pNode), vSupp, vSuppRefs ); } static inline int Gia_NodeMffcSizeSupp( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp, Vec_Int_t * vSuppRefs ) { int ConeSize1, ConeSize2, i, iObj; assert( !Gia_IsComplement(pNode) ); assert( Gia_ObjIsAnd(pNode) ); Vec_IntClear( vSupp ); Vec_IntClear( vSuppRefs ); Gia_ManIncrementTravId( p ); ConeSize1 = Gia_NodeDeref_rec( p, pNode ); Gia_NodeCollect_rec( p, Gia_ObjFanin0(pNode), vSupp, vSuppRefs ); Gia_NodeCollect_rec( p, Gia_ObjFanin1(pNode), vSupp, vSuppRefs ); ConeSize2 = Gia_NodeRef_rec( p, pNode ); assert( ConeSize1 == ConeSize2 ); assert( ConeSize1 >= 0 ); // record supp refs Vec_IntForEachEntry( vSupp, iObj, i ) Vec_IntAddToEntry( vSuppRefs, i, -Gia_ObjRefNumId(p, iObj) ); return ConeSize1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManDomDerive_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pNode ) { if ( Gia_ObjIsTravIdCurrent(p, pNode) ) return pNode->Value; Gia_ObjSetTravIdCurrent(p, pNode); assert( Gia_ObjIsAnd(pNode) ); Gia_ManDomDerive_rec( pNew, p, Gia_ObjFanin0(pNode) ); Gia_ManDomDerive_rec( pNew, p, Gia_ObjFanin1(pNode) ); return pNode->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pNode), Gia_ObjFanin1Copy(pNode) ); } Gia_Man_t * Gia_ManDomDerive( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vSupp, int nVars ) { Gia_Man_t * pNew, * pTemp; int nMints = 1 << nVars; int i, m, iResLit; assert( nVars >= 0 && nVars <= 5 ); 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 ); for ( i = 0; i < Vec_IntSize(vSupp); i++ ) Gia_ManAppendCi(pNew); for ( m = 0; m < nMints; m++ ) { Gia_Obj_t * pObj; Gia_ManIncrementTravId( p ); Gia_ManForEachObjVec( vSupp, p, pObj, i ) { if ( i < nVars ) pObj->Value = (m >> i) & 1; else pObj->Value = Gia_ObjToLit(pNew, Gia_ManCi(pNew, i)); Gia_ObjSetTravIdCurrent( p, pObj ); } iResLit = Gia_ManDomDerive_rec( pNew, p, pRoot ); Gia_ManAppendCo( pNew, iResLit ); } Gia_ManHashStop( pNew ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManComputeDomsTry( Gia_Man_t * p ) { extern void Gia_ManCollapseTestTest( Gia_Man_t * p ); Vec_Int_t * vSupp, * vSuppRefs; Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, nSize, Entry, k; abctime clk = Abc_Clock(); ABC_FREE( p->pRefs ); Gia_ManLevelNum( p ); Gia_ManCreateRefs( p ); Gia_ManComputeDoms( p ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); vSupp = Vec_IntAlloc( 1000 ); vSuppRefs = Vec_IntAlloc( 1000 ); Gia_ManForEachObj( p, pObj, i ) { if ( !Gia_ObjIsAnd(pObj) && !Gia_ObjIsCo(pObj) ) continue; if ( Gia_ObjDom(p, pObj) != i ) continue; if ( Gia_ObjIsCo(pObj) ) pObj = Gia_ObjFanin0(pObj); if ( !Gia_ObjIsAnd(pObj) ) continue; nSize = Gia_NodeMffcSizeSupp( p, pObj, vSupp, vSuppRefs ); if ( nSize < 10 )//|| nSize > 100 ) continue; // sort by cost Vec_IntSelectSortCost2( Vec_IntArray(vSupp), Vec_IntSize(vSupp), Vec_IntArray(vSuppRefs) ); printf( "Obj %6d : ", i ); printf( "Cone = %4d ", nSize ); printf( "Supp = %4d ", Vec_IntSize(vSupp) ); // Vec_IntForEachEntry( vSuppRefs, Entry, k ) // printf( "%d(%d) ", -Entry, Gia_ObjLevelId(p, Vec_IntEntry(vSupp, k)) ); printf( "\n" ); // selected k for ( k = 0; k < Vec_IntSize(vSupp); k++ ) if ( Vec_IntEntry(vSuppRefs, k) == 1 ) break; k = Abc_MinInt( k, 3 ); k = 0; // dump pNew = Gia_ManDomDerive( p, pObj, vSupp, k ); Gia_DumpAiger( pNew, "mffc", i, 6 ); Gia_ManCollapseTestTest( pNew ); Gia_ManStop( pNew ); } Vec_IntFree( vSuppRefs ); Vec_IntFree( vSupp ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaMfs.c000066400000000000000000000544031477524141600156470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaMfs.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Interface with the MFS package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaMfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "opt/sfm/sfm.h" #include "misc/tim/tim.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p ) { word uTruth, * pTruth, uTruths6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; Gia_Obj_t * pObj, * pObjExtra; Vec_Wec_t * vFanins; // mfs data Vec_Str_t * vFixed; // mfs data Vec_Str_t * vEmpty; // mfs data Vec_Str_t * vDenied; // 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, w, nWords; int Id, iFan, nMfsVars, nBbIns = 0, nBbOuts = 0, Counter = 0; 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; // prepare storage nMfsVars = Gia_ManCiNum(p) + 1 + Gia_ManLutNum(p) + Gia_ManCoNum(p) + nBbIns + nBbOuts; vFanins = Vec_WecStart( nMfsVars ); vFixed = Vec_StrStart( nMfsVars ); vEmpty = Vec_StrStart( nMfsVars ); vDenied = Vec_StrStart( nMfsVars ); vTruths = Vec_WrdStart( nMfsVars ); vStarts = Vec_IntStart( nMfsVars ); vTruths2 = Vec_WrdAlloc( 10000 ); // deny the PIs which are modeling blackbox outputs from being considered // in substitutions for (int i = 0; i < nBbOuts; i++) Vec_StrWriteEntry( vDenied, i, (char)1 ); // set internal PIs Gia_ManCleanCopyArray( p ); Gia_ManForEachCiId( p, Id, i ) Gia_ObjSetCopyArray( p, Id, Counter++ ); // set constant node Vec_StrWriteEntry( vFixed, Counter, (char)1 ); Vec_WrdWriteEntry( vTruths, Counter, (word)0 ); Gia_ObjSetCopyArray( p, 0, Counter++ ); // set internal LUTs vLeaves = Vec_IntAlloc( nLutSizeMax ); Gia_ObjComputeTruthTableStart( p, nLutSizeMax ); Gia_ManForEachLut( p, Id ) { Vec_IntClear( vLeaves ); vArray = Vec_WecEntry( vFanins, Counter ); Vec_IntGrow( vArray, Gia_ObjLutSize(p, Id) ); Gia_LutForEachFanin( p, Id, iFan, k ) { assert( Gia_ObjCopyArray(p, iFan) >= 0 ); Vec_IntPush( vArray, Gia_ObjCopyArray(p, iFan) ); Vec_IntPush( vLeaves, iFan ); } 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) ); 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, 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 ); Vec_StrWriteEntry( vEmpty, Counter, (char)1 ); } Gia_ObjSetCopyArray( p, Id, Counter++ ); } Gia_ObjComputeTruthTableStop( p ); // set all POs Gia_ManForEachCo( p, pObj, i ) { iFan = Gia_ObjFaninId0p( p, pObj ); assert( Gia_ObjCopyArray(p, iFan) >= 0 ); vArray = Vec_WecEntry( vFanins, Counter ); Vec_IntFill( vArray, 1, Gia_ObjCopyArray(p, iFan) ); if ( i < Gia_ManCoNum(p) - nRealPos ) // internal PO { Vec_StrWriteEntry( vFixed, Counter, (char)1 ); 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++ ); } // skip POs due to box inputs Counter += nBbIns; assert( Counter == nMfsVars ); // add functions of the boxes if ( p->pAigExtra ) { assert( Gia_ManCiNum(p->pAigExtra) < 16 ); Gia_ObjComputeTruthTableStart( p->pAigExtra, Gia_ManCiNum(p->pAigExtra) ); } { int iBbIn = 0, iBbOut = 0; curCi = nRealPis; curCo = 0; for ( k = 0; k < nBoxes; k++ ) { nBoxIns = Tim_ManBoxInputNum( pManTime, k ); nBoxOuts = Tim_ManBoxOutputNum( pManTime, k ); // iterate through box outputs if ( !Tim_ManBoxIsBlack(pManTime, k) ) //&& Tim_ManBoxInputNum(pManTime, k) <= 6 ) { assert(p->pAigExtra); // 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 pObj = Gia_ManCi( p, curCi + j ); Counter = Gia_ObjCopyArray( p, Gia_ObjId(p, pObj) ); // add box inputs (POs of the AIG) as fanins vArray = Vec_WecEntry( vFanins, Counter ); Vec_IntGrow( vArray, nBoxIns ); for ( i = 0; i < nBoxIns; i++ ) { iFan = Gia_ObjId( p, Gia_ManCo(p, curCo + i) ); assert( Gia_ObjCopyArray(p, iFan) >= 0 ); Vec_IntPush( vArray, Gia_ObjCopyArray(p, iFan) ); } Vec_StrWriteEntry( vFixed, Counter, (char)1 ); // 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 { 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_TtMinBase( pTruth, Vec_IntArray(vArray), Vec_IntSize(vArray), Vec_IntSize(vLeaves) ); Vec_IntShrink( vArray, nVars ); 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 { for ( j = 0; j < nBoxOuts; j++ ) { // CI corresponding to the box outputs pObj = Gia_ManCi( p, curCi + j ); Counter = Gia_ObjCopyArray( p, Gia_ObjId(p, pObj) ); // connect it with the special primary input (iBbOut) vArray = Vec_WecEntry( vFanins, Counter ); assert( Vec_IntSize(vArray) == 0 ); Vec_IntFill( vArray, 1, iBbOut++ ); Vec_StrWriteEntry( vFixed, Counter, (char)1 ); Vec_StrWriteEntry( vEmpty, Counter, (char)1 ); Vec_StrWriteEntry( vDenied, Counter, (char)1 ); Vec_WrdWriteEntry( vTruths, Counter, uTruths6[0] ); } for ( i = 0; i < nBoxIns; i++ ) { // CO corresponding to the box inputs pObj = Gia_ManCo( p, curCo + i ); Counter = Gia_ObjCopyArray( p, Gia_ObjId(p, pObj) ); // connect it with the special primary output (iBbIn) int poNum = nMfsVars - nBbIns + iBbIn++; vArray = Vec_WecEntry( vFanins, poNum ); Vec_StrWriteEntry( vFixed, poNum, (char)1 ); assert( Vec_IntSize(vArray) == 0 ); Vec_IntFill( vArray, 1, Counter ); } } // set internal POs pointing directly to internal PIs as no-delay for ( i = 0; i < nBoxIns; i++ ) { pObj = Gia_ManCo( p, curCo + i ); if ( !Gia_ObjIsCi( Gia_ObjFanin0(pObj) ) ) continue; Counter = Gia_ObjCopyArray( p, Gia_ObjFaninId0p(p, pObj) ); Vec_StrWriteEntry( vEmpty, Counter, (char)1 ); } curCo += nBoxIns; curCi += nBoxOuts; } curCo += nRealPos; // verify counts assert( curCi == Gia_ManCiNum(p) ); assert( curCo == Gia_ManCoNum(p) ); assert( iBbIn == nBbIns ); assert( iBbOut == nBbOuts ); } if (p->pAigExtra) { Gia_ObjComputeTruthTableStop( p->pAigExtra ); assert( curCi - nRealPis == Gia_ManCoNum(p->pAigExtra) ); } // finalize Vec_IntFree( vLeaves ); return Sfm_NtkConstruct( vFanins, nBbOuts + nRealPis, nRealPos + nBbIns, vFixed, vEmpty, vDenied, vTruths, vStarts, vTruths2 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManInsertMfs( Gia_Man_t * p, Sfm_Ntk_t * pNtk, int fAllBoxes ) { extern int Gia_ManFromIfLogicCreateLut( Gia_Man_t * pNew, word * pRes, Vec_Int_t * vLeaves, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 ); Gia_Man_t * pNew; Gia_Obj_t * pObj; Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; int nBoxes = Gia_ManBoxNum(p); int nRealPis = nBoxes ? Tim_ManPiNum(pManTime) : Gia_ManPiNum(p); int nRealPos = nBoxes ? Tim_ManPoNum(pManTime) : Gia_ManPoNum(p); int i, k, Id, curCi, curCo, nBoxIns, nBoxOuts, iLitNew, iMfsId, iGroup, Fanin; int nMfsNodes; word * pTruth, uTruthVar = ABC_CONST(0xAAAAAAAAAAAAAAAA); Vec_Wec_t * vGroups = Vec_WecStart( nBoxes ); Vec_Int_t * vMfs2Gia, * vMfs2Old; Vec_Int_t * vGroupMap; Vec_Int_t * vMfsTopo, * vCover, * vBoxesLeft; Vec_Int_t * vArray, * vLeaves; Vec_Int_t * vMapping, * vMapping2; int nBbIns = 0, nBbOuts = 0; if ( pManTime ) Tim_ManBlackBoxIoNum( pManTime, &nBbIns, &nBbOuts ); nMfsNodes = 1 + Gia_ManCiNum(p) + Gia_ManLutNum(p) + Gia_ManCoNum(p) + nBbIns + nBbOuts; vMfs2Gia = Vec_IntStartFull( nMfsNodes ); vMfs2Old = Vec_IntStartFull( nMfsNodes ); vGroupMap = Vec_IntStartFull( nMfsNodes ); Gia_ManForEachObj( p, pObj, i ) if ( Gia_ObjCopyArray(p, i) > 0 ) Vec_IntWriteEntry( vMfs2Old, Gia_ObjCopyArray(p, i), i ); // collect nodes curCi = nRealPis; curCo = 0; for ( i = 0; i < nBoxes; i++ ) { nBoxIns = Tim_ManBoxInputNum( pManTime, i ); nBoxOuts = Tim_ManBoxOutputNum( pManTime, i ); vArray = Vec_WecEntry( vGroups, i ); for ( k = 0; k < nBoxIns; k++ ) { pObj = Gia_ManCo( p, curCo + k ); iMfsId = Gia_ObjCopyArray( p, Gia_ObjId(p, pObj) ); assert( iMfsId > 0 ); Vec_IntPush( vArray, iMfsId ); Vec_IntWriteEntry( vGroupMap, iMfsId, Abc_Var2Lit(i,0) ); } for ( k = 0; k < nBoxOuts; k++ ) { pObj = Gia_ManCi( p, curCi + k ); iMfsId = Gia_ObjCopyArray( p, Gia_ObjId(p, pObj) ); assert( iMfsId > 0 ); Vec_IntPush( vArray, iMfsId ); Vec_IntWriteEntry( vGroupMap, iMfsId, Abc_Var2Lit(i,1) ); } curCo += nBoxIns; curCi += nBoxOuts; } curCo += nRealPos; assert( curCi == Gia_ManCiNum(p) ); assert( curCo == Gia_ManCoNum(p) ); // collect nodes in the given order vBoxesLeft = Vec_IntAlloc( nBoxes ); vMfsTopo = Sfm_NtkDfs( pNtk, vGroups, vGroupMap, vBoxesLeft, fAllBoxes ); assert( Vec_IntSize(vBoxesLeft) <= nBoxes ); assert( Vec_IntSize(vMfsTopo) > 0 ); // start new GIA pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // start mapping vMapping = Vec_IntStart( Gia_ManObjNum(p) ); vMapping2 = Vec_IntStart( 1 ); // create const LUT Vec_IntWriteEntry( vMapping, 0, Vec_IntSize(vMapping2) ); Vec_IntPush( vMapping2, 0 ); Vec_IntPush( vMapping2, 0 ); // map constant Vec_IntWriteEntry( vMfs2Gia, Gia_ObjCopyArray(p, 0), 0 ); // map primary inputs Gia_ManForEachCiId( p, Id, i ) if ( i < nRealPis ) Vec_IntWriteEntry( vMfs2Gia, Gia_ObjCopyArray(p, Id), Gia_ManAppendCi(pNew) ); // map internal nodes vLeaves = Vec_IntAlloc( 6 ); vCover = Vec_IntAlloc( 1 << 16 ); Vec_IntForEachEntry( vMfsTopo, iMfsId, i ) { pTruth = Sfm_NodeReadTruth( pNtk, iMfsId ); iGroup = Vec_IntEntry( vGroupMap, iMfsId ); vArray = Sfm_NodeReadFanins( pNtk, iMfsId ); // belongs to pNtk if ( Vec_IntSize(vArray) == 1 && Vec_IntEntry(vArray,0) < nBbOuts ) // skip unreal inputs { // create CI for the output of black box assert( Abc_LitIsCompl(iGroup) ); iLitNew = Gia_ManAppendCi( pNew ); Vec_IntWriteEntry( vMfs2Gia, iMfsId, iLitNew ); continue; } Vec_IntClear( vLeaves ); // handle internal CIs first, before we go looking for vLeaves if ( iGroup != -1 && Abc_LitIsCompl(iGroup) ) { //Dau_DsdPrintFromTruth( pTruth, Vec_IntSize(vLeaves) ); iLitNew = Gia_ManAppendCi( pNew ); goto done; } Vec_IntForEachEntry( vArray, Fanin, k ) { iLitNew = Vec_IntEntry( vMfs2Gia, Fanin ); assert( iLitNew >= 0 ); Vec_IntPush( vLeaves, iLitNew ); } if ( iGroup == -1 ) // internal node { assert( Sfm_NodeReadUsed(pNtk, iMfsId) ); if ( Gia_ObjLutIsMux(p, Vec_IntEntry(vMfs2Old, iMfsId)) ) { int MapSize = Vec_IntSize(vMapping2); int nVarsNew; Abc_TtSimplify( pTruth, Vec_IntArray(vLeaves), Vec_IntSize(vLeaves), &nVarsNew ); Vec_IntShrink( vLeaves, nVarsNew ); Abc_TtFlipVar5( pTruth, Vec_IntSize(vLeaves) ); iLitNew = Gia_ManFromIfLogicCreateLut( pNew, pTruth, vLeaves, vCover, vMapping, vMapping2 ); Abc_TtFlipVar5( pTruth, Vec_IntSize(vLeaves) ); if ( MapSize < Vec_IntSize(vMapping2) ) { assert( Vec_IntEntryLast(vMapping2) == Abc_Lit2Var(iLitNew) ); Vec_IntWriteEntry(vMapping2, Vec_IntSize(vMapping2)-1, -Abc_Lit2Var(iLitNew) ); } } else { Abc_TtFlipVar5( pTruth, Vec_IntSize(vLeaves) ); iLitNew = Gia_ManFromIfLogicCreateLut( pNew, pTruth, vLeaves, vCover, vMapping, vMapping2 ); Abc_TtFlipVar5( pTruth, Vec_IntSize(vLeaves) ); } } else // internal CO { assert( pTruth[0] == uTruthVar || pTruth[0] == ~uTruthVar ); iLitNew = Gia_ManAppendCo( pNew, Abc_LitNotCond(Vec_IntEntry(vLeaves, 0), pTruth[0] == ~uTruthVar) ); //printf("Group = %d. po = %d\n", iGroup>>1, iMfsId ); } done: Vec_IntWriteEntry( vMfs2Gia, iMfsId, iLitNew ); } Vec_IntFree( vCover ); Vec_IntFree( vLeaves ); // map primary outputs Gia_ManForEachCo( p, pObj, i ) { if ( i < Gia_ManCoNum(p) - nRealPos ) // internal COs { iMfsId = Gia_ObjCopyArray( p, Gia_ObjId(p, pObj) ); iGroup = Vec_IntEntry( vGroupMap, iMfsId ); if ( Vec_IntFind(vMfsTopo, iGroup) >= 0 ) { iLitNew = Vec_IntEntry( vMfs2Gia, iMfsId ); if ( iLitNew < 0 ) continue; assert( iLitNew >= 0 ); } continue; } iLitNew = Vec_IntEntry( vMfs2Gia, Gia_ObjCopyArray(p, Gia_ObjFaninId0p(p, pObj)) ); assert( iLitNew >= 0 ); Gia_ManAppendCo( pNew, Abc_LitNotCond(iLitNew, Gia_ObjFaninC0(pObj)) ); } // finish mapping if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) ) Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) ); else Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 ); assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) ); Vec_IntForEachEntry( vMapping, iLitNew, i ) if ( iLitNew > 0 ) Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) ); Vec_IntAppend( vMapping, vMapping2 ); Vec_IntFree( vMapping2 ); assert( pNew->vMapping == NULL ); pNew->vMapping = vMapping; // create new timing manager and extra AIG if ( pManTime ) pNew->pManTime = Gia_ManUpdateTimMan2( p, vBoxesLeft, 0 ); // update extra STG if ( p->pAigExtra ) pNew->pAigExtra = Gia_ManUpdateExtraAig2( p->pManTime, p->pAigExtra, vBoxesLeft ); // duplicated flops if ( p->vRegClasses ) pNew->vRegClasses = Vec_IntDup( p->vRegClasses ); // duplicated initial state if ( p->vRegInits ) pNew->vRegInits = Vec_IntDup( p->vRegInits ); pNew->nAnd2Delay = p->nAnd2Delay; // cleanup Vec_WecFree( vGroups ); Vec_IntFree( vMfsTopo ); Vec_IntFree( vGroupMap ); Vec_IntFree( vMfs2Gia ); Vec_IntFree( vMfs2Old ); Vec_IntFree( vBoxesLeft ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManPerformMfs( Gia_Man_t * p, Sfm_Par_t * pPars ) { Sfm_Ntk_t * pNtk; Gia_Man_t * pNew; int nFaninMax, nNodes = 0; assert( Gia_ManRegNum(p) == 0 ); assert( p->vMapping != 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 > 15 ) { Abc_Print( 1, "Currently \"&mfs\" cannot process the network containing nodes with more than 15 fanins.\n" ); return NULL; } // collect information pNtk = Gia_ManExtractMfs( p ); if (pPars->fTestReimport) goto reimport; // perform optimization nNodes = Sfm_NtkPerform( pNtk, pPars ); if ( nNodes == 0 ) { if ( p->pManTime ) Abc_Print( 1, "The network is not changed by \"&mfs\".\n" ); pNew = Gia_ManDup( p ); pNew->vMapping = Vec_IntDup( p->vMapping ); Gia_ManTransferTiming( pNew, p ); } else { reimport: pNew = Gia_ManInsertMfs( p, pNtk, pPars->fAllBoxes ); if( pPars->fVerbose ) Abc_Print( 1, "The network has %d nodes changed by \"&mfs\".\n", nNodes ); // check integrity //Gia_ManCheckIntegrityWithBoxes( pNew ); } Sfm_NtkFree( pNtk ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaMinLut.c000066400000000000000000001163261477524141600163350ustar00rootroot00000000000000/**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[2000]; 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, 2000, 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[2000]; 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, 2000, 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, 2000, 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 abc-0.52/src/aig/gia/giaMinLut2.c000066400000000000000000001373141477524141600164170ustar00rootroot00000000000000/**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 abc-0.52/src/aig/gia/giaMini.c000066400000000000000000001402561477524141600160200ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaMini.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Reader/writer for MiniAIG.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaMini.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "opt/dau/dau.h" #include "base/main/mainInt.h" #include "misc/util/utilTruth.h" #include "aig/miniaig/miniaig.h" #include "aig/miniaig/minilut.h" 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 /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Converts MiniAIG into GIA.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ObjFromMiniFanin0Copy( Gia_Man_t * pGia, Vec_Int_t * vCopies, Mini_Aig_t * p, int Id ) { int Lit = Mini_AigNodeFanin0( p, Id ); return Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(Lit)), Abc_LitIsCompl(Lit) ); } int Gia_ObjFromMiniFanin1Copy( Gia_Man_t * pGia, Vec_Int_t * vCopies, Mini_Aig_t * p, int Id ) { 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, int fGiaSimple ) { 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 if ( fGiaSimple ) pGia->fGiaSimple = fGiaSimple; else 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 ); Vec_IntPush( vCopies, iGiaLit ); } assert( Vec_IntSize(vCopies) == nNodes ); if ( pvCopies ) *pvCopies = vCopies; else Vec_IntFree( vCopies ); Gia_ManSetRegNum( pGia, Mini_AigRegNum(p) ); if ( !fGiaSimple ) { pGia = Gia_ManCleanup( pTemp = pGia ); if ( pvCopies ) Gia_ManDupRemapLiterals( *pvCopies, pTemp ); Gia_ManStop( pTemp ); } return pGia; } /**Function************************************************************* Synopsis [Converts GIA into MiniAIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mini_Aig_t * Gia_ManToMiniAig( Gia_Man_t * pGia ) { Mini_Aig_t * p; Gia_Obj_t * pObj; int i; // create the manager p = Mini_AigStart(); Gia_ManConst0(pGia)->Value = Mini_AigLitConst0(); // create primary inputs Gia_ManForEachCi( pGia, pObj, i ) pObj->Value = Mini_AigCreatePi(p); // create internal nodes Gia_ManForEachAnd( pGia, pObj, i ) pObj->Value = Mini_AigAnd( p, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // create primary outputs Gia_ManForEachCo( pGia, pObj, i ) pObj->Value = Mini_AigCreatePo( p, Gia_ObjFanin0Copy(pObj) ); // set registers Mini_AigSetRegNum( p, Gia_ManRegNum(pGia) ); return p; } /**Function************************************************************* Synopsis [Procedures to input/output MiniAIG into/from internal GIA.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameGiaInputMiniAig( Abc_Frame_t * pAbc, void * p ) { Gia_Man_t * pGia; if ( pAbc == NULL ) 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, 0 ); Abc_FrameUpdateGia( pAbc, pGia ); pAbc->pGiaMiniAig = Gia_ManDup( pGia ); // Gia_ManDelete( pGia ); } void * Abc_FrameGiaOutputMiniAig( Abc_Frame_t * pAbc ) { Gia_Man_t * pGia; if ( pAbc == NULL ) printf( "ABC framework is not initialized by calling Abc_Start()\n" ); pGia = Abc_FrameReadGia( pAbc ); if ( pGia == NULL ) printf( "Current network in ABC framework is not defined.\n" ); return Gia_ManToMiniAig( pGia ); } /**Function************************************************************* Synopsis [Procedures to read/write GIA to/from MiniAIG file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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 * 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 ) { Mini_Aig_t * p = Gia_ManToMiniAig( pGia ); Mini_AigDump( p, pFileName ); //Mini_AigDumpVerilog( "test_miniaig.v", "top", p ); Mini_AigStop( p ); } /**Function************************************************************* Synopsis [Converts MiniLUT into GIA.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFromMiniLut( Mini_Lut_t * p, Vec_Int_t ** pvCopies ) { Gia_Man_t * pGia, * pTemp; Vec_Int_t * vCopies; Vec_Int_t * vCover = Vec_IntAlloc( 1000 ); Vec_Int_t * vLits = Vec_IntAlloc( 100 ); int i, k, Fan, iGiaLit, nNodes; int LutSize = Abc_MaxInt( 2, Mini_LutSize(p) ); // 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 Gia_ManHashAlloc( pGia ); 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 ); word Truth = ((word)*puTruth << 32) | (word)*puTruth; word * pTruth = LutSize < 6 ? &Truth : (word *)puTruth; Vec_IntClear( vLits ); Mini_LutForEachFanin( p, i, Fan, k ) Vec_IntPush( vLits, Vec_IntEntry(vCopies, Fan) ); iGiaLit = Dsm_ManTruthToGia( pGia, pTruth, vLits, vCover ); } else assert( 0 ); Vec_IntPush( vCopies, iGiaLit ); } Vec_IntFree( vCover ); Vec_IntFree( vLits ); Gia_ManHashStop( pGia ); assert( Vec_IntSize(vCopies) == nNodes ); if ( pvCopies ) *pvCopies = vCopies; else Vec_IntFree( vCopies ); Gia_ManSetRegNum( pGia, Mini_LutRegNum(p) ); pGia = Gia_ManCleanup( pTemp = pGia ); if ( pvCopies ) Gia_ManDupRemapLiterals( *pvCopies, pTemp ); Gia_ManStop( pTemp ); 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.] Description [These are LUTs whose all PO fanouts require them in negative polarity. Other fanouts may require them in positive polarity.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Bit_t * Gia_ManFindComplLuts( Gia_Man_t * pGia ) { Gia_Obj_t * pObj; int i; // mark objects pointed by COs in negative polarity Vec_Bit_t * vMarks = Vec_BitStart( Gia_ManObjNum(pGia) ); Gia_ManForEachCo( pGia, pObj, i ) if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) && Gia_ObjFaninC0(pObj) ) Vec_BitWriteEntry( vMarks, Gia_ObjFaninId0p(pGia, pObj), 1 ); // unmark objects pointed by COs in positive polarity Gia_ManForEachCo( pGia, pObj, i ) if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) && !Gia_ObjFaninC0(pObj) ) Vec_BitWriteEntry( vMarks, Gia_ObjFaninId0p(pGia, pObj), 0 ); return vMarks; } /**Function************************************************************* Synopsis [Converts GIA into MiniLUT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mini_Lut_t * Gia_ManToMiniLut( Gia_Man_t * pGia ) { Mini_Lut_t * p; 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) ); LutSize = Gia_ManLutSizeMax( pGia ); LutSize = Abc_MaxInt( LutSize, 2 ); nWords = Abc_Truth6WordNum( LutSize ); assert( LutSize >= 2 ); // create the manager 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 vMarks = Gia_ManFindComplLuts( pGia ); Gia_ObjComputeTruthTableStart( pGia, LutSize ); Gia_ManForEachLut( pGia, i ) { Vec_IntClear( vLeaves ); Gia_LutForEachFanin( pGia, i, iFanin, k ) Vec_IntPush( vLeaves, iFanin ); if ( Vec_IntSize(vLeaves) > 6 ) { int Extra = Vec_IntSize(vLeaves) - 7; for ( k = Extra; k >= 0; k-- ) Vec_IntPush( vLeaves, Vec_IntEntry(vLeaves, k) ); for ( k = Extra; k >= 0; k-- ) Vec_IntDrop( vLeaves, k ); assert( Vec_IntSize(vLeaves) == Gia_ObjLutSize(pGia, i) ); } Gia_ManForEachObjVec( vLeaves, pGia, pFanin, k ) pVars[k] = pFanin->Value; pObj = Gia_ManObj( pGia, i ); pTruth = Gia_ObjComputeTruthTableCut( pGia, pObj, vLeaves ); if ( Vec_BitEntry(vMarks, i) ) Abc_TtNot( pTruth, nWords ); Vec_IntForEachEntry( vLeaves, iFanin, k ) if ( Vec_BitEntry(vMarks, iFanin) ) Abc_TtFlip( pTruth, nWords, k ); pObj->Value = Mini_LutCreateNode( p, Gia_ObjLutSize(pGia, i), pVars, (unsigned *)pTruth ); } Vec_IntFree( vLeaves ); // create inverter truth table Vec_WrdClear( pGia->vTtMemory ); for ( i = 0; i < nWords; i++ ) Vec_WrdPush( pGia->vTtMemory, ABC_CONST(0x5555555555555555) ); pTruth = Vec_WrdArray( pGia->vTtMemory ); // create primary outputs Gia_ManForEachCo( pGia, pObj, i ) { if ( Gia_ObjFanin0(pObj) == Gia_ManConst0(pGia) ) pObj->Value = Mini_LutCreatePo( p, Gia_ObjFaninC0(pObj) ); else if ( Gia_ObjFaninC0(pObj) == Vec_BitEntry(vMarks, Gia_ObjFaninId0p(pGia, pObj)) ) pObj->Value = Mini_LutCreatePo( p, Gia_ObjFanin0(pObj)->Value ); else // add inverter LUT { 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 ); } } Vec_IntFree( vInvMap ); Vec_BitFree( vMarks ); Gia_ObjComputeTruthTableStop( pGia ); // set registers Mini_LutSetRegNum( p, Gia_ManRegNum(pGia) ); //Mini_LutPrintStats( p ); //printf( "Added %d inverters.\n", Count ); return p; } char * Gia_ManToMiniLutAttr( Gia_Man_t * pGia, void * pMiniLut ) { Mini_Lut_t * p = (Mini_Lut_t *)pMiniLut; int i; char * pAttrs = ABC_CALLOC( char, Mini_LutNodeNum(p) ); Gia_ManForEachLut( pGia, i ) if ( Gia_ObjLutIsMux(pGia, i) ) pAttrs[Gia_ManObj(pGia, i)->Value] = 1; return pAttrs; } /**Function************************************************************* Synopsis [Procedures to input/output MiniAIG into/from internal GIA.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameGiaInputMiniLut( Abc_Frame_t * pAbc, void * p ) { Gia_Man_t * pGia; if ( pAbc == NULL ) printf( "ABC framework is not initialized by calling Abc_Start()\n" ); pGia = Gia_ManFromMiniLut( (Mini_Lut_t *)p, NULL ); 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; Gia_Man_t * pGia; if ( pAbc == NULL ) printf( "ABC framework is not initialized by calling Abc_Start()\n" ); Gia_ManStopP( &pAbc->pGiaMiniLut ); Vec_IntFreeP( &pAbc->vCopyMiniLut ); pGia = Abc_FrameReadGia( pAbc ); if ( pGia == NULL ) printf( "Current network in ABC framework is not defined.\n" ); pRes = Gia_ManToMiniLut( pGia ); pAbc->pGiaMiniLut = Gia_ManFromMiniLut( pRes, &pAbc->vCopyMiniLut ); return pRes; } char * Abc_FrameGiaOutputMiniLutAttr( Abc_Frame_t * pAbc, void * pMiniLut ) { Gia_Man_t * pGia; if ( pAbc == NULL ) printf( "ABC framework is not initialized by calling Abc_Start()\n" ); pGia = Abc_FrameReadGia( pAbc ); if ( pGia == NULL ) printf( "Current network in ABC framework is not defined.\n" ); return Gia_ManToMiniLutAttr( pGia, pMiniLut ); } int * Abc_FrameGiaOutputMiniLutObj( Abc_Frame_t * pAbc ) { int * pRes = NULL; if ( pAbc == NULL ) printf( "ABC framework is not initialized by calling Abc_Start()\n" ); if ( pAbc->vMiniLutObjs == NULL ) printf( "MiniLut objects are not defined.\n" ); pRes = Vec_IntReleaseArray( pAbc->vMiniLutObjs ); Vec_IntFreeP( &pAbc->vMiniLutObjs ); return pRes; } void Abc_FrameSetObjDelays( Abc_Frame_t * pAbc, int * pDelays, int nDelays ) { Vec_IntFreeP( &pAbc->vObjDelays ); pAbc->vObjDelays = Vec_IntAllocArrayCopy( pDelays, nDelays ); } /**Function************************************************************* Synopsis [Procedures to read/write GIA to/from MiniAIG file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManReadMiniLut( char * pFileName ) { Mini_Lut_t * p = Mini_LutLoad( pFileName ); Gia_Man_t * pGia = Gia_ManFromMiniLut( p, NULL ); ABC_FREE( pGia->pName ); pGia->pName = Extra_FileNameGeneric( pFileName ); Mini_LutStop( p ); return pGia; } void Gia_ManWriteMiniLut( Gia_Man_t * pGia, char * pFileName ) { Mini_Lut_t * p = Gia_ManToMiniLut( pGia ); Mini_LutDump( p, pFileName ); Mini_LutStop( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Gia_ManMapMiniLut2MiniAig( Gia_Man_t * p, Gia_Man_t * p1, Gia_Man_t * p2, Vec_Int_t * vMap1, Vec_Int_t * vMap2 ) { int * pRes = ABC_FALLOC( int, Vec_IntSize(vMap2) ); Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); int i, Entry, iRepr, fCompl, iLit; Gia_Obj_t * pObj; Gia_ManSetPhase( p1 ); Gia_ManSetPhase( p2 ); Vec_IntForEachEntry( vMap1, Entry, i ) { if ( Entry == -1 ) continue; pObj = Gia_ManObj( p1, Abc_Lit2Var(Entry) ); if ( ~pObj->Value == 0 ) continue; fCompl = Abc_LitIsCompl(Entry) ^ pObj->fPhase; iRepr = Gia_ObjReprSelf(p, Abc_Lit2Var(pObj->Value)); Vec_IntWriteEntry( vMap, iRepr, Abc_Var2Lit(i, fCompl) ); } Vec_IntForEachEntry( vMap2, Entry, i ) { if ( Entry == -1 ) continue; pObj = Gia_ManObj( p2, Abc_Lit2Var(Entry) ); if ( ~pObj->Value == 0 ) continue; fCompl = Abc_LitIsCompl(Entry) ^ pObj->fPhase; iRepr = Gia_ObjReprSelf(p, Abc_Lit2Var(pObj->Value)); if ( (iLit = Vec_IntEntry(vMap, iRepr)) == -1 ) continue; pRes[i] = Abc_LitNotCond( iLit, fCompl ); } Vec_IntFill( vMap, Gia_ManCoNum(p1), -1 ); Vec_IntForEachEntry( vMap1, Entry, i ) { if ( Entry == -1 ) continue; pObj = Gia_ManObj( p1, Abc_Lit2Var(Entry) ); if ( !Gia_ObjIsCo(pObj) ) continue; Vec_IntWriteEntry( vMap, Gia_ObjCioId(pObj), i ); } Vec_IntForEachEntry( vMap2, Entry, i ) { if ( Entry == -1 ) continue; pObj = Gia_ManObj( p2, Abc_Lit2Var(Entry) ); if ( !Gia_ObjIsCo(pObj) ) continue; assert( pRes[i] == -1 ); pRes[i] = Abc_Var2Lit( Vec_IntEntry(vMap, Gia_ObjCioId(pObj)), 0 ); assert( pRes[i] != -1 ); } Vec_IntFree( vMap ); return pRes; } void Gia_ManNameMapVerify( Gia_Man_t * p, Gia_Man_t * p1, Gia_Man_t * p2, Vec_Int_t * vMap1, Vec_Int_t * vMap2, int * pMap ) { int iLut, iObj1, iObj2, nSize = Vec_IntSize(vMap2); Gia_Obj_t * pObjAig, * pObjLut; Gia_ManSetPhase( p1 ); Gia_ManSetPhase( p2 ); for ( iLut = 0; iLut < nSize; iLut++ ) if ( pMap[iLut] >= 0 ) { int iObj = Abc_Lit2Var( pMap[iLut] ); int fCompl = Abc_LitIsCompl( pMap[iLut] ); int iLitAig = Vec_IntEntry( vMap1, iObj ); int iLitLut = Vec_IntEntry( vMap2, iLut ); pObjAig = Gia_ManObj( p1, Abc_Lit2Var(iLitAig) ); if ( Gia_ObjIsCo(pObjAig) ) continue; if ( ~pObjAig->Value == 0 ) continue; pObjLut = Gia_ManObj( p2, Abc_Lit2Var(iLitLut) ); if ( ~pObjLut->Value == 0 ) continue; iObj1 = Gia_ObjReprSelf(p, Abc_Lit2Var(pObjAig->Value)); iObj2 = Gia_ObjReprSelf(p, Abc_Lit2Var(pObjLut->Value)); if ( iObj1 != iObj2 ) printf( "Found functional mismatch for LutId %d and AigId %d.\n", iLut, iObj ); if ( (pObjLut->fPhase ^ Abc_LitIsCompl(iLitLut)) != (pObjAig->fPhase ^ Abc_LitIsCompl(iLitAig) ^ fCompl) ) printf( "Found phase mismatch for LutId %d and AigId %d.\n", iLut, iObj ); } } int * Abc_FrameReadMiniLutNameMapping( Abc_Frame_t * pAbc ) { int fVerbose = 0; int nConfs = 1000; Gia_Man_t * pGia, * pTemp; int * pRes = NULL; if ( pAbc->pGiaMiniAig == NULL ) printf( "GIA derived from MiniAig is not available.\n" ); if ( pAbc->pGiaMiniLut == NULL ) printf( "GIA derived from MiniLut is not available.\n" ); 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, 0 ); // compute equivalences in this AIG pTemp = Gia_ManComputeGiaEquivs( pGia, nConfs, fVerbose ); Gia_ManStop( pTemp ); //if ( fVerbose ) // Abc_PrintTime( 1, "Equivalence computation time", Abc_Clock() - clk ); //if ( fVerbose ) // Gia_ManPrintStats( pGia, NULL ); //Vec_IntPrint( pAbc->vCopyMiniAig ); //Vec_IntPrint( pAbc->vCopyMiniLut ); pRes = Gia_ManMapMiniLut2MiniAig( pGia, pAbc->pGiaMiniAig, pAbc->pGiaMiniLut, pAbc->vCopyMiniAig, pAbc->vCopyMiniLut ); //Gia_ManNameMapVerify( pGia, pAbc->pGiaMiniAig, pAbc->pGiaMiniLut, pAbc->vCopyMiniAig, pAbc->vCopyMiniLut, pRes ); 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_FrameReadMiniLutSwitching2( Abc_Frame_t * pAbc, int fRandPiFactor ) { Vec_Int_t * vSwitching; int i, iObj, * pRes = NULL; if ( pAbc->pGiaMiniLut == NULL ) { printf( "GIA derived from MiniLut is not available.\n" ); return NULL; } vSwitching = Gia_ManComputeSwitchProbs2( pAbc->pGiaMiniLut, 48, 16, 0, fRandPiFactor ); pRes = ABC_CALLOC( int, Vec_IntSize(pAbc->vCopyMiniLut) ); Vec_IntForEachEntry( pAbc->vCopyMiniLut, iObj, i ) if ( iObj >= 0 ) pRes[i] = (int)(10000*Vec_FltEntry( (Vec_Flt_t *)vSwitching, Abc_Lit2Var(iObj) )); Vec_IntFree( vSwitching ); return pRes; } int * Abc_FrameReadMiniLutSwitchingPo( Abc_Frame_t * pAbc ) { Vec_Int_t * vSwitching; 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 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Gia_ManRetimableF( Gia_Man_t * p, int * pRst, int * pSet, int * pEna ) { Vec_Str_t * vStops = Vec_StrStart( Gia_ManObjNum(p) ); Vec_Int_t * vTemps = Vec_IntStartFull( 3*Gia_ManObjNum(p) ); Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i; char * pStops = Vec_StrArray(vStops); assert( Gia_ManRegNum(p) > 0 ); Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) { Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRo) + 0, pRst[i] ); Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRo) + 1, pSet[i] ); Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRo) + 2, pEna[i] ); } Gia_ManForEachAnd( p, pObj, i ) { int * pFan0 = Vec_IntEntryP( vTemps, 3*Gia_ObjFaninId0(pObj, i) ); int * pFan1 = Vec_IntEntryP( vTemps, 3*Gia_ObjFaninId1(pObj, i) ); int * pNode = Vec_IntEntryP( vTemps, 3*i ); pStops[i] = (char)1; if ( pFan0[0] != -1 && pFan0[0] == pFan1[0] && pFan0[1] == pFan1[1] && pFan0[2] == pFan1[2] ) pStops[i] = (char)0, pNode[0] = pFan0[0], pNode[1] = pFan0[1], pNode[2] = pFan0[2]; } Vec_IntFree( vTemps ); return vStops; } Vec_Str_t * Gia_ManRetimableB( Gia_Man_t * p, int * pRst, int * pSet, int * pEna ) { Vec_Str_t * vStops = Vec_StrStart( Gia_ManObjNum(p) ); Vec_Int_t * vTemps = Vec_IntStartFull( 3*Gia_ManObjNum(p) ); Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i, n, iFanout; char * pStops = Vec_StrArray(vStops); assert( Gia_ManRegNum(p) > 0 ); Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) { Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRi) + 0, pRst[i] ); Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRi) + 1, pSet[i] ); Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRi) + 2, pEna[i] ); } Gia_ManStaticFanoutStart( p ); Gia_ManForEachAndReverse( p, pObj, i ) { int * pFan0 = Vec_IntEntryP( vTemps, 3*Gia_ObjFanoutId(p, i, 0) ); int * pNode = Vec_IntEntryP( vTemps, 3*i ); pStops[i] = (char)1; if ( pFan0[0] == -1 ) continue; Gia_ObjForEachFanoutStaticId( p, i, iFanout, n ) { int * pFan1 = Vec_IntEntryP( vTemps, 3*iFanout ); if ( pFan1[0] == -1 || pFan0[0] != pFan1[0] || pFan0[1] != pFan1[1] || pFan0[2] != pFan1[2] ) break; } if ( n < Gia_ObjFanoutNum(p, pObj) ) continue; pStops[i] = (char)0, pNode[0] = pFan0[0], pNode[1] = pFan0[1], pNode[2] = pFan0[2]; } Gia_ManStaticFanoutStop( p ); Vec_IntFree( vTemps ); Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) { if ( Gia_ObjIsAnd(Gia_ManObj(p, Abc_Lit2Var(pRst[i]))) ) pStops[Abc_Lit2Var(pRst[i])] = 1; if ( Gia_ObjIsAnd(Gia_ManObj(p, Abc_Lit2Var(pSet[i]))) ) pStops[Abc_Lit2Var(pSet[i])] = 1; if ( Gia_ObjIsAnd(Gia_ManObj(p, Abc_Lit2Var(pEna[i]))) ) pStops[Abc_Lit2Var(pEna[i])] = 1; } return vStops; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameRemapLits( int * pLits, int nLits, Vec_Int_t * vMap ) { for ( int i = 0; i < nLits; i++ ) pLits[i] = Abc_Lit2LitL( Vec_IntArray(vMap), pLits[i] ); } void Abc_FrameSetRetimingData( Abc_Frame_t * pAbc, int * pRst, int * pSet, int * pEna, int nRegs ) { Gia_Man_t * pGia; int * pRstNew = ABC_CALLOC( int, nRegs ); int * pSetNew = ABC_CALLOC( int, nRegs ); int * pEnaNew = ABC_CALLOC( int, nRegs ); if ( pAbc == NULL ) printf( "ABC framework is not initialized by calling Abc_Start()\n" ); pGia = Abc_FrameReadGia( pAbc ); if ( pGia == NULL ) printf( "Current network in ABC framework is not defined.\n" ); else { assert( nRegs == Gia_ManRegNum(pGia) ); memmove( pRstNew, pRst, sizeof(int)*nRegs ); memmove( pSetNew, pSet, sizeof(int)*nRegs ); memmove( pEnaNew, pEna, sizeof(int)*nRegs ); } if ( pAbc->vCopyMiniAig == NULL ) printf( "Mapping of MiniAig nodes is not available.\n" ); else { Abc_FrameRemapLits( pRstNew, nRegs, pAbc->vCopyMiniAig ); Abc_FrameRemapLits( pSetNew, nRegs, pAbc->vCopyMiniAig ); Abc_FrameRemapLits( pEnaNew, nRegs, pAbc->vCopyMiniAig ); } assert( pGia->vStopsF == NULL ); assert( pGia->vStopsB == NULL ); pGia->vStopsF = Gia_ManRetimableF( pGia, pRstNew, pSetNew, pEnaNew ); pGia->vStopsB = Gia_ManRetimableB( pGia, pRstNew, pSetNew, pEnaNew ); ABC_FREE( pRstNew ); ABC_FREE( pSetNew ); ABC_FREE( pEnaNew ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaMulFind.c000066400000000000000000001033131477524141600164530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaMulFind.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Multiplier detection.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaMulFind.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManMulFindXors2_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXor ) { if ( !Gia_ObjIsAnd(pObj) ) return; if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( !pObj->fMark0 ) { if ( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) && Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) >= 4 && Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) >= 4 ) Vec_IntPushTwo( vXor, Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninId1p(p, pObj) ); return; } Gia_Obj_t * pFan0, * pFan1; int RetValue = Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1); assert( RetValue ); Gia_ManMulFindXors2_rec( p, Gia_Regular(pFan0), vXor ); Gia_ManMulFindXors2_rec( p, Gia_Regular(pFan1), vXor ); } Vec_Wec_t * Gia_ManMulFindXors2( Gia_Man_t * p ) { Vec_Wec_t * vXors = Vec_WecAlloc( 100 ); Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); Gia_Obj_t * pObj, * pFan0, * pFan1; int i; Gia_ManCreateRefs( p ); Gia_ManCleanMark01( p ); Gia_ManForEachAnd( p, pObj, i ) { if ( !Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) continue; Gia_Regular(pFan0)->fMark1 = 1; Gia_Regular(pFan1)->fMark1 = 1; pObj->fMark0 = 1; } Gia_ManForEachAnd( p, pObj, i ) { if ( pObj->fMark0 && !pObj->fMark1 ) { Gia_ManIncrementTravId( p ); Vec_IntClear( vTemp ); Gia_ManMulFindXors2_rec( p, pObj, vTemp ); if ( Vec_IntSize(vTemp) > 0 ) Vec_IntAppend( Vec_WecPushLevel(vXors), vTemp ); } } Vec_IntFree( vTemp ); return vXors; } int Gia_ManMulFindMaxSize( Vec_Wec_t * vXors, Vec_Int_t * vUsed ) { Vec_Int_t * vLevel; int i, iBest = -1, nBestSize = 0; Vec_WecForEachLevel( vXors, vLevel, i ) if ( !Vec_IntEntry(vUsed, i) && nBestSize < Vec_IntSize(vLevel) ) nBestSize = Vec_IntSize(vLevel), iBest = i; return iBest; } int Gia_ManMulFindGetOverlap( Vec_Int_t * p1, Vec_Int_t * p2 ) { int i, k, ObjI, ObjK, Counter = 0; Vec_IntForEachEntry( p1, ObjI, i ) Vec_IntForEachEntry( p2, ObjK, k ) if ( ObjI == ObjK ) Counter++; return Counter; } int Gia_ManMulFindGetOverlap2( Vec_Int_t * p1, Vec_Int_t * p2 ) { int i, k, ObjI, ObjK, Counter = 0; Vec_IntForEachEntryStart( p1, ObjI, i, 1 ) Vec_IntForEachEntry( p2, ObjK, k ) if ( ObjI == ObjK ) Counter++; return Counter; } int Gia_ManMulFindMaxOverlap( Vec_Wec_t * vXors, Vec_Int_t * vUsed, Vec_Int_t * vFound ) { Vec_Int_t * vLevel; int i, iBest = -1, nThisSize, nBestSize = 0; Vec_WecForEachLevel( vXors, vLevel, i ) if ( !Vec_IntEntry(vUsed, i) && nBestSize < (nThisSize = Gia_ManMulFindGetOverlap(vFound, vLevel)) ) nBestSize = nThisSize, iBest = i; return iBest; } Vec_Wec_t * Gia_ManMulFindSets( Gia_Man_t * p, Vec_Wec_t * vXors ) { Vec_Wec_t * vSets = Vec_WecAlloc( 100 ); Vec_Int_t * vUsed = Vec_IntStart( Vec_WecSize(vXors) ); Vec_Int_t * vFound = Vec_IntAlloc( 100 ); int Item, k, Obj; while ( (Item = Gia_ManMulFindMaxSize(vXors, vUsed)) != -1 ) { Vec_Int_t * vTemp = Vec_WecEntry(vXors, Item); Vec_Int_t * vNew = Vec_WecPushLevel( vSets ); Vec_IntPush( vNew, Item ); Vec_IntWriteEntry( vUsed, Item, 1 ); Vec_IntClear( vFound ); Vec_IntAppend( vFound, vTemp ); while ( (Item = Gia_ManMulFindMaxOverlap(vXors, vUsed, vFound)) != -1 ) { Vec_IntPush( vNew, Item ); Vec_IntWriteEntry( vUsed, Item, 1 ); vTemp = Vec_WecEntry(vXors, Item); Vec_IntForEachEntry( vTemp, Obj, k ) Vec_IntPushUnique( vFound, Obj ); } } Vec_IntFree( vUsed ); Vec_IntFree( vFound ); return vSets; } int Gia_ManMulFindOne( Gia_Man_t * p, Vec_Wec_t * vXors, Vec_Int_t * vSet, Vec_Int_t * vMap, Vec_Int_t * vA, Vec_Int_t * vB, int fVerbose ) { Vec_Int_t * vObjs = Vec_IntAlloc( 100 ); int i, j, Obj, Obj1, Obj2; Vec_IntForEachEntry( vSet, Obj, i ) Vec_IntAppend( vObjs, Vec_WecEntry(vXors, Obj) ); Vec_IntForEachEntry( vObjs, Obj, i ) Vec_IntAddToEntry( vMap, Obj, 1 ); Vec_IntForEachEntry( vSet, Obj, i ) { Vec_Int_t * vTemp = Vec_WecEntry(vXors, Obj); int k = 0; Vec_IntForEachEntryDouble( vTemp, Obj1, Obj2, j ) if ( Vec_IntEntry(vMap, Obj1) > 1 || Vec_IntEntry(vMap, Obj2) > 1 ) Vec_IntWriteEntry(vTemp, k++, Obj1), Vec_IntWriteEntry(vTemp, k++, Obj2); Vec_IntShrink( vTemp, k ); } Vec_IntForEachEntry( vObjs, Obj, i ) Vec_IntWriteEntry( vMap, Obj, 0 ); Vec_IntClear( vObjs ); Vec_IntForEachEntry( vSet, Obj, i ) Vec_IntAppend( vObjs, Vec_WecEntry(vXors, Obj) ); if ( Vec_IntSize(vObjs) == 0 ) { Vec_IntFree(vObjs); return 0; } Vec_IntClear( vA ); Vec_IntClear( vB ); Vec_IntPush( vA, Vec_IntPop(vObjs) ); Vec_IntPush( vB, Vec_IntPop(vObjs) ); while ( Vec_IntSize(vObjs) > 0 ) { int k = 0; Vec_IntForEachEntryDouble( vObjs, Obj1, Obj2, j ) { if ( Vec_IntFind(vA, Obj1) >= 0 ) Vec_IntPushUnique(vB, Obj2); else if ( Vec_IntFind(vA, Obj2) >= 0 ) Vec_IntPushUnique(vB, Obj1); else if ( Vec_IntFind(vB, Obj1) >= 0 ) Vec_IntPushUnique(vA, Obj2); else if ( Vec_IntFind(vB, Obj2) >= 0 ) Vec_IntPushUnique(vA, Obj1); else { Vec_IntWriteEntry(vObjs, k++, Obj1); Vec_IntWriteEntry(vObjs, k++, Obj2); } } Vec_IntShrink( vObjs, k ); } Vec_IntSort( vA, 0 ); Vec_IntSort( vB, 0 ); Vec_IntClear( vObjs ); Vec_IntForEachEntry( vSet, Obj, i ) Vec_IntAppend( vObjs, Vec_WecEntry(vXors, Obj) ); Vec_IntForEachEntryDouble( vObjs, Obj1, Obj2, j ) if ( !((Vec_IntFind(vA, Obj1) >= 0 && Vec_IntFind(vB, Obj2) >= 0) || (Vec_IntFind(vA, Obj2) >= 0 && Vec_IntFind(vB, Obj1) >= 0)) ) { if ( fVerbose ) printf( "Internal verification failed.\n" ); Vec_IntFree( vObjs ); Vec_IntClear( vA ); Vec_IntClear( vB ); return 0; } if ( fVerbose ) printf( "Generated system with %d+%d+%d=%d variables and %d equations.\n", Vec_IntSize(vA),Vec_IntSize(vB),Vec_IntSize(vSet), Vec_IntSize(vA)+Vec_IntSize(vB)+Vec_IntSize(vSet), Vec_IntSize(vObjs)/2 ); Vec_IntFree( vObjs ); return 1; } Vec_Wec_t * Gia_ManMulFindAInputs2( Gia_Man_t * p, int fVerbose ) { Vec_Wec_t * vMuls = Vec_WecAlloc( 10 ); Vec_Wec_t * vXors = Gia_ManMulFindXors2( p ); Vec_Wec_t * vSets = Gia_ManMulFindSets( p, vXors ); Vec_Int_t * vMap = Vec_IntStart( Gia_ManObjNum(p) ); Vec_Int_t * vA = Vec_IntAlloc( 100 ); Vec_Int_t * vB = Vec_IntAlloc( 100 ); Vec_Int_t * vSet; int i; Vec_WecForEachLevel( vSets, vSet, i ) { if ( !Gia_ManMulFindOne(p, vXors, vSet, vMap, vA, vB, fVerbose) ) continue; Vec_IntAppend( Vec_WecPushLevel(vMuls), vA ); Vec_IntAppend( Vec_WecPushLevel(vMuls), vB ); Vec_WecPushLevel(vMuls); } Vec_WecFree( vXors ); Vec_WecFree( vSets ); Vec_IntFree( vMap ); Vec_IntFree( vA ); Vec_IntFree( vB ); return vMuls; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManMulFindAddEntry1( Vec_Int_t * vPairs, int Obj ) { int Entry, Sum, k; Vec_IntForEachEntryDouble( vPairs, Entry, Sum, k ) if ( Obj == Entry ) { Vec_IntAddToEntry( vPairs, k+1, 1 ); break; } if ( k == Vec_IntSize(vPairs) ) Vec_IntPushTwo( vPairs, Obj, 1 ); } Vec_Int_t * Gia_ManMulFindCounts( Vec_Wec_t * vCuts4, Vec_Int_t * vSet ) { Vec_Int_t * vCounts = Vec_IntAlloc( 10 ); int i, k, Obj, Item; Vec_IntForEachEntry( vSet, Item, i ) { Vec_Int_t * vCut = Vec_WecEntry(vCuts4, Item); Vec_IntForEachEntryStart( vCut, Obj, k, 1 ) Gia_ManMulFindAddEntry1( vCounts, Obj ); } return vCounts; } int Gia_ManMulFindNextEntry( Vec_Wec_t * vCuts4, Vec_Int_t * vSet, int Entry ) { int i, Item; Vec_IntForEachEntry( vSet, Item, i ) { Vec_Int_t * vCut = Vec_WecEntry(vCuts4, Item); if ( Vec_IntSize(vCut) == 0 ) continue; assert( Vec_IntSize(vCut) == 3 ); int RetValue = -1; if ( Vec_IntEntry(vCut, 1) == Entry ) RetValue = Vec_IntEntry(vCut, 2); if ( Vec_IntEntry(vCut, 2) == Entry ) RetValue = Vec_IntEntry(vCut, 1); if ( RetValue == -1 ) continue; Vec_IntClear( vCut ); return RetValue; } return -1; } void Gia_ManMulFindArg1( Vec_Wec_t * vCuts4, Vec_Int_t * vSet, Vec_Int_t * vArg1 ) { Vec_Int_t * vCounts = Gia_ManMulFindCounts( vCuts4, vSet ); int Entry = -1, Sum, k; Vec_IntClear( vArg1 ); Vec_IntForEachEntryDouble( vCounts, Entry, Sum, k ) if ( Sum == 1 ) { Vec_IntPush( vArg1, Entry ); break; } assert( Entry != -1 ); while ( (Entry = Gia_ManMulFindNextEntry(vCuts4, vSet, Entry)) != -1 ) Vec_IntPush( vArg1, Entry ); Vec_IntFree( vCounts ); } int Gia_ManMulFindNextEntryCount( Vec_Int_t * vCounts, int Entry0 ) { int Entry, Sum, k; Vec_IntForEachEntryDouble( vCounts, Entry, Sum, k ) if ( Entry == Entry0 ) return Sum; return -1; } int Gia_ManMulFindNextEntry2( Vec_Wec_t * vCuts4, Vec_Int_t * vSet, int Entry, Vec_Int_t * vCounts, int * pEntry0, int * pEntry1 ) { int i, Item; Vec_IntForEachEntry( vSet, Item, i ) { Vec_Int_t * vCut = Vec_WecEntry(vCuts4, Item); if ( Vec_IntSize(vCut) == 0 ) continue; assert( Vec_IntSize(vCut) == 4 ); int Entry0, Entry1, iPlace = Vec_IntFind( vCut, Entry ); if ( iPlace == -1 ) continue; if ( iPlace == 1 ) Entry0 = Vec_IntEntry(vCut, 2), Entry1 = Vec_IntEntry(vCut, 3); else if ( iPlace == 2 ) Entry0 = Vec_IntEntry(vCut, 1), Entry1 = Vec_IntEntry(vCut, 3); else if ( iPlace == 3 ) Entry0 = Vec_IntEntry(vCut, 1), Entry1 = Vec_IntEntry(vCut, 2); else assert( 0 ); int Count0 = Gia_ManMulFindNextEntryCount(vCounts, Entry0); int Count1 = Gia_ManMulFindNextEntryCount(vCounts, Entry1); *pEntry0 = Count0 <= Count1 ? Entry0 : Entry1; *pEntry1 = Count0 <= Count1 ? Entry1 : Entry0; // remove entries Vec_IntForEachEntry( vSet, Item, i ) { Vec_Int_t * vCut = Vec_WecEntry(vCuts4, Item); if ( Vec_IntSize(vCut) == 0 ) continue; if ( Vec_IntFind( vCut, Entry ) >= 0 ) Vec_IntClear( vCut ); } return 1; } return 0; } void Gia_ManMulFindArg2( Vec_Wec_t * vCuts5, Vec_Int_t * vSet, Vec_Int_t * vArg2, int Entry0, int Entry1 ) { Vec_Int_t * vCounts = Gia_ManMulFindCounts( vCuts5, vSet ); int Entry, Sum, k, SumMin = ABC_INFINITY, SumMax = 0; Vec_IntForEachEntryDouble( vCounts, Entry, Sum, k ) { SumMin = Abc_MinInt( SumMin, Sum ); SumMax = Abc_MaxInt( SumMax, Sum ); } Vec_IntClear( vArg2 ); Vec_IntForEachEntryDouble( vCounts, Entry, Sum, k ) if ( Entry == Entry0 || Entry == Entry1 ) { Vec_IntPush( vArg2, Entry == Entry0 ? Entry1 : Entry0 ); Vec_IntPush( vArg2, Entry ); break; } Entry = Vec_IntEntry(vArg2, 1); while ( Gia_ManMulFindNextEntry2(vCuts5, vSet, Entry, vCounts, &Entry0, &Entry1) ) Vec_IntPushTwo( vArg2, Entry0, Entry1 ), Entry = Entry1; Vec_IntFree( vCounts ); } void Gia_ManMulFindAddEntry( Vec_Int_t * vPairs, int Obj0, int Obj1 ) { int Entry0, Entry1, Sum, k; Vec_IntForEachEntryTriple( vPairs, Entry0, Entry1, Sum, k ) if ( Obj0 == Entry0 && Obj1 == Entry1 ) { Vec_IntAddToEntry( vPairs, k+2, 1 ); break; } if ( k == Vec_IntSize(vPairs) ) Vec_IntPushThree( vPairs, Obj0, Obj1, 1 ); } Vec_Wec_t * Gia_ManMulFindBInputs2( Gia_Man_t * p, Vec_Wec_t * vCuts4, Vec_Wec_t * vCuts5, int fVerbose ) { Vec_Wec_t * vRes = Vec_WecAlloc( 10 ); Vec_Int_t * vPairs = Vec_IntAlloc( 1000 ); Vec_Int_t * vSet = Vec_IntAlloc( 100 ); Vec_Int_t * vCut, * vArg1, * vArg2; int i, j, k, n, Entry0, Entry1, Sum, Obj0, Obj1; Vec_WecForEachLevel( vCuts4, vCut, i ) Vec_IntForEachEntryStart( vCut, Obj0, j, 1 ) Vec_IntForEachEntryStart( vCut, Obj1, k, j+1 ) Gia_ManMulFindAddEntry( vPairs, Obj0, Obj1 ); Vec_IntForEachEntryTriple( vPairs, Entry0, Entry1, Sum, n ) { if ( Sum < 3 ) continue; Vec_IntClear( vSet ); Vec_WecForEachLevel( vCuts4, vCut, i ) Vec_IntForEachEntryStart( vCut, Obj0, j, 1 ) Vec_IntForEachEntryStart( vCut, Obj1, k, j+1 ) if ( Obj0 == Entry0 && Obj1 == Entry1 ) { Vec_IntPush( vSet, i ); Vec_IntDrop( vCut, k ); Vec_IntDrop( vCut, j ); j = k = Vec_IntSize(vCut); } vArg1 = Vec_WecPushLevel(vRes); vArg2 = Vec_WecPushLevel(vRes); Vec_WecPushLevel(vRes); Gia_ManMulFindArg1( vCuts4, vSet, vArg1 ); // find overlapping with arg1 and remove nodes in arg1 Vec_IntClear( vSet ); Vec_WecForEachLevel( vCuts5, vCut, i ) if ( Gia_ManMulFindGetOverlap2(vCut, vArg1) ) { k = 1; Vec_IntForEachEntryStart( vCut, Obj0, j, 1 ) if ( Vec_IntFind(vArg1, Obj0) == -1 ) Vec_IntWriteEntry( vCut, k++, Obj0 ); Vec_IntShrink( vCut, k ); Vec_IntPush( vSet, i ); } Gia_ManMulFindArg2( vCuts5, vSet, vArg2, Entry0, Entry1 ); } Vec_IntFree( vSet ); Vec_IntFree( vPairs ); return vRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManMulFindOverlap( Vec_Int_t * p1, Vec_Int_t * p2 ) { int i, k, ObjI, ObjK, Counter = 0; Vec_IntForEachEntry( p1, ObjI, i ) Vec_IntForEachEntry( p2, ObjK, k ) if ( ObjI == ObjK ) Counter++; return Counter; } void Gia_ManMulFindAssignGroup( Vec_Int_t * vTemp, int iGroup, Vec_Int_t * vMap ) { int k, Obj; Vec_IntForEachEntry( vTemp, Obj, k ) { //assert( Vec_IntEntry(vMap, Obj) == -1 || Vec_IntEntry(vMap, Obj) == iGroup ); Vec_IntWriteEntry(vMap, Obj, iGroup); } Vec_IntPush( vTemp, iGroup ); } Vec_Int_t * Gia_ManMulFindGroups( Vec_Wec_t * p, int nObjs, int fUseMap ) { Vec_Int_t * vIndex = Vec_IntAlloc( 100 ), * vTemp; Vec_Int_t * vMap = Vec_IntStartFull( nObjs ); int i, Counter, nGroups = 0; Vec_Int_t * vUngrouped = Vec_IntStartNatural( Vec_WecSize(p) ); while ( Vec_IntSize(vUngrouped) ) { int k, Obj, Item = Vec_IntPop(vUngrouped); vTemp = Vec_WecEntry(p, Item); Gia_ManMulFindAssignGroup( vTemp, nGroups, vMap ); int fChanges = 1; while ( fChanges ) { fChanges = 0; Vec_IntForEachEntry( vUngrouped, Item, i ) { vTemp = Vec_WecEntry(p, Item); Counter = 0; Vec_IntForEachEntry( vTemp, Obj, k ) if ( Vec_IntEntry(vMap, Obj) >= 0 ) Counter++; if ( Counter < 1 ) continue; Gia_ManMulFindAssignGroup( vTemp, nGroups, vMap ); Vec_IntDrop( vUngrouped, i-- ); fChanges = 1; } } nGroups++; } Vec_IntFree( vUngrouped ); Vec_IntFree( vMap ); if ( fUseMap ) Vec_WecForEachLevel( p, vTemp, i ) Vec_IntPushTwo( vTemp, i, Vec_IntPop(vTemp) ); Vec_WecSortByLastInt( p, 0 ); Counter = 0; Vec_IntPush( vIndex, 0 ); Vec_WecForEachLevel( p, vTemp, i ) if ( Vec_IntPop(vTemp) != Counter ) Vec_IntPush( vIndex, i ), Counter++; Vec_IntPush( vIndex, Vec_WecSize(p) ); assert( Vec_WecSize(p) == 0 || Vec_IntSize(vIndex) == nGroups + 1 ); return vIndex; } Vec_Wec_t * Gia_ManMulFindXors( Gia_Man_t * p, Vec_Wec_t * vCuts3, int fVerbose ) { Vec_Wec_t * vXors = Vec_WecAlloc( 10 ); Vec_Int_t * vIndex = Gia_ManMulFindGroups( vCuts3, Gia_ManObjNum(p), 0 ); Vec_Int_t * vAll = Vec_IntAlloc( 100 ); Vec_Bit_t * vSigs[2] = { Vec_BitStart(Gia_ManObjNum(p)), Vec_BitStart(Gia_ManObjNum(p)) }; Vec_Int_t * vTemp; int g, c, k, Obj, Start; Vec_IntForEachEntryStop( vIndex, Start, g, Vec_IntSize(vIndex)-1 ) { Vec_WecForEachLevelStartStop( vCuts3, vTemp, c, Start, Vec_IntEntry(vIndex, g+1) ) Vec_IntForEachEntry( vTemp, Obj, k ) if ( !Vec_BitEntry(vSigs[k==0], Obj) ) { Vec_BitWriteEntry( vSigs[k==0], Obj, 1 ); Vec_IntPush( vAll, Obj ); } Vec_Int_t * vIns = Vec_WecPushLevel( vXors ); Vec_Int_t * vOuts = Vec_WecPushLevel( vXors ); Vec_IntForEachEntry( vAll, Obj, k ) { if ( Vec_BitEntry(vSigs[0], Obj) && !Vec_BitEntry(vSigs[1], Obj) ) Vec_IntPush( vIns, Obj ); if ( !Vec_BitEntry(vSigs[0], Obj) && Vec_BitEntry(vSigs[1], Obj) ) Vec_IntPush( vOuts, Obj ); Vec_BitWriteEntry( vSigs[0], Obj, 0 ); Vec_BitWriteEntry( vSigs[1], Obj, 0 ); } Vec_IntClear( vAll ); } return vXors; } Vec_Int_t * Gia_ManFindMulDetectOrder( Vec_Wec_t * vAll, int iStart, int iStop ) { Vec_Int_t * vOrder = Vec_IntAlloc( iStop - iStart ); Vec_Int_t * vUsed = Vec_IntStart( iStop ), * vTemp; int i, nMatches = 0, iNext = -1; Vec_WecForEachLevelStartStop( vAll, vTemp, i, iStart, iStop ) if ( Vec_IntSize(vTemp) == 2 ) nMatches++, iNext = i; if ( nMatches == 1 ) { while ( Vec_IntSize(vOrder) < iStop - iStart ) { Vec_IntPush( vOrder, iNext ); Vec_IntWriteEntry( vUsed, iNext, 1 ); nMatches = 0; Vec_WecForEachLevelStartStop( vAll, vTemp, i, iStart, iStop ) { if ( Vec_IntEntry(vUsed, i) ) continue; Vec_Int_t * vLast = Vec_WecEntry(vAll, Vec_IntEntryLast(vOrder)); if ( Gia_ManMulFindOverlap(vTemp, vLast) == Vec_IntSize(vLast) && Vec_IntSize(vTemp) == Vec_IntSize(vLast) + 2 ) nMatches++, iNext = i; } if ( nMatches != 1 ) break; } } Vec_IntFree( vUsed ); if ( Vec_IntSize(vOrder) == 0 ) Vec_IntFreeP( &vOrder ); return vOrder; } Vec_Wec_t * Gia_ManMulFindAInputs( Gia_Man_t * p, Vec_Wec_t * vXors, int fVerbose ) { Vec_Wec_t * vRes = Vec_WecAlloc( 10 ); Vec_Wec_t * vAll = Vec_WecAlloc( Vec_WecSize(vXors)/2 ); Gia_Obj_t * pObj; Vec_Int_t * vIns, * vOuts, * vTemp, * vIndex, * vOrder; int i, k, g, Start, Entry, Entry0, Entry1; Gia_ManCreateRefs( p ); Vec_WecForEachLevelDouble( vXors, vIns, vOuts, i ) { vTemp = Vec_WecPushLevel( vAll ); Gia_ManForEachObjVec( vIns, p, pObj, k ) if ( Gia_ObjIsAnd(pObj) && !Gia_ObjFaninC0(pObj) && Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) >= 4 && !Gia_ObjFaninC1(pObj) && Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) >= 4 ) Vec_IntPushTwo( vTemp, Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninId1p(p, pObj) ); if ( Vec_IntSize(vTemp) == 0 ) Vec_WecShrink(vAll, Vec_WecSize(vAll)-1); } vIndex = Gia_ManMulFindGroups( vAll, Gia_ManObjNum(p), 0 ); Vec_IntForEachEntryStop( vIndex, Start, g, Vec_IntSize(vIndex)-1 ) { vOrder = Gia_ManFindMulDetectOrder( vAll, Start, Vec_IntEntry(vIndex, g+1) ); if ( vOrder == NULL ) continue; Vec_Int_t * vIn0 = Vec_WecPushLevel( vRes ); Vec_Int_t * vIn1 = Vec_WecPushLevel( vRes ); Vec_Int_t * vOut = Vec_WecPushLevel( vRes ); vTemp = Vec_WecEntry( vAll, Vec_IntEntry(vOrder, 0) ); assert( Vec_IntSize(vTemp) == 2 ); Vec_IntPush( vIn0, Vec_IntEntry(vTemp, 0) ); Vec_IntPush( vIn1, Vec_IntEntry(vTemp, 1) ); Vec_IntForEachEntryStart( vOrder, Entry, i, 1 ) { vTemp = Vec_WecEntry( vAll, Entry ); Vec_IntForEachEntryDouble( vTemp, Entry0, Entry1, k ) { if ( Vec_IntFind(vIn0, Entry0) >= 0 && Vec_IntFind(vIn1, Entry1) == -1 ) Vec_IntPush( vIn1, Entry1 ); else if ( Vec_IntFind(vIn0, Entry0) == -1 && Vec_IntFind(vIn1, Entry1) >= 0 ) Vec_IntPush( vIn0, Entry0 ); else assert( (Vec_IntFind(vIn0, Entry0) >= 0 && Vec_IntFind(vIn1, Entry1) >= 0) || (Vec_IntFind(vIn0, Entry1) >= 0 && Vec_IntFind(vIn1, Entry0) >= 0) ); } } Vec_IntReverseOrder( vIn0 ); Vec_IntReverseOrder( vIn1 ); vOut = NULL; } Vec_IntFree( vIndex ); Vec_WecFree( vAll ); return vRes; } Vec_Wec_t * Gia_ManMulFindBInputs( Gia_Man_t * p, Vec_Wec_t * vCuts4, Vec_Wec_t * vCuts5, int fVerbose ) { Vec_Wec_t * vRes = Vec_WecAlloc( 10 ); Vec_Int_t * vTemp; int g, c, k, Obj, Start; Vec_Int_t * vIndex = Gia_ManMulFindGroups( vCuts4, Gia_ManObjNum(p), 0 ); Vec_IntForEachEntryStop( vIndex, Start, g, Vec_IntSize(vIndex)-1 ) { Vec_Int_t * vAll = Vec_IntAlloc ( 100 ); Vec_WecForEachLevelStartStop( vCuts4, vTemp, c, Start, Vec_IntEntry(vIndex, g+1) ) Vec_IntForEachEntryStart( vTemp, Obj, k, 1 ) Vec_IntPush( vAll, Obj ); Vec_IntUniqify( vAll ); int GroupSize = Vec_IntEntry(vIndex, g+1) - Start; Vec_Int_t * vCnt = Vec_IntStart( Vec_IntSize(vAll) ); Vec_WecForEachLevelStartStop( vCuts4, vTemp, c, Start, Vec_IntEntry(vIndex, g+1) ) Vec_IntForEachEntryStart( vTemp, Obj, k, 1 ) Vec_IntAddToEntry( vCnt, Vec_IntFind(vAll, Obj), 1 ); if ( Vec_IntCountEntry(vCnt, 1) != 2 || Vec_IntCountEntry(vCnt, 2) != GroupSize-1 || Vec_IntCountEntry(vCnt, GroupSize) != 2 ) { printf( "Detection of group %d failed.\n", g ); continue; } Vec_Int_t * vIn1 = Vec_WecPushLevel( vRes ); Vec_Int_t * vIn2 = Vec_WecPushLevel( vRes ); Vec_Int_t * vOut = Vec_WecPushLevel( vRes ); Vec_IntForEachEntry( vAll, Obj, k ) if ( Vec_IntEntry(vCnt, k) <= 2 ) Vec_IntPush( vIn1, Obj ); else Vec_IntPush( vIn2, Obj ); Vec_IntSort( vIn1, 0 ); Vec_IntSort( vIn2, 0 ); // TODO: check chain in[i] -> in[i+1] Vec_WecForEachLevel( vCuts5, vTemp, c ) { Vec_IntShift( vTemp, 1 ); if ( Gia_ManMulFindOverlap(vTemp, vIn1) >= 2 ) Vec_IntForEachEntryStart( vTemp, Obj, k, 1 ) if ( Vec_IntFind(vIn1, Obj) == -1 ) { Vec_IntPushUnique(vIn2, Obj); } Vec_IntShift( vTemp, -1 ); } Vec_IntSort( vIn2, 0 ); vOut = NULL; } Vec_IntFree( vIndex ); return vRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManMulFindTfo( Gia_Man_t * p, Vec_Int_t * vIn0, Vec_Int_t * vIn1 ) { Vec_Int_t * vTfo = Vec_IntAlloc( 100 ); Gia_Obj_t * pObj; int i, Obj; Gia_ManIncrementTravId( p ); Vec_IntForEachEntry( vIn0, Obj, i ) Gia_ObjSetTravIdCurrentId( p, Obj ); Vec_IntForEachEntry( vIn1, Obj, i ) Gia_ObjSetTravIdCurrentId( p, Obj ); Gia_ManForEachAnd( p, pObj, i ) { if ( Gia_ObjIsTravIdCurrentId(p, i) ) continue; if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)) && Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)) ) Gia_ObjSetTravIdCurrentId( p, i ), Vec_IntPush( vTfo, i ); } return vTfo; } Vec_Wrd_t * Gia_ManMulFindSimCone( Gia_Man_t * p, Vec_Int_t * vIn0, Vec_Int_t * vIn1, Vec_Wrd_t * vSim0, Vec_Wrd_t * vSim1, Vec_Int_t * vTfo ) { Vec_Wrd_t * vRes = Vec_WrdAlloc( Vec_IntSize(vTfo) ); Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(p) ); Gia_Obj_t * pObj; int i, Obj; Vec_IntForEachEntry( vIn0, Obj, i ) Vec_WrdWriteEntry( vSims, Obj, Vec_WrdEntry(vSim0, i) ); Vec_IntForEachEntry( vIn1, Obj, i ) Vec_WrdWriteEntry( vSims, Obj, Vec_WrdEntry(vSim1, i) ); Gia_ManForEachObjVec( vTfo, p, pObj, i ) { word Sim0 = Vec_WrdEntry(vSims, Gia_ObjFaninId0p(p, pObj) ); word Sim1 = Vec_WrdEntry(vSims, Gia_ObjFaninId1p(p, pObj) ); Vec_WrdWriteEntry( vSims, Gia_ObjId(p, pObj), (Gia_ObjFaninC0(pObj) ? ~Sim0 : Sim0) & (Gia_ObjFaninC1(pObj) ? ~Sim1 : Sim1) ); } Vec_IntForEachEntry( vTfo, Obj, i ) Vec_WrdPush( vRes, Vec_WrdEntry(vSims, Obj) ); Vec_WrdFree( vSims ); return vRes; } int Gia_ManMulFindGetArg( Vec_Wrd_t * vSim, int i, int fSigned ) { int w, Res = 0; word Word = 0; Vec_WrdForEachEntry( vSim, Word, w ) if ( (Word >> i) & 1 ) Res |= (1 << w); if ( fSigned && ((Word >> i) & 1) ) Res |= ~0 << Vec_WrdSize(vSim); return Res; } void Gia_ManMulFindSetArg( Vec_Wrd_t * vSim, int i, int iNum ) { int w; word * pWords = Vec_WrdArray(vSim); for ( w = 0; w < Vec_WrdSize(vSim); w++ ) if ( (iNum >> w) & 1 ) pWords[w] |= (word)1 << i; } Vec_Wrd_t * Gia_ManMulFindSim( Vec_Wrd_t * vSim0, Vec_Wrd_t * vSim1, int fSigned ) { assert( Vec_WrdSize(vSim0) + Vec_WrdSize(vSim1) <= 30 ); Vec_Wrd_t * vRes = Vec_WrdStart( Vec_WrdSize(vSim0) + Vec_WrdSize(vSim1) ); for ( int i = 0; i < 64; i++ ) { int a = Gia_ManMulFindGetArg( vSim0, i, fSigned ); int b = Gia_ManMulFindGetArg( vSim1, i, fSigned ); Gia_ManMulFindSetArg( vRes, i, a * b ); } return vRes; } void Gia_ManMulFindOutputs( Gia_Man_t * p, Vec_Wec_t * vTerms, int fVerbose ) { Abc_Random(1); for ( int m = 0; m < Vec_WecSize(vTerms)/3; m++ ) { Vec_Int_t * vIn0 = Vec_WecEntry(vTerms, 3*m+0); Vec_Int_t * vIn1 = Vec_WecEntry(vTerms, 3*m+1); Vec_Int_t * vOut = Vec_WecEntry(vTerms, 3*m+2); Vec_Wrd_t * vSim0 = Vec_WrdStartRandom( Vec_IntSize(vIn0) ); Vec_Wrd_t * vSim1 = Vec_WrdStartRandom( Vec_IntSize(vIn1) ); Vec_Wrd_t * vSimU = Gia_ManMulFindSim( vSim0, vSim1, 0 ); Vec_Wrd_t * vSimS = Gia_ManMulFindSim( vSim0, vSim1, 1 ); Vec_Int_t * vTfo = Gia_ManMulFindTfo( p, vIn0, vIn1 ); Vec_Wrd_t * vSims = Gia_ManMulFindSimCone( p, vIn0, vIn1, vSim0, vSim1, vTfo ); Vec_Int_t * vOutU = Vec_IntAlloc( 100 ); Vec_Int_t * vOutS = Vec_IntAlloc( 100 ); word Word; int w, iPlace; Vec_WrdForEachEntry( vSimU, Word, w ) { if ( (iPlace = Vec_WrdFind(vSims, Word)) >= 0 ) Vec_IntPush( vOutU, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 0) ); else if ( (iPlace = Vec_WrdFind(vSims, ~Word)) >= 0 ) Vec_IntPush( vOutU, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 1) ); else Vec_IntPush( vOutU, -1 ); } Vec_WrdForEachEntry( vSimS, Word, w ) { if ( (iPlace = Vec_WrdFind(vSims, Word)) >= 0 ) Vec_IntPush( vOutS, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 0) ); else if ( (iPlace = Vec_WrdFind(vSims, ~Word)) >= 0 ) Vec_IntPush( vOutS, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 1) ); else Vec_IntPush( vOutS, -1 ); } assert( Vec_IntSize(vOut) == 0 ); if ( Vec_IntCountEntry(vOutU, -1) < Vec_IntSize(vOutU) || Vec_IntCountEntry(vOutS, -1) < Vec_IntSize(vOutS) ) { if ( Vec_IntCountEntry(vOutU, -1) < Vec_IntCountEntry(vOutS, -1) ) Vec_IntAppend( vOut, vOutU ), Vec_IntPush(vOut, 0); else Vec_IntAppend( vOut, vOutS ), Vec_IntPush(vOut, 1); } else { Vec_IntClear(vIn0); Vec_IntClear(vIn1); } Vec_WrdFree( vSim0 ); Vec_WrdFree( vSim1 ); Vec_WrdFree( vSimU ); Vec_WrdFree( vSimS ); Vec_WrdFree( vSims ); Vec_IntFree( vTfo ); Vec_IntFree( vOutU ); Vec_IntFree( vOutS ); } Vec_WecRemoveEmpty( vTerms ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Gia_ManMulFindCuts( Gia_Man_t * p, int nCutNum, int fVerbose ) { extern Vec_Mem_t * Dau_CollectNpnFunctions( word * p, int nVars, int fVerbose ); extern Vec_Ptr_t * Gia_ManMatchCutsArray( Vec_Ptr_t * vTtMems, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose ); word pTruths[3] = { ABC_CONST(0x6969696969696969), ABC_CONST(0x35C035C035C035C0), ABC_CONST(0xF335ACC0F335ACC0) }; Vec_Ptr_t * vTtMems = Vec_PtrAlloc( 3 ); Vec_Mem_t * vTtMem; int i; for ( i = 0; i < 3; i++ ) Vec_PtrPush( vTtMems, Dau_CollectNpnFunctions( pTruths+i, i+3, fVerbose ) ); Vec_Ptr_t * vAll = Gia_ManMatchCutsArray( vTtMems, p, 5, nCutNum, fVerbose ); Vec_PtrForEachEntry( Vec_Mem_t *, vTtMems, vTtMem, i ) Vec_MemHashFree( vTtMem ), Vec_MemFree( vTtMem ); Vec_PtrFree( vTtMems ); return vAll; } Vec_Wec_t * Gia_ManMulFindA( Gia_Man_t * p, Vec_Wec_t * vCuts3, int fVerbose ) { Vec_Wec_t * vXors = Gia_ManMulFindXors( p, vCuts3, fVerbose ); Vec_Wec_t * vTerms = Gia_ManMulFindAInputs2( p, fVerbose ); if ( Vec_WecSize(vTerms) ) Gia_ManMulFindOutputs( p, vTerms, fVerbose ); Vec_WecFree( vXors ); return vTerms; } Vec_Wec_t * Gia_ManMulFindB( Gia_Man_t * p, Vec_Wec_t * vCuts4, Vec_Wec_t * vCuts5, int fVerbose ) { Vec_Wec_t * vTerms = Vec_WecAlloc( 12 ); if ( Vec_WecSize(vCuts4) && Vec_WecSize(vCuts5) ) vTerms = Gia_ManMulFindBInputs2( p, vCuts4, vCuts5, fVerbose ); if ( Vec_WecSize(vTerms) ) Gia_ManMulFindOutputs( p, vTerms, fVerbose ); return vTerms; } void Gia_ManMulFindPrintSet( Vec_Int_t * vSet, int fLit, int fSkipLast ) { int i, Temp, Limit = Vec_IntSize(vSet) - fSkipLast; printf( "{" ); Vec_IntForEachEntryStop( vSet, Temp, i, Limit ) { if ( Temp == -1 ) printf( "n/a%s", i < Limit-1 ? " ":"" ); else printf( "%s%d%s", (fLit & Abc_LitIsCompl(Temp)) ? "~":"", fLit ? Abc_Lit2Var(Temp) : Temp, i < Limit-1 ? " ":"" ); } printf( "}" ); } void Gia_ManMulFindPrintOne( Vec_Wec_t * vTerms, int m, int fBooth ) { Vec_Int_t * vIn0 = Vec_WecEntry(vTerms, 3*m+0); Vec_Int_t * vIn1 = Vec_WecEntry(vTerms, 3*m+1); Vec_Int_t * vOut = Vec_WecEntry(vTerms, 3*m+2); printf( "%sooth %ssigned %d x %d: ", fBooth ? "B" : "Non-b", Vec_IntEntryLast(vOut) ? "" : "un", Vec_IntSize(vIn0), Vec_IntSize(vIn1) ); Gia_ManMulFindPrintSet( vIn0, 0, 0 ); printf( " * " ); Gia_ManMulFindPrintSet( vIn1, 0, 0 ); printf( " = " ); Gia_ManMulFindPrintSet( vOut, 1, 1 ); printf( "\n" ); } void Gia_ManMulFind( Gia_Man_t * p, int nCutNum, int fVerbose ) { Vec_Ptr_t * vAll = Gia_ManMulFindCuts( p, nCutNum, fVerbose ); int m; Vec_Wec_t * vCuts3 = (Vec_Wec_t *)Vec_PtrEntry(vAll, 0); Vec_Wec_t * vCuts4 = (Vec_Wec_t *)Vec_PtrEntry(vAll, 1); Vec_Wec_t * vCuts5 = (Vec_Wec_t *)Vec_PtrEntry(vAll, 2); Vec_Wec_t * vTermsB = Gia_ManMulFindB( p, vCuts4, vCuts5, fVerbose ); Vec_Wec_t * vTermsA = Gia_ManMulFindA( p, vCuts3, fVerbose ); printf( "Detected %d booth and %d non-booth multipliers.\n", Vec_WecSize(vTermsB)/3, Vec_WecSize(vTermsA)/3 ); for ( m = 0; m < Vec_WecSize(vTermsA)/3; m++ ) Gia_ManMulFindPrintOne( vTermsA, m, 0 ); for ( m = 0; m < Vec_WecSize(vTermsB)/3; m++ ) Gia_ManMulFindPrintOne( vTermsB, m, 1 ); Vec_WecFree( vTermsB ); Vec_WecFree( vTermsA ); Vec_WecFree( vCuts3 ); Vec_WecFree( vCuts4 ); Vec_WecFree( vCuts5 ); Vec_PtrFree( vAll ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaMuxes.c000066400000000000000000001210301477524141600162120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaMuxes.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Multiplexer profiling algorithm.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaMuxes.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/util/utilNam.h" #include "misc/util/utilTruth.h" #include "misc/vec/vecWec.h" #include "misc/vec/vecHsh.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Counts XORs and MUXes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCountMuxXor( Gia_Man_t * p, int * pnMuxes, int * pnXors ) { Gia_Obj_t * pObj, * pFan0, * pFan1; int i; *pnMuxes = *pnXors = 0; Gia_ManForEachAnd( p, pObj, i ) { if ( !Gia_ObjIsMuxType(pObj) ) continue; if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) (*pnXors)++; else (*pnMuxes)++; } } void Gia_ManPrintMuxStats( Gia_Man_t * p ) { int nAnds, nMuxes, nXors, nTotal; if ( p->pMuxes ) { nAnds = Gia_ManAndNotBufNum(p)-Gia_ManXorNum(p)-Gia_ManMuxNum(p); nXors = Gia_ManXorNum(p); nMuxes = Gia_ManMuxNum(p); nTotal = nAnds + 3*nXors + 3*nMuxes; } else { Gia_ManCountMuxXor( p, &nMuxes, &nXors ); nAnds = Gia_ManAndNotBufNum(p) - 3*nMuxes - 3*nXors; nTotal = Gia_ManAndNotBufNum(p); } Abc_Print( 1, "stats: " ); Abc_Print( 1, "xor =%8d %6.2f %% ", nXors, 300.0*nXors/nTotal ); Abc_Print( 1, "mux =%8d %6.2f %% ", nMuxes, 300.0*nMuxes/nTotal ); Abc_Print( 1, "and =%8d %6.2f %% ", nAnds, 100.0*nAnds/nTotal ); Abc_Print( 1, "obj =%8d ", Gia_ManAndNotBufNum(p) ); fflush( stdout ); } /**Function************************************************************* Synopsis [Derives GIA with MUXes.] Description [Create MUX if the sum of fanin references does not exceed limit.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupMuxes( Gia_Man_t * p, int Limit ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pFan0, * pFan1, * pFanC, * pSiblNew, * pObjNew; int i; assert( p->pMuxes == NULL ); assert( Limit >= 0 ); // allows to create AIG with XORs without MUXes 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 ); if ( Gia_ManHasChoices(p) ) pNew->pSibls = ABC_CALLOC( int, 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_ObjIsMuxType(pObj) || Gia_ObjSibl(p, Gia_ObjFaninId0(pObj, i)) || Gia_ObjSibl(p, Gia_ObjFaninId1(pObj, i)) ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) pObj->Value = Gia_ManHashXorReal( pNew, Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)) ); else if ( Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) + Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) > Limit ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else { pFanC = Gia_ObjRecognizeMux( pObj, &pFan1, &pFan0 ); pObj->Value = Gia_ManHashMuxReal( pNew, Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFanC)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)) ); } if ( !Gia_ObjSibl(p, i) ) continue; pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); pSiblNew = Gia_ManObj( pNew, Abc_Lit2Var(Gia_ObjSiblObj(p, i)->Value) ); if ( Gia_ObjIsAnd(pObjNew) && Gia_ObjIsAnd(pSiblNew) && Gia_ObjId(pNew, pObjNew) > Gia_ObjId(pNew, pSiblNew) ) pNew->pSibls[Gia_ObjId(pNew, pObjNew)] = Gia_ObjId(pNew, pSiblNew); } Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // perform cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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 || Gia_ManXorNum(p) ); // start the new manager pNew = Gia_ManStart( 5000 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); 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 = 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) ) pObj->Value = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // perform cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Test these procedures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupMuxesTest( Gia_Man_t * p ) { Gia_Man_t * pNew, * pNew2; pNew = Gia_ManDupMuxes( p, 2 ); pNew2 = Gia_ManDupNoMuxes( pNew, 0 ); Gia_ManPrintStats( p, NULL ); Gia_ManPrintStats( pNew, NULL ); Gia_ManPrintStats( pNew2, NULL ); Gia_ManStop( pNew ); // Gia_ManStop( pNew2 ); return pNew2; } /**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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_MuxRef_rec( Gia_Man_t * p, int iObj ) { Gia_Obj_t * pObj; if ( !Gia_ObjIsMuxId(p, iObj) ) return 0; pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjRefInc(p, pObj) ) return 0; return Gia_MuxRef_rec( p, Gia_ObjFaninId0p(p, pObj) ) + Gia_MuxRef_rec( p, Gia_ObjFaninId1p(p, pObj) ) + Gia_MuxRef_rec( p, Gia_ObjFaninId2p(p, pObj) ) + 1; } int Gia_MuxRef( Gia_Man_t * p, int iObj ) { Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); assert( Gia_ObjIsMuxId(p, iObj) ); return Gia_MuxRef_rec( p, Gia_ObjFaninId0p(p, pObj) ) + Gia_MuxRef_rec( p, Gia_ObjFaninId1p(p, pObj) ) + Gia_MuxRef_rec( p, Gia_ObjFaninId2p(p, pObj) ) + 1; } int Gia_MuxDeref_rec( Gia_Man_t * p, int iObj ) { Gia_Obj_t * pObj; if ( !Gia_ObjIsMuxId(p, iObj) ) return 0; pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjRefDec(p, pObj) ) return 0; return Gia_MuxDeref_rec( p, Gia_ObjFaninId0p(p, pObj) ) + Gia_MuxDeref_rec( p, Gia_ObjFaninId1p(p, pObj) ) + Gia_MuxDeref_rec( p, Gia_ObjFaninId2p(p, pObj) ) + 1; } int Gia_MuxDeref( Gia_Man_t * p, int iObj ) { Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); assert( Gia_ObjIsMuxId(p, iObj) ); return Gia_MuxDeref_rec( p, Gia_ObjFaninId0p(p, pObj) ) + Gia_MuxDeref_rec( p, Gia_ObjFaninId1p(p, pObj) ) + Gia_MuxDeref_rec( p, Gia_ObjFaninId2p(p, pObj) ) + 1; } int Gia_MuxMffcSize( Gia_Man_t * p, int iObj ) { int Count1, Count2; if ( !Gia_ObjIsMuxId(p, iObj) ) return 0; Count1 = Gia_MuxDeref( p, iObj ); Count2 = Gia_MuxRef( p, iObj ); assert( Count1 == Count2 ); return Count1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_MuxStructPrint_rec( Gia_Man_t * p, int iObj, int fFirst ) { Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); int iCtrl; if ( !fFirst && (!Gia_ObjIsMuxId(p, iObj) || Gia_ObjRefNumId(p, iObj) > 0) ) { // printf( "%d", iObj ); printf( "<%02d>", Gia_ObjLevelId(p, iObj) ); return; } iCtrl = Gia_ObjFaninId2p(p, pObj); printf( " [(" ); if ( Gia_ObjIsMuxId(p, iCtrl) && Gia_ObjRefNumId(p, iCtrl) == 0 ) Gia_MuxStructPrint_rec( p, iCtrl, 0 ); else { printf( "%d", iCtrl ); printf( "<%d>", Gia_ObjLevelId(p, iCtrl) ); } printf( ")" ); if ( Gia_ObjFaninC2(p, pObj) ) { Gia_MuxStructPrint_rec( p, Gia_ObjFaninId0p(p, pObj), 0 ); printf( "|" ); Gia_MuxStructPrint_rec( p, Gia_ObjFaninId1p(p, pObj), 0 ); printf( "]" ); } else { Gia_MuxStructPrint_rec( p, Gia_ObjFaninId1p(p, pObj), 0 ); printf( "|" ); Gia_MuxStructPrint_rec( p, Gia_ObjFaninId0p(p, pObj), 0 ); printf( "]" ); } } void Gia_MuxStructPrint( Gia_Man_t * p, int iObj ) { int Count1, Count2; assert( Gia_ObjIsMuxId(p, iObj) ); Count1 = Gia_MuxDeref( p, iObj ); Gia_MuxStructPrint_rec( p, iObj, 1 ); Count2 = Gia_MuxRef( p, iObj ); assert( Count1 == Count2 ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_MuxStructDump_rec( Gia_Man_t * p, int iObj, int fFirst, Vec_Str_t * vStr, int nDigitsId ) { Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); int iCtrl; if ( !fFirst && (!Gia_ObjIsMuxId(p, iObj) || Gia_ObjRefNumId(p, iObj) > 0) ) return; iCtrl = Gia_ObjFaninId2p(p, pObj); Vec_StrPush( vStr, '[' ); Vec_StrPush( vStr, '(' ); if ( Gia_ObjIsMuxId(p, iCtrl) && Gia_ObjRefNumId(p, iCtrl) == 0 ) Gia_MuxStructDump_rec( p, iCtrl, 0, vStr, nDigitsId ); else Vec_StrPrintNumStar( vStr, iCtrl, nDigitsId ); Vec_StrPush( vStr, ')' ); if ( Gia_ObjFaninC2(p, pObj) ) { Gia_MuxStructDump_rec( p, Gia_ObjFaninId0p(p, pObj), 0, vStr, nDigitsId ); Vec_StrPush( vStr, '|' ); Gia_MuxStructDump_rec( p, Gia_ObjFaninId1p(p, pObj), 0, vStr, nDigitsId ); Vec_StrPush( vStr, ']' ); } else { Gia_MuxStructDump_rec( p, Gia_ObjFaninId1p(p, pObj), 0, vStr, nDigitsId ); Vec_StrPush( vStr, '|' ); Gia_MuxStructDump_rec( p, Gia_ObjFaninId0p(p, pObj), 0, vStr, nDigitsId ); Vec_StrPush( vStr, ']' ); } } int Gia_MuxStructDump( Gia_Man_t * p, int iObj, Vec_Str_t * vStr, int nDigitsNum, int nDigitsId ) { int Count1, Count2; assert( Gia_ObjIsMuxId(p, iObj) ); Count1 = Gia_MuxDeref( p, iObj ); Vec_StrClear( vStr ); Vec_StrPrintNumStar( vStr, Count1, nDigitsNum ); Gia_MuxStructDump_rec( p, iObj, 1, vStr, nDigitsId ); Vec_StrPush( vStr, '\0' ); Count2 = Gia_MuxRef( p, iObj ); assert( Count1 == Count2 ); return Count1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManMuxCompare( char ** pp1, char ** pp2 ) { int Diff = strcmp( *pp1, *pp2 ); if ( Diff < 0 ) return 1; if ( Diff > 0) return -1; return 0; } int Gia_ManMuxCountOne( char * p ) { int Count = 0; for ( ; *p; p++ ) Count += (*p == '['); return Count; } typedef struct Mux_Man_t_ Mux_Man_t; struct Mux_Man_t_ { Gia_Man_t * pGia; // manager Abc_Nam_t * pNames; // hashing name into ID Vec_Wec_t * vTops; // top nodes for each struct }; /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Mux_Man_t * Mux_ManAlloc( Gia_Man_t * pGia ) { Mux_Man_t * p; p = ABC_CALLOC( Mux_Man_t, 1 ); p->pGia = pGia; p->pNames = Abc_NamStart( 10000, 50 ); p->vTops = Vec_WecAlloc( 1000 ); Vec_WecPushLevel( p->vTops ); return p; } void Mux_ManFree( Mux_Man_t * p ) { Abc_NamStop( p->pNames ); Vec_WecFree( p->vTops ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManMuxProfile( Mux_Man_t * p, int fWidth ) { int i, Entry, Counter, Total; Vec_Int_t * vVec, * vCounts; vCounts = Vec_IntStart( 1000 ); if ( fWidth ) { Vec_WecForEachLevelStart( p->vTops, vVec, i, 1 ) Vec_IntAddToEntry( vCounts, Abc_MinInt(Vec_IntSize(vVec), 999), 1 ); } else { for ( i = 1; i < Vec_WecSize(p->vTops); i++ ) Vec_IntAddToEntry( vCounts, Abc_MinInt(atoi(Abc_NamStr(p->pNames, i)), 999), 1 ); } Total = Vec_IntCountPositive(vCounts); if ( Total == 0 ) return 0; printf( "The distribution of MUX tree %s:\n", fWidth ? "widths" : "sizes" ); Counter = 0; Vec_IntForEachEntry( vCounts, Entry, i ) { if ( !Entry ) continue; if ( ++Counter == 12 ) printf( "\n" ), Counter = 0; printf( " %d=%d", i, Entry ); } printf( "\nSummary: " ); printf( "Max = %d ", Vec_IntFindMax(vCounts) ); printf( "Ave = %.2f", 1.0*Vec_IntSum(vCounts)/Total ); printf( "\n" ); Vec_IntFree( vCounts ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManMuxProfiling( Gia_Man_t * p ) { Mux_Man_t * pMan; Gia_Man_t * pNew; Gia_Obj_t * pObj; Vec_Str_t * vStr; Vec_Int_t * vFans, * vVec; int i, Counter, fFound, iStructId, nDigitsId; abctime clk = Abc_Clock(); pNew = Gia_ManDupMuxes( p, 2 ); nDigitsId = Abc_Base10Log( Gia_ManObjNum(pNew) ); pMan = Mux_ManAlloc( pNew ); Gia_ManLevelNum( pNew ); Gia_ManCreateRefs( pNew ); Gia_ManForEachCo( pNew, pObj, i ) Gia_ObjRefFanin0Inc( pNew, pObj ); vStr = Vec_StrAlloc( 1000 ); vFans = Gia_ManFirstFanouts( pNew ); Gia_ManForEachMux( pNew, pObj, i ) { // skip MUXes in the middle of the tree (which have only one MUX fanout) if ( Gia_ObjRefNumId(pNew, i) == 1 && Gia_ObjIsMuxId(pNew, Vec_IntEntry(vFans, i)) ) continue; // this node is the root of the MUX structure - create hash key Counter = Gia_MuxStructDump( pNew, i, vStr, 3, nDigitsId ); if ( Counter == 1 ) continue; iStructId = Abc_NamStrFindOrAdd( pMan->pNames, Vec_StrArray(vStr), &fFound ); if ( !fFound ) Vec_WecPushLevel( pMan->vTops ); assert( Abc_NamObjNumMax(pMan->pNames) == Vec_WecSize(pMan->vTops) ); Vec_IntPush( Vec_WecEntry(pMan->vTops, iStructId), i ); } Vec_StrFree( vStr ); Vec_IntFree( vFans ); printf( "MUX structure profile for AIG \"%s\":\n", p->pName ); printf( "Total MUXes = %d. Total trees = %d. Unique trees = %d. Memory = %.2f MB ", Gia_ManMuxNum(pNew), Vec_WecSizeSize(pMan->vTops), Vec_WecSize(pMan->vTops)-1, 1.0*Abc_NamMemUsed(pMan->pNames)/(1<<20) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( Gia_ManMuxProfile(pMan, 0) ) { Gia_ManMuxProfile( pMan, 1 ); // short the first ones printf( "The first %d structures: \n", 10 ); Vec_WecForEachLevelStartStop( pMan->vTops, vVec, i, 1, Abc_MinInt(Vec_WecSize(pMan->vTops), 10) ) { char * pTemp = Abc_NamStr(pMan->pNames, i); printf( "%5d : ", i ); printf( "Occur = %4d ", Vec_IntSize(vVec) ); printf( "Size = %4d ", atoi(pTemp) ); printf( "%s\n", pTemp ); } // print trees for the first one Counter = 0; Vec_WecForEachLevelStart( pMan->vTops, vVec, i, 1 ) { char * pTemp = Abc_NamStr(pMan->pNames, i); if ( Vec_IntSize(vVec) > 5 && atoi(pTemp) > 5 ) { int k, Entry; printf( "For example, structure %d has %d MUXes and bit-width %d:\n", i, atoi(pTemp), Vec_IntSize(vVec) ); Vec_IntForEachEntry( vVec, Entry, k ) Gia_MuxStructPrint( pNew, Entry ); if ( ++Counter == 5 ) break; } } } Mux_ManFree( pMan ); Gia_ManStop( pNew ); } /**Function************************************************************* Synopsis [Compute one-level TFI/TFO structural signatures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // these are object/fanin/fanout attributes // http://stackoverflow.com/questions/9907160/how-to-convert-enum-names-to-string-in-c #define GIA_FOREACH_ITEM(ITEM) \ ITEM(C0) \ ITEM(PO) \ ITEM(PI) \ ITEM(FF) \ ITEM(XOR) \ ITEM(MUX) \ ITEM(AND) \ ITEM(iC0) \ ITEM(iC1) \ ITEM(iPI) \ ITEM(iFF) \ ITEM(iXOR) \ ITEM(iMUX) \ ITEM(iAND) \ ITEM(iANDn) \ ITEM(iANDp) \ ITEM(oPO) \ ITEM(oFF) \ ITEM(oXOR) \ ITEM(oMUXc) \ ITEM(oMUXd) \ ITEM(oAND) \ ITEM(oANDn) \ ITEM(oANDp) \ ITEM(GIA_END) #define GENERATE_ENUM(ENUM) ENUM, typedef enum { GIA_FOREACH_ITEM(GENERATE_ENUM) } Gia_ObjType_t; #define GENERATE_STRING(STRING) #STRING, static const char * GIA_TYPE_STRINGS[] = { GIA_FOREACH_ITEM(GENERATE_STRING) }; void Gia_ManProfileStructuresTest( Gia_Man_t * p ) { int i; for ( i = 0; i < GIA_END; i++ ) printf( "%d = %s\n", i, GIA_TYPE_STRINGS[i] ); } // find object code int Gia_ManEncodeObj( Gia_Man_t * p, int i ) { Gia_Obj_t * pObj = Gia_ManObj( p, i ); assert( !Gia_ObjIsRi(p, pObj) ); if ( Gia_ObjIsConst0(pObj) ) return C0; if ( Gia_ObjIsPo(p, pObj) ) return PO; if ( Gia_ObjIsPi(p, pObj) ) return PI; if ( Gia_ObjIsCi(pObj) ) return FF; if ( Gia_ObjIsXor(pObj) ) return XOR; if ( Gia_ObjIsMux(p, pObj) ) return MUX; assert( Gia_ObjIsAnd(pObj) ); return AND; } // find fanin code int Gia_ManEncodeFanin( Gia_Man_t * p, int iLit ) { Gia_Obj_t * pObj = Gia_ManObj( p, Abc_Lit2Var(iLit) ); if ( Gia_ObjIsConst0(pObj) ) return iC0; if ( Gia_ObjIsPi(p, pObj) ) return iPI; if ( Gia_ObjIsCi(pObj) ) return iFF; if ( Gia_ObjIsXor(pObj) ) return iXOR; if ( Gia_ObjIsMux(p, pObj) ) return iMUX; assert( Gia_ObjIsAnd(pObj) ); return iAND; // if ( Abc_LitIsCompl(iLit) ) // return iANDn; // else // return iANDp; } // find fanout code Gia_ObjType_t Gia_ManEncodeFanout( Gia_Man_t * p, Gia_Obj_t * pObj, int i ) { // int iLit; if ( Gia_ObjIsPo(p, pObj) ) return oPO; if ( Gia_ObjIsCo(pObj) ) return oFF; if ( Gia_ObjIsXor(pObj) ) return oXOR; if ( Gia_ObjIsMux(p, pObj) ) return i == 2 ? oMUXc : oMUXd; assert( Gia_ObjIsAnd(pObj) ); return oAND; // iLit = i ? Gia_ObjFaninLit1p(p, pObj) : Gia_ObjFaninLit0p(p, pObj); // if ( Abc_LitIsCompl(iLit) ) // return oANDn; // else // return oANDp; } void Gia_ManProfileCollect( Gia_Man_t * p, int i, Vec_Int_t * vCode, Vec_Int_t * vCodeOffsets, Vec_Int_t * vArray ) { int k; Vec_IntClear( vArray ); for ( k = Vec_IntEntry(vCodeOffsets, i); k < Vec_IntEntry(vCodeOffsets, i+1); k++ ) Vec_IntPush( vArray, Vec_IntEntry(vCode, k) ); } void Gia_ManProfilePrintOne( Gia_Man_t * p, int i, Vec_Int_t * vArray ) { Gia_Obj_t * pObj = Gia_ManObj( p, i ); int k, nFanins, nFanouts; if ( Gia_ObjIsRi(p, pObj) ) return; nFanins = Gia_ObjIsRo(p, pObj) ? 1 : Gia_ObjFaninNum(p, pObj); nFanouts = Gia_ObjFanoutNum(p, pObj); printf( "%6d : ", i ); for ( k = 0; k < nFanins; k++ ) printf( " %5s", GIA_TYPE_STRINGS[Vec_IntEntry(vArray, k + 1)] ); for ( ; k < 3; k++ ) printf( " %5s", "" ); printf( " ->" ); printf( " %5s", GIA_TYPE_STRINGS[Vec_IntEntry(vArray, 0)] ); printf( " ->" ); if ( nFanouts > 0 ) { int Count = 1, Prev = Vec_IntEntry(vArray, 1 + nFanins); for ( k = 1; k < nFanouts; k++ ) { if ( Prev != Vec_IntEntry(vArray, k + 1 + nFanins) ) { printf( " %d x %s", Count, GIA_TYPE_STRINGS[Prev] ); Prev = Vec_IntEntry(vArray, k + 1 + nFanins); Count = 0; } Count++; } printf( " %d x %s", Count, GIA_TYPE_STRINGS[Prev] ); } printf( "\n" ); } Vec_Int_t * Gia_ManProfileHash( Gia_Man_t * p, Vec_Int_t * vCode, Vec_Int_t * vCodeOffsets ) { Hsh_VecMan_t * pHash; Vec_Int_t * vRes, * vArray; Gia_Obj_t * pObj; int i; vRes = Vec_IntAlloc( Gia_ManObjNum(p) ); pHash = Hsh_VecManStart( Gia_ManObjNum(p) ); // add empty entry vArray = Vec_IntAlloc( 100 ); Hsh_VecManAdd( pHash, vArray ); // iterate through the entries Gia_ManForEachObj( p, pObj, i ) { Gia_ManProfileCollect( p, i, vCode, vCodeOffsets, vArray ); Vec_IntPush( vRes, Hsh_VecManAdd( pHash, vArray ) ); } Hsh_VecManStop( pHash ); Vec_IntFree( vArray ); assert( Vec_IntSize(vRes) == Gia_ManObjNum(p) ); return vRes; } void Gia_ManProfileStructuresInt( Gia_Man_t * p, int nLimit, int fVerbose ) { Vec_Int_t * vRes, * vCount, * vFirst; Vec_Int_t * vCode, * vCodeOffsets, * vArray; Gia_Obj_t * pObj, * pFanout; int i, k, nFanins, nFanouts, * pPerm, nClasses; assert( p->pMuxes ); Gia_ManStaticFanoutStart( p ); // create fanout codes vArray = Vec_IntAlloc( 100 ); vCode = Vec_IntAlloc( 5 * Gia_ManObjNum(p) ); vCodeOffsets = Vec_IntAlloc( Gia_ManObjNum(p) ); Gia_ManForEachObj( p, pObj, i ) { Vec_IntPush( vCodeOffsets, Vec_IntSize(vCode) ); if ( Gia_ObjIsRi(p, pObj) ) continue; nFanins = Gia_ObjFaninNum(p, pObj); nFanouts = Gia_ObjFanoutNum(p, pObj); Vec_IntPush( vCode, Gia_ManEncodeObj(p, i) ); if ( nFanins == 3 ) { int iLit = Gia_ObjFaninLit2p(p, pObj); Vec_IntPush( vCode, Gia_ManEncodeFanin(p, Abc_LitRegular(iLit)) ); if ( Abc_LitIsCompl(iLit) ) { Vec_IntPush( vCode, Gia_ManEncodeFanin(p, Gia_ObjFaninLit0p(p, pObj)) ); Vec_IntPush( vCode, Gia_ManEncodeFanin(p, Gia_ObjFaninLit1p(p, pObj)) ); } else { Vec_IntPush( vCode, Gia_ManEncodeFanin(p, Gia_ObjFaninLit1p(p, pObj)) ); Vec_IntPush( vCode, Gia_ManEncodeFanin(p, Gia_ObjFaninLit0p(p, pObj)) ); } } else if ( nFanins == 2 ) { int Code0 = Gia_ManEncodeFanin(p, Gia_ObjFaninLit0p(p, pObj)); int Code1 = Gia_ManEncodeFanin(p, Gia_ObjFaninLit1p(p, pObj)); Vec_IntPush( vCode, Code0 < Code1 ? Code0 : Code1 ); Vec_IntPush( vCode, Code0 < Code1 ? Code1 : Code0 ); } else if ( nFanins == 1 ) Vec_IntPush( vCode, Gia_ManEncodeFanin(p, Gia_ObjFaninLit0p(p, pObj)) ); else if ( Gia_ObjIsRo(p, pObj) ) Vec_IntPush( vCode, Gia_ManEncodeFanin(p, Gia_ObjFaninLit0p(p, Gia_ObjRoToRi(p, pObj))) ); // add fanouts Vec_IntClear( vArray ); Gia_ObjForEachFanoutStatic( p, pObj, pFanout, k ) { int Index = Gia_ObjWhatFanin( p, pFanout, pObj ); Gia_ObjType_t Type = Gia_ManEncodeFanout( p, pFanout, Index ); Vec_IntPush( vArray, Type ); } Vec_IntSort( vArray, 0 ); Vec_IntAppend( vCode, vArray ); } assert( Vec_IntSize(vCodeOffsets) == Gia_ManObjNum(p) ); Vec_IntPush( vCodeOffsets, Vec_IntSize(vCode) ); // print the results if ( fVerbose ) { printf( "Showing TFI/node/TFO structures for all nodes:\n" ); Gia_ManForEachObj( p, pObj, i ) { Gia_ManProfileCollect( p, i, vCode, vCodeOffsets, vArray ); Gia_ManProfilePrintOne( p, i, vArray ); } } // collect statistics vRes = Gia_ManProfileHash( p, vCode, vCodeOffsets ); //Vec_IntPrint( vRes ); // count how many times each class appears nClasses = Vec_IntFindMax(vRes) + 1; vCount = Vec_IntStart( nClasses ); vFirst = Vec_IntStart( nClasses ); Gia_ManForEachObj( p, pObj, i ) { int Entry = Vec_IntEntry( vRes, i ); if ( Gia_ObjIsRi(p, pObj) ) continue; if ( Vec_IntEntry(vCount, Entry) == 0 ) Vec_IntWriteEntry( vFirst, Entry, i ); Vec_IntAddToEntry( vCount, Entry, -1 ); } // sort the counts pPerm = Abc_MergeSortCost( Vec_IntArray(vCount), Vec_IntSize(vCount) ); printf( "Showing TFI/node/TFO structures that appear more than %d times.\n", nLimit ); for ( i = 0; i < nClasses-1; i++ ) { if ( nLimit > -Vec_IntEntry(vCount, pPerm[i]) ) break; printf( "%6d : ", i ); printf( "%6d : ", pPerm[i] ); printf( "Weight =%6d ", -Vec_IntEntry(vCount, pPerm[i]) ); printf( "First obj =" ); // print the object Gia_ManProfileCollect( p, Vec_IntEntry(vFirst, pPerm[i]), vCode, vCodeOffsets, vArray ); Gia_ManProfilePrintOne( p, Vec_IntEntry(vFirst, pPerm[i]), vArray ); } // cleanup ABC_FREE( pPerm ); Vec_IntFree( vRes ); Vec_IntFree( vCount ); Vec_IntFree( vFirst ); Vec_IntFree( vArray ); Vec_IntFree( vCode ); Vec_IntFree( vCodeOffsets ); Gia_ManStaticFanoutStop( p ); } void Gia_ManProfileStructures( Gia_Man_t * p, int nLimit, int fVerbose ) { if ( p->pMuxes ) Gia_ManProfileStructuresInt( p, nLimit, fVerbose ); else { Gia_Man_t * pNew = Gia_ManDupMuxes( p, 2 ); Gia_ManProfileStructuresInt( pNew, nLimit, fVerbose ); Gia_ManStop( pNew ); } } /**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 /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaNewBdd.h000066400000000000000000000723021477524141600162700ustar00rootroot00000000000000/**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 #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; } static inline void fatal_error(const char* message) { std::cerr << message << std::endl; std::abort(); } 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) fatal_error("nCacheMax must not be smaller than nCacheSize"); nMax = (cac)1 << nCacheMaxLog; if(!(nMax << 1)) fatal_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()) fatal_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())) fatal_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) fatal_error("nObjsMax must not be smaller than nObjsAlloc"); if(nVars_ >= (int)VarMax()) fatal_error("Memout (nVars) in init"); nVars = nVars_; lit nObjsMaxLit = (lit)1 << p.nObjsMaxLog; if(!nObjsMaxLit) fatal_error("Memout (nObjsMax) in init"); if(nObjsMaxLit > (lit)BvarMax()) nObjsMax = BvarMax(); else nObjsMax = (bvar)nObjsMaxLit; lit nObjsAllocLit = (lit)1 << p.nObjsAllocLog; if(!nObjsAllocLit) fatal_error("Memout (nObjsAlloc) in init"); if(nObjsAllocLit > (lit)BvarMax()) nObjsAlloc = BvarMax(); else nObjsAlloc = (bvar)nObjsAllocLit; if(nObjsAlloc <= (bvar)nVars) fatal_error("nObjsAlloc must be larger than nVars"); uniq nUniqueSize = (uniq)1 << p.nUniqueSizeLog; if(!nUniqueSize) fatal_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) fatal_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 RemoveRefIfUnused() { if(!nGbc && nReo == BvarMax()) vRefs.clear(); } void TurnOnReo(int nReo_ = 0, std::vector const *vLits = NULL) { if(nReo_) nReo = nReo_; else nReo = nObjs << 1; if((lit)nReo > (lit)BvarMax()) nReo = BvarMax(); if(vRefs.empty()) { if(vLits) SetRef(*vLits); else vRefs.resize(nObjsAlloc); } } void TurnOffReo() { nReo = BvarMax(); } var GetNumVars() const { return nVars; } void GetOrdering(std::vector &Var2Level_) { Var2Level_.resize(nVars); for(var v = 0; v < nVars; v++) Var2Level_[v] = Var2Level[v]; } bvar CountNodes() { bvar count = 1; 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 abc-0.52/src/aig/gia/giaNewTt.h000066400000000000000000000217631477524141600161730ustar00rootroot00000000000000/**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 #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(); } static void fatal_error(const char* message) { std::cerr << message << std::endl; std::abort(); } struct Param { int nObjsAllocLog; int nObjsMaxLog; int nVerbose; bool fCountOnes; int nGbc; int nReo; // dummy std::vector *pVar2Level; // 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) fatal_error("nObjsMax must not be smaller than nObjsAlloc"); if(nVars >= lww()) nSize = 1ull << (nVars - lww()); else nSize = 1; if(!nSize) fatal_error("Memout (nVars) in init"); if(!(nSize << p.nObjsMaxLog)) fatal_error("Memout (nObjsMax) in init"); lit nObjsMaxLit = (lit)1 << p.nObjsMaxLog; if(!nObjsMaxLit) fatal_error("Memout (nObjsMax) in init"); if(nObjsMaxLit > (lit)BvarMax()) nObjsMax = BvarMax(); else nObjsMax = (bvar)nObjsMaxLit; lit nObjsAllocLit = (lit)1 << p.nObjsAllocLog; if(!nObjsAllocLit) fatal_error("Memout (nObjsAlloc) in init"); if(nObjsAllocLit > (lit)BvarMax()) nObjsAlloc = BvarMax(); else nObjsAlloc = (bvar)nObjsAllocLit; if(nObjsAlloc <= (bvar)nVars) fatal_error("nObjsAlloc must be larger than nVars"); nTotalSize = nSize << p.nObjsAllocLog; vVals.resize(nTotalSize); if(p.fCountOnes && nVars > 63) fatal_error("nVars must be less than 64 to count ones"); nObjs = 1; for(int i = 0; i < 6 && i < nVars; i++) { for(size j = 0; j < nSize; j++) 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())) fatal_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 RemoveRefIfUnused() { if(!nGbc) vRefs.clear(); } void TurnOffReo() {} int GetNumVars() const { return nVars; } void PrintNode(lit x) const { bvar a = Lit2Bvar(x); word c = LitIsCompl(x)? one(): 0; 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 abc-0.52/src/aig/gia/giaNf.c000066400000000000000000003136201477524141600154640ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaNf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Standard-cell mapper.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaNf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "gia.h" #include "misc/st/st.h" #include "map/mio/mio.h" #include "misc/util/utilTruth.h" #include "misc/extra/extra.h" #include "base/main/main.h" #include "misc/vec/vecMem.h" #include "misc/vec/vecWec.h" #include "opt/dau/dau.h" #include "misc/util/utilNam.h" #include "map/scl/sclCon.h" #include "misc/tim/tim.h" #ifdef _MSC_VER # include # define __builtin_popcount __popcnt #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define NF_LEAF_MAX 6 #define NF_CUT_MAX 32 #define NF_NO_LEAF 31 #define NF_NO_FUNC 0x3FFFFFF #define NF_EPSILON 0.001 typedef struct Nf_Cut_t_ Nf_Cut_t; struct Nf_Cut_t_ { word Sign; // signature int Delay; // delay float Flow; // flow unsigned iFunc : 26; // function (NF_NO_FUNC) unsigned Useless : 1; // function unsigned nLeaves : 5; // leaf number (NF_NO_LEAF) int pLeaves[NF_LEAF_MAX+1]; // leaves }; typedef struct Nf_Cfg_t_ Nf_Cfg_t; struct Nf_Cfg_t_ { unsigned fCompl : 1; // complemented unsigned Phase : 7; // match phase unsigned Perm : 24; // match permutation }; typedef struct Nf_Mat_t_ Nf_Mat_t; struct Nf_Mat_t_ { unsigned Gate : 20; // gate unsigned CutH : 10; // cut handle unsigned fCompl : 1; // complemented unsigned fBest : 1; // best cut Nf_Cfg_t Cfg; // input literals int D; // delay float F; // area }; typedef struct Nf_Obj_t_ Nf_Obj_t; struct Nf_Obj_t_ { Nf_Mat_t M[2][2]; // del/area (2x) }; typedef struct Nf_Man_t_ Nf_Man_t; struct Nf_Man_t_ { // user data Gia_Man_t * pGia; // derived manager Tim_Man_t * pManTim; // timing manager Jf_Par_t * pPars; // parameters // matching Vec_Mem_t * vTtMem; // truth tables Vec_Wec_t * vTt2Match; // matches for truth tables Mio_Cell2_t * pCells; // library gates int nCells; // library gate count // cut data Nf_Obj_t * pNfObjs; // best cuts Vec_Ptr_t vPages; // cut memory Vec_Int_t vCutSets; // cut offsets Vec_Int_t vMapRefs; // mapping refs (2x) Vec_Flt_t vFlowRefs; // flow refs (2x) Vec_Int_t vRequired; // required times (2x) Vec_Flt_t vCutFlows; // temporary cut area Vec_Int_t vCutDelays; // temporary cut delay Vec_Int_t vBackup; // backup literals int iCur; // current position int Iter; // mapping iterations int fUseEla; // use exact area int nInvs; // the inverter count int InvDelayI; // inverter delay word InvAreaW; // inverter delay float InvAreaF; // inverter area // statistics abctime clkStart; // starting time double CutCount[6]; // cut counts int nCutUseAll; // objects with useful cuts }; static inline int Nf_Cfg2Int( Nf_Cfg_t Mat ) { union { int x; Nf_Cfg_t y; } v; v.y = Mat; return v.x; } static inline Nf_Cfg_t Nf_Int2Cfg( int Int ) { union { int x; Nf_Cfg_t y; } v; v.x = Int; return v.y; } static inline Nf_Obj_t * Nf_ManObj( Nf_Man_t * p, int i ) { return p->pNfObjs + i; } static inline Mio_Cell2_t* Nf_ManCell( Nf_Man_t * p, int i ) { return p->pCells + i; } static inline int * Nf_ManCutSet( Nf_Man_t * p, int i ) { return (int *)Vec_PtrEntry(&p->vPages, i >> 16) + (i & 0xFFFF); } static inline int Nf_ObjCutSetId( Nf_Man_t * p, int i ) { return Vec_IntEntry( &p->vCutSets, i ); } static inline int * Nf_ObjCutSet( Nf_Man_t * p, int i ) { return Nf_ManCutSet(p, Nf_ObjCutSetId(p, i)); } static inline int Nf_ObjHasCuts( Nf_Man_t * p, int i ) { return (int)(Vec_IntEntry(&p->vCutSets, i) > 0); } static inline int * Nf_ObjCutBest( Nf_Man_t * p, int i ) { return NULL; } static inline int Nf_ObjCutUseless( Nf_Man_t * p, int TruthId ) { return (int)(TruthId >= Vec_WecSize(p->vTt2Match)); } static inline float Nf_ObjCutFlow( Nf_Man_t * p, int i ) { return Vec_FltEntry(&p->vCutFlows, i); } static inline int Nf_ObjCutDelay( Nf_Man_t * p, int i ) { return Vec_IntEntry(&p->vCutDelays, i); } static inline void Nf_ObjSetCutFlow( Nf_Man_t * p, int i, float a ) { Vec_FltWriteEntry(&p->vCutFlows, i, a); } static inline void Nf_ObjSetCutDelay( Nf_Man_t * p, int i, int d ) { Vec_IntWriteEntry(&p->vCutDelays, i, d); } static inline int Nf_ObjMapRefNum( Nf_Man_t * p, int i, int c ) { return Vec_IntEntry(&p->vMapRefs, Abc_Var2Lit(i,c)); } static inline int Nf_ObjMapRefInc( Nf_Man_t * p, int i, int c ) { return (*Vec_IntEntryP(&p->vMapRefs, Abc_Var2Lit(i,c)))++; } static inline int Nf_ObjMapRefDec( Nf_Man_t * p, int i, int c ) { return --(*Vec_IntEntryP(&p->vMapRefs, Abc_Var2Lit(i,c))); } static inline float Nf_ObjFlowRefs( Nf_Man_t * p, int i, int c ) { return Vec_FltEntry(&p->vFlowRefs, Abc_Var2Lit(i,c)); } static inline int Nf_ObjRequired( Nf_Man_t * p, int i, int c ) { return Vec_IntEntry(&p->vRequired, Abc_Var2Lit(i,c)); } static inline void Nf_ObjSetRequired( Nf_Man_t * p,int i, int c, int f ) { Vec_IntWriteEntry(&p->vRequired, Abc_Var2Lit(i,c), f); } static inline void Nf_ObjUpdateRequired( Nf_Man_t * p,int i, int c, int f ) { if (Nf_ObjRequired(p, i, c) > f) Nf_ObjSetRequired(p, i, c, f); } static inline Nf_Mat_t * Nf_ObjMatchD( Nf_Man_t * p, int i, int c ) { return &Nf_ManObj(p, i)->M[c][0]; } static inline Nf_Mat_t * Nf_ObjMatchA( Nf_Man_t * p, int i, int c ) { return &Nf_ManObj(p, i)->M[c][1]; } static inline int Nf_CutSize( int * pCut ) { return pCut[0] & NF_NO_LEAF; } static inline int Nf_CutFunc( int * pCut ) { return ((unsigned)pCut[0] >> 5); } static inline int * Nf_CutLeaves( int * pCut ) { return pCut + 1; } static inline int Nf_CutSetBoth( int n, int f ) { return n | (f << 5); } static inline int Nf_CutIsTriv( int * pCut, int i ) { return Nf_CutSize(pCut) == 1 && pCut[1] == i; } static inline int Nf_CutHandle( int * pCutSet, int * pCut ) { assert( pCut > pCutSet ); return pCut - pCutSet; } static inline int * Nf_CutFromHandle( int * pCutSet, int h ) { assert( h > 0 ); return pCutSet + h; } static inline int Nf_CfgVar( Nf_Cfg_t Cfg, int i ) { return (Cfg.Perm >> (i<<2)) & 15; } static inline int Nf_CfgCompl( Nf_Cfg_t Cfg, int i ) { return (Cfg.Phase >> i) & 1; } #define Nf_SetForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += Nf_CutSize(pCut) + 1 ) #define Nf_CutForEachVarCompl( pCut, Cfg, iVar, fCompl, i ) for ( i = 0; i < Nf_CutSize(pCut) && (iVar = Nf_CutLeaves(pCut)[Nf_CfgVar(Cfg, i)]) && ((fCompl = Nf_CfgCompl(Cfg, i)), 1); i++ ) #define Nf_CfgForEachVarCompl( Cfg, Size, iVar, fCompl, i ) for ( i = 0; i < Size && ((iVar = Nf_CfgVar(Cfg, i)), 1) && ((fCompl = Nf_CfgCompl(Cfg, i)), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Nf_StoCellIsDominated( Mio_Cell2_t * pCell, int * pFans, int * pProf ) { int k; if ( pCell->AreaF + NF_EPSILON < Abc_Int2Float(pProf[0]) ) return 0; for ( k = 0; k < (int)pCell->nFanins; k++ ) if ( pCell->iDelays[Abc_Lit2Var(pFans[k])] < pProf[k+1] ) return 0; return 1; // pCell is dominated } void Nf_StoCreateGateAdd( Vec_Mem_t * vTtMem, Vec_Wec_t * vTt2Match, Mio_Cell2_t * pCell, word uTruth, int * pFans, int nFans, Vec_Wec_t * vProfs, Vec_Int_t * vStore, int fPinFilter, int fPinPerm, int fPinQuick ) { Vec_Int_t * vArray, * vArrayProfs = NULL; int i, k, GateId, Entry, fCompl = (int)(uTruth & 1); word uFunc = fCompl ? ~uTruth : uTruth; int iFunc = Vec_MemHashInsert( vTtMem, &uFunc ); Nf_Cfg_t Mat = Nf_Int2Cfg(0); // get match array if ( iFunc == Vec_WecSize(vTt2Match) ) Vec_WecPushLevel( vTt2Match ); vArray = Vec_WecEntry( vTt2Match, iFunc ); // create match Mat.fCompl = fCompl; assert( nFans == (int)pCell->nFanins ); for ( i = 0; i < nFans; i++ ) { Mat.Perm |= (unsigned)(i << (Abc_Lit2Var(pFans[i]) << 2)); Mat.Phase |= (unsigned)(Abc_LitIsCompl(pFans[i]) << Abc_Lit2Var(pFans[i])); } // check other profiles if ( fPinFilter ) { // get profile array assert( Vec_WecSize(vTt2Match) == Vec_WecSize(vProfs) ); if ( iFunc == Vec_WecSize(vProfs) ) Vec_WecPushLevel( vProfs ); vArrayProfs = Vec_WecEntry( vProfs, iFunc ); assert( Vec_IntSize(vArray) == 2 * Vec_IntSize(vArrayProfs) ); // skip dominated matches Vec_IntForEachEntryDouble( vArray, GateId, Entry, i ) if ( Nf_Int2Cfg(Entry).Phase == Mat.Phase && Nf_Int2Cfg(Entry).fCompl == Mat.fCompl ) { int Offset = Vec_IntEntry(vArrayProfs, i/2); int * pProf = Vec_IntEntryP(vStore, Offset); if ( Nf_StoCellIsDominated(pCell, pFans, pProf) ) return; } } // check pin permutation if ( !fPinPerm ) // do not use pin-permutation (improves delay when pin-delays differ) { if ( fPinQuick ) // reduce the number of matches agressively { Vec_IntForEachEntryDouble( vArray, GateId, Entry, i ) if ( GateId == (int)pCell->Id && __builtin_popcount( Nf_Int2Cfg(Entry).Phase & 0xff ) == __builtin_popcount( Mat.Phase & 0xff ) ) return; } else // reduce the number of matches less agressively { Vec_IntForEachEntryDouble( vArray, GateId, Entry, i ) if ( GateId == (int)pCell->Id && Nf_Int2Cfg(Entry).Phase == Mat.Phase ) return; } } // save data and profile Vec_IntPush( vArray, pCell->Id ); Vec_IntPush( vArray, Nf_Cfg2Int(Mat) ); // add delay profile if ( fPinFilter ) { Vec_IntPush( vArrayProfs, Vec_IntSize(vStore) ); Vec_IntPush( vStore, Abc_Float2Int(pCell->AreaF) ); for ( k = 0; k < nFans; k++ ) Vec_IntPush( vStore, pCell->iDelays[Abc_Lit2Var(pFans[k])] ); } } void Nf_StoCreateGateMaches( Vec_Mem_t * vTtMem, Vec_Wec_t * vTt2Match, Mio_Cell2_t * pCell, int ** pComp, int ** pPerm, int * pnPerms, Vec_Wec_t * vProfs, Vec_Int_t * vStore, int fPinFilter, int fPinPerm, int fPinQuick ) { int Perm[NF_LEAF_MAX], * Perm1, * Perm2; int nPerms = pnPerms[pCell->nFanins]; int nMints = (1 << pCell->nFanins); word tCur, tTemp1, tTemp2; int i, p, c; assert( pCell->nFanins <= 6 ); for ( i = 0; i < (int)pCell->nFanins; i++ ) Perm[i] = Abc_Var2Lit( i, 0 ); tCur = tTemp1 = pCell->uTruth; for ( p = 0; p < nPerms; p++ ) { tTemp2 = tCur; for ( c = 0; c < nMints; c++ ) { Nf_StoCreateGateAdd( vTtMem, vTt2Match, pCell, tCur, Perm, pCell->nFanins, vProfs, vStore, fPinFilter, fPinPerm, fPinQuick ); // update tCur = Abc_Tt6Flip( tCur, pComp[pCell->nFanins][c] ); Perm1 = Perm + pComp[pCell->nFanins][c]; *Perm1 = Abc_LitNot( *Perm1 ); } assert( tTemp2 == tCur ); if ( nPerms == 1 ) continue; // update tCur = Abc_Tt6SwapAdjacent( tCur, pPerm[pCell->nFanins][p] ); Perm1 = Perm + pPerm[pCell->nFanins][p]; Perm2 = Perm1 + 1; ABC_SWAP( int, *Perm1, *Perm2 ); } assert( tTemp1 == tCur ); } Mio_Cell2_t * Nf_StoDeriveMatches( Vec_Mem_t * vTtMem, Vec_Wec_t * vTt2Match, int * pnCells, int fPinFilter, int fPinPerm, int fPinQuick ) { int fVerbose = 0; //abctime clk = Abc_Clock(); Vec_Wec_t * vProfs = Vec_WecAlloc( 1000 ); Vec_Int_t * vStore = Vec_IntAlloc( 10000 ); int * pComp[7], * pPerm[7], nPerms[7], i; Mio_Cell2_t * pCells; Vec_WecPushLevel( vProfs ); Vec_WecPushLevel( vProfs ); for ( i = 1; i <= 6; i++ ) pComp[i] = Extra_GreyCodeSchedule( i ); for ( i = 1; i <= 6; i++ ) pPerm[i] = Extra_PermSchedule( i ); for ( i = 1; i <= 6; i++ ) nPerms[i] = Extra_Factorial( i ); pCells = Mio_CollectRootsNewDefault2( 6, pnCells, fVerbose ); if ( pCells != NULL ) for ( i = 2; i < *pnCells; i++ ) Nf_StoCreateGateMaches( vTtMem, vTt2Match, pCells+i, pComp, pPerm, nPerms, vProfs, vStore, fPinFilter, fPinPerm, fPinQuick ); for ( i = 1; i <= 6; i++ ) ABC_FREE( pComp[i] ); for ( i = 1; i <= 6; i++ ) ABC_FREE( pPerm[i] ); Vec_WecFree( vProfs ); Vec_IntFree( vStore ); //Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return pCells; } void Nf_StoPrintOne( Nf_Man_t * p, int Count, int t, int i, int GateId, Nf_Cfg_t Mat ) { Mio_Cell2_t * pC = p->pCells + GateId; word * pTruth = Vec_MemReadEntry(p->vTtMem, t); int k, nSuppSize = Abc_TtSupportSize(pTruth, 6); printf( "%6d : ", Count ); printf( "%6d : ", t ); printf( "%6d : ", i ); printf( "Gate %16s ", pC->pName ); printf( "Area =%8.2f ", pC->AreaF ); printf( "In = %d ", pC->nFanins ); if ( Mat.fCompl ) printf( " compl " ); else printf( " " ); for ( k = 0; k < (int)pC->nFanins; k++ ) { int fComplF = (Mat.Phase >> k) & 1; int iFanin = (Mat.Perm >> (3*k)) & 7; printf( "%c", 'a' + iFanin - fComplF * ('a' - 'A') ); } printf( " " ); Dau_DsdPrintFromTruth( pTruth, nSuppSize ); } void Nf_StoPrint( Nf_Man_t * p, int fVerbose ) { int t, i, GateId, Entry, Count = 0; for ( t = 2; t < Vec_WecSize(p->vTt2Match); t++ ) { Vec_Int_t * vArr = Vec_WecEntry( p->vTt2Match, t ); Vec_IntForEachEntryDouble( vArr, GateId, Entry, i ) { Count++; if ( !fVerbose ) continue; //if ( t < 10 ) // Nf_StoPrintOne( p, Count, t, i/2, GateId, Pf_Int2Mat(Entry) ); } } printf( "Gates = %d. Truths = %d. Matches = %d.\n", p->nCells, Vec_MemEntryNum(p->vTtMem), Count ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Nf_Man_t * Nf_StoCreate( Gia_Man_t * pGia, Jf_Par_t * pPars ) { extern void Mf_ManSetFlowRefs( Gia_Man_t * p, Vec_Int_t * vRefs ); Vec_Int_t * vFlowRefs; Nf_Man_t * p; int i, Entry; assert( pPars->nCutNum > 1 && pPars->nCutNum <= NF_CUT_MAX ); assert( pPars->nLutSize > 1 && pPars->nLutSize <= NF_LEAF_MAX ); ABC_FREE( pGia->pRefs ); Vec_IntFreeP( &pGia->vCellMapping ); if ( Gia_ManHasChoices(pGia) ) Gia_ManSetPhase(pGia); // create p = ABC_CALLOC( Nf_Man_t, 1 ); p->clkStart = Abc_Clock(); p->pGia = pGia; p->pManTim = (Tim_Man_t *)pGia->pManTime; p->pPars = pPars; p->pNfObjs = ABC_CALLOC( Nf_Obj_t, Gia_ManObjNum(pGia) ); p->iCur = 2; // other Vec_PtrGrow( &p->vPages, 256 ); // cut memory Vec_IntFill( &p->vMapRefs, 2*Gia_ManObjNum(pGia), 0 ); // mapping refs (2x) Vec_FltFill( &p->vFlowRefs, 2*Gia_ManObjNum(pGia), 0 ); // flow refs (2x) Vec_IntFill( &p->vRequired, 2*Gia_ManObjNum(pGia), SCL_INFINITY ); // required times (2x) Vec_IntFill( &p->vCutSets, Gia_ManObjNum(pGia), 0 ); // cut offsets Vec_FltFill( &p->vCutFlows, Gia_ManObjNum(pGia), 0 ); // cut area Vec_IntFill( &p->vCutDelays,Gia_ManObjNum(pGia), 0 ); // cut delay Vec_IntGrow( &p->vBackup, 1000 ); // references vFlowRefs = Vec_IntAlloc(0); Mf_ManSetFlowRefs( pGia, vFlowRefs ); Vec_IntForEachEntry( vFlowRefs, Entry, i ) { Vec_FltWriteEntry( &p->vFlowRefs, 2*i, /*0.5* */Entry ); Vec_FltWriteEntry( &p->vFlowRefs, 2*i+1, /*0.5* */Entry ); } Vec_IntFree(vFlowRefs); // matching Mio_LibraryMatchesFetch( (Mio_Library_t *)Abc_FrameReadLibGen(), &p->vTtMem, &p->vTt2Match, &p->pCells, &p->nCells, p->pPars->fPinFilter, p->pPars->fPinPerm, p->pPars->fPinQuick ); if ( p->pCells == NULL ) return NULL; p->InvDelayI = p->pCells[3].iDelays[0]; p->InvAreaW = p->pCells[3].AreaW; p->InvAreaF = p->pCells[3].AreaF; Nf_ObjMatchD(p, 0, 0)->Gate = 0; Nf_ObjMatchD(p, 0, 1)->Gate = 1; // prepare cuts return p; } void Nf_StoDelete( Nf_Man_t * p ) { Vec_PtrFreeData( &p->vPages ); ABC_FREE( p->vPages.pArray ); ABC_FREE( p->vMapRefs.pArray ); ABC_FREE( p->vFlowRefs.pArray ); ABC_FREE( p->vRequired.pArray ); ABC_FREE( p->vCutSets.pArray ); ABC_FREE( p->vCutFlows.pArray ); ABC_FREE( p->vCutDelays.pArray ); ABC_FREE( p->vBackup.pArray ); ABC_FREE( p->pNfObjs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Nf_CutComputeTruth6( Nf_Man_t * p, Nf_Cut_t * pCut0, Nf_Cut_t * pCut1, int fCompl0, int fCompl1, Nf_Cut_t * pCutR, int fIsXor ) { // extern int Nf_ManTruthCanonicize( word * t, int nVars ); int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t = fIsXor ? t0 ^ t1 : t0 & t1; if ( (fCompl = (int)(t & 1)) ) t = ~t; pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); assert( (int)(t & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, &t); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); pCutR->Useless = Nf_ObjCutUseless( p, truthId ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } static inline int Nf_CutComputeTruthMux6( Nf_Man_t * p, Nf_Cut_t * pCut0, Nf_Cut_t * pCut1, Nf_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Nf_Cut_t * pCutR ) { int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); word tC = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCutC->iFunc)); if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; if ( Abc_LitIsCompl(pCutC->iFunc) ^ fComplC ) tC = ~tC; t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); tC = Abc_Tt6Expand( tC, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t = (tC & t1) | (~tC & t0); if ( (fCompl = (int)(t & 1)) ) t = ~t; pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); assert( (int)(t & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, &t); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); pCutR->Useless = Nf_ObjCutUseless( p, truthId ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Nf_CutCountBits( word i ) { i = i - ((i >> 1) & 0x5555555555555555); i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); return (i*(0x0101010101010101))>>56; } static inline word Nf_CutGetSign( int * pLeaves, int nLeaves ) { word Sign = 0; int i; for ( i = 0; i < nLeaves; i++ ) Sign |= ((word)1) << (pLeaves[i] & 0x3F); return Sign; } static inline int Nf_CutCreateUnit( Nf_Cut_t * p, int i ) { p->Delay = 0; p->Flow = 0; p->iFunc = 2; p->nLeaves = 1; p->pLeaves[0] = i; p->Sign = ((word)1) << (i & 0x3F); return 1; } static inline void Nf_CutPrint( Nf_Man_t * p, Nf_Cut_t * pCut ) { int i, nDigits = Abc_Base10Log(Gia_ManObjNum(p->pGia)); printf( "%d {", pCut->nLeaves ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) printf( " %*d", nDigits, pCut->pLeaves[i] ); for ( ; i < (int)p->pPars->nLutSize; i++ ) printf( " %*s", nDigits, " " ); printf( " } Useless = %d. D = %4d A = %9.4f F = %6d ", pCut->Useless, pCut->Delay, pCut->Flow, pCut->iFunc ); if ( p->vTtMem ) Dau_DsdPrintFromTruth( Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut->iFunc)), pCut->nLeaves ); else printf( "\n" ); } static inline int Nf_ManPrepareCuts( Nf_Cut_t * pCuts, Nf_Man_t * p, int iObj, int fAddUnit ) { if ( Nf_ObjHasCuts(p, iObj) ) { Nf_Cut_t * pMfCut = pCuts; int i, * pCut, * pList = Nf_ObjCutSet(p, iObj); Nf_SetForEachCut( pList, pCut, i ) { pMfCut->Delay = 0; pMfCut->Flow = 0; pMfCut->iFunc = Nf_CutFunc( pCut ); pMfCut->nLeaves = Nf_CutSize( pCut ); pMfCut->Sign = Nf_CutGetSign( pCut+1, Nf_CutSize(pCut) ); pMfCut->Useless = Nf_ObjCutUseless( p, Abc_Lit2Var(pMfCut->iFunc) ); memcpy( pMfCut->pLeaves, pCut+1, sizeof(int) * Nf_CutSize(pCut) ); pMfCut++; } if ( fAddUnit && pCuts->nLeaves > 1 ) return pList[0] + Nf_CutCreateUnit( pMfCut, iObj ); return pList[0]; } return Nf_CutCreateUnit( pCuts, iObj ); } static inline int Nf_ManSaveCuts( Nf_Man_t * p, Nf_Cut_t ** pCuts, int nCuts, int fUseful ) { int i, * pPlace, iCur, nInts = 1, nCutsNew = 0; for ( i = 0; i < nCuts; i++ ) if ( !fUseful || !pCuts[i]->Useless ) nInts += pCuts[i]->nLeaves + 1, nCutsNew++; if ( (p->iCur & 0xFFFF) + nInts > 0xFFFF ) p->iCur = ((p->iCur >> 16) + 1) << 16; if ( Vec_PtrSize(&p->vPages) == (p->iCur >> 16) ) Vec_PtrPush( &p->vPages, ABC_ALLOC(int, (1<<16)) ); iCur = p->iCur; p->iCur += nInts; pPlace = Nf_ManCutSet( p, iCur ); *pPlace++ = nCutsNew; for ( i = 0; i < nCuts; i++ ) if ( !fUseful || !pCuts[i]->Useless ) { *pPlace++ = Nf_CutSetBoth( pCuts[i]->nLeaves, pCuts[i]->iFunc ); memcpy( pPlace, pCuts[i]->pLeaves, sizeof(int) * pCuts[i]->nLeaves ); pPlace += pCuts[i]->nLeaves; } return iCur; } static inline int Nf_ManCountUseful( Nf_Cut_t ** pCuts, int nCuts ) { int i, Count = 0; for ( i = 0; i < nCuts; i++ ) Count += !pCuts[i]->Useless; return Count; } static inline int Nf_ManCountMatches( Nf_Man_t * p, Nf_Cut_t ** pCuts, int nCuts ) { int i, Count = 0; for ( i = 0; i < nCuts; i++ ) if ( !pCuts[i]->Useless ) Count += Vec_IntSize(Vec_WecEntry(p->vTt2Match, Abc_Lit2Var(pCuts[i]->iFunc))) / 2; return Count; } /**Function************************************************************* Synopsis [Check correctness of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Nf_CutCheck( Nf_Cut_t * pBase, Nf_Cut_t * pCut ) // check if pCut is contained in pBase { int nSizeB = pBase->nLeaves; int nSizeC = pCut->nLeaves; int i, * pB = pBase->pLeaves; int k, * pC = pCut->pLeaves; for ( i = 0; i < nSizeC; i++ ) { for ( k = 0; k < nSizeB; k++ ) if ( pC[i] == pB[k] ) break; if ( k == nSizeB ) return 0; } return 1; } static inline int Nf_SetCheckArray( Nf_Cut_t ** ppCuts, int nCuts ) { Nf_Cut_t * pCut0, * pCut1; int i, k, m, n, Value; assert( nCuts > 0 ); for ( i = 0; i < nCuts; i++ ) { pCut0 = ppCuts[i]; assert( pCut0->nLeaves <= NF_LEAF_MAX ); assert( pCut0->Sign == Nf_CutGetSign(pCut0->pLeaves, pCut0->nLeaves) ); // check duplicates for ( m = 0; m < (int)pCut0->nLeaves; m++ ) for ( n = m + 1; n < (int)pCut0->nLeaves; n++ ) assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] ); // check pairs for ( k = 0; k < nCuts; k++ ) { pCut1 = ppCuts[k]; if ( pCut0 == pCut1 ) continue; // check containments Value = Nf_CutCheck( pCut0, pCut1 ); assert( Value == 0 ); } } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Nf_CutMergeOrder( Nf_Cut_t * pCut0, Nf_Cut_t * pCut1, Nf_Cut_t * pCut, int nLutSize ) { int nSize0 = pCut0->nLeaves; int nSize1 = pCut1->nLeaves; int i, * pC0 = pCut0->pLeaves; int k, * pC1 = pCut1->pLeaves; int c, * pC = pCut->pLeaves; // the case of the largest cut sizes if ( nSize0 == nLutSize && nSize1 == nLutSize ) { for ( i = 0; i < nSize0; i++ ) { if ( pC0[i] != pC1[i] ) return 0; pC[i] = pC0[i]; } pCut->nLeaves = nLutSize; pCut->iFunc = NF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; } // compare two cuts with different numbers i = k = c = 0; if ( nSize0 == 0 ) goto FlushCut1; if ( nSize1 == 0 ) goto FlushCut0; while ( 1 ) { if ( c == nLutSize ) return 0; if ( pC0[i] < pC1[k] ) { pC[c++] = pC0[i++]; if ( i >= nSize0 ) goto FlushCut1; } else if ( pC0[i] > pC1[k] ) { pC[c++] = pC1[k++]; if ( k >= nSize1 ) goto FlushCut0; } else { pC[c++] = pC0[i++]; k++; if ( i >= nSize0 ) goto FlushCut1; if ( k >= nSize1 ) goto FlushCut0; } } FlushCut0: if ( c + nSize0 > nLutSize + i ) return 0; while ( i < nSize0 ) pC[c++] = pC0[i++]; pCut->nLeaves = c; pCut->iFunc = NF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; FlushCut1: if ( c + nSize1 > nLutSize + k ) return 0; while ( k < nSize1 ) pC[c++] = pC1[k++]; pCut->nLeaves = c; pCut->iFunc = NF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; } static inline int Nf_CutMergeOrderMux( Nf_Cut_t * pCut0, Nf_Cut_t * pCut1, Nf_Cut_t * pCut2, Nf_Cut_t * pCut, int nLutSize ) { int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; int x2, i2 = 0, nSize2 = pCut2->nLeaves, * pC2 = pCut2->pLeaves; int xMin, c = 0, * pC = pCut->pLeaves; while ( 1 ) { x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; x2 = (i2 == nSize2) ? ABC_INFINITY : pC2[i2]; xMin = Abc_MinInt( Abc_MinInt(x0, x1), x2 ); if ( xMin == ABC_INFINITY ) break; if ( c == nLutSize ) return 0; pC[c++] = xMin; if (x0 == xMin) i0++; if (x1 == xMin) i1++; if (x2 == xMin) i2++; } pCut->nLeaves = c; pCut->iFunc = NF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign | pCut2->Sign; return 1; } static inline int Nf_SetCutIsContainedOrder( Nf_Cut_t * pBase, Nf_Cut_t * pCut ) // check if pCut is contained in pBase { int i, nSizeB = pBase->nLeaves; int k, nSizeC = pCut->nLeaves; if ( nSizeB == nSizeC ) { for ( i = 0; i < nSizeB; i++ ) if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) return 0; return 1; } assert( nSizeB > nSizeC ); if ( nSizeC == 0 ) return 1; for ( i = k = 0; i < nSizeB; i++ ) { if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) return 0; if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) { if ( ++k == nSizeC ) return 1; } } return 0; } static inline int Nf_SetLastCutIsContained( Nf_Cut_t ** pCuts, int nCuts ) { int i; for ( i = 0; i < nCuts; i++ ) if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Nf_SetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) ) return 1; return 0; } static inline int Nf_SetLastCutContainsArea( Nf_Cut_t ** pCuts, int nCuts ) { int i, k, fChanges = 0; for ( i = 0; i < nCuts; i++ ) if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Nf_SetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) ) pCuts[i]->nLeaves = NF_NO_LEAF, fChanges = 1; if ( !fChanges ) return nCuts; for ( i = k = 0; i <= nCuts; i++ ) { if ( pCuts[i]->nLeaves == NF_NO_LEAF ) continue; if ( k < i ) ABC_SWAP( Nf_Cut_t *, pCuts[k], pCuts[i] ); k++; } return k - 1; } static inline int Nf_CutCompareArea( Nf_Cut_t * pCut0, Nf_Cut_t * pCut1 ) { if ( pCut0->Useless < pCut1->Useless ) return -1; if ( pCut0->Useless > pCut1->Useless ) return 1; if ( pCut0->Flow < pCut1->Flow - NF_EPSILON ) return -1; if ( pCut0->Flow > pCut1->Flow + NF_EPSILON ) return 1; if ( pCut0->Delay < pCut1->Delay ) return -1; if ( pCut0->Delay > pCut1->Delay ) return 1; if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; return 0; } static inline void Nf_SetSortByArea( Nf_Cut_t ** pCuts, int nCuts ) { int i; for ( i = nCuts; i > 0; i-- ) { if ( Nf_CutCompareArea(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 ) return; ABC_SWAP( Nf_Cut_t *, pCuts[i - 1], pCuts[i] ); } } static inline int Nf_SetAddCut( Nf_Cut_t ** pCuts, int nCuts, int nCutNum ) { if ( nCuts == 0 ) return 1; nCuts = Nf_SetLastCutContainsArea(pCuts, nCuts); Nf_SetSortByArea( pCuts, nCuts ); return Abc_MinInt( nCuts + 1, nCutNum - 1 ); } static inline int Nf_CutArea( Nf_Man_t * p, int nLeaves ) { if ( nLeaves < 2 ) return 0; return nLeaves + p->pPars->nAreaTuner; } static inline void Nf_CutParams( Nf_Man_t * p, Nf_Cut_t * pCut, float FlowRefs ) { int i, nLeaves = pCut->nLeaves; assert( nLeaves <= p->pPars->nLutSize ); pCut->Delay = 0; pCut->Flow = 0; for ( i = 0; i < nLeaves; i++ ) { pCut->Delay = Abc_MaxInt( pCut->Delay, Nf_ObjCutDelay(p, pCut->pLeaves[i]) ); pCut->Flow += Nf_ObjCutFlow(p, pCut->pLeaves[i]); } pCut->Delay += (int)(nLeaves > 1); pCut->Flow = (pCut->Flow + Nf_CutArea(p, nLeaves)) / FlowRefs; } void Nf_ObjMergeOrder( Nf_Man_t * p, int iObj ) { Nf_Cut_t pCuts0[NF_CUT_MAX], pCuts1[NF_CUT_MAX], pCuts[NF_CUT_MAX], * pCutsR[NF_CUT_MAX]; Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); //Nf_Obj_t * pBest = Nf_ManObj(p, iObj); float dFlowRefs = Nf_ObjFlowRefs(p, iObj, 0) + Nf_ObjFlowRefs(p, iObj, 1); int nLutSize = p->pPars->nLutSize; int nCutNum = p->pPars->nCutNum; int nCuts0 = Nf_ManPrepareCuts(pCuts0, p, Gia_ObjFaninId0(pObj, iObj), 1); int nCuts1 = Nf_ManPrepareCuts(pCuts1, p, Gia_ObjFaninId1(pObj, iObj), 1); int fComp0 = Gia_ObjFaninC0(pObj); int fComp1 = Gia_ObjFaninC1(pObj); int iSibl = Gia_ObjSibl(p->pGia, iObj); Nf_Cut_t * pCut0, * pCut1, * pCut0Lim = pCuts0 + nCuts0, * pCut1Lim = pCuts1 + nCuts1; int i, nCutsUse, nCutsR = 0; assert( !Gia_ObjIsBuf(pObj) ); for ( i = 0; i < nCutNum; i++ ) pCutsR[i] = pCuts + i; if ( iSibl ) { Nf_Cut_t pCuts2[NF_CUT_MAX]; Gia_Obj_t * pObjE = Gia_ObjSiblObj(p->pGia, iObj); int fCompE = Gia_ObjPhase(pObj) ^ Gia_ObjPhase(pObjE); int nCuts2 = Nf_ManPrepareCuts(pCuts2, p, iSibl, 0); Nf_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) { *pCutsR[nCutsR] = *pCut2; pCutsR[nCutsR]->iFunc = Abc_LitNotCond( pCutsR[nCutsR]->iFunc, fCompE ); Nf_CutParams( p, pCutsR[nCutsR], dFlowRefs ); nCutsR = Nf_SetAddCut( pCutsR, nCutsR, nCutNum ); } } if ( Gia_ObjIsMuxId(p->pGia, iObj) ) { Nf_Cut_t pCuts2[NF_CUT_MAX]; int nCuts2 = Nf_ManPrepareCuts(pCuts2, p, Gia_ObjFaninId2(p->pGia, iObj), 1); int fComp2 = Gia_ObjFaninC2(p->pGia, pObj); Nf_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; p->CutCount[0] += nCuts0 * nCuts1 * nCuts2; for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) { if ( Nf_CutCountBits(pCut0->Sign | pCut1->Sign | pCut2->Sign) > nLutSize ) continue; p->CutCount[1]++; if ( !Nf_CutMergeOrderMux(pCut0, pCut1, pCut2, pCutsR[nCutsR], nLutSize) ) continue; if ( Nf_SetLastCutIsContained(pCutsR, nCutsR) ) continue; p->CutCount[2]++; if ( Nf_CutComputeTruthMux6(p, pCut0, pCut1, pCut2, fComp0, fComp1, fComp2, pCutsR[nCutsR]) ) pCutsR[nCutsR]->Sign = Nf_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); Nf_CutParams( p, pCutsR[nCutsR], dFlowRefs ); nCutsR = Nf_SetAddCut( pCutsR, nCutsR, nCutNum ); } } else { int fIsXor = Gia_ObjIsXor(pObj); p->CutCount[0] += nCuts0 * nCuts1; for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) { if ( (int)(pCut0->nLeaves + pCut1->nLeaves) > nLutSize && Nf_CutCountBits(pCut0->Sign | pCut1->Sign) > nLutSize ) continue; p->CutCount[1]++; if ( !Nf_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], nLutSize) ) continue; if ( Nf_SetLastCutIsContained(pCutsR, nCutsR) ) continue; p->CutCount[2]++; if ( Nf_CutComputeTruth6(p, pCut0, pCut1, fComp0, fComp1, pCutsR[nCutsR], fIsXor) ) pCutsR[nCutsR]->Sign = Nf_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); Nf_CutParams( p, pCutsR[nCutsR], dFlowRefs ); nCutsR = Nf_SetAddCut( pCutsR, nCutsR, nCutNum ); } } // debug printout if ( 0 ) // if ( iObj % 10000 == 0 ) // if ( iObj == 1090 ) { printf( "*** Obj = %d Useful = %d\n", iObj, Nf_ManCountUseful(pCutsR, nCutsR) ); for ( i = 0; i < nCutsR; i++ ) Nf_CutPrint( p, pCutsR[i] ); printf( "\n" ); } // verify assert( nCutsR > 0 && nCutsR < nCutNum ); // assert( Nf_SetCheckArray(pCutsR, nCutsR) ); // store the cutset Nf_ObjSetCutFlow( p, iObj, pCutsR[0]->Flow ); Nf_ObjSetCutDelay( p, iObj, pCutsR[0]->Delay ); *Vec_IntEntryP(&p->vCutSets, iObj) = Nf_ManSaveCuts(p, pCutsR, nCutsR, 0); p->CutCount[3] += nCutsR; nCutsUse = Nf_ManCountUseful(pCutsR, nCutsR); p->CutCount[4] += nCutsUse; p->nCutUseAll += nCutsUse == nCutsR; p->CutCount[5] += Nf_ManCountMatches(p, pCutsR, nCutsR); } void Nf_ManComputeCuts( Nf_Man_t * p ) { Gia_Obj_t * pObj; int i, iFanin, arrTime; float CutFlow = 0, CutFlowAve = 0; int fFirstCi = 0, nCutFlow = 0; if ( p->pManTim ) Tim_ManIncrementTravId( p->pManTim ); Gia_ManForEachObjWithBoxes( p->pGia, pObj, i ) if ( Gia_ObjIsBuf(pObj) ) { iFanin = Gia_ObjFaninId0(pObj, i); Nf_ObjSetCutFlow( p, i, Nf_ObjCutFlow(p, iFanin) ); Nf_ObjSetCutDelay( p, i, Nf_ObjCutDelay(p, iFanin) ); } else if ( Gia_ObjIsAnd(pObj) ) Nf_ObjMergeOrder( p, i ); else if ( Gia_ObjIsCi(pObj) ) { if ( fFirstCi ) { CutFlowAve = CutFlow / nCutFlow; CutFlow = 0; nCutFlow = 0; fFirstCi = 0; } arrTime = Tim_ManGetCiArrival( p->pManTim, Gia_ObjCioId(pObj) ); Nf_ObjSetCutFlow( p, i, CutFlowAve ); // approximation! Nf_ObjSetCutDelay( p, i, arrTime ); } else if ( Gia_ObjIsCo(pObj) ) { iFanin = Gia_ObjFaninId0(pObj, i); CutFlow += Nf_ObjCutFlow(p, iFanin); arrTime = Nf_ObjCutDelay(p, iFanin); Tim_ManSetCoArrival( p->pManTim, Gia_ObjCioId(pObj), arrTime ); nCutFlow++; fFirstCi = 1; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nf_ManPrintStats( Nf_Man_t * p, char * pTitle ) { if ( !p->pPars->fVerbose ) return; printf( "%s : ", pTitle ); printf( "Delay =%8.2f ", Scl_Int2Flt(p->pPars->MapDelay) ); printf( "Area =%12.2f ", p->pPars->MapAreaF ); printf( "Gate =%6d ", (int)p->pPars->Area ); printf( "Inv =%6d ", (int)p->nInvs ); printf( "Edge =%7d ", (int)p->pPars->Edge ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); fflush( stdout ); } void Nf_ManPrintInit( Nf_Man_t * p ) { int nChoices; if ( !p->pPars->fVerbose ) return; printf( "LutSize = %d ", p->pPars->nLutSize ); printf( "CutNum = %d ", p->pPars->nCutNum ); printf( "Iter = %d ", p->pPars->nRounds );//+ p->pPars->nRoundsEla ); printf( "Coarse = %d ", p->pPars->fCoarsen ); printf( "Cells = %d ", p->nCells ); printf( "Funcs = %d ", Vec_MemEntryNum(p->vTtMem) ); printf( "Matches = %d ", Vec_WecSizeSize(p->vTt2Match)/2 ); printf( "And = %d ", Gia_ManAndNum(p->pGia) ); nChoices = Gia_ManChoiceNum( p->pGia ); if ( nChoices ) printf( "Choices = %d ", nChoices ); printf( "\n" ); printf( "Computing cuts...\r" ); fflush( stdout ); } void Nf_ManPrintQuit( Nf_Man_t * p ) { float MemGia = Gia_ManMemory(p->pGia) / (1<<20); float MemMan =(1.0 * sizeof(Nf_Obj_t) + 8.0 * sizeof(int)) * Gia_ManObjNum(p->pGia) / (1<<20); float MemCuts = 1.0 * sizeof(int) * (1 << 16) * Vec_PtrSize(&p->vPages) / (1<<20); float MemTt = p->vTtMem ? Vec_MemMemory(p->vTtMem) / (1<<20) : 0; if ( p->CutCount[0] == 0 ) p->CutCount[0] = 1; if ( !p->pPars->fVerbose ) return; printf( "CutPair = %.0f ", p->CutCount[0] ); printf( "Merge = %.0f (%.1f) ", p->CutCount[1], 1.0*p->CutCount[1]/Gia_ManAndNum(p->pGia) ); printf( "Eval = %.0f (%.1f) ", p->CutCount[2], 1.0*p->CutCount[2]/Gia_ManAndNum(p->pGia) ); printf( "Cut = %.0f (%.1f) ", p->CutCount[3], 1.0*p->CutCount[3]/Gia_ManAndNum(p->pGia) ); printf( "Use = %.0f (%.1f) ", p->CutCount[4], 1.0*p->CutCount[4]/Gia_ManAndNum(p->pGia) ); printf( "Mat = %.0f (%.1f) ", p->CutCount[5], 1.0*p->CutCount[5]/Gia_ManAndNum(p->pGia) ); // printf( "Equ = %d (%.2f %%) ", p->nCutUseAll, 100.0*p->nCutUseAll /p->CutCount[0] ); printf( "\n" ); printf( "Gia = %.2f MB ", MemGia ); printf( "Man = %.2f MB ", MemMan ); printf( "Cut = %.2f MB ", MemCuts ); printf( "TT = %.2f MB ", MemTt ); printf( "Total = %.2f MB ", MemGia + MemMan + MemCuts + MemTt ); // printf( "\n" ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); fflush( stdout ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nf_ManCutMatchPrint( Nf_Man_t * p, int iObj, char * pStr, Nf_Mat_t * pM ) { Mio_Cell2_t * pCell; int i, * pCut; printf( "%5d %s : ", iObj, pStr ); if ( pM->CutH == 0 ) { printf( "Unassigned\n" ); return; } pCell = Nf_ManCell( p, pM->Gate ); pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, iObj), pM->CutH ); printf( "D =%6.2f ", Scl_Int2Flt(pM->D) ); printf( "A =%6.2f ", pM->F ); printf( "C = %d ", pM->fCompl ); // printf( "B = %d ", pM->fBest ); printf( " " ); printf( "Cut = {" ); for ( i = 0; i < (int)pCell->nFanins; i++ ) printf( "%4d ", Nf_CutLeaves(pCut)[i] ); for ( ; i < 6; i++ ) printf( " " ); printf( "} " ); printf( "%10s ", pCell->pName ); printf( "%d ", pCell->nFanins ); printf( "{" ); for ( i = 0; i < (int)pCell->nFanins; i++ ) printf( "%6.2f ", Scl_Int2Flt(pCell->iDelays[i]) ); for ( ; i < 6; i++ ) printf( " " ); printf( " } " ); for ( i = 0; i < (int)pCell->nFanins; i++ ) printf( "%s%d ", Nf_CfgCompl(pM->Cfg, i) ? "!":" ", Nf_CfgVar(pM->Cfg, i) ); for ( ; i < 6; i++ ) printf( " " ); Dau_DsdPrintFromTruth( &pCell->uTruth, pCell->nFanins ); } void Nf_ManCutMatchOne( Nf_Man_t * p, int iObj, int * pCut, int * pCutSet ) { Nf_Obj_t * pBest = Nf_ManObj(p, iObj); int * pFans = Nf_CutLeaves(pCut); int nFans = Nf_CutSize(pCut); int iFuncLit = Nf_CutFunc(pCut); int fComplExt = Abc_LitIsCompl(iFuncLit); Vec_Int_t * vArr = Vec_WecEntry( p->vTt2Match, Abc_Lit2Var(iFuncLit) ); int i, k, c, Info, Offset, iFanin, fComplF; int ArrivalD, ArrivalA; Nf_Mat_t * pD, * pA; // assign fanins matches Nf_Obj_t * pBestF[NF_LEAF_MAX]; for ( i = 0; i < nFans; i++ ) pBestF[i] = Nf_ManObj( p, pFans[i] ); // special cases if ( nFans == 0 ) { int Const = (iFuncLit == 1); assert( iFuncLit == 0 || iFuncLit == 1 ); for ( c = 0; c < 2; c++ ) { pD = Nf_ObjMatchD( p, iObj, c ); pA = Nf_ObjMatchA( p, iObj, c ); pD->D = pA->D = 0; pD->F = pA->F = p->pCells[c ^ Const].AreaF; pD->CutH = pA->CutH = Nf_CutHandle(pCutSet, pCut); pD->Gate = pA->Gate = c ^ Const; // pD->Conf = pA->Conf = 0; pD->Cfg = pA->Cfg = Nf_Int2Cfg(0); } return; } // consider matches of this function Vec_IntForEachEntryDouble( vArr, Info, Offset, i ) { Nf_Cfg_t Cfg = Nf_Int2Cfg(Offset); Mio_Cell2_t*pC = Nf_ManCell( p, Info ); int fCompl = Cfg.fCompl ^ fComplExt; int Required = Nf_ObjRequired( p, iObj, fCompl ), Delay = 0; Nf_Mat_t * pD = &pBest->M[fCompl][0]; Nf_Mat_t * pA = &pBest->M[fCompl][1]; float AreaF = pC->AreaF; assert( nFans == (int)pC->nFanins ); Nf_CfgForEachVarCompl( Cfg, nFans, iFanin, fComplF, k ) { ArrivalD = pBestF[iFanin]->M[fComplF][0].D; ArrivalA = pBestF[iFanin]->M[fComplF][1].D; if ( ArrivalA + pC->iDelays[k] <= Required && Required != SCL_INFINITY ) { Delay = Abc_MaxInt( Delay, ArrivalA + pC->iDelays[k] ); if ( AreaF >= (float)1e32 || pBestF[iFanin]->M[fComplF][1].F >= (float)1e32 ) AreaF = (float)1e32; else AreaF += pBestF[iFanin]->M[fComplF][1].F; } else { if ( pD->D < SCL_INFINITY && pA->D < SCL_INFINITY && ArrivalD + pC->iDelays[k] > Required ) break; Delay = Abc_MaxInt( Delay, ArrivalD + pC->iDelays[k] ); //AreaF += pBestF[iFanin]->M[fComplF][0].F; if ( AreaF >= (float)1e32 || pBestF[iFanin]->M[fComplF][0].F >= (float)1e32 ) AreaF = (float)1e32; else AreaF += pBestF[iFanin]->M[fComplF][0].F; } } if ( k < nFans ) continue; // select best Cfgch if ( pD->D > Delay ) { pD->D = Delay; pD->F = AreaF; pD->CutH = Nf_CutHandle(pCutSet, pCut); pD->Gate = pC->Id; pD->Cfg = Cfg; pD->Cfg.fCompl = 0; } if ( pA->F > AreaF + NF_EPSILON ) { pA->D = Delay; pA->F = AreaF; pA->CutH = Nf_CutHandle(pCutSet, pCut); pA->Gate = pC->Id; pA->Cfg = Cfg; pA->Cfg.fCompl = 0; } } } static inline void Nf_ObjPrepareCi( Nf_Man_t * p, int iObj, int Time ) { Nf_Mat_t * pD0 = Nf_ObjMatchD( p, iObj, 0 ); Nf_Mat_t * pA0 = Nf_ObjMatchA( p, iObj, 0 ); Nf_Mat_t * pD = Nf_ObjMatchD( p, iObj, 1 ); Nf_Mat_t * pA = Nf_ObjMatchA( p, iObj, 1 ); pD0->D = pA0->D = pD->D = pA->D = Time; pD->fCompl = 1; pD->D += p->InvDelayI; pD->F = p->InvAreaF; pA->fCompl = 1; pA->D += p->InvDelayI; pA->F = p->InvAreaF; Nf_ObjMatchD( p, iObj, 0 )->fBest = 1; Nf_ObjMatchD( p, iObj, 1 )->fBest = 1; } static inline void Nf_ObjPrepareBuf( Nf_Man_t * p, Gia_Obj_t * pObj ) { // get fanin info int iObj = Gia_ObjId( p->pGia, pObj ); int iFanin = Gia_ObjFaninId0( pObj, iObj ); Nf_Mat_t * pDf = Nf_ObjMatchD( p, iFanin, Gia_ObjFaninC0(pObj) ); //Nf_Mat_t * pAf = Nf_ObjMatchA( p, iFanin, Gia_ObjFaninC0(pObj) ); // set the direct phase Nf_Mat_t * pDp = Nf_ObjMatchD( p, iObj, 0 ); Nf_Mat_t * pAp = Nf_ObjMatchA( p, iObj, 0 ); Nf_Mat_t * pDn = Nf_ObjMatchD( p, iObj, 1 ); Nf_Mat_t * pAn = Nf_ObjMatchA( p, iObj, 1 ); assert( Gia_ObjIsBuf(pObj) ); memset( Nf_ManObj(p, iObj), 0, sizeof(Nf_Obj_t) ); // set the direct phase pDp->D = pAp->D = pDf->D; pDp->F = pAp->F = pDf->F; // do not pass flow??? pDp->fBest = 1; // set the inverted phase pDn->D = pAn->D = pDf->D + p->InvDelayI; pDn->F = pAn->F = pDf->F + p->InvAreaF; pDn->fCompl = pAn->fCompl = 1; pDn->fBest = 1; } static inline int Nf_CutRequired( Nf_Man_t * p, Nf_Mat_t * pM, int * pCutSet ) { Mio_Cell2_t * pCell = Nf_ManCell( p, pM->Gate ); int * pCut = Nf_CutFromHandle( pCutSet, pM->CutH ); int i, iVar, fCompl; int Arr, Req, Arrival = 0, Required = 0; Nf_CutForEachVarCompl( pCut, pM->Cfg, iVar, fCompl, i ) { Arr = Nf_ManObj(p, iVar)->M[fCompl][0].D + pCell->iDelays[i]; Req = Nf_ObjRequired(p, iVar, fCompl); Arrival = Abc_MaxInt( Arrival, Arr ); if ( Req < SCL_INFINITY ) Required = Abc_MaxInt( Required, Req + pCell->iDelays[i] ); } return Abc_MaxInt( Required + p->pPars->nReqTimeFlex*p->InvDelayI, Arrival ); } static inline void Nf_ObjComputeRequired( Nf_Man_t * p, int iObj ) { Nf_Obj_t * pBest = Nf_ManObj(p, iObj); int c, * pCutSet = Nf_ObjCutSet( p, iObj ); for ( c = 0; c < 2; c++ ) if ( Nf_ObjRequired(p, iObj, c) == SCL_INFINITY ) Nf_ObjSetRequired( p, iObj, c, Nf_CutRequired(p, &pBest->M[c][0], pCutSet) ); } void Nf_ManCutMatch( Nf_Man_t * p, int iObj ) { Nf_Obj_t * pBest = Nf_ManObj(p, iObj); Nf_Mat_t * pDp = &pBest->M[0][0]; Nf_Mat_t * pDn = &pBest->M[1][0]; Nf_Mat_t * pAp = &pBest->M[0][1]; Nf_Mat_t * pAn = &pBest->M[1][1]; float FlowRefPf = Nf_ObjFlowRefs(p, iObj, 0); float FlowRefNf = Nf_ObjFlowRefs(p, iObj, 1); int i, * pCut, * pCutSet = Nf_ObjCutSet( p, iObj ); int Required[2] = {0}; if ( p->Iter ) { Nf_ObjComputeRequired( p, iObj ); Required[0] = Nf_ObjRequired( p, iObj, 0 ); Required[1] = Nf_ObjRequired( p, iObj, 1 ); } memset( pBest, 0, sizeof(Nf_Obj_t) ); pDp->D = SCL_INFINITY; pDp->F = FLT_MAX; pDn->D = SCL_INFINITY; pDn->F = FLT_MAX; pAp->D = SCL_INFINITY; pAp->F = FLT_MAX; pAn->D = SCL_INFINITY; pAn->F = FLT_MAX; Nf_SetForEachCut( pCutSet, pCut, i ) { if ( Abc_Lit2Var(Nf_CutFunc(pCut)) >= Vec_WecSize(p->vTt2Match) ) continue; assert( !Nf_CutIsTriv(pCut, iObj) ); assert( Nf_CutSize(pCut) <= p->pPars->nLutSize ); assert( Abc_Lit2Var(Nf_CutFunc(pCut)) < Vec_WecSize(p->vTt2Match) ); Nf_ManCutMatchOne( p, iObj, pCut, pCutSet ); } /* if ( 461 == iObj && p->Iter == 0 ) { printf( "\nObj %6d (%.2f %.2f):\n", iObj, Scl_Int2Flt(Required[0]), Scl_Int2Flt(Required[1]) ); Nf_ManCutMatchPrint( p, iObj, "Dp", &pBest->M[0][0] ); Nf_ManCutMatchPrint( p, iObj, "Dn", &pBest->M[1][0] ); Nf_ManCutMatchPrint( p, iObj, "Ap", &pBest->M[0][1] ); Nf_ManCutMatchPrint( p, iObj, "An", &pBest->M[1][1] ); printf( "\n" ); } */ // divide by ref count pDp->F = pDp->F / FlowRefPf; pAp->F = pAp->F / FlowRefPf; pDn->F = pDn->F / FlowRefNf; pAn->F = pAn->F / FlowRefNf; // add the inverters assert( pDp->D < SCL_INFINITY || pDn->D < SCL_INFINITY ); if ( pDp->D > pDn->D + p->InvDelayI ) { *pDp = *pDn; pDp->D += p->InvDelayI; pDp->F += p->InvAreaF; pDp->fCompl = 1; if ( pAp->D == SCL_INFINITY ) *pAp = *pDp; //printf( "Using inverter to improve delay at node %d in phase %d.\n", iObj, 1 ); } else if ( pDn->D > pDp->D + p->InvDelayI ) { *pDn = *pDp; pDn->D += p->InvDelayI; pDn->F += p->InvAreaF; pDn->fCompl = 1; if ( pAn->D == SCL_INFINITY ) *pAn = *pDn; //printf( "Using inverter to improve delay at node %d in phase %d.\n", iObj, 0 ); } //assert( pAp->F < FLT_MAX || pAn->F < FLT_MAX ); // try replacing pos with neg if ( pAp->D == SCL_INFINITY || (pAp->F > pAn->F + p->InvAreaF + NF_EPSILON && pAn->D + p->InvDelayI <= Required[0]) ) { assert( p->Iter > 0 ); *pAp = *pAn; pAp->D += p->InvDelayI; pAp->F += p->InvAreaF; pAp->fCompl = 1; if ( pDp->D == SCL_INFINITY ) *pDp = *pAp; //printf( "Using inverter to improve area at node %d in phase %d.\n", iObj, 1 ); } // try replacing neg with pos else if ( pAn->D == SCL_INFINITY || (pAn->F > pAp->F + p->InvAreaF + NF_EPSILON && pAp->D + p->InvDelayI <= Required[1]) ) { assert( p->Iter > 0 ); *pAn = *pAp; pAn->D += p->InvDelayI; pAn->F += p->InvAreaF; pAn->fCompl = 1; if ( pDn->D == SCL_INFINITY ) *pDn = *pAn; //printf( "Using inverter to improve area at node %d in phase %d.\n", iObj, 0 ); } if ( pDp->D == SCL_INFINITY ) printf( "Object %d has pDp unassigned.\n", iObj ); if ( pDn->D == SCL_INFINITY ) printf( "Object %d has pDn unassigned.\n", iObj ); if ( pAp->D == SCL_INFINITY ) printf( "Object %d has pAp unassigned.\n", iObj ); if ( pAn->D == SCL_INFINITY ) printf( "Object %d has pAn unassigned.\n", iObj ); /* pDp->F = Abc_MinFloat( pDp->F, FLT_MAX/SCL_NUM ); pDn->F = Abc_MinFloat( pDn->F, FLT_MAX/SCL_NUM ); pAp->F = Abc_MinFloat( pAp->F, FLT_MAX/SCL_NUM ); pAn->F = Abc_MinFloat( pAn->F, FLT_MAX/SCL_NUM ); */ assert( pDp->D < SCL_INFINITY ); assert( pDn->D < SCL_INFINITY ); assert( pAp->D < SCL_INFINITY ); assert( pAn->D < SCL_INFINITY ); assert( pDp->F < FLT_MAX ); assert( pDn->F < FLT_MAX ); assert( pAp->F < FLT_MAX ); assert( pAn->F < FLT_MAX ); /* if ( p->Iter && (pDp->D > Required[0] || pDn->D > Required[1]) ) { printf( "%5d : ", iObj ); printf( "Dp = %6.2f ", Scl_Int2Flt(pDp->D) ); printf( "Dn = %6.2f ", Scl_Int2Flt(pDn->D) ); printf( " " ); printf( "Ap = %6.2f ", Scl_Int2Flt(pAp->D) ); printf( "An = %6.2f ", Scl_Int2Flt(pAn->D) ); printf( " " ); printf( "Rp = %6.2f ", Scl_Int2Flt(Required[0]) ); printf( "Rn = %6.2f ", Scl_Int2Flt(Required[1]) ); printf( "\n" ); } */ } static inline Nf_Mat_t * Nf_ObjMatchBest( Nf_Man_t * p, int i, int c ) { Nf_Mat_t * pD = Nf_ObjMatchD(p, i, c); Nf_Mat_t * pA = Nf_ObjMatchA(p, i, c); assert( pD->fBest != pA->fBest ); //assert( Nf_ObjMapRefNum(p, i, c) > 0 ); if ( pA->fBest ) return pA; if ( pD->fBest ) return pD; return NULL; } void Nf_ManComputeMapping( Nf_Man_t * p ) { Gia_Obj_t * pObj; int i, arrTime; if ( p->pManTim ) Tim_ManIncrementTravId( p->pManTim ); Gia_ManForEachObjWithBoxes( p->pGia, pObj, i ) if ( Gia_ObjIsBuf(pObj) ) Nf_ObjPrepareBuf( p, pObj ); else if ( Gia_ObjIsAnd(pObj) ) Nf_ManCutMatch( p, i ); else if ( Gia_ObjIsCi(pObj) ) { arrTime = Tim_ManGetCiArrival( p->pManTim, Gia_ObjCioId(pObj) ); Nf_ObjPrepareCi( p, i, arrTime ); } else if ( Gia_ObjIsCo(pObj) ) { arrTime = Nf_ObjMatchD( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj) )->D; Tim_ManSetCoArrival( p->pManTim, Gia_ObjCioId(pObj), arrTime ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nf_ManSetOutputRequireds( Nf_Man_t * p, int fPropCompl ) { Gia_Obj_t * pObj; int Required = 0, MapDelayOld = p->pPars->MapDelay; int fUseConMan = Scl_ConIsRunning() && Scl_ConHasOutReqs(); int i, iObj, fCompl, nLits = 2*Gia_ManObjNum(p->pGia); Vec_IntFill( &p->vRequired, nLits, SCL_INFINITY ); // compute delay p->pPars->MapDelay = 0; Gia_ManForEachCoWithBoxes( p->pGia, pObj, i ) { Required = Nf_ObjMatchD( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj) )->D; p->pPars->MapDelay = Abc_MaxInt( p->pPars->MapDelay, Required ); } if ( p->Iter && MapDelayOld < p->pPars->MapDelay && p->pGia->vOutReqs == NULL ) printf( "******** Critical delay violation %.2f -> %.2f ********\n", Scl_Int2Flt(MapDelayOld), Scl_Int2Flt(p->pPars->MapDelay) ); p->pPars->MapDelay = Abc_MaxInt( p->pPars->MapDelay, MapDelayOld ); // check delay target if ( p->pPars->MapDelayTarget == 0 && p->pPars->nRelaxRatio ) p->pPars->MapDelayTarget = p->pPars->MapDelay * (100 + p->pPars->nRelaxRatio) / 100; if ( p->pPars->MapDelayTarget > 0 ) { if ( p->pPars->MapDelay < p->pPars->MapDelayTarget ) p->pPars->MapDelay = p->pPars->MapDelayTarget; else if ( p->pPars->nRelaxRatio == 0 ) Abc_Print( 0, "Relaxing user-specified delay target from %.2f to %.2f.\n", Scl_Int2Flt(p->pPars->MapDelayTarget), Scl_Int2Flt(p->pPars->MapDelay) ); } //assert( p->pPars->MapDelayTarget == 0 ); // set required times if ( p->pManTim ) Tim_ManIncrementTravId( p->pManTim ); Gia_ManForEachCoWithBoxes( p->pGia, pObj, i ) { iObj = Gia_ObjFaninId0p(p->pGia, pObj); fCompl = Gia_ObjFaninC0(pObj); Required = Nf_ObjMatchD(p, iObj, fCompl)->D; Required = p->pPars->fDoAverage ? Required * (100 + p->pPars->nRelaxRatio) / 100 : p->pPars->MapDelay; // if external required time can be achieved, use it if ( fUseConMan ) { if ( Scl_ConGetOutReq(i) > 0 && Required <= Scl_ConGetOutReq(i) ) Required = Scl_ConGetOutReq(i); } else if ( p->pGia->vOutReqs ) { int NewRequired = Scl_Flt2Int(Vec_FltEntry(p->pGia->vOutReqs, i)); if ( NewRequired > 0 && Required <= NewRequired ) Required = Abc_MinInt( 2*Required, NewRequired ); } // if external required cannot be achieved, set the earliest possible arrival time // else if ( p->pGia->vOutReqs && Vec_FltEntry(p->pGia->vOutReqs, i) > 0 && Required > Vec_FltEntry(p->pGia->vOutReqs, i) ) // ptTime->Rise = ptTime->Fall = ptTime->Worst = Required; // otherwise, set the global required time Nf_ObjUpdateRequired( p, iObj, fCompl, Required ); if ( fPropCompl && iObj > 0 && Nf_ObjMatchBest(p, iObj, fCompl)->fCompl ) Nf_ObjUpdateRequired( p, iObj, !fCompl, Required - p->InvDelayI ); if ( p->pManTim == NULL ) continue; if ( fPropCompl && iObj > 0 && Nf_ObjMatchBest(p, iObj, fCompl)->fCompl ) Tim_ManSetCoRequired( p->pManTim, Gia_ObjCioId(pObj), Required - p->InvDelayI ); else Tim_ManSetCoRequired( p->pManTim, Gia_ObjCioId(pObj), Required ); //Nf_ObjMapRefInc( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj)); } } void Nf_ManSetMapRefsGate( Nf_Man_t * p, int iObj, int Required, Nf_Mat_t * pM ) { int k, iVar, fCompl; Mio_Cell2_t * pCell = Nf_ManCell( p, pM->Gate ); int * pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, iObj), pM->CutH ); Nf_CutForEachVarCompl( pCut, pM->Cfg, iVar, fCompl, k ) { Nf_ObjMapRefInc( p, iVar, fCompl ); Nf_ObjUpdateRequired( p, iVar, fCompl, Required - pCell->iDelays[k] ); } assert( Nf_CutSize(pCut) == (int)pCell->nFanins ); // update global stats p->pPars->MapAreaF += pCell->AreaF; p->pPars->Edge += Nf_CutSize(pCut); p->pPars->Area++; // update status of the gate assert( pM->fBest == 0 ); pM->fBest = 1; } void Nf_ManPrintMatches( Nf_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachAnd( p->pGia, pObj, i ) { Nf_Mat_t * pDp = Nf_ObjMatchD( p, i, 0 ); Nf_Mat_t * pAp = Nf_ObjMatchA( p, i, 0 ); Nf_Mat_t * pDn = Nf_ObjMatchD( p, i, 1 ); Nf_Mat_t * pAn = Nf_ObjMatchA( p, i, 1 ); printf( "%5d : ", i ); printf( "Dp = %6.2f ", Scl_Int2Flt(pDp->D) ); printf( "Dn = %6.2f ", Scl_Int2Flt(pDn->D) ); printf( " " ); printf( "Ap = %6.2f ", Scl_Int2Flt(pAp->D) ); printf( "An = %6.2f ", Scl_Int2Flt(pAn->D) ); printf( " " ); printf( "Dp = %8s ", Nf_ManCell(p, pDp->Gate)->pName ); printf( "Dn = %8s ", Nf_ManCell(p, pDn->Gate)->pName ); printf( "Ap = %8s ", Nf_ManCell(p, pAp->Gate)->pName ); printf( "An = %8s ", Nf_ManCell(p, pAn->Gate)->pName ); printf( "\n" ); } } int Nf_ManSetMapRefs( Nf_Man_t * p ) { float Coef = 1.0 / (1.0 + (p->Iter + 1) * (p->Iter + 1)); float * pFlowRefs = Vec_FltArray( &p->vFlowRefs ); int * pMapRefs = Vec_IntArray( &p->vMapRefs ); int nLits = 2*Gia_ManObjNum(p->pGia); int i, c, Id, nRefs[2], reqTime; Gia_Obj_t * pObj; Nf_Mat_t * pD, * pA, * pM; Nf_Mat_t * pDs[2], * pAs[2], * pMs[2]; int Required = 0, Requireds[2]; assert( !p->fUseEla ); // if ( p->Iter == 0 ) // Nf_ManPrintMatches( p ); Nf_ManSetOutputRequireds( p, 0 ); // set output references memset( pMapRefs, 0, sizeof(int) * nLits ); Gia_ManForEachCo( p->pGia, pObj, i ) Nf_ObjMapRefInc( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj)); // compute area and edges p->nInvs = 0; p->pPars->MapAreaF = 0; p->pPars->Area = p->pPars->Edge = 0; Gia_ManForEachObjReverseWithBoxes( p->pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) ) { if ( Nf_ObjMapRefNum(p, i, 1) ) { Nf_ObjMapRefInc( p, i, 0 ); Nf_ObjUpdateRequired( p, i, 0, Nf_ObjRequired(p, i, 1) - p->InvDelayI ); p->pPars->MapAreaF += p->InvAreaF; p->pPars->Edge++; p->pPars->Area++; p->nInvs++; } Nf_ObjUpdateRequired( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj), Nf_ObjRequired(p, i, 0) ); Nf_ObjMapRefInc( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj)); continue; } if ( Gia_ObjIsCi(pObj) ) { if ( Nf_ObjMapRefNum(p, i, 1) ) { Nf_ObjMapRefInc( p, i, 0 ); Nf_ObjUpdateRequired( p, i, 0, Nf_ObjRequired(p, i, 1) - p->InvDelayI ); p->pPars->MapAreaF += p->InvAreaF; p->pPars->Edge++; p->pPars->Area++; p->nInvs++; } Tim_ManSetCiRequired( p->pManTim, Gia_ObjCioId(pObj), Nf_ObjRequired(p, i, 0) ); continue; } if ( Gia_ObjIsCo(pObj) ) { reqTime = Tim_ManGetCoRequired( p->pManTim, Gia_ObjCioId(pObj) ); Nf_ObjUpdateRequired( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj), reqTime ); Nf_ObjMapRefInc( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj)); continue; } // skip if this node is not used for ( c = 0; c < 2; c++ ) nRefs[c] = Nf_ObjMapRefNum(p, i, c); if ( !nRefs[0] && !nRefs[1] ) continue; // consider two cases if ( nRefs[0] && nRefs[1] ) { // find best matches for both phases for ( c = 0; c < 2; c++ ) { Requireds[c] = Nf_ObjRequired( p, i, c ); //assert( Requireds[c] < SCL_INFINITY ); pDs[c] = Nf_ObjMatchD( p, i, c ); pAs[c] = Nf_ObjMatchA( p, i, c ); pMs[c] = (pAs[c]->D <= Requireds[c]) ? pAs[c] : pDs[c]; } // swap complemented matches if ( pMs[0]->fCompl && pMs[1]->fCompl ) { // pMs[0]->fCompl = pMs[1]->fCompl = 0; // ABC_SWAP( Nf_Mat_t *, pMs[0], pMs[1] ); // find best matches for both phases pMs[0] = Nf_ObjMatchD( p, i, 0 ); pMs[1] = Nf_ObjMatchD( p, i, 1 ); assert( !pMs[0]->fCompl || !pMs[1]->fCompl ); } // check if intervers are involved if ( !pMs[0]->fCompl && !pMs[1]->fCompl ) // no inverters { for ( c = 0; c < 2; c++ ) Nf_ManSetMapRefsGate( p, i, Requireds[c], pMs[c] ); } else { // one interver assert( !pMs[0]->fCompl || !pMs[1]->fCompl ); c = pMs[1]->fCompl; assert( pMs[c]->fCompl && !pMs[!c]->fCompl ); //printf( "Using inverter at node %d in phase %d\n", i, c ); // update this phase pM = pMs[c]; pM->fBest = 1; Required = Requireds[c]; // update opposite phase Nf_ObjMapRefInc( p, i, !c ); Nf_ObjUpdateRequired( p, i, !c, Required - p->InvDelayI ); // select opposite phase Required = Nf_ObjRequired( p, i, !c ); //assert( Required < SCL_INFINITY ); pD = Nf_ObjMatchD( p, i, !c ); pA = Nf_ObjMatchA( p, i, !c ); pM = (pA->D <= Required) ? pA : pD; assert( !pM->fCompl ); // create gate Nf_ManSetMapRefsGate( p, i, Required, pM ); // account for the inverter p->pPars->MapAreaF += p->InvAreaF; p->pPars->Edge++; p->pPars->Area++; p->nInvs++; } } else { c = (int)(nRefs[1] > 0); assert( nRefs[c] && !nRefs[!c] ); // consider this phase Required = Nf_ObjRequired( p, i, c ); //assert( Required < SCL_INFINITY ); pD = Nf_ObjMatchD( p, i, c ); pA = Nf_ObjMatchA( p, i, c ); pM = (pA->D <= Required) ? pA : pD; if ( pM->fCompl ) // use inverter { p->nInvs++; //printf( "Using inverter at node %d in phase %d\n", i, c ); pM->fBest = 1; // update opposite phase Nf_ObjMapRefInc( p, i, !c ); Nf_ObjUpdateRequired( p, i, !c, Required - p->InvDelayI ); // select opposite phase Required = Nf_ObjRequired( p, i, !c ); //assert( Required < SCL_INFINITY ); pD = Nf_ObjMatchD( p, i, !c ); pA = Nf_ObjMatchA( p, i, !c ); pM = (pA->D <= Required) ? pA : pD; assert( !pM->fCompl ); // account for the inverter p->pPars->MapAreaF += p->InvAreaF; p->pPars->Edge++; p->pPars->Area++; } // create gate Nf_ManSetMapRefsGate( p, i, Required, pM ); } // the result of this: // - only one phase can be implemented as inverter of the other phase // - required times are propagated correctly // - references are set correctly } Gia_ManForEachCiIdWithBoxes( p->pGia, Id, i ) if ( Nf_ObjMapRefNum(p, Id, 1) ) { Nf_ObjMapRefInc( p, Id, 0 ); Nf_ObjUpdateRequired( p, Id, 0, Required - p->InvDelayI ); p->pPars->MapAreaF += p->InvAreaF; p->pPars->Edge++; p->pPars->Area++; p->nInvs++; } // blend references for ( i = 0; i < nLits; i++ ) pFlowRefs[i] = Abc_MaxFloat(1.0, Coef * pFlowRefs[i] + (1.0 - Coef) * Abc_MaxFloat(1, pMapRefs[i])); // pFlowRefs[i] = 0.2 * pFlowRefs[i] + 0.8 * Abc_MaxFloat(1, pMapRefs[i]); return p->pPars->Area; } /**Function************************************************************* Synopsis [Area recovery.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word Nf_MatchDeref_rec( Nf_Man_t * p, int i, int c, Nf_Mat_t * pM ) { word Area = 0; int k, iVar, fCompl, * pCut; assert( pM->fBest ); if ( pM->fCompl ) { assert( Nf_ObjMapRefNum(p, i, !c) > 0 ); if ( !Nf_ObjMapRefDec(p, i, !c) ) Area += Nf_MatchDeref_rec( p, i, !c, Nf_ObjMatchD(p, i, !c) ); return Area + p->InvAreaW; } if ( Nf_ObjCutSetId(p, i) == 0 ) return 0; pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, i), pM->CutH ); Nf_CutForEachVarCompl( pCut, pM->Cfg, iVar, fCompl, k ) { assert( Nf_ObjMapRefNum(p, iVar, fCompl) > 0 ); if ( !Nf_ObjMapRefDec(p, iVar, fCompl) ) Area += Nf_MatchDeref_rec( p, iVar, fCompl, Nf_ObjMatchD(p, iVar, fCompl) ); } return Area + Nf_ManCell(p, pM->Gate)->AreaW; } word Nf_MatchRef_rec( Nf_Man_t * p, int i, int c, Nf_Mat_t * pM, int Required, Vec_Int_t * vBackup ) { word Area = 0; int ReqFanin; int k, iVar, fCompl, * pCut; assert( pM->fBest ); assert( pM->D <= Required ); if ( pM->fCompl ) { ReqFanin = Required - p->InvDelayI; if ( vBackup ) Vec_IntPush( vBackup, Abc_Var2Lit(i, !c) ); assert( Nf_ObjMapRefNum(p, i, !c) >= 0 ); if ( !Nf_ObjMapRefInc(p, i, !c) ) Area += Nf_MatchRef_rec( p, i, !c, Nf_ObjMatchD(p, i, !c), ReqFanin, vBackup ); return Area + p->InvAreaW; } if ( Nf_ObjCutSetId(p, i) == 0 ) return 0; pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, i), pM->CutH ); Nf_CutForEachVarCompl( pCut, pM->Cfg, iVar, fCompl, k ) { ReqFanin = Required - Nf_ManCell(p, pM->Gate)->iDelays[k]; if ( vBackup ) Vec_IntPush( vBackup, Abc_Var2Lit(iVar, fCompl) ); assert( Nf_ObjMapRefNum(p, iVar, fCompl) >= 0 ); if ( !Nf_ObjMapRefInc(p, iVar, fCompl) ) Area += Nf_MatchRef_rec( p, iVar, fCompl, Nf_ObjMatchD(p, iVar, fCompl), ReqFanin, vBackup ); } return Area + Nf_ManCell(p, pM->Gate)->AreaW; } word Nf_MatchRefArea( Nf_Man_t * p, int i, int c, Nf_Mat_t * pM, int Required ) { word Area; int iLit, k; Vec_IntClear( &p->vBackup ); Area = Nf_MatchRef_rec( p, i, c, pM, Required, &p->vBackup ); Vec_IntForEachEntry( &p->vBackup, iLit, k ) { assert( Nf_ObjMapRefNum(p, Abc_Lit2Var(iLit), Abc_LitIsCompl(iLit)) > 0 ); Nf_ObjMapRefDec( p, Abc_Lit2Var(iLit), Abc_LitIsCompl(iLit) ); } return Area; } void Nf_ManElaBestMatchOne( Nf_Man_t * p, int iObj, int c, int * pCut, int * pCutSet, Nf_Mat_t * pRes, int Required ) { Nf_Mat_t Mb,*pMb = &Mb, * pMd; int * pFans = Nf_CutLeaves(pCut); int nFans = Nf_CutSize(pCut); int iFuncLit = Nf_CutFunc(pCut); int fComplExt = Abc_LitIsCompl(iFuncLit); Vec_Int_t * vArr = Vec_WecEntry( p->vTt2Match, Abc_Lit2Var(iFuncLit) ); int i, k, Info, Offset, iFanin, fComplF; // assign fanins matches Nf_Obj_t * pBestF[NF_LEAF_MAX]; for ( i = 0; i < nFans; i++ ) pBestF[i] = Nf_ManObj( p, pFans[i] ); // consider matches of this function memset( pMb, 0, sizeof(Nf_Mat_t) ); pMb->D = SCL_INFINITY; pMb->F = FLT_MAX; // special cases if ( nFans == 0 ) { int Const = (iFuncLit == 1); //printf( "Node %d(%d) is const\n", iObj, c ); assert( iFuncLit == 0 || iFuncLit == 1 ); pMb->D = 0; pMb->F = p->pCells[c ^ Const].AreaF; pMb->CutH = Nf_CutHandle(pCutSet, pCut); pMb->Gate = c ^ Const; // pMb->Conf = 0; pMb->Cfg = Nf_Int2Cfg(0); pMb->fBest = 1; // compare if ( pRes->F > pMb->F + NF_EPSILON || (pRes->F > pMb->F - NF_EPSILON && pRes->D > pMb->D) ) *pRes = *pMb; return; } // consider matches of this function Vec_IntForEachEntryDouble( vArr, Info, Offset, i ) { Nf_Cfg_t Cfg = Nf_Int2Cfg(Offset); Mio_Cell2_t*pC = Nf_ManCell( p, Info ); int fCompl = Cfg.fCompl ^ fComplExt; int Delay = 0; assert( nFans == (int)pC->nFanins ); if ( fCompl != c ) continue; Nf_CfgForEachVarCompl( Cfg, nFans, iFanin, fComplF, k ) { pMd = &pBestF[iFanin]->M[fComplF][0]; assert( pMd->fBest ); Delay = Abc_MaxInt( Delay, pMd->D + pC->iDelays[k] ); if ( Delay > Required ) break; } if ( k < nFans ) continue; // create match pMb->D = Delay; pMb->F = FLT_MAX; pMb->fBest = 1; pMb->fCompl = 0; pMb->CutH = Nf_CutHandle(pCutSet, pCut); pMb->Gate = pC->Id; pMb->Cfg = Cfg; pMb->Cfg.fCompl = 0; // compute area pMb->F = Scl_Int2Flt((int)Nf_MatchRefArea(p, iObj, c, pMb, Required)); // compare if ( pRes->F > pMb->F + NF_EPSILON || (pRes->F > pMb->F - NF_EPSILON && pRes->D > pMb->D) ) *pRes = *pMb; } } void Nf_ManElaBestMatch( Nf_Man_t * p, int iObj, int c, Nf_Mat_t * pRes, int Required ) { int k, * pCut, * pCutSet = Nf_ObjCutSet( p, iObj ); memset( pRes, 0, sizeof(Nf_Mat_t) ); pRes->D = SCL_INFINITY; pRes->F = FLT_MAX; Nf_SetForEachCut( pCutSet, pCut, k ) { if ( Abc_Lit2Var(Nf_CutFunc(pCut)) >= Vec_WecSize(p->vTt2Match) ) continue; Nf_ManElaBestMatchOne( p, iObj, c, pCut, pCutSet, pRes, Required ); } } int Nf_ManComputeArrival( Nf_Man_t * p, Nf_Mat_t * pM, int * pCutSet ) { int Delay = 0; Nf_Mat_t * pMfan; int iVar, fCompl, k; Mio_Cell2_t * pCell = Nf_ManCell( p, pM->Gate ); int * pCut = Nf_CutFromHandle( pCutSet, pM->CutH ); assert( !pM->fCompl ); Nf_CutForEachVarCompl( pCut, pM->Cfg, iVar, fCompl, k ) { pMfan = Nf_ObjMatchBest( p, iVar, fCompl ); Delay = Abc_MaxInt( Delay, pMfan->D + pCell->iDelays[k] ); } //if ( pM->fCompl ) Delay += p->InvDelayI; return Delay; } void Nf_ManResetMatches( Nf_Man_t * p, int Round ) { Gia_Obj_t * pObj; Nf_Mat_t * pDc, * pAc, * pMfan, * pM[2]; int i, c, Arrival; // go through matches in the topo order if ( p->pManTim ) Tim_ManIncrementTravId( p->pManTim ); Gia_ManForEachObjWithBoxes( p->pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) ) { pMfan = Nf_ObjMatchBest( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj) ); for ( c = 0; c < 2; c++ ) { pDc = Nf_ObjMatchD( p, i, c ); pAc = Nf_ObjMatchA( p, i, c ); pDc->F = pAc->F = 0; pDc->D = pMfan->D + (c ? p->InvDelayI : 0); assert( pDc->fBest ); assert( !pAc->fBest ); assert( c==0 || pDc->fCompl ); } continue; } if ( Gia_ObjIsCi(pObj) ) { Arrival = Tim_ManGetCiArrival( p->pManTim, Gia_ObjCioId(pObj) ); Nf_ObjPrepareCi( p, i, Arrival ); continue; } if ( Gia_ObjIsCo(pObj) ) { Arrival = Nf_ObjMatchD( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj) )->D; Tim_ManSetCoArrival( p->pManTim, Gia_ObjCioId(pObj), Arrival ); continue; } // select the best match for each phase for ( c = 0; c < 2; c++ ) { pDc = Nf_ObjMatchD( p, i, c ); pAc = Nf_ObjMatchA( p, i, c ); pDc->F = pAc->F = 0; if ( Nf_ObjMapRefNum(p, i, c) ) { assert( pDc->fBest != pAc->fBest ); if ( pAc->fBest ) ABC_SWAP( Nf_Mat_t, *pDc, *pAc ); assert( pDc->fBest ); assert( !pAc->fBest ); } else { assert( Round > 0 || (!pDc->fBest && !pAc->fBest) ); // if ( (p->pPars->fAreaOnly || (Round & 1)) && !pAc->fCompl ) if ( (Round & 1) && !pAc->fCompl ) ABC_SWAP( Nf_Mat_t, *pDc, *pAc ); pDc->fBest = 1; pAc->fBest = 0; } } // consider best matches of both phases pM[0] = Nf_ObjMatchD( p, i, 0 ); pM[1] = Nf_ObjMatchD( p, i, 1 ); assert( pM[0]->fBest && pM[1]->fBest ); // swap complemented matches if ( pM[0]->fCompl && pM[1]->fCompl ) { // pM[0]->fCompl = pM[1]->fCompl = 0; // ABC_SWAP( Nf_Mat_t *, pM[0], pM[1] ); assert( 0 ); } if ( !pM[0]->fCompl && !pM[1]->fCompl ) { for ( c = 0; c < 2; c++ ) { Arrival = Nf_ManComputeArrival( p, pM[c], Nf_ObjCutSet(p, i) ); //if ( Nf_ObjMapRefNum(p, i, c) ) // assert( Round || Arrival <= pM[c]->D ); pM[c]->D = Arrival; } } else { // consider non-complemented match c = !pM[1]->fCompl; assert( !pM[c]->fCompl ); assert( pM[!c]->fCompl ); Arrival = Nf_ManComputeArrival( p, pM[c], Nf_ObjCutSet(p, i) ); //if ( Nf_ObjMapRefNum(p, i, c) ) // assert( Round || Arrival <= pM[c]->D ); pM[c]->D = Arrival; // consider complemented match Arrival = pM[!c]->D; *pM[!c] = *pM[c]; pM[!c]->D += p->InvDelayI; pM[!c]->fCompl = 1; //if ( Nf_ObjMapRefNum(p, i, !c) ) // assert( Round || pM[!c]->D <= Arrival ); } } } void Nf_ManComputeMappingEla( Nf_Man_t * p ) { int fVerbose = 0; Gia_Obj_t * pObj; Mio_Cell2_t * pCell; Nf_Mat_t Mb, * pMb = &Mb, * pM; word AreaBef, AreaAft, Gain = 0; int i, c, iVar, Id, fCompl, k, * pCut, Required; Nf_ManResetMatches( p, p->Iter - p->pPars->nRounds ); Nf_ManSetOutputRequireds( p, 1 ); Gia_ManForEachObjReverseWithBoxes( p->pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) ) { if ( Nf_ObjMapRefNum(p, i, 1) ) Nf_ObjUpdateRequired( p, i, 0, Nf_ObjRequired(p, i, 1) - p->InvDelayI ); int reqTime = Nf_ObjRequired(p, i, 0); int iObj = Gia_ObjFaninId0p(p->pGia, pObj); int fCompl = Gia_ObjFaninC0(pObj); Nf_ObjUpdateRequired( p, iObj, fCompl, reqTime ); if ( iObj > 0 && Nf_ObjMatchBest(p, iObj, fCompl)->fCompl ) Nf_ObjUpdateRequired( p, iObj, !fCompl, reqTime - p->InvDelayI ); continue; } if ( Gia_ObjIsCi(pObj) ) { if ( Nf_ObjMapRefNum(p, i, 1) ) Nf_ObjUpdateRequired( p, i, 0, Nf_ObjRequired(p, i, 1) - p->InvDelayI ); Tim_ManSetCiRequired( p->pManTim, Gia_ObjCioId(pObj), Nf_ObjRequired(p, i, 0) ); continue; } if ( Gia_ObjIsCo(pObj) ) { int reqTime = Tim_ManGetCoRequired( p->pManTim, Gia_ObjCioId(pObj) ); int iObj = Gia_ObjFaninId0p(p->pGia, pObj); int fCompl = Gia_ObjFaninC0(pObj); Nf_ObjUpdateRequired( p, iObj, fCompl, reqTime ); if ( iObj > 0 && Nf_ObjMatchBest(p, iObj, fCompl)->fCompl ) Nf_ObjUpdateRequired( p, iObj, !fCompl, reqTime - p->InvDelayI ); continue; } for ( c = 0; c < 2; c++ ) if ( Nf_ObjMapRefNum(p, i, c) ) { pM = Nf_ObjMatchBest( p, i, c ); Required = Nf_ObjRequired( p, i, c ); assert( pM->D <= Required ); if ( pM->fCompl ) continue; // search for a better match assert( !pM->fCompl ); AreaBef = Nf_MatchDeref_rec( p, i, c, pM ); assert( pM->fBest ); Nf_ManElaBestMatch( p, i, c, pMb, Required ); AreaAft = Nf_MatchRef_rec( p, i, c, pMb, Required, NULL ); Gain += AreaBef - AreaAft; // print area recover progress if ( fVerbose && Nf_ManCell(p, pM->Gate)->pName != Nf_ManCell(p, pMb->Gate)->pName ) { printf( "%4d (%d) ", i, c ); printf( "%8s ->%8s ", Nf_ManCell(p, pM->Gate)->pName, Nf_ManCell(p, pMb->Gate)->pName ); printf( "%d -> %d ", Nf_ManCell(p, pM->Gate)->nFanins, Nf_ManCell(p, pMb->Gate)->nFanins ); printf( "D: %7.2f -> %7.2f ", Scl_Int2Flt(pM->D), Scl_Int2Flt(pMb->D) ); printf( "R: %7.2f ", Required == SCL_INFINITY ? 9999.99 : Scl_Int2Flt(Required) ); printf( "A: %7.2f -> %7.2f ", Scl_Int2Flt((int)AreaBef), Scl_Int2Flt((int)AreaAft) ); printf( "G: %7.2f (%7.2f) ", Scl_Int2Flt((int)AreaBef - (int)AreaAft), Scl_Int2Flt((int)Gain) ); printf( "\n" ); } // set best match assert( pMb->fBest ); assert( pMb->D <= Required ); //assert( Scl_Flt2Int(pMb->F) == (int)AreaAft ); //assert( AreaBef >= AreaAft ); *pM = *pMb; // update timing pCell = Nf_ManCell( p, pMb->Gate ); pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, i), pMb->CutH ); Nf_CutForEachVarCompl( pCut, pMb->Cfg, iVar, fCompl, k ) { pM = Nf_ObjMatchBest( p, iVar, fCompl ); assert( pM->D <= Required - pCell->iDelays[k] ); Nf_ObjUpdateRequired( p, iVar, fCompl, Required - pCell->iDelays[k] ); if ( pM->fCompl ) { pM = Nf_ObjMatchBest( p, iVar, !fCompl ); assert( pM->D <= Required - pCell->iDelays[k] - p->InvDelayI ); Nf_ObjUpdateRequired( p, iVar, !fCompl, Required - pCell->iDelays[k] - p->InvDelayI ); } } } } Gia_ManForEachCiIdWithBoxes( p->pGia, Id, i ) if ( Nf_ObjMapRefNum(p, Id, 1) ) { Required = Nf_ObjRequired( p, i, 1 ); Nf_ObjUpdateRequired( p, Id, 0, Required - p->InvDelayI ); } } void Nf_ManFixPoDrivers( Nf_Man_t * p ) { Gia_Obj_t * pObj; Nf_Mat_t * pM, * pMc; int i, iDriver, Count = 0; Gia_ManForEachCo( p->pGia, pObj, i ) { iDriver = Gia_ObjFaninId0p(p->pGia, pObj); if ( !Gia_ObjIsAnd(Gia_ManObj(p->pGia, iDriver)) ) continue; // skip unless both are used if ( !Nf_ObjMapRefNum(p, iDriver, 0) || !Nf_ObjMapRefNum(p, iDriver, 1) ) continue; pM = Nf_ObjMatchD( p, iDriver, Gia_ObjFaninC0(pObj) ); pMc = Nf_ObjMatchD( p, iDriver, !Gia_ObjFaninC0(pObj) ); // skip unless both are non-complemented if ( pM->fCompl || pMc->fCompl ) continue; // skip if arrival time exceeds the required time if ( pMc->D + p->InvDelayI > p->pPars->MapDelay ) continue; // update references Nf_MatchDeref_rec( p, iDriver, Gia_ObjFaninC0(pObj), pM ); Nf_ObjMapRefInc( p, iDriver, !Gia_ObjFaninC0(pObj) ); // add inverter *pM = *pMc; pM->D += p->InvDelayI; pM->fCompl = 1; pM->fBest = 1; pMc->fBest = 1; Count++; } //printf( "Fixed %d PO drivers.\n", Count ); } /**Function************************************************************* Synopsis [Deriving mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Nf_ManDeriveMapping( Nf_Man_t * p ) { Vec_Int_t * vMapping; Nf_Mat_t * pM; int i, k, c, Id, iVar, fCompl, * pCut; assert( p->pGia->vCellMapping == NULL ); vMapping = Vec_IntAlloc( 2*Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); Vec_IntFill( vMapping, 2*Gia_ManObjNum(p->pGia), 0 ); // create CI inverters Gia_ManForEachCiId( p->pGia, Id, i ) if ( Nf_ObjMapRefNum(p, Id, 1) ) Vec_IntWriteEntry( vMapping, Abc_Var2Lit(Id, 1), -1 ); // create internal nodes Gia_ManForEachAndId( p->pGia, i ) { Gia_Obj_t * pObj = Gia_ManObj(p->pGia, i); if ( Gia_ObjIsBuf(pObj) ) { if ( Nf_ObjMapRefNum(p, i, 1) ) Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, 1), -1 ); Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, 0), -2 ); continue; } for ( c = 0; c < 2; c++ ) if ( Nf_ObjMapRefNum(p, i, c) ) { pM = Nf_ObjMatchBest( p, i, c ); // remember inverter if ( pM->fCompl ) { Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, c), -1 ); continue; } // Nf_ManCutMatchPrint( p, i, c, pM ); pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, i), pM->CutH ); Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, c), Vec_IntSize(vMapping) ); Vec_IntPush( vMapping, Nf_CutSize(pCut) ); Nf_CutForEachVarCompl( pCut, pM->Cfg, iVar, fCompl, k ) Vec_IntPush( vMapping, Abc_Var2Lit(iVar, fCompl) ); Vec_IntPush( vMapping, pM->Gate ); } } // assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); p->pGia->vCellMapping = vMapping; return p->pGia; } void Nf_ManUpdateStats( Nf_Man_t * p ) { Nf_Mat_t * pM; Gia_Obj_t * pObj; Mio_Cell2_t * pCell; int i, c, Id, * pCut; p->pPars->MapAreaF = 0; p->nInvs = 0; p->pPars->Area = p->pPars->Edge = 0; Gia_ManForEachAndReverse( p->pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) ) { if ( Nf_ObjMapRefNum(p, i, 1) ) { p->pPars->MapAreaF += p->InvAreaF; p->pPars->Edge++; p->pPars->Area++; p->nInvs++; } continue; } for ( c = 0; c < 2; c++ ) if ( Nf_ObjMapRefNum(p, i, c) ) { pM = Nf_ObjMatchBest( p, i, c ); if ( pM->fCompl ) { p->pPars->MapAreaF += p->InvAreaF; p->pPars->Edge++; p->pPars->Area++; p->nInvs++; continue; } pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, i), pM->CutH ); pCell = Nf_ManCell( p, pM->Gate ); assert( Nf_CutSize(pCut) == (int)pCell->nFanins ); p->pPars->MapAreaF += pCell->AreaF; p->pPars->Edge += Nf_CutSize(pCut); p->pPars->Area++; //printf( "%5d (%d) : Gate = %7s \n", i, c, pCell->pName ); } } Gia_ManForEachCiId( p->pGia, Id, i ) if ( Nf_ObjMapRefNum(p, Id, 1) ) { p->pPars->MapAreaF += p->InvAreaF; p->pPars->Edge++; p->pPars->Area++; p->nInvs++; } } /**Function************************************************************* Synopsis [Extract window.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* int nInputs; // the number of inputs int nObjs; // number of all objects Vec_Int_t * vRoots; // output drivers to be mapped (root -> obj lit) Vec_Wec_t * vCuts; // cuts (cut -> obj lit + fanin lits) Vec_Wec_t * vObjCuts; // cuts (obj lit -> obj lit + cut lits) Vec_Int_t * vSolCuts; // current solution (index -> cut) Vec_Int_t * vCutGates; // gates (cut -> gate) */ int Nf_ManExtractWindow( void * pMan, Vec_Int_t * vRoots, Vec_Wec_t * vCuts, Vec_Wec_t * vObjCuts, Vec_Int_t * vSolCuts, Vec_Int_t * vCutGates, Vec_Wrd_t * vCutAreas, word * pInvArea, int StartVar, int nVars ) { Nf_Man_t * p = (Nf_Man_t *)pMan; int nInputs = Gia_ManCiNum(p->pGia); int LitShift = 2*nInputs+2; Gia_Obj_t * pObj; int c, iObj; if ( 2*Gia_ManAndNum(p->pGia) + Gia_ManCiNum(p->pGia) > nVars ) { printf( "The number of variables is too large: 2*%d + %d = %d > %d.\n", Gia_ManAndNum(p->pGia), Gia_ManCiNum(p->pGia), 2*Gia_ManAndNum(p->pGia) + Gia_ManCiNum(p->pGia), nVars ); return 0; } *pInvArea = p->InvAreaW; // save roots Vec_IntClear( vRoots ); Gia_ManForEachCo( p->pGia, pObj, c ) { assert( !Gia_ObjIsCi(Gia_ObjFanin0(pObj)) ); Vec_IntPush( vRoots, Gia_ObjFaninLit0p(p->pGia, pObj)-LitShift ); } // prepare Vec_WecClear( vCuts ); Vec_WecClear( vObjCuts ); Vec_IntClear( vSolCuts ); Vec_IntClear( vCutGates ); Vec_WrdClear( vCutAreas ); // collect cuts for each node Gia_ManForEachAndId( p->pGia, iObj ) { Vec_Int_t * vObj[2], * vCutOne; int iCut, * pCut, * pCutSet; int iCutInv[2] = {-1, -1}; // get matches Nf_Mat_t * pM[2] = {NULL, NULL}; for ( c = 0; c < 2; c++ ) { if ( Nf_ObjMapRefNum(p, iObj, c) == 0 ) continue; if ( Nf_ObjMatchBest(p, iObj, c)->fCompl ) { assert( iCutInv[c] == -1 ); iCutInv[c] = Vec_IntSize(vSolCuts); Vec_IntPush( vSolCuts, -1 ); continue; } pM[c] = Nf_ObjMatchBest(p, iObj, c); } // start collecting cuts of pos-obj and neg-obj assert( Vec_WecSize(vObjCuts) == 2*iObj-LitShift ); for ( c = 0; c < 2; c++ ) { vObj[c] = Vec_WecPushLevel( vObjCuts ); Vec_IntPush( vObj[c], Abc_Var2Lit(Abc_Var2Lit(iObj, c)-LitShift, 1) ); } // enumerate cuts pCutSet = Nf_ObjCutSet( p, iObj ); Nf_SetForEachCut( pCutSet, pCut, iCut ) { assert( !Nf_CutIsTriv(pCut, iObj) ); assert( Nf_CutSize(pCut) <= p->pPars->nLutSize ); if ( Abc_Lit2Var(Nf_CutFunc(pCut)) < Vec_WecSize(p->vTt2Match) ) { int * pFans = Nf_CutLeaves(pCut); int nFans = Nf_CutSize(pCut); int iFuncLit = Nf_CutFunc(pCut); int fComplExt = Abc_LitIsCompl(iFuncLit); Vec_Int_t * vArr = Vec_WecEntry( p->vTt2Match, Abc_Lit2Var(iFuncLit) ); int i, k, c, Info, Offset, iFanin, fComplF, iCutLit; Vec_IntForEachEntryDouble( vArr, Info, Offset, i ) { Nf_Cfg_t Cfg = Nf_Int2Cfg(Offset); int fCompl = Cfg.fCompl ^ fComplExt; Mio_Cell2_t*pC = Nf_ManCell( p, Info ); assert( nFans == (int)pC->nFanins ); Vec_IntPush( vCutGates, Info ); Vec_WrdPush( vCutAreas, pC->AreaW ); // to make comparison possible Cfg.fCompl = 0; // add solution cut for ( c = 0; c < 2; c++ ) { if ( pM[c] == NULL ) continue; if ( (int)pM[c]->CutH == Nf_CutHandle(pCutSet, pCut) && (int)pM[c]->Gate == Info && Nf_Cfg2Int(pM[c]->Cfg) == Nf_Cfg2Int(Cfg) ) { Vec_IntPush( vSolCuts, Vec_WecSize(vCuts) ); //printf( "adding solution for %d\n", Abc_Var2Lit(iObj, c)-LitShift ); } } // add new cut iCutLit = Abc_Var2Lit( StartVar + Vec_WecSize(vCuts), 0 ); vCutOne = Vec_WecPushLevel( vCuts ); // add literals Vec_IntPush( vCutOne, Abc_Var2Lit(iObj, fCompl) ); Vec_IntPush( vObj[fCompl], iCutLit ); Nf_CfgForEachVarCompl( Cfg, nFans, iFanin, fComplF, k ) if ( pFans[iFanin] >= nInputs + 1 ) // internal node { Vec_IntPush( vCutOne, Abc_Var2Lit(pFans[iFanin], fComplF) ); //Vec_IntPush( Vec_WecEntry(vObjCuts, Abc_Var2Lit(pFans[iFanin], fComplF)-LitShift), iCutLit ); } else if ( fComplF ) // complemented primary input Vec_IntPush( vCutOne, Abc_Var2Lit(pFans[iFanin], 1) ); } } } assert( iCutInv[0] == -1 || iCutInv[1] == -1 ); // add inverter cut for ( c = 0; c < 2; c++ ) { if ( iCutInv[c] != -1 ) Vec_IntWriteEntry( vSolCuts, iCutInv[c], Vec_WecSize(vCuts) ); // the obj-lit implies its cut Vec_IntPush( Vec_WecEntry(vObjCuts, Abc_Var2Lit(iObj, c)-LitShift), Abc_Var2Lit(StartVar + Vec_WecSize(vCuts), 0) ); // the cut includes both literals vCutOne = Vec_WecPushLevel( vCuts ); Vec_IntPush( vCutOne, Abc_Var2Lit(iObj, c) ); Vec_IntPush( vCutOne, Abc_Var2Lit(iObj, !c) ); Vec_IntPush( vCutGates, 3 ); Vec_WrdPush( vCutAreas, p->InvAreaW ); } } // for ( c = 0; c < p->nCells; c++ ) // printf( "%d=%s ", c, p->pCells[c].pName ); // printf( "\n" ); // add complemented inputs Gia_ManForEachCiId( p->pGia, iObj, c ) if ( Nf_ObjMapRefNum(p, iObj, 1) ) Vec_IntPush( vSolCuts, -(2*Gia_ManAndNum(p->pGia)+c) ); assert( Vec_WecSize(vCuts) == Vec_IntSize(vCutGates) ); assert( Vec_WecSize(vCuts) == Vec_WrdSize(vCutAreas) ); assert( Vec_WecSize(vObjCuts) == 2*Gia_ManAndNum(p->pGia) ); return nInputs; } /**Function************************************************************* Synopsis [Technology mappping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nf_ManSetDefaultPars( Jf_Par_t * pPars ) { memset( pPars, 0, sizeof(Jf_Par_t) ); pPars->nLutSize = 6; pPars->nCutNum = 16; pPars->nProcNum = 0; pPars->nRounds = 4; pPars->nRoundsEla = 2; pPars->nRelaxRatio = 0; pPars->nCoarseLimit = 3; pPars->nAreaTuner = 0; pPars->nReqTimeFlex = 0; pPars->nVerbLimit = 5; pPars->DelayTarget = -1; pPars->fAreaOnly = 0; pPars->fPinPerm = 0; pPars->fPinQuick = 0; pPars->fPinFilter = 0; pPars->fOptEdge = 1; pPars->fCoarsen = 0; pPars->fCutMin = 1; pPars->fGenCnf = 0; pPars->fPureAig = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; pPars->nLutSizeMax = NF_LEAF_MAX; pPars->nCutNumMax = NF_CUT_MAX; pPars->MapDelayTarget = 0; } Gia_Man_t * Nf_ManPerformMappingInt( Gia_Man_t * pGia, Jf_Par_t * pPars ) { Gia_Man_t * pNew = NULL, * pCls; Nf_Man_t * p; int i, Id; if ( Gia_ManHasChoices(pGia) || pGia->pManTime ) pPars->fCoarsen = 0; pCls = pPars->fCoarsen ? Gia_ManDupMuxes(pGia, pPars->nCoarseLimit) : pGia; p = Nf_StoCreate( pCls, pPars ); if ( p == NULL ) return NULL; // if ( p->pManTim ) Tim_ManPrint( p->pManTim ); p->pGia->iFirstNonPiId = p->pManTim ? Tim_ManPiNum(p->pManTim) : Gia_ManCiNum(p->pGia); p->pGia->iFirstPoId = p->pManTim ? Gia_ManCoNum(p->pGia) - Tim_ManPoNum(p->pManTim) : 0; p->pGia->iFirstAndObj = 1 + p->pGia->iFirstNonPiId; p->pGia->iFirstPoObj = Gia_ManObjNum(p->pGia) - Gia_ManCoNum(p->pGia) + p->pGia->iFirstPoId; // if ( pPars->fVeryVerbose ) // Nf_StoPrint( p, pPars->fVeryVerbose ); if ( pPars->fVerbose && pPars->fCoarsen ) { printf( "Initial " ); Gia_ManPrintMuxStats( pGia ); printf( "\n" ); printf( "Derived " ); Gia_ManPrintMuxStats( pCls ); printf( "\n" ); } Nf_ManPrintInit( p ); Nf_ManComputeCuts( p ); Nf_ManPrintQuit( p ); if ( Scl_ConIsRunning() ) { Gia_ManForEachCiIdWithBoxes( p->pGia, Id, i ) Nf_ObjPrepareCi( p, Id, Scl_ConGetInArr(i) ); } else { Gia_ManForEachCiIdWithBoxes( p->pGia, Id, i ) // Nf_ObjPrepareCi( p, Id, Scl_Flt2Int(p->pGia->vInArrs ? Abc_MaxFloat(0.0, Vec_FltEntry(p->pGia->vInArrs, i)) : 0.0) ); Nf_ObjPrepareCi( p, Id, Scl_Flt2Int(p->pGia->vInArrs ? Vec_FltEntry(p->pGia->vInArrs, i) : 0.0) ); } for ( p->Iter = 0; p->Iter < p->pPars->nRounds; p->Iter++ ) { Nf_ManComputeMapping( p ); Nf_ManSetMapRefs( p ); Nf_ManPrintStats( p, (char *)(p->Iter ? "Area " : "Delay") ); } p->fUseEla = 1; for ( ; p->Iter < p->pPars->nRounds + pPars->nRoundsEla; p->Iter++ ) { Nf_ManComputeMappingEla( p ); Nf_ManUpdateStats( p ); Nf_ManPrintStats( p, "Ela " ); } Nf_ManFixPoDrivers( p ); pNew = Nf_ManDeriveMapping( p ); /* if ( pPars->fAreaOnly ) { int Sbm_ManTestSat( void * pMan ); Sbm_ManTestSat( p ); } */ Nf_StoDelete( p ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCellMappingVerify_rec( Gia_Man_t * p, int iLit ) { int iFanLit, k, Result = 1; if ( Abc_LitIsCompl(iLit) && Gia_ObjIsTravIdCurrentId(p, Abc_Lit2Var(iLit)) ) return 1; if ( !Abc_LitIsCompl(iLit) && Gia_ObjIsTravIdPreviousId(p, Abc_Lit2Var(iLit)) ) return 1; if ( Abc_LitIsCompl(iLit) ) Gia_ObjSetTravIdCurrentId(p, Abc_Lit2Var(iLit)); else Gia_ObjSetTravIdPreviousId(p, Abc_Lit2Var(iLit)); if ( !Gia_ObjIsAndNotBuf(Gia_ManObj(p, Abc_Lit2Var(iLit))) ) return 1; if ( !Gia_ObjIsCell(p, iLit) ) { Abc_Print( -1, "Gia_ManCellMappingVerify: Internal literal %d does not have mapping.\n", iLit ); return 0; } if ( Gia_ObjIsCellBuf(p, iLit) ) return Gia_ManCellMappingVerify_rec( p, Gia_ObjFaninLit0p(p, Gia_ManObj(p, Abc_Lit2Var(iLit))) ); if ( Gia_ObjIsCellInv(p, iLit) ) return Gia_ManCellMappingVerify_rec( p, Abc_LitNot(iLit) ); Gia_CellForEachFanin( p, iLit, iFanLit, k ) if ( Result ) Result &= Gia_ManCellMappingVerify_rec( p, iFanLit ); return Result; } void Gia_ManCellMappingVerify( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, iLit, Result = 1; assert( Gia_ManHasCellMapping(p) ); Gia_ManIncrementTravId( p ); Gia_ManIncrementTravId( p ); Gia_ManForEachBuf( p, pObj, i ) { if ( !Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) continue; iLit = Gia_ObjFaninLit0p(p, pObj); if ( !Gia_ObjIsCell(p, iLit) ) { Abc_Print( -1, "Gia_ManCellMappingVerify: Buffer driver %d does not have mapping.\n", Gia_ObjFaninId0p(p, pObj) ); Result = 0; continue; } Result &= Gia_ManCellMappingVerify_rec( p, iLit ); } Gia_ManForEachCo( p, pObj, i ) { if ( !Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) continue; iLit = Gia_ObjFaninLit0p(p, pObj); if ( !Gia_ObjIsCell(p, iLit) ) { Abc_Print( -1, "Gia_ManCellMappingVerify: CO driver %d does not have mapping.\n", Gia_ObjFaninId0p(p, pObj) ); Result = 0; continue; } Result &= Gia_ManCellMappingVerify_rec( p, iLit ); } // if ( Result ) // Abc_Print( 1, "Mapping verified correctly.\n" ); } void Gia_ManTransferCellMapping( Gia_Man_t * p, Gia_Man_t * pGia ) { int iLit, iLitNew, k, iFanLit, iPlace; if ( !Gia_ManHasCellMapping(pGia) ) return; Gia_ManCellMappingVerify( pGia ); Vec_IntFreeP( &p->vCellMapping ); p->vCellMapping = Vec_IntAlloc( 4 * Gia_ManObjNum(p) ); Vec_IntFill( p->vCellMapping, 2 * Gia_ManObjNum(p), 0 ); Gia_ManForEachCell( pGia, iLit ) { Gia_Obj_t * pObj = Gia_ManObj(pGia, Abc_Lit2Var(iLit)); if ( Gia_ObjValue(pObj) == ~0 ) // handle dangling LUT continue; assert( !Abc_LitIsCompl( Gia_ObjValue(pObj) ) ); iLitNew = Abc_LitNotCond( Gia_ObjValue(pObj), Abc_LitIsCompl(iLit) ); if ( Gia_ObjIsCellInv(pGia, iLit) ) { Vec_IntWriteEntry( p->vCellMapping, iLitNew, -1 ); continue; } if ( Gia_ObjIsCellBuf(pGia, iLit) ) { Vec_IntWriteEntry( p->vCellMapping, iLitNew, -2 ); continue; } Vec_IntWriteEntry( p->vCellMapping, iLitNew, Vec_IntSize(p->vCellMapping) ); iPlace = Vec_IntSize( p->vCellMapping ); Vec_IntPush( p->vCellMapping, Gia_ObjCellSize(pGia, iLit) ); Gia_CellForEachFanin( pGia, iLit, iFanLit, k ) { int iFanLitNew = Gia_ObjValue( Gia_ManObj(pGia, Abc_Lit2Var(iFanLit)) ); if ( iFanLitNew == ~0 ) // handle dangling LUT fanin Vec_IntAddToEntry( p->vCellMapping, iPlace, -1 ); else Vec_IntPush( p->vCellMapping, Abc_LitNotCond(iFanLitNew, Abc_LitIsCompl(iFanLit)) ); } Vec_IntPush( p->vCellMapping, Gia_ObjCellId(pGia, iLit) ); } Gia_ManCellMappingVerify( p ); } Gia_Man_t * Nf_ManPerformMapping( Gia_Man_t * p, Jf_Par_t * pPars ) { Gia_Man_t * pNew; if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) && Gia_ManIsNormalized(p) ) { pNew = Gia_ManDupUnnormalize( p ); if ( pNew == NULL ) return NULL; Gia_ManTransferTiming( pNew, p ); p = pNew; // mapping pNew = Nf_ManPerformMappingInt( p, pPars ); if ( pNew != p ) { Gia_ManTransferTiming( pNew, p ); Gia_ManStop( p ); } // normalize pNew = Gia_ManDupNormalize( p = pNew, 0 ); Gia_ManTransferCellMapping( pNew, p ); Gia_ManTransferTiming( pNew, p ); Gia_ManStop( p ); assert( Gia_ManIsNormalized(pNew) ); } else { pNew = Nf_ManPerformMappingInt( p, pPars ); Gia_ManTransferTiming( pNew, p ); //Gia_ManCellMappingVerify( pNew ); // remove choices after mapping ABC_FREE( pNew->pReprs ); ABC_FREE( pNew->pNexts ); } //pNew->MappedDelay = (int)((If_Par_t *)pp)->FinalDelay; //pNew->MappedArea = (int)((If_Par_t *)pp)->FinalArea; return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaOf.c000066400000000000000000002066451477524141600154750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaOf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [LUT structure mapper.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaOf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/st/st.h" #include "map/mio/mio.h" #include "misc/util/utilTruth.h" #include "misc/extra/extra.h" #include "base/main/main.h" #include "misc/vec/vecMem.h" #include "misc/vec/vecWec.h" #include "opt/dau/dau.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define OF_LEAF_MAX 6 #define OF_CUT_MAX 32 #define OF_NO_LEAF 31 #define OF_NO_FUNC 0x7FFFFFF #define OF_CUT_EXTRA 4 // size; delay1, delay2; area typedef struct Of_Cut_t_ Of_Cut_t; struct Of_Cut_t_ { word Sign; // signature int Delay; // delay int Flow; // flow unsigned iFunc : 27; // function (OF_NO_FUNC) unsigned nLeaves : 5; // leaf number (OF_NO_LEAF) int pLeaves[OF_LEAF_MAX+1]; // leaves }; typedef struct Of_Obj_t_ Of_Obj_t; struct Of_Obj_t_ { int iCutH; // best cut int iCutH2; // best cut int Delay1; // arrival time int Delay2; // arrival time int Required; // required int nRefs; // references int Flow; // area flow int Temp; // unused }; typedef struct Of_Man_t_ Of_Man_t; struct Of_Man_t_ { // user data Gia_Man_t * pGia; // derived manager Jf_Par_t * pPars; // parameters // cut data Vec_Mem_t * vTtMem; // truth tables Vec_Ptr_t vPages; // cut memory Vec_Int_t vCutSets; // cut offsets Vec_Int_t vCutFlows; // temporary cut area Vec_Int_t vCutDelays; // temporary cut delay Vec_Int_t vCutRefs; // temporary cut referebces int iCur; // current position int Iter; // mapping iterations // object data Of_Obj_t * pObjs; // statistics abctime clkStart; // starting time double CutCount[6]; // cut counts }; #define OF_NUM 10 #define OF_NUMINV 0.1 static inline int Of_Flt2Int( float f ) { return (int)(OF_NUM*f); } static inline float Of_Int2Flt( int i ) { return OF_NUMINV*i; } static inline int * Of_ManCutSet( Of_Man_t * p, int i ) { return (int *)Vec_PtrEntry(&p->vPages, i >> 16) + (i & 0xFFFF); } static inline int Of_ObjCutSetId( Of_Man_t * p, int i ) { return Vec_IntEntry( &p->vCutSets, i ); } static inline int * Of_ObjCutSet( Of_Man_t * p, int i ) { return Of_ManCutSet(p, Of_ObjCutSetId(p, i)); } static inline int Of_ObjHasCuts( Of_Man_t * p, int i ) { return (int)(Vec_IntEntry(&p->vCutSets, i) > 0); } static inline int Of_ObjCutFlow( Of_Man_t * p, int i ) { return Vec_IntEntry(&p->vCutFlows, i); } static inline int Of_ObjCutDelay( Of_Man_t * p, int i ) { return Vec_IntEntry(&p->vCutDelays, i); } static inline void Of_ObjSetCutFlow( Of_Man_t * p, int i, int a ) { Vec_IntWriteEntry(&p->vCutFlows, i, a); } static inline void Of_ObjSetCutDelay( Of_Man_t * p, int i, int d ) { Vec_IntWriteEntry(&p->vCutDelays, i, d); } static inline int Of_CutSize( int * pCut ) { return pCut[0] & OF_NO_LEAF; } static inline int Of_CutFunc( int * pCut ) { return ((unsigned)pCut[0] >> 5); } static inline int * Of_CutLeaves( int * pCut ) { return pCut + 1; } static inline int Of_CutSetBoth( int n, int f ) { return n | (f << 5); } static inline int Of_CutHandle( int * pCutSet, int * pCut ) { assert( pCut > pCutSet ); return pCut - pCutSet; } static inline int * Of_CutFromHandle( int * pCutSet, int h ) { assert( h > 0 ); return pCutSet + h; } static inline int Of_CutDelay1( int * pCut ) { return pCut[1 + Of_CutSize(pCut)]; } static inline int Of_CutDelay2( int * pCut ) { return pCut[2 + Of_CutSize(pCut)]; } static inline int Of_CutAreaFlow( int * pCut ) { return pCut[3 + Of_CutSize(pCut)]; } static inline void Of_CutSetDelay1( int * pCut, int d ) { pCut[1 + Of_CutSize(pCut)] = d; } static inline void Of_CutSetDelay2( int * pCut, int d ) { pCut[2 + Of_CutSize(pCut)] = d; } static inline void Of_CutSetAreaFlow( int * pCut, int d ) { pCut[3 + Of_CutSize(pCut)] = d; } static inline int Of_CutVar( int * pCut, int v ) { return Abc_Lit2Var(Of_CutLeaves(pCut)[v]); } static inline int Of_CutFlag( int * pCut, int v ) { return Abc_LitIsCompl(Of_CutLeaves(pCut)[v]); } static inline void Of_CutCleanFlag( int * pCut, int v ) { Of_CutLeaves(pCut)[v] = Abc_LitRegular(Of_CutLeaves(pCut)[v]); } static inline void Of_CutSetFlag( int * pCut, int v, int x ) { Of_CutLeaves(pCut)[v] = Abc_Var2Lit(Of_CutVar(pCut, v), x); } static inline Of_Obj_t * Of_ObjData( Of_Man_t * p, int i ) { return p->pObjs + i; } static inline int Of_ObjCutBest( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->iCutH; } static inline int Of_ObjCutBest2( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->iCutH2; } static inline int Of_ObjDelay1( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->Delay1; } static inline int Of_ObjDelay2( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->Delay2; } static inline int Of_ObjRequired( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->Required; } static inline int Of_ObjRefNum( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->nRefs; } static inline int Of_ObjFlow( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->Flow; } static inline void Of_ObjSetCutBest( Of_Man_t * p, int i, int x ) { Of_ObjData(p, i)->iCutH = x; } static inline void Of_ObjSetCutBest2( Of_Man_t * p, int i, int x ) { Of_ObjData(p, i)->iCutH2 = x; } static inline void Of_ObjSetDelay1( Of_Man_t * p, int i, int x ) { Of_ObjData(p, i)->Delay1 = x; } static inline void Of_ObjSetDelay2( Of_Man_t * p, int i, int x ) { Of_ObjData(p, i)->Delay2 = x; } static inline void Of_ObjSetRequired( Of_Man_t * p, int i, int x ) { Of_ObjData(p, i)->Required = x; } static inline void Of_ObjSetRefNum( Of_Man_t * p, int i, int x ) { Of_ObjData(p, i)->nRefs = x; } static inline void Of_ObjSetFlow( Of_Man_t * p, int i, int x ) { Of_ObjData(p, i)->Flow = x; } static inline void Of_ObjUpdateRequired( Of_Man_t * p,int i, int x ) { if ( Of_ObjRequired(p, i) > x ) Of_ObjSetRequired(p, i, x); } static inline int Of_ObjRefInc( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->nRefs++; } static inline int Of_ObjRefDec( Of_Man_t * p, int i ) { return --Of_ObjData(p, i)->nRefs; } static inline int * Of_ObjCutBestP( Of_Man_t * p, int iObj ) { assert(iObj>0 && iObjpGia));return Of_ManCutSet( p, Of_ObjCutBest(p, iObj) ); } static inline void Of_ObjSetCutBestP( Of_Man_t * p, int * pCutSet, int iObj, int * pCut ) { Of_ObjSetCutBest( p, iObj, Of_ObjCutSetId(p, iObj) + Of_CutHandle(pCutSet, pCut) ); } static inline int * Of_ObjCutBestP2( Of_Man_t * p, int iObj ) { assert(iObj>0 && iObjpGia));return Of_ManCutSet( p, Of_ObjCutBest2(p, iObj) ); } static inline void Of_ObjSetCutBestP2( Of_Man_t * p, int * pCutSet, int iObj, int * pCut ) { Of_ObjSetCutBest2( p, iObj, Of_ObjCutSetId(p, iObj) + Of_CutHandle(pCutSet, pCut) ); } #define Of_SetForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += Of_CutSize(pCut) + OF_CUT_EXTRA ) #define Of_ObjForEachCut( pCuts, i, nCuts ) for ( i = 0, i < nCuts; i++ ) #define Of_CutForEachVar( pCut, iVar, i ) for ( i = 0; i < Of_CutSize(pCut) && (iVar = Of_CutVar(pCut,i)); i++ ) #define Of_CutForEachVarFlag( pCut, iVar, Flag, i ) for ( i = 0; i < Of_CutSize(pCut) && (iVar = Of_CutVar(pCut,i)) && ((Flag = Of_CutFlag(pCut,i)), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Area flow.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Of_ManAreaFlow( Of_Man_t * p ) { int AreaUnit = 1000; int i, Id, Total = 0; Gia_Obj_t * pObj; assert( p->pGia->pRefs == NULL ); Gia_ManCreateRefs( p->pGia ); Of_ObjSetFlow( p, 0, 0 ); Gia_ManForEachCiId( p->pGia, Id, i ) Of_ObjSetFlow( p, Id, 0 ); Gia_ManForEachAnd( p->pGia, pObj, Id ) Of_ObjSetFlow( p, Id, (Gia_ObjFanin0(pObj)->Value + Gia_ObjFanin1(pObj)->Value + AreaUnit) / Gia_ObjRefNum(p->pGia, pObj) ); Gia_ManForEachCo( p->pGia, pObj, i ) Total += Gia_ObjFanin0(pObj)->Value; ABC_FREE( p->pGia->pRefs ); if ( 1 ) return; printf( "CI = %5d. ", Gia_ManCiNum(p->pGia) ); printf( "CO = %5d. ", Gia_ManCoNum(p->pGia) ); printf( "And = %8d. ", Gia_ManAndNum(p->pGia) ); printf( "Area = %8d. ", Total/AreaUnit ); printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Of_Man_t * Of_StoCreate( Gia_Man_t * pGia, Jf_Par_t * pPars ) { extern void Mf_ManSetFlowRefs( Gia_Man_t * p, Vec_Int_t * vRefs ); Of_Man_t * p; Vec_Int_t * vFlowRefs; int * pRefs = NULL; assert( pPars->nCutNum > 1 && pPars->nCutNum <= OF_CUT_MAX ); assert( pPars->nLutSize > 1 && pPars->nLutSize <= OF_LEAF_MAX ); ABC_FREE( pGia->pRefs ); Vec_IntFreeP( &pGia->vCellMapping ); if ( Gia_ManHasChoices(pGia) ) Gia_ManSetPhase(pGia); // create references ABC_FREE( pGia->pRefs ); vFlowRefs = Vec_IntAlloc(0); Mf_ManSetFlowRefs( pGia, vFlowRefs ); pGia->pRefs= Vec_IntReleaseArray(vFlowRefs); Vec_IntFree(vFlowRefs); // create p = ABC_CALLOC( Of_Man_t, 1 ); p->clkStart = Abc_Clock(); p->pGia = pGia; p->pPars = pPars; p->pObjs = ABC_CALLOC( Of_Obj_t, Gia_ManObjNum(pGia) ); p->iCur = 2; // other Vec_PtrGrow( &p->vPages, 256 ); // cut memory Vec_IntFill( &p->vCutSets, Gia_ManObjNum(pGia), 0 ); // cut offsets Vec_IntFill( &p->vCutFlows, Gia_ManObjNum(pGia), 0 ); // cut area Vec_IntFill( &p->vCutDelays,Gia_ManObjNum(pGia), 0 ); // cut delay Vec_IntGrow( &p->vCutRefs, 1000 ); // cut references if ( pPars->fCutMin ) p->vTtMem = Vec_MemAllocForTT( 6, 0 ); // compute area flow pRefs = pGia->pRefs; pGia->pRefs = NULL; Of_ManAreaFlow( p ); pGia->pRefs = pRefs; return p; } void Of_StoDelete( Of_Man_t * p ) { Vec_PtrFreeData( &p->vPages ); Vec_PtrErase( &p->vPages ); Vec_IntErase( &p->vCutSets ); Vec_IntErase( &p->vCutFlows ); Vec_IntErase( &p->vCutDelays ); Vec_IntErase( &p->vCutRefs ); ABC_FREE( p->pObjs ); // matching if ( p->pPars->fCutMin ) Vec_MemHashFree( p->vTtMem ); if ( p->pPars->fCutMin ) Vec_MemFree( p->vTtMem ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Of_CutComputeTruth6( Of_Man_t * p, Of_Cut_t * pCut0, Of_Cut_t * pCut1, int fCompl0, int fCompl1, Of_Cut_t * pCutR, int fIsXor ) { // extern int Of_ManTruthCanonicize( word * t, int nVars ); int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t = fIsXor ? t0 ^ t1 : t0 & t1; if ( (fCompl = (int)(t & 1)) ) t = ~t; pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); assert( (int)(t & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, &t); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } static inline int Of_CutComputeTruthMux6( Of_Man_t * p, Of_Cut_t * pCut0, Of_Cut_t * pCut1, Of_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Of_Cut_t * pCutR ) { int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); word tC = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCutC->iFunc)); if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; if ( Abc_LitIsCompl(pCutC->iFunc) ^ fComplC ) tC = ~tC; t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); tC = Abc_Tt6Expand( tC, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t = (tC & t1) | (~tC & t0); if ( (fCompl = (int)(t & 1)) ) t = ~t; pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); assert( (int)(t & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, &t); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Of_CutCountBits( word i ) { i = i - ((i >> 1) & 0x5555555555555555); i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); return (i*(0x0101010101010101))>>56; } static inline word Of_CutGetSign( int * pLeaves, int nLeaves ) { word Sign = 0; int i; for ( i = 0; i < nLeaves; i++ ) Sign |= ((word)1) << (pLeaves[i] & 0x3F); return Sign; } static inline int Of_CutCreateUnit( Of_Cut_t * p, int i ) { p->Delay = 0; p->Flow = 0; p->iFunc = 2; p->nLeaves = 1; p->pLeaves[0] = i; p->Sign = ((word)1) << (i & 0x3F); return 1; } static inline void Of_Cutprintf( Of_Man_t * p, Of_Cut_t * pCut ) { int i, nDigits = Abc_Base10Log(Gia_ManObjNum(p->pGia)); printf( "%d {", pCut->nLeaves ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) printf( " %*d", nDigits, pCut->pLeaves[i] ); for ( ; i < (int)p->pPars->nLutSize; i++ ) printf( " %*s", nDigits, " " ); printf( " } D = %4d A = %9d F = %6d ", pCut->Delay, pCut->Flow, pCut->iFunc ); if ( p->vTtMem ) Dau_DsdPrintFromTruth( Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut->iFunc)), pCut->nLeaves ); else printf( "\n" ); } static inline int Of_ManPrepareCuts( Of_Cut_t * pCuts, Of_Man_t * p, int iObj, int fAddUnit ) { if ( Of_ObjHasCuts(p, iObj) ) { Of_Cut_t * pMfCut = pCuts; int i, * pCut, * pList = Of_ObjCutSet(p, iObj); Of_SetForEachCut( pList, pCut, i ) { pMfCut->Delay = 0; pMfCut->Flow = 0; pMfCut->iFunc = Of_CutFunc( pCut ); pMfCut->nLeaves = Of_CutSize( pCut ); pMfCut->Sign = Of_CutGetSign( pCut+1, Of_CutSize(pCut) ); memcpy( pMfCut->pLeaves, pCut+1, sizeof(int) * Of_CutSize(pCut) ); pMfCut++; } if ( fAddUnit && pCuts->nLeaves > 1 ) return pList[0] + Of_CutCreateUnit( pMfCut, iObj ); return pList[0]; } return Of_CutCreateUnit( pCuts, iObj ); } static inline int Of_ManSaveCuts( Of_Man_t * p, Of_Cut_t ** pCuts, int nCuts ) { int i, * pPlace, iCur, nInts = 1, nCutsNew = 0; for ( i = 0; i < nCuts; i++ ) nInts += pCuts[i]->nLeaves + OF_CUT_EXTRA, nCutsNew++; if ( (p->iCur & 0xFFFF) + nInts > 0xFFFF ) p->iCur = ((p->iCur >> 16) + 1) << 16; if ( Vec_PtrSize(&p->vPages) == (p->iCur >> 16) ) Vec_PtrPush( &p->vPages, ABC_CALLOC(int, (1<<16)) ); iCur = p->iCur; p->iCur += nInts; pPlace = Of_ManCutSet( p, iCur ); *pPlace++ = nCutsNew; for ( i = 0; i < nCuts; i++ ) { *pPlace++ = Of_CutSetBoth( pCuts[i]->nLeaves, pCuts[i]->iFunc ); memcpy( pPlace, pCuts[i]->pLeaves, sizeof(int) * pCuts[i]->nLeaves ); pPlace += pCuts[i]->nLeaves; memset( pPlace, 0xFF, sizeof(int) * (OF_CUT_EXTRA - 1) ); pPlace += OF_CUT_EXTRA - 1; } return iCur; } static inline void Of_ManLiftCuts( Of_Man_t * p, int iObj ) { int i, k, * pCut, * pList = Of_ObjCutSet(p, iObj); assert( Of_ObjHasCuts(p, iObj) ); Of_SetForEachCut( pList, pCut, i ) { for ( k = 1; k <= Of_CutSize(pCut); k++ ) pCut[k] = Abc_Var2Lit(pCut[k], 0); } } static inline void Of_CutPrint( int * pCut ) { int k, iVar; printf( "Cut with %d inputs and function %3d : { ", Of_CutSize(pCut), Of_CutFunc(pCut) == OF_NO_FUNC ? 0 : Of_CutFunc(pCut) ); Of_CutForEachVar( pCut, iVar, k ) printf( "%d ", iVar ); printf( "}\n" ); } /**Function************************************************************* Synopsis [Check correctness of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Of_CutCheck( Of_Cut_t * pBase, Of_Cut_t * pCut ) // check if pCut is contained in pBase { int nSizeB = pBase->nLeaves; int nSizeC = pCut->nLeaves; int i, * pB = pBase->pLeaves; int k, * pC = pCut->pLeaves; for ( i = 0; i < nSizeC; i++ ) { for ( k = 0; k < nSizeB; k++ ) if ( pC[i] == pB[k] ) break; if ( k == nSizeB ) return 0; } return 1; } static inline int Of_SetCheckArray( Of_Cut_t ** ppCuts, int nCuts ) { Of_Cut_t * pCut0, * pCut1; int i, k, m, n, Value; assert( nCuts > 0 ); for ( i = 0; i < nCuts; i++ ) { pCut0 = ppCuts[i]; assert( pCut0->nLeaves <= OF_LEAF_MAX ); assert( pCut0->Sign == Of_CutGetSign(pCut0->pLeaves, pCut0->nLeaves) ); // check duplicates for ( m = 0; m < (int)pCut0->nLeaves; m++ ) for ( n = m + 1; n < (int)pCut0->nLeaves; n++ ) assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] ); // check pairs for ( k = 0; k < nCuts; k++ ) { pCut1 = ppCuts[k]; if ( pCut0 == pCut1 ) continue; // check containments Value = Of_CutCheck( pCut0, pCut1 ); assert( Value == 0 ); } } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Of_CutMergeOrder( Of_Cut_t * pCut0, Of_Cut_t * pCut1, Of_Cut_t * pCut, int nLutSize ) { int nSize0 = pCut0->nLeaves; int nSize1 = pCut1->nLeaves; int i, * pC0 = pCut0->pLeaves; int k, * pC1 = pCut1->pLeaves; int c, * pC = pCut->pLeaves; // the case of the largest cut sizes if ( nSize0 == nLutSize && nSize1 == nLutSize ) { for ( i = 0; i < nSize0; i++ ) { if ( pC0[i] != pC1[i] ) return 0; pC[i] = pC0[i]; } pCut->nLeaves = nLutSize; pCut->iFunc = OF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; } // compare two cuts with different numbers i = k = c = 0; if ( nSize0 == 0 ) goto FlushCut1; if ( nSize1 == 0 ) goto FlushCut0; while ( 1 ) { if ( c == nLutSize ) return 0; if ( pC0[i] < pC1[k] ) { pC[c++] = pC0[i++]; if ( i >= nSize0 ) goto FlushCut1; } else if ( pC0[i] > pC1[k] ) { pC[c++] = pC1[k++]; if ( k >= nSize1 ) goto FlushCut0; } else { pC[c++] = pC0[i++]; k++; if ( i >= nSize0 ) goto FlushCut1; if ( k >= nSize1 ) goto FlushCut0; } } FlushCut0: if ( c + nSize0 > nLutSize + i ) return 0; while ( i < nSize0 ) pC[c++] = pC0[i++]; pCut->nLeaves = c; pCut->iFunc = OF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; FlushCut1: if ( c + nSize1 > nLutSize + k ) return 0; while ( k < nSize1 ) pC[c++] = pC1[k++]; pCut->nLeaves = c; pCut->iFunc = OF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; } static inline int Of_CutMergeOrderMux( Of_Cut_t * pCut0, Of_Cut_t * pCut1, Of_Cut_t * pCut2, Of_Cut_t * pCut, int nLutSize ) { int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; int x2, i2 = 0, nSize2 = pCut2->nLeaves, * pC2 = pCut2->pLeaves; int xMin, c = 0, * pC = pCut->pLeaves; while ( 1 ) { x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; x2 = (i2 == nSize2) ? ABC_INFINITY : pC2[i2]; xMin = Abc_MinInt( Abc_MinInt(x0, x1), x2 ); if ( xMin == ABC_INFINITY ) break; if ( c == nLutSize ) return 0; pC[c++] = xMin; if (x0 == xMin) i0++; if (x1 == xMin) i1++; if (x2 == xMin) i2++; } pCut->nLeaves = c; pCut->iFunc = OF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign | pCut2->Sign; return 1; } static inline int Of_SetCutIsContainedOrder( Of_Cut_t * pBase, Of_Cut_t * pCut ) // check if pCut is contained in pBase { int i, nSizeB = pBase->nLeaves; int k, nSizeC = pCut->nLeaves; if ( nSizeB == nSizeC ) { for ( i = 0; i < nSizeB; i++ ) if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) return 0; return 1; } assert( nSizeB > nSizeC ); if ( nSizeC == 0 ) return 1; for ( i = k = 0; i < nSizeB; i++ ) { if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) return 0; if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) { if ( ++k == nSizeC ) return 1; } } return 0; } static inline int Of_SetLastCutIsContained( Of_Cut_t ** pCuts, int nCuts ) { int i; for ( i = 0; i < nCuts; i++ ) if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Of_SetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) ) return 1; return 0; } static inline int Of_SetLastCutContainsArea( Of_Cut_t ** pCuts, int nCuts ) { int i, k, fChanges = 0; for ( i = 0; i < nCuts; i++ ) if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Of_SetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) ) pCuts[i]->nLeaves = OF_NO_LEAF, fChanges = 1; if ( !fChanges ) return nCuts; for ( i = k = 0; i <= nCuts; i++ ) { if ( pCuts[i]->nLeaves == OF_NO_LEAF ) continue; if ( k < i ) ABC_SWAP( Of_Cut_t *, pCuts[k], pCuts[i] ); k++; } return k - 1; } static inline int Of_CutCompareArea( Of_Cut_t * pCut0, Of_Cut_t * pCut1 ) { if ( pCut0->Delay < pCut1->Delay ) return -1; if ( pCut0->Delay > pCut1->Delay ) return 1; if ( pCut0->Flow < pCut1->Flow ) return -1; if ( pCut0->Flow > pCut1->Flow ) return 1; if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; return 0; } static inline void Of_SetSortByArea( Of_Cut_t ** pCuts, int nCuts ) { int i; for ( i = nCuts; i > 0; i-- ) { if ( Of_CutCompareArea(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 ) return; ABC_SWAP( Of_Cut_t *, pCuts[i - 1], pCuts[i] ); } } static inline int Of_SetAddCut( Of_Cut_t ** pCuts, int nCuts, int nCutNum ) { if ( nCuts == 0 ) return 1; nCuts = Of_SetLastCutContainsArea(pCuts, nCuts); Of_SetSortByArea( pCuts, nCuts ); return Abc_MinInt( nCuts + 1, nCutNum - 1 ); } static inline int Of_CutArea( Of_Man_t * p, int nLeaves ) { if ( nLeaves < 2 ) return 0; return nLeaves + p->pPars->nAreaTuner; } static inline void Of_CutParams( Of_Man_t * p, Of_Cut_t * pCut, int nGiaRefs ) { int i, nLeaves = pCut->nLeaves; assert( nLeaves <= p->pPars->nLutSize ); pCut->Delay = 0; pCut->Flow = 0; for ( i = 0; i < nLeaves; i++ ) { pCut->Delay = Abc_MaxInt( pCut->Delay, Of_ObjCutDelay(p, pCut->pLeaves[i]) ); pCut->Flow += Of_ObjCutFlow(p, pCut->pLeaves[i]); } pCut->Delay += (int)(nLeaves > 1); pCut->Flow = (pCut->Flow + 100 * Of_CutArea(p, nLeaves)) / (nGiaRefs ? nGiaRefs : 1); } void Of_ObjMergeOrder( Of_Man_t * p, int iObj ) { Of_Cut_t pCuts0[OF_CUT_MAX], pCuts1[OF_CUT_MAX], pCuts[OF_CUT_MAX], * pCutsR[OF_CUT_MAX]; Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); int nGiaRefs = 2*Gia_ObjRefNumId(p->pGia, iObj); int nLutSize = p->pPars->nLutSize; int nCutNum = p->pPars->nCutNum; int nCuts0 = Of_ManPrepareCuts(pCuts0, p, Gia_ObjFaninId0(pObj, iObj), 1); int nCuts1 = Of_ManPrepareCuts(pCuts1, p, Gia_ObjFaninId1(pObj, iObj), 1); int fComp0 = Gia_ObjFaninC0(pObj); int fComp1 = Gia_ObjFaninC1(pObj); int iSibl = Gia_ObjSibl(p->pGia, iObj); Of_Cut_t * pCut0, * pCut1, * pCut0Lim = pCuts0 + nCuts0, * pCut1Lim = pCuts1 + nCuts1; int i, nCutsR = 0; assert( !Gia_ObjIsBuf(pObj) ); for ( i = 0; i < nCutNum; i++ ) pCutsR[i] = pCuts + i; if ( iSibl ) { Of_Cut_t pCuts2[OF_CUT_MAX]; Gia_Obj_t * pObjE = Gia_ObjSiblObj(p->pGia, iObj); int fCompE = Gia_ObjPhase(pObj) ^ Gia_ObjPhase(pObjE); int nCuts2 = Of_ManPrepareCuts(pCuts2, p, iSibl, 0); Of_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) { *pCutsR[nCutsR] = *pCut2; if ( p->pPars->fCutMin ) pCutsR[nCutsR]->iFunc = Abc_LitNotCond( pCutsR[nCutsR]->iFunc, fCompE ); Of_CutParams( p, pCutsR[nCutsR], nGiaRefs ); nCutsR = Of_SetAddCut( pCutsR, nCutsR, nCutNum ); } } if ( Gia_ObjIsMuxId(p->pGia, iObj) ) { Of_Cut_t pCuts2[OF_CUT_MAX]; int nCuts2 = Of_ManPrepareCuts(pCuts2, p, Gia_ObjFaninId2(p->pGia, iObj), 1); int fComp2 = Gia_ObjFaninC2(p->pGia, pObj); Of_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; p->CutCount[0] += nCuts0 * nCuts1 * nCuts2; for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) { if ( Of_CutCountBits(pCut0->Sign | pCut1->Sign | pCut2->Sign) > nLutSize ) continue; p->CutCount[1]++; if ( !Of_CutMergeOrderMux(pCut0, pCut1, pCut2, pCutsR[nCutsR], nLutSize) ) continue; if ( Of_SetLastCutIsContained(pCutsR, nCutsR) ) continue; p->CutCount[2]++; if ( p->pPars->fCutMin && Of_CutComputeTruthMux6(p, pCut0, pCut1, pCut2, fComp0, fComp1, fComp2, pCutsR[nCutsR]) ) pCutsR[nCutsR]->Sign = Of_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); Of_CutParams( p, pCutsR[nCutsR], nGiaRefs ); nCutsR = Of_SetAddCut( pCutsR, nCutsR, nCutNum ); } } else { int fIsXor = Gia_ObjIsXor(pObj); p->CutCount[0] += nCuts0 * nCuts1; for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) { if ( (int)(pCut0->nLeaves + pCut1->nLeaves) > nLutSize && Of_CutCountBits(pCut0->Sign | pCut1->Sign) > nLutSize ) continue; p->CutCount[1]++; if ( !Of_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], nLutSize) ) continue; if ( Of_SetLastCutIsContained(pCutsR, nCutsR) ) continue; p->CutCount[2]++; if ( p->pPars->fCutMin && Of_CutComputeTruth6(p, pCut0, pCut1, fComp0, fComp1, pCutsR[nCutsR], fIsXor) ) pCutsR[nCutsR]->Sign = Of_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); Of_CutParams( p, pCutsR[nCutsR], nGiaRefs ); nCutsR = Of_SetAddCut( pCutsR, nCutsR, nCutNum ); } } // debug printout if ( 0 ) { printf( "*** Obj = %d\n", iObj ); for ( i = 0; i < nCutsR; i++ ) Of_Cutprintf( p, pCutsR[i] ); printf( "\n" ); } // verify assert( nCutsR > 0 && nCutsR < nCutNum ); //assert( Of_SetCheckArray(pCutsR, nCutsR) ); // store the cutset Of_ObjSetCutFlow( p, iObj, pCutsR[0]->Flow ); Of_ObjSetCutDelay( p, iObj, pCutsR[0]->Delay ); *Vec_IntEntryP(&p->vCutSets, iObj) = Of_ManSaveCuts(p, pCutsR, nCutsR); p->CutCount[3] += nCutsR; } void Of_ManComputeCuts( Of_Man_t * p ) { Gia_Obj_t * pObj; int i, iFanin; Gia_ManForEachAnd( p->pGia, pObj, i ) if ( Gia_ObjIsBuf(pObj) ) { iFanin = Gia_ObjFaninId0(pObj, i); Of_ObjSetCutFlow( p, i, Of_ObjCutFlow(p, iFanin) ); Of_ObjSetCutDelay( p, i, Of_ObjCutDelay(p, iFanin) ); } else Of_ObjMergeOrder( p, i ); Gia_ManForEachAnd( p->pGia, pObj, i ) if ( !Gia_ObjIsBuf(pObj) ) Of_ManLiftCuts( p, i ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Of_ManPrintStats( Of_Man_t * p, char * pTitle ) { if ( !p->pPars->fVerbose ) return; printf( "%s : ", pTitle ); printf( "Delay =%8.2f ", Of_Int2Flt((int)p->pPars->Delay) ); printf( "Area =%8d ", (int)p->pPars->Area ); printf( "Edge =%9d ", (int)p->pPars->Edge ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); fflush( stdout ); } void Of_ManPrintInit( Of_Man_t * p ) { int nChoices; if ( !p->pPars->fVerbose ) return; printf( "LutSize = %d ", p->pPars->nLutSize ); printf( "CutNum = %d ", p->pPars->nCutNum ); printf( "Iter = %d ", p->pPars->nRounds + p->pPars->nRoundsEla ); printf( "Coarse = %d ", p->pPars->fCoarsen ); if ( p->pPars->fCutMin ) printf( "Funcs = %d ", Vec_MemEntryNum(p->vTtMem) ); nChoices = Gia_ManChoiceNum( p->pGia ); if ( nChoices ) printf( "Choices = %d ", nChoices ); printf( "\n" ); printf( "Computing cuts...\r" ); fflush( stdout ); } void Of_ManPrintQuit( Of_Man_t * p ) { float MemGia = Gia_ManMemory(p->pGia) / (1<<20); float MemMan = 1.0 * sizeof(Of_Obj_t) * Gia_ManObjNum(p->pGia) / (1<<20); float MemCuts = 1.0 * sizeof(int) * (1 << 16) * Vec_PtrSize(&p->vPages) / (1<<20); float MemTt = p->vTtMem ? Vec_MemMemory(p->vTtMem) / (1<<20) : 0; if ( p->CutCount[0] == 0 ) p->CutCount[0] = 1; if ( !p->pPars->fVerbose ) return; printf( "CutPair = %.0f ", p->CutCount[0] ); printf( "Merge = %.0f (%.1f) ", p->CutCount[1], 1.0*p->CutCount[1]/Gia_ManAndNum(p->pGia) ); printf( "Eval = %.0f (%.1f) ", p->CutCount[2], 1.0*p->CutCount[2]/Gia_ManAndNum(p->pGia) ); printf( "Cut = %.0f (%.1f) ", p->CutCount[3], 1.0*p->CutCount[3]/Gia_ManAndNum(p->pGia) ); // printf( "Use = %.0f (%.1f) ", p->CutCount[4], 1.0*p->CutCount[4]/Gia_ManAndNum(p->pGia) ); // printf( "Mat = %.0f (%.1f) ", p->CutCount[5], 1.0*p->CutCount[5]/Gia_ManAndNum(p->pGia) ); // printf( "Equ = %d (%.2f %%) ", p->nCutUseAll, 100.0*p->nCutUseAll /p->CutCount[0] ); printf( "\n" ); printf( "Gia = %.2f MB ", MemGia ); printf( "Man = %.2f MB ", MemMan ); printf( "Cut = %.2f MB ", MemCuts ); if ( p->pPars->fCutMin ) printf( "TT = %.2f MB ", MemTt ); printf( "Total = %.2f MB ", MemGia + MemMan + MemCuts + MemTt ); // printf( "\n" ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); fflush( stdout ); } /**Function************************************************************* Synopsis [Technology mappping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* static inline int Of_ManComputeForwardCut( Of_Man_t * p, int iObj, int * pCut ) { int k, iVar, Delay = 0, Area = Of_CutArea(p, Of_CutSize(pCut)); int DelayLut1 = p->pPars->nDelayLut1; Of_CutForEachVar( pCut, iVar, k ) { Delay = Abc_MaxInt( Delay, Of_ObjDelay1(p, iVar) + DelayLut1 ); if ( p->Iter ) Area += Of_ObjRefNum(p, iVar) ? 0 : Of_ObjFlow(p, iVar); } Of_CutSetDelay1( pCut, Delay ); if ( p->Iter ) Of_CutSetAreaFlow( pCut, Area ); return Delay; } static inline void Of_ManComputeForwardObj( Of_Man_t * p, int iObj ) { int Delay1 = ABC_INFINITY, Area1 = ABC_INFINITY; int * pList = Of_ObjCutSet(p, iObj); int i, * pCut, * pCutMin = NULL, * pCutMin2 = NULL; // compute cut arrivals Of_SetForEachCut( pList, pCut, i ) { int Delay1This = Of_ManComputeForwardCut(p, iObj, pCut); if ( Delay1 > Delay1This ) { Delay1 = Delay1This; pCutMin = pCut; } if ( p->Iter && Area1 > Of_CutAreaFlow(pCut) ) { Area1 = Of_CutAreaFlow(pCut); pCutMin2 = pCut; } } // if mapping is present, set object arrival equal to cut arrival if ( Of_ObjRefNum(p, iObj) ) { pCutMin = Of_ObjCutBestP(p, iObj); Delay1 = Of_CutDelay1( pCutMin ); Of_ObjSetDelay1( p, iObj, Delay1 ); if ( p->Iter ) Of_ObjSetFlow( p, iObj, Of_CutAreaFlow(pCutMin) ); } else { if ( p->Iter == 0 ) { Of_ObjSetCutBestP( p, pList, iObj, pCutMin ); Of_ObjSetDelay1( p, iObj, Delay1 ); } else { Of_ObjSetCutBestP( p, pList, iObj, pCutMin2 ); Of_ObjSetDelay1( p, iObj, Of_CutDelay1(pCutMin2) ); Of_ObjSetFlow( p, iObj, Of_CutAreaFlow(pCutMin2) ); } } } */ /* int * Of_CutReferChooseCut( Of_Man_t * p, int Var, int Required, int fSetBest ) { int i, CostMin = ABC_INFINITY; int * pCutMin = NULL, * pList = Of_ObjCutSet(p, Var); int * pCut = Of_ObjCutBestP(p, Var); assert( Of_CutDelay1(pCut) <= Required ); // return pCut; // choose cut with smaller area Of_SetForEachCut( pList, pCut, i ) { if ( Of_CutDelay1(pCut) > Required ) continue; if ( CostMin > Of_CutAreaFlow(pCut) ) { CostMin = Of_CutAreaFlow(pCut); pCutMin = pCut; } } assert( pCutMin != NULL ); assert( Of_CutDelay1(pCutMin) <= Required ); if ( fSetBest ) Of_ObjSetCutBestP( p, pList, Var, pCutMin ); return pCutMin; } int Of_CutRef2_rec( Of_Man_t * p, int * pCut, int Required, int fSetBest ) { int i, Var, Count = Of_CutArea(p, Of_CutSize(pCut)); assert( Of_CutDelay1(pCut) <= Required ); Required -= p->pPars->nDelayLut1; Of_CutForEachVar( pCut, Var, i ) { if ( !Of_ObjCutBest(p, Var) ) continue; if ( !fSetBest ) Vec_IntPush( &p->vCutRefs, Var ); if ( Of_ObjRefInc(p, Var) ) continue; Count += Of_CutRef2_rec( p, Of_CutReferChooseCut(p, Var, Required, fSetBest), Required, fSetBest ); } return Count; } static inline int Of_CutAreaDerefed2( Of_Man_t * p, int * pCut, int Required ) { int Ela1, i, iObj; assert( Vec_IntSize(&p->vCutRefs) == 0 ); Ela1 = Of_CutRef2_rec( p, pCut, Required, 0 ); Vec_IntForEachEntry( &p->vCutRefs, iObj, i ) Of_ObjRefDec(p, iObj); Vec_IntClear( &p->vCutRefs ); return Ela1; } */ static inline int Of_ManComputeForwardCut( Of_Man_t * p, int iObj, int * pCut ) { int k, iVar, Delay = 0; int DelayLut1 = p->pPars->nDelayLut1; Of_CutForEachVar( pCut, iVar, k ) Delay = Abc_MaxInt( Delay, Of_ObjDelay1(p, iVar) + DelayLut1 ); Of_CutSetDelay1( pCut, Delay ); return Delay; } static inline int Of_ManComputeForwardCutArea( Of_Man_t * p, int iObj, int * pCut ) { int k, iVar, Area = 100 * Of_CutArea(p, Of_CutSize(pCut)); Of_CutForEachVar( pCut, iVar, k ) Area += Of_ObjFlow(p, iVar); return Area / Abc_MaxInt(1, Of_ObjRefNum(p, iObj)); } static inline void Of_ManComputeForwardObj( Of_Man_t * p, int iObj ) { int Delay1 = ABC_INFINITY; int i, * pCut, * pCutMin = NULL, * pList = Of_ObjCutSet(p, iObj); // compute cut arrivals Of_SetForEachCut( pList, pCut, i ) { int Delay1This = Of_ManComputeForwardCut(p, iObj, pCut); if ( Delay1 > Delay1This ) { Delay1 = Delay1This; pCutMin = pCut; } } // if mapping is present, set object arrival equal to cut arrival if ( Of_ObjRefNum(p, iObj) ) pCutMin = Of_ObjCutBestP(p, iObj); Of_ObjSetCutBestP( p, pList, iObj, pCutMin ); Of_ObjSetDelay1( p, iObj, Of_CutDelay1(pCutMin) ); if ( p->Iter ) Of_ObjSetFlow( p, iObj, Of_ManComputeForwardCutArea(p, iObj, pCutMin) ); } void Of_ManComputeForward1( Of_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachAnd( p->pGia, pObj, i ) if ( Gia_ObjIsBuf(pObj) ) Of_ObjSetDelay1( p, i, Of_ObjDelay1(p, Gia_ObjFaninId0(pObj, i)) ); else Of_ManComputeForwardObj( p, i ); } int Of_CutRef_rec( Of_Man_t * p, int * pCut ) { int i, Var, Count = (p->Iter & 1) ? 1 : Of_CutArea(p, Of_CutSize(pCut)); Of_CutForEachVar( pCut, Var, i ) if ( Of_ObjCutBest(p, Var) && !Of_ObjRefInc(p, Var) ) Count += Of_CutRef_rec( p, Of_ObjCutBestP(p, Var) ); return Count; } int Of_CutDeref_rec( Of_Man_t * p, int * pCut ) { int i, Var, Count = (p->Iter & 1) ? 1 : Of_CutArea(p, Of_CutSize(pCut)); Of_CutForEachVar( pCut, Var, i ) if ( Of_ObjCutBest(p, Var) && !Of_ObjRefDec(p, Var) ) Count += Of_CutDeref_rec( p, Of_ObjCutBestP(p, Var) ); return Count; } static inline int Of_CutAreaDerefed( Of_Man_t * p, int * pCut ) { int Ela1 = Of_CutRef_rec( p, pCut ); int Ela2 = Of_CutDeref_rec( p, pCut ); assert( Ela1 == Ela2 ); return Ela1; } int Of_CutRef2_rec( Of_Man_t * p, int * pCut ) { int i, Var, Count = (p->Iter & 1) ? 1 : Of_CutArea(p, Of_CutSize(pCut)); Of_CutForEachVar( pCut, Var, i ) { if ( !Of_ObjCutBest(p, Var) ) continue; Vec_IntPush( &p->vCutRefs, Var ); if ( Of_ObjRefInc(p, Var) ) continue; Count += Of_CutRef2_rec( p, Of_ObjCutBestP(p, Var) ); } return Count; } static inline int Of_CutAreaDerefed2( Of_Man_t * p, int * pCut ) { int Ela1, i, iObj; assert( Vec_IntSize(&p->vCutRefs) == 0 ); Ela1 = Of_CutRef2_rec( p, pCut ); Vec_IntForEachEntry( &p->vCutRefs, iObj, i ) Of_ObjRefDec(p, iObj); Vec_IntClear( &p->vCutRefs ); return Ela1; } static inline void Of_ManComputeForwardObj2( Of_Man_t * p, int iObj ) { int Delay, Required = Of_ObjRequired(p, iObj); int AreaBef = 0, AreaAft = 0, Area, AreaMin = ABC_INFINITY; int k, * pCut, * pCutMin = NULL, * pList = Of_ObjCutSet(p, iObj); if ( Of_ObjRefNum(p, iObj) ) AreaBef = Of_CutDeref_rec( p, Of_ObjCutBestP(p, iObj) ); Of_SetForEachCut( pList, pCut, k ) { Delay = Of_ManComputeForwardCut(p, iObj, pCut); if ( Delay > Required ) continue; Area = Of_CutAreaDerefed2( p, pCut ); if ( AreaMin > Area ) { AreaMin = Area; pCutMin = pCut; } } assert( pCutMin != NULL ); Of_ObjSetCutBestP( p, pList, iObj, pCutMin ); if ( Of_ObjRefNum(p, iObj) ) AreaAft = Of_CutRef_rec( p, pCutMin ); assert( AreaAft <= AreaBef ); Delay = Of_CutDelay1(pCutMin); assert( Delay <= Required ); Of_ObjSetDelay1( p, iObj, Delay ); } void Of_ManComputeForward2( Of_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachAnd( p->pGia, pObj, i ) if ( Gia_ObjIsBuf(pObj) ) Of_ObjSetDelay1( p, i, Of_ObjDelay1(p, Gia_ObjFaninId0(pObj, i)) ); else Of_ManComputeForwardObj2( p, i ); } static inline int Of_ManComputeOutputRequired( Of_Man_t * p, int fCleanRefs ) { int i, Id, Delay = 0; for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ ) { Of_ObjSetRequired( p, i, ABC_INFINITY ); if ( fCleanRefs ) Of_ObjSetRefNum( p, i, 0 ); } Gia_ManForEachCoDriverId( p->pGia, Id, i ) Delay = Abc_MaxInt( Delay, Of_ObjDelay1(p, Id) ); Gia_ManForEachCoDriverId( p->pGia, Id, i ) { Of_ObjUpdateRequired( p, Id, Delay ); if ( fCleanRefs ) Of_ObjRefInc( p, Id ); } if ( p->pPars->Delay && p->pPars->Delay < Delay ) printf( "Error: Delay violation.\n" ); p->pPars->Delay = Delay; return Delay; } static inline int Of_ManComputeBackwardCut( Of_Man_t * p, int * pCut ) { int k, iVar, Cost = 0; Of_CutForEachVar( pCut, iVar, k ) if ( !Of_ObjRefNum(p, iVar) ) Cost += Of_ObjFlow( p, iVar ); return Cost; } void Of_ManComputeBackward1( Of_Man_t * p ) { Gia_Obj_t * pObj; int DelayLut1 = p->pPars->nDelayLut1; int i, k, iVar, * pList, * pCut, * pCutMin; Of_ManComputeOutputRequired( p, 1 ); // compute area and edges p->pPars->Area = p->pPars->Edge = 0; Gia_ManForEachAndReverse( p->pGia, pObj, i ) { int CostMin, Cost, Required = Of_ObjRequired(p, i); if ( Gia_ObjIsBuf(pObj) ) { int FaninId = Gia_ObjFaninId0(pObj, i); Of_ObjUpdateRequired( p, FaninId, Required ); Of_ObjRefInc( p, FaninId ); continue; } if ( !Of_ObjRefNum(p, i) ) continue; // select the best cut pCutMin = NULL; CostMin = ABC_INFINITY; pList = Of_ObjCutSet( p, i ); Of_SetForEachCut( pList, pCut, k ) { if ( Of_CutDelay1(pCut) > Required ) continue; Cost = Of_ManComputeBackwardCut( p, pCut ); if ( CostMin > Cost ) { CostMin = Cost; pCutMin = pCut; } } // the cut is selected assert( pCutMin != NULL ); Of_ObjSetCutBestP( p, pList, i, pCutMin ); Of_CutForEachVar( pCutMin, iVar, k ) { Of_ObjUpdateRequired( p, iVar, Required - DelayLut1 ); Of_ObjRefInc( p, iVar ); } // update parameters p->pPars->Edge += Of_CutSize(pCutMin); p->pPars->Area++; } } void Of_ManComputeBackward2( Of_Man_t * p ) { Gia_Obj_t * pObj; int DelayLut1 = p->pPars->nDelayLut1; int i, k, iVar, * pCutMin; Of_ManComputeOutputRequired( p, 0 ); // compute area and edges p->pPars->Area = p->pPars->Edge = 0; Gia_ManForEachAndReverse( p->pGia, pObj, i ) { int Required = Of_ObjRequired(p, i); if ( Gia_ObjIsBuf(pObj) ) { int FaninId = Gia_ObjFaninId0(pObj, i); Of_ObjUpdateRequired( p, FaninId, Required ); continue; } if ( !Of_ObjRefNum(p, i) ) continue; // lookup for the cut pCutMin = Of_ObjCutBestP( p, i ); Of_CutForEachVar( pCutMin, iVar, k ) Of_ObjUpdateRequired( p, iVar, Required - DelayLut1 ); // update parameters p->pPars->Edge += Of_CutSize(pCutMin); p->pPars->Area++; } } void Of_ManComputeBackward3( Of_Man_t * p ) { Gia_Obj_t * pObj; int DelayLut1 = p->pPars->nDelayLut1; int i, k, iVar, * pList, * pCut, * pCutMin; int AreaBef = 0, AreaAft = 0; Of_ManComputeOutputRequired( p, 0 ); // compute area and edges p->pPars->Area = p->pPars->Edge = 0; Gia_ManForEachAndReverse( p->pGia, pObj, i ) { int CostMin, Cost, Required = Of_ObjRequired(p, i); if ( Gia_ObjIsBuf(pObj) ) { int FaninId = Gia_ObjFaninId0(pObj, i); Of_ObjUpdateRequired( p, FaninId, Required ); continue; } if ( !Of_ObjRefNum(p, i) ) continue; // deref best cut AreaBef = Of_CutDeref_rec( p, Of_ObjCutBestP(p, i) ); // select the best cut pCutMin = NULL; CostMin = ABC_INFINITY; pList = Of_ObjCutSet( p, i ); Of_SetForEachCut( pList, pCut, k ) { if ( Of_CutDelay1(pCut) > Required ) continue; Cost = Of_CutAreaDerefed2( p, pCut ); if ( CostMin > Cost ) { CostMin = Cost; pCutMin = pCut; } } // the cut is selected assert( pCutMin != NULL ); Of_ObjSetCutBestP( p, pList, i, pCutMin ); Of_CutForEachVar( pCutMin, iVar, k ) Of_ObjUpdateRequired( p, iVar, Required - DelayLut1 ); // ref best cut AreaAft = Of_CutRef_rec( p, pCutMin ); assert( AreaAft <= AreaBef ); // update parameters p->pPars->Edge += Of_CutSize(pCutMin); p->pPars->Area++; } } /**Function************************************************************* Synopsis [Technology mappping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Of_ManComputeForwardDirconCut( Of_Man_t * p, int iObj, int * pCut, int * pDelay1, int * pDelay2 ) { // Delay1 - main delay; Delay2 - precomputed LUT delay in terms of Delay1 for the fanins int Delays[6], Perm[6] = {0, 1, 2, 3, 4, 5}; int DelayLut1 = p->pPars->nDelayLut1; int DelayLut2 = p->pPars->nDelayLut2; int nSize = Of_CutSize(pCut); int k, iVar, Flag, SlowCon, Delay, DelayAfter, fDirConWorks; Of_CutForEachVar( pCut, iVar, k ) { Delays[k] = Of_ObjDelay1(p, iVar) + DelayLut1; // printf( "%3d%s ", iVar, Flag ? "*" : " " ); } for ( ; k < p->pPars->nLutSize; k++ ) { Delays[k] = -ABC_INFINITY; // printf( " " ); } Vec_IntSelectSortCost2Reverse( Perm, nSize, Delays ); assert( nSize < 2 || Delays[0] >= Delays[nSize-1] ); assert( Delays[0] >= 0 && Delays[nSize-1] >= 0 ); // consider speedup due to dircons fDirConWorks = 1; *pDelay1 = *pDelay2 = 0; SlowCon = p->pPars->nFastEdges < nSize ? Delays[p->pPars->nFastEdges] : 0; for ( k = 0; k < nSize; k++ ) { // use dircon if the following is true // - the input is eligible for dircon (does not exceed the limit) // - there is an expected gain in delay, compared the largest delay without dircon // - the dircon delay is indeed lower than the largest delay without dircon // - all previous dircons worked out well // - the node is an AND-gate iVar = Of_CutVar( pCut, Perm[k] ); assert( Delays[k] == Of_ObjDelay1(p, iVar) + DelayLut1 ); DelayAfter = Of_ObjDelay2(p, iVar) + DelayLut2; if ( k < p->pPars->nFastEdges && Delays[k] > SlowCon && DelayAfter < Delays[k] && fDirConWorks && Gia_ObjIsAndNotBuf(Gia_ManObj(p->pGia, iVar)) ) { Delay = DelayAfter; Of_CutSetFlag( pCut, Perm[k], 1 ); } else { Delay = Delays[k];// + DelayLut2; Of_CutSetFlag( pCut, Perm[k], 0 ); fDirConWorks = 0; } *pDelay1 = Abc_MaxInt( *pDelay1, Delay ); *pDelay2 = Abc_MaxInt( *pDelay2, Delays[k] ); } // printf( " %5.2f", Of_Int2Flt(*pDelay1) ); // printf( " %5.2f\n", Of_Int2Flt(*pDelay2) ); // do not use the structure if simple LUT is better if ( *pDelay1 > *pDelay2 ) { for ( k = 0; k < nSize; k++ ) Of_CutSetFlag( pCut, k, 0 ); *pDelay1 = *pDelay2; } assert( *pDelay1 <= *pDelay2 ); Of_CutSetDelay1( pCut, *pDelay1 ); Of_CutSetDelay2( pCut, *pDelay2 ); // verify Of_CutForEachVarFlag( pCut, iVar, Flag, k ) { if ( Flag ) assert( Of_ObjDelay2(p, iVar) + DelayLut2 <= *pDelay1 ); else assert( Of_ObjDelay1(p, iVar) + DelayLut1 <= *pDelay1 ); assert( Of_ObjDelay1(p, iVar) + DelayLut1 <= *pDelay2 ); } } int Of_ManComputeForwardDirconObj( Of_Man_t * p, int iObj ) { int Delay1 = ABC_INFINITY, Delay2 = ABC_INFINITY; int i, * pCut, * pCutMin = NULL, * pCutMin2 = NULL, * pList = Of_ObjCutSet(p, iObj); Of_SetForEachCut( pList, pCut, i ) { int Delay1This, Delay2This; Of_ManComputeForwardDirconCut( p, iObj, pCut, &Delay1This, &Delay2This ); if ( Delay1 > Delay1This ) pCutMin = pCut; if ( Delay2 > Delay2This ) pCutMin2 = pCut; Delay1 = Abc_MinInt( Delay1, Delay1This ); Delay2 = Abc_MinInt( Delay2, Delay2This ); } Of_ObjSetDelay1( p, iObj, Delay1 ); Of_ObjSetDelay2( p, iObj, Delay2 ); Of_ObjSetCutBestP( p, pList, iObj, pCutMin ); Of_ObjSetCutBestP2( p, pList, iObj, pCutMin2 ); return Delay1; } void Of_ManComputeForwardDircon1( Of_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachAnd( p->pGia, pObj, i ) if ( Gia_ObjIsBuf(pObj) ) { Of_ObjSetDelay1( p, i, Of_ObjDelay1(p, Gia_ObjFaninId0(pObj, i)) ); Of_ObjSetDelay2( p, i, Of_ObjDelay2(p, Gia_ObjFaninId0(pObj, i)) ); } else Of_ManComputeForwardDirconObj( p, i ); } void Of_ManComputeBackwardDircon1( Of_Man_t * p ) { Gia_Obj_t * pObj; Vec_Bit_t * vPointed; int DelayLut1 = p->pPars->nDelayLut1; int DelayLut2 = p->pPars->nDelayLut2; int i, k, iVar, Flag, * pList, * pCutMin; int CountNodes = 0, CountEdges = 0; Of_ManComputeOutputRequired( p, 1 ); printf( "Global delay =%8.2f\n", Of_Int2Flt((int)p->pPars->Delay) ); //return; // compute area and edges vPointed = Vec_BitStart( Gia_ManObjNum(p->pGia) ); p->pPars->Area = p->pPars->Edge = 0; Gia_ManForEachAndReverse( p->pGia, pObj, i ) { int CostMin, fPointed, Required = Of_ObjRequired(p, i); if ( Gia_ObjIsBuf(pObj) ) { int FaninId = Gia_ObjFaninId0(pObj, i); Of_ObjUpdateRequired( p, FaninId, Required ); Of_ObjRefInc( p, FaninId ); continue; } if ( !Of_ObjRefNum(p, i) ) continue; // check if the LUT is has an outgoing dircon edge fPointed = Vec_BitEntry(vPointed, i); CountNodes += fPointed; /* // select the best cut { int * pCut; pCutMin = NULL; CostMin = ABC_INFINITY; pList = Of_ObjCutSet( p, i ); Of_SetForEachCut( pList, pCut, k ) { int Cost; if ( (fPointed ? Of_CutDelay2(pCut) : Of_CutDelay1(pCut)) > Required ) continue; Cost = Of_ManComputeBackwardCut( p, pCut ); if ( CostMin > Cost ) { CostMin = Cost; pCutMin = pCut; } } } */ if ( fPointed ) { pCutMin = Of_ObjCutBestP2( p, i ); CostMin = Of_CutDelay2(pCutMin); //assert( Of_CutDelay2(pCutMin) <= Required ); } else { pCutMin = Of_ObjCutBestP( p, i ); CostMin = Of_CutDelay1(pCutMin); //assert( Of_CutDelay1(pCutMin) <= Required ); } // remove dircon markers //if ( fPointed ) // Of_CutForEachVarFlag( pCutMin, iVar, Flag, k ) // Of_CutSetFlag( pCutMin, k, 0 ); // the cut is selected assert( pCutMin != NULL ); pList = Of_ObjCutSet( p, i ); Of_ObjSetCutBestP( p, pList, i, pCutMin ); ///// SET THE BEST CUT Of_CutForEachVarFlag( pCutMin, iVar, Flag, k ) { Of_ObjUpdateRequired( p, iVar, Required - ((Flag && !fPointed) ? DelayLut2 : DelayLut1) ); Of_ObjRefInc( p, iVar ); if ( Flag && !fPointed ) { Vec_BitWriteEntry( vPointed, iVar, 1 ); CountEdges++; } } // update parameters p->pPars->Edge += Of_CutSize(pCutMin); p->pPars->Area++; } Vec_BitFree( vPointed ); //printf( "Dircon nodes = %d. Dircon edges = %d.\n", CountNodes, CountEdges ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Of_ManCreateSat( Of_Man_t * p, int nCutsAll, Vec_Int_t * vFirst, Vec_Int_t * vCutNum, Vec_Int_t * vBestNode, Vec_Int_t * vBestCut ) { extern void Cnf_AddCardinConstrPairWise( sat_solver * p, Vec_Int_t * vVars, int K, int fStrict ); Gia_Obj_t * pObj, * pVar; int * pCutSet, * pCut; int i, k, v, c, Var, Lit, pLits[2], status, RetValue, nCutCount, nClauses; Vec_Int_t * vLits = Vec_IntAlloc( 100 ); abctime clk = Abc_Clock(); // start solver sat_solver * pSat = sat_solver_new(); sat_solver_setnvars( pSat, Gia_ManAndNum(p->pGia) + nCutsAll ); // set polarity Vec_IntAppend( vBestNode, vBestCut ); //Vec_IntPrint( vBestNode ); sat_solver_set_polarity( pSat, Vec_IntArray(vBestNode), Vec_IntSize(vBestNode) ); Vec_IntShrink( vBestNode, Vec_IntSize(vBestNode) - Vec_IntSize(vBestCut) ); // add clauses for nodes Gia_ManForEachAnd( p->pGia, pObj, i ) { int iFirst = Vec_IntEntry(vFirst, i); int nCuts = Vec_IntEntry(vCutNum, i); Vec_IntClear( vLits ); Vec_IntPush( vLits, Abc_Var2Lit(pObj->Value, 1) ); for ( c = 0; c < nCuts; c++ ) Vec_IntPush( vLits, Abc_Var2Lit(iFirst + c, 0) ); RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits) ); assert( RetValue ); } // add clauses for cuts nCutCount = 0; Gia_ManForEachAnd( p->pGia, pObj, i ) { pCutSet = Of_ObjCutSet(p, i); Of_SetForEachCut( pCutSet, pCut, k ) { pLits[0] = Abc_Var2Lit( Gia_ManAndNum(p->pGia) + nCutCount, 1 ); pLits[1] = Abc_Var2Lit( pObj->Value, 0 ); RetValue = sat_solver_addclause( pSat, pLits, pLits+2 ); assert( RetValue ); Of_CutForEachVar( pCut, Var, v ) { pVar = Gia_ManObj(p->pGia, Var); if ( !Gia_ObjIsAnd(pVar) ) continue; pLits[1] = Abc_Var2Lit( pVar->Value, 0 ); RetValue = sat_solver_addclause( pSat, pLits, pLits+2 ); assert( RetValue ); } nCutCount++; } } assert( nCutCount == nCutsAll ); // mark CO drivers Gia_ManForEachCo( p->pGia, pObj, i ) Gia_ObjFanin0(pObj)->fMark0 = 1; // set used nodes to 1 Gia_ManForEachAnd( p->pGia, pObj, i ) if ( pObj->fMark0 ) { Lit = Abc_Var2Lit( pObj->Value, 0 ); RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); assert( RetValue ); } // unmark CO drivers Gia_ManForEachCo( p->pGia, pObj, i ) Gia_ObjFanin0(pObj)->fMark0 = 0; // Sat_SolverWriteDimacs( pSat, "temp.cnf", NULL, NULL, 0 ); // add cardinality constraint nClauses = pSat->stats.clauses; Vec_IntClear( vLits ); Vec_IntFillNatural( vLits, Gia_ManAndNum(p->pGia) ); Cnf_AddCardinConstrPairWise( pSat, vLits, Vec_IntSize(vBestNode)-2, 0 ); printf( "Problem clauses = %d. Cardinality clauses = %d.\n", nClauses, pSat->stats.clauses - nClauses ); // solve the problem status = sat_solver_solve( pSat, NULL, NULL, 1000000, 0, 0, 0 ); if ( status == l_Undef ) printf( "Undecided. " ); if ( status == l_True ) printf( "Satisfiable. " ); if ( status == l_False ) printf( "Unsatisfiable. " ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); Sat_SolverPrintStats( stdout, pSat ); if ( status == l_True ) { int nOnes = 0; for ( v = 0; v < Gia_ManAndNum(p->pGia); v++ ) { printf( "%d", sat_solver_var_value(pSat, v) ); nOnes += sat_solver_var_value(pSat, v); } printf( " Nodes = %d\n", nOnes ); nOnes = 0; for ( ; v < Gia_ManAndNum(p->pGia) + nCutsAll; v++ ) { printf( "%d", sat_solver_var_value(pSat, v) ); nOnes += sat_solver_var_value(pSat, v); } printf( " LUTs = %d\n", nOnes ); } // cleanup sat_solver_delete( pSat ); Vec_IntFree( vLits ); } void Of_ManPrintCuts( Of_Man_t * p ) { int fVerbose = 0; Gia_Obj_t * pObj; int * pCutSet, * pCut, * pCutBest; int i, k, v, Var, nCuts; Vec_Int_t * vFirst = Vec_IntStartFull( Gia_ManObjNum(p->pGia) ); Vec_Int_t * vCutNum = Vec_IntStartFull( Gia_ManObjNum(p->pGia) ); Vec_Int_t * vBestNode = Vec_IntAlloc( 100 ); Vec_Int_t * vBestCut = Vec_IntAlloc( 100 ); int nAndsAll = 0, nCutsAll = 0, Shift = Gia_ManAndNum(p->pGia); Gia_ManFillValue( p->pGia ); Gia_ManForEachAnd( p->pGia, pObj, i ) { // get the best cut pCutBest = NULL; if ( Of_ObjRefNum(p, i) ) { Vec_IntPush( vBestNode, nAndsAll ); pCutBest = Of_ObjCutBestP( p, i ); } pObj->Value = nAndsAll++; // get the cutset pCutSet = Of_ObjCutSet(p, i); // count cuts nCuts = 0; Of_SetForEachCut( pCutSet, pCut, k ) nCuts++; // save Vec_IntWriteEntry( vFirst, i, Shift + nCutsAll ); Vec_IntWriteEntry( vCutNum, i, nCuts ); // print cuts if ( fVerbose ) printf( "Node %d. Cuts %d.\n", i, nCuts ); Of_SetForEachCut( pCutSet, pCut, k ) { if ( fVerbose ) { printf( "{ " ); Of_CutForEachVar( pCut, Var, v ) printf( "%d ", Var ); printf( "} %s\n", pCutBest == pCut ? "best" :"" ); } if ( pCutBest == pCut ) Vec_IntPush( vBestCut, Shift + nCutsAll ); nCutsAll++; } } assert( nAndsAll == Shift ); printf( "Total: Ands = %d. Luts = %d. Cuts = %d.\n", nAndsAll, Vec_IntSize(vBestNode), nCutsAll ); // create SAT problem Of_ManCreateSat( p, nCutsAll, vFirst, vCutNum, vBestNode, vBestCut ); Vec_IntFree( vFirst ); Vec_IntFree( vCutNum ); Vec_IntFree( vBestNode ); Vec_IntFree( vBestCut ); } /**Function************************************************************* Synopsis [Technology mappping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Of_ManSetDefaultPars( Jf_Par_t * pPars ) { memset( pPars, 0, sizeof(Jf_Par_t) ); pPars->nLutSize = 4; pPars->nCutNum = 16; pPars->nProcNum = 0; pPars->nRounds = 3; pPars->nRoundsEla = 4; pPars->nRelaxRatio = 0; pPars->nCoarseLimit = 3; pPars->nAreaTuner = 10; pPars->DelayTarget = -1; pPars->nDelayLut1 = 10; pPars->nDelayLut2 = 2; pPars->nFastEdges = 0; // pPars->fAreaOnly = 0; pPars->fOptEdge = 1; pPars->fCoarsen = 0; pPars->fCutMin = 0; pPars->fGenCnf = 0; pPars->fPureAig = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; pPars->nLutSizeMax = OF_LEAF_MAX; pPars->nCutNumMax = OF_CUT_MAX; pPars->MapDelayTarget = -1; } Gia_Man_t * Of_ManDeriveMapping( Of_Man_t * p ) { Vec_Int_t * vMapping, * vPacking = NULL; Vec_Bit_t * vPointed; int i, k, iVar, * pCut, Place, Flag; assert( !p->pPars->fCutMin && p->pGia->vMapping == NULL ); vMapping = Vec_IntAlloc( Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); Vec_IntFill( vMapping, Gia_ManObjNum(p->pGia), 0 ); if ( p->pPars->nFastEdges ) { vPacking = Vec_IntAlloc( 1000 ); Vec_IntPush( vPacking, 0 ); } vPointed = Vec_BitStart( Gia_ManObjNum(p->pGia) ); Gia_ManForEachAndId( p->pGia, i ) { if ( !Of_ObjRefNum(p, i) ) continue; assert( !Gia_ObjIsBuf(Gia_ManObj(p->pGia,i)) ); pCut = Of_ObjCutBestP( p, i ); Vec_IntWriteEntry( vMapping, i, Vec_IntSize(vMapping) ); Vec_IntPush( vMapping, Of_CutSize(pCut) ); Of_CutForEachVar( pCut, iVar, k ) Vec_IntPush( vMapping, iVar ); Vec_IntPush( vMapping, i ); if ( vPacking == NULL || Vec_BitEntry(vPointed, i) ) continue; Place = Vec_IntSize( vPacking ); Vec_IntPush( vPacking, 0 ); Vec_IntPush( vPacking, i ); Of_CutForEachVarFlag( pCut, iVar, Flag, k ) if ( Flag ) { Vec_IntPush( vPacking, iVar ); Vec_BitWriteEntry( vPointed, iVar, 1 ); } Vec_IntAddToEntry( vPacking, Place, Vec_IntSize(vPacking)-Place-1 ); Vec_IntAddToEntry( vPacking, 0, 1 ); } assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); p->pGia->vMapping = vMapping; p->pGia->vPacking = vPacking; Vec_BitFree( vPointed ); return p->pGia; } Gia_Man_t * Of_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) { Gia_Man_t * pNew = NULL, * pCls; Of_Man_t * p; int i, Id; if ( Gia_ManHasChoices(pGia) ) pPars->fCoarsen = 0, pPars->fCutMin = 1; pCls = pPars->fCoarsen ? Gia_ManDupMuxes(pGia, pPars->nCoarseLimit) : pGia; p = Of_StoCreate( pCls, pPars ); if ( pPars->fVerbose && pPars->fCoarsen ) { printf( "Initial " ); Gia_ManPrintMuxStats( pGia ); printf( "\n" ); printf( "Derived " ); Gia_ManPrintMuxStats( pCls ); printf( "\n" ); } Of_ManPrintInit( p ); Of_ManComputeCuts( p ); Of_ManPrintQuit( p ); Gia_ManForEachCiId( p->pGia, Id, i ) { int Time = Of_Flt2Int(p->pGia->vInArrs ? Abc_MaxFloat(0.0, Vec_FltEntry(p->pGia->vInArrs, i)) : 0.0); Of_ObjSetDelay1( p, Id, Time ); Of_ObjSetDelay2( p, Id, Time ); } if ( p->pPars->nFastEdges ) { p->pPars->nRounds = 1; for ( p->Iter = 0; p->Iter < p->pPars->nRounds; p->Iter++ ) { if ( p->Iter == 0 ) { Of_ManComputeForwardDircon1( p ); Of_ManComputeBackwardDircon1( p ); Of_ManPrintStats( p, "Delay" ); } else { Of_ManComputeForwardDircon1( p ); Of_ManComputeBackwardDircon1( p ); Of_ManPrintStats( p, "Flow " ); } } } else { for ( p->Iter = 0; p->Iter < p->pPars->nRounds; p->Iter++ ) { if ( p->Iter == 0 ) { Of_ManComputeForward1( p ); Of_ManComputeBackward1( p ); Of_ManPrintStats( p, "Delay" ); } else { Of_ManComputeForward1( p ); Of_ManComputeBackward1( p ); Of_ManPrintStats( p, "Flow " ); } } for ( ; p->Iter < p->pPars->nRounds + p->pPars->nRoundsEla; p->Iter++ ) { if ( p->Iter < p->pPars->nRounds + p->pPars->nRoundsEla - 1 ) { Of_ManComputeForward2( p ); Of_ManComputeBackward3( p ); Of_ManPrintStats( p, "Area " ); } else { Of_ManComputeForward1( p ); Of_ManComputeBackward3( p ); Of_ManPrintStats( p, "Area " ); } } } pNew = Of_ManDeriveMapping( p ); Gia_ManMappingVerify( pNew ); if ( pNew->vPacking ) Gia_ManConvertPackingToEdges( pNew ); //Of_ManPrintCuts( p ); Of_StoDelete( p ); if ( pCls != pGia ) Gia_ManStop( pCls ); if ( pNew == NULL ) return Gia_ManDup( pGia ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaPack.c000066400000000000000000000156331477524141600160020ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaPack.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [LUT packing.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaPack.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collects LUT nodes in the increasing order of distance from COs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManLutCollect2( Gia_Man_t * p ) { Gia_Obj_t * pObj; Vec_Int_t * vOrder; int i, k, Id, iFan; vOrder = Vec_IntAlloc( Gia_ManLutNum(p) ); Gia_ManIncrementTravId( p ); Gia_ManForEachCoDriver( p, pObj, i ) { if ( !Gia_ObjIsAnd(pObj) ) continue; Id = Gia_ObjId( p, pObj ); assert( Gia_ObjIsLut(p, Id) ); if ( Gia_ObjIsTravIdCurrentId(p, Id) ) continue; Gia_ObjSetTravIdCurrentId(p, Id); Vec_IntPush( vOrder, Id ); } Vec_IntForEachEntry( vOrder, Id, i ) { Gia_LutForEachFanin( p, Id, iFan, k ) { if ( !Gia_ObjIsAnd(Gia_ManObj(p, iFan)) ) continue; assert( Gia_ObjIsLut(p, iFan) ); if ( Gia_ObjIsTravIdCurrentId(p, iFan) ) continue; Gia_ObjSetTravIdCurrentId(p, iFan); Vec_IntPush( vOrder, iFan ); } } assert( Vec_IntCap(vOrder) == 16 || Vec_IntSize(vOrder) == Vec_IntCap(vOrder) ); Vec_IntReverseOrder( vOrder ); return vOrder; } Vec_Int_t * Gia_ManLutCollect( Gia_Man_t * p ) { Vec_Int_t * vLuts, * vDist, * vOrder; int i, k, Id, iFan, * pPerm; // collect LUTs vLuts = Vec_IntAlloc( Gia_ManAndNum(p) ); Gia_ManForEachLut( p, Id ) Vec_IntPush( vLuts, Id ); // propagate distance vDist = Vec_IntStart( Gia_ManObjNum(p) ); Gia_ManForEachCoDriverId( p, Id, i ) Vec_IntWriteEntry( vDist, Id, 1 ); Vec_IntForEachEntryReverse( vLuts, Id, i ) { int Dist = 1 + Vec_IntEntry(vDist, Id); Gia_LutForEachFanin( p, Id, iFan, k ) Vec_IntUpdateEntry( vDist, iFan, Dist ); } // sort LUTs by distance k = 0; Vec_IntForEachEntry( vLuts, Id, i ) Vec_IntWriteEntry( vDist, k++, -Vec_IntEntry(vDist, Id) ); Vec_IntShrink( vDist, k ); pPerm = Abc_MergeSortCost( Vec_IntArray(vDist), Vec_IntSize(vDist) ); // collect vOrder = Vec_IntAlloc( Vec_IntSize(vLuts) ); for ( i = 0; i < Vec_IntSize(vLuts); i++ ) Vec_IntPush( vOrder, Vec_IntEntry(vLuts, pPerm[i]) ); Vec_IntFree( vDist ); Vec_IntFree( vLuts ); ABC_FREE( pPerm ); return vOrder; } /**Function************************************************************* Synopsis [LUT packing algorithm.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManLutPacking( Gia_Man_t * p, int nBlockSize, int DelayRoute, int DelayDir, int fVerbose ) { int Delays[32], Perm[32]; Vec_Int_t * vPacking, * vStarts; Vec_Int_t * vOrder = Gia_ManLutCollect( p ); Vec_Int_t * vDelay = Vec_IntStart( Gia_ManObjNum(p) ); Vec_Int_t * vBlock = Vec_IntStart( Gia_ManObjNum(p) ); Vec_Int_t * vBSize = Vec_IntAlloc( 2 * Vec_IntSize(vOrder) / nBlockSize ); int i, k, Id, iFan, nSize, iBlock, Delay, DelayMax = 0; // create blocks Vec_IntForEachEntry( vOrder, Id, i ) { nSize = Gia_ObjLutSize( p, Id ); assert( nSize <= 32 ); Gia_LutForEachFanin( p, Id, iFan, k ) { Delays[k] = Vec_IntEntry(vDelay, iFan); Perm[k] = iFan; } Vec_IntSelectSortCost2Reverse( Perm, nSize, Delays ); assert( nSize < 2 || Delays[0] >= Delays[nSize-1] ); assert( Delays[0] >= 0 && Delays[nSize-1] >= 0 ); // check if we can reduce delay by adding it to the same bin as the latest one iBlock = Vec_IntEntry( vBlock, Perm[0] ); if ( Delays[0] > 0 && Delays[0] > Delays[1] && Vec_IntEntry(vBSize, iBlock) < nBlockSize ) { Delay = Delays[0] + DelayDir; Vec_IntWriteEntry( vBlock, Id, iBlock ); Vec_IntAddToEntry( vBSize, iBlock, 1 ); } else // clean new block { Delay = Delays[0] + DelayRoute; Vec_IntWriteEntry( vBlock, Id, Vec_IntSize(vBSize) ); Vec_IntPush( vBSize, 1 ); } // calculate delay for ( k = 1; k < nSize; k++ ) Delay = Abc_MaxInt( Delay, Delays[k] + DelayRoute ); Vec_IntWriteEntry( vDelay, Id, Delay ); DelayMax = Abc_MaxInt( DelayMax, Delay ); } assert( Vec_IntSum(vBSize) == Vec_IntSize(vOrder) ); // create packing info vPacking = Vec_IntAlloc( Vec_IntSize(vBSize) + Vec_IntSize(vOrder) + 1 ); Vec_IntPush( vPacking, Vec_IntSize(vBSize) ); // create starting places for each block vStarts = Vec_IntAlloc( Vec_IntSize(vBSize) ); Vec_IntForEachEntry( vBSize, nSize, i ) { Vec_IntPush( vPacking, nSize ); Vec_IntPush( vStarts, Vec_IntSize(vPacking) ); Vec_IntFillExtra( vPacking, Vec_IntSize(vPacking) + nSize, -1 ); } assert( Vec_IntCap(vPacking) == 16 || Vec_IntSize(vPacking) == Vec_IntCap(vPacking) ); // collect LUTs from the block Vec_IntForEachEntryReverse( vOrder, Id, i ) { int Block = Vec_IntEntry( vBlock, Id ); int Start = Vec_IntEntry( vStarts, Block ); assert( Vec_IntEntry(vPacking, Start) == -1 ); Vec_IntWriteEntry( vPacking, Start, Id ); Vec_IntAddToEntry( vStarts, Block, 1 ); } assert( Vec_IntCountEntry(vPacking, -1) == 0 ); // cleanup Vec_IntFree( vOrder ); Vec_IntFree( vDelay ); Vec_IntFree( vBlock ); Vec_IntFree( vBSize ); Vec_IntFree( vStarts ); Vec_IntFreeP( &p->vPacking ); p->vPacking = vPacking; printf( "Global delay = %d.\n", DelayMax ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaPat.c000066400000000000000000000110021477524141600156320ustar00rootroot00000000000000/**CFile**************************************************************** FileName [gia.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 /// //////////////////////////////////////////////////////////////////////// static inline int Sat_ObjXValue( Gia_Obj_t * pObj ) { return (pObj->fMark1 << 1) | pObj->fMark0; } static inline void Sat_ObjSetXValue( Gia_Obj_t * pObj, int v) { pObj->fMark0 = (v & 1); pObj->fMark1 = ((v >> 1) & 1); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collects nodes in the cone and initialized them to x.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_SatCollectCone_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vVisit ) { if ( Sat_ObjXValue(pObj) == GIA_UND ) return; if ( Gia_ObjIsAnd(pObj) ) { Gia_SatCollectCone_rec( p, Gia_ObjFanin0(pObj), vVisit ); Gia_SatCollectCone_rec( p, Gia_ObjFanin1(pObj), vVisit ); } assert( Sat_ObjXValue(pObj) == 0 ); Sat_ObjSetXValue( pObj, GIA_UND ); Vec_IntPush( vVisit, Gia_ObjId(p, pObj) ); } /**Function************************************************************* Synopsis [Collects nodes in the cone and initialized them to x.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_SatCollectCone( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vVisit ) { assert( !Gia_IsComplement(pObj) ); assert( !Gia_ObjIsConst0(pObj) ); assert( Sat_ObjXValue(pObj) == 0 ); Vec_IntClear( vVisit ); Gia_SatCollectCone_rec( p, pObj, vVisit ); } /**Function************************************************************* Synopsis [Checks if the counter-examples asserts the output.] Description [Assumes that fMark0 and fMark1 are clean. Leaves them clean.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_SatVerifyPattern( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vCex, Vec_Int_t * vVisit ) { Gia_Obj_t * pObj; int i, Entry, Value, Value0, Value1; assert( Gia_ObjIsCo(pRoot) ); assert( !Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) ); // collect nodes and initialized them to x Gia_SatCollectCone( p, Gia_ObjFanin0(pRoot), vVisit ); // set binary values to nodes in the counter-example Vec_IntForEachEntry( vCex, Entry, i ) // Sat_ObjSetXValue( Gia_ManObj(p, Abc_Lit2Var(Entry)), Abc_LitIsCompl(Entry)? GIA_ZER : GIA_ONE ); Sat_ObjSetXValue( Gia_ManCi(p, Abc_Lit2Var(Entry)), Abc_LitIsCompl(Entry)? GIA_ZER : GIA_ONE ); // simulate Gia_ManForEachObjVec( vVisit, p, pObj, i ) { if ( Gia_ObjIsCi(pObj) ) continue; assert( Gia_ObjIsAnd(pObj) ); Value0 = Sat_ObjXValue( Gia_ObjFanin0(pObj) ); Value1 = Sat_ObjXValue( Gia_ObjFanin1(pObj) ); Value = Gia_XsimAndCond( Value0, Gia_ObjFaninC0(pObj), Value1, Gia_ObjFaninC1(pObj) ); Sat_ObjSetXValue( pObj, Value ); } Value = Sat_ObjXValue( Gia_ObjFanin0(pRoot) ); Value = Gia_XsimNotCond( Value, Gia_ObjFaninC0(pRoot) ); if ( Value != GIA_ONE ) printf( "Gia_SatVerifyPattern(): Verification FAILED.\n" ); // else // printf( "Gia_SatVerifyPattern(): Verification succeeded.\n" ); // assert( Value == GIA_ONE ); // clean the nodes Gia_ManForEachObjVec( vVisit, p, pObj, i ) Sat_ObjSetXValue( pObj, 0 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaPat2.c000066400000000000000000001627431477524141600157370ustar00rootroot00000000000000/**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); int iLit0, iLit1; if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); Min_ManFromGia_rec( pNew, p, Gia_ObjFaninId0(pObj, iObj) ); Min_ManFromGia_rec( pNew, p, Gia_ObjFaninId1(pObj, iObj) ); iLit0 = Gia_ObjFanin0Copy(pObj); iLit1 = Gia_ObjFanin1Copy(pObj); pObj->Value = Min_ManAppendObj( pNew, Abc_MinInt(iLit0, iLit1), Abc_MaxInt(iLit0, iLit1) ); } Min_Man_t * Min_ManFromGia( Gia_Man_t * p, Vec_Int_t * vOuts ) { 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_ObjFanin0Copy(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); Val1 = Min_LitValL(p, iLit1); } 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); Val1 = Min_LitValL(p, iLit1); } 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); Val1 = Min_LitValL(p, iLit1); } 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); Val1 = Min_LitValL(p, iLit1); } 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; { assert( Gia_ObjIsCo(pObj) ); if ( Gia_ObjFaninId0p(p, pObj) == 0 ) { if ( fVerbose ) printf( "Output %d is driven by constant %d.\n", Gia_ObjCioId(pObj), Gia_ObjFaninC0(pObj) ); 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 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_GenerateCexesDumpBlif( char * pFileName, Gia_Man_t * p, Vec_Wec_t * vCexes ) { extern Vec_Ptr_t * Gia_GetFakeNames( int nNames, int fCaps ); FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file name \"%s\".\n", pFileName ); return; } int fFakeIns = 0, fFakeOuts = 0; if ( p->vNamesIn == NULL ) p->vNamesIn = Gia_GetFakeNames( Gia_ManCiNum(p), 0 ), fFakeIns = 1; if ( p->vNamesOut == NULL ) p->vNamesOut = Gia_GetFakeNames( Gia_ManCoNum(p), 1 ), fFakeOuts = 1; Gia_Obj_t * pObj, * pObj2; char * pLine = ABC_CALLOC( char, Gia_ManCiNum(p)+3 ); int i, k, c, iLit, nOuts[2] = {0}, nCexes = Vec_WecSize(vCexes) / Gia_ManCoNum(p); fprintf( pFile, "# Satisfying assignments for the primary outputs generated by ABC on %s\n", Gia_TimeStamp() ); fprintf( pFile, ".model %s\n", p->pName ); fprintf( pFile, ".inputs" ); Gia_ManForEachCi( p, pObj, i ) fprintf( pFile, " %s", Gia_ObjCiName(p, i) ); fprintf( pFile, "\n.outputs" ); Gia_ManForEachCo( p, pObj, i ) fprintf( pFile, " %s", Gia_ObjCoName(p, i) ); fprintf( pFile, "\n" ); Gia_ManForEachCo( p, pObj, i ) { if ( Gia_ObjFaninLit0p(p, pObj) == 0 ) { fprintf( pFile, ".names %s\n", Gia_ObjCoName(p, i) ); nOuts[0]++; } else if ( Gia_ObjFaninLit0p(p, pObj) == 1 ) { fprintf( pFile, ".names %s\n 1\n", Gia_ObjCiName(p, i) ); nOuts[1]++; } else { fprintf( pFile, ".names" ); Gia_ManForEachCi( p, pObj2, c ) fprintf( pFile, " %s", Gia_ObjCiName(p, c) ); fprintf( pFile, " %s\n", Gia_ObjCoName(p, i) ); for ( c = 0; c < nCexes; c++ ) { Vec_Int_t * vPat = Vec_WecEntry( vCexes, i*nCexes+c ); memset(pLine, '-', Gia_ManCiNum(p) ); Vec_IntForEachEntry( vPat, iLit, k ) pLine[Abc_Lit2Var(iLit)-1] = '1' - Abc_LitIsCompl(iLit); fprintf( pFile, "%s 1\n", pLine ); } nOuts[1]++; } } fprintf( pFile, ".end\n\n" ); fclose( pFile ); printf( "Information about %d sat, %d unsat, and %d undecided primary outputs was written into BLIF file \"%s\".\n", nOuts[1], nOuts[0], Gia_ManCoNum(p)-nOuts[1]-nOuts[0], pFileName ); free( pLine ); if ( fFakeIns ) Vec_PtrFreeFree( p->vNamesIn ), p->vNamesIn = NULL; if ( fFakeOuts ) Vec_PtrFreeFree( p->vNamesOut ), p->vNamesOut = NULL; } void Gia_GenerateCexesDumpFile( char * pFileName, Gia_Man_t * p, Vec_Wec_t * vCexes, int fShort ) { FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file name \"%s\".\n", pFileName ); return; } Gia_Obj_t * pObj; char * pLine = ABC_CALLOC( char, Gia_ManCiNum(p)+3 ); int i, k, c, iLit, nOuts[2] = {0}, nCexes = Vec_WecSize(vCexes) / Gia_ManCoNum(p); Gia_ManForEachCo( p, pObj, i ) { if ( Gia_ObjFaninLit0p(p, Gia_ManCo(p, i)) == 0 ) { fprintf( pFile, "%d : unsat\n", i ); nOuts[0]++; } else if ( fShort ) { for ( c = 0; c < nCexes; c++ ) { Vec_Int_t * vPat = Vec_WecEntry( vCexes, i*nCexes+c ); fprintf( pFile, "%d :", i ); if ( Vec_IntSize(vPat) == 0 ) fprintf( pFile, " not available" ); else Vec_IntForEachEntry( vPat, iLit, k ) fprintf( pFile, " %d", iLit ); fprintf( pFile, "\n" ); } nOuts[1]++; } else { for ( c = 0; c < nCexes; c++ ) { Vec_Int_t * vPat = Vec_WecEntry( vCexes, i*nCexes+c ); memset(pLine, '-', Gia_ManCiNum(p) ); Vec_IntForEachEntry( vPat, iLit, k ) pLine[Abc_Lit2Var(iLit)-1] = '1' - Abc_LitIsCompl(iLit); fprintf( pFile, "%d : %s\n", i, pLine ); } nOuts[1]++; } } printf( "Information about %d sat, %d unsat, and %d undecided primary outputs was written into file \"%s\".\n", nOuts[1], nOuts[0], Gia_ManCoNum(p)-nOuts[1]-nOuts[0], pFileName ); fclose( pFile ); free( pLine ); } void Gia_GenerateCexes( char * pFileName, Gia_Man_t * p, int nMaxTries, int nMinCexes, int fUseSim, int fUseSat, int fShort, int fBlif, int fVerbose, int fVeryVerbose ) { unsigned Start = Abc_Random(1); Vec_Int_t * vStats[3] = {0}; int i; Vec_Wec_t * vCexes = Min_ManComputeCexes( p, NULL, nMaxTries, nMinCexes, vStats, fUseSim, fUseSat, fVerbose ); assert( Vec_WecSize(vCexes) == Gia_ManCoNum(p) * nMinCexes ); if ( fBlif ) Gia_GenerateCexesDumpBlif( pFileName, p, vCexes ); else Gia_GenerateCexesDumpFile( pFileName, p, vCexes, fShort ); for ( i = 0; i < 3; i++ ) Vec_IntFreeP( &vStats[i] ); Vec_WecFree( vCexes ); Start = 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaPf.c000066400000000000000000001432501477524141600154660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaNf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Standard-cell mapper.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaNf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "gia.h" #include "misc/st/st.h" #include "map/mio/mio.h" #include "misc/util/utilTruth.h" #include "misc/extra/extra.h" #include "base/main/main.h" #include "misc/vec/vecMem.h" #include "misc/vec/vecWec.h" #include "opt/dau/dau.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define PF_LEAF_MAX 6 #define PF_CUT_MAX 32 #define PF_NO_LEAF 31 #define PF_NO_FUNC 0x3FFFFFF #define PF_INFINITY FLT_MAX typedef struct Pf_Cut_t_ Pf_Cut_t; struct Pf_Cut_t_ { word Sign; // signature int Delay; // delay float Flow; // flow unsigned iFunc : 26; // function (PF_NO_FUNC) unsigned Useless : 1; // function unsigned nLeaves : 5; // leaf number (PF_NO_LEAF) int pLeaves[PF_LEAF_MAX+1]; // leaves }; typedef struct Pf_Mat_t_ Pf_Mat_t; struct Pf_Mat_t_ { unsigned fCompl : 8; // complemented unsigned Phase : 6; // match phase unsigned Perm : 18; // match permutation }; typedef struct Pf_Obj_t_ Pf_Obj_t; struct Pf_Obj_t_ { float Area; unsigned Gate : 7; // gate unsigned nLeaves : 3; // fanin count unsigned nRefs : 22; // ref count int pLeaves[6]; // leaf literals }; typedef struct Pf_Man_t_ Pf_Man_t; struct Pf_Man_t_ { // user data Gia_Man_t * pGia; // derived manager Jf_Par_t * pPars; // parameters // matching Vec_Mem_t * vTtMem; // truth tables Vec_Wec_t * vTt2Match; // matches for truth tables Mio_Cell_t * pCells; // library gates int nCells; // library gate count // cut data Pf_Obj_t * pPfObjs; // best cuts Vec_Ptr_t vPages; // cut memory Vec_Int_t vCutSets; // cut offsets Vec_Flt_t vCutFlows; // temporary cut area Vec_Int_t vCutDelays; // temporary cut delay int iCur; // current position int Iter; // mapping iterations int fUseEla; // use exact area int nInvs; // the inverter count float InvDelay; // inverter delay float InvArea; // inverter area // statistics abctime clkStart; // starting time double CutCount[6]; // cut counts int nCutUseAll; // objects with useful cuts }; static inline int Pf_Mat2Int( Pf_Mat_t Mat ) { union { int x; Pf_Mat_t y; } v; v.y = Mat; return v.x; } static inline Pf_Mat_t Pf_Int2Mat( int Int ) { union { int x; Pf_Mat_t y; } v; v.x = Int; return v.y; } static inline Pf_Obj_t * Pf_ManObj( Pf_Man_t * p, int i ) { return p->pPfObjs + i; } static inline Mio_Cell_t* Pf_ManCell( Pf_Man_t * p, int i ) { return p->pCells + i; } static inline int * Pf_ManCutSet( Pf_Man_t * p, int i ) { return (int *)Vec_PtrEntry(&p->vPages, i >> 16) + (i & 0xFFFF); } static inline int Pf_ObjCutSetId( Pf_Man_t * p, int i ) { return Vec_IntEntry( &p->vCutSets, i ); } static inline int * Pf_ObjCutSet( Pf_Man_t * p, int i ) { return Pf_ManCutSet(p, Pf_ObjCutSetId(p, i)); } static inline int Pf_ObjHasCuts( Pf_Man_t * p, int i ) { return (int)(Vec_IntEntry(&p->vCutSets, i) > 0); } static inline int Pf_ObjCutUseless( Pf_Man_t * p, int TruthId ) { return (int)(TruthId >= Vec_WecSize(p->vTt2Match)); } static inline float Pf_ObjCutFlow( Pf_Man_t * p, int i ) { return Vec_FltEntry(&p->vCutFlows, i); } static inline int Pf_ObjCutDelay( Pf_Man_t * p, int i ) { return Vec_IntEntry(&p->vCutDelays, i); } static inline void Pf_ObjSetCutFlow( Pf_Man_t * p, int i, float a ) { Vec_FltWriteEntry(&p->vCutFlows, i, a); } static inline void Pf_ObjSetCutDelay( Pf_Man_t * p, int i, int d ) { Vec_IntWriteEntry(&p->vCutDelays, i, d); } static inline int Pf_CutSize( int * pCut ) { return pCut[0] & PF_NO_LEAF; } static inline int Pf_CutFunc( int * pCut ) { return ((unsigned)pCut[0] >> 5); } static inline int * Pf_CutLeaves( int * pCut ) { return pCut + 1; } static inline int Pf_CutSetBoth( int n, int f ) { return n | (f << 5); } static inline int Pf_CutIsTriv( int * pCut, int i ) { return Pf_CutSize(pCut) == 1 && pCut[1] == i; } static inline int Pf_CutHandle( int * pCutSet, int * pCut ) { assert( pCut > pCutSet ); return pCut - pCutSet; } static inline int * Pf_CutFromHandle( int * pCutSet, int h ) { assert( h > 0 ); return pCutSet + h; } static inline int Pf_CutConfLit( int Conf, int i ) { return 15 & (Conf >> (i << 2)); } static inline int Pf_CutConfVar( int Conf, int i ) { return Abc_Lit2Var( Pf_CutConfLit(Conf, i) ); } static inline int Pf_CutConfC( int Conf, int i ) { return Abc_LitIsCompl( Pf_CutConfLit(Conf, i) ); } #define Pf_SetForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += Pf_CutSize(pCut) + 1 ) #define Pf_ObjForEachCut( pCuts, i, nCuts ) for ( i = 0, i < nCuts; i++ ) #define Pf_CutForEachLit( pCut, Conf, iLit, i ) for ( i = 0; i < Pf_CutSize(pCut) && (iLit = Abc_Lit2LitV(Pf_CutLeaves(pCut), Pf_CutConfLit(Conf, i))); i++ ) #define Pf_CutForEachVar( pCut, Conf, iVar, c, i ) for ( i = 0; i < Pf_CutSize(pCut) && (iVar = Pf_CutLeaves(pCut)[Pf_CutConfVar(Conf, i)]) && ((c = Pf_CutConfC(Conf, i)), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pf_StoCreateGateAdd( Pf_Man_t * pMan, word uTruth, int * pFans, int nFans, int CellId ) { Vec_Int_t * vArray; Pf_Mat_t Mat = Pf_Int2Mat(0); int i, GateId, Entry, fCompl = (int)(uTruth & 1); word uFunc = fCompl ? ~uTruth : uTruth; int iFunc = Vec_MemHashInsert( pMan->vTtMem, &uFunc ); if ( iFunc == Vec_WecSize(pMan->vTt2Match) ) Vec_WecPushLevel( pMan->vTt2Match ); vArray = Vec_WecEntry( pMan->vTt2Match, iFunc ); Mat.fCompl = fCompl; assert( nFans < 7 ); for ( i = 0; i < nFans; i++ ) { Mat.Perm |= (unsigned)(Abc_Lit2Var(pFans[i]) << (3*i)); Mat.Phase |= (unsigned)(Abc_LitIsCompl(pFans[i]) << i); } // check if the same one exists Vec_IntForEachEntryDouble( vArray, GateId, Entry, i ) if ( GateId == CellId && Pf_Int2Mat(Entry).Phase == Mat.Phase ) break; if ( i == Vec_IntSize(vArray) ) { Vec_IntPush( vArray, CellId ); Vec_IntPush( vArray, Pf_Mat2Int(Mat) ); } } void Pf_StoCreateGate( Pf_Man_t * pMan, Mio_Cell_t * pCell, int ** pComp, int ** pPerm, int * pnPerms ) { int Perm[PF_LEAF_MAX], * Perm1, * Perm2; int nPerms = pnPerms[pCell->nFanins]; int nMints = (1 << pCell->nFanins); word tCur, tTemp1, tTemp2; int i, p, c; for ( i = 0; i < (int)pCell->nFanins; i++ ) Perm[i] = Abc_Var2Lit( i, 0 ); tCur = tTemp1 = pCell->uTruth; for ( p = 0; p < nPerms; p++ ) { tTemp2 = tCur; for ( c = 0; c < nMints; c++ ) { Pf_StoCreateGateAdd( pMan, tCur, Perm, pCell->nFanins, pCell->Id ); // update tCur = Abc_Tt6Flip( tCur, pComp[pCell->nFanins][c] ); Perm1 = Perm + pComp[pCell->nFanins][c]; *Perm1 = Abc_LitNot( *Perm1 ); } assert( tTemp2 == tCur ); // update tCur = Abc_Tt6SwapAdjacent( tCur, pPerm[pCell->nFanins][p] ); Perm1 = Perm + pPerm[pCell->nFanins][p]; Perm2 = Perm1 + 1; ABC_SWAP( int, *Perm1, *Perm2 ); } assert( tTemp1 == tCur ); } void Pf_StoDeriveMatches( Pf_Man_t * p, int fVerbose ) { // abctime clk = Abc_Clock(); int * pComp[7]; int * pPerm[7]; int nPerms[7], i; for ( i = 2; i <= 6; i++ ) pComp[i] = Extra_GreyCodeSchedule( i ); for ( i = 2; i <= 6; i++ ) pPerm[i] = Extra_PermSchedule( i ); for ( i = 2; i <= 6; i++ ) nPerms[i] = Extra_Factorial( i ); p->pCells = Mio_CollectRootsNewDefault( 6, &p->nCells, fVerbose ); for ( i = 4; i < p->nCells; i++ ) Pf_StoCreateGate( p, p->pCells + i, pComp, pPerm, nPerms ); for ( i = 2; i <= 6; i++ ) ABC_FREE( pComp[i] ); for ( i = 2; i <= 6; i++ ) ABC_FREE( pPerm[i] ); // Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } void Pf_StoPrintOne( Pf_Man_t * p, int Count, int t, int i, int GateId, Pf_Mat_t Mat ) { Mio_Cell_t * pC = p->pCells + GateId; word * pTruth = Vec_MemReadEntry(p->vTtMem, t); int k, nSuppSize = Abc_TtSupportSize(pTruth, 6); printf( "%6d : ", Count ); printf( "%6d : ", t ); printf( "%6d : ", i ); printf( "Gate %16s ", pC->pName ); printf( "Area =%8.2f ", pC->Area ); printf( "In = %d ", pC->nFanins ); if ( Mat.fCompl ) printf( " compl " ); else printf( " " ); for ( k = 0; k < (int)pC->nFanins; k++ ) { int fComplF = (Mat.Phase >> k) & 1; int iFanin = (Mat.Perm >> (3*k)) & 7; printf( "%c", 'a' + iFanin - fComplF * ('a' - 'A') ); } printf( " " ); Dau_DsdPrintFromTruth( pTruth, nSuppSize ); } void Pf_StoPrint( Pf_Man_t * p, int fVerbose ) { int t, i, GateId, Entry, Count = 0; for ( t = 2; t < Vec_WecSize(p->vTt2Match); t++ ) { Vec_Int_t * vArr = Vec_WecEntry( p->vTt2Match, t ); Vec_IntForEachEntryDouble( vArr, GateId, Entry, i ) { Count++; if ( !fVerbose ) continue; if ( t < 10 ) Pf_StoPrintOne( p, Count, t, i/2, GateId, Pf_Int2Mat(Entry) ); } } printf( "Gates = %d. Truths = %d. Matches = %d.\n", p->nCells, Vec_MemEntryNum(p->vTtMem), Count ); } /* void Pf_ManPrepareLibraryTest() { int fVerbose = 0; abctime clk = Abc_Clock(); Pf_Man_t * p; p = Pf_StoCreate( NULL, NULL, fVerbose ); Pf_StoPrint( p, fVerbose ); Pf_StoDelete(p); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } */ /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Pf_Man_t * Pf_StoCreate( Gia_Man_t * pGia, Jf_Par_t * pPars ) { extern void Mf_ManSetFlowRefs( Gia_Man_t * p, Vec_Int_t * vRefs ); Pf_Man_t * p; Vec_Int_t * vFlowRefs; assert( pPars->nCutNum > 1 && pPars->nCutNum <= PF_CUT_MAX ); assert( pPars->nLutSize > 1 && pPars->nLutSize <= PF_LEAF_MAX ); ABC_FREE( pGia->pRefs ); Vec_IntFreeP( &pGia->vCellMapping ); if ( Gia_ManHasChoices(pGia) ) Gia_ManSetPhase(pGia); // create references ABC_FREE( pGia->pRefs ); vFlowRefs = Vec_IntAlloc(0); Mf_ManSetFlowRefs( pGia, vFlowRefs ); pGia->pRefs= Vec_IntReleaseArray(vFlowRefs); Vec_IntFree(vFlowRefs); // create p = ABC_CALLOC( Pf_Man_t, 1 ); p->clkStart = Abc_Clock(); p->pGia = pGia; p->pPars = pPars; p->pPfObjs = ABC_CALLOC( Pf_Obj_t, Gia_ManObjNum(pGia) ); p->iCur = 2; // other Vec_PtrGrow( &p->vPages, 256 ); // cut memory Vec_IntFill( &p->vCutSets, Gia_ManObjNum(pGia), 0 ); // cut offsets Vec_FltFill( &p->vCutFlows, Gia_ManObjNum(pGia), 0 ); // cut area Vec_IntFill( &p->vCutDelays,Gia_ManObjNum(pGia), 0 ); // cut delay // matching p->vTtMem = Vec_MemAllocForTT( 6, 0 ); p->vTt2Match = Vec_WecAlloc( 1000 ); Vec_WecPushLevel( p->vTt2Match ); Vec_WecPushLevel( p->vTt2Match ); assert( Vec_WecSize(p->vTt2Match) == Vec_MemEntryNum(p->vTtMem) ); Pf_StoDeriveMatches( p, 0 );//pPars->fVerbose ); p->InvDelay = p->pCells[3].Delays[0]; p->InvArea = p->pCells[3].Area; //Pf_ObjMatchD(p, 0, 0)->Gate = 0; //Pf_ObjMatchD(p, 0, 1)->Gate = 1; // prepare cuts return p; } void Pf_StoDelete( Pf_Man_t * p ) { Vec_PtrFreeData( &p->vPages ); ABC_FREE( p->vPages.pArray ); ABC_FREE( p->vCutSets.pArray ); ABC_FREE( p->vCutFlows.pArray ); ABC_FREE( p->vCutDelays.pArray ); ABC_FREE( p->pPfObjs ); // matching Vec_WecFree( p->vTt2Match ); Vec_MemHashFree( p->vTtMem ); Vec_MemFree( p->vTtMem ); ABC_FREE( p->pCells ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Pf_CutComputeTruth6( Pf_Man_t * p, Pf_Cut_t * pCut0, Pf_Cut_t * pCut1, int fCompl0, int fCompl1, Pf_Cut_t * pCutR, int fIsXor ) { // extern int Pf_ManTruthCanonicize( word * t, int nVars ); int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t = fIsXor ? t0 ^ t1 : t0 & t1; if ( (fCompl = (int)(t & 1)) ) t = ~t; pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); assert( (int)(t & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, &t); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); pCutR->Useless = Pf_ObjCutUseless( p, truthId ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } static inline int Pf_CutComputeTruthMux6( Pf_Man_t * p, Pf_Cut_t * pCut0, Pf_Cut_t * pCut1, Pf_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Pf_Cut_t * pCutR ) { int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); word tC = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCutC->iFunc)); if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; if ( Abc_LitIsCompl(pCutC->iFunc) ^ fComplC ) tC = ~tC; t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); tC = Abc_Tt6Expand( tC, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); t = (tC & t1) | (~tC & t0); if ( (fCompl = (int)(t & 1)) ) t = ~t; pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); assert( (int)(t & 1) == 0 ); truthId = Vec_MemHashInsert(p->vTtMem, &t); pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); pCutR->Useless = Pf_ObjCutUseless( p, truthId ); assert( (int)pCutR->nLeaves <= nOldSupp ); return (int)pCutR->nLeaves < nOldSupp; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Pf_CutCountBits( word i ) { i = i - ((i >> 1) & 0x5555555555555555); i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); return (i*(0x0101010101010101))>>56; } static inline word Pf_CutGetSign( int * pLeaves, int nLeaves ) { word Sign = 0; int i; for ( i = 0; i < nLeaves; i++ ) Sign |= ((word)1) << (pLeaves[i] & 0x3F); return Sign; } static inline int Pf_CutCreateUnit( Pf_Cut_t * p, int i ) { p->Delay = 0; p->Flow = 0; p->iFunc = 2; p->nLeaves = 1; p->pLeaves[0] = i; p->Sign = ((word)1) << (i & 0x3F); return 1; } static inline void Pf_Cutprintf( Pf_Man_t * p, Pf_Cut_t * pCut ) { int i, nDigits = Abc_Base10Log(Gia_ManObjNum(p->pGia)); printf( "%d {", pCut->nLeaves ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) printf( " %*d", nDigits, pCut->pLeaves[i] ); for ( ; i < (int)p->pPars->nLutSize; i++ ) printf( " %*s", nDigits, " " ); printf( " } Useless = %d. D = %4d A = %9.4f F = %6d ", pCut->Useless, pCut->Delay, pCut->Flow, pCut->iFunc ); if ( p->vTtMem ) Dau_DsdPrintFromTruth( Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut->iFunc)), pCut->nLeaves ); else printf( "\n" ); } static inline int Pf_ManPrepareCuts( Pf_Cut_t * pCuts, Pf_Man_t * p, int iObj, int fAddUnit ) { if ( Pf_ObjHasCuts(p, iObj) ) { Pf_Cut_t * pMfCut = pCuts; int i, * pCut, * pList = Pf_ObjCutSet(p, iObj); Pf_SetForEachCut( pList, pCut, i ) { pMfCut->Delay = 0; pMfCut->Flow = 0; pMfCut->iFunc = Pf_CutFunc( pCut ); pMfCut->nLeaves = Pf_CutSize( pCut ); pMfCut->Sign = Pf_CutGetSign( pCut+1, Pf_CutSize(pCut) ); pMfCut->Useless = Pf_ObjCutUseless( p, Abc_Lit2Var(pMfCut->iFunc) ); memcpy( pMfCut->pLeaves, pCut+1, sizeof(int) * Pf_CutSize(pCut) ); pMfCut++; } if ( fAddUnit && pCuts->nLeaves > 1 ) return pList[0] + Pf_CutCreateUnit( pMfCut, iObj ); return pList[0]; } return Pf_CutCreateUnit( pCuts, iObj ); } static inline int Pf_ManSaveCuts( Pf_Man_t * p, Pf_Cut_t ** pCuts, int nCuts, int fUseful ) { int i, * pPlace, iCur, nInts = 1, nCutsNew = 0; for ( i = 0; i < nCuts; i++ ) if ( !fUseful || !pCuts[i]->Useless ) nInts += pCuts[i]->nLeaves + 1, nCutsNew++; if ( (p->iCur & 0xFFFF) + nInts > 0xFFFF ) p->iCur = ((p->iCur >> 16) + 1) << 16; if ( Vec_PtrSize(&p->vPages) == (p->iCur >> 16) ) Vec_PtrPush( &p->vPages, ABC_ALLOC(int, (1<<16)) ); iCur = p->iCur; p->iCur += nInts; pPlace = Pf_ManCutSet( p, iCur ); *pPlace++ = nCutsNew; for ( i = 0; i < nCuts; i++ ) if ( !fUseful || !pCuts[i]->Useless ) { *pPlace++ = Pf_CutSetBoth( pCuts[i]->nLeaves, pCuts[i]->iFunc ); memcpy( pPlace, pCuts[i]->pLeaves, sizeof(int) * pCuts[i]->nLeaves ); pPlace += pCuts[i]->nLeaves; } return iCur; } static inline int Pf_ManCountUseful( Pf_Cut_t ** pCuts, int nCuts ) { int i, Count = 0; for ( i = 0; i < nCuts; i++ ) Count += !pCuts[i]->Useless; return Count; } static inline int Pf_ManCountMatches( Pf_Man_t * p, Pf_Cut_t ** pCuts, int nCuts ) { int i, Count = 0; for ( i = 0; i < nCuts; i++ ) if ( !pCuts[i]->Useless ) Count += Vec_IntSize(Vec_WecEntry(p->vTt2Match, Abc_Lit2Var(pCuts[i]->iFunc))) / 2; return Count; } /**Function************************************************************* Synopsis [Check correctness of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Pf_CutCheck( Pf_Cut_t * pBase, Pf_Cut_t * pCut ) // check if pCut is contained in pBase { int nSizeB = pBase->nLeaves; int nSizeC = pCut->nLeaves; int i, * pB = pBase->pLeaves; int k, * pC = pCut->pLeaves; for ( i = 0; i < nSizeC; i++ ) { for ( k = 0; k < nSizeB; k++ ) if ( pC[i] == pB[k] ) break; if ( k == nSizeB ) return 0; } return 1; } static inline int Pf_SetCheckArray( Pf_Cut_t ** ppCuts, int nCuts ) { Pf_Cut_t * pCut0, * pCut1; int i, k, m, n, Value; assert( nCuts > 0 ); for ( i = 0; i < nCuts; i++ ) { pCut0 = ppCuts[i]; assert( pCut0->nLeaves <= PF_LEAF_MAX ); assert( pCut0->Sign == Pf_CutGetSign(pCut0->pLeaves, pCut0->nLeaves) ); // check duplicates for ( m = 0; m < (int)pCut0->nLeaves; m++ ) for ( n = m + 1; n < (int)pCut0->nLeaves; n++ ) assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] ); // check pairs for ( k = 0; k < nCuts; k++ ) { pCut1 = ppCuts[k]; if ( pCut0 == pCut1 ) continue; // check containments Value = Pf_CutCheck( pCut0, pCut1 ); assert( Value == 0 ); } } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Pf_CutMergeOrder( Pf_Cut_t * pCut0, Pf_Cut_t * pCut1, Pf_Cut_t * pCut, int nLutSize ) { int nSize0 = pCut0->nLeaves; int nSize1 = pCut1->nLeaves; int i, * pC0 = pCut0->pLeaves; int k, * pC1 = pCut1->pLeaves; int c, * pC = pCut->pLeaves; // the case of the largest cut sizes if ( nSize0 == nLutSize && nSize1 == nLutSize ) { for ( i = 0; i < nSize0; i++ ) { if ( pC0[i] != pC1[i] ) return 0; pC[i] = pC0[i]; } pCut->nLeaves = nLutSize; pCut->iFunc = PF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; } // compare two cuts with different numbers i = k = c = 0; if ( nSize0 == 0 ) goto FlushCut1; if ( nSize1 == 0 ) goto FlushCut0; while ( 1 ) { if ( c == nLutSize ) return 0; if ( pC0[i] < pC1[k] ) { pC[c++] = pC0[i++]; if ( i >= nSize0 ) goto FlushCut1; } else if ( pC0[i] > pC1[k] ) { pC[c++] = pC1[k++]; if ( k >= nSize1 ) goto FlushCut0; } else { pC[c++] = pC0[i++]; k++; if ( i >= nSize0 ) goto FlushCut1; if ( k >= nSize1 ) goto FlushCut0; } } FlushCut0: if ( c + nSize0 > nLutSize + i ) return 0; while ( i < nSize0 ) pC[c++] = pC0[i++]; pCut->nLeaves = c; pCut->iFunc = PF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; FlushCut1: if ( c + nSize1 > nLutSize + k ) return 0; while ( k < nSize1 ) pC[c++] = pC1[k++]; pCut->nLeaves = c; pCut->iFunc = PF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign; return 1; } static inline int Pf_CutMergeOrderMux( Pf_Cut_t * pCut0, Pf_Cut_t * pCut1, Pf_Cut_t * pCut2, Pf_Cut_t * pCut, int nLutSize ) { int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; int x2, i2 = 0, nSize2 = pCut2->nLeaves, * pC2 = pCut2->pLeaves; int xMin, c = 0, * pC = pCut->pLeaves; while ( 1 ) { x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; x2 = (i2 == nSize2) ? ABC_INFINITY : pC2[i2]; xMin = Abc_MinInt( Abc_MinInt(x0, x1), x2 ); if ( xMin == ABC_INFINITY ) break; if ( c == nLutSize ) return 0; pC[c++] = xMin; if (x0 == xMin) i0++; if (x1 == xMin) i1++; if (x2 == xMin) i2++; } pCut->nLeaves = c; pCut->iFunc = PF_NO_FUNC; pCut->Sign = pCut0->Sign | pCut1->Sign | pCut2->Sign; return 1; } static inline int Pf_SetCutIsContainedOrder( Pf_Cut_t * pBase, Pf_Cut_t * pCut ) // check if pCut is contained in pBase { int i, nSizeB = pBase->nLeaves; int k, nSizeC = pCut->nLeaves; if ( nSizeB == nSizeC ) { for ( i = 0; i < nSizeB; i++ ) if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) return 0; return 1; } assert( nSizeB > nSizeC ); if ( nSizeC == 0 ) return 1; for ( i = k = 0; i < nSizeB; i++ ) { if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) return 0; if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) { if ( ++k == nSizeC ) return 1; } } return 0; } static inline int Pf_SetLastCutIsContained( Pf_Cut_t ** pCuts, int nCuts ) { int i; for ( i = 0; i < nCuts; i++ ) if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Pf_SetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) ) return 1; return 0; } static inline int Pf_SetLastCutContainsArea( Pf_Cut_t ** pCuts, int nCuts ) { int i, k, fChanges = 0; for ( i = 0; i < nCuts; i++ ) if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Pf_SetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) ) pCuts[i]->nLeaves = PF_NO_LEAF, fChanges = 1; if ( !fChanges ) return nCuts; for ( i = k = 0; i <= nCuts; i++ ) { if ( pCuts[i]->nLeaves == PF_NO_LEAF ) continue; if ( k < i ) ABC_SWAP( Pf_Cut_t *, pCuts[k], pCuts[i] ); k++; } return k - 1; } static inline int Pf_CutCompareArea( Pf_Cut_t * pCut0, Pf_Cut_t * pCut1 ) { if ( pCut0->Useless < pCut1->Useless ) return -1; if ( pCut0->Useless > pCut1->Useless ) return 1; if ( pCut0->Flow < pCut1->Flow ) return -1; if ( pCut0->Flow > pCut1->Flow ) return 1; if ( pCut0->Delay < pCut1->Delay ) return -1; if ( pCut0->Delay > pCut1->Delay ) return 1; if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; return 0; } static inline void Pf_SetSortByArea( Pf_Cut_t ** pCuts, int nCuts ) { int i; for ( i = nCuts; i > 0; i-- ) { if ( Pf_CutCompareArea(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 ) return; ABC_SWAP( Pf_Cut_t *, pCuts[i - 1], pCuts[i] ); } } static inline int Pf_SetAddCut( Pf_Cut_t ** pCuts, int nCuts, int nCutNum ) { if ( nCuts == 0 ) return 1; nCuts = Pf_SetLastCutContainsArea(pCuts, nCuts); Pf_SetSortByArea( pCuts, nCuts ); return Abc_MinInt( nCuts + 1, nCutNum - 1 ); } static inline int Pf_CutArea( Pf_Man_t * p, int nLeaves ) { if ( nLeaves < 2 ) return 0; return nLeaves + p->pPars->nAreaTuner; } static inline void Pf_CutParams( Pf_Man_t * p, Pf_Cut_t * pCut, int nGiaRefs ) { int i, nLeaves = pCut->nLeaves; assert( nLeaves <= p->pPars->nLutSize ); pCut->Delay = 0; pCut->Flow = 0; for ( i = 0; i < nLeaves; i++ ) { pCut->Delay = Abc_MaxInt( pCut->Delay, Pf_ObjCutDelay(p, pCut->pLeaves[i]) ); pCut->Flow += Pf_ObjCutFlow(p, pCut->pLeaves[i]); } pCut->Delay += (int)(nLeaves > 1); pCut->Flow = (pCut->Flow + Pf_CutArea(p, nLeaves)) / (nGiaRefs ? nGiaRefs : 1); } void Pf_ObjMergeOrder( Pf_Man_t * p, int iObj ) { Pf_Cut_t pCuts0[PF_CUT_MAX], pCuts1[PF_CUT_MAX], pCuts[PF_CUT_MAX], * pCutsR[PF_CUT_MAX]; Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); int nGiaRefs = 2*Gia_ObjRefNumId(p->pGia, iObj); int nLutSize = p->pPars->nLutSize; int nCutNum = p->pPars->nCutNum; int nCuts0 = Pf_ManPrepareCuts(pCuts0, p, Gia_ObjFaninId0(pObj, iObj), 1); int nCuts1 = Pf_ManPrepareCuts(pCuts1, p, Gia_ObjFaninId1(pObj, iObj), 1); int fComp0 = Gia_ObjFaninC0(pObj); int fComp1 = Gia_ObjFaninC1(pObj); int iSibl = Gia_ObjSibl(p->pGia, iObj); Pf_Cut_t * pCut0, * pCut1, * pCut0Lim = pCuts0 + nCuts0, * pCut1Lim = pCuts1 + nCuts1; int i, nCutsUse, nCutsR = 0; assert( !Gia_ObjIsBuf(pObj) ); for ( i = 0; i < nCutNum; i++ ) pCutsR[i] = pCuts + i; if ( iSibl ) { Pf_Cut_t pCuts2[PF_CUT_MAX]; Gia_Obj_t * pObjE = Gia_ObjSiblObj(p->pGia, iObj); int fCompE = Gia_ObjPhase(pObj) ^ Gia_ObjPhase(pObjE); int nCuts2 = Pf_ManPrepareCuts(pCuts2, p, iSibl, 0); Pf_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) { *pCutsR[nCutsR] = *pCut2; pCutsR[nCutsR]->iFunc = Abc_LitNotCond( pCutsR[nCutsR]->iFunc, fCompE ); Pf_CutParams( p, pCutsR[nCutsR], nGiaRefs ); nCutsR = Pf_SetAddCut( pCutsR, nCutsR, nCutNum ); } } if ( Gia_ObjIsMuxId(p->pGia, iObj) ) { Pf_Cut_t pCuts2[PF_CUT_MAX]; int nCuts2 = Pf_ManPrepareCuts(pCuts2, p, Gia_ObjFaninId2(p->pGia, iObj), 1); int fComp2 = Gia_ObjFaninC2(p->pGia, pObj); Pf_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; p->CutCount[0] += nCuts0 * nCuts1 * nCuts2; for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) { if ( Pf_CutCountBits(pCut0->Sign | pCut1->Sign | pCut2->Sign) > nLutSize ) continue; p->CutCount[1]++; if ( !Pf_CutMergeOrderMux(pCut0, pCut1, pCut2, pCutsR[nCutsR], nLutSize) ) continue; if ( Pf_SetLastCutIsContained(pCutsR, nCutsR) ) continue; p->CutCount[2]++; if ( Pf_CutComputeTruthMux6(p, pCut0, pCut1, pCut2, fComp0, fComp1, fComp2, pCutsR[nCutsR]) ) pCutsR[nCutsR]->Sign = Pf_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); Pf_CutParams( p, pCutsR[nCutsR], nGiaRefs ); nCutsR = Pf_SetAddCut( pCutsR, nCutsR, nCutNum ); } } else { int fIsXor = Gia_ObjIsXor(pObj); p->CutCount[0] += nCuts0 * nCuts1; for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) { if ( (int)(pCut0->nLeaves + pCut1->nLeaves) > nLutSize && Pf_CutCountBits(pCut0->Sign | pCut1->Sign) > nLutSize ) continue; p->CutCount[1]++; if ( !Pf_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], nLutSize) ) continue; if ( Pf_SetLastCutIsContained(pCutsR, nCutsR) ) continue; p->CutCount[2]++; if ( Pf_CutComputeTruth6(p, pCut0, pCut1, fComp0, fComp1, pCutsR[nCutsR], fIsXor) ) pCutsR[nCutsR]->Sign = Pf_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); Pf_CutParams( p, pCutsR[nCutsR], nGiaRefs ); nCutsR = Pf_SetAddCut( pCutsR, nCutsR, nCutNum ); } } // debug printout if ( 0 ) // if ( iObj % 10000 == 0 ) // if ( iObj == 1090 ) { printf( "*** Obj = %d Useful = %d\n", iObj, Pf_ManCountUseful(pCutsR, nCutsR) ); for ( i = 0; i < nCutsR; i++ ) Pf_Cutprintf( p, pCutsR[i] ); printf( "\n" ); } // verify assert( nCutsR > 0 && nCutsR < nCutNum ); // assert( Pf_SetCheckArray(pCutsR, nCutsR) ); // store the cutset Pf_ObjSetCutFlow( p, iObj, pCutsR[0]->Flow ); Pf_ObjSetCutDelay( p, iObj, pCutsR[0]->Delay ); *Vec_IntEntryP(&p->vCutSets, iObj) = Pf_ManSaveCuts(p, pCutsR, nCutsR, 0); p->CutCount[3] += nCutsR; nCutsUse = Pf_ManCountUseful(pCutsR, nCutsR); p->CutCount[4] += nCutsUse; p->nCutUseAll += nCutsUse == nCutsR; p->CutCount[5] += Pf_ManCountMatches(p, pCutsR, nCutsR); } void Pf_ManComputeCuts( Pf_Man_t * p ) { Gia_Obj_t * pObj; int i, iFanin; Gia_ManForEachAnd( p->pGia, pObj, i ) if ( Gia_ObjIsBuf(pObj) ) { iFanin = Gia_ObjFaninId0(pObj, i); Pf_ObjSetCutFlow( p, i, Pf_ObjCutFlow(p, iFanin) ); Pf_ObjSetCutDelay( p, i, Pf_ObjCutDelay(p, iFanin) ); } else Pf_ObjMergeOrder( p, i ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pf_ManPrintStats( Pf_Man_t * p, char * pTitle ) { if ( !p->pPars->fVerbose ) return; printf( "%s : ", pTitle ); 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 ); printf( "Edge =%7d ", (int)p->pPars->Edge ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); fflush( stdout ); } void Pf_ManPrintInit( Pf_Man_t * p ) { int nChoices; if ( !p->pPars->fVerbose ) return; printf( "LutSize = %d ", p->pPars->nLutSize ); printf( "CutNum = %d ", p->pPars->nCutNum ); printf( "Iter = %d ", p->pPars->nRounds + p->pPars->nRoundsEla ); printf( "Coarse = %d ", p->pPars->fCoarsen ); printf( "Cells = %d ", p->nCells ); printf( "Funcs = %d ", Vec_MemEntryNum(p->vTtMem) ); printf( "Matches = %d ", Vec_WecSizeSize(p->vTt2Match)/2 ); nChoices = Gia_ManChoiceNum( p->pGia ); if ( nChoices ) printf( "Choices = %d ", nChoices ); printf( "\n" ); printf( "Computing cuts...\r" ); fflush( stdout ); } void Pf_ManPrintQuit( Pf_Man_t * p ) { float MemGia = Gia_ManMemory(p->pGia) / (1<<20); float MemMan =(1.0 * sizeof(Pf_Obj_t) + 3.0 * sizeof(int)) * Gia_ManObjNum(p->pGia) / (1<<20); float MemCuts = 1.0 * sizeof(int) * (1 << 16) * Vec_PtrSize(&p->vPages) / (1<<20); float MemTt = p->vTtMem ? Vec_MemMemory(p->vTtMem) / (1<<20) : 0; if ( p->CutCount[0] == 0 ) p->CutCount[0] = 1; if ( !p->pPars->fVerbose ) return; printf( "CutPair = %.0f ", p->CutCount[0] ); printf( "Merge = %.0f (%.1f) ", p->CutCount[1], 1.0*p->CutCount[1]/Gia_ManAndNum(p->pGia) ); printf( "Eval = %.0f (%.1f) ", p->CutCount[2], 1.0*p->CutCount[2]/Gia_ManAndNum(p->pGia) ); printf( "Cut = %.0f (%.1f) ", p->CutCount[3], 1.0*p->CutCount[3]/Gia_ManAndNum(p->pGia) ); printf( "Use = %.0f (%.1f) ", p->CutCount[4], 1.0*p->CutCount[4]/Gia_ManAndNum(p->pGia) ); printf( "Mat = %.0f (%.1f) ", p->CutCount[5], 1.0*p->CutCount[5]/Gia_ManAndNum(p->pGia) ); // printf( "Equ = %d (%.2f %%) ", p->nCutUseAll, 100.0*p->nCutUseAll /p->CutCount[0] ); printf( "\n" ); printf( "Gia = %.2f MB ", MemGia ); printf( "Man = %.2f MB ", MemMan ); printf( "Cut = %.2f MB ", MemCuts ); printf( "TT = %.2f MB ", MemTt ); printf( "Total = %.2f MB ", MemGia + MemMan + MemCuts + MemTt ); // printf( "\n" ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); fflush( stdout ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* void Pf_ManSetMapRefsGate( Pf_Man_t * p, int iObj, float Required, Pf_Mat_t * pM ) { int k, iVar, fCompl; Mio_Cell_t * pCell = Pf_ManCell( p, pM->Gate ); int * pCut = Pf_CutFromHandle( Pf_ObjCutSet(p, iObj), pM->CutH ); Pf_CutForEachVar( pCut, pM->Conf, iVar, fCompl, k ) { Pf_ObjMapRefInc( p, iVar, fCompl ); Pf_ObjUpdateRequired( p, iVar, fCompl, Required - pCell->Delays[k] ); } assert( Pf_CutSize(pCut) == (int)pCell->nFanins ); // update global stats p->pPars->MapArea += pCell->Area; p->pPars->Edge += Pf_CutSize(pCut); p->pPars->Area++; // update status of the gate assert( pM->fBest == 0 ); pM->fBest = 1; } int Pf_ManSetMapRefs( Pf_Man_t * p ) { float Coef = 1.0 / (1.0 + (p->Iter + 1) * (p->Iter + 1)); float * pFlowRefs = Vec_FltArray( &p->vFlowRefs ); int * pMapRefs = Vec_IntArray( &p->vMapRefs ); float Epsilon = p->pPars->Epsilon; int nLits = 2*Gia_ManObjNum(p->pGia); int i, c, Id, nRefs[2]; Pf_Mat_t * pD, * pA, * pM; Pf_Mat_t * pDs[2], * pAs[2], * pMs[2]; Gia_Obj_t * pObj; float Required = 0, Requireds[2]; // check references assert( !p->fUseEla ); memset( pMapRefs, 0, sizeof(int) * nLits ); Vec_FltFill( &p->vRequired, nLits, PF_INFINITY ); // for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ ) // assert( !Pf_ObjMapRefNum(p, i, 0) && !Pf_ObjMapRefNum(p, i, 1) ); // compute delay p->pPars->MapDelay = 0; Gia_ManForEachCo( p->pGia, pObj, i ) { Required = Pf_ObjMatchD( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj) )->D; if ( Required == PF_INFINITY ) { Pf_ManCutMatchprintf( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj), Pf_ObjMatchD( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj) ) ); } p->pPars->MapDelay = Abc_MaxFloat( p->pPars->MapDelay, Required ); } // check delay target if ( p->pPars->MapDelayTarget == -1 && p->pPars->nRelaxRatio ) p->pPars->MapDelayTarget = (int)((float)p->pPars->MapDelay * (100.0 + p->pPars->nRelaxRatio) / 100.0); if ( p->pPars->MapDelayTarget != -1 ) { if ( p->pPars->MapDelay < p->pPars->MapDelayTarget + Epsilon ) p->pPars->MapDelay = p->pPars->MapDelayTarget; else if ( p->pPars->nRelaxRatio == 0 ) Abc_Print( 0, "Relaxing user-specified delay target from %.2f to %.2f.\n", p->pPars->MapDelayTarget, p->pPars->MapDelay ); } // set required times Gia_ManForEachCo( p->pGia, pObj, i ) { Required = Pf_ObjMatchD( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj) )->D; Required = p->pPars->fDoAverage ? Required * (100.0 + p->pPars->nRelaxRatio) / 100.0 : p->pPars->MapDelay; Pf_ObjUpdateRequired( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj), Required ); Pf_ObjMapRefInc( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj)); } // compute area and edges p->nInvs = 0; p->pPars->MapArea = 0; p->pPars->Area = p->pPars->Edge = 0; Gia_ManForEachAndReverse( p->pGia, pObj, i ) { if ( Gia_ObjIsBuf(pObj) ) { if ( Pf_ObjMapRefNum(p, i, 1) ) { Pf_ObjMapRefInc( p, i, 0 ); Pf_ObjUpdateRequired( p, i, 0, Pf_ObjRequired(p, i, 1) - p->InvDelay ); p->pPars->MapArea += p->InvArea; p->pPars->Edge++; p->pPars->Area++; p->nInvs++; } Pf_ObjUpdateRequired( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj), Pf_ObjRequired(p, i, 0) ); Pf_ObjMapRefInc( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj)); continue; } // skip if this node is not used for ( c = 0; c < 2; c++ ) { nRefs[c] = Pf_ObjMapRefNum(p, i, c); //if ( Pf_ObjMatchD( p, i, c )->fCompl ) // printf( "Match D of node %d has inv in phase %d.\n", i, c ); //if ( Pf_ObjMatchA( p, i, c )->fCompl ) // printf( "Match A of node %d has inv in phase %d.\n", i, c ); } if ( !nRefs[0] && !nRefs[1] ) continue; // consider two cases if ( nRefs[0] && nRefs[1] ) { // find best matches for both phases for ( c = 0; c < 2; c++ ) { Requireds[c] = Pf_ObjRequired( p, i, c ); //assert( Requireds[c] < PF_INFINITY ); pDs[c] = Pf_ObjMatchD( p, i, c ); pAs[c] = Pf_ObjMatchA( p, i, c ); pMs[c] = (pAs[c]->D < Requireds[c] + Epsilon) ? pAs[c] : pDs[c]; } // swap complemented matches if ( pMs[0]->fCompl && pMs[1]->fCompl ) { pMs[0]->fCompl = pMs[1]->fCompl = 0; ABC_SWAP( Pf_Mat_t *, pMs[0], pMs[1] ); } // check if intervers are involved if ( !pMs[0]->fCompl && !pMs[1]->fCompl ) { // no inverters for ( c = 0; c < 2; c++ ) Pf_ManSetMapRefsGate( p, i, Requireds[c], pMs[c] ); } else { // one interver assert( !pMs[0]->fCompl || !pMs[1]->fCompl ); c = pMs[1]->fCompl; assert( pMs[c]->fCompl && !pMs[!c]->fCompl ); //printf( "Using inverter at node %d in phase %d\n", i, c ); // update this phase phase pM = pMs[c]; pM->fBest = 1; Required = Requireds[c]; // update opposite phase Pf_ObjMapRefInc( p, i, !c ); Pf_ObjUpdateRequired( p, i, !c, Required - p->InvDelay ); // select oppositve phase Required = Pf_ObjRequired( p, i, !c ); //assert( Required < PF_INFINITY ); pD = Pf_ObjMatchD( p, i, !c ); pA = Pf_ObjMatchA( p, i, !c ); pM = (pA->D < Required + Epsilon) ? pA : pD; assert( !pM->fCompl ); // account for the inverter p->pPars->MapArea += p->InvArea; p->pPars->Edge++; p->pPars->Area++; p->nInvs++; // create gate Pf_ManSetMapRefsGate( p, i, Required, pM ); } } else { c = (int)(nRefs[1] > 0); assert( nRefs[c] && !nRefs[!c] ); // consider this phase Required = Pf_ObjRequired( p, i, c ); //assert( Required < PF_INFINITY ); pD = Pf_ObjMatchD( p, i, c ); pA = Pf_ObjMatchA( p, i, c ); pM = (pA->D < Required + Epsilon) ? pA : pD; if ( pM->fCompl ) // use inverter { p->nInvs++; //printf( "Using inverter at node %d in phase %d\n", i, c ); pM->fBest = 1; // update opposite phase Pf_ObjMapRefInc( p, i, !c ); Pf_ObjUpdateRequired( p, i, !c, Required - p->InvDelay ); // select oppositve phase Required = Pf_ObjRequired( p, i, !c ); //assert( Required < PF_INFINITY ); pD = Pf_ObjMatchD( p, i, !c ); pA = Pf_ObjMatchA( p, i, !c ); pM = (pA->D < Required + Epsilon) ? pA : pD; assert( !pM->fCompl ); // account for the inverter p->pPars->MapArea += p->InvArea; p->pPars->Edge++; p->pPars->Area++; } // create gate Pf_ManSetMapRefsGate( p, i, Required, pM ); } // the result of this: // - only one phase can be implemented as inverter of the other phase // - required times are propagated correctly // - references are set correctly } Gia_ManForEachCiId( p->pGia, Id, i ) if ( Pf_ObjMapRefNum(p, Id, 1) ) { Pf_ObjMapRefInc( p, Id, 0 ); Pf_ObjUpdateRequired( p, Id, 0, Required - p->InvDelay ); p->pPars->MapArea += p->InvArea; p->pPars->Edge++; p->pPars->Area++; p->nInvs++; } // blend references for ( i = 0; i < nLits; i++ ) // pFlowRefs[i] = Abc_MaxFloat(1.0, pMapRefs[i]); pFlowRefs[i] = Abc_MaxFloat(1.0, Coef * pFlowRefs[i] + (1.0 - Coef) * Abc_MaxFloat(1, pMapRefs[i])); // pFlowRefs[i] = 0.2 * pFlowRefs[i] + 0.8 * Abc_MaxFloat(1, pMapRefs[i]); // memset( pMapRefs, 0, sizeof(int) * nLits ); return p->pPars->Area; } Gia_Man_t * Pf_ManDeriveMapping( Pf_Man_t * p ) { Vec_Int_t * vMapping; Pf_Mat_t * pM; int i, k, c, Id, iLit, * pCut; assert( p->pGia->vCellMapping == NULL ); vMapping = Vec_IntAlloc( 2*Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); Vec_IntFill( vMapping, 2*Gia_ManObjNum(p->pGia), 0 ); // create CI inverters Gia_ManForEachCiId( p->pGia, Id, i ) if ( Pf_ObjMapRefNum(p, Id, 1) ) Vec_IntWriteEntry( vMapping, Abc_Var2Lit(Id, 1), -1 ); // create internal nodes Gia_ManForEachAndId( p->pGia, i ) { Gia_Obj_t * pObj = Gia_ManObj(p->pGia, i); if ( Gia_ObjIsBuf(pObj) ) { if ( Pf_ObjMapRefNum(p, i, 1) ) Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, 1), -1 ); Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, 0), -2 ); continue; } for ( c = 0; c < 2; c++ ) if ( Pf_ObjMapRefNum(p, i, c) ) { // printf( "Using %d %d\n", i, c ); pM = Pf_ObjMatchBest( p, i, c ); // remember inverter if ( pM->fCompl ) { Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, c), -1 ); continue; } // Pf_ManCutMatchprintf( p, i, c, pM ); pCut = Pf_CutFromHandle( Pf_ObjCutSet(p, i), pM->CutH ); // create mapping Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, c), Vec_IntSize(vMapping) ); Vec_IntPush( vMapping, Pf_CutSize(pCut) ); Pf_CutForEachLit( pCut, pM->Conf, iLit, k ) Vec_IntPush( vMapping, iLit ); Vec_IntPush( vMapping, pM->Gate ); } } // assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); p->pGia->vCellMapping = vMapping; return p->pGia; } */ /**Function************************************************************* Synopsis [Technology mappping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pf_ManComputeMapping( Pf_Man_t * p ) { } /**Function************************************************************* Synopsis [Technology mappping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Pf_ManSetDefaultPars( Jf_Par_t * pPars ) { memset( pPars, 0, sizeof(Jf_Par_t) ); pPars->nLutSize = 6; pPars->nCutNum = 16; pPars->nProcNum = 0; pPars->nRounds = 3; pPars->nRoundsEla = 0; pPars->nRelaxRatio = 0; pPars->nCoarseLimit = 3; pPars->nAreaTuner = 1; pPars->nVerbLimit = 5; pPars->DelayTarget = -1; pPars->fAreaOnly = 0; pPars->fOptEdge = 1; pPars->fCoarsen = 0; pPars->fCutMin = 1; pPars->fGenCnf = 0; pPars->fPureAig = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; pPars->nLutSizeMax = PF_LEAF_MAX; pPars->nCutNumMax = PF_CUT_MAX; pPars->MapDelayTarget = -1; pPars->Epsilon = (float)0.01; } Gia_Man_t * Pf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) { Gia_Man_t * pNew = NULL, * pCls; Pf_Man_t * p; if ( Gia_ManHasChoices(pGia) ) pPars->fCoarsen = 0; pCls = pPars->fCoarsen ? Gia_ManDupMuxes(pGia, pPars->nCoarseLimit) : pGia; p = Pf_StoCreate( pCls, pPars ); // if ( pPars->fVeryVerbose ) Pf_StoPrint( p, 1 ); if ( pPars->fVerbose && pPars->fCoarsen ) { printf( "Initial " ); Gia_ManPrintMuxStats( pGia ); printf( "\n" ); printf( "Derived " ); Gia_ManPrintMuxStats( pCls ); printf( "\n" ); } Pf_ManPrintInit( p ); Pf_ManComputeCuts( p ); Pf_ManPrintQuit( p ); /* Gia_ManForEachCiId( p->pGia, Id, i ) Pf_ObjPrepareCi( p, Id ); for ( p->Iter = 0; p->Iter < p->pPars->nRounds; p->Iter++ ) { Pf_ManComputeMapping( p ); //Pf_ManSetMapRefs( p ); Pf_ManPrintStats( p, p->Iter ? "Area " : "Delay" ); } p->fUseEla = 1; for ( ; p->Iter < p->pPars->nRounds + pPars->nRoundsEla; p->Iter++ ) { Pf_ManComputeMapping( p ); //Pf_ManUpdateStats( p ); Pf_ManPrintStats( p, "Ela " ); } */ pNew = NULL; //Pf_ManDeriveMapping( p ); // Gia_ManMappingVerify( pNew ); Pf_StoDelete( p ); if ( pCls != pGia ) Gia_ManStop( pCls ); if ( pNew == NULL ) return Gia_ManDup( pGia ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaProp.c000066400000000000000000000120121477524141600160300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaProp.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Constraint propagation on the AIG.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaProp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define GIA_SAT_SHIFT 12 #define GIA_ROOT_MASK #define GIA_PATH00_MASK #define GIA_PATH10_MASK #define GIA_PATH20_MASK #define GIA_PATH30_MASK #define GIA_PATH00_MASK #define GIA_PATH10_MASK #define GIA_PATH20_MASK #define GIA_PATH30_MASK static inline int Gia_SatObjIsRoot( Gia_Obj_t * p ) { return 0; } static inline int Gia_SatObjXorRoot( Gia_Obj_t * p ) { return 0; } static inline int Gia_SatObjIsAssigned( Gia_Obj_t * p ) { return 0; } static inline int Gia_SatObjIsHeld( Gia_Obj_t * p ) { return 0; } static inline int Gia_SatObjValue( Gia_Obj_t * p ) { return 0; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks if the give cut is satisfied.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_SatPathCheckCutSat_rec( Gia_Obj_t * p, int fCompl ) { if ( Gia_SatObjIsRoot(p) ) return Gia_ObjIsAssigned(p) && Gia_SatObjValue(p) == fCompl; if ( Gia_SatObjPath0(p) && !Gia_SatPathCheckCutSat_rec( Gia_ObjFanin0(p), fCompl ^ Gia_ObjFaninC0(p) ) ) return 0; if ( Gia_SatObjPath1(p) && !Gia_SatPathCheckCutSat_rec( Gia_ObjFanin1(p), fCompl ^ Gia_ObjFaninC1(p) ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Checks if the give cut is satisfied.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_SatPathCheckCutSat( Gia_Obj_t * p ) { int RetValue; assert( Gia_SatObjIsRoot(p) ); Gia_SatObjXorRoot(p); RetValue = Gia_SatPathCheckCutSat_rec( p ); Gia_SatObjXorRoot(p); return RetValue; } /**Function************************************************************* Synopsis [Unbinds literals on the path.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_SatPathUnbind_rec( Gia_Obj_t * p ) { } /**Function************************************************************* Synopsis [Creates a feasible path from the node to a terminal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_SatPathStart_rec( Gia_Obj_t * p, int fDiffs, int fCompl ) { if ( Gia_SatObjIsRoot(p) ) return fDiffs && (!Gia_ObjIsAssigned(p) || Gia_SatObjValue(p) != fCompl); if ( fCompl == 0 ) { if ( Gia_SatPathStart_rec( Gia_ObjFanin0(p), fDiffs + !Gia_SatObjPath0(p), fCompl ^ Gia_ObjFaninC0(p) ) && Gia_SatPathStart_rec( Gia_ObjFanin1(p), fDiffs + !Gia_SatObjPath1(p), fCompl ^ Gia_ObjFaninC1(p) ) ) return Gia_ObjSetDraftPath0(p) + Gia_ObjSetDraftPath1(p); } else { if ( Gia_SatPathStart_rec( Gia_ObjFanin0(p), fDiffs + !Gia_SatObjPath0(p), fCompl ^ Gia_ObjFaninC0(p) ) ) { Gia_ObjUnsetDraftPath1(p); return Gia_ObjSetDraftPath0(p); } if ( Gia_SatPathStart_rec( Gia_ObjFanin1(p), fDiffs + !Gia_SatObjPath1(p), fCompl ^ Gia_ObjFaninC1(p) ) ) { Gia_ObjUnsetDraftPath0(p); return Gia_ObjSetDraftPath1(p); } } return 0; } /**Function************************************************************* Synopsis [Creates a feasible path from the node to a terminal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_SatPathStart( Gia_Obj_t * p ) { int RetValue; assert( Gia_SatObjIsRoot(p) ); Gia_SatObjXorRoot(p); RetValue = Gia_SatPathStart_rec( p, 0, 0 ); Gia_SatObjXorRoot(p); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaQbf.c000066400000000000000000001353571477524141600156420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaQbf.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [QBF solver.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 18, 2014.] Revision [$Id: giaQbf.c,v 1.00 2014/10/18 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" #include "misc/extra/extra.h" #include "sat/glucose/AbcGlucose.h" #include "misc/util/utilTruth.h" #include "base/io/ioResub.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Qbf_Man_t_ Qbf_Man_t; struct Qbf_Man_t_ { Gia_Man_t * pGia; // original miter int nPars; // parameter variables int nVars; // functional variables int fVerbose; // verbose flag // internal variables int iParVarBeg; // SAT var ID of the first par variable in the ver solver sat_solver * pSatVer; // verification instance sat_solver * pSatSyn; // synthesis instance bmcg_sat_solver*pSatSynG; // synthesis instance Vec_Int_t * vValues; // variable values Vec_Int_t * vParMap; // parameter mapping Vec_Int_t * vLits; // literals for the SAT solver abctime clkStart; // global timeout abctime clkSat; // SAT solver time }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Generating QBF miter to solve the induction problem.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_GenCollectFlopIndexes( char * pStr, int nLutNum, int nLutSize, int nFlops ) { int nDups; char * pTemp; Vec_Int_t * vFlops; assert( nLutSize * nLutNum <= nFlops ); if ( pStr == NULL ) return Vec_IntStartNatural( nLutNum * nLutSize ); vFlops = Vec_IntAlloc( nLutNum * nLutSize ); pTemp = strtok( pStr, ", " ); while ( pTemp ) { int iFlop = atoi(pTemp); if ( iFlop >= nFlops ) { printf( "Flop index (%d) exceeds the number of flops (%d).\n", iFlop, nFlops ); break; } Vec_IntPush( vFlops, iFlop ); pTemp = strtok( NULL, ", " ); } if ( Vec_IntSize(vFlops) != nLutNum * nLutSize ) { printf( "Gia_GenCollectFlopIndexes: Expecting %d flop indexes (instead of %d).\n", nLutNum * nLutSize, Vec_IntSize(vFlops) ); Vec_IntFree( vFlops ); return NULL; } nDups = Vec_IntCountDuplicates(vFlops); if ( nDups ) { printf( "Gia_GenCollectFlopIndexes: There are %d duplicated flops in the list.\n", nDups ); Vec_IntFree( vFlops ); return NULL; } return vFlops; } int Gia_GenCreateMux_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_GenCreateMux_rec( pNew, pCtrl, nCtrl-1, vData, Shift ); iLit1 = Gia_GenCreateMux_rec( pNew, pCtrl, nCtrl-1, vData, Shift + (1<<(nCtrl-1)) ); return Gia_ManHashMux( pNew, pCtrl[nCtrl-1], iLit1, iLit0 ); } Vec_Int_t * Gia_GenCreateMuxes( Gia_Man_t * p, Gia_Man_t * pNew, Vec_Int_t * vFlops, int nLutNum, int nLutSize, Vec_Int_t * vParLits, int fUseRi ) { Vec_Int_t * vLits = Vec_IntAlloc( nLutNum ); int i, k, iMux, iFlop, pCtrl[16]; // add MUXes for each group of flops assert( Vec_IntSize(vFlops) == nLutNum * nLutSize ); for ( i = 0; i < nLutNum; i++ ) { for ( k = 0; k < nLutSize; k++ ) { iFlop = Vec_IntEntry(vFlops, i * nLutSize + k); assert( iFlop >= 0 && iFlop < Gia_ManRegNum(p) ); if ( fUseRi ) pCtrl[k] = Gia_ManRi(p, iFlop)->Value; else pCtrl[k] = Gia_ManRo(p, iFlop)->Value; } iMux = Gia_GenCreateMux_rec( pNew, pCtrl, nLutSize, vParLits, i * (1 << nLutSize) ); Vec_IntPush( vLits, iMux ); } return vLits; } 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, 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) vParLits = Vec_IntAlloc( nPars ); for ( i = 0; i < nPars; i++ ) Vec_IntPush( vParLits, i ? Abc_Var2Lit(i+1, 0) : 1 ); // create new manager 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; for ( i = 0; i < nPars; i++ ) Gia_ManAppendCi( 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_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); 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)) ); /////////////////////////////////////////////////////////////////////////// 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 Vec_IntFree( vLits0 ); Vec_IntFree( vLits1 ); Vec_IntFree( vFlops ); Vec_IntFree( vParLits ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSatEnum( Gia_Man_t * pGia, int nConfLimit, int nTimeOut, int fVerbose ) { Cnf_Dat_t * pCnf; sat_solver * pSat; Vec_Int_t * vLits; int i, iLit, iParVarBeg, Iter; int nSolutions = 0, RetValue = 0; abctime clkStart = Abc_Clock(); pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pGia, 8, 0, 1, 0, 0 ); pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); iParVarBeg = pCnf->nVars - Gia_ManPiNum(pGia);// - 1; Cnf_DataFree( pCnf ); // iterate through the SAT assignment vLits = Vec_IntAlloc( Gia_ManPiNum(pGia) ); for ( Iter = 1 ; ; Iter++ ) { int status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 ); if ( status == l_False ) { RetValue = 1; break; } if ( status == l_Undef ) { RetValue = 0; break; } nSolutions++; // extract SAT assignment Vec_IntClear( vLits ); for ( i = 0; i < Gia_ManPiNum(pGia); i++ ) Vec_IntPush( vLits, Abc_Var2Lit(iParVarBeg+i, sat_solver_var_value(pSat, iParVarBeg+i)) ); if ( fVerbose ) { printf( "%5d : ", Iter ); Vec_IntForEachEntry( vLits, iLit, i ) printf( "%d", !Abc_LitIsCompl(iLit) ); printf( "\n" ); } // add clause if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ) ) { RetValue = 1; break; } if ( nTimeOut && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= nTimeOut ) { RetValue = 0; break; } } sat_solver_delete( pSat ); Vec_IntFree( vLits ); if ( nTimeOut && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= nTimeOut ) printf( "Enumerated %d assignments when timeout (%d sec) was reached. ", nSolutions, nTimeOut ); else if ( nConfLimit && !RetValue ) printf( "Enumerated %d assignments when conflict limit (%d) was reached. ", nSolutions, nConfLimit ); else printf( "Enumerated the complete set of %d assignments. ", nSolutions ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); return RetValue; } /**Function************************************************************* Synopsis [Dumps the original problem in QDIMACS format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_QbfDumpFile( 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, * vExists; Gia_Obj_t * pObj; char * pFileName; int i, Entry; // create var map vVarMap = Vec_IntStart( pCnf->nVars ); Gia_ManForEachCi( pGia, pObj, i ) if ( i < nPars ) Vec_IntWriteEntry( vVarMap, pCnf->pVarNums[Gia_ManCiIdToId(pGia, i)], 1 ); // create various maps vForAlls = Vec_IntAlloc( nPars ); vExists = Vec_IntAlloc( Gia_ManCiNum(pGia) - nPars ); Vec_IntForEachEntry( vVarMap, Entry, i ) if ( Entry ) Vec_IntPush( vForAlls, i ); else Vec_IntPush( vExists, i ); // generate CNF pFileName = Extra_FileNameGenericAppend( pGia->pSpec, ".qdimacs" ); Cnf_DataWriteIntoFile( pCnf, pFileName, 0, vForAlls, vExists ); Cnf_DataFree( pCnf ); Vec_IntFree( vForAlls ); Vec_IntFree( vExists ); 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************************************************************* Synopsis [Generate one SAT assignment of the problem.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Qbf_Man_t * Gia_QbfAlloc( Gia_Man_t * pGia, int nPars, int fGlucose, int fVerbose ) { Qbf_Man_t * p; Cnf_Dat_t * pCnf; Gia_ObjFlipFaninC0( Gia_ManPo(pGia, 0) ); pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pGia, 8, 0, 1, 0, 0 ); Gia_ObjFlipFaninC0( Gia_ManPo(pGia, 0) ); p = ABC_CALLOC( Qbf_Man_t, 1 ); p->clkStart = Abc_Clock(); p->pGia = pGia; p->nPars = nPars; p->nVars = Gia_ManPiNum(pGia) - nPars; p->fVerbose = fVerbose; p->iParVarBeg = pCnf->nVars - Gia_ManPiNum(pGia);// - 1; p->pSatVer = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); p->pSatSyn = sat_solver_new(); p->pSatSynG = fGlucose ? bmcg_sat_solver_start() : NULL; p->vValues = Vec_IntAlloc( Gia_ManPiNum(pGia) ); p->vParMap = Vec_IntStartFull( nPars ); p->vLits = Vec_IntAlloc( nPars ); sat_solver_setnvars( p->pSatSyn, nPars ); if ( p->pSatSynG ) bmcg_sat_solver_set_nvars( p->pSatSynG, nPars ); Cnf_DataFree( pCnf ); return p; } void Gia_QbfFree( Qbf_Man_t * p ) { sat_solver_delete( p->pSatVer ); sat_solver_delete( p->pSatSyn ); if ( p->pSatSynG ) bmcg_sat_solver_stop( p->pSatSynG ); Vec_IntFree( p->vLits ); Vec_IntFree( p->vValues ); Vec_IntFree( p->vParMap ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Create and add one cofactor.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_QbfQuantifyOne( Gia_Man_t * p, int iVar, int fAndAll, int fOrAll ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; Vec_Int_t * vCofs; int i, c; pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); // compute cofactors vCofs = Vec_IntAlloc( 2 * Gia_ManPoNum(p) ); for ( c = 0; c < 2; c++ ) { Gia_ManPi(p, iVar)->Value = c; Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachPo( p, pObj, i ) Vec_IntPush( vCofs, Gia_ObjFanin0Copy(pObj) ); } if ( fAndAll ) { for ( i = 0; i < Gia_ManPoNum(p); i++ ) Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, Vec_IntEntry(vCofs, i), Vec_IntEntry(vCofs, Gia_ManPoNum(p)+i)) ); } else if ( fOrAll ) { for ( i = 0; i < Gia_ManPoNum(p); i++ ) Gia_ManAppendCo( pNew, Gia_ManHashOr(pNew, Vec_IntEntry(vCofs, i), Vec_IntEntry(vCofs, Gia_ManPoNum(p)+i)) ); } else { Vec_IntForEachEntry( vCofs, c, i ) Gia_ManAppendCo( pNew, c ); } Vec_IntFree( vCofs ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } Gia_Man_t * Gia_QbfQuantifyAll( Gia_Man_t * p, int nPars, int fAndAll, int fOrAll ) { Gia_Man_t * pNew, * pTemp; int v; pNew = Gia_ManDup( p ); for ( v = Gia_ManPiNum(p) - 1; v >= nPars; v-- ) { pNew = Gia_QbfQuantifyOne( pTemp = pNew, v, fAndAll, fOrAll ); Gia_ManStop( pTemp ); } return pNew; } /**Function************************************************************* Synopsis [Create and add one cofactor.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_QbfCofactor( Gia_Man_t * p, int nPars, Vec_Int_t * vValues, Vec_Int_t * vParMap ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; assert( Gia_ManPiNum(p) == nPars + Vec_IntSize(vValues) ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); Gia_ManHashAlloc( pNew ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachPi( p, pObj, i ) if ( i < nPars ) { pObj->Value = Gia_ManAppendCi(pNew); if ( Vec_IntEntry(vParMap, i) != -1 ) pObj->Value = Vec_IntEntry(vParMap, i); } else pObj->Value = Vec_IntEntry(vValues, i - nPars); Gia_ManForEachAnd( p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); assert( Gia_ManPiNum(pNew) == nPars ); return pNew; } /* int Gia_QbfAddCofactor( Qbf_Man_t * p, Gia_Man_t * pCof ) { Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pCof, 8, 0, 1, 0, 0 ); int i, iFirstVar = sat_solver_nvars(p->pSatSyn) + pCnf->nVars - Gia_ManPiNum(pCof);// - 1; pCnf->pMan = NULL; Cnf_DataLift( pCnf, sat_solver_nvars(p->pSatSyn) ); for ( i = 0; i < pCnf->nClauses; i++ ) if ( !sat_solver_addclause( p->pSatSyn, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) { Cnf_DataFree( pCnf ); return 0; } Cnf_DataFree( pCnf ); // add connection clauses for ( i = 0; i < Gia_ManPiNum(p->pGia); i++ ) if ( !sat_solver_add_buffer( p->pSatSyn, i, iFirstVar+i, 0 ) ) return 0; return 1; } */ void Cnf_SpecialDataLift( Cnf_Dat_t * p, int nVarsPlus, int firstPiVar, int lastPiVar) { int v, var; for ( v = 0; v < p->nLiterals; v++ ) { var = p->pClauses[0][v] / 2; if (var < firstPiVar || var >= lastPiVar) p->pClauses[0][v] += 2*nVarsPlus; else p->pClauses[0][v] -= 2*firstPiVar; } } int Gia_QbfAddCofactor( Qbf_Man_t * p, Gia_Man_t * pCof ) { Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pCof, 8, 0, 1, 0, 0 ); int i, useold = 0; int iFirstVar = useold ? sat_solver_nvars(p->pSatSyn) + pCnf->nVars - Gia_ManPiNum(pCof) : pCnf->nVars - Gia_ManPiNum(pCof); //-1 pCnf->pMan = NULL; if (useold) Cnf_DataLift( pCnf, sat_solver_nvars(p->pSatSyn) ); else Cnf_SpecialDataLift( pCnf, sat_solver_nvars(p->pSatSyn), iFirstVar, iFirstVar + Gia_ManPiNum(p->pGia) ); for ( i = 0; i < pCnf->nClauses; i++ ) if ( !sat_solver_addclause( p->pSatSyn, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) { Cnf_DataFree( pCnf ); return 0; } Cnf_DataFree( pCnf ); // add connection clauses if (useold) for ( i = 0; i < Gia_ManPiNum(p->pGia); i++ ) if ( !sat_solver_add_buffer( p->pSatSyn, i, iFirstVar+i, 0 ) ) return 0; return 1; } int Gia_QbfAddCofactorG( Qbf_Man_t * p, Gia_Man_t * pCof ) { Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pCof, 8, 0, 1, 0, 0 ); int i, iFirstVar = pCnf->nVars - Gia_ManPiNum(pCof); //-1 pCnf->pMan = NULL; Cnf_SpecialDataLift( pCnf, bmcg_sat_solver_varnum(p->pSatSynG), iFirstVar, iFirstVar + Gia_ManPiNum(p->pGia) ); for ( i = 0; i < pCnf->nClauses; i++ ) if ( !bmcg_sat_solver_addclause( p->pSatSynG, pCnf->pClauses[i], pCnf->pClauses[i+1]-pCnf->pClauses[i] ) ) { Cnf_DataFree( pCnf ); return 0; } Cnf_DataFree( pCnf ); return 1; } /**Function************************************************************* Synopsis [Extract SAT assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_QbfOnePattern( Qbf_Man_t * p, Vec_Int_t * vValues ) { int i; Vec_IntClear( vValues ); for ( i = 0; i < p->nPars; i++ ) Vec_IntPush( vValues, p->pSatSynG ? bmcg_sat_solver_read_cex_varvalue(p->pSatSynG, i) : sat_solver_var_value(p->pSatSyn, i) ); } void Gia_QbfPrint( Qbf_Man_t * p, Vec_Int_t * vValues, int Iter ) { printf( "%5d : ", Iter ); assert( Vec_IntSize(vValues) == p->nVars ); Vec_IntPrintBinary( vValues ); printf( " " ); printf( "Var =%7d ", p->pSatSynG ? bmcg_sat_solver_varnum(p->pSatSynG) : sat_solver_nvars(p->pSatSyn) ); printf( "Cla =%7d ", p->pSatSynG ? bmcg_sat_solver_clausenum(p->pSatSynG) : sat_solver_nclauses(p->pSatSyn) ); printf( "Conf =%9d ", p->pSatSynG ? bmcg_sat_solver_conflictnum(p->pSatSynG) : sat_solver_nconflicts(p->pSatSyn) ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); } /**Function************************************************************* Synopsis [Generate one SAT assignment in terms of functional vars.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_QbfVerify( Qbf_Man_t * p, Vec_Int_t * vValues ) { int i, Entry, RetValue; assert( Vec_IntSize(vValues) == p->nPars ); Vec_IntClear( p->vLits ); Vec_IntForEachEntry( vValues, Entry, i ) Vec_IntPush( p->vLits, Abc_Var2Lit(p->iParVarBeg+i, !Entry) ); RetValue = sat_solver_solve( p->pSatVer, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits), 0, 0, 0, 0 ); if ( RetValue == l_True ) { Vec_IntClear( vValues ); for ( i = 0; i < p->nVars; i++ ) Vec_IntPush( vValues, sat_solver_var_value(p->pSatVer, p->iParVarBeg+p->nPars+i) ); } return RetValue == l_True ? 1 : 0; } /**Function************************************************************* Synopsis [Constraint learning.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_QbfAddSpecialConstr( Qbf_Man_t * p ) { int i, status, Lits[2]; for ( i = 0; i < 4*11; i++ ) if ( i % 4 == 0 ) { assert( Vec_IntEntry(p->vParMap, i) == -1 ); Vec_IntWriteEntry( p->vParMap, i, (i % 4) == 3 ); Lits[0] = Abc_Var2Lit( i, (i % 4) != 3 ); status = sat_solver_addclause( p->pSatSyn, Lits, Lits+1 ); assert( status ); } } void Gia_QbfLearnConstraint( Qbf_Man_t * p, Vec_Int_t * vValues ) { int i, status, Entry, Lits[2]; assert( Vec_IntSize(vValues) == p->nPars ); printf( " Pattern " ); Vec_IntPrintBinary( vValues ); printf( "\n" ); Vec_IntForEachEntry( vValues, Entry, i ) { Lits[0] = Abc_Var2Lit( i, Entry ); status = sat_solver_solve( p->pSatSyn, Lits, Lits+1, 0, 0, 0, 0 ); printf( " Var =%4d ", i ); if ( status != l_True ) { printf( "UNSAT\n" ); Lits[0] = Abc_LitNot(Lits[0]); status = sat_solver_addclause( p->pSatSyn, Lits, Lits+1 ); assert( status ); continue; } Gia_QbfOnePattern( p, p->vLits ); Vec_IntPrintBinary( p->vLits ); printf( "\n" ); } assert( Vec_IntSize(vValues) == p->nPars ); } /**Function************************************************************* Synopsis [Performs QBF solving using an improved algorithm.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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; int i, status, RetValue = 0; abctime clk; // Gia_QbfAddSpecialConstr( p ); if ( fVerbose ) printf( "Solving QBF for \"%s\" with %d parameters, %d variables and %d AIG nodes.\n", Gia_ManName(pGia), p->nPars, p->nVars, Gia_ManAndNum(pGia) ); assert( Gia_ManRegNum(pGia) == 0 ); Vec_IntFill( p->vValues, nPars, 0 ); for ( i = 0; Gia_QbfVerify(p, p->vValues); i++ ) { // generate next constraint assert( Vec_IntSize(p->vValues) == p->nVars ); pCof = Gia_QbfCofactor( pGia, nPars, p->vValues, p->vParMap ); status = p->pSatSynG ? Gia_QbfAddCofactorG( p, pCof ) : Gia_QbfAddCofactor( p, pCof ); Gia_ManStop( pCof ); if ( status == 0 ) { RetValue = 1; break; } // synthesize next assignment clk = Abc_Clock(); if ( p->pSatSynG ) status = bmcg_sat_solver_solve( p->pSatSynG, NULL, 0 ); else status = sat_solver_solve( p->pSatSyn, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 ); p->clkSat += Abc_Clock() - clk; if ( fVerbose ) Gia_QbfPrint( p, p->vValues, i ); if ( status == l_False ) { RetValue = 1; break; } if ( status == l_Undef ) { RetValue = -1; break; } // extract SAT assignment Gia_QbfOnePattern( p, p->vValues ); assert( Vec_IntSize(p->vValues) == p->nPars ); // examine variables // Gia_QbfLearnConstraint( p, p->vValues ); // Vec_IntPrintBinary( p->vValues ); printf( "\n" ); if ( nIterLimit && i+1 == nIterLimit ) { RetValue = -1; break; } if ( nTimeOut && (Abc_Clock() - p->clkStart)/CLOCKS_PER_SEC >= nTimeOut ) { RetValue = -1; break; } } if ( RetValue == 0 ) { int nZeros = Vec_IntCountZero( p->vValues ); printf( "Parameters: " ); 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 ); else if ( RetValue == -1 && nConfLimit ) printf( "The problem aborted after %d conflicts. ", nConfLimit ); else if ( RetValue == -1 && nIterLimit ) printf( "The problem aborted after %d iterations. ", nIterLimit ); else if ( RetValue == 1 ) printf( "The problem is UNSAT after %d iterations. ", i ); else printf( "The problem is SAT after %d iterations. ", i ); if ( fVerbose ) { printf( "\n" ); Abc_PrintTime( 1, "SAT ", p->clkSat ); Abc_PrintTime( 1, "Other", Abc_Clock() - p->clkStart - p->clkSat ); Abc_PrintTime( 1, "TOTAL", Abc_Clock() - p->clkStart ); } else Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); Gia_QbfFree( p ); return RetValue; } /**Function************************************************************* Synopsis [Derive the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ sat_solver * Gia_ManGenSolver( Gia_Man_t * p, Vec_Int_t * vInsOuts, int nIns ) { Gia_Obj_t * pObj; int i, nObjs = Gia_ManObjNum(p); sat_solver * pSat = sat_solver_new(); sat_solver_setnvars( pSat, 2 * nObjs ); Gia_ManIncrementTravId(p); Gia_ManForEachObjVecStart( vInsOuts, p, pObj, i, nIns ) Gia_ObjSetTravIdCurrent(p, pObj); Gia_ManForEachAnd( p, pObj, i ) if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) sat_solver_add_and( pSat, i, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninId1(pObj, i), Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); Gia_ManForEachAnd( p, pObj, i ) sat_solver_add_and( pSat, nObjs+i, nObjs+Gia_ObjFaninId0(pObj, i), nObjs+Gia_ObjFaninId1(pObj, i), Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); Gia_ManForEachCi( p, pObj, i ) if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) sat_solver_add_buffer( pSat, nObjs+Gia_ObjId(p, pObj), Gia_ObjId(p, pObj), 0 ); Gia_ManForEachCo( p, pObj, i ) if ( Gia_ObjFaninId0p(p, pObj) > 0 ) { sat_solver_add_buffer( pSat, Gia_ObjId(p, pObj), Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj) ); sat_solver_add_buffer( pSat, nObjs+Gia_ObjId(p, pObj), nObjs+Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj) ); sat_solver_add_buffer( pSat, nObjs+Gia_ObjId(p, pObj), Gia_ObjId(p, pObj), 0 ); } return pSat; } Vec_Int_t * Gia_ManGenCombs( Gia_Man_t * p, Vec_Int_t * vInsOuts, int nIns, int fVerbose ) { int nTimeOut = 600, nConfLimit = 1000000; int i, iSatVar, Iter, Mask, nSolutions = 0, RetValue = 0; abctime clkStart = Abc_Clock(); sat_solver * pSat = Gia_ManGenSolver( p, vInsOuts, nIns ); Vec_Int_t * vLits = Vec_IntAlloc( 100 ); Vec_Int_t * vRes = Vec_IntAlloc( 1000 ); for ( Iter = 0; Iter < 1000000; Iter++ ) { int status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 ); if ( status == l_False ) { RetValue = 1; break; } if ( status == l_Undef ) { RetValue = 0; break; } nSolutions++; // extract SAT assignment Mask = 0; Vec_IntClear( vLits ); Vec_IntForEachEntry( vInsOuts, iSatVar, i ) { Vec_IntPush( vLits, Abc_Var2Lit(iSatVar, sat_solver_var_value(pSat, iSatVar)) ); if ( sat_solver_var_value(pSat, iSatVar) ) Mask |= 1 << (Vec_IntSize(vInsOuts)-1-i); } Vec_IntPush( vRes, Mask ); if ( fVerbose ) { printf( "%5d : ", Iter ); Vec_IntForEachEntry( vInsOuts, iSatVar, i ) { if ( i == nIns ) printf( " " ); printf( "%d", (Mask >> (Vec_IntSize(vInsOuts)-1-i)) & 1 ); } printf( "\n" ); } // add clause if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ) ) { RetValue = 1; break; } if ( nTimeOut && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= nTimeOut ) { RetValue = 0; break; } } Vec_IntSort( vRes, 0 ); Vec_IntFree( vLits ); sat_solver_delete( pSat ); if ( RetValue == 0 ) Vec_IntFreeP( &vRes ); if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); return vRes; } void Gia_ManGenWriteRel( Vec_Int_t * vRes, int nIns, int nOuts, char * pFileName ) { int i, k, Mask, nVars = nIns + nOuts; Abc_RData_t * p2, * p = Abc_RDataStart( nIns, nOuts, Vec_IntSize(vRes) ); Vec_IntForEachEntry( vRes, Mask, i ) { for ( k = 0; k < nVars; k++ ) if ( (Mask >> (nVars-1-k)) & 1 ) { // the bit is 1 if ( k < nIns ) Abc_RDataSetIn( p, k, i ); else Abc_RDataSetOut( p, 2*(k-nIns)+1, i ); } else { // the bit is zero if ( k >= nIns ) Abc_RDataSetOut( p, 2*(k-nIns), i ); } } Abc_WritePla( p, pFileName, 0 ); p2 = Abc_RData2Rel( p ); Abc_WritePla( p2, Extra_FileNameGenericAppend(pFileName, "_rel.pla"), 1 ); Abc_RDataStop( p2 ); Abc_RDataStop( p ); } void Gia_ManGenRel2( Gia_Man_t * pGia, Vec_Int_t * vInsOuts, int nIns, char * pFileName, int fVerbose ) { Vec_Int_t * vRes = Gia_ManGenCombs( pGia, vInsOuts, nIns, fVerbose ); if ( vRes == NULL ) { printf( "Enumerating solutions did not succeed.\n" ); return; } Gia_ManGenWriteRel( vRes, nIns, Vec_IntSize(vInsOuts)-nIns, pFileName ); Vec_IntFree( vRes ); } /**Function************************************************************* Synopsis [Derive the SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManCollectNodeTfos( Gia_Man_t * p, int * pNodes, int nNodes ) { Vec_Int_t * vTfo = Vec_IntAlloc( 100 ); Gia_Obj_t * pObj; int i; Gia_ManIncrementTravId( p ); for ( i = 0; i < nNodes; i++ ) Gia_ObjSetTravIdCurrentId( p, pNodes[i] ); Gia_ManForEachAnd( p, pObj, i ) { if ( Gia_ObjIsTravIdCurrentId(p, i) ) continue; if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)) || Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)) ) Gia_ObjSetTravIdCurrentId( p, i ), Vec_IntPush( vTfo, i ); } Gia_ManForEachCo( p, pObj, i ) if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0p(p, pObj)) ) Vec_IntPush( vTfo, Gia_ObjId(p, pObj) ); return vTfo; } Vec_Int_t * Gia_ManCollectNodeTfis( Gia_Man_t * p, Vec_Int_t * vNodes ) { Vec_Int_t * vTfi = Vec_IntAlloc( 100 ); Gia_Obj_t * pObj; int i, Id; Gia_ManIncrementTravId( p ); Gia_ManForEachObjVec( vNodes, p, pObj, i ) if ( Gia_ObjIsCo(pObj) ) Gia_ObjSetTravIdCurrentId( p, Gia_ObjFaninId0p(p, pObj) ); Gia_ManForEachAndReverse( p, pObj, i ) { if ( !Gia_ObjIsTravIdCurrentId(p, i) ) continue; Gia_ObjSetTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)); Gia_ObjSetTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)); } Gia_ManForEachCiId( p, Id, i ) if ( Gia_ObjIsTravIdCurrentId(p, Id) ) Vec_IntPush( vTfi, Id ); Gia_ManForEachAnd( p, pObj, i ) if ( Gia_ObjIsTravIdCurrentId(p, i) ) Vec_IntPush( vTfi, i ); return vTfi; } Gia_Man_t * Gia_ManGenRelMiter( Gia_Man_t * pGia, Vec_Int_t * vInsOuts, int nIns ) { Vec_Int_t * vTfo = Gia_ManCollectNodeTfos( pGia, Vec_IntEntryP(vInsOuts, nIns), Vec_IntSize(vInsOuts)-nIns ); Vec_Int_t * vTfi = Gia_ManCollectNodeTfis( pGia, vTfo ); Vec_Int_t * vInLits = Vec_IntAlloc( nIns ); Vec_Int_t * vOutLits = Vec_IntAlloc( Vec_IntSize(vInsOuts) - nIns ); Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iLit = 0; Gia_ManFillValue( pGia ); pNew = Gia_ManStart( 1000 ); pNew->pName = Abc_UtilStrsav( pGia->pName ); Gia_ManHashAlloc( pNew ); Gia_ManForEachObjVec( vTfi, pGia, pObj, i ) if ( Gia_ObjIsCi(pObj) ) pObj->Value = Gia_ManAppendCi(pNew); for ( i = 0; i < Vec_IntSize(vInsOuts)-nIns; i++ ) Vec_IntPush( vInLits, Gia_ManAppendCi(pNew) ); Gia_ManForEachObjVec( vTfi, pGia, pObj, i ) if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachObjVec( vTfo, pGia, pObj, i ) if ( Gia_ObjIsCo(pObj) ) pObj->Value = Gia_ObjFanin0Copy(pObj); Gia_ManForEachObjVec( vInsOuts, pGia, pObj, i ) if ( i < nIns ) Vec_IntPush( vOutLits, pObj->Value ); else pObj->Value = Vec_IntEntry( vInLits, i-nIns ); Gia_ManForEachObjVec( vTfo, pGia, pObj, i ) if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManForEachObjVec( vTfo, pGia, pObj, i ) if ( Gia_ObjIsCo(pObj) ) iLit = Gia_ManHashOr( pNew, iLit, Gia_ManHashXor(pNew, Gia_ObjFanin0Copy(pObj), pObj->Value) ); Gia_ManAppendCo( pNew, iLit ); Vec_IntForEachEntry( vOutLits, iLit, i ) Gia_ManAppendCo( pNew, iLit ); Vec_IntFree( vTfo ); Vec_IntFree( vTfi ); Vec_IntFree( vInLits ); Vec_IntFree( vOutLits ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); return pNew; } void Gia_ManPrintRelMinterm( int Mint, int nIns, int nVars ) { for ( int i = 0; i < nVars; i++ ) printf( "%s%d", i == nIns ? " ":"", (Mint >> (nVars-1-i)) & 1 ); printf( "\n" ); } Vec_Int_t * Gia_ManGenIoCombs( Gia_Man_t * pGia, Vec_Int_t * vInsOuts, int nIns, int fVerbose ) { abctime clkStart = Abc_Clock(); int nTimeOut = 600, nConfLimit = 1000000; int i, iNode, iSatVar, Iter, Mask, nSolutions = 0, RetValue = 0; Gia_Man_t * pMiter = Gia_ManGenRelMiter( pGia, vInsOuts, nIns ); Cnf_Dat_t * pCnf = (Cnf_Dat_t*)Mf_ManGenerateCnf( pMiter, 8, 0, 0, 0, 0 ); sat_solver * pSat = (sat_solver*)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); int iLit = Abc_Var2Lit( 1, 0 ); // enumerating the care set (the miter output is 1) int status = sat_solver_addclause( pSat, &iLit, &iLit + 1 ); assert( status ); Vec_Int_t * vSatVars = Vec_IntAlloc( Vec_IntSize(vInsOuts) ); Vec_IntForEachEntry( vInsOuts, iNode, i ) Vec_IntPush( vSatVars, i < nIns ? 2+i : pCnf->nVars-Vec_IntSize(vInsOuts)+i ); Vec_Int_t * vLits = Vec_IntAlloc( 100 ); Vec_Int_t * vRes = Vec_IntAlloc( 1000 ); for ( Iter = 0; Iter < 1000000; Iter++ ) { int status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 ); if ( status == l_False ) { RetValue = 1; break; } if ( status == l_Undef ) { RetValue = 0; break; } nSolutions++; // extract SAT assignment Mask = 0; Vec_IntClear( vLits ); Vec_IntForEachEntry( vSatVars, iSatVar, i ) { Vec_IntPush( vLits, Abc_Var2Lit(iSatVar, sat_solver_var_value(pSat, iSatVar)) ); if ( sat_solver_var_value(pSat, iSatVar) ) Mask |= 1 << (Vec_IntSize(vInsOuts)-1-i); } Vec_IntPush( vRes, Mask ); if ( 0 ) { printf( "%5d : ", Iter ); Gia_ManPrintRelMinterm( Mask, nIns, Vec_IntSize(vSatVars) ); } // add clause if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ) ) { RetValue = 1; break; } if ( nTimeOut && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= nTimeOut ) { RetValue = 0; break; } } // complement the set of input/output minterms Vec_Int_t * vBits = Vec_IntStart( 1 << Vec_IntSize(vInsOuts) ); Vec_IntForEachEntry( vRes, Mask, i ) Vec_IntWriteEntry( vBits, Mask, 1 ); Vec_IntClear( vRes ); Vec_IntForEachEntry( vBits, Mask, i ) if ( !Mask ) Vec_IntPush( vRes, i ); Vec_IntFree( vBits ); // cleanup Vec_IntFree( vLits ); sat_solver_delete( pSat ); Gia_ManStop( pMiter ); Cnf_DataFree( pCnf ); if ( RetValue == 0 ) Vec_IntFreeP( &vRes ); return vRes; } void Gia_ManGenRel( Gia_Man_t * pGia, Vec_Int_t * vInsOuts, int nIns, char * pFileName, int fVerbose ) { abctime clkStart = Abc_Clock(); Vec_Int_t * vRes = Gia_ManGenIoCombs( pGia, vInsOuts, nIns, fVerbose ); if ( vRes == NULL ) { printf( "Enumerating solutions did not succeed.\n" ); return; } Gia_ManGenWriteRel( vRes, nIns, Vec_IntSize(vInsOuts)-nIns, pFileName ); if ( fVerbose ) { printf( "The resulting relation with %d input/output minterms is written into file \"%s\". ", Vec_IntSize(vRes), pFileName ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); if ( 0 ) { int i, Mint; Vec_IntForEachEntry( vRes, Mint, i ) Gia_ManPrintRelMinterm( Mint, nIns, Vec_IntSize(vInsOuts) ); } } Vec_IntFree( vRes ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaReshape1.c000066400000000000000000000030311477524141600165610ustar00rootroot00000000000000/**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 abc-0.52/src/aig/gia/giaReshape2.c000066400000000000000000000030301477524141600165610ustar00rootroot00000000000000/**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 abc-0.52/src/aig/gia/giaResub.c000066400000000000000000002413471477524141600162070ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaResub.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: giaResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/vec/vecWec.h" #include "misc/vec/vecQue.h" #include "misc/vec/vecHsh.h" #include "misc/util/utilTruth.h" #include "base/io/ioResub.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes MFFCs of all qualifying nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ObjCheckMffc_rec( Gia_Man_t * p,Gia_Obj_t * pObj, int Limit, Vec_Int_t * vNodes ) { int iFanin; if ( Gia_ObjIsCi(pObj) ) return 1; assert( Gia_ObjIsAnd(pObj) ); iFanin = Gia_ObjFaninId0p(p, pObj); Vec_IntPush( vNodes, iFanin ); if ( !Gia_ObjRefDecId(p, iFanin) && (Vec_IntSize(vNodes) > Limit || !Gia_ObjCheckMffc_rec(p, Gia_ObjFanin0(pObj), Limit, vNodes)) ) return 0; iFanin = Gia_ObjFaninId1p(p, pObj); Vec_IntPush( vNodes, iFanin ); if ( !Gia_ObjRefDecId(p, iFanin) && (Vec_IntSize(vNodes) > Limit || !Gia_ObjCheckMffc_rec(p, Gia_ObjFanin1(pObj), Limit, vNodes)) ) return 0; if ( !Gia_ObjIsMux(p, pObj) ) return 1; iFanin = Gia_ObjFaninId2p(p, pObj); Vec_IntPush( vNodes, iFanin ); if ( !Gia_ObjRefDecId(p, iFanin) && (Vec_IntSize(vNodes) > Limit || !Gia_ObjCheckMffc_rec(p, Gia_ObjFanin2(p, pObj), Limit, vNodes)) ) return 0; return 1; } int Gia_ObjCheckMffc( Gia_Man_t * p, Gia_Obj_t * pRoot, int Limit, Vec_Int_t * vNodes, Vec_Int_t * vLeaves, Vec_Int_t * vInners ) { int RetValue, iObj, i; Vec_IntClear( vNodes ); RetValue = Gia_ObjCheckMffc_rec( p, pRoot, Limit, vNodes ); if ( RetValue ) { Vec_IntClear( vLeaves ); Vec_IntClear( vInners ); Vec_IntSort( vNodes, 0 ); Vec_IntForEachEntry( vNodes, iObj, i ) if ( Gia_ObjRefNumId(p, iObj) > 0 || Gia_ObjIsCi(Gia_ManObj(p, iObj)) ) { if ( !Vec_IntSize(vLeaves) || Vec_IntEntryLast(vLeaves) != iObj ) Vec_IntPush( vLeaves, iObj ); } else { if ( !Vec_IntSize(vInners) || Vec_IntEntryLast(vInners) != iObj ) Vec_IntPush( vInners, iObj ); } Vec_IntPush( vInners, Gia_ObjId(p, pRoot) ); } Vec_IntForEachEntry( vNodes, iObj, i ) Gia_ObjRefIncId( p, iObj ); return RetValue; } Vec_Wec_t * Gia_ManComputeMffcs( Gia_Man_t * p, int LimitMin, int LimitMax, int SuppMax, int RatioBest ) { Gia_Obj_t * pObj; Vec_Wec_t * vMffcs; Vec_Int_t * vNodes, * vLeaves, * vInners, * vMffc; int i, iPivot; assert( p->pMuxes ); vNodes = Vec_IntAlloc( 2 * LimitMax ); vLeaves = Vec_IntAlloc( 2 * LimitMax ); vInners = Vec_IntAlloc( 2 * LimitMax ); vMffcs = Vec_WecAlloc( 1000 ); Gia_ManCreateRefs( p ); Gia_ManForEachAnd( p, pObj, i ) { if ( !Gia_ObjRefNum(p, pObj) ) continue; if ( !Gia_ObjCheckMffc(p, pObj, LimitMax, vNodes, vLeaves, vInners) ) continue; if ( Vec_IntSize(vInners) < LimitMin ) continue; if ( Vec_IntSize(vLeaves) > SuppMax ) continue; // improve cut // collect cut vMffc = Vec_WecPushLevel( vMffcs ); Vec_IntGrow( vMffc, Vec_IntSize(vLeaves) + Vec_IntSize(vInners) + 20 ); Vec_IntPush( vMffc, i ); Vec_IntPush( vMffc, Vec_IntSize(vLeaves) ); Vec_IntPush( vMffc, Vec_IntSize(vInners) ); Vec_IntAppend( vMffc, vLeaves ); // Vec_IntAppend( vMffc, vInners ); // add last entry equal to the ratio Vec_IntPush( vMffc, 1000 * Vec_IntSize(vInners) / Vec_IntSize(vLeaves) ); } Vec_IntFree( vNodes ); Vec_IntFree( vLeaves ); Vec_IntFree( vInners ); // sort MFFCs by their inner/leaf ratio Vec_WecSortByLastInt( vMffcs, 1 ); Vec_WecForEachLevel( vMffcs, vMffc, i ) Vec_IntPop( vMffc ); // remove those whose ratio is not good iPivot = RatioBest * Vec_WecSize(vMffcs) / 100; Vec_WecForEachLevelStart( vMffcs, vMffc, i, iPivot ) Vec_IntErase( vMffc ); assert( iPivot <= Vec_WecSize(vMffcs) ); Vec_WecShrink( vMffcs, iPivot ); return vMffcs; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintDivStats( Gia_Man_t * p, Vec_Wec_t * vMffcs, Vec_Wec_t * vPivots ) { int fVerbose = 0; Vec_Int_t * vMffc; int i, nDivs, nDivsAll = 0, nDivs0 = 0; Vec_WecForEachLevel( vMffcs, vMffc, i ) { nDivs = Vec_IntSize(vMffc) - 3 - Vec_IntEntry(vMffc, 1) - Vec_IntEntry(vMffc, 2); nDivs0 += (nDivs == 0); nDivsAll += nDivs; if ( !fVerbose ) continue; printf( "%6d : ", Vec_IntEntry(vMffc, 0) ); printf( "Leaf =%3d ", Vec_IntEntry(vMffc, 1) ); printf( "Mffc =%4d ", Vec_IntEntry(vMffc, 2) ); printf( "Divs =%4d ", nDivs ); printf( "\n" ); } printf( "Collected %d (%.1f %%) MFFCs and %d (%.1f %%) have no divisors (div ave for others is %.2f).\n", Vec_WecSize(vMffcs), 100.0 * Vec_WecSize(vMffcs) / Gia_ManAndNum(p), nDivs0, 100.0 * nDivs0 / Gia_ManAndNum(p), 1.0*nDivsAll/Abc_MaxInt(1, Vec_WecSize(vMffcs) - nDivs0) ); printf( "Using %.2f MB for MFFCs and %.2f MB for pivots. ", Vec_WecMemory(vMffcs)/(1<<20), Vec_WecMemory(vPivots)/(1<<20) ); } /**Function************************************************************* Synopsis [Compute divisors and Boolean functions for the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManAddDivisors( Gia_Man_t * p, Vec_Wec_t * vMffcs ) { Vec_Wec_t * vPivots; Vec_Int_t * vMffc, * vPivot, * vPivot0, * vPivot1; Vec_Int_t * vCommon, * vCommon2, * vMap; Gia_Obj_t * pObj; int i, k, iObj, iPivot, iMffc; //abctime clkStart = Abc_Clock(); // initialize pivots (mapping of nodes into MFFCs whose leaves they are) vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); vPivots = Vec_WecStart( Gia_ManObjNum(p) ); Vec_WecForEachLevel( vMffcs, vMffc, i ) { assert( Vec_IntSize(vMffc) == 3 + Vec_IntEntry(vMffc, 1) ); iPivot = Vec_IntEntry( vMffc, 0 ); Vec_IntWriteEntry( vMap, iPivot, i ); // iterate through the MFFC leaves Vec_IntForEachEntryStart( vMffc, iObj, k, 3 ) { vPivot = Vec_WecEntry( vPivots, iObj ); if ( Vec_IntSize(vPivot) == 0 ) Vec_IntGrow(vPivot, 4); Vec_IntPush( vPivot, iPivot ); } } Vec_WecForEachLevel( vPivots, vPivot, i ) Vec_IntSort( vPivot, 0 ); // create pivots for internal nodes while growing MFFCs vCommon = Vec_IntAlloc( 100 ); vCommon2 = Vec_IntAlloc( 100 ); Gia_ManForEachAnd( p, pObj, i ) { // find commont pivots // the slow down happens because some PIs have very large sets of pivots vPivot0 = Vec_WecEntry( vPivots, Gia_ObjFaninId0(pObj, i) ); vPivot1 = Vec_WecEntry( vPivots, Gia_ObjFaninId1(pObj, i) ); Vec_IntTwoFindCommon( vPivot0, vPivot1, vCommon ); if ( Gia_ObjIsMuxId(p, i) ) { vPivot = Vec_WecEntry( vPivots, Gia_ObjFaninId2(p, i) ); Vec_IntTwoFindCommon( vPivot, vCommon, vCommon2 ); ABC_SWAP( Vec_Int_t *, vCommon, vCommon2 ); } if ( Vec_IntSize(vCommon) == 0 ) continue; // add new pivots (this trick increased memory used in vPivots) vPivot = Vec_WecEntry( vPivots, i ); Vec_IntTwoMerge2( vPivot, vCommon, vCommon2 ); ABC_SWAP( Vec_Int_t, *vPivot, *vCommon2 ); // grow MFFCs Vec_IntForEachEntry( vCommon, iObj, k ) { iMffc = Vec_IntEntry( vMap, iObj ); assert( iMffc != -1 ); vMffc = Vec_WecEntry( vMffcs, iMffc ); Vec_IntPush( vMffc, i ); } } //Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); Vec_IntFree( vCommon ); Vec_IntFree( vCommon2 ); Vec_IntFree( vMap ); Gia_ManPrintDivStats( p, vMffcs, vPivots ); Vec_WecFree( vPivots ); // returns the modified array of MFFCs } void Gia_ManResubTest( Gia_Man_t * p ) { Vec_Wec_t * vMffcs; Gia_Man_t * pNew = Gia_ManDupMuxes( p, 2 ); abctime clkStart = Abc_Clock(); vMffcs = Gia_ManComputeMffcs( pNew, 4, 100, 8, 100 ); Gia_ManAddDivisors( pNew, vMffcs ); Vec_WecFree( vMffcs ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); Gia_ManStop( pNew ); } /**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.] Description [] SideEffects [] 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; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManResubFindUsed( Vec_Int_t * vRes, int nDivs, int nNodes, Vec_Int_t * vSupp ) { int i, k, iLit, Counter = 1; Vec_Int_t * vUsed = Vec_IntStartFull( nDivs ); Vec_Int_t * vRes2 = Vec_IntDup( vRes ); Vec_IntWriteEntry( vUsed, 0, 0 ); assert( Vec_IntSize(vRes) % 2 == 1 ); Vec_IntSort( vRes2, 0 ); Vec_IntForEachEntry( vRes2, iLit, k ) { int iVar = Abc_Lit2Var(iLit); if ( iVar > 0 && iVar < nDivs && Vec_IntEntry(vUsed, iVar) == -1 ) { Vec_IntWriteEntry( vUsed, iVar, Counter++ ); Vec_IntPush( vSupp, iVar-2 ); } } Vec_IntFree( vRes2 ); for ( i = nDivs; i < nDivs + nNodes; i++ ) Vec_IntPush( vUsed, Counter++ ); return vUsed; } Vec_Int_t * Gia_ManResubRemapSolution( Vec_Int_t * vRes, Vec_Int_t * vUsed ) { int i, iLit; Vec_Int_t * vResNew = Vec_IntAlloc( Vec_IntSize(vRes) ); Vec_IntForEachEntry( vRes, iLit, i ) Vec_IntPush( vResNew, Abc_Lit2LitV(Vec_IntArray(vUsed), iLit) ); return vResNew; } void Gia_ManResubRecordSolution( char * pFileName, Vec_Int_t * vRes, int nDivs ) { FILE * pFile = fopen( pFileName, "ab" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; } Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); Vec_Int_t * vUsed = Gia_ManResubFindUsed( vRes, nDivs, Vec_IntSize(vRes)/2, vSupp ); Vec_Int_t * vResN = Gia_ManResubRemapSolution( vRes, vUsed ); int i, Temp; fprintf( pFile, "\n.s" ); Vec_IntForEachEntry( vSupp, Temp, i ) fprintf( pFile, " %d", Temp ); fprintf( pFile, "\n.a" ); Vec_IntForEachEntry( vResN, Temp, i ) fprintf( pFile, " %d", Temp ); fprintf( pFile, "\n" ); fclose( pFile ); Vec_IntFree( vUsed ); Vec_IntFree( vSupp ); Vec_IntFree( vResN ); } Gia_Man_t * Gia_ManResubUnateOne( char * pFileName, int nLimit, int nDivMax, int fWriteSol, int fVerbose ) { Gia_Man_t * pNew = NULL; Abc_RData_t * p = Abc_ReadPla( pFileName ); if ( p == NULL ) return NULL; assert( p->nOuts == 1 ); Vec_Ptr_t * vDivs = Vec_PtrAlloc( 2+p->nIns ); Vec_Int_t * vRes = Vec_IntAlloc( 100 ); Vec_PtrPush( vDivs, Vec_WrdEntryP(p->vSimsOut, 0*p->nSimWords) ); Vec_PtrPush( vDivs, Vec_WrdEntryP(p->vSimsOut, 1*p->nSimWords) ); int i, k, ArraySize, * pArray; for ( i = 0; i < p->nIns; i++ ) Vec_PtrPush( vDivs, Vec_WrdEntryP(p->vSimsIn, i*p->nSimWords) ); Abc_ResubPrepareManager( p->nSimWords ); if ( fVerbose ) printf( "The problem has %d divisors and %d outputs.\n", p->nIns, p->nOuts ); ArraySize = Abc_ResubComputeFunction( (void **)Vec_PtrArray(vDivs), Vec_PtrSize(vDivs), p->nSimWords, nLimit, nDivMax, 0, 0, 1, fVerbose, &pArray ); for ( k = 0; k < ArraySize; k++ ) Vec_IntPush( vRes, pArray[k] ); if ( ArraySize ) { //Vec_IntPrint( vRes ); Vec_Wec_t * vGates = Vec_WecStart(1); Vec_IntAppend( Vec_WecEntry(vGates, 0), vRes ); pNew = Gia_ManConstructFromGates( vGates, Vec_PtrSize(vDivs) ); Vec_WecFree( vGates ); if ( fVerbose ) printf( "The solution has %d inputs and %d nodes.\n", Gia_ManCiNum(pNew), Gia_ManAndNum(pNew) ); } if ( fWriteSol && ArraySize ) Gia_ManResubRecordSolution( pFileName, vRes, Vec_PtrSize(vDivs) ); Abc_ResubPrepareManager( 0 ); Vec_IntFree( vRes ); Vec_PtrFree( vDivs ); Abc_RDataStop( p ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaResub2.c000066400000000000000000001573101477524141600162650ustar00rootroot00000000000000/**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 abc-0.52/src/aig/gia/giaResub3.c000066400000000000000000000031051477524141600162560ustar00rootroot00000000000000/**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 abc-0.52/src/aig/gia/giaResub6.c000066400000000000000000000447351477524141600162770ustar00rootroot00000000000000/**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" #include "base/io/ioResub.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 Vec_Int_t vSupp; // support }; 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 ); Vec_IntErase( &p->vSupp ); ABC_FREE( p->ppLits ); ABC_FREE( p->ppSets ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Res6_Man_t * Res6_ManReadPla( char * pFileName ) { int i, n; Abc_RData_t * pData = Abc_ReadPla( pFileName ); assert( pData->nOuts == 1 ); Res6_Man_t * p = pData ? Res6_ManStart( 0, pData->nIns, pData->nOuts, pData->nPats ) : NULL; if ( p == NULL ) return NULL; assert( pData->nSimWords == p->nWords ); for ( i = 1; i < p->nDivs; i++ ) for ( n = 0; n < 2; n++ ) Abc_TtCopy( p->ppLits[2*i+n], Vec_WrdEntryP(pData->vSimsIn, (i-1)*pData->nSimWords), pData->nSimWords, n ); for ( i = 0; i < (1 << p->nOuts); i++ ) Abc_TtCopy( p->ppSets[i], Vec_WrdEntryP(pData->vSimsOut, i*pData->nSimWords), pData->nSimWords, 0 ); if ( pData->vDivs ) Vec_IntForEachEntry( pData->vDivs, n, i ) Vec_IntPush( &p->vSupp, 1+n ); if ( pData->vSol ) { Vec_IntForEachEntry( pData->vSol, n, i ) Vec_IntPush( &p->vSol, n ); Vec_IntPush( &p->vSol, Vec_IntEntryLast(&p->vSol) ); } Abc_RDataStop( pData ); return p; } /**Function************************************************************* Synopsis [] 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 Pat = %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 ); //Vec_IntPrint( vSol ); 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 ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Res6_FindBestEvalPla( Res6_Man_t * p, Vec_Int_t * vSol ) { int i, n, iObj, iLit0, iLit1, iOffset = 2*(1+Vec_IntSize(&p->vSupp)); assert( Vec_IntSize(vSol) % 2 == 0 ); Vec_IntForEachEntry( &p->vSupp, iObj, i ) for ( n = 0; n < 2; n++ ) Abc_TtCopy( p->ppLits[2*(1+i)+n], p->ppLits[2*iObj+n], p->nWords, 0 ); Vec_IntForEachEntryDouble( vSol, iLit0, iLit1, i ) { if ( iLit0 > iLit1 ) { Abc_TtXor( p->ppLits[iOffset+i+0], p->ppLits[iLit0], p->ppLits[iLit1], p->nWords, 0 ); Abc_TtXor( p->ppLits[iOffset+i+1], p->ppLits[iLit0], p->ppLits[iLit1], p->nWords, 1 ); } else { Abc_TtAnd( p->ppLits[iOffset+i+0], p->ppLits[iLit0], p->ppLits[iLit1], p->nWords, 0 ); Abc_TtOr ( p->ppLits[iOffset+i+1], p->ppLits[iLit0^1], p->ppLits[iLit1^1], p->nWords ); } } return Res6_FindGetCost( p, Vec_IntEntryLast(vSol) ); } void Res6_ManResubVerifyPla( Res6_Man_t * p, Vec_Int_t * vSol ) { int Cost = Res6_FindBestEvalPla( p, vSol ); if ( Cost == 0 ) printf( "Verification successful.\n" ); else printf( "Verification FAILED with %d errors on %d patterns.\n", Cost, p->nPats ); } void Res6_PrintSolutionPla( Vec_Int_t * vSol, int nSuppSize, int nDivs ) { int iNode, nNodes = Vec_IntSize(vSol)/2-1; assert( Vec_IntSize(vSol) % 2 == 0 ); printf( "Solution: In = %d Div = %d Node = %d Out = %d\n", nSuppSize, nDivs-1, nNodes, 1 ); for ( iNode = 0; iNode <= nNodes; iNode++ ) { int * pLits = Vec_IntEntryP( vSol, 2*iNode ); printf( "x%-2d = ", 1+nSuppSize+iNode ); Res6_LitPrint( pLits[0], 1+nSuppSize ); if ( pLits[0] != pLits[1] ) { printf( " %c ", pLits[0] < pLits[1] ? '&' : '^' ); Res6_LitPrint( pLits[1], 1+nSuppSize ); } printf( "\n" ); } } void Res6_ManResubCheckPla( char * pFileName, int fVerbose ) { Res6_Man_t * p = Res6_ManReadPla( pFileName ); if ( p == NULL ) return; //Vec_IntPrint( &p->vSupp ); //Vec_IntPrint( &p->vSol ); if ( fVerbose ) Res6_ManPrintProblem( p, 0 ); if ( fVerbose ) Res6_PrintSolutionPla( &p->vSol, Vec_IntSize(&p->vSupp), p->nDivs ); //if ( fVerbose ) // Res6_PrintSuppSims( vSol, p->ppLits, p->nWords, p->nDivs ); Res6_ManResubVerifyPla( p, &p->vSol ); Res6_ManStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaRetime.c000066400000000000000000000240471477524141600163500ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaRetime.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Performs most-forward retiming for AIG with flop classes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaRetime.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Marks objects reachables from Const0 and PIs/ Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManMarkAutonomous_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return pObj->fMark0; Gia_ObjSetTravIdCurrent(p, pObj); assert( pObj->fMark0 == 0 ); if ( Gia_ObjIsPi(p, pObj) || Gia_ObjIsConst0(pObj) ) return pObj->fMark0 = 1; if ( Gia_ObjIsCo(pObj) ) return pObj->fMark0 = Gia_ManMarkAutonomous_rec( p, Gia_ObjFanin0(pObj) ); if ( Gia_ObjIsCi(pObj) ) return pObj->fMark0 = Gia_ManMarkAutonomous_rec( p, Gia_ObjRoToRi(p, pObj) ); assert( Gia_ObjIsAnd(pObj) ); if ( Gia_ManMarkAutonomous_rec( p, Gia_ObjFanin0(pObj) ) ) return pObj->fMark0 = 1; return pObj->fMark0 = Gia_ManMarkAutonomous_rec( p, Gia_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Marks with current trav ROs reachable from Const0 and PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManMarkAutonomous( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManCleanMark0( p ); Gia_ManIncrementTravId( p ); Gia_ManForEachRo( p, pObj, i ) Gia_ManMarkAutonomous_rec( p, pObj ); Gia_ManIncrementTravId( p ); Gia_ManForEachRo( p, pObj, i ) if ( pObj->fMark0 ) Gia_ObjSetTravIdCurrent( p, pObj ); Gia_ManCleanMark0( p ); } /**Function************************************************************* Synopsis [Duplicates the AIG recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManRetimeDup_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj ) { if ( ~pObj->Value ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManRetimeDup_rec( pNew, Gia_ObjFanin0(pObj) ); Gia_ManRetimeDup_rec( pNew, Gia_ObjFanin1(pObj) ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } /**Function************************************************************* Synopsis [Duplicates the AIG while retiming the registers to the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManRetimeDupForward( Gia_Man_t * p, Vec_Ptr_t * vCut ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i; // create the new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); // create the true PIs Gia_ManFillValue( p ); Gia_ManSetPhase( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); // create the registers Vec_PtrForEachEntry( Gia_Obj_t *, vCut, pObj, i ) pObj->Value = Abc_LitNotCond( Gia_ManAppendCi(pNew), pObj->fPhase ); // duplicate logic above the cut Gia_ManForEachCo( p, pObj, i ) Gia_ManRetimeDup_rec( pNew, Gia_ObjFanin0(pObj) ); // create the true POs Gia_ManForEachPo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); // remember value in LI Gia_ManForEachRi( p, pObj, i ) pObj->Value = Gia_ObjFanin0Copy(pObj); // transfer values from the LIs to the LOs Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) pObjRo->Value = pObjRi->Value; // erase the data values on the internal nodes of the cut Vec_PtrForEachEntry( Gia_Obj_t *, vCut, pObj, i ) if ( Gia_ObjIsAnd(pObj) ) pObj->Value = ~0; // duplicate logic below the cut Vec_PtrForEachEntry( Gia_Obj_t *, vCut, pObj, i ) { Gia_ManRetimeDup_rec( pNew, pObj ); Gia_ManAppendCo( pNew, Abc_LitNotCond( pObj->Value, pObj->fPhase ) ); } Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Vec_PtrSize(vCut) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Derives the cut for forward retiming.] Description [Assumes topological ordering of the nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManRetimeForwardOne( Gia_Man_t * p, int * pnRegFixed, int * pnRegMoves ) { Vec_Int_t * vFlopClasses = NULL; Vec_Int_t * vObjClasses = NULL; Gia_Man_t * pNew; Vec_Ptr_t * vCut; Gia_Obj_t * pObj; int i; if ( p->vFlopClasses ) { // printf( "Performing retiming with register classes.\n" ); vObjClasses = Vec_IntAlloc( Gia_ManObjNum(p) ); for ( i = 0; i < Gia_ManObjNum(p); i++ ) Vec_IntPush( vObjClasses, -1 ); Gia_ManForEachRo( p, pObj, i ) Vec_IntWriteEntry( vObjClasses, Gia_ObjId(p, pObj), Vec_IntEntry(p->vFlopClasses, i) ); vFlopClasses = Vec_IntAlloc( Gia_ManRegNum(p) ); } // mark the retimable nodes Gia_ManIncrementTravId( p ); Gia_ManMarkAutonomous( p ); // mark the retimable registers with the fresh trav ID Gia_ManIncrementTravId( p ); *pnRegFixed = 0; Gia_ManForEachRo( p, pObj, i ) if ( Gia_ObjIsTravIdPrevious(p, pObj) ) Gia_ObjSetTravIdCurrent(p, pObj); else (*pnRegFixed)++; // mark all the nodes that can be retimed forward *pnRegMoves = 0; Gia_ManForEachAnd( p, pObj, i ) if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) && Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) { if ( vObjClasses && Vec_IntEntry(vObjClasses, Gia_ObjFaninId0(pObj, i)) != Vec_IntEntry(vObjClasses, Gia_ObjFaninId1(pObj, i)) ) continue; if ( vObjClasses ) Vec_IntWriteEntry( vObjClasses, Gia_ObjId(p, pObj), Vec_IntEntry(vObjClasses, Gia_ObjFaninId0(pObj, i)) ); Gia_ObjSetTravIdCurrent(p, pObj); (*pnRegMoves)++; } // mark the remaining registers Gia_ManForEachRo( p, pObj, i ) Gia_ObjSetTravIdCurrent(p, pObj); // find the cut (all such marked objects that fanout into unmarked nodes) vCut = Vec_PtrAlloc( 1000 ); Gia_ManIncrementTravId( p ); Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjIsTravIdPrevious(p, pObj) ) continue; if ( (Gia_ObjIsCo(pObj) || Gia_ObjIsAnd(pObj)) && Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin0(pObj)) ) { if ( vFlopClasses ) Vec_IntPush( vFlopClasses, Vec_IntEntry(vObjClasses, Gia_ObjFaninId0(pObj, i)) ); Vec_PtrPush( vCut, Gia_ObjFanin0(pObj) ); Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) ); } if ( Gia_ObjIsAnd(pObj) && Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin1(pObj)) ) { if ( vFlopClasses ) Vec_IntPush( vFlopClasses, Vec_IntEntry(vObjClasses, Gia_ObjFaninId1(pObj, i)) ); Vec_PtrPush( vCut, Gia_ObjFanin1(pObj) ); Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin1(pObj) ); } } assert( vFlopClasses == NULL || Vec_IntSize(vFlopClasses) == Vec_PtrSize(vCut) ); // finally derive the new manager pNew = Gia_ManRetimeDupForward( p, vCut ); Vec_PtrFree( vCut ); if ( vObjClasses ) Vec_IntFree( vObjClasses ); pNew->vFlopClasses = vFlopClasses; return pNew; } /**Function************************************************************* Synopsis [Derives the cut for forward retiming.] Description [Assumes topological ordering of the nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManRetimeForward( Gia_Man_t * p, int nMaxIters, int fVerbose ) { Gia_Man_t * pNew, * pTemp; int i, nRegFixed, nRegMoves = 1; abctime clk; pNew = p; for ( i = 0; i < nMaxIters && nRegMoves > 0; i++ ) { clk = Abc_Clock(); pNew = Gia_ManRetimeForwardOne( pTemp = pNew, &nRegFixed, &nRegMoves ); if ( fVerbose ) { printf( "%2d : And = %6d. Reg = %5d. Unret = %5d. Move = %6d. ", i + 1, Gia_ManAndNum(pTemp), Gia_ManRegNum(pTemp), nRegFixed, nRegMoves ); ABC_PRT( "Time", Abc_Clock() - clk ); } if ( pTemp != p ) Gia_ManStop( pTemp ); } /* clk = Abc_Clock(); pNew = Gia_ManReduceLaches( pNew, fVerbose ); if ( fVerbose ) { ABC_PRT( "Register sharing time", Abc_Clock() - clk ); } */ return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaRex.c000066400000000000000000000447701477524141600156660ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaRex.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Regular expressions.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaRex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Simulate AIG with the given sequence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManAutomSimulate( Gia_Man_t * p, Vec_Int_t * vAlpha, char * pSim ) { Gia_Obj_t * pObj, * pObjRi, * pObjRo; int nInputs = Vec_IntSize(vAlpha); int nFrames = strlen(pSim); int i, k; assert( Gia_ManPiNum(p) == nInputs ); printf( "Simulating string \"%s\":\n", pSim ); Gia_ManCleanMark0(p); Gia_ManForEachRo( p, pObj, i ) pObj->fMark0 = 0; for ( i = 0; i < nFrames; i++ ) { Gia_ManForEachPi( p, pObj, k ) pObj->fMark0 = (int)(Vec_IntFind(vAlpha, pSim[i]) == 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_ManForEachRiRo( p, pObjRi, pObjRo, k ) pObjRo->fMark0 = pObjRi->fMark0; printf( "Frame %d : %c %d\n", i, pSim[i], Gia_ManPo(p, 0)->fMark0 ); } Gia_ManCleanMark0(p); } /**Function************************************************************* Synopsis [Builds 1-hotness contraint.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManBuild1Hot_rec( Gia_Man_t * p, int * pLits, int nLits, int * pZero, int * pOne ) { int Zero0, One0, Zero1, One1; if ( nLits == 1 ) { *pZero = Abc_LitNot(pLits[0]); *pOne = pLits[0]; return; } Gia_ManBuild1Hot_rec( p, pLits, nLits/2, &Zero0, &One0 ); Gia_ManBuild1Hot_rec( p, pLits + nLits/2, nLits - nLits/2, &Zero1, &One1 ); *pZero = Gia_ManHashAnd( p, Zero0, Zero1 ); *pOne = Gia_ManHashOr( p, Gia_ManHashAnd(p, Zero0, One1), Gia_ManHashAnd(p, Zero1, One0) ); } int Gia_ManBuild1Hot( Gia_Man_t * p, Vec_Int_t * vLits ) { int Zero, One; assert( Vec_IntSize(vLits) > 0 ); Gia_ManBuild1Hot_rec( p, Vec_IntArray(vLits), Vec_IntSize(vLits), &Zero, &One ); return One; } /**Function************************************************************* Synopsis [Converting regular expressions into sequential AIGs.] Description [http://algs4.cs.princeton.edu/lectures/54RegularExpressions.pdf] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_SymbSpecial( char c ) { return c == '(' || c == ')' || c == '*' || c == '|'; } // collects info about input alphabet and state of the automaton int Gia_ManRexNumInputs( char * pStr, Vec_Int_t ** pvAlphas, Vec_Int_t ** pvStr2Sta ) { int i, nStates = 0, Length = strlen(pStr); Vec_Int_t * vAlphas = Vec_IntAlloc( 100 ); // alphabet Vec_Int_t * vStr2Sta = Vec_IntStartFull( Length + 1 ); // symbol to state for ( i = 0; i < Length; i++ ) { if ( Gia_SymbSpecial(pStr[i]) ) continue; if ( Vec_IntFind(vAlphas, pStr[i]) == -1 ) Vec_IntPush( vAlphas, pStr[i] ); Vec_IntWriteEntry( vStr2Sta, i, nStates++ ); } Vec_IntWriteEntry( vStr2Sta, i, nStates ); *pvAlphas = vAlphas; *pvStr2Sta = vStr2Sta; return nStates; } // prints automaton void Gia_ManPrintAutom( char * pStr, Vec_Int_t * vStaTrans ) { int i = 0, nLength = strlen(pStr); for ( i = 0; i < nLength; i++ ) { printf( "%d \'%c\' ", i, pStr[i] ); if ( Vec_IntEntry(vStaTrans, i) >= 0 ) printf( "-> %d \'%c\' ", Vec_IntEntry(vStaTrans, i), pStr[Vec_IntEntry(vStaTrans, i)] ); printf( "\n" ); } } // prints states reachable through e-transitions void Gia_ManPrintReached( char * pStr, int iState, Vec_Int_t * vReached ) { int i, Entry; printf( "Reached from state %d \'%c\': ", iState, pStr[iState] ); Vec_IntForEachEntry( vReached, Entry, i ) printf( "%d \'%c\' ", Entry, pStr[Entry] ); printf( "\n" ); } // collect states reachable from the given one by e-transitions void Gia_ManPrintReached_rec( char * pStr, Vec_Int_t * vStaTrans, int iState, Vec_Int_t * vReached, Vec_Int_t * vVisited, int TravId ) { if ( Vec_IntEntry(vVisited, iState) == TravId ) return; Vec_IntWriteEntry( vVisited, iState, TravId ); if ( !Gia_SymbSpecial(pStr[iState]) ) // read state Vec_IntPush( vReached, iState ); if ( pStr[iState] == '\0' ) return; if ( Gia_SymbSpecial(pStr[iState]) && pStr[iState] != '|' ) // regular e-transition Gia_ManPrintReached_rec( pStr, vStaTrans, iState + 1, vReached, vVisited, TravId ); if ( Vec_IntEntry(vStaTrans, iState) >= 0 ) // additional e-transition Gia_ManPrintReached_rec( pStr, vStaTrans, Vec_IntEntry(vStaTrans, iState), vReached, vVisited, TravId ); } void Gia_ManCollectReached( char * pStr, Vec_Int_t * vStaTrans, int iState, Vec_Int_t * vReached, Vec_Int_t * vVisited, int TravId ) { assert( iState == 0 || !Gia_SymbSpecial(pStr[iState]) ); assert( Vec_IntEntry(vVisited, iState) != TravId ); Vec_IntClear( vReached ); Gia_ManPrintReached_rec( pStr, vStaTrans, iState + 1, vReached, vVisited, TravId ); } // preprocesses the regular expression char * Gia_ManRexPreprocess( char * pStr ) { char * pCopy = ABC_CALLOC( char, strlen(pStr) * 2 + 10 ); int i, k = 0; pCopy[k++] = '('; pCopy[k++] = '('; for ( i = 0; pStr[i]; i++ ) { if ( pStr[i] == '(' ) pCopy[k++] = '('; else if ( pStr[i] == ')' ) pCopy[k++] = ')'; if ( pStr[i] != ' ' && pStr[i] != '\t' && pStr[i] != '\n' && pStr[i] != '\r' ) pCopy[k++] = pStr[i]; } pCopy[k++] = ')'; pCopy[k++] = ')'; pCopy[k++] = '\0'; return pCopy; } // construct sequential AIG for the automaton Gia_Man_t * Gia_ManRex2Gia( char * pStrInit, int fOrder, int fVerbose ) { Gia_Man_t * pNew = NULL, * pTemp; Vec_Int_t * vAlphas, * vStr2Sta, * vStaLits; Vec_Int_t * vStaTrans, * vStack, * vVisited; Vec_Str_t * vInit; char * pStr = Gia_ManRexPreprocess( pStrInit ); int nStates = Gia_ManRexNumInputs( pStr, &vAlphas, &vStr2Sta ); int i, k, iLit, Entry, nLength = strlen(pStr), nTravId = 1; if ( fOrder ) Vec_IntSort( vAlphas, 0 ); // if ( fVerbose ) { printf( "Input variable order: " ); Vec_IntForEachEntry( vAlphas, Entry, k ) printf( "%c", (char)Entry ); printf( "\n" ); } // start AIG pNew = Gia_ManStart( 1000 ); pNew->pName = Abc_UtilStrsav( pStrInit ); for ( i = 0; i < Vec_IntSize(vAlphas) + nStates; i++ ) Gia_ManAppendCi( pNew ); // prepare automaton vStaLits = Vec_IntStart( nStates + 1 ); vStaTrans = Vec_IntStartFull( nLength ); vStack = Vec_IntAlloc( nLength ); vVisited = Vec_IntStartFull( nLength + 1 ); for ( i = 0; i < nLength; i++ ) { int Lp = i; if ( pStr[i] == '(' || pStr[i] == '|' ) Vec_IntPush( vStack, i ); else if ( pStr[i] == ')' ) { int Or = Vec_IntPop( vStack ); if ( pStr[Or] == '|' ) { Lp = Vec_IntPop( vStack ); Vec_IntWriteEntry( vStaTrans, Lp, Or + 1 ); Vec_IntWriteEntry( vStaTrans, Or, i ); } else Lp = Or; } if ( i < nLength - 1 && pStr[i+1] == '*' ) { Vec_IntWriteEntry( vStaTrans, Lp, i+1 ); Vec_IntWriteEntry( vStaTrans, i+1, Lp ); } } assert( Vec_IntSize(vStack) == 0 ); if ( fVerbose ) Gia_ManPrintAutom( pStr, vStaTrans ); // create next-state functions for each state Gia_ManHashAlloc( pNew ); for ( i = 1; i < nLength; i++ ) { int iThis, iThat, iThisLit, iInputLit; if ( Gia_SymbSpecial(pStr[i]) ) continue; Gia_ManCollectReached( pStr, vStaTrans, i, vStack, vVisited, nTravId++ ); if ( fVerbose ) Gia_ManPrintReached( pStr, i, vStack ); // create transitions from this state under this input iThis = Vec_IntEntry(vStr2Sta, i); iThisLit = Gia_Obj2Lit(pNew, Gia_ManPi(pNew, Vec_IntSize(vAlphas) + iThis)); iInputLit = Gia_Obj2Lit(pNew, Gia_ManPi(pNew, Vec_IntFind(vAlphas, pStr[i]))); iLit = Gia_ManHashAnd( pNew, iThisLit, iInputLit ); Vec_IntForEachEntry( vStack, Entry, k ) { iThat = Vec_IntEntry(vStr2Sta, Entry); iLit = Gia_ManHashOr( pNew, iLit, Vec_IntEntry(vStaLits, iThat) ); Vec_IntWriteEntry( vStaLits, iThat, iLit ); } } // create one-hotness Vec_IntClear( vStack ); for ( i = 0; i < Vec_IntSize(vAlphas); i++ ) Vec_IntPush( vStack, Gia_Obj2Lit(pNew, Gia_ManPi(pNew, i)) ); iLit = Gia_ManBuild1Hot( pNew, vStack ); // combine with outputs Vec_IntForEachEntry( vStaLits, Entry, k ) Vec_IntWriteEntry( vStaLits, k, Gia_ManHashAnd(pNew, iLit, Entry) ); Gia_ManHashStop( pNew ); // collect initial state Gia_ManCollectReached( pStr, vStaTrans, 0, vStack, vVisited, nTravId++ ); if ( fVerbose ) Gia_ManPrintReached( pStr, 0, vStack ); vInit = Vec_StrStart( nStates + 1 ); Vec_StrFill( vInit, nStates, '0' ); Vec_IntForEachEntry( vStack, Entry, k ) if ( pStr[Entry] != '\0' ) Vec_StrWriteEntry( vInit, Vec_IntEntry(vStr2Sta, Entry), '1' ); if ( fVerbose ) printf( "Init state = %s\n", Vec_StrArray(vInit) ); // add outputs Vec_IntPushFirst( vStaLits, Vec_IntPop(vStaLits) ); assert( Vec_IntSize(vStaLits) == nStates + 1 ); Vec_IntForEachEntry( vStaLits, iLit, i ) Gia_ManAppendCo( pNew, iLit ); Gia_ManSetRegNum( pNew, nStates ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); // add initial state pNew = Gia_ManDupZeroUndc( pTemp = pNew, Vec_StrArray(vInit), 0, 0, 0 ); Gia_ManStop( pTemp ); Vec_StrFree( vInit ); /* Gia_ManAutomSimulate( pNew, vAlphas, "0" ); Gia_ManAutomSimulate( pNew, vAlphas, "01" ); Gia_ManAutomSimulate( pNew, vAlphas, "110" ); Gia_ManAutomSimulate( pNew, vAlphas, "011" ); Gia_ManAutomSimulate( pNew, vAlphas, "111" ); Gia_ManAutomSimulate( pNew, vAlphas, "1111" ); Gia_ManAutomSimulate( pNew, vAlphas, "1010" ); Gia_ManAutomSimulate( pNew, vAlphas, "A" ); Gia_ManAutomSimulate( pNew, vAlphas, "AD" ); Gia_ManAutomSimulate( pNew, vAlphas, "ABCD" ); Gia_ManAutomSimulate( pNew, vAlphas, "BCD" ); Gia_ManAutomSimulate( pNew, vAlphas, "CD" ); */ // cleanup Vec_IntFree( vAlphas ); Vec_IntFree( vStr2Sta ); Vec_IntFree( vStaLits ); Vec_IntFree( vStaTrans ); Vec_IntFree( vStack ); Vec_IntFree( vVisited ); ABC_FREE( pStr ); return pNew; } /**Function************************************************************* Synopsis [Transposing 64-bit matrix.] Description [Borrowed from "Hacker's Delight", by Henry Warren.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManAutomTranspose64( word A[64] ) { int j, k; word t, m = 0x00000000FFFFFFFF; for ( j = 32; j != 0; j = j >> 1, m = m ^ (m << j) ) { for ( k = 0; k < 64; k = (k + j + 1) & ~j ) { t = (A[k] ^ (A[k+j] >> j)) & m; A[k] = A[k] ^ t; A[k+j] = A[k+j] ^ (t << j); } } } /**Function************************************************************* Synopsis [Simulate AIG with the given sequence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word Gia_ManAutomSim0( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Wrd_t * vTemp ) { return Gia_ObjFaninC0(pObj) ? ~Vec_WrdEntry(vTemp, Gia_ObjFaninId0p(p, pObj)) : Vec_WrdEntry(vTemp, Gia_ObjFaninId0p(p, pObj)); } static inline word Gia_ManAutomSim1( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Wrd_t * vTemp ) { return Gia_ObjFaninC1(pObj) ? ~Vec_WrdEntry(vTemp, Gia_ObjFaninId1p(p, pObj)) : Vec_WrdEntry(vTemp, Gia_ObjFaninId1p(p, pObj)); } word Gia_ManAutomStep( Gia_Man_t * p, word Cur, word * pNext, Vec_Wrd_t * vTemp ) { Gia_Obj_t * pObj; int i; assert( Gia_ManPoNum(p) == 1 ); assert( Vec_WrdSize(vTemp) >= Gia_ManObjNum(p) ); Vec_WrdWriteEntry( vTemp, 0, 0 ); Gia_ManForEachPi( p, pObj, i ) Vec_WrdWriteEntry( vTemp, Gia_ObjId(p, pObj), ((word)1) << (63-i) ); Gia_ManForEachRo( p, pObj, i ) Vec_WrdWriteEntry( vTemp, Gia_ObjId(p, pObj), ((Cur >> (63-i)) & 1) ? ~((word)0) : 0 ); Gia_ManForEachAnd( p, pObj, i ) Vec_WrdWriteEntry( vTemp, i, Gia_ManAutomSim0(p, pObj, vTemp) & Gia_ManAutomSim1(p, pObj, vTemp) ); Gia_ManForEachRi( p, pObj, i ) pNext[i] = Gia_ManAutomSim0(p, pObj, vTemp); for ( ; i < 64; i++ ) pNext[i] = 0; // transpose // for ( i = 0; i < 64; i++ ) // Extra_PrintBinary( stdout, (unsigned *)&pNext[i], 64 ), Abc_Print( 1, "\n" ); // printf( "\n" ); Gia_ManAutomTranspose64( pNext ); // for ( i = 0; i < 64; i++ ) // Extra_PrintBinary( stdout, (unsigned *)&pNext[i], 64 ), Abc_Print( 1, "\n" ); // printf( "\n" ); // return output values return Gia_ManAutomSim0(p, Gia_ManPo(p, 0), vTemp); } void Gia_ManAutomWalkOne( Gia_Man_t * p, int nSteps, Vec_Wrd_t * vStates, Vec_Int_t * vCounts, Vec_Wrd_t * vTemp, word Init ) { word iState = 0, Output, pNext[64]; int i, k, kMin, Index, IndexMin; int Count, CountMin; for ( i = 0; i < nSteps; i++ ) { Output = Gia_ManAutomStep( p, iState, pNext, vTemp ); // check visited states kMin = -1; IndexMin = -1; CountMin = ABC_INFINITY; for ( k = 0; k < Gia_ManPiNum(p); k++ ) { if ( pNext[k] == Init ) continue; Index = Vec_WrdFind( vStates, pNext[k] ); Count = Index == -1 ? 0 : Vec_IntEntry( vCounts, Index ); if ( CountMin > Count || (CountMin != ABC_INFINITY && Count && ((float)CountMin / Count) > (float)rand()/RAND_MAX ) ) { CountMin = Count; IndexMin = Index; kMin = k; } if ( CountMin == 0 ) break; } // choose the best state if ( CountMin == ABC_INFINITY ) { for ( k = 0; k < Gia_ManPiNum(p); k++ ) if ( (Output >> (63-k)) & 1 ) { printf( "%c", 'a' + k ); printf( "!" ); } break; } assert( CountMin < ABC_INFINITY ); if ( IndexMin == -1 ) { assert( CountMin == 0 ); IndexMin = Vec_IntSize(vCounts); Vec_IntPush( vCounts, 0 ); Vec_WrdPush( vStates, pNext[kMin] ); } Vec_IntAddToEntry( vCounts, IndexMin, 1 ); iState = pNext[kMin]; //Extra_PrintBinary( stdout, (unsigned *)&iState, 64 ); printf( "\n" ); // print the transition printf( "%c", 'a' + kMin ); if ( (Output >> (63-kMin)) & 1 ) printf( "!" ); } printf( "\n" ); } // find flop variables pointed to by negative edges word Gia_ManAutomInit( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, Index; word Init = 0; Gia_ManForEachAnd( p, pObj, i ) { if ( Gia_ObjFaninC0(pObj) && Gia_ObjIsCi(Gia_ObjFanin0(pObj)) ) { Index = Gia_ObjCioId(Gia_ObjFanin0(pObj)) - Gia_ManPiNum(p); if ( Index >= 0 ) Init |= ((word)1 << (63-Index)); } if ( Gia_ObjFaninC1(pObj) && Gia_ObjIsCi(Gia_ObjFanin1(pObj)) ) { Index = Gia_ObjCioId(Gia_ObjFanin1(pObj)) - Gia_ManPiNum(p); if ( Index >= 0 ) Init |= ((word)1 << (63-Index)); } } return Init; } void Gia_ManAutomWalk( Gia_Man_t * p, int nSteps, int nWalks, int fVerbose ) { Vec_Wrd_t * vTemp, * vStates; Vec_Int_t * vCounts; int i; word Init; if ( Gia_ManPoNum(p) != 1 ) { printf( "AIG should have one primary output.\n" ); return; } if ( Gia_ManPiNum(p) > 64 ) { printf( "Cannot simulate an automaton with more than 64 inputs.\n" ); return; } if ( Gia_ManRegNum(p) > 64 ) { printf( "Cannot simulate an automaton with more than 63 states.\n" ); return; } vTemp = Vec_WrdStart( Gia_ManObjNum(p) ); vStates = Vec_WrdAlloc( 1000 ); vCounts = Vec_IntAlloc( 1000 ); Vec_WrdPush( vStates, 0 ); Vec_IntPush( vCounts, 1 ); Init = Gia_ManAutomInit( p ); for ( i = 0; i < nWalks; i++ ) Gia_ManAutomWalkOne( p, nSteps, vStates, vCounts, vTemp, Init ); if ( fVerbose ) { word State; Vec_WrdForEachEntry( vStates, State, i ) { State ^= Init; printf( "%3d : ", i ); Extra_PrintBinary( stdout, (unsigned *)&State, 64 ); printf( " %d ", Vec_IntEntry(vCounts, i) ); printf( "\n" ); } printf( "\n" ); } Vec_WrdFree( vTemp ); Vec_WrdFree( vStates ); Vec_IntFree( vCounts ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaRrr.cpp000066400000000000000000000032711477524141600162240ustar00rootroot00000000000000#include "aig/gia/gia.h" #include "opt/rrr/rrr.h" #include "opt/rrr/rrrAbc.h" ABC_NAMESPACE_IMPL_START Gia_Man_t *Gia_ManRrr(Gia_Man_t *pGia, int iSeed, int nWords, int nTimeout, int nSchedulerVerbose, int nPartitionerVerbose, int nOptimizerVerbose, int nAnalyzerVerbose, int nSimulatorVerbose, int nSatSolverVerbose, int fUseBddCspf, int fUseBddMspf, int nConflictLimit, int nSortType, int nOptimizerFlow, int nSchedulerFlow, int nPartitionType, int nDistance, int nJobs, int nThreads, int nPartitionSize, int nPartitionSizeMin, int fDeterministic, int nParallelPartitions, int fOptOnInsert, int fGreedy) { rrr::AndNetwork ntk; ntk.Read(pGia, rrr::GiaReader); rrr::Parameter Par; Par.iSeed = iSeed; Par.nWords = nWords; Par.nTimeout = nTimeout; Par.nSchedulerVerbose = nSchedulerVerbose; Par.nPartitionerVerbose = nPartitionerVerbose; Par.nOptimizerVerbose = nOptimizerVerbose; Par.nAnalyzerVerbose = nAnalyzerVerbose; Par.nSimulatorVerbose = nSimulatorVerbose; Par.nSatSolverVerbose = nSatSolverVerbose; Par.fUseBddCspf = fUseBddCspf; Par.fUseBddMspf = fUseBddMspf; Par.nConflictLimit = nConflictLimit; Par.nSortType = nSortType; Par.nOptimizerFlow = nOptimizerFlow; Par.nSchedulerFlow = nSchedulerFlow; Par.nPartitionType = nPartitionType; Par.nDistance = nDistance; Par.nJobs = nJobs; Par.nThreads = nThreads; Par.nPartitionSize = nPartitionSize; Par.nPartitionSizeMin = nPartitionSizeMin; Par.fDeterministic = fDeterministic; Par.nParallelPartitions = nParallelPartitions; Par.fOptOnInsert = fOptOnInsert; Par.fGreedy = fGreedy; rrr::Perform(&ntk, &Par); Gia_Man_t *pNew = rrr::CreateGia(&ntk); return pNew; } ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSat.c000066400000000000000000000274721477524141600156570ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [New constraint-propagation procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define GIA_LIMIT 10 typedef struct Gia_ManSat_t_ Gia_ManSat_t; struct Gia_ManSat_t_ { Aig_MmFlex_t * pMem; }; typedef struct Gia_ObjSat1_t_ Gia_ObjSat1_t; struct Gia_ObjSat1_t_ { char nFans; char nOffset; char PathsH; char PathsV; }; typedef struct Gia_ObjSat2_t_ Gia_ObjSat2_t; struct Gia_ObjSat2_t_ { unsigned fTerm : 1; unsigned iLit : 31; }; typedef struct Gia_ObjSat_t_ Gia_ObjSat_t; struct Gia_ObjSat_t_ { union { Gia_ObjSat1_t Obj1; Gia_ObjSat2_t Obj2; }; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_ManSat_t * Gia_ManSatStart() { Gia_ManSat_t * p; p = ABC_CALLOC( Gia_ManSat_t, 1 ); p->pMem = Aig_MmFlexStart(); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSatStop( Gia_ManSat_t * p ) { Aig_MmFlexStop( p->pMem, 0 ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Collects the supergate rooted at this ] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSatPartCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, int * pLits, int * pnLits ) { Gia_Obj_t * pFanin; assert( Gia_ObjIsAnd(pObj) ); assert( pObj->fMark0 == 0 ); pFanin = Gia_ObjFanin0(pObj); if ( pFanin->fMark0 || Gia_ObjFaninC0(pObj) ) pLits[(*pnLits)++] = Gia_Var2Lit(Gia_ObjId(p, pFanin), Gia_ObjFaninC0(pObj)); else Gia_ManSatPartCollectSuper(p, pFanin, pLits, pnLits); pFanin = Gia_ObjFanin1(pObj); if ( pFanin->fMark0 || Gia_ObjFaninC1(pObj) ) pLits[(*pnLits)++] = Gia_Var2Lit(Gia_ObjId(p, pFanin), Gia_ObjFaninC1(pObj)); else Gia_ManSatPartCollectSuper(p, pFanin, pLits, pnLits); } /**Function************************************************************* Synopsis [Returns the number of words used.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSatPartCreate_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int * pObjPlace, int * pStore ) { Gia_Obj_t * pFanin; int i, nWordsUsed, nSuperSize = 0, Super[2*GIA_LIMIT]; // make sure this is a valid node assert( Gia_ObjIsAnd(pObj) ); assert( pObj->fMark0 == 0 ); // collect inputs to the supergate Gia_ManSatPartCollectSuper( p, pObj, Super, &nSuperSize ); assert( nSuperSize <= 2*GIA_LIMIT ); // create the root entry *pObjPlace = 0; ((Gia_ObjSat1_t *)pObjPlace)->nFans = Gia_Var2Lit( nSuperSize, 0 ); ((Gia_ObjSat1_t *)pObjPlace)->nOffset = pStore - pObjPlace; nWordsUsed = nSuperSize; for ( i = 0; i < nSuperSize; i++ ) { pFanin = Gia_ManObj( p, Gia_Lit2Var(Super[i]) ); if ( pFanin->fMark0 ) { ((Gia_ObjSat2_t *)(pStore + i))->fTerm = 1; ((Gia_ObjSat2_t *)(pStore + i))->iLit = Super[i]; } else { assert( Gia_LitIsCompl(Super[i]) ); nWordsUsed += Gia_ManSatPartCreate_rec( p, pFanin, pStore + i, pStore + nWordsUsed ); } } return nWordsUsed; } /**Function************************************************************* Synopsis [Creates part and returns the number of words used.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSatPartCreate( Gia_Man_t * p, Gia_Obj_t * pObj, int * pStore ) { return 1 + Gia_ManSatPartCreate_rec( p, pObj, pStore, pStore + 1 ); } /**Function************************************************************* Synopsis [Count the number of internal nodes in the leaf-DAG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSatPartCountClauses( Gia_Man_t * p, Gia_Obj_t * pObj, int * pnOnset, int * pnOffset ) { Gia_Obj_t * pFanin; int nOnset0, nOnset1, nOffset0, nOffset1; assert( Gia_ObjIsAnd(pObj) ); pFanin = Gia_ObjFanin0(pObj); if ( pFanin->fMark0 ) nOnset0 = 1, nOffset0 = 1; else { Gia_ManSatPartCountClauses(p, pFanin, &nOnset0, &nOffset0); if ( Gia_ObjFaninC0(pObj) ) { int Temp = nOnset0; nOnset0 = nOffset0; nOffset0 = Temp; } } pFanin = Gia_ObjFanin1(pObj); if ( pFanin->fMark0 ) nOnset1 = 1, nOffset1 = 1; else { Gia_ManSatPartCountClauses(p, pFanin, &nOnset1, &nOffset1); if ( Gia_ObjFaninC1(pObj) ) { int Temp = nOnset1; nOnset1 = nOffset1; nOffset1 = Temp; } } *pnOnset = nOnset0 * nOnset1; *pnOffset = nOffset0 + nOffset1; } /**Function************************************************************* Synopsis [Count the number of internal nodes in the leaf-DAG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSatPartCount( Gia_Man_t * p, Gia_Obj_t * pObj, int * pnLeaves, int * pnNodes ) { Gia_Obj_t * pFanin; int Level0 = 0, Level1 = 0; assert( Gia_ObjIsAnd(pObj) ); assert( pObj->fMark0 == 0 ); (*pnNodes)++; pFanin = Gia_ObjFanin0(pObj); if ( pFanin->fMark0 ) (*pnLeaves)++; else Level0 = Gia_ManSatPartCount(p, pFanin, pnLeaves, pnNodes) + Gia_ObjFaninC0(pObj); pFanin = Gia_ObjFanin1(pObj); if ( pFanin->fMark0 ) (*pnLeaves)++; else Level1 = Gia_ManSatPartCount(p, pFanin, pnLeaves, pnNodes) + Gia_ObjFaninC1(pObj); return Abc_MaxInt( Level0, Level1 ); } /**Function************************************************************* Synopsis [Count the number of internal nodes in the leaf-DAG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSatPartCountNodes( Gia_Man_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pFanin; int nNodes0 = 0, nNodes1 = 0; assert( Gia_ObjIsAnd(pObj) ); assert( pObj->fMark0 == 0 ); pFanin = Gia_ObjFanin0(pObj); if ( !(pFanin->fMark0) ) nNodes0 = Gia_ManSatPartCountNodes(p, pFanin); pFanin = Gia_ObjFanin1(pObj); if ( !(pFanin->fMark0) ) nNodes1 = Gia_ManSatPartCountNodes(p, pFanin); return nNodes0 + nNodes1 + 1; } /**Function************************************************************* Synopsis [Count the number of internal nodes in the leaf-DAG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSatPartPrint( Gia_Man_t * p, Gia_Obj_t * pObj, int Step ) { Gia_Obj_t * pFanin; assert( Gia_ObjIsAnd(pObj) ); assert( pObj->fMark0 == 0 ); pFanin = Gia_ObjFanin0(pObj); if ( pFanin->fMark0 ) printf( "%s%d", Gia_ObjFaninC0(pObj)?"!":"", Gia_ObjId(p,pFanin) ); else { if ( Gia_ObjFaninC0(pObj) ) printf( "(" ); Gia_ManSatPartPrint(p, pFanin, Step + Gia_ObjFaninC0(pObj)); if ( Gia_ObjFaninC0(pObj) ) printf( ")" ); } printf( "%s", (Step & 1)? " + " : "*" ); pFanin = Gia_ObjFanin1(pObj); if ( pFanin->fMark0 ) printf( "%s%d", Gia_ObjFaninC1(pObj)?"!":"", Gia_ObjId(p,pFanin) ); else { if ( Gia_ObjFaninC1(pObj) ) printf( "(" ); Gia_ManSatPartPrint(p, pFanin, Step + Gia_ObjFaninC1(pObj)); if ( Gia_ObjFaninC1(pObj) ) printf( ")" ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSatExperiment( Gia_Man_t * p ) { int nStored, Storage[1000], * pStart; Gia_ManSat_t * pMan; Gia_Obj_t * pObj; int i, nLevels, nLeaves, nNodes, nCount[2*GIA_LIMIT+2] = {0}, nCountAll = 0; int Num0 = 0, Num1 = 0; clock_t clk = clock(); int nWords = 0, nWords2 = 0; pMan = Gia_ManSatStart(); // mark the nodes to become roots of leaf-DAGs Gia_ManCreateValueRefs( p ); Gia_ManForEachObj( p, pObj, i ) { pObj->fMark0 = 0; if ( Gia_ObjIsCo(pObj) ) Gia_ObjFanin0(pObj)->fMark0 = 1; else if ( Gia_ObjIsCi(pObj) ) pObj->fMark0 = 1; else if ( Gia_ObjIsAnd(pObj) ) { if ( pObj->Value > 1 || Gia_ManSatPartCountNodes(p,pObj) >= GIA_LIMIT ) pObj->fMark0 = 1; } pObj->Value = 0; } // compute the sizes of leaf-DAGs Gia_ManForEachAnd( p, pObj, i ) { if ( pObj->fMark0 == 0 ) continue; pObj->fMark0 = 0; nCountAll++; nStored = Gia_ManSatPartCreate( p, pObj, Storage ); nWords2 += nStored; assert( nStored < 500 ); pStart = (int *)Aig_MmFlexEntryFetch( pMan->pMem, sizeof(int) * nStored ); memcpy( pStart, Storage, sizeof(int) * nStored ); nLeaves = nNodes = 0; nLevels = 1+Gia_ManSatPartCount( p, pObj, &nLeaves, &nNodes ); nWords += nLeaves + nNodes; if ( nNodes <= 2*GIA_LIMIT ) nCount[nNodes]++; else nCount[2*GIA_LIMIT+1]++; // if ( nNodes > 10 && i % 100 == 0 ) // if ( nNodes > 5 ) if ( 0 ) { Gia_ManSatPartCountClauses( p, pObj, &Num0, &Num1 ); printf( "%8d : And = %3d. Lev = %2d. Clauses = %3d. (%3d + %3d).\n", i, nNodes, nLevels, Num0+Num1, Num0, Num1 ); Gia_ManSatPartPrint( p, pObj, 0 ); printf( "\n" ); } pObj->fMark0 = 1; } printf( "\n" ); Gia_ManForEachObj( p, pObj, i ) pObj->fMark0 = 0; Gia_ManSatStop( pMan ); for ( i = 0; i < 2*GIA_LIMIT+2; i++ ) printf( "%2d=%6d %7.2f %% %7.2f %%\n", i, nCount[i], 100.0*nCount[i]/nCountAll, 100.0*i*nCount[i]/Gia_ManAndNum(p) ); ABC_PRMn( "MemoryEst", 4*nWords ); ABC_PRMn( "MemoryReal", 4*nWords2 ); printf( "%5.2f bpn ", 4.0*nWords2/Gia_ManObjNum(p) ); ABC_PRT( "Time", clock() - clk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSat3.c000066400000000000000000000071461477524141600157360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaSatoko.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Interface to Satoko solver.] Author [Alan Mishchenko, Bruno Schmitt] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaSatoko.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver3.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ sat_solver3 * Gia_ManSat3Init( Cnf_Dat_t * pCnf ) { sat_solver3 * pSat = sat_solver3_new(); int i; //sat_solver_setnvars( pSat, p->nVars ); for ( i = 0; i < pCnf->nClauses; i++ ) { if ( !sat_solver3_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) { sat_solver3_delete( pSat ); return NULL; } } return pSat; } void Gia_ManSat3Report( int iOutput, int status, abctime clk ) { if ( iOutput >= 0 ) Abc_Print( 1, "Output %6d : ", iOutput ); else Abc_Print( 1, "Total: " ); if ( status == l_Undef ) Abc_Print( 1, "UNDECIDED " ); else if ( status == l_True ) Abc_Print( 1, "SATISFIABLE " ); else Abc_Print( 1, "UNSATISFIABLE " ); Abc_PrintTime( 1, "Time", clk ); } sat_solver3 * Gia_ManSat3Create( Gia_Man_t * p ) { Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 1, 0, 0 ); sat_solver3 * pSat = Gia_ManSat3Init( pCnf ); int status = pSat ? sat_solver3_simplify(pSat) : 0; Cnf_DataFree( pCnf ); if ( status ) return pSat; if ( pSat ) sat_solver3_delete( pSat ); return NULL; } int Gia_ManSat3CallOne( Gia_Man_t * p, int iOutput ) { abctime clk = Abc_Clock(); sat_solver3 * pSat; int status, Cost = 0; pSat = Gia_ManSat3Create( p ); if ( pSat ) { status = sat_solver3_solve( pSat, NULL, NULL, 0, 0, 0, 0 ); Cost = (unsigned)pSat->stats.conflicts; sat_solver3_delete( pSat ); } else status = l_False; Gia_ManSat3Report( iOutput, status, Abc_Clock() - clk ); return Cost; } void Gia_ManSat3Call( Gia_Man_t * p, int fSplit ) { Gia_Man_t * pOne; Gia_Obj_t * pRoot; int i; if ( fSplit ) { abctime clk = Abc_Clock(); Gia_ManForEachCo( p, pRoot, i ) { pOne = Gia_ManDupDfsCone( p, pRoot ); Gia_ManSat3CallOne( pOne, i ); Gia_ManStop( pOne ); } Abc_PrintTime( 1, "Total time", Abc_Clock() - clk ); return; } Gia_ManSat3CallOne( p, -1 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSatEdge.c000066400000000000000000000451551477524141600164420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaSatEdge.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: giaSatEdge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/tim/tim.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Seg_Man_t_ Seg_Man_t; struct Seg_Man_t_ { sat_solver * pSat; // SAT solver //Vec_Int_t * vCardVars; // candinality variables int nVars; // max vars (edge num) int LogN; // base-2 log of max vars int Power2; // power-2 of LogN int FirstVar; // first variable to be used // parameters int nBTLimit; // conflicts int DelayMax; // external delay int nEdges; // the number of edges int fDelay; // delay mode int fReverse; // reverse windowing int fVerbose; // verbose // window Gia_Man_t * pGia; Vec_Int_t * vPolars; // polarity Vec_Int_t * vToSkip; // edges to skip Vec_Int_t * vEdges; // edges as fanin/fanout pairs Vec_Int_t * vFirsts; // first SAT variable Vec_Int_t * vNvars; // number of SAT variables Vec_Int_t * vLits; // literals int * pLevels; // levels // statistics abctime timeStart; }; extern sat_solver * Sbm_AddCardinSolver( int LogN, Vec_Int_t ** pvVars ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Count the number of edges between internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Seg_ManCountIntEdges( Gia_Man_t * p, Vec_Int_t * vPolars, Vec_Int_t * vToSkip, int nFanouts ) { int i, iLut, iFanin; Vec_Int_t * vEdges = Vec_IntAlloc( 1000 ); assert( Gia_ManHasMapping(p) ); Vec_IntClear( vPolars ); Vec_IntClear( vToSkip ); if ( nFanouts ) Gia_ManSetLutRefs( p ); Gia_ManForEachLut( p, iLut ) Gia_LutForEachFanin( p, iLut, iFanin, i ) if ( Gia_ObjIsAnd(Gia_ManObj(p, iFanin)) ) { if ( p->vEdge1 && Gia_ObjCheckEdge(p, iFanin, iLut) ) Vec_IntPush( vPolars, Vec_IntSize(vEdges)/2 ); if ( nFanouts && Gia_ObjLutRefNumId(p, iFanin) >= nFanouts ) Vec_IntPush( vToSkip, Vec_IntSize(vEdges)/2 ); Vec_IntPushTwo( vEdges, iFanin, iLut ); } if ( nFanouts ) ABC_FREE( p->pLutRefs ); return vEdges; } Vec_Wec_t * Seg_ManCollectObjEdges( Vec_Int_t * vEdges, int nObjs ) { int iFanin, iObj, i; Vec_Wec_t * vRes = Vec_WecStart( nObjs ); Vec_IntForEachEntryDouble( vEdges, iFanin, iObj, i ) { Vec_WecPush( vRes, iFanin, i/2 ); Vec_WecPush( vRes, iObj, i/2 ); } return vRes; } int Seg_ManCountIntLevels( Seg_Man_t * p, int iStartVar ) { Gia_Obj_t * pObj; int iLut, nVars; Vec_IntFill( p->vFirsts, Gia_ManObjNum(p->pGia), -1 ); Vec_IntFill( p->vNvars, Gia_ManObjNum(p->pGia), 0 ); ABC_FREE( p->pLevels ); if ( p->pGia->pManTime ) { p->DelayMax = Gia_ManLutLevelWithBoxes( p->pGia ); p->pLevels = Vec_IntReleaseArray( p->pGia->vLevels ); Vec_IntFreeP( &p->pGia->vLevels ); } else p->DelayMax = Gia_ManLutLevel( p->pGia, &p->pLevels ); Gia_ManForEachObj1( p->pGia, pObj, iLut ) { if ( Gia_ObjIsCo(pObj) ) continue; if ( Gia_ObjIsAnd(pObj) && !Gia_ObjIsLut(p->pGia, iLut) ) continue; assert( Gia_ObjIsCi(pObj) || Gia_ObjIsLut(p->pGia, iLut) ); Vec_IntWriteEntry( p->vFirsts, iLut, iStartVar ); //assert( p->pLevels[iLut] > 0 ); nVars = p->pLevels[iLut] < 2 ? 0 : p->pLevels[iLut]; Vec_IntWriteEntry( p->vNvars, iLut, nVars ); iStartVar += nVars; } return iStartVar; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Seg_Man_t * Seg_ManAlloc( Gia_Man_t * pGia, int nFanouts ) { int nVarsAll; Seg_Man_t * p = ABC_CALLOC( Seg_Man_t, 1 ); p->vPolars = Vec_IntAlloc( 1000 ); p->vToSkip = Vec_IntAlloc( 1000 ); p->vEdges = Seg_ManCountIntEdges( pGia, p->vPolars, p->vToSkip, nFanouts ); p->nVars = Vec_IntSize(p->vEdges)/2; p->LogN = Abc_Base2Log(p->nVars); p->Power2 = 1 << p->LogN; //p->pSat = Sbm_AddCardinSolver( p->LogN, &p->vCardVars ); p->pSat = sat_solver_new(); sat_solver_setnvars( p->pSat, p->nVars ); p->FirstVar = sat_solver_nvars( p->pSat ); sat_solver_bookmark( p->pSat ); p->pGia = pGia; // internal p->vFirsts = Vec_IntAlloc( 0 ); p->vNvars = Vec_IntAlloc( 0 ); p->vLits = Vec_IntAlloc( 0 ); nVarsAll = Seg_ManCountIntLevels( p, p->FirstVar ); sat_solver_setnvars( p->pSat, nVarsAll ); // other Gia_ManFillValue( pGia ); return p; } void Seg_ManClean( Seg_Man_t * p ) { p->timeStart = Abc_Clock(); sat_solver_rollback( p->pSat ); sat_solver_bookmark( p->pSat ); // internal Vec_IntClear( p->vEdges ); Vec_IntClear( p->vFirsts ); Vec_IntClear( p->vNvars ); Vec_IntClear( p->vLits ); Vec_IntClear( p->vPolars ); Vec_IntClear( p->vToSkip ); // other Gia_ManFillValue( p->pGia ); } void Seg_ManStop( Seg_Man_t * p ) { sat_solver_delete( p->pSat ); //Vec_IntFree( p->vCardVars ); // internal Vec_IntFree( p->vEdges ); Vec_IntFree( p->vFirsts ); Vec_IntFree( p->vNvars ); Vec_IntFree( p->vLits ); Vec_IntFree( p->vPolars ); Vec_IntFree( p->vToSkip ); ABC_FREE( p->pLevels ); // other ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Seg_ManCreateCnf( Seg_Man_t * p, int fTwo, int fVerbose ) { Tim_Man_t * pTim = (Tim_Man_t *)p->pGia->pManTime; Gia_Obj_t * pObj; Vec_Wec_t * vObjEdges; Vec_Int_t * vLevel; int iLut, iFanin, iFirst; int pLits[3], Count = 0; int i, k, nVars, Edge, value; abctime clk = Abc_Clock(); // edge delay constraints int nConstr = sat_solver_nclauses(p->pSat); Gia_ManForEachObj( p->pGia, pObj, iLut ) { int iFirstLut = Vec_IntEntry( p->vFirsts, iLut ); int nVarsLut = Vec_IntEntry( p->vNvars, iLut ); if ( pTim && Gia_ObjIsCi(pObj) ) { int iBox = Tim_ManBoxForCi( pTim, Gia_ObjCioId(pObj) ); if ( nVarsLut > 0 && iBox >= 0 ) { int iCiId = Tim_ManBoxOutputFirst( pTim, iBox ); if ( iCiId == Gia_ObjCioId(pObj) ) // first input { int nIns = Tim_ManBoxInputNum( pTim, iBox ); int iIn0 = Tim_ManBoxInputFirst( pTim, iBox ); for ( i = 0; i < nIns-1; i++ ) // skip carry-in pin { Gia_Obj_t * pOut = Gia_ManCo( p->pGia, iIn0+i ); int iDriverId = Gia_ObjFaninId0p( p->pGia, pOut ); int AddOn; iFirst = Vec_IntEntry( p->vFirsts, iDriverId ); nVars = Vec_IntEntry( p->vNvars, iDriverId ); assert( nVars < nVarsLut ); AddOn = (int)(nVars < nVarsLut); for ( k = 0; k < nVars; k++ ) { pLits[0] = Abc_Var2Lit( iFirst+k, 1 ); pLits[1] = Abc_Var2Lit( iFirstLut+k+AddOn, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); assert( value ); } } } else // intermediate input { Gia_Obj_t * pIn = Gia_ManCi( p->pGia, iCiId ); int iObjId = Gia_ObjId( p->pGia, pIn ); iFirst = Vec_IntEntry( p->vFirsts, iObjId ); nVars = Vec_IntEntry( p->vNvars, iObjId ); if ( nVars > 0 ) { for ( k = 0; k < nVars; k++ ) { pLits[0] = Abc_Var2Lit( iFirst+k, 1 ); pLits[1] = Abc_Var2Lit( iFirstLut+k, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); assert( value ); } } } } continue; } if ( !Gia_ObjIsLut(p->pGia, iLut) ) continue; Gia_LutForEachFanin( p->pGia, iLut, iFanin, i ) if ( pTim && Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin)) ) { iFirst = Vec_IntEntry( p->vFirsts, iFanin ); nVars = Vec_IntEntry( p->vNvars, iFanin ); assert( nVars <= nVarsLut ); if ( nVars > 0 ) { for ( k = 0; k < nVars; k++ ) { pLits[0] = Abc_Var2Lit( iFirst+k, 1 ); pLits[1] = Abc_Var2Lit( iFirstLut+k, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); assert( value ); } } } else if ( Gia_ObjIsAnd(Gia_ManObj(p->pGia, iFanin)) ) { iFirst = Vec_IntEntry( p->vFirsts, iFanin ); nVars = Vec_IntEntry( p->vNvars, iFanin ); assert( nVars != 1 && nVars < nVarsLut ); // add initial if ( nVars == 0 ) { pLits[0] = Abc_Var2Lit( Count, 1 ); pLits[1] = Abc_Var2Lit( iFirstLut, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); assert( value ); pLits[0] = Abc_Var2Lit( Count, 0 ); pLits[1] = Abc_Var2Lit( iFirstLut+1, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); assert( value ); } // add others for ( k = 0; k < nVars; k++ ) { pLits[0] = Abc_Var2Lit( iFirst+k, 1 ); pLits[1] = Abc_Var2Lit( Count, 1 ); pLits[2] = Abc_Var2Lit( iFirstLut+k, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+3 ); assert( value ); pLits[0] = Abc_Var2Lit( iFirst+k, 1 ); pLits[1] = Abc_Var2Lit( Count, 0 ); pLits[2] = Abc_Var2Lit( iFirstLut+k+1, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+3 ); assert( value ); } Count++; } } assert( Count == p->nVars ); if ( fVerbose ) printf( "Delay constraints = %d. ", sat_solver_nclauses(p->pSat) - nConstr ); nConstr = sat_solver_nclauses(p->pSat); /* // delay relationship constraints Vec_IntForEachEntryTwo( p->vFirsts, p->vNvars, iFirst, nVars, iLut ) { if ( nVars < 2 ) continue; for ( i = 1; i < nVars; i++ ) { pLits[0] = Abc_Var2Lit( iFirst + i - 1, 1 ); pLits[1] = Abc_Var2Lit( iFirst + i, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); assert( value ); } } */ // edge compatibility constraint vObjEdges = Seg_ManCollectObjEdges( p->vEdges, Gia_ManObjNum(p->pGia) ); Vec_WecForEachLevel( vObjEdges, vLevel, i ) { int v1, v2, v3, Var1, Var2, Var3; if ( (!fTwo && Vec_IntSize(vLevel) >= 2) || (fTwo && Vec_IntSize(vLevel) > 10) ) { Vec_IntForEachEntry( vLevel, Var1, v1 ) Vec_IntForEachEntryStart( vLevel, Var2, v2, v1 + 1 ) { pLits[0] = Abc_Var2Lit( Var1, 1 ); pLits[1] = Abc_Var2Lit( Var2, 1 ); value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); assert( value ); } } else if ( fTwo && Vec_IntSize(vLevel) >= 3 ) { Vec_IntForEachEntry( vLevel, Var1, v1 ) Vec_IntForEachEntryStart( vLevel, Var2, v2, v1 + 1 ) Vec_IntForEachEntryStart( vLevel, Var3, v3, v2 + 1 ) { pLits[0] = Abc_Var2Lit( Var1, 1 ); pLits[1] = Abc_Var2Lit( Var2, 1 ); pLits[2] = Abc_Var2Lit( Var3, 1 ); value = sat_solver_addclause( p->pSat, pLits, pLits+3 ); assert( value ); } } } Vec_WecFree( vObjEdges ); // block forbidden edges Vec_IntForEachEntry( p->vToSkip, Edge, i ) { pLits[0] = Abc_Var2Lit( Edge, 1 ); value = sat_solver_addclause( p->pSat, pLits, pLits+1 ); assert( value ); } if ( fVerbose ) printf( "Edge constraints = %d. ", sat_solver_nclauses(p->pSat) - nConstr ); if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Seg_ManConvertResult( Seg_Man_t * p ) { int iFanin, iObj, i; Vec_Int_t * vEdges2 = Vec_IntAlloc( 1000 ); Vec_IntForEachEntryDouble( p->vEdges, iFanin, iObj, i ) if ( sat_solver_var_value(p->pSat, i/2) ) Vec_IntPushTwo( vEdges2, iFanin, iObj ); return vEdges2; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Seg_ManComputeDelay( Gia_Man_t * pGia, int DelayInit, int nFanouts, int fTwo, int fVerbose ) { int nBTLimit = 0; int nTimeOut = 0; int fVeryVerbose = 0; Gia_Obj_t * pObj; abctime clk = Abc_Clock(); Vec_Int_t * vEdges2 = NULL; int i, iLut, iFirst, nVars, status, Delay, nConfs; Seg_Man_t * p = Seg_ManAlloc( pGia, nFanouts ); int DelayStart = DelayInit ? DelayInit : p->DelayMax; if ( fVerbose ) printf( "Running SatEdge with starting delay %d and edge %d (edge vars %d, total vars %d)\n", DelayStart, fTwo+1, p->FirstVar, sat_solver_nvars(p->pSat) ); Seg_ManCreateCnf( p, fTwo, fVerbose ); //Sat_SolverWriteDimacs( p->pSat, "test_edge.cnf", NULL, NULL, 0 ); // set resource limits sat_solver_set_resource_limits( p->pSat, nBTLimit, 0, 0, 0 ); sat_solver_set_runtime_limit( p->pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); sat_solver_set_random( p->pSat, 1 ); sat_solver_set_polarity( p->pSat, Vec_IntArray(p->vPolars), Vec_IntSize(p->vPolars) ); //sat_solver_set_var_activity( p->pSat, NULL, p->nVars ); // increment delay gradually for ( Delay = p->DelayMax; Delay >= 0; Delay-- ) { // we constrain COs, although it would be fine to constrain only POs Gia_ManForEachCoDriver( p->pGia, pObj, i ) { iLut = Gia_ObjId( p->pGia, pObj ); iFirst = Vec_IntEntry( p->vFirsts, iLut ); nVars = Vec_IntEntry( p->vNvars, iLut ); if ( Delay < nVars && !sat_solver_push(p->pSat, Abc_Var2Lit(iFirst + Delay, 1)) ) break; } if ( i < Gia_ManCoNum(p->pGia) ) { printf( "Proved UNSAT for delay %d. ", Delay ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); break; } if ( Delay > DelayStart ) continue; // solve with assumptions //clk = Abc_Clock(); nConfs = sat_solver_nconflicts( p->pSat ); status = sat_solver_solve_internal( p->pSat ); nConfs = sat_solver_nconflicts( p->pSat ) - nConfs; if ( status == l_True ) { if ( fVerbose ) { int Count = 0; for ( i = 0; i < p->nVars; i++ ) Count += sat_solver_var_value(p->pSat, i); printf( "Solution with delay %2d and %5d edges exists. Conf = %8d. ", Delay, Count, nConfs ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } // save the result Vec_IntFreeP( &vEdges2 ); vEdges2 = Seg_ManConvertResult( p ); if ( fVeryVerbose ) { for ( i = 0; i < p->nVars; i++ ) printf( "%d=%d ", i, sat_solver_var_value(p->pSat, i) ); printf( " " ); for ( i = p->nVars; i < sat_solver_nvars(p->pSat); i++ ) printf( "%d=%d ", i, sat_solver_var_value(p->pSat, i) ); printf( "\n" ); } } else { if ( fVerbose ) { if ( status == l_False ) printf( "Proved UNSAT for delay %d. ", Delay ); else printf( "Resource limit reached for delay %d. ", Delay ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } break; } } Gia_ManEdgeFromArray( p->pGia, vEdges2 ); Vec_IntFreeP( &vEdges2 ); Seg_ManStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSatLE.c000066400000000000000000001161421477524141600160710ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaSatLE.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Mapping with edges.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaSatLE.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/extra/extra.h" #include "misc/tim/tim.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Sle_CutSize( int * pCut ) { return pCut[0] & 0xF; } // 4 bits static inline int Sle_CutSign( int * pCut ) { return ((unsigned)pCut[0]) >> 4; } // 28 bits static inline int Sle_CutSetSizeSign( int s, int S ) { return (S << 4) | s; } static inline int * Sle_CutLeaves( int * pCut ) { return pCut + 1; } static inline int Sle_CutIsUsed( int * pCut ) { return pCut[1] != 0; } static inline void Sle_CutSetUnused( int * pCut ) { pCut[1] = 0; } static inline int Sle_ListCutNum( int * pList ) { return pList[0]; } #define Sle_ForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += Sle_CutSize(pCut) + 1 ) // cuts with unit-cut #define Sle_ForEachCut1( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i <= pList[0]; i++, pCut += Sle_CutSize(pCut) + 1 ) // only non-unit cuts //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Cut computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Sle_CutMergeOrder( int * pCut0, int * pCut1, int * pCut, int nLutSize ) { int nSize0 = Sle_CutSize(pCut0); int nSize1 = Sle_CutSize(pCut1); int i, * pC0 = Sle_CutLeaves(pCut0); int k, * pC1 = Sle_CutLeaves(pCut1); int c, * pC = Sle_CutLeaves(pCut); // the case of the largest cut sizes if ( nSize0 == nLutSize && nSize1 == nLutSize ) { for ( i = 0; i < nSize0; i++ ) { if ( pC0[i] != pC1[i] ) return 0; pC[i] = pC0[i]; } pCut[0] = Sle_CutSetSizeSign( nLutSize, Sle_CutSign(pCut0) | Sle_CutSign(pCut1) ); return 1; } // compare two cuts with different numbers i = k = c = 0; if ( nSize0 == 0 ) goto FlushCut1; if ( nSize1 == 0 ) goto FlushCut0; while ( 1 ) { if ( c == nLutSize ) return 0; if ( pC0[i] < pC1[k] ) { pC[c++] = pC0[i++]; if ( i >= nSize0 ) goto FlushCut1; } else if ( pC0[i] > pC1[k] ) { pC[c++] = pC1[k++]; if ( k >= nSize1 ) goto FlushCut0; } else { pC[c++] = pC0[i++]; k++; if ( i >= nSize0 ) goto FlushCut1; if ( k >= nSize1 ) goto FlushCut0; } } FlushCut0: if ( c + nSize0 > nLutSize + i ) return 0; while ( i < nSize0 ) pC[c++] = pC0[i++]; pCut[0] = Sle_CutSetSizeSign( c, Sle_CutSign(pCut0) | Sle_CutSign(pCut1) ); return 1; FlushCut1: if ( c + nSize1 > nLutSize + k ) return 0; while ( k < nSize1 ) pC[c++] = pC1[k++]; pCut[0] = Sle_CutSetSizeSign( c, Sle_CutSign(pCut0) | Sle_CutSign(pCut1) ); return 1; } static inline int Sle_SetCutIsContainedOrder( int * pBase, int * pCut ) // check if pCut is contained in pBase { int i, nSizeB = Sle_CutSize(pBase); int k, nSizeC = Sle_CutSize(pCut); int * pLeaveB = Sle_CutLeaves(pBase); int * pLeaveC = Sle_CutLeaves(pCut); if ( nSizeB == nSizeC ) { for ( i = 0; i < nSizeB; i++ ) if ( pLeaveB[i] != pLeaveC[i] ) return 0; return 1; } assert( nSizeB > nSizeC ); if ( nSizeC == 0 ) return 1; for ( i = k = 0; i < nSizeB; i++ ) { if ( pLeaveB[i] > pLeaveC[k] ) return 0; if ( pLeaveB[i] == pLeaveC[k] ) { if ( ++k == nSizeC ) return 1; } } return 0; } static inline int Sle_CutCountBits( unsigned i ) { i = i - ((i >> 1) & 0x55555555); i = (i & 0x33333333) + ((i >> 2) & 0x33333333); i = ((i + (i >> 4)) & 0x0F0F0F0F); return (i*(0x01010101))>>24; } static inline int Sle_SetLastCutIsContained( Vec_Int_t * vTemp, int * pBase ) { int i, * pCut, * pList = Vec_IntArray(vTemp); Sle_ForEachCut( pList, pCut, i ) if ( Sle_CutIsUsed(pCut) && Sle_CutSize(pCut) <= Sle_CutSize(pBase) && (Sle_CutSign(pCut) & Sle_CutSign(pBase)) == Sle_CutSign(pCut) && Sle_SetCutIsContainedOrder(pBase, pCut) ) return 1; return 0; } static inline void Sle_SetAddCut( Vec_Int_t * vTemp, int * pCut ) { int i, * pBase, * pList = Vec_IntArray(vTemp); Sle_ForEachCut( pList, pBase, i ) if ( Sle_CutIsUsed(pBase) && Sle_CutSize(pCut) < Sle_CutSize(pBase) && (Sle_CutSign(pCut) & Sle_CutSign(pBase)) == Sle_CutSign(pCut) && Sle_SetCutIsContainedOrder(pBase, pCut) ) Sle_CutSetUnused( pBase ); Vec_IntPushArray( vTemp, pCut, Sle_CutSize(pCut)+1 ); Vec_IntAddToEntry( vTemp, 0, 1 ); } int Sle_ManCutMerge( Gia_Man_t * p, int iObj, Vec_Int_t * vCuts, Vec_Int_t * vTemp, int nLutSize ) { Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); int * pList0 = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, Gia_ObjFaninId0(pObj, iObj)) ); int * pList1 = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, Gia_ObjFaninId1(pObj, iObj)) ); int * pCut0, * pCut1, i, k, Cut[8], nCuts = 0; Vec_IntFill( vTemp, 1, 0 ); Sle_ForEachCut1( pList0, pCut0, i ) Sle_ForEachCut1( pList1, pCut1, k ) { if ( Sle_CutSize(pCut0) + Sle_CutSize(pCut1) > nLutSize && Sle_CutCountBits(Sle_CutSign(pCut0) | Sle_CutSign(pCut1)) > nLutSize ) continue; if ( !Sle_CutMergeOrder(pCut0, pCut1, Cut, nLutSize) ) continue; if ( Sle_SetLastCutIsContained(vTemp, Cut) ) continue; Sle_SetAddCut( vTemp, Cut ); } // reload Vec_IntWriteEntry( vCuts, iObj, Vec_IntSize(vCuts) ); Vec_IntPush( vCuts, -1 ); pList0 = Vec_IntArray(vTemp); Sle_ForEachCut( pList0, pCut0, i ) { if ( !Sle_CutIsUsed(pCut0) ) continue; Vec_IntPushArray( vCuts, pCut0, Sle_CutSize(pCut0)+1 ); nCuts++; } // add unit cut Vec_IntPush( vCuts, Sle_CutSetSizeSign(1, 1<<(iObj % 28)) ); Vec_IntPush( vCuts, iObj ); Vec_IntWriteEntry( vCuts, Vec_IntEntry(vCuts, iObj), nCuts ); return nCuts; } Vec_Int_t * Sle_ManComputeCuts( Gia_Man_t * p, int nLutSize, int fVerbose ) { int i, iObj, nCuts = 0; Vec_Int_t * vTemp = Vec_IntAlloc( 1000 ); Vec_Int_t * vCuts = Vec_IntAlloc( 30 * Gia_ManAndNum(p) ); assert( nLutSize <= 6 ); Vec_IntFill( vCuts, Gia_ManObjNum(p), 0 ); Gia_ManForEachCiId( p, iObj, i ) { Vec_IntWriteEntry( vCuts, iObj, Vec_IntSize(vCuts) ); Vec_IntPush( vCuts, 0 ); Vec_IntPush( vCuts, Sle_CutSetSizeSign(1, 1<<(iObj % 28)) ); Vec_IntPush( vCuts, iObj ); } Gia_ManForEachAndId( p, iObj ) nCuts += Sle_ManCutMerge( p, iObj, vCuts, vTemp, nLutSize ); if ( fVerbose ) printf( "Nodes = %d. Cuts = %d. Cuts/Node = %.2f. Ints/Node = %.2f. Mem = %.2f MB.\n", Gia_ManAndNum(p), nCuts, 1.0*nCuts/Gia_ManAndNum(p), 1.0*(Vec_IntSize(vCuts)-Gia_ManObjNum(p))/Gia_ManAndNum(p), 1.0*Vec_IntMemory(vCuts) / (1<<20) ); Vec_IntFree( vTemp ); return vCuts; } /**Function************************************************************* Synopsis [Cut delay computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sle_ManComputeDelayCut( Gia_Man_t * p, int * pCut, Vec_Int_t * vTime ) { int nSize = Sle_CutSize(pCut); int k, * pC = Sle_CutLeaves(pCut); int DelayMax = 0; for ( k = 0; k < nSize; k++ ) DelayMax = Abc_MaxInt( DelayMax, Vec_IntEntry(vTime, pC[k]) ); return DelayMax + 1; } int Sle_ManComputeDelayOne( Gia_Man_t * p, int iObj, Vec_Int_t * vCuts, Vec_Int_t * vTime ) { int i, * pCut, Delay, DelayMin = ABC_INFINITY; int * pList = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, iObj) ); Sle_ForEachCut( pList, pCut, i ) { Delay = Sle_ManComputeDelayCut( p, pCut, vTime ); DelayMin = Abc_MinInt( DelayMin, Delay ); } Vec_IntWriteEntry( vTime, iObj, DelayMin ); return DelayMin; } int Sle_ManComputeDelay( Gia_Man_t * p, Vec_Int_t * vCuts ) { int iObj, Delay, DelayMax = 0; Vec_Int_t * vTime = Vec_IntStart( Gia_ManObjNum(p) ); Gia_ManForEachAndId( p, iObj ) { Delay = Sle_ManComputeDelayOne( p, iObj, vCuts, vTime ); DelayMax = Abc_MaxInt( DelayMax, Delay ); } Vec_IntFree( vTime ); //printf( "Delay = %d.\n", DelayMax ); return DelayMax; } /**Function************************************************************* Synopsis [Cut printing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sle_ManPrintCut( int * pCut ) { int nSize = Sle_CutSize(pCut); int k, * pC = Sle_CutLeaves(pCut); printf( "{" ); for ( k = 0; k < nSize; k++ ) printf( " %d", pC[k] ); printf( " }\n" ); } void Sle_ManPrintCuts( Gia_Man_t * p, Vec_Int_t * vCuts, int iObj ) { int i, * pCut; int * pList = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, iObj) ); printf( "Obj %3d\n", iObj ); Sle_ForEachCut( pList, pCut, i ) Sle_ManPrintCut( pCut ); printf( "\n" ); } void Sle_ManPrintCutsAll( Gia_Man_t * p, Vec_Int_t * vCuts ) { int iObj; Gia_ManForEachAndId( p, iObj ) Sle_ManPrintCuts( p, vCuts, iObj ); } void Sle_ManComputeCutsTest( Gia_Man_t * p ) { Vec_Int_t * vCuts = Sle_ManComputeCuts( p, 4, 1 ); //Sle_ManPrintCutsAll( p, vCuts ); Vec_IntFree( vCuts ); } /**Function************************************************************* Synopsis [Derive mask representing internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Bit_t * Sle_ManInternalNodeMask( Gia_Man_t * pGia ) { int iObj; Vec_Bit_t * vMask = Vec_BitStart( Gia_ManObjNum(pGia) ); Gia_ManForEachAndId( pGia, iObj ) Vec_BitWriteEntry( vMask, iObj, 1 ); return vMask; } /**Function************************************************************* Synopsis [Check if the cut contains only primary inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sle_ManCutHasPisOnly( int * pCut, Vec_Bit_t * vMask ) { int k, * pC = Sle_CutLeaves(pCut); for ( k = 0; k < Sle_CutSize(pCut); k++ ) if ( Vec_BitEntry(vMask, pC[k]) ) // internal node return 0; return 1; } /**Function************************************************************* Synopsis [Derive cut fanins of each node.] Description [These are nodes that are fanins of some cut of this node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Sle_ManCollectCutFaninsOne( Gia_Man_t * pGia, int iObj, Vec_Int_t * vCuts, Vec_Bit_t * vMask, Vec_Int_t * vCutFanins, Vec_Bit_t * vMap ) { int i, iFanin, * pCut, * pList = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, iObj) ); Sle_ForEachCut( pList, pCut, i ) { int nSize = Sle_CutSize(pCut); int k, * pC = Sle_CutLeaves(pCut); assert( nSize > 1 ); for ( k = 0; k < nSize; k++ ) if ( Vec_BitEntry(vMask, pC[k]) && !Vec_BitEntry(vMap, pC[k]) ) { Vec_BitWriteEntry( vMap, pC[k], 1 ); Vec_IntPush( vCutFanins, pC[k] ); } } Vec_IntForEachEntry( vCutFanins, iFanin, i ) Vec_BitWriteEntry( vMap, iFanin, 0 ); } Vec_Wec_t * Sle_ManCollectCutFanins( Gia_Man_t * pGia, Vec_Int_t * vCuts, Vec_Bit_t * vMask ) { int iObj; Vec_Bit_t * vMap = Vec_BitStart( Gia_ManObjNum(pGia) ); Vec_Wec_t * vCutFanins = Vec_WecStart( Gia_ManObjNum(pGia) ); Gia_ManForEachAndId( pGia, iObj ) Sle_ManCollectCutFaninsOne( pGia, iObj, vCuts, vMask, Vec_WecEntry(vCutFanins, iObj), vMap ); Vec_BitFree( vMap ); return vCutFanins; } typedef struct Sle_Man_t_ Sle_Man_t; struct Sle_Man_t_ { // user's data Gia_Man_t * pGia; // user's manager (with mapping and edges) int nLevels; // total number of levels int fVerbose; // verbose flag int nSatCalls; // the number of SAT calls // SAT variables int nNodeVars; // node variables (Gia_ManAndNum(pGia)) int nCutVars; // cut variables (total number of non-trivial cuts) int nEdgeVars; // edge variables (total number of internal edges) int nDelayVars; // delay variables (nNodeVars * nLevelsMax) int nVarsTotal; // total number of variables // SAT clauses int nCutClas; // cut clauses int nEdgeClas; // edge clauses int nEdgeClas2; // edge clauses exclusivity int nDelayClas; // delay clauses // internal data sat_solver * pSat; // SAT solver Vec_Bit_t * vMask; // internal node mask Vec_Int_t * vCuts; // cuts for each node Vec_Wec_t * vCutFanins; // internal cut fanins of each node Vec_Wec_t * vFanoutEdges; // internal cut fanins of each node Vec_Wec_t * vEdgeCuts; // cuts of each edge for one node Vec_Int_t * vObjMap; // temporary object map Vec_Int_t * vCutFirst; // first cut of each node Vec_Int_t * vEdgeFirst; // first edge of each node Vec_Int_t * vDelayFirst; // first edge of each node Vec_Int_t * vPolars; // initial Vec_Int_t * vLits; // literals // statistics abctime timeStart; }; static inline int * Sle_ManList( Sle_Man_t * p, int i ) { return Vec_IntEntryP(p->vCuts, Vec_IntEntry(p->vCuts, i)); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sle_Man_t * Sle_ManAlloc( Gia_Man_t * pGia, int nLevels, int fVerbose ) { Sle_Man_t * p = ABC_CALLOC( Sle_Man_t, 1 ); p->pGia = pGia; p->nLevels = nLevels; p->fVerbose = fVerbose; p->vMask = Sle_ManInternalNodeMask( pGia ); p->vCuts = Sle_ManComputeCuts( pGia, 4, fVerbose ); p->vCutFanins = Sle_ManCollectCutFanins( pGia, p->vCuts, p->vMask ); p->vFanoutEdges = Vec_WecStart( Gia_ManObjNum(pGia) ); p->vEdgeCuts = Vec_WecAlloc( 100 ); p->vObjMap = Vec_IntStartFull( Gia_ManObjNum(pGia) ); p->vCutFirst = Vec_IntStartFull( Gia_ManObjNum(pGia) ); p->vEdgeFirst = Vec_IntStartFull( Gia_ManObjNum(pGia) ); p->vDelayFirst = Vec_IntStartFull( Gia_ManObjNum(pGia) ); p->vPolars = Vec_IntAlloc( 100 ); p->vLits = Vec_IntAlloc( 100 ); p->nLevels = Sle_ManComputeDelay( pGia, p->vCuts ); return p; } void Sle_ManStop( Sle_Man_t * p ) { sat_solver_delete( p->pSat ); Vec_BitFree( p->vMask ); Vec_IntFree( p->vCuts ); Vec_WecFree( p->vCutFanins ); Vec_WecFree( p->vFanoutEdges ); Vec_WecFree( p->vEdgeCuts ); Vec_IntFree( p->vObjMap ); Vec_IntFree( p->vCutFirst ); Vec_IntFree( p->vEdgeFirst ); Vec_IntFree( p->vDelayFirst ); Vec_IntFree( p->vPolars ); Vec_IntFree( p->vLits ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sle_ManMarkupVariables( Sle_Man_t * p ) { int iObj, Counter = Gia_ManObjNum(p->pGia); // node variables p->nNodeVars = Counter; // cut variables Gia_ManForEachAndId( p->pGia, iObj ) { Vec_IntWriteEntry( p->vCutFirst, iObj, Counter ); Counter += Sle_ListCutNum( Sle_ManList(p, iObj) ); } p->nCutVars = Counter - p->nNodeVars; // edge variables Gia_ManForEachAndId( p->pGia, iObj ) { Vec_IntWriteEntry( p->vEdgeFirst, iObj, Counter ); Counter += Vec_IntSize( Vec_WecEntry(p->vCutFanins, iObj) ); } p->nEdgeVars = Counter - p->nCutVars - p->nNodeVars; // delay variables Gia_ManForEachAndId( p->pGia, iObj ) { Vec_IntWriteEntry( p->vDelayFirst, iObj, Counter ); Counter += p->nLevels; } p->nDelayVars = Counter - p->nEdgeVars - p->nCutVars - p->nNodeVars; p->nVarsTotal = Counter; } /**Function************************************************************* Synopsis [Derive initial variable assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // returns 1 if Cut can represent LUT (Cut is equal or is contained in LUT) static inline int Sle_ManCheckContained( int * pCutLeaves, int nCutLeaves, int * pLutFanins, int nLutFanins ) { int i, k; if ( nCutLeaves > nLutFanins ) return 0; for ( i = 0; i < nCutLeaves; i++ ) { for ( k = 0; k < nLutFanins; k++ ) if ( pCutLeaves[i] == pLutFanins[k] ) break; if ( k == nLutFanins ) // not found return 0; } return 1; } void Sle_ManDeriveInit( Sle_Man_t * p ) { Vec_Int_t * vEdges; int i, iObj, iFanin, iEdge; if ( !Gia_ManHasMapping(p->pGia) ) return; // derive initial state Vec_IntClear( p->vPolars ); Gia_ManForEachAndId( p->pGia, iObj ) { int nFanins, * pFanins, * pCut, * pList, iFound = -1; if ( !Gia_ObjIsLut(p->pGia, iObj) ) continue; Vec_IntPush( p->vPolars, iObj ); // node var nFanins = Gia_ObjLutSize( p->pGia, iObj ); pFanins = Gia_ObjLutFanins( p->pGia, iObj ); // find cut pList = Sle_ManList( p, iObj ); Sle_ForEachCut( pList, pCut, i ) if ( Sle_ManCheckContained( Sle_CutLeaves(pCut), Sle_CutSize(pCut), pFanins, nFanins ) ) { iFound = i; break; } if ( iFound == -1 ) { printf( "Cannot find the following cut at node %d: {", iObj ); for ( i = 0; i < nFanins; i++ ) printf( " %d", pFanins[i] ); printf( " }\n" ); Sle_ManPrintCuts( p->pGia, p->vCuts, iObj ); fflush( stdout ); } assert( iFound >= 0 ); Vec_IntPush( p->vPolars, Vec_IntEntry(p->vCutFirst, iObj) + iFound ); // cut var // check if the cut contains only primary inputs - if so, its delay is equal to 1 if ( Sle_ManCutHasPisOnly(pCut, p->vMask) ) Vec_IntPush( p->vPolars, Vec_IntEntry(p->vDelayFirst, iObj) ); // delay var } Vec_IntSort( p->vPolars, 0 ); // find zero-delay edges if ( !p->pGia->vEdge1 ) return; vEdges = Gia_ManEdgeToArray( p->pGia ); Vec_IntForEachEntryDouble( vEdges, iFanin, iObj, i ) { assert( iFanin < iObj ); assert( Gia_ObjIsLut(p->pGia, iFanin) ); assert( Gia_ObjIsLut(p->pGia, iObj) ); assert( Gia_ObjIsAnd(Gia_ManObj(p->pGia, iFanin)) ); assert( Gia_ObjIsAnd(Gia_ManObj(p->pGia, iObj)) ); // find edge iEdge = Vec_IntFind( Vec_WecEntry(p->vCutFanins, iObj), iFanin ); if ( iEdge < 0 ) continue; assert( iEdge >= 0 ); Vec_IntPush( p->vPolars, Vec_IntEntry(p->vEdgeFirst, iObj) + iEdge ); // edge } Vec_IntFree( vEdges ); } /**Function************************************************************* Synopsis [Derive CNF.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sle_ManDeriveCnf( Sle_Man_t * p, int nBTLimit, int fDynamic ) { int nTimeOut = 0; int i, iObj, value; Vec_Int_t * vArray; // start the SAT solver p->pSat = sat_solver_new(); sat_solver_setnvars( p->pSat, p->nVarsTotal ); sat_solver_set_resource_limits( p->pSat, nBTLimit, 0, 0, 0 ); sat_solver_set_runtime_limit( p->pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); sat_solver_set_random( p->pSat, 1 ); sat_solver_set_polarity( p->pSat, Vec_IntArray(p->vPolars), Vec_IntSize(p->vPolars) ); //sat_solver_set_var_activity( p->pSat, NULL, p->nVarsTotal ); // set drivers to be mapped Gia_ManForEachCoDriverId( p->pGia, iObj, i ) if ( Vec_BitEntry(p->vMask, iObj) ) // internal node { Vec_IntFill( p->vLits, 1, Abc_Var2Lit(iObj, 0) ); // pos lit value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); assert( value ); } // add cover clauses and edge-to-cut clauses Gia_ManForEachAndId( p->pGia, iObj ) { int e, iEdge, nEdges = 0, Entry; int iCutVar0 = Vec_IntEntry( p->vCutFirst, iObj ); int iEdgeVar0 = Vec_IntEntry( p->vEdgeFirst, iObj ); int * pCut, * pList = Sle_ManList( p, iObj ); Vec_Int_t * vCutFans = Vec_WecEntry( p->vCutFanins, iObj ); assert( iCutVar0 > 0 && iEdgeVar0 > 0 ); // node requires one of the cuts Vec_IntFill( p->vLits, 1, Abc_Var2Lit(iObj, 1) ); // neg lit for ( i = 0; i < Sle_ListCutNum(pList); i++ ) Vec_IntPush( p->vLits, Abc_Var2Lit(iCutVar0 + i, 0) ); value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); assert( value ); // cuts are mutually exclusive for ( i = 0; i < Sle_ListCutNum(pList); i++ ) for ( e = i+1; e < Sle_ListCutNum(pList); e++ ) { Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(iCutVar0 + i, 1), Abc_Var2Lit(iCutVar0 + e, 1) ); value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); assert( value ); } // cut requires fanin nodes Vec_WecInit( p->vEdgeCuts, Vec_IntSize(vCutFans) ); Sle_ForEachCut( pList, pCut, i ) { int nSize = Sle_CutSize(pCut); int k, * pC = Sle_CutLeaves(pCut); assert( nSize > 1 ); for ( k = 0; k < nSize; k++ ) { if ( !Vec_BitEntry(p->vMask, pC[k]) ) continue; Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(iCutVar0 + i, 1), Abc_Var2Lit(pC[k], 0) ); value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); assert( value ); // find the edge ID between pC[k] and iObj iEdge = Vec_IntEntry(p->vObjMap, pC[k]); if ( iEdge == -1 ) { Vec_IntWriteEntry( p->vObjMap, pC[k], (iEdge = nEdges++) ); Vec_WecPush( p->vFanoutEdges, pC[k], iEdgeVar0 + iEdge ); } Vec_WecPush( p->vEdgeCuts, iEdge, iCutVar0 + i ); p->nCutClas++; } // cut requires the node Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(iCutVar0 + i, 1), Abc_Var2Lit(iObj, 0) ); value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); assert( value ); } assert( nEdges == Vec_IntSize(vCutFans) ); // edge requires one of the fanout cuts Vec_WecForEachLevel( p->vEdgeCuts, vArray, e ) { assert( Vec_IntSize(vArray) > 0 ); Vec_IntFill( p->vLits, 1, Abc_Var2Lit(iEdgeVar0 + e, 1) ); // neg lit (edge) Vec_IntForEachEntry( vArray, Entry, i ) Vec_IntPush( p->vLits, Abc_Var2Lit(Entry, 0) ); // pos lit (cut) value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); assert( value ); p->nEdgeClas++; } // clean object map Vec_IntForEachEntry( vCutFans, Entry, i ) Vec_IntWriteEntry( p->vObjMap, Entry, -1 ); } // mutual exclusivity of edges Vec_WecForEachLevel( p->vFanoutEdges, vArray, iObj ) { int j, k, EdgeJ, EdgeK; int iEdgeVar0 = Vec_IntEntry( p->vEdgeFirst, iObj ); Vec_Int_t * vCutFans = Vec_WecEntry( p->vCutFanins, iObj ); // add fanin edges for ( i = 0; i < Vec_IntSize(vCutFans); i++ ) Vec_IntPush( vArray, iEdgeVar0 + i ); // generate pairs if ( fDynamic ) continue; Vec_IntForEachEntry( vArray, EdgeJ, j ) Vec_IntForEachEntryStart( vArray, EdgeK, k, j+1 ) { Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(EdgeJ, 1), Abc_Var2Lit(EdgeK, 1) ); value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); assert( value ); } p->nEdgeClas2 += Vec_IntSize(vArray) * (Vec_IntSize(vArray) - 1) / 2; } // add delay clauses Gia_ManForEachAndId( p->pGia, iObj ) { int e, iFanin; int iEdgeVar0 = Vec_IntEntry( p->vEdgeFirst, iObj ); int iDelayVar0 = Vec_IntEntry( p->vDelayFirst, iObj ); Vec_Int_t * vCutFans = Vec_WecEntry( p->vCutFanins, iObj ); // check if the node has cuts containing only primary inputs int * pCut, * pList = Sle_ManList( p, iObj ); Sle_ForEachCut( pList, pCut, i ) if ( Sle_ManCutHasPisOnly(pCut, p->vMask) ) { Vec_IntFill( p->vLits, 1, Abc_Var2Lit(iDelayVar0, 0) ); // pos lit // Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(iObj, 1), Abc_Var2Lit(iDelayVar0, 0) ); value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); assert( value ); break; } // if ( i < Sle_ListCutNum(pList) ) // continue; // create delay requirements for each cut fanin of this node Vec_IntForEachEntry( vCutFans, iFanin, e ) { int d, iDelayVarIn = Vec_IntEntry( p->vDelayFirst, iFanin ); for ( d = 0; d < p->nLevels; d++ ) { Vec_IntClear( p->vLits ); Vec_IntPush( p->vLits, Abc_Var2Lit(iObj, 1) ); Vec_IntPush( p->vLits, Abc_Var2Lit(iFanin, 1) ); Vec_IntPush( p->vLits, Abc_Var2Lit(iDelayVarIn + d, 1) ); Vec_IntPush( p->vLits, Abc_Var2Lit(iEdgeVar0 + e, 0) ); if ( d < p->nLevels-1 ) Vec_IntPush( p->vLits, Abc_Var2Lit(iDelayVar0 + d+1, 0) ); value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); assert( value ); Vec_IntClear( p->vLits ); Vec_IntPush( p->vLits, Abc_Var2Lit(iObj, 1) ); Vec_IntPush( p->vLits, Abc_Var2Lit(iFanin, 1) ); Vec_IntPush( p->vLits, Abc_Var2Lit(iDelayVarIn + d, 1) ); if ( d < p->nLevels-1 ) Vec_IntPush( p->vLits, Abc_Var2Lit(iEdgeVar0 + e, 1) ); Vec_IntPush( p->vLits, Abc_Var2Lit(iDelayVar0 + d, 0) ); value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); assert( value ); } p->nDelayClas += 2*p->nLevels; } } } /**Function************************************************************* Synopsis [Add edge compatibility constraints.] Description [Returns 1 if constraints have been added.] SideEffects [] SeeAlso [] ***********************************************************************/ int Sle_ManAddEdgeConstraints( Sle_Man_t * p, int nEdges ) { Vec_Int_t * vArray; Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); int value, iObj, nAdded = 0; assert( nEdges == 1 || nEdges == 2 ); Vec_WecForEachLevel( p->vFanoutEdges, vArray, iObj ) { int j, k, EdgeJ, EdgeK; // check if they are incompatible Vec_IntClear( vTemp ); Vec_IntForEachEntry( vArray, EdgeJ, j ) if ( sat_solver_var_value(p->pSat, EdgeJ) ) Vec_IntPush( vTemp, EdgeJ ); if ( Vec_IntSize(vTemp) <= nEdges ) continue; nAdded++; if ( nEdges == 1 ) { // generate pairs Vec_IntForEachEntry( vTemp, EdgeJ, j ) Vec_IntForEachEntryStart( vTemp, EdgeK, k, j+1 ) { Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(EdgeJ, 1), Abc_Var2Lit(EdgeK, 1) ); value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); assert( value ); } p->nEdgeClas2 += Vec_IntSize(vTemp) * (Vec_IntSize(vTemp) - 1) / 2; } else if ( nEdges == 2 ) { int m, EdgeM; // generate triples Vec_IntForEachEntry( vTemp, EdgeJ, j ) Vec_IntForEachEntryStart( vTemp, EdgeK, k, j+1 ) Vec_IntForEachEntryStart( vTemp, EdgeM, m, k+1 ) { Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(EdgeJ, 1), Abc_Var2Lit(EdgeK, 1) ); Vec_IntPush( p->vLits, Abc_Var2Lit(EdgeM, 1) ); value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); assert( value ); } p->nEdgeClas2 += Vec_IntSize(vTemp) * (Vec_IntSize(vTemp) - 1) * (Vec_IntSize(vTemp) - 2) / 6; } else assert( 0 ); } Vec_IntFree( vTemp ); //printf( "Added clauses to %d nodes.\n", nAdded ); return nAdded; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sle_ManDeriveResult( Sle_Man_t * p, Vec_Int_t * vEdge2, Vec_Int_t * vMapping ) { Vec_Int_t * vMapTemp; int iObj; // create mapping Vec_IntFill( vMapping, Gia_ManObjNum(p->pGia), 0 ); Gia_ManForEachAndId( p->pGia, iObj ) { int i, iCut, iCutVar0 = Vec_IntEntry( p->vCutFirst, iObj ); int * pCut, * pCutThis = NULL, * pList = Sle_ManList( p, iObj ); if ( !sat_solver_var_value(p->pSat, iObj) ) continue; Sle_ForEachCut( pList, pCut, iCut ) if ( sat_solver_var_value(p->pSat, iCutVar0 + iCut) ) { assert( pCutThis == NULL ); pCutThis = pCut; } assert( pCutThis != NULL ); Vec_IntWriteEntry( vMapping, iObj, Vec_IntSize(vMapping) ); Vec_IntPush( vMapping, Sle_CutSize(pCutThis) ); for ( i = 0; i < Sle_CutSize(pCutThis); i++ ) Vec_IntPush( vMapping, Sle_CutLeaves(pCutThis)[i] ); Vec_IntPush( vMapping, iObj ); } vMapTemp = p->pGia->vMapping; p->pGia->vMapping = vMapping; // collect edges Vec_IntClear( vEdge2 ); Gia_ManForEachAndId( p->pGia, iObj ) { int i, iFanin, iEdgeVar0 = Vec_IntEntry( p->vEdgeFirst, iObj ); Vec_Int_t * vCutFans = Vec_WecEntry( p->vCutFanins, iObj ); //int * pCut, * pList = Sle_ManList( p, iObj ); // int iCutVar0 = Vec_IntEntry( p->vCutFirst, iObj ); if ( !sat_solver_var_value(p->pSat, iObj) ) continue; //for ( i = 0; i < Sle_ListCutNum(pList); i++ ) // printf( "%d", sat_solver_var_value(p->pSat, iCutVar0 + i) ); //printf( "\n" ); Vec_IntForEachEntry( vCutFans, iFanin, i ) if ( sat_solver_var_value(p->pSat, iFanin) && sat_solver_var_value(p->pSat, iEdgeVar0 + i) ) { // verify edge int * pFanins = Gia_ObjLutFanins( p->pGia, iObj ); int k, nFanins = Gia_ObjLutSize( p->pGia, iObj ); for ( k = 0; k < nFanins; k++ ) { //printf( "%d ", pFanins[k] ); if ( pFanins[k] == iFanin ) break; } //printf( "\n" ); if ( k == nFanins ) // printf( "Cannot find LUT with input %d at node %d.\n", iFanin, iObj ); continue; Vec_IntPushTwo( vEdge2, iFanin, iObj ); } } p->pGia->vMapping = vMapTemp; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sle_ManExplore( Gia_Man_t * pGia, int nBTLimit, int DelayInit, int fDynamic, int fTwoEdges, int fVerbose ) { int fVeryVerbose = 0; abctime clk = Abc_Clock(); Vec_Int_t * vEdges2 = Vec_IntAlloc(1000); Vec_Int_t * vMapping = Vec_IntAlloc(1000); int i, iLut, nConfs, status, Delay, iFirstVar; int DelayStart = (DelayInit || !Gia_ManHasMapping(pGia)) ? DelayInit : Gia_ManLutLevel(pGia, NULL); Sle_Man_t * p = Sle_ManAlloc( pGia, DelayStart, fVerbose ); if ( fVerbose ) printf( "Running solver with %d conflicts, %d initial delay, and %d edges. Dynamic constraints = %s.\n", nBTLimit, DelayInit, 1+fTwoEdges, fDynamic?"yes":"no" ); Sle_ManMarkupVariables( p ); if ( fVerbose ) printf( "Vars: Total = %d. Node = %d. Cut = %d. Edge = %d. Delay = %d.\n", p->nVarsTotal, p->nNodeVars, p->nCutVars, p->nEdgeVars, p->nDelayVars ); Sle_ManDeriveInit( p ); Sle_ManDeriveCnf( p, nBTLimit, fDynamic || fTwoEdges ); if ( fVerbose ) printf( "Clas: Total = %d. Cut = %d. Edge = %d. EdgeEx = %d. Delay = %d.\n", sat_solver_nclauses(p->pSat), p->nCutClas, p->nEdgeClas, p->nEdgeClas2, p->nDelayClas ); //Sat_SolverWriteDimacs( p->pSat, "temp.cnf", NULL, NULL, 0 ); for ( Delay = p->nLevels; Delay >= 0; Delay-- ) { // we constrain COs, although it would be fine to constrain only POs if ( Delay < p->nLevels ) { Gia_ManForEachCoDriverId( p->pGia, iLut, i ) if ( Vec_BitEntry(p->vMask, iLut) ) // internal node { iFirstVar = Vec_IntEntry( p->vDelayFirst, iLut ); if ( !sat_solver_push(p->pSat, Abc_Var2Lit(iFirstVar + Delay, 1)) ) break; } if ( i < Gia_ManCoNum(p->pGia) ) { if ( fVerbose ) { printf( "Proved UNSAT for delay %d. ", Delay ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } break; } } // solve with assumptions //clk = Abc_Clock(); nConfs = sat_solver_nconflicts( p->pSat ); while ( 1 ) { p->nSatCalls++; status = sat_solver_solve_internal( p->pSat ); if ( status != l_True ) break; if ( !Sle_ManAddEdgeConstraints(p, 1+fTwoEdges) ) break; } nConfs = sat_solver_nconflicts( p->pSat ) - nConfs; if ( status == l_True ) { if ( fVerbose ) { int nNodes = 0, nEdges = 0; for ( i = 0; i < p->nNodeVars; i++ ) nNodes += sat_solver_var_value(p->pSat, i); for ( i = 0; i < p->nEdgeVars; i++ ) nEdges += sat_solver_var_value(p->pSat, p->nNodeVars + p->nCutVars + i); printf( "Solution with delay %2d, node count %5d, and edge count %5d exists. Conf = %8d. ", Delay, nNodes, nEdges, nConfs ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } // save the result Sle_ManDeriveResult( p, vEdges2, vMapping ); if ( fVeryVerbose ) { printf( "Nodes: " ); for ( i = 0; i < p->nNodeVars; i++ ) if ( sat_solver_var_value(p->pSat, i) ) printf( "%d ", i ); printf( "\n" ); printf( "\n" ); Vec_IntPrint( p->vCutFirst ); printf( "Cuts: " ); for ( i = 0; i < p->nCutVars; i++ ) if ( sat_solver_var_value(p->pSat, p->nNodeVars + i) ) printf( "%d ", p->nNodeVars + i ); printf( "\n" ); printf( "\n" ); Vec_IntPrint( p->vEdgeFirst ); printf( "Edges: " ); for ( i = 0; i < p->nEdgeVars; i++ ) if ( sat_solver_var_value(p->pSat, p->nNodeVars + p->nCutVars + i) ) printf( "%d ", p->nNodeVars + p->nCutVars + i ); printf( "\n" ); printf( "\n" ); Vec_IntPrint( p->vDelayFirst ); printf( "Delays: " ); for ( i = 0; i < p->nDelayVars; i++ ) if ( sat_solver_var_value(p->pSat, p->nNodeVars + p->nCutVars + p->nEdgeVars + i) ) printf( "%d ", p->nNodeVars + p->nCutVars + p->nEdgeVars + i ); printf( "\n" ); printf( "\n" ); } } else { if ( fVerbose ) { if ( status == l_False ) printf( "Proved UNSAT for delay %d. Conf = %8d. ", Delay, nConfs ); else printf( "Resource limit reached for delay %d. Conf = %8d. ", Delay, nConfs ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } break; } } if ( fVerbose ) printf( "Clas: Total = %d. Cut = %d. Edge = %d. EdgeEx = %d. Delay = %d. Calls = %d.\n", sat_solver_nclauses(p->pSat), p->nCutClas, p->nEdgeClas, p->nEdgeClas2, p->nDelayClas, p->nSatCalls ); if ( Vec_IntSize(vMapping) > 0 ) { Gia_ManEdgeFromArray( p->pGia, vEdges2 ); Vec_IntFree( vEdges2 ); Vec_IntFreeP( &p->pGia->vMapping ); p->pGia->vMapping = vMapping; } else { Vec_IntFree( vEdges2 ); Vec_IntFree( vMapping ); } Vec_IntFreeP( &p->pGia->vPacking ); Sle_ManStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSatLut.c000066400000000000000000002525401477524141600163400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaSatLut.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: giaSatLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/tim/tim.h" #include "misc/util/utilTruth.h" #include "sat/bsat/satStore.h" #include "misc/util/utilNam.h" #include "map/scl/sclCon.h" #include "misc/vec/vecHsh.h" #ifdef _MSC_VER #define unlink _unlink #else #include #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Sbl_Man_t_ Sbl_Man_t; struct Sbl_Man_t_ { sat_solver * pSat; // SAT solver Vec_Int_t * vCardVars; // candinality variables int nVars; // max vars int LogN; // base-2 log of max vars int Power2; // power-2 of LogN int FirstVar; // first variable to be used // statistics int nTried; // nodes tried int nImproved; // nodes improved int nRuns; // the number of runs int nHashWins; // the number of hashed windows int nSmallWins; // the number of small windows int nLargeWins; // the number of large windows int nIterOuts; // the number of iters exceeded // parameters int LutSize; // LUT size int nBTLimit; // conflicts int DelayMax; // external delay int nEdges; // the number of edges int fDelay; // delay mode int fReverse; // reverse windowing int fVerbose; // verbose int fVeryVerbose; // verbose int fVeryVeryVerbose; // verbose // window Gia_Man_t * pGia; Vec_Int_t * vLeaves; // leaf nodes Vec_Int_t * vAnds; // AND-gates Vec_Int_t * vNodes; // internal LUTs Vec_Int_t * vRoots; // driver nodes (a subset of vAnds) Vec_Int_t * vRootVars; // driver nodes (as SAT variables) Hsh_VecMan_t * pHash; // hash table for windows // timing Vec_Int_t * vArrs; // arrival times Vec_Int_t * vReqs; // required times Vec_Wec_t * vWindow; // fanins of each node in the window Vec_Int_t * vPath; // critical path (as SAT variables) Vec_Int_t * vEdges; // fanin edges // cuts Vec_Wrd_t * vCutsI1; // input bit patterns Vec_Wrd_t * vCutsI2; // input bit patterns Vec_Wrd_t * vCutsN1; // node bit patterns Vec_Wrd_t * vCutsN2; // node bit patterns Vec_Int_t * vCutsNum; // cut counts for each obj Vec_Int_t * vCutsStart; // starting cuts for each obj Vec_Int_t * vCutsObj; // object to which this cut belongs Vec_Wrd_t * vTempI1; // temporary cuts Vec_Wrd_t * vTempI2; // temporary cuts Vec_Wrd_t * vTempN1; // temporary cuts Vec_Wrd_t * vTempN2; // temporary cuts Vec_Int_t * vSolInit; // initial solution Vec_Int_t * vSolCur; // current solution Vec_Int_t * vSolBest; // best solution // temporary Vec_Int_t * vLits; // literals Vec_Int_t * vAssump; // literals Vec_Int_t * vPolar; // variables polarity // statistics abctime timeWin; // windowing abctime timeCut; // cut computation abctime timeSat; // SAT runtime abctime timeSatSat; // satisfiable time abctime timeSatUns; // unsatisfiable time abctime timeSatUnd; // undecided time abctime timeTime; // timing time abctime timeStart; // starting time abctime timeTotal; // all runtime abctime timeOther; // other time }; extern sat_solver * Sbm_AddCardinSolver( int LogN, Vec_Int_t ** pvVars ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sbl_Man_t * Sbl_ManAlloc( Gia_Man_t * pGia, int Number ) { Sbl_Man_t * p = ABC_CALLOC( Sbl_Man_t, 1 ); p->nVars = Number; p->LogN = Abc_Base2Log(Number); p->Power2 = 1 << p->LogN; p->pSat = Sbm_AddCardinSolver( p->LogN, &p->vCardVars ); p->FirstVar = sat_solver_nvars( p->pSat ); sat_solver_bookmark( p->pSat ); // window p->pGia = pGia; p->vLeaves = Vec_IntAlloc( p->nVars ); p->vAnds = Vec_IntAlloc( p->nVars ); p->vNodes = Vec_IntAlloc( p->nVars ); p->vRoots = Vec_IntAlloc( p->nVars ); p->vRootVars = Vec_IntAlloc( p->nVars ); p->pHash = Hsh_VecManStart( 1000 ); // timing p->vArrs = Vec_IntAlloc( 0 ); p->vReqs = Vec_IntAlloc( 0 ); p->vWindow = Vec_WecAlloc( 128 ); p->vPath = Vec_IntAlloc( 32 ); p->vEdges = Vec_IntAlloc( 32 ); // cuts p->vCutsI1 = Vec_WrdAlloc( 1000 ); // input bit patterns p->vCutsI2 = Vec_WrdAlloc( 1000 ); // input bit patterns p->vCutsN1 = Vec_WrdAlloc( 1000 ); // node bit patterns p->vCutsN2 = Vec_WrdAlloc( 1000 ); // node bit patterns p->vCutsNum = Vec_IntAlloc( 64 ); // cut counts for each obj p->vCutsStart = Vec_IntAlloc( 64 ); // starting cuts for each obj p->vCutsObj = Vec_IntAlloc( 1000 ); p->vSolInit = Vec_IntAlloc( 64 ); p->vSolCur = Vec_IntAlloc( 64 ); p->vSolBest = Vec_IntAlloc( 64 ); p->vTempI1 = Vec_WrdAlloc( 32 ); p->vTempI2 = Vec_WrdAlloc( 32 ); p->vTempN1 = Vec_WrdAlloc( 32 ); p->vTempN2 = Vec_WrdAlloc( 32 ); // internal p->vLits = Vec_IntAlloc( 64 ); p->vAssump = Vec_IntAlloc( 64 ); p->vPolar = Vec_IntAlloc( 1000 ); // other Gia_ManFillValue( pGia ); return p; } void Sbl_ManClean( Sbl_Man_t * p ) { p->timeStart = Abc_Clock(); sat_solver_rollback( p->pSat ); sat_solver_bookmark( p->pSat ); // internal Vec_IntClear( p->vLeaves ); Vec_IntClear( p->vAnds ); Vec_IntClear( p->vNodes ); Vec_IntClear( p->vRoots ); Vec_IntClear( p->vRootVars ); // timing Vec_IntClear( p->vArrs ); Vec_IntClear( p->vReqs ); Vec_WecClear( p->vWindow ); Vec_IntClear( p->vPath ); Vec_IntClear( p->vEdges ); // cuts Vec_WrdClear( p->vCutsI1 ); Vec_WrdClear( p->vCutsI2 ); Vec_WrdClear( p->vCutsN1 ); Vec_WrdClear( p->vCutsN2 ); Vec_IntClear( p->vCutsNum ); Vec_IntClear( p->vCutsStart ); Vec_IntClear( p->vCutsObj ); Vec_IntClear( p->vSolInit ); Vec_IntClear( p->vSolCur ); Vec_IntClear( p->vSolBest ); Vec_WrdClear( p->vTempI1 ); Vec_WrdClear( p->vTempI2 ); Vec_WrdClear( p->vTempN1 ); Vec_WrdClear( p->vTempN2 ); // temporary Vec_IntClear( p->vLits ); Vec_IntClear( p->vAssump ); Vec_IntClear( p->vPolar ); // other Gia_ManFillValue( p->pGia ); } void Sbl_ManStop( Sbl_Man_t * p ) { sat_solver_delete( p->pSat ); Vec_IntFree( p->vCardVars ); // internal Vec_IntFree( p->vLeaves ); Vec_IntFree( p->vAnds ); Vec_IntFree( p->vNodes ); Vec_IntFree( p->vRoots ); Vec_IntFree( p->vRootVars ); Hsh_VecManStop( p->pHash ); // timing Vec_IntFree( p->vArrs ); Vec_IntFree( p->vReqs ); Vec_WecFree( p->vWindow ); Vec_IntFree( p->vPath ); Vec_IntFree( p->vEdges ); // cuts Vec_WrdFree( p->vCutsI1 ); Vec_WrdFree( p->vCutsI2 ); Vec_WrdFree( p->vCutsN1 ); Vec_WrdFree( p->vCutsN2 ); Vec_IntFree( p->vCutsNum ); Vec_IntFree( p->vCutsStart ); Vec_IntFree( p->vCutsObj ); Vec_IntFree( p->vSolInit ); Vec_IntFree( p->vSolCur ); Vec_IntFree( p->vSolBest ); Vec_WrdFree( p->vTempI1 ); Vec_WrdFree( p->vTempI2 ); Vec_WrdFree( p->vTempN1 ); Vec_WrdFree( p->vTempN2 ); // temporary Vec_IntFree( p->vLits ); Vec_IntFree( p->vAssump ); Vec_IntFree( p->vPolar ); // other ABC_FREE( p ); } /**Function************************************************************* Synopsis [For each node in the window, create fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sbl_ManGetCurrentMapping( Sbl_Man_t * p ) { Vec_Int_t * vObj; word CutI1, CutI2, CutN1, CutN2; int i, c, b, iObj; Vec_WecClear( p->vWindow ); Vec_WecInit( p->vWindow, Vec_IntSize(p->vAnds) ); assert( Vec_IntSize(p->vSolCur) > 0 ); Vec_IntForEachEntry( p->vSolCur, c, i ) { CutI1 = Vec_WrdEntry( p->vCutsI1, c ); CutI2 = Vec_WrdEntry( p->vCutsI2, c ); CutN1 = Vec_WrdEntry( p->vCutsN1, c ); CutN2 = Vec_WrdEntry( p->vCutsN2, c ); iObj = Vec_IntEntry( p->vCutsObj, c ); //iObj = Vec_IntEntry( p->vAnds, iObj ); vObj = Vec_WecEntry( p->vWindow, iObj ); Vec_IntClear( vObj ); assert( Vec_IntSize(vObj) == 0 ); for ( b = 0; b < 64; b++ ) if ( (CutI1 >> b) & 1 ) Vec_IntPush( vObj, Vec_IntEntry(p->vLeaves, b) ); for ( b = 0; b < 64; b++ ) if ( (CutI2 >> b) & 1 ) Vec_IntPush( vObj, Vec_IntEntry(p->vLeaves, 64+b) ); for ( b = 0; b < 64; b++ ) if ( (CutN1 >> b) & 1 ) Vec_IntPush( vObj, Vec_IntEntry(p->vAnds, b) ); for ( b = 0; b < 64; b++ ) if ( (CutN2 >> b) & 1 ) Vec_IntPush( vObj, Vec_IntEntry(p->vAnds, 64+b) ); } } /**Function************************************************************* Synopsis [Timing computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sbl_ManComputeDelay( Sbl_Man_t * p, int iLut, Vec_Int_t * vFanins ) { int k, iFan, Delay = 0; Vec_IntForEachEntry( vFanins, iFan, k ) Delay = Abc_MaxInt( Delay, Vec_IntEntry(p->vArrs, iFan) + 1 ); return Delay; } int Sbl_ManCreateTiming( Sbl_Man_t * p, int DelayStart ) { Vec_Int_t * vFanins; int DelayMax = DelayStart, Delay, iLut, iFan, k; // compute arrival times Vec_IntFill( p->vArrs, Gia_ManObjNum(p->pGia), 0 ); if ( p->pGia->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)p->pGia->pManTime) ) { Gia_Obj_t * pObj; Vec_Int_t * vNodes = Gia_ManOrderWithBoxes( p->pGia ); Tim_ManIncrementTravId( (Tim_Man_t*)p->pGia->pManTime ); Gia_ManForEachObjVec( vNodes, p->pGia, pObj, k ) { iLut = Gia_ObjId( p->pGia, pObj ); if ( Gia_ObjIsAnd(pObj) ) { if ( Gia_ObjIsLut2(p->pGia, iLut) ) { vFanins = Gia_ObjLutFanins2(p->pGia, iLut); Delay = Sbl_ManComputeDelay( p, iLut, vFanins ); Vec_IntWriteEntry( p->vArrs, iLut, Delay ); DelayMax = Abc_MaxInt( DelayMax, Delay ); } } else if ( Gia_ObjIsCi(pObj) ) { int arrTime = Tim_ManGetCiArrival( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj) ); Vec_IntWriteEntry( p->vArrs, iLut, arrTime ); } else if ( Gia_ObjIsCo(pObj) ) { int arrTime = Vec_IntEntry( p->vArrs, Gia_ObjFaninId0(pObj, iLut) ); Tim_ManSetCoArrival( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj), arrTime ); } else if ( !Gia_ObjIsConst0(pObj) ) assert( 0 ); } Vec_IntFree( vNodes ); } else { Gia_ManForEachLut2( p->pGia, iLut ) { vFanins = Gia_ObjLutFanins2(p->pGia, iLut); Delay = Sbl_ManComputeDelay( p, iLut, vFanins ); Vec_IntWriteEntry( p->vArrs, iLut, Delay ); DelayMax = Abc_MaxInt( DelayMax, Delay ); } } // compute required times Vec_IntFill( p->vReqs, Gia_ManObjNum(p->pGia), ABC_INFINITY ); Gia_ManForEachCoDriverId( p->pGia, iLut, k ) Vec_IntDowndateEntry( p->vReqs, iLut, DelayMax ); if ( p->pGia->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)p->pGia->pManTime) ) { Gia_Obj_t * pObj; Vec_Int_t * vNodes = Gia_ManOrderWithBoxes( p->pGia ); Tim_ManIncrementTravId( (Tim_Man_t*)p->pGia->pManTime ); Tim_ManInitPoRequiredAll( (Tim_Man_t*)p->pGia->pManTime, DelayMax ); Gia_ManForEachObjVecReverse( vNodes, p->pGia, pObj, k ) { iLut = Gia_ObjId( p->pGia, pObj ); if ( Gia_ObjIsAnd(pObj) ) { if ( Gia_ObjIsLut2(p->pGia, iLut) ) { Delay = Vec_IntEntry(p->vReqs, iLut) - 1; vFanins = Gia_ObjLutFanins2(p->pGia, iLut); Vec_IntForEachEntry( vFanins, iFan, k ) Vec_IntDowndateEntry( p->vReqs, iFan, Delay ); } } else if ( Gia_ObjIsCi(pObj) ) { int reqTime = Vec_IntEntry( p->vReqs, iLut ); Tim_ManSetCiRequired( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj), reqTime ); } else if ( Gia_ObjIsCo(pObj) ) { int reqTime = Tim_ManGetCoRequired( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj) ); Vec_IntWriteEntry( p->vReqs, Gia_ObjFaninId0(pObj, iLut), reqTime ); } else if ( !Gia_ObjIsConst0(pObj) ) assert( 0 ); } Vec_IntFree( vNodes ); } else { Gia_ManForEachLut2Reverse( p->pGia, iLut ) { Delay = Vec_IntEntry(p->vReqs, iLut) - 1; vFanins = Gia_ObjLutFanins2(p->pGia, iLut); Vec_IntForEachEntry( vFanins, iFan, k ) Vec_IntDowndateEntry( p->vReqs, iFan, Delay ); } } return DelayMax; } /**Function************************************************************* Synopsis [Given mapping in p->vSolCur, check if mapping meets delay.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sbl_ManEvaluateMappingEdge( Sbl_Man_t * p, int DelayGlo ) { abctime clk = Abc_Clock(); Vec_Int_t * vArray; int i, DelayMax; Vec_IntClear( p->vPath ); // update new timing Sbl_ManGetCurrentMapping( p ); // derive new timing DelayMax = Gia_ManEvalWindow( p->pGia, p->vLeaves, p->vAnds, p->vWindow, p->vPolar, 1 ); p->timeTime += Abc_Clock() - clk; if ( DelayMax <= DelayGlo ) return 1; // create critical path composed of all nodes Vec_WecForEachLevel( p->vWindow, vArray, i ) if ( Vec_IntSize(vArray) > 0 ) Vec_IntPush( p->vPath, Abc_Var2Lit(i, 1) ); return 0; } /**Function************************************************************* Synopsis [Given mapping in p->vSolCur, check the critical path.] Description [Returns 1 if the mapping satisfies the timing. Returns 0, if the critical path is detected.] SideEffects [] SeeAlso [] ***********************************************************************/ int Sbl_ManCriticalFanin( Sbl_Man_t * p, int iLut, Vec_Int_t * vFanins ) { int k, iFan, Delay = Vec_IntEntry(p->vArrs, iLut); Vec_IntForEachEntry( vFanins, iFan, k ) if ( Vec_IntEntry(p->vArrs, iFan) + 1 == Delay ) return iFan; return -1; } int Sbl_ManEvaluateMapping( Sbl_Man_t * p, int DelayGlo ) { abctime clk = Abc_Clock(); Vec_Int_t * vFanins; int i, iLut = -1, iAnd, Delay, Required; if ( p->pGia->vEdge1 ) return Sbl_ManEvaluateMappingEdge( p, DelayGlo ); Vec_IntClear( p->vPath ); // derive timing Sbl_ManCreateTiming( p, DelayGlo ); // update new timing Sbl_ManGetCurrentMapping( p ); Vec_IntForEachEntry( p->vAnds, iLut, i ) { vFanins = Vec_WecEntry( p->vWindow, i ); Delay = Sbl_ManComputeDelay( p, iLut, vFanins ); Vec_IntWriteEntry( p->vArrs, iLut, Delay ); } // compare timing at the root nodes Vec_IntForEachEntry( p->vRoots, iLut, i ) { Delay = Vec_IntEntry( p->vArrs, iLut ); Required = Vec_IntEntry( p->vReqs, iLut ); if ( Delay > Required ) // updated timing exceeded original timing break; } p->timeTime += Abc_Clock() - clk; if ( i == Vec_IntSize(p->vRoots) ) return 1; // derive the critical path // find SAT variable of the node whose GIA ID is "iLut" iAnd = Vec_IntFind( p->vAnds, iLut ); assert( iAnd >= 0 ); // critical path begins in node "iLut", which is i-th root of the window assert( iAnd == Vec_IntEntry(p->vRootVars, i) ); while ( 1 ) { Vec_IntPush( p->vPath, Abc_Var2Lit(iAnd, 1) ); // find fanins of this node vFanins = Vec_WecEntry( p->vWindow, iAnd ); // find critical fanin iLut = Sbl_ManCriticalFanin( p, iLut, vFanins ); assert( iLut > 0 ); // find SAT variable of the node whose GIA ID is "iLut" iAnd = Vec_IntFind( p->vAnds, iLut ); if ( iAnd == -1 ) break; } return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sbl_ManUpdateMapping( Sbl_Man_t * p ) { // Gia_Obj_t * pObj; Vec_Int_t * vObj; word CutI1, CutI2, CutN1, CutN2; int i, c, b, iObj, iTemp; assert( Vec_IntSize(p->vSolBest) < Vec_IntSize(p->vSolInit) ); Vec_IntForEachEntry( p->vAnds, iObj, i ) { vObj = Vec_WecEntry(p->pGia->vMapping2, iObj); Vec_IntForEachEntry( vObj, iTemp, b ) Gia_ObjLutRefDecId( p->pGia, iTemp ); Vec_IntClear( vObj ); } Vec_IntForEachEntry( p->vSolBest, c, i ) { CutI1 = Vec_WrdEntry( p->vCutsI1, c ); CutI2 = Vec_WrdEntry( p->vCutsI2, c ); CutN1 = Vec_WrdEntry( p->vCutsN1, c ); CutN2 = Vec_WrdEntry( p->vCutsN2, c ); iObj = Vec_IntEntry( p->vCutsObj, c ); iObj = Vec_IntEntry( p->vAnds, iObj ); vObj = Vec_WecEntry( p->pGia->vMapping2, iObj ); Vec_IntClear( vObj ); assert( Vec_IntSize(vObj) == 0 ); for ( b = 0; b < 64; b++ ) if ( (CutI1 >> b) & 1 ) Vec_IntPush( vObj, Vec_IntEntry(p->vLeaves, b) ); for ( b = 0; b < 64; b++ ) if ( (CutI2 >> b) & 1 ) Vec_IntPush( vObj, Vec_IntEntry(p->vLeaves, 64+b) ); for ( b = 0; b < 64; b++ ) if ( (CutN1 >> b) & 1 ) Vec_IntPush( vObj, Vec_IntEntry(p->vAnds, b) ); for ( b = 0; b < 64; b++ ) if ( (CutN2 >> b) & 1 ) Vec_IntPush( vObj, Vec_IntEntry(p->vAnds, 64+b) ); Vec_IntForEachEntry( vObj, iTemp, b ) Gia_ObjLutRefIncId( p->pGia, iTemp ); } /* // verify Gia_ManForEachLut2Vec( p->pGia, vObj, i ) Vec_IntForEachEntry( vObj, iTemp, b ) Gia_ObjLutRefDecId( p->pGia, iTemp ); Gia_ManForEachCo( p->pGia, pObj, i ) Gia_ObjLutRefDecId( p->pGia, Gia_ObjFaninId0p(p->pGia, pObj) ); for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ ) if ( p->pGia->pLutRefs[i] ) printf( "Object %d has %d refs\n", i, p->pGia->pLutRefs[i] ); Gia_ManForEachCo( p->pGia, pObj, i ) Gia_ObjLutRefIncId( p->pGia, Gia_ObjFaninId0p(p->pGia, pObj) ); Gia_ManForEachLut2Vec( p->pGia, vObj, i ) Vec_IntForEachEntry( vObj, iTemp, b ) Gia_ObjLutRefIncId( p->pGia, iTemp ); */ } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Sbl_ManPrintCut( word CutI1, word CutI2, word CutN1, word CutN2 ) { int b, Count = 0; printf( "{ " ); for ( b = 0; b < 64; b++ ) if ( (CutI1 >> b) & 1 ) printf( "i%d ", b ), Count++; for ( b = 0; b < 64; b++ ) if ( (CutI2 >> b) & 1 ) printf( "i%d ", 64+b ), Count++; printf( " " ); for ( b = 0; b < 64; b++ ) if ( (CutN1 >> b) & 1 ) printf( "n%d ", b ), Count++; for ( b = 0; b < 64; b++ ) if ( (CutN2 >> b) & 1 ) printf( "n%d ", 64+b ), Count++; printf( "};\n" ); return Count; } static int Sbl_ManFindAndPrintCut( Sbl_Man_t * p, int c ) { return Sbl_ManPrintCut( Vec_WrdEntry(p->vCutsI1, c), Vec_WrdEntry(p->vCutsI2, c), Vec_WrdEntry(p->vCutsN1, c), Vec_WrdEntry(p->vCutsN2, c) ); } static inline int Sbl_CutIsFeasible( word CutI1, word CutI2, word CutN1, word CutN2, int LutSize ) { int Count = (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); assert( LutSize <= 6 ); CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); if ( LutSize <= 4 ) return Count <= 4; CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); return Count <= 6; } static inline int Sbl_CutPushUncontained( Vec_Wrd_t * vCutsI1, Vec_Wrd_t * vCutsI2, Vec_Wrd_t * vCutsN1, Vec_Wrd_t * vCutsN2, word CutI1, word CutI2, word CutN1, word CutN2 ) { int i, k = 0; assert( vCutsI1->nSize == vCutsN1->nSize ); assert( vCutsI2->nSize == vCutsN2->nSize ); for ( i = 0; i < vCutsI1->nSize; i++ ) if ( (vCutsI1->pArray[i] & CutI1) == vCutsI1->pArray[i] && (vCutsI2->pArray[i] & CutI2) == vCutsI2->pArray[i] && (vCutsN1->pArray[i] & CutN1) == vCutsN1->pArray[i] && (vCutsN2->pArray[i] & CutN2) == vCutsN2->pArray[i] ) return 1; for ( i = 0; i < vCutsI1->nSize; i++ ) if ( (vCutsI1->pArray[i] & CutI1) != CutI1 || (vCutsI2->pArray[i] & CutI2) != CutI2 || (vCutsN1->pArray[i] & CutN1) != CutN1 || (vCutsN2->pArray[i] & CutN2) != CutN2 ) { Vec_WrdWriteEntry( vCutsI1, k, vCutsI1->pArray[i] ); Vec_WrdWriteEntry( vCutsI2, k, vCutsI2->pArray[i] ); Vec_WrdWriteEntry( vCutsN1, k, vCutsN1->pArray[i] ); Vec_WrdWriteEntry( vCutsN2, k, vCutsN2->pArray[i] ); k++; } Vec_WrdShrink( vCutsI1, k ); Vec_WrdShrink( vCutsI2, k ); Vec_WrdShrink( vCutsN1, k ); Vec_WrdShrink( vCutsN2, k ); Vec_WrdPush( vCutsI1, CutI1 ); Vec_WrdPush( vCutsI2, CutI2 ); Vec_WrdPush( vCutsN1, CutN1 ); Vec_WrdPush( vCutsN2, CutN2 ); return 0; } static inline void Sbl_ManComputeCutsOne( Sbl_Man_t * p, int Fan0, int Fan1, int Obj ) { word * pCutsI1 = Vec_WrdArray(p->vCutsI1); word * pCutsI2 = Vec_WrdArray(p->vCutsI2); word * pCutsN1 = Vec_WrdArray(p->vCutsN1); word * pCutsN2 = Vec_WrdArray(p->vCutsN2); int Start0 = Vec_IntEntry( p->vCutsStart, Fan0 ); int Start1 = Vec_IntEntry( p->vCutsStart, Fan1 ); int Limit0 = Start0 + Vec_IntEntry( p->vCutsNum, Fan0 ); int Limit1 = Start1 + Vec_IntEntry( p->vCutsNum, Fan1 ); int i, k; assert( Obj >= 0 && Obj < 128 ); Vec_WrdClear( p->vTempI1 ); Vec_WrdClear( p->vTempI2 ); Vec_WrdClear( p->vTempN1 ); Vec_WrdClear( p->vTempN2 ); for ( i = Start0; i < Limit0; i++ ) for ( k = Start1; k < Limit1; k++ ) if ( Sbl_CutIsFeasible(pCutsI1[i] | pCutsI1[k], pCutsI2[i] | pCutsI2[k], pCutsN1[i] | pCutsN1[k], pCutsN2[i] | pCutsN2[k], p->LutSize) ) Sbl_CutPushUncontained( p->vTempI1, p->vTempI2, p->vTempN1, p->vTempN2, pCutsI1[i] | pCutsI1[k], pCutsI2[i] | pCutsI2[k], pCutsN1[i] | pCutsN1[k], pCutsN2[i] | pCutsN2[k] ); Vec_IntPush( p->vCutsStart, Vec_WrdSize(p->vCutsI1) ); Vec_IntPush( p->vCutsNum, Vec_WrdSize(p->vTempI1) + 1 ); Vec_WrdAppend( p->vCutsI1, p->vTempI1 ); Vec_WrdAppend( p->vCutsI2, p->vTempI2 ); Vec_WrdAppend( p->vCutsN1, p->vTempN1 ); Vec_WrdAppend( p->vCutsN2, p->vTempN2 ); Vec_WrdPush( p->vCutsI1, 0 ); Vec_WrdPush( p->vCutsI2, 0 ); if ( Obj < 64 ) { Vec_WrdPush( p->vCutsN1, (((word)1) << Obj) ); Vec_WrdPush( p->vCutsN2, 0 ); } else { Vec_WrdPush( p->vCutsN1, 0 ); Vec_WrdPush( p->vCutsN2, (((word)1) << (Obj-64)) ); } for ( i = 0; i <= Vec_WrdSize(p->vTempI1); i++ ) Vec_IntPush( p->vCutsObj, Obj ); } static inline int Sbl_ManFindCut( Sbl_Man_t * p, int Obj, word CutI1, word CutI2, word CutN1, word CutN2 ) { word * pCutsI1 = Vec_WrdArray(p->vCutsI1); word * pCutsI2 = Vec_WrdArray(p->vCutsI2); word * pCutsN1 = Vec_WrdArray(p->vCutsN1); word * pCutsN2 = Vec_WrdArray(p->vCutsN2); int Start0 = Vec_IntEntry( p->vCutsStart, Obj ); int Limit0 = Start0 + Vec_IntEntry( p->vCutsNum, Obj ); int i; //printf( "\nLooking for:\n" ); //Sbl_ManPrintCut( CutI, CutN ); //printf( "\n" ); for ( i = Start0; i < Limit0; i++ ) { //Sbl_ManPrintCut( pCutsI[i], pCutsN[i] ); if ( pCutsI1[i] == CutI1 && pCutsI2[i] == CutI2 && pCutsN1[i] == CutN1 && pCutsN2[i] == CutN2 ) return i; } return -1; } int Sbl_ManComputeCuts( Sbl_Man_t * p ) { abctime clk = Abc_Clock(); Gia_Obj_t * pObj; Vec_Int_t * vFanins; int i, k, Index, Fanin, nObjs = Vec_IntSize(p->vLeaves) + Vec_IntSize(p->vAnds); assert( Vec_IntSize(p->vLeaves) <= 128 && Vec_IntSize(p->vAnds) <= p->nVars ); // assign leaf cuts Vec_IntClear( p->vCutsStart ); Vec_IntClear( p->vCutsObj ); Vec_IntClear( p->vCutsNum ); Vec_WrdClear( p->vCutsI1 ); Vec_WrdClear( p->vCutsI2 ); Vec_WrdClear( p->vCutsN1 ); Vec_WrdClear( p->vCutsN2 ); Gia_ManForEachObjVec( p->vLeaves, p->pGia, pObj, i ) { Vec_IntPush( p->vCutsStart, Vec_WrdSize(p->vCutsI1) ); Vec_IntPush( p->vCutsObj, -1 ); Vec_IntPush( p->vCutsNum, 1 ); if ( i < 64 ) { Vec_WrdPush( p->vCutsI1, (((word)1) << i) ); Vec_WrdPush( p->vCutsI2, 0 ); } else { Vec_WrdPush( p->vCutsI1, 0 ); Vec_WrdPush( p->vCutsI2, (((word)1) << (i-64)) ); } Vec_WrdPush( p->vCutsN1, 0 ); Vec_WrdPush( p->vCutsN2, 0 ); pObj->Value = i; } // assign internal cuts Gia_ManForEachObjVec( p->vAnds, p->pGia, pObj, i ) { assert( Gia_ObjIsAnd(pObj) ); assert( ~Gia_ObjFanin0(pObj)->Value ); assert( ~Gia_ObjFanin1(pObj)->Value ); Sbl_ManComputeCutsOne( p, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value, i ); pObj->Value = Vec_IntSize(p->vLeaves) + i; } assert( Vec_IntSize(p->vCutsStart) == nObjs ); assert( Vec_IntSize(p->vCutsNum) == nObjs ); assert( Vec_WrdSize(p->vCutsI1) == Vec_WrdSize(p->vCutsN1) ); assert( Vec_WrdSize(p->vCutsI2) == Vec_WrdSize(p->vCutsN2) ); assert( Vec_WrdSize(p->vCutsI1) == Vec_IntSize(p->vCutsObj) ); // check that roots are mapped nodes Vec_IntClear( p->vRootVars ); Gia_ManForEachObjVec( p->vRoots, p->pGia, pObj, i ) { int Obj = Gia_ObjId(p->pGia, pObj); if ( Gia_ObjIsCi(pObj) ) continue; assert( Gia_ObjIsLut2(p->pGia, Obj) ); assert( ~pObj->Value ); Vec_IntPush( p->vRootVars, pObj->Value - Vec_IntSize(p->vLeaves) ); } // create current solution Vec_IntClear( p->vPolar ); Vec_IntClear( p->vSolInit ); Gia_ManForEachObjVec( p->vAnds, p->pGia, pObj, i ) { word CutI1 = 0, CutI2 = 0, CutN1 = 0, CutN2 = 0; int Obj = Gia_ObjId(p->pGia, pObj); if ( !Gia_ObjIsLut2(p->pGia, Obj) ) continue; assert( (int)pObj->Value == Vec_IntSize(p->vLeaves) + i ); // add node Vec_IntPush( p->vPolar, i ); Vec_IntPush( p->vSolInit, i ); // add its cut //Gia_LutForEachFaninObj( p->pGia, Obj, pFanin, k ) vFanins = Gia_ObjLutFanins2( p->pGia, Obj ); Vec_IntForEachEntry( vFanins, Fanin, k ) { Gia_Obj_t * pFanin = Gia_ManObj( p->pGia, Fanin ); assert( (int)pFanin->Value < Vec_IntSize(p->vLeaves) || Gia_ObjIsLut2(p->pGia, Fanin) ); // if ( ~pFanin->Value == 0 ) // Gia_ManPrintConeMulti( p->pGia, p->vAnds, p->vLeaves, p->vPath ); if ( ~pFanin->Value == 0 ) continue; assert( ~pFanin->Value ); if ( (int)pFanin->Value < Vec_IntSize(p->vLeaves) ) { if ( (int)pFanin->Value < 64 ) CutI1 |= ((word)1 << pFanin->Value); else CutI2 |= ((word)1 << (pFanin->Value - 64)); } else { if ( pFanin->Value - Vec_IntSize(p->vLeaves) < 64 ) CutN1 |= ((word)1 << (pFanin->Value - Vec_IntSize(p->vLeaves))); else CutN2 |= ((word)1 << (pFanin->Value - Vec_IntSize(p->vLeaves) - 64)); } } // find the new cut Index = Sbl_ManFindCut( p, Vec_IntSize(p->vLeaves) + i, CutI1, CutI2, CutN1, CutN2 ); if ( Index < 0 ) { //printf( "Cannot find the available cut.\n" ); continue; } assert( Index >= 0 ); Vec_IntPush( p->vPolar, p->FirstVar+Index ); } // clean value Gia_ManForEachObjVec( p->vLeaves, p->pGia, pObj, i ) pObj->Value = ~0; Gia_ManForEachObjVec( p->vAnds, p->pGia, pObj, i ) pObj->Value = ~0; p->timeCut += Abc_Clock() - clk; return Vec_WrdSize(p->vCutsI1); } int Sbl_ManCreateCnf( Sbl_Man_t * p ) { int i, k, c, pLits[2], value; word * pCutsN1 = Vec_WrdArray(p->vCutsN1); word * pCutsN2 = Vec_WrdArray(p->vCutsN2); assert( p->FirstVar == sat_solver_nvars(p->pSat) ); sat_solver_setnvars( p->pSat, sat_solver_nvars(p->pSat) + Vec_WrdSize(p->vCutsI1) ); //printf( "\n" ); for ( i = 0; i < Vec_IntSize(p->vAnds); i++ ) { int Start0 = Vec_IntEntry( p->vCutsStart, Vec_IntSize(p->vLeaves) + i ); int Limit0 = Start0 + Vec_IntEntry( p->vCutsNum, Vec_IntSize(p->vLeaves) + i ) - 1; // add main clause Vec_IntClear( p->vLits ); Vec_IntPush( p->vLits, Abc_Var2Lit(i, 1) ); //printf( "Node %d implies cuts: ", i ); for ( k = Start0; k < Limit0; k++ ) { Vec_IntPush( p->vLits, Abc_Var2Lit(p->FirstVar+k, 0) ); //printf( "%d ", p->FirstVar+k ); } //printf( "\n" ); value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); assert( value ); // binary clauses for ( k = Start0; k < Limit0; k++ ) { word Cut1 = pCutsN1[k]; word Cut2 = pCutsN2[k]; //printf( "Cut %d implies root node %d.\n", p->FirstVar+k, i ); // root clause pLits[0] = Abc_Var2Lit( p->FirstVar+k, 1 ); pLits[1] = Abc_Var2Lit( i, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( value ); // fanin clauses for ( c = 0; c < 64 && Cut1; c++, Cut1 >>= 1 ) { if ( (Cut1 & 1) == 0 ) continue; //printf( "Cut %d implies fanin %d.\n", p->FirstVar+k, c ); pLits[1] = Abc_Var2Lit( c, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( value ); } for ( c = 0; c < 64 && Cut2; c++, Cut2 >>= 1 ) { if ( (Cut2 & 1) == 0 ) continue; //printf( "Cut %d implies fanin %d.\n", p->FirstVar+k, c ); pLits[1] = Abc_Var2Lit( c+64, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( value ); } } } sat_solver_set_polarity( p->pSat, Vec_IntArray(p->vPolar), Vec_IntSize(p->vPolar) ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Sbl_ManWindow( Sbl_Man_t * p ) { int i, ObjId; // collect leaves Vec_IntClear( p->vLeaves ); Gia_ManForEachCiId( p->pGia, ObjId, i ) Vec_IntPush( p->vLeaves, ObjId ); // collect internal Vec_IntClear( p->vAnds ); Gia_ManForEachAndId( p->pGia, ObjId ) Vec_IntPush( p->vAnds, ObjId ); // collect roots Vec_IntClear( p->vRoots ); Gia_ManForEachCoDriverId( p->pGia, ObjId, i ) Vec_IntPush( p->vRoots, ObjId ); } int Sbl_ManWindow2( Sbl_Man_t * p, int iPivot ) { abctime clk = Abc_Clock(); Vec_Int_t * vRoots, * vNodes, * vLeaves, * vAnds; int Count = Gia_ManComputeOneWin( p->pGia, iPivot, &vRoots, &vNodes, &vLeaves, &vAnds ); p->timeWin += Abc_Clock() - clk; if ( Count == 0 ) return 0; Vec_IntClear( p->vRoots ); Vec_IntAppend( p->vRoots, vRoots ); Vec_IntClear( p->vNodes ); Vec_IntAppend( p->vNodes, vNodes ); Vec_IntClear( p->vLeaves ); Vec_IntAppend( p->vLeaves, vLeaves ); Vec_IntClear( p->vAnds ); Vec_IntAppend( p->vAnds, vAnds ); //Vec_IntPrint( vRoots ); //Vec_IntPrint( vAnds ); //Vec_IntPrint( vLeaves ); // recompute internal nodes // Gia_ManIncrementTravId( p->pGia ); // Gia_ManCollectAnds( p->pGia, Vec_IntArray(p->vRoots), Vec_IntSize(p->vRoots), p->vAnds, p->vLeaves ); return Count; } int Sbl_ManTestSat( Sbl_Man_t * p, int iPivot ) { int fKeepTrying = 1; abctime clk = Abc_Clock(), clk2; int i, status, Root, Count, StartSol, nConfTotal = 0, nIters = 0; int nEntries = Hsh_VecSize( p->pHash ); p->nTried++; Sbl_ManClean( p ); // compute one window Count = Sbl_ManWindow2( p, iPivot ); if ( Count == 0 ) { if ( p->fVeryVerbose ) printf( "Obj %d: Window with less than %d nodes does not exist.\n", iPivot, p->nVars ); p->nSmallWins++; return 0; } Hsh_VecManAdd( p->pHash, p->vAnds ); if ( nEntries == Hsh_VecSize(p->pHash) ) { if ( p->fVeryVerbose ) printf( "Obj %d: This window was already tried.\n", iPivot ); p->nHashWins++; return 0; } if ( p->fVeryVerbose ) printf( "\nObj = %6d : Leaf = %2d. AND = %2d. Root = %2d. LUT = %2d.\n", iPivot, Vec_IntSize(p->vLeaves), Vec_IntSize(p->vAnds), Vec_IntSize(p->vRoots), Vec_IntSize(p->vNodes) ); if ( Vec_IntSize(p->vLeaves) > 128 || Vec_IntSize(p->vAnds) > p->nVars ) { if ( p->fVeryVerbose ) printf( "Obj %d: Encountered window with %d inputs and %d internal nodes.\n", iPivot, Vec_IntSize(p->vLeaves), Vec_IntSize(p->vAnds) ); p->nLargeWins++; return 0; } if ( Vec_IntSize(p->vAnds) < 10 ) { if ( p->fVeryVerbose ) printf( "Skipping.\n" ); return 0; } // derive cuts Sbl_ManComputeCuts( p ); // derive SAT instance Sbl_ManCreateCnf( p ); if ( p->fVeryVeryVerbose ) printf( "All clauses = %d. Multi clauses = %d. Binary clauses = %d. Other clauses = %d.\n\n", sat_solver_nclauses(p->pSat), Vec_IntSize(p->vAnds), Vec_WrdSize(p->vCutsI1) - Vec_IntSize(p->vAnds), sat_solver_nclauses(p->pSat) - Vec_WrdSize(p->vCutsI1) ); // create assumptions // cardinality Vec_IntClear( p->vAssump ); Vec_IntPush( p->vAssump, -1 ); // unused variables for ( i = Vec_IntSize(p->vAnds); i < p->Power2; i++ ) Vec_IntPush( p->vAssump, Abc_Var2Lit(i, 1) ); // root variables Vec_IntForEachEntry( p->vRootVars, Root, i ) Vec_IntPush( p->vAssump, Abc_Var2Lit(Root, 0) ); // Vec_IntPrint( p->vAssump ); StartSol = Vec_IntSize(p->vSolInit) + 1; // StartSol = 30; while ( fKeepTrying && StartSol-fKeepTrying > 0 ) { int Count = 0, LitCount = 0; int nConfBef, nConfAft; if ( p->fVeryVerbose ) printf( "Trying to find mapping with %d LUTs.\n", StartSol-fKeepTrying ); // for ( i = Vec_IntSize(p->vSolInit)-5; i < nVars; i++ ) // Vec_IntPush( p->vAssump, Abc_Var2Lit(Vec_IntEntry(p->vCardVars, i), 1) ); Vec_IntWriteEntry( p->vAssump, 0, Abc_Var2Lit(Vec_IntEntry(p->vCardVars, StartSol-fKeepTrying), 1) ); // solve the problem clk2 = Abc_Clock(); nConfBef = (int)p->pSat->stats.conflicts; status = sat_solver_solve( p->pSat, Vec_IntArray(p->vAssump), Vec_IntLimit(p->vAssump), p->nBTLimit, 0, 0, 0 ); p->timeSat += Abc_Clock() - clk2; nConfAft = (int)p->pSat->stats.conflicts; nConfTotal += nConfAft - nConfBef; nIters++; p->nRuns++; if ( status == l_True ) p->timeSatSat += Abc_Clock() - clk2; else if ( status == l_False ) p->timeSatUns += Abc_Clock() - clk2; else p->timeSatUnd += Abc_Clock() - clk2; if ( status == l_Undef ) break; if ( status == l_True ) { if ( p->fVeryVeryVerbose ) { for ( i = 0; i < Vec_IntSize(p->vAnds); i++ ) printf( "%d", sat_solver_var_value(p->pSat, i) ); printf( "\n" ); for ( i = 0; i < Vec_IntSize(p->vAnds); i++ ) if ( sat_solver_var_value(p->pSat, i) ) { printf( "%d=%d ", i, sat_solver_var_value(p->pSat, i) ); Count++; } printf( "Count = %d\n", Count ); } // for ( i = p->FirstVar; i < sat_solver_nvars(p->pSat); i++ ) // printf( "%d", sat_solver_var_value(p->pSat, i) ); // printf( "\n" ); Count = 1; Vec_IntClear( p->vSolCur ); for ( i = p->FirstVar; i < sat_solver_nvars(p->pSat); i++ ) if ( sat_solver_var_value(p->pSat, i) ) { if ( p->fVeryVeryVerbose ) printf( "Cut %3d : Node = %3d %6d ", Count++, Vec_IntEntry(p->vCutsObj, i-p->FirstVar), Vec_IntEntry(p->vAnds, Vec_IntEntry(p->vCutsObj, i-p->FirstVar)) ); if ( p->fVeryVeryVerbose ) LitCount += Sbl_ManFindAndPrintCut( p, i-p->FirstVar ); Vec_IntPush( p->vSolCur, i-p->FirstVar ); } //Vec_IntPrint( p->vRootVars ); //Vec_IntPrint( p->vRoots ); //Vec_IntPrint( p->vAnds ); //Vec_IntPrint( p->vLeaves ); } // fKeepTrying = status == l_True ? fKeepTrying + 1 : 0; // check the timing if ( status == l_True ) { if ( p->fDelay && !Sbl_ManEvaluateMapping(p, p->DelayMax) ) { int iLit, value; if ( p->fVeryVerbose ) { printf( "Critical path of length (%d) is detected: ", Vec_IntSize(p->vPath) ); Vec_IntForEachEntry( p->vPath, iLit, i ) printf( "%d=%d ", i, Vec_IntEntry(p->vAnds, Abc_Lit2Var(iLit)) ); printf( "\n" ); } // add the clause value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vPath), Vec_IntLimit(p->vPath) ); assert( value ); } else { Vec_IntClear( p->vSolBest ); Vec_IntAppend( p->vSolBest, p->vSolCur ); fKeepTrying++; } } else fKeepTrying = 0; if ( p->fVeryVerbose ) { if ( status == l_False ) printf( "UNSAT " ); else if ( status == l_True ) printf( "SAT " ); else printf( "UNDEC " ); printf( "confl =%8d. ", nConfAft - nConfBef ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 ); printf( "Total " ); printf( "confl =%8d. ", nConfTotal ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( p->fVeryVeryVerbose && status == l_True ) printf( "LitCount = %d.\n", LitCount ); printf( "\n" ); } if ( nIters == 10 ) { p->nIterOuts++; //printf( "Obj %d : Quitting after %d iterations.\n", iPivot, nIters ); break; } } // update solution if ( Vec_IntSize(p->vSolBest) > 0 && Vec_IntSize(p->vSolBest) < Vec_IntSize(p->vSolInit) ) { int nDelayCur, nEdgesCur = 0; Sbl_ManUpdateMapping( p ); if ( p->pGia->vEdge1 ) { nDelayCur = Gia_ManEvalEdgeDelay( p->pGia ); nEdgesCur = Gia_ManEvalEdgeCount( p->pGia ); } else nDelayCur = Sbl_ManCreateTiming( p, p->DelayMax ); if ( p->fVerbose ) printf( "Object %5d : Saved %2d nodes (Conf =%8d) Iter =%3d Delay = %d Edges = %4d\n", iPivot, Vec_IntSize(p->vSolInit)-Vec_IntSize(p->vSolBest), nConfTotal, nIters, nDelayCur, nEdgesCur ); p->timeTotal += Abc_Clock() - p->timeStart; p->nImproved++; return 2; } else { // printf( "Object %5d : Saved %2d nodes (Conf =%8d) Iter =%3d\n", iPivot, 0, nConfTotal, nIters ); } p->timeTotal += Abc_Clock() - p->timeStart; return 1; } void Sbl_ManPrintRuntime( Sbl_Man_t * p ) { printf( "Runtime breakdown:\n" ); p->timeOther = p->timeTotal - p->timeWin - p->timeCut - p->timeSat - p->timeTime; ABC_PRTP( "Win ", p->timeWin , p->timeTotal ); ABC_PRTP( "Cut ", p->timeCut , p->timeTotal ); ABC_PRTP( "Sat ", p->timeSat, p->timeTotal ); ABC_PRTP( " Sat ", p->timeSatSat, p->timeTotal ); ABC_PRTP( " Unsat", p->timeSatUns, p->timeTotal ); ABC_PRTP( " Undec", p->timeSatUnd, p->timeTotal ); ABC_PRTP( "Timing", p->timeTime , p->timeTotal ); ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); ABC_PRTP( "ALL ", p->timeTotal, p->timeTotal ); } void Gia_ManLutSat( Gia_Man_t * pGia, int LutSize, int nNumber, int nImproves, int nBTLimit, int DelayMax, int nEdges, int fDelay, int fReverse, int fVerbose, int fVeryVerbose ) { int iLut, nImproveCount = 0; Sbl_Man_t * p = Sbl_ManAlloc( pGia, nNumber ); p->LutSize = LutSize; // LUT size p->nBTLimit = nBTLimit; // conflicts p->DelayMax = DelayMax; // external delay p->nEdges = nEdges; // the number of edges p->fDelay = fDelay; // delay mode p->fReverse = fReverse; // reverse windowing p->fVerbose = fVerbose | fVeryVerbose; p->fVeryVerbose = fVeryVerbose; if ( p->fVerbose ) printf( "Parameters: WinSize = %d AIG nodes. Conf = %d. DelayMax = %d.\n", p->nVars, p->nBTLimit, p->DelayMax ); // determine delay limit if ( fDelay && pGia->vEdge1 && p->DelayMax == 0 ) p->DelayMax = Gia_ManEvalEdgeDelay( pGia ); // iterate through the internal nodes Gia_ManComputeOneWinStart( pGia, nNumber, fReverse ); Gia_ManForEachLut2( pGia, iLut ) { if ( Sbl_ManTestSat( p, iLut ) != 2 ) continue; if ( ++nImproveCount == nImproves ) break; } Gia_ManComputeOneWin( pGia, -1, NULL, NULL, NULL, NULL ); if ( p->fVerbose ) printf( "Tried = %d. Used = %d. HashWin = %d. SmallWin = %d. LargeWin = %d. IterOut = %d. SAT runs = %d.\n", p->nTried, p->nImproved, p->nHashWins, p->nSmallWins, p->nLargeWins, p->nIterOuts, p->nRuns ); if ( p->fVerbose ) Sbl_ManPrintRuntime( p ); Sbl_ManStop( p ); Vec_IntFreeP( &pGia->vPacking ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_RunKadical( char * pFileNameIn, char * pFileNameOut, int Seed, int nBTLimit, int TimeOut, int fVerbose, int * pStatus ) { extern Vec_Int_t * Exa4_ManParse( char *pFileName ); int fVerboseSolver = 0; abctime clkTotal = Abc_Clock(); Vec_Int_t * vRes = NULL; #ifdef _WIN32 char * pKadical = "kadical.exe"; #else char * pKadical = "./kadical"; FILE * pFile = fopen( pKadical, "rb" ); if ( pFile == NULL ) pKadical += 2; else fclose( pFile ); #endif char Command[1000], * pCommand = (char *)&Command; if ( nBTLimit ) { if ( TimeOut ) sprintf( pCommand, "%s --seed=%d -c %d -t %d %s %s > %s", pKadical, Seed, nBTLimit, TimeOut, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut ); else sprintf( pCommand, "%s --seed=%d -c %d %s %s > %s", pKadical, Seed, nBTLimit, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut ); } else { if ( TimeOut ) sprintf( pCommand, "%s --seed=%d -t %d %s %s > %s", pKadical, Seed, TimeOut, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut ); else sprintf( pCommand, "%s --seed=%d %s %s > %s", pKadical, Seed, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut ); } #ifdef __wasm if ( 1 ) #else if ( system( pCommand ) == -1 ) #endif { fprintf( stdout, "Command \"%s\" did not succeed.\n", pCommand ); return 0; } vRes = Exa4_ManParse( pFileNameOut ); if ( fVerbose ) { if ( vRes ) printf( "The problem has a solution. " ), *pStatus = 0; else if ( vRes == NULL && TimeOut == 0 ) printf( "The problem has no solution. " ), *pStatus = 1; else if ( vRes == NULL ) printf( "The problem has no solution or reached a resource limit after %d sec. ", TimeOut ), *pStatus = -1; Abc_PrintTime( 1, "SAT solver time", Abc_Clock() - clkTotal ); } return vRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_SatVarReqPos( int i ) { return i*7+0; } // p int Gia_SatVarReqNeg( int i ) { return i*7+1; } // n int Gia_SatVarAckPos( int i ) { return i*7+2; } // P int Gia_SatVarAckNeg( int i ) { return i*7+3; } // N int Gia_SatVarInv ( int i ) { return i*7+4; } // i int Gia_SatVarFan0 ( int i ) { return i*7+5; } // 0 int Gia_SatVarFan1 ( int i ) { return i*7+6; } // 1 int Gia_SatValReqPos( Vec_Int_t * p, int i ) { return Vec_IntEntry(p, i*7+0); } // p int Gia_SatValReqNeg( Vec_Int_t * p, int i ) { return Vec_IntEntry(p, i*7+1); } // n int Gia_SatValAckPos( Vec_Int_t * p, int i ) { return Vec_IntEntry(p, i*7+2); } // P int Gia_SatValAckNeg( Vec_Int_t * p, int i ) { return Vec_IntEntry(p, i*7+3); } // N int Gia_SatValInv ( Vec_Int_t * p, int i ) { return Vec_IntEntry(p, i*7+4); } // i int Gia_SatValFan0 ( Vec_Int_t * p, int i ) { return Vec_IntEntry(p, i*7+5); } // 0 int Gia_SatValFan1 ( Vec_Int_t * p, int i ) { return Vec_IntEntry(p, i*7+6); } // 1 void Gia_SatDumpClause( Vec_Str_t * vStr, int * pLits, int nLits ) { for ( int i = 0; i < nLits; i++ ) Vec_StrPrintF( vStr, "%d ", Abc_LitIsCompl(pLits[i]) ? -Abc_Lit2Var(pLits[i])-1 : Abc_Lit2Var(pLits[i])+1 ); Vec_StrPrintF( vStr, "0\n" ); } void Gia_SatDumpLiteral( Vec_Str_t * vStr, int Lit ) { Gia_SatDumpClause( vStr, &Lit, 1 ); } void Gia_SatDumpKlause( Vec_Str_t * vStr, int nIns, int nAnds, int nBound ) { int i, nVars = nIns + 7*nAnds; Vec_StrPrintF( vStr, "k %d ", nVars - nBound ); // counting primary inputs: n for ( i = 0; i < nIns; i++ ) Vec_StrPrintF( vStr, "-%d ", Gia_SatVarReqNeg(1+i)+1 ); // counting internal nodes: p, n, P, N, i, 0, 1 for ( i = 0; i < 7*nAnds; i++ ) Vec_StrPrintF( vStr, "-%d ", (1+nIns)*7+i+1 ); Vec_StrPrintF( vStr, "0\n" ); } Vec_Str_t * Gia_ManSimpleCnf( Gia_Man_t * p, int nBound ) { Vec_Str_t * vStr = Vec_StrAlloc( 10000 ); Gia_SatDumpKlause( vStr, Gia_ManCiNum(p), Gia_ManAndNum(p), nBound ); int i, n, m, Id, pLits[4]; Gia_Obj_t * pObj; for ( n = 0; n < 7; n++ ) Gia_SatDumpLiteral( vStr, Abc_Var2Lit(n, 1) ); // acknowledge positive PI literals Gia_ManForEachCiId( p, Id, i ) for ( n = 0; n < 7; n++ ) if ( n != 1 ) Gia_SatDumpLiteral( vStr, Abc_Var2Lit(Gia_SatVarReqPos(Id)+n, n>0) ); // require driving PO literals Gia_ManForEachCo( p, pObj, i ) Gia_SatDumpLiteral( vStr, Abc_Var2Lit( Gia_SatVarReqPos(Gia_ObjFaninId0p(p, pObj)) + Gia_ObjFaninC0(pObj), 0 ) ); // internal nodes Gia_ManForEachAnd( p, pObj, i ) { int fCompl[2] = { Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj) }; int iFans[2] = { Gia_ObjFaninId0(pObj, i), Gia_ObjFaninId1(pObj, i) }; Gia_Obj_t * pFans[2] = { Gia_ObjFanin0(pObj), Gia_ObjFanin1(pObj) }; // require inverter: p & !n & N -> i, n & !p & P -> i for ( n = 0; n < 2; n++ ) { pLits[0] = Abc_Var2Lit( Gia_SatVarReqPos(i)+n, 1 ); pLits[1] = Abc_Var2Lit( Gia_SatVarReqNeg(i)-n, 0 ); pLits[2] = Abc_Var2Lit( Gia_SatVarAckNeg(i)-n, 1 ); pLits[3] = Abc_Var2Lit( Gia_SatVarInv (i), 0 ); Gia_SatDumpClause( vStr, pLits, 4 ); } // exclusive acknowledge: !P + !N pLits[0] = Abc_Var2Lit( Gia_SatVarAckPos(i), 1 ); pLits[1] = Abc_Var2Lit( Gia_SatVarAckNeg(i), 1 ); Gia_SatDumpClause( vStr, pLits, 2 ); // required acknowledge: p -> P + N, n -> P + N pLits[1] = Abc_Var2Lit( Gia_SatVarAckPos(i), 0 ); pLits[2] = Abc_Var2Lit( Gia_SatVarAckNeg(i), 0 ); pLits[0] = Abc_Var2Lit( Gia_SatVarReqPos(i), 1 ); Gia_SatDumpClause( vStr, pLits, 3 ); pLits[0] = Abc_Var2Lit( Gia_SatVarReqNeg(i), 1 ); Gia_SatDumpClause( vStr, pLits, 3 ); // forbid acknowledge: !p & !n -> !P, !p & !n -> !N pLits[0] = Abc_Var2Lit( Gia_SatVarReqPos(i), 0 ); pLits[1] = Abc_Var2Lit( Gia_SatVarReqNeg(i), 0 ); pLits[2] = Abc_Var2Lit( Gia_SatVarAckPos(i), 1 ); Gia_SatDumpClause( vStr, pLits, 3 ); pLits[2] = Abc_Var2Lit( Gia_SatVarAckNeg(i), 1 ); Gia_SatDumpClause( vStr, pLits, 3 ); // when fanins can be used: !N & !P -> !0, !N & !P -> !1 pLits[0] = Abc_Var2Lit( Gia_SatVarAckPos(i), 0 ); pLits[1] = Abc_Var2Lit( Gia_SatVarAckNeg(i), 0 ); pLits[2] = Abc_Var2Lit( Gia_SatVarFan0(i), 1 ); Gia_SatDumpClause( vStr, pLits, 3 ); pLits[2] = Abc_Var2Lit( Gia_SatVarFan1(i), 1 ); Gia_SatDumpClause( vStr, pLits, 3 ); // when fanins are not used: 0 -> !N, 0 -> !P, 1 -> !N, 1 -> !P for ( m = 0; m < 2; m++ ) for ( n = 0; n < 2; n++ ) { pLits[0] = Abc_Var2Lit( Gia_SatVarFan0(i)+n, 1 ); pLits[1] = Abc_Var2Lit( Gia_SatVarReqPos(iFans[n])+m, 1 ); Gia_SatDumpClause( vStr, pLits, 2 ); } // can only extend both when both complemented: !(C0 & C1) -> !0 + !1 pLits[0] = Abc_Var2Lit( Gia_SatVarFan0(i), 1 ); pLits[1] = Abc_Var2Lit( Gia_SatVarFan1(i), 1 ); if ( !fCompl[0] || !fCompl[1] ) Gia_SatDumpClause( vStr, pLits, 2 ); // if fanin is a primary input, cannot extend it (pi -> !0 or pi -> !1) for ( n = 0; n < 2; n++ ) if ( Gia_ObjIsCi(pFans[n]) ) Gia_SatDumpLiteral( vStr, Abc_Var2Lit( Gia_SatVarFan0(i)+n, 1 ) ); // propagating assignments when fanin is not used // P & !0 -> C0 ? P0 : N0 // N & !0 -> C0 ? N0 : P0 // P & !1 -> C1 ? P1 : N1 // N & !1 -> C1 ? N1 : P1 for ( m = 0; m < 2; m++ ) for ( n = 0; n < 2; n++ ) { pLits[0] = Abc_Var2Lit( Gia_SatVarAckPos(i)+m, 1 ); pLits[1] = Abc_Var2Lit( Gia_SatVarFan0(i)+n, 0 ); pLits[2] = Abc_Var2Lit( Gia_SatVarReqPos(iFans[n]) + !(m ^ fCompl[n]), 0 ); Gia_SatDumpClause( vStr, pLits, 3 ); } // propagating assignments when fanins are used // P & 0 -> (C0 ^ C00) ? P00 : N00 // P & 0 -> (C0 ^ C01) ? P01 : N01 // N & 0 -> (C0 ^ C00) ? N00 : P00 // N & 0 -> (C0 ^ C01) ? N01 : P01 // P & 1 -> (C1 ^ C10) ? P10 : N10 // P & 1 -> (C1 ^ C11) ? P11 : N11 // N & 1 -> (C1 ^ C10) ? N10 : P10 // N & 1 -> (C1 ^ C11) ? N11 : P11 for ( m = 0; m < 2; m++ ) for ( n = 0; n < 2; n++ ) if ( Gia_ObjIsAnd(pFans[n]) ) { pLits[0] = Abc_Var2Lit( Gia_SatVarAckPos(i)+m, 1 ); pLits[1] = Abc_Var2Lit( Gia_SatVarFan0(i)+n, 1 ); pLits[2] = Abc_Var2Lit( Gia_SatVarReqPos(Gia_ObjFaninId0p(p, pFans[n])) + !(m ^ fCompl[n] ^ Gia_ObjFaninC0(pFans[n])), 0 ); Gia_SatDumpClause( vStr, pLits, 3 ); pLits[2] = Abc_Var2Lit( Gia_SatVarReqPos(Gia_ObjFaninId1p(p, pFans[n])) + !(m ^ fCompl[n] ^ Gia_ObjFaninC1(pFans[n])), 0 ); Gia_SatDumpClause( vStr, pLits, 3 ); } } Vec_StrPush( vStr, '\0' ); return vStr; } typedef enum { GIA_GATE_ZERO, // 0: GIA_GATE_ONE, // 1: GIA_GATE_BUF, // 2: GIA_GATE_INV, // 3: GIA_GATE_NAN2, // 4: GIA_GATE_NOR2, // 5: GIA_GATE_AOI21, // 6: GIA_GATE_NAN3, // 7: GIA_GATE_NOR3, // 8: GIA_GATE_OAI21, // 9: GIA_GATE_AOI22, // 10: GIA_GATE_OAI22, // 11: RTM_VAL_VOID // 12: unused value } Gia_ManGate_t; Vec_Int_t * Gia_ManDeriveSimpleMapping( Gia_Man_t * p, Vec_Int_t * vRes ) { Vec_Int_t * vMapping = Vec_IntStart( 2*Gia_ManObjNum(p) ); int i, Id; Gia_Obj_t * pObj; Gia_ManForEachCiId( p, Id, i ) if ( Gia_SatValReqNeg(vRes, Id) ) Vec_IntWriteEntry( vMapping, Abc_Var2Lit(Id, 1), -1 ); Gia_ManForEachAnd( p, pObj, i ) { if ( Gia_SatValAckPos(vRes, i) + Gia_SatValAckNeg(vRes, i) == 0 ) continue; assert( Gia_SatValAckPos(vRes, i) != Gia_SatValAckNeg(vRes, i) ); if ( (Gia_SatValReqPos(vRes, i) && Gia_SatValReqNeg(vRes, i)) || Gia_SatValInv(vRes, i) ) Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, Gia_SatValAckPos(vRes, i)), -1 ); int fComp = Gia_SatValAckNeg(vRes, i); int fFan0 = Gia_SatValFan0(vRes, i); int fFan1 = Gia_SatValFan1(vRes, i); Gia_Obj_t * pFans[2] = { Gia_ObjFanin0(pObj), Gia_ObjFanin1(pObj) }; Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, fComp), Vec_IntSize(vMapping) ); if ( fFan0 && fFan1 ) { assert( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ); Vec_IntPush( vMapping, 4 ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC0(pFans[0]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pFans[0]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC0(pFans[1]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC1(pFans[1]))) ); Vec_IntPush( vMapping, fComp ? GIA_GATE_OAI22 : GIA_GATE_AOI22 ); } else if ( fFan0 ) { Vec_IntPush( vMapping, 3 ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC0(pFans[0]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pFans[0]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pObj), !(fComp ^ Gia_ObjFaninC1(pObj))) ); if ( Gia_ObjFaninC0(pObj) ) Vec_IntPush( vMapping, fComp ? GIA_GATE_OAI21 : GIA_GATE_AOI21 ); else Vec_IntPush( vMapping, fComp ? GIA_GATE_NAN3 : GIA_GATE_NOR3 ); } else if ( fFan1 ) { Vec_IntPush( vMapping, 3 ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC0(pFans[1]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC1(pFans[1]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pObj), !(fComp ^ Gia_ObjFaninC0(pObj))) ); if ( Gia_ObjFaninC1(pObj) ) Vec_IntPush( vMapping, fComp ? GIA_GATE_OAI21 : GIA_GATE_AOI21 ); else Vec_IntPush( vMapping, fComp ? GIA_GATE_NAN3 : GIA_GATE_NOR3 ); } else { Vec_IntPush( vMapping, 2 ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pObj), !(fComp ^ Gia_ObjFaninC0(pObj))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pObj), !(fComp ^ Gia_ObjFaninC1(pObj))) ); Vec_IntPush( vMapping, fComp ? GIA_GATE_NAN2 : GIA_GATE_NOR2 ); } } return vMapping; } void Gia_ManSimplePrintMapping( Vec_Int_t * vRes, int nIns ) { int i, k, nObjs = Vec_IntSize(vRes)/7, nSteps = Abc_Base10Log(nObjs); int nCard = Vec_IntSum(vRes) - nIns; char NumStr[10]; printf( "Solution with cardinality %d:\n", nCard ); for ( k = 0; k < nSteps; k++ ) { printf( " " ); for ( i = 0; i < nObjs; i++ ) { sprintf( NumStr, "%02d", i ); printf( "%c", NumStr[k] ); } printf( "\n" ); } for ( k = 0; k < 7; k++ ) { printf( "%c ", "pnPNi01"[k] ); for ( i = 0; i < nObjs; i++ ) if ( Vec_IntEntry( vRes, i*7+k ) == 0 ) printf( " " ); else printf( "1" ); printf( "\n" ); } } int Gia_ManDumpCnf( char * pFileName, Vec_Str_t * vStr, int nVars ) { FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open input file \"%s\".\n", pFileName ); return 0; } fprintf( pFile, "p knf %d %d\n%s\n", nVars, Vec_StrCountEntry(vStr, '\n'), Vec_StrArray(vStr) ); fclose( pFile ); return 1; } int Gia_ManDumpCnf2( Vec_Str_t * vStr, int nVars, int argc, char ** argv, abctime Time, int Status ) { Vec_Str_t * vFileName = Vec_StrAlloc( 100 ); int c; Vec_StrPrintF( vFileName, "%s", argv[0] + (argv[0][0] == '&') ); for ( c = 1; c < argc; c++ ) Vec_StrPrintF( vFileName, "_%s", argv[c] + (argv[c][0] == '-') ); Vec_StrPrintF( vFileName, ".cnf" ); Vec_StrPush( vFileName, '\0' ); FILE * pFile = fopen( Vec_StrArray(vFileName), "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", Vec_StrArray(vFileName) ); Vec_StrFree(vFileName); return 0; } Vec_StrFree(vFileName); fprintf( pFile, "c This file was generated by ABC command: \"" ); fprintf( pFile, "%s", argv[0] ); for ( c = 1; c < argc; c++ ) fprintf( pFile, " %s", argv[c] ); fprintf( pFile, "\" on %s\n", Gia_TimeStamp() ); fprintf( pFile, "c Cardinality CDCL (https://github.com/jreeves3/Cardinality-CDCL) found it to be " ); if ( Status == 1 ) fprintf( pFile, "UNSAT" ); if ( Status == 0 ) fprintf( pFile, "SAT" ); if ( Status == -1 ) fprintf( pFile, "UNDECIDED" ); fprintf( pFile, " in %.2f sec\n", 1.0*((double)(Time))/((double)CLOCKS_PER_SEC) ); fprintf( pFile, "p knf %d %d\n%s\n", nVars, Vec_StrCountEntry(vStr, '\n'), Vec_StrArray(vStr) ); fclose( pFile ); return 1; } int Gia_ManSimpleMapping( Gia_Man_t * p, int nBound, int Seed, int nBTLimit, int nTimeout, int fVerbose, int fKeepFile, int argc, char ** argv ) { abctime clkStart = Abc_Clock(); srand(time(NULL)); int Status, Rand = ((((unsigned)rand()) << 12) ^ ((unsigned)rand())) & 0xFFFFFF; char pFileNameI[32]; sprintf( pFileNameI, "_%06x_.cnf", Rand ); char pFileNameO[32]; sprintf( pFileNameO, "_%06x_.out", Rand ); if ( nBound == 0 ) nBound = 5 * Gia_ManAndNum(p); Vec_Str_t * vStr = Gia_ManSimpleCnf( p, nBound/2 ); int nVars = 7*(Gia_ManObjNum(p)-Gia_ManCoNum(p)); if ( !Gia_ManDumpCnf(pFileNameI, vStr, nVars) ) { Vec_StrFree( vStr ); return 0; } if ( fVerbose ) printf( "SAT variables = %d. SAT clauses = %d. Cardinality bound = %d. Conflict limit = %d. Timeout = %d.\n", nVars, Vec_StrCountEntry(vStr, '\n'), nBound, nBTLimit, nTimeout ); Vec_Int_t * vRes = Gia_RunKadical( pFileNameI, pFileNameO, Seed, nBTLimit, nTimeout, fVerbose, &Status ); unlink( pFileNameI ); //unlink( pFileNameO ); if ( fKeepFile ) Gia_ManDumpCnf2( vStr, nVars, argc, argv, Abc_Clock() - clkStart, Status ); Vec_StrFree( vStr ); if ( vRes == NULL ) return 0; Vec_IntFreeP( &p->vCellMapping ); assert( p->vCellMapping == NULL ); Vec_IntDrop( vRes, 0 ); if ( fVerbose ) Gia_ManSimplePrintMapping( vRes, Gia_ManCiNum(p) ); p->vCellMapping = Gia_ManDeriveSimpleMapping( p, vRes ); Vec_IntFree( vRes ); if ( fVerbose ) Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ #define KSAT_OBJS 24 #define KSAT_MINTS 64 #define KSAT_SPACE (4+3*KSAT_OBJS+3*KSAT_MINTS) int Gia_KSatVarInv( int * pMap, int i ) { return pMap[i*KSAT_SPACE+0]; } int Gia_KSatVarAnd( int * pMap, int i ) { return pMap[i*KSAT_SPACE+1]; } int Gia_KSatVarEqu( int * pMap, int i ) { return pMap[i*KSAT_SPACE+2]; } int Gia_KSatVarRef( int * pMap, int i ) { return pMap[i*KSAT_SPACE+3]; } int Gia_KSatVarFan( int * pMap, int i, int f, int k ) { return pMap[i*KSAT_SPACE+4+f*KSAT_OBJS+k]; } int Gia_KSatVarMin( int * pMap, int i, int m, int k ) { return pMap[i*KSAT_SPACE+4+3*KSAT_OBJS+3*m+k]; } void Gia_KSatSetInv( int * pMap, int i, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+0] ); pMap[i*KSAT_SPACE+0] = iVar; } void Gia_KSatSetAnd( int * pMap, int i, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+1] ); pMap[i*KSAT_SPACE+1] = iVar; } void Gia_KSatSetEqu( int * pMap, int i, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+2] ); pMap[i*KSAT_SPACE+2] = iVar; } void Gia_KSatSetRef( int * pMap, int i, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+3] ); pMap[i*KSAT_SPACE+3] = iVar; } void Gia_KSatSetFan( int * pMap, int i, int f, int k, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+4+f*KSAT_OBJS+k] ); pMap[i*KSAT_SPACE+4+f*KSAT_OBJS+k] = iVar; } void Gia_KSatSetMin( int * pMap, int i, int m, int k, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+4+3*KSAT_OBJS+3*m+k] ); pMap[i*KSAT_SPACE+4+3*KSAT_OBJS+3*m+k] = iVar; } int Gia_KSatValInv( int * pMap, int i, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+0] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+0] ); } int Gia_KSatValAnd( int * pMap, int i, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+1] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+1] ); } int Gia_KSatValEqu( int * pMap, int i, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+2] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+2] ); } int Gia_KSatValRef( int * pMap, int i, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+3] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+3] ); } int Gia_KSatValFan( int * pMap, int i, int f, int k, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+4+f*KSAT_OBJS+k] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+4+f*KSAT_OBJS+k] ); } int Gia_KSatValMin( int * pMap, int i, int m, int k, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+4+3*KSAT_OBJS+3*m+k] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+4+3*KSAT_OBJS+3*m+k] ); } int * Gia_KSatMapInit( int nIns, int nNodes, word Truth, int * pnVars ) { assert( nIns + nNodes <= KSAT_OBJS ); assert( (1 << nIns) <= KSAT_MINTS ); int n, m, f, k, nVars = 2, * pMap = ABC_FALLOC( int, KSAT_OBJS*KSAT_SPACE ); for ( n = nIns; n < nIns+nNodes; n++ ) { Gia_KSatSetInv(pMap, n, nVars++); Gia_KSatSetAnd(pMap, n, nVars++); Gia_KSatSetEqu(pMap, n, nVars++); Gia_KSatSetRef(pMap, n, nVars++); } for ( n = nIns; n < nIns+nNodes; n++ ) { for ( f = 0; f < 2; f++ ) for ( k = 0; k < n; k++ ) Gia_KSatSetFan(pMap, n, f, k, nVars++); for ( k = n+1; k < nIns+nNodes; k++ ) Gia_KSatSetFan(pMap, n, 2, k, nVars++); } for ( m = 0; m < (1<> n) & 1 ); Gia_KSatSetMin(pMap, nIns+nNodes-1, m, 0, (Truth >> m) & 1 ); for ( n = nIns; n < nIns+nNodes; n++ ) for ( k = 0; k < 3; k++ ) if ( k || n < nIns+nNodes-1 ) Gia_KSatSetMin(pMap, n, m, k, nVars++); } if ( pnVars ) *pnVars = nVars; return pMap; } int Gia_KSatFindFan( int * pMap, int i, int f, Vec_Int_t * vRes ) { assert( f < 2 ); for ( int k = 0; k < i; k++ ) if ( Gia_KSatValFan( pMap, i, f, k, vRes ) ) return k; assert( 0 ); return -1; } Vec_Int_t * Gia_ManKSatGenLevels( char * pGuide, int nIns, int nNodes ) { Vec_Int_t * vRes; int i, k, Count = 0; for ( i = 0; pGuide[i]; i++ ) Count += pGuide[i] - '0'; if ( Count != nNodes ) { printf( "Guidance %s has %d nodes while the problem has %d nodes.\n", pGuide, Count, nNodes ); return NULL; } int FirstPrev = 0; int FirstThis = nIns; int FirstNext = FirstThis; vRes = Vec_IntStartFull( 2*nIns ); for ( i = 0; pGuide[i]; i++ ) { FirstNext += pGuide[i] - '0'; for ( k = FirstThis; k < FirstNext; k++ ) Vec_IntPushTwo( vRes, FirstPrev, FirstThis ); FirstPrev = FirstThis; FirstThis = FirstNext; } assert( Vec_IntSize(vRes) == 2*(nIns + nNodes) ); Count = 0; //int Start, Stop; //Vec_IntForEachEntryDouble(vRes, Start, Stop, i) // printf( "%2d : Start %2d Stop %2d\n", Count++, Start, Stop ); return vRes; } Vec_Str_t * Gia_ManKSatCnf( int * pMap, int nIns, int nNodes, int nBound, int fMultiLevel, char * pGuide ) { Vec_Str_t * vStr = Vec_StrAlloc( 10000 ); Vec_Int_t * vRes = pGuide ? Gia_ManKSatGenLevels( pGuide, nIns, nNodes ) : NULL; int i, j, m, n, f, c, a, Start, Stop, nLits = 0, pLits[256] = {0}; Gia_SatDumpLiteral( vStr, 1 ); Gia_SatDumpLiteral( vStr, 2 ); if ( vRes ) { n = nIns; Vec_IntForEachEntryDoubleStart( vRes, Start, Stop, i, 2*nIns ) { for ( j = 0; j < Start; j++ ) Gia_SatDumpLiteral( vStr, Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 1, j), 1 ) ); for ( f = 0; f < 2; f++ ) for ( j = Stop; j < n; j++ ) Gia_SatDumpLiteral( vStr, Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, j), 1 ) ); n++; } assert( n == nIns + nNodes ); } // fanins are connected once for ( n = nIns; n < nIns+nNodes; n++ ) for ( f = 0; f < 2; f++ ) { nLits = 0; for ( i = 0; i < n; i++ ) pLits[nLits++] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 0 ); Gia_SatDumpClause( vStr, pLits, nLits ); /* for ( i = 0; i < n; i++ ) for ( j = 0; j < i; j++ ) { pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 1 ); pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, j), 1 ); Gia_SatDumpClause( vStr, pLits, 2 ); } */ Vec_StrPrintF( vStr, "k %d ", n-1 ); for ( i = 0; i < n; i++ ) pLits[i] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 1 ); Gia_SatDumpClause( vStr, pLits, n ); } for ( n = nIns; n < nIns+nNodes; n++ ) { // fanins are equal for ( i = 0; i < n; i++ ) { pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 0, i), 1 ); pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 1, i), 1 ); pLits[2] = Abc_Var2Lit( Gia_KSatVarEqu(pMap, n), 0 ); Gia_SatDumpClause( vStr, pLits, 3 ); } for ( i = 0; i < n; i++ ) for ( j = i+1; j < n; j++ ) { pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 0, i), 1 ); pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 1, j), 1 ); pLits[2] = Abc_Var2Lit( Gia_KSatVarEqu(pMap, n), 1 ); Gia_SatDumpClause( vStr, pLits, 3 ); } // if fanins are equal, inv is used pLits[0] = Abc_Var2Lit( Gia_KSatVarEqu(pMap, n), 1 ); pLits[1] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), 0 ); Gia_SatDumpClause( vStr, pLits, 2 ); // fanin ordering for ( i = 0; i < n; i++ ) for ( j = 0; j < i; j++ ) { pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 0, i), 1 ); pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 1, j), 1 ); Gia_SatDumpClause( vStr, pLits, 2 ); } } for ( n = nIns; n < nIns+nNodes-1; n++ ) { // there is a fanout to the node above for ( i = n+1; i < nIns+nNodes; i++ ) { for ( f = 0; f < 2; f++ ) { pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, i, f, n), 1 ); pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 2, i), 0 ); Gia_SatDumpClause( vStr, pLits, 2 ); } pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, i, 0, n), 0 ); pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, i, 1, n), 0 ); pLits[2] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 2, i), 1 ); Gia_SatDumpClause( vStr, pLits, 3 ); } // there is at least one fanout, except the last one nLits = 0; for ( i = n+1; i < nIns+nNodes; i++ ) pLits[nLits++] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 2, i), 0 ); assert( nLits > 0 ); Gia_SatDumpClause( vStr, pLits, nLits ); } // there is more than one fanout, except the last one for ( n = nIns; n < nIns+nNodes-1; n++ ) { for ( i = n+1; i < nIns+nNodes; i++ ) for ( j = i+1; j < nIns+nNodes; j++ ) { pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 2, i), 1 ); pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 2, j), 1 ); pLits[2] = Abc_Var2Lit( Gia_KSatVarRef(pMap, n), 0 ); Gia_SatDumpClause( vStr, pLits, 3 ); } // if more than one fanout, inv is used pLits[0] = Abc_Var2Lit( Gia_KSatVarRef(pMap, n), 1 ); pLits[1] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), 0 ); Gia_SatDumpClause( vStr, pLits, 2 ); // if inv is not used, its fanins' invs are used if ( !fMultiLevel ) { pLits[0] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), 0 ); for ( i = nIns; i < n; i++ ) for ( f = 0; f < 2; f++ ) { pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 1 ); pLits[2] = Abc_Var2Lit( Gia_KSatVarInv(pMap, i), 0 ); Gia_SatDumpClause( vStr, pLits, 3 ); } } } // the last one always uses inverter Gia_SatDumpLiteral( vStr, Abc_Var2Lit( Gia_KSatVarInv(pMap, nIns+nNodes-1), 0 ) ); /* // for each minterm, for each pair of possible fanins, the node's output is determined using and/or and inv (4*N*N*M) for ( m = 0; m < (1 << nIns); m++ ) for ( n = nIns; n < nIns+nNodes; n++ ) for ( c = 0; c < 2; c++ ) for ( a = 0; a < 2; a++ ) { // implications: Fan(f) & Mint(m) & !And & !Inv -> Val1 for ( f = 0; f < 2; f++ ) for ( i = 0; i < n; i++ ) { pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 1 ); pLits[1] = Abc_Var2Lit( Gia_KSatVarMin(pMap, i, m, 0), !a ); pLits[2] = Abc_Var2Lit( Gia_KSatVarAnd(pMap, n), a ); pLits[3] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), c ); pLits[4] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 0), a^c ); Gia_SatDumpClause( vStr, pLits, 5 ); } // large clauses: Fan(0) & Fan(1) & !Mint(m) & !Mint(m) & !And & !Inv -> Val0 for ( i = 0; i < n; i++ ) for ( j = i; j < n; j++ ) { pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 0, i), 1 ); pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 1, j), 1 ); pLits[2] = Abc_Var2Lit( Gia_KSatVarMin(pMap, i, m, 0), a ); pLits[3] = Abc_Var2Lit( Gia_KSatVarMin(pMap, j, m, 0), a ); pLits[4] = Abc_Var2Lit( Gia_KSatVarAnd(pMap, n), a ); pLits[5] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), c ); pLits[6] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 0), a==c ); Gia_SatDumpClause( vStr, pLits, 7 ); } } */ // for each minterm, define a fanin variable and use it to get the node's output based on and/or and inv (4*N*N*M) for ( m = 0; m < (1 << nIns); m++ ) for ( n = nIns; n < nIns+nNodes; n++ ) { for ( i = 0; i < n; i++ ) for ( f = 0; f < 2; f++ ) for ( c = 0; c < 2; c++ ) { pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 1 ); pLits[1] = Abc_Var2Lit( Gia_KSatVarMin(pMap, i, m, 0), c ); pLits[2] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 1+f), !c ); Gia_SatDumpClause( vStr, pLits, 3 ); } for ( c = 0; c < 2; c++ ) for ( a = 0; a < 2; a++ ) { // implications: Mint(m,f) & !And & !Inv -> Val1 for ( f = 0; f < 2; f++ ) { pLits[0] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 1+f), !a ); pLits[1] = Abc_Var2Lit( Gia_KSatVarAnd(pMap, n), a ); pLits[2] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), c ); pLits[3] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 0), a^c ); Gia_SatDumpClause( vStr, pLits, 4 ); } // large clauses: !Mint(m,0) & !Mint(m,1) & !And & !Inv -> Val0 pLits[0] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 1), a ); pLits[1] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 2), a ); pLits[2] = Abc_Var2Lit( Gia_KSatVarAnd(pMap, n), a ); pLits[3] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), c ); pLits[4] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 0), a==c ); Gia_SatDumpClause( vStr, pLits, 5 ); } } // the number of nodes with duplicated fanins and without inv is maximized if ( nBound && 2*nNodes > nBound ) { Vec_StrPrintF( vStr, "k %d ", 2*nNodes-nBound ); nLits = 0; for ( n = nIns; n < nIns+nNodes; n++ ) { pLits[nLits++] = Abc_Var2Lit(Gia_KSatVarEqu(pMap, n), 0); pLits[nLits++] = Abc_Var2Lit(Gia_KSatVarInv(pMap, n), 1); } Gia_SatDumpClause( vStr, pLits, nLits ); } Vec_StrPush( vStr, '\0' ); Vec_IntFreeP( &vRes ); return vStr; } typedef enum { GIA_GATE2_ZERO, // 0: GIA_GATE2_ONE, // 1: GIA_GATE2_BUF, // 2: GIA_GATE2_INV, // 3: GIA_GATE2_NAN2, // 4: GIA_GATE2_NOR2, // 5: GIA_GATE2_AOI21, // 6: GIA_GATE2_NAN3, // 7: GIA_GATE2_NOR3, // 8: GIA_GATE2_OAI21, // 9: GIA_GATE2_NOR4, // 10: GIA_GATE2_AOI211, // 11: GIA_GATE2_AOI22, // 12: GIA_GATE2_NAN4, // 13: GIA_GATE2_OAI211, // 14: GIA_GATE2_OAI22, // 15: GIA_GATE2_VOID // 16: unused value } Gia_ManGate2_t; Vec_Int_t * Gia_ManDeriveKSatMappingArray( Gia_Man_t * p, Vec_Int_t * vRes ) { Vec_Int_t * vMapping = Vec_IntStart( 2*Gia_ManObjNum(p) ); int i, Id; Gia_Obj_t * pObj; Gia_ManForEachCiId( p, Id, i ) if ( Vec_IntEntry(vRes, Id) ) Vec_IntWriteEntry( vMapping, Abc_Var2Lit(Id, 1), -1 ); Gia_ManForEachAnd( p, pObj, i ) { assert( Vec_IntEntry(vRes, i) > 0 ); if ( (Vec_IntEntry(vRes, i) & 2) == 0 ) { assert( (Vec_IntEntry(vRes, i) & 1) == 0 ); continue; } Gia_Obj_t * pFans[2] = { Gia_ObjFanin0(pObj), Gia_ObjFanin1(pObj) }; int fComp = ((Vec_IntEntry(vRes, i) >> 2) & 1) != 0; int fFan0 = ((Vec_IntEntry(vRes, Gia_ObjFaninId0(pObj, i)) >> 1) & 1) == 0 && Gia_ObjIsAnd(pFans[0]); int fFan1 = ((Vec_IntEntry(vRes, Gia_ObjFaninId1(pObj, i)) >> 1) & 1) == 0 && Gia_ObjIsAnd(pFans[1]); if ( Vec_IntEntry(vRes, i) & 1 ) Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, !fComp), -1 ); Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, fComp), Vec_IntSize(vMapping) ); if ( fFan0 && fFan1 ) { Vec_IntPush( vMapping, 4 ); if ( !Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) { Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC0(pFans[1]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC1(pFans[1]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC0(pFans[0]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pFans[0]))) ); } else { Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC0(pFans[0]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pFans[0]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC0(pFans[1]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC1(pFans[1]))) ); } if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) Vec_IntPush( vMapping, fComp ? GIA_GATE2_OAI22 : GIA_GATE2_AOI22 ); else if ( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ) Vec_IntPush( vMapping, fComp ? GIA_GATE2_NAN4 : GIA_GATE2_NOR4 ); else Vec_IntPush( vMapping, fComp ? GIA_GATE2_OAI211 : GIA_GATE2_AOI211 ); } else if ( fFan0 ) { Vec_IntPush( vMapping, 3 ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC0(pFans[0]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pFans[0]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pObj), !(fComp ^ Gia_ObjFaninC1(pObj))) ); if ( Gia_ObjFaninC0(pObj) ) Vec_IntPush( vMapping, fComp ? GIA_GATE2_OAI21 : GIA_GATE2_AOI21 ); else Vec_IntPush( vMapping, fComp ? GIA_GATE2_NAN3 : GIA_GATE2_NOR3 ); } else if ( fFan1 ) { Vec_IntPush( vMapping, 3 ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC0(pFans[1]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC1(pFans[1]))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pObj), !(fComp ^ Gia_ObjFaninC0(pObj))) ); if ( Gia_ObjFaninC1(pObj) ) Vec_IntPush( vMapping, fComp ? GIA_GATE2_OAI21 : GIA_GATE2_AOI21 ); else Vec_IntPush( vMapping, fComp ? GIA_GATE2_NAN3 : GIA_GATE2_NOR3 ); } else { Vec_IntPush( vMapping, 2 ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pObj), !(fComp ^ Gia_ObjFaninC0(pObj))) ); Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pObj), !(fComp ^ Gia_ObjFaninC1(pObj))) ); Vec_IntPush( vMapping, fComp ? GIA_GATE2_NAN2 : GIA_GATE2_NOR2 ); } } return vMapping; } Gia_Man_t * Gia_ManDeriveKSatMapping( Vec_Int_t * vRes, int * pMap, int nIns, int nNodes, int fVerbose ) { Vec_Int_t * vGuide = Vec_IntStart( 1000 ); Gia_Man_t * pNew = Gia_ManStart( nIns + nNodes + 2 ); pNew->pName = Abc_UtilStrsav( "test" ); int i, nSave = 0, pCopy[256] = {0}; for ( i = 1; i <= nIns; i++ ) pCopy[i] = Gia_ManAppendCi( pNew ); for ( i = nIns; i < nIns+nNodes; i++ ) { int iFan0 = Gia_KSatFindFan( pMap, i, 0, vRes ); int iFan1 = Gia_KSatFindFan( pMap, i, 1, vRes ); if ( iFan0 == iFan1 ) pCopy[i+1] = pCopy[iFan0+1]; else if ( Gia_KSatValAnd(pMap, i, vRes) ) pCopy[i+1] = Gia_ManAppendAnd( pNew, pCopy[iFan0+1], pCopy[iFan1+1] ); else pCopy[i+1] = Gia_ManAppendOr( pNew, pCopy[iFan0+1], pCopy[iFan1+1] ); pCopy[i+1] = Abc_LitNotCond( pCopy[i+1], Gia_KSatValInv(pMap, i, vRes) ); if ( iFan0 == iFan1 ) *Vec_IntEntryP(vGuide, Abc_Lit2Var(pCopy[i+1])) ^= 1; else if ( Gia_KSatValAnd(pMap, i, vRes) ) *Vec_IntEntryP(vGuide, Abc_Lit2Var(pCopy[i+1])) ^= 4 | (2*Gia_KSatValInv(pMap, i, vRes)); else *Vec_IntEntryP(vGuide, Abc_Lit2Var(pCopy[i+1])) ^= 8 | (2*Gia_KSatValInv(pMap, i, vRes)); if ( fVerbose ) { if ( i == nIns+nNodes-1 ) printf( " F = " ); else printf( "%2d = ", i ); if ( iFan0 == iFan1 ) printf( "INV( %d )\n", iFan0 ); else if ( Gia_KSatValAnd(pMap, i, vRes) ) printf( "%sAND( %d, %d )\n", Gia_KSatValInv(pMap, i, vRes) ? "N":"", iFan0, iFan1 ); else printf( "%sOR( %d, %d )\n", Gia_KSatValInv(pMap, i, vRes) ? "N":"", iFan0, iFan1 ); nSave += (iFan0 == iFan1) || !Gia_KSatValInv(pMap, i, vRes); if ( i == nIns+nNodes-1 ) printf( "Solution cost = %d\n", 2*(2*nNodes - nSave) ); } } Gia_ManAppendCo( pNew, pCopy[nIns+nNodes] ); //pNew->vCellMapping = Gia_ManDeriveKSatMappingArray( pNew, vGuide ); Vec_IntFree( vGuide ); return pNew; } word Gia_ManGetTruth( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, Id; word pFuncs[256] = {0}, Const[2] = {0, ~(word)0}; assert( Gia_ManObjNum(p) <= 256 ); Gia_ManForEachCiId( p, Id, i ) pFuncs[Id] = s_Truths6[i]; Gia_ManForEachAnd( p, pObj, i ) pFuncs[i] = (Const[Gia_ObjFaninC0(pObj)] ^ pFuncs[Gia_ObjFaninId0(pObj, i)]) & (Const[Gia_ObjFaninC1(pObj)] ^ pFuncs[Gia_ObjFaninId1(pObj, i)]); pObj = Gia_ManCo(p, 0); return Const[Gia_ObjFaninC0(pObj)] ^ pFuncs[Gia_ObjFaninId0p(p, pObj)]; } Gia_Man_t * Gia_ManKSatMapping( word Truth, int nIns, int nNodes, int nBound, int Seed, int fMultiLevel, int nBTLimit, int nTimeout, int fVerbose, int fKeepFile, int argc, char ** argv, char * pGuide ) { abctime clkStart = Abc_Clock(); Gia_Man_t * pNew = NULL; srand(time(NULL)); int Status, Rand = ((((unsigned)rand()) << 12) ^ ((unsigned)rand())) & 0xFFFFFF; char pFileNameI[32]; sprintf( pFileNameI, "_%06x_.cnf", Rand ); char pFileNameO[32]; sprintf( pFileNameO, "_%06x_.out", Rand ); int nVars = 0, * pMap = Gia_KSatMapInit( nIns, nNodes, Truth, &nVars ); Vec_Str_t * vStr = Gia_ManKSatCnf( pMap, nIns, nNodes, nBound/2, fMultiLevel, pGuide ); if ( !Gia_ManDumpCnf(pFileNameI, vStr, nVars) ) { Vec_StrFree( vStr ); return NULL; } if ( fVerbose ) printf( "Vars = %d. Nodes = %d. Cardinality bound = %d. SAT vars = %d. SAT clauses = %d. Conflict limit = %d. Timeout = %d.\n", nIns, nNodes, nBound, nVars, Vec_StrCountEntry(vStr, '\n'), nBTLimit, nTimeout ); Vec_Int_t * vRes = Gia_RunKadical( pFileNameI, pFileNameO, Seed, nBTLimit, nTimeout, 1, &Status ); unlink( pFileNameI ); //unlink( pFileNameO ); if ( fKeepFile ) Gia_ManDumpCnf2( vStr, nVars, argc, argv, Abc_Clock() - clkStart, Status ); Vec_StrFree( vStr ); if ( vRes == NULL ) return 0; Vec_IntDrop( vRes, 0 ); pNew = Gia_ManDeriveKSatMapping( vRes, pMap, nIns, nNodes, fVerbose ); printf( "Verification %s. ", Truth == Gia_ManGetTruth(pNew) ? "passed" : "failed" ); Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart ); Vec_IntFree( vRes ); ABC_FREE( pMap ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSatMap.c000066400000000000000000000561751477524141600163170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaSatMap.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: giaSatMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "sat/bsat/satStore.h" #include "misc/vec/vecWec.h" #include "misc/util/utilNam.h" #include "map/scl/sclCon.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // operation manager typedef struct Sbm_Man_t_ Sbm_Man_t; struct Sbm_Man_t_ { sat_solver * pSat; // SAT solver Vec_Int_t * vCardVars; // candinality variables int LogN; // max vars int FirstVar; // first variable to be used int LitShift; // shift in terms of literals (2*Gia_ManCiNum(pGia)+2) int nInputs; // the number of inputs // window Vec_Int_t * vRoots; // output drivers to be mapped (root -> lit) Vec_Wec_t * vCuts; // cuts (cut -> node lit + fanin lits) Vec_Wec_t * vObjCuts; // cuts (obj -> node lit + cut lits) Vec_Int_t * vSolCuts; // current solution (index -> cut) Vec_Int_t * vCutGates; // gates (cut -> gate) Vec_Wrd_t * vCutAreas; // area of each cut // solver Vec_Int_t * vAssump; // assumptions (root nodes) Vec_Int_t * vPolar; // polarity of nodes and cuts // timing Vec_Int_t * vArrs; // arrivals for the inputs (input -> time) Vec_Int_t * vReqs; // required for the outputs (root -> time) // internal Vec_Int_t * vLit2Used; // current solution (lit -> used) Vec_Int_t * vDelays; // node arrivals (lit -> time) Vec_Int_t * vReason; // timing reasons (lit -> cut) }; /* Cuts in p->vCuts have 0-based numbers and are expressed in terms of object literals. Cuts in p->vObjCuts are expressed in terms of the obj-lit + cut-lits (i + p->FirstVar) Unit cuts for each polarity are ordered in the end. */ //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Verify solution. Create polarity and assumptions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sbm_ManCheckSol( Sbm_Man_t * p, Vec_Int_t * vSol ) { //int K = Vec_IntSize(vSol) - 1; int i, j, Lit, Cut; int RetValue = 1; Vec_Int_t * vCut; // clear polarity and assumptions Vec_IntClear( p->vPolar ); // mark used literals Vec_IntFill( p->vLit2Used, Vec_WecSize(p->vObjCuts) + p->nInputs, 0 ); Vec_IntForEachEntry( p->vSolCuts, Cut, i ) { if ( Cut < 0 ) // input inverter variable { Vec_IntWriteEntry( p->vLit2Used, -Cut, 1 ); Vec_IntPush( p->vPolar, -Cut ); continue; } Vec_IntPush( p->vPolar, p->FirstVar + Cut ); vCut = Vec_WecEntry( p->vCuts, Cut ); Lit = Vec_IntEntry( vCut, 0 ) - p->LitShift; // obj literal if ( Vec_IntEntry(p->vLit2Used, Lit) ) continue; Vec_IntWriteEntry( p->vLit2Used, Lit, 1 ); Vec_IntPush( p->vPolar, Lit ); // literal variable } // check that the output literals are used Vec_IntForEachEntry( p->vRoots, Lit, i ) { if ( Vec_IntEntry(p->vLit2Used, Lit) == 0 ) printf( "Output literal %d has no cut.\n", Lit ), RetValue = 0; } // check internal nodes Vec_IntForEachEntry( p->vSolCuts, Cut, i ) { if ( Cut < 0 ) continue; vCut = Vec_WecEntry( p->vCuts, Cut ); Vec_IntForEachEntryStart( vCut, Lit, j, 1 ) if ( Lit - p->LitShift < 0 ) { assert( Abc_LitIsCompl(Lit) ); if ( Vec_IntEntry(p->vLit2Used, Vec_WecSize(p->vObjCuts) + Abc_Lit2Var(Lit)-1) == 0 ) printf( "Inverter of input %d of cut %d is not mapped.\n", Abc_Lit2Var(Lit)-1, Cut ), RetValue = 0; } else if ( Vec_IntEntry(p->vLit2Used, Lit - p->LitShift) == 0 ) printf( "Internal literal %d of cut %d is not mapped.\n", Lit - p->LitShift, Cut ), RetValue = 0; // create polarity Vec_IntPush( p->vPolar, p->FirstVar + Cut ); // cut variable } return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Sbm_ManCreateCnf( Sbm_Man_t * p ) { int i, k, Lit, Lits[2], value; Vec_Int_t * vLits, * vCutOne, * vLitsPrev; // sat_solver_rollback( p->Sat ); if ( !Sbm_ManCheckSol(p, p->vSolCuts) ) return 0; // increase var count assert( p->FirstVar == sat_solver_nvars(p->pSat) ); sat_solver_setnvars( p->pSat, sat_solver_nvars(p->pSat) + Vec_WecSize(p->vCuts) ); // iterate over arrays containing obj-lit cuts (neg-obj-lit cut-lits followed by pos-obj-lit cut-lits) vLitsPrev = NULL; Vec_WecForEachLevel( p->vObjCuts, vLits, i ) { assert( Vec_IntSize(vLits) >= 2 ); value = sat_solver_addclause( p->pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits) ); assert( value ); /* // for each cut, add implied nodes Lits[0] = Abc_LitNot( Vec_IntEntry(vLits, 0) ); assert( Lits[0] < 2*p->FirstVar ); Vec_IntForEachEntryStart( vLits, Lit, k, 1 ) { assert( Lit >= 2*p->FirstVar ); Lits[1] = Abc_LitNot( Lit ); value = sat_solver_addclause( p->pSat, Lits, Lits + 2 ); assert( value ); //printf( "Adding clause %d + %d.\n", Lits[0], Lits[1]-2*p->FirstVar ); } */ //printf( "\n" ); // create invertor exclusivity clause if ( i & 1 ) { Lits[0] = Abc_LitNot( Vec_IntEntryLast(vLits) ); Lits[1] = Abc_LitNot( Vec_IntEntryLast(vLitsPrev) ); value = sat_solver_addclause( p->pSat, Lits, Lits + 2 ); assert( value ); //printf( "Adding exclusivity clause %d + %d.\n", Lits[0]-2*p->FirstVar, Lits[1]-2*p->FirstVar ); } vLitsPrev = vLits; } // add inverters Vec_WecForEachLevel( p->vCuts, vCutOne, i ) Vec_IntForEachEntry( vCutOne, Lit, k ) if ( Abc_Lit2Var(Lit)-1 < p->nInputs ) // input { assert( k > 0 ); Lits[0] = Abc_Var2Lit( Vec_WecSize(p->vObjCuts) + Abc_Lit2Var(Lit)-1, 0 ); Lits[1] = Abc_Var2Lit( p->FirstVar + i, 1 ); value = sat_solver_addclause( p->pSat, Lits, Lits + 2 ); assert( value ); } else // internal node { Lits[0] = Abc_Var2Lit( Lit-p->LitShift, 0 ); Lits[1] = Abc_Var2Lit( p->FirstVar + i, 1 ); value = sat_solver_addclause( p->pSat, Lits, Lits + 2 ); assert( value ); } sat_solver_set_polarity( p->pSat, Vec_IntArray(p->vPolar), Vec_IntSize(p->vPolar) ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int sat_solver_add_and1( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1, int fCompl ) { lit Lits[3]; int Cid; Lits[0] = toLitCond( iVar, !fCompl ); Lits[1] = toLitCond( iVar0, fCompl0 ); Cid = sat_solver_addclause( pSat, Lits, Lits + 2 ); assert( Cid ); Lits[0] = toLitCond( iVar, !fCompl ); Lits[1] = toLitCond( iVar1, fCompl1 ); Cid = sat_solver_addclause( pSat, Lits, Lits + 2 ); assert( Cid ); /* Lits[0] = toLitCond( iVar, fCompl ); Lits[1] = toLitCond( iVar0, !fCompl0 ); Lits[2] = toLitCond( iVar1, !fCompl1 ); Cid = sat_solver_addclause( pSat, Lits, Lits + 3 ); assert( Cid ); */ return 3; } static inline int sat_solver_add_and2( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1, int fCompl ) { lit Lits[3]; int Cid; /* Lits[0] = toLitCond( iVar, !fCompl ); Lits[1] = toLitCond( iVar0, fCompl0 ); Cid = sat_solver_addclause( pSat, Lits, Lits + 2 ); assert( Cid ); Lits[0] = toLitCond( iVar, !fCompl ); Lits[1] = toLitCond( iVar1, fCompl1 ); Cid = sat_solver_addclause( pSat, Lits, Lits + 2 ); assert( Cid ); */ Lits[0] = toLitCond( iVar, fCompl ); Lits[1] = toLitCond( iVar0, !fCompl0 ); Lits[2] = toLitCond( iVar1, !fCompl1 ); Cid = sat_solver_addclause( pSat, Lits, Lits + 3 ); assert( Cid ); 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Sbm_AddSorter( sat_solver * p, int * pVars, int i, int k, int * pnVars ) { int iVar1 = (*pnVars)++; int iVar2 = (*pnVars)++; int fVerbose = 0; if ( fVerbose ) { int v; for ( v = 0; v < i; v++ ) printf( " " ); printf( "<" ); for ( v = i+1; v < k; v++ ) printf( "-" ); printf( ">" ); for ( v = k+1; v < 8; v++ ) printf( " " ); printf( " " ); printf( "[%3d :%3d ] -> [%3d :%3d ]\n", pVars[i], pVars[k], iVar1, iVar2 ); } // sat_solver_add_and1( p, iVar1, pVars[i], pVars[k], 1, 1, 1 ); // sat_solver_add_and2( p, iVar2, pVars[i], pVars[k], 0, 0, 0 ); sat_solver_add_half_sorter( p, iVar1, iVar2, pVars[i], pVars[k] ); pVars[i] = iVar1; pVars[k] = iVar2; } static inline void Sbm_AddCardinConstrMerge( sat_solver * p, int * pVars, int lo, int hi, int r, int * pnVars ) { int i, step = r * 2; if ( step < hi - lo ) { Sbm_AddCardinConstrMerge( p, pVars, lo, hi-r, step, pnVars ); Sbm_AddCardinConstrMerge( p, pVars, lo+r, hi, step, pnVars ); for ( i = lo+r; i < hi-r; i += step ) Sbm_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 = sat_solver_addclause( p, Lits, Lits + 2 ); assert( Cid ); } } } static inline void Sbm_AddCardinConstrRange( sat_solver * 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++ ) Sbm_AddSorter( p, pVars, i, i + (hi - lo + 1) / 2, pnVars ); Sbm_AddCardinConstrRange( p, pVars, lo, mid, pnVars ); Sbm_AddCardinConstrRange( p, pVars, mid+1, hi, pnVars ); Sbm_AddCardinConstrMerge( p, pVars, lo, hi, 1, pnVars ); } } int Sbm_AddCardinConstrPairWise( sat_solver * p, Vec_Int_t * vVars, int K ) { int nVars = Vec_IntSize(vVars); Sbm_AddCardinConstrRange( p, Vec_IntArray(vVars), 0, nVars - 1, &nVars ); sat_solver_bookmark( p ); return nVars; } sat_solver * Sbm_AddCardinSolver( int LogN, Vec_Int_t ** pvVars ) { int nVars = 1 << LogN; int nVarsAlloc = nVars + 2 * (nVars * LogN * (LogN-1) / 4 + nVars - 1), nVarsReal; Vec_Int_t * vVars = Vec_IntStartNatural( nVars ); sat_solver * pSat = sat_solver_new(); sat_solver_setnvars( pSat, nVarsAlloc ); nVarsReal = Sbm_AddCardinConstrPairWise( pSat, vVars, 2 ); assert( nVarsReal == nVarsAlloc ); *pvVars = vVars; return pSat; } void Sbm_AddCardinConstrTest() { int LogN = 3, nVars = 1 << LogN, K = 2, Count = 1; Vec_Int_t * vVars, * vLits = Vec_IntAlloc( nVars ); sat_solver * pSat = Sbm_AddCardinSolver( LogN, &vVars ); int nVarsReal = sat_solver_nvars( pSat ); int Lit = Abc_Var2Lit( Vec_IntEntry(vVars, K), 1 ); printf( "LogN = %d. N = %3d. Vars = %5d. Clauses = %6d. Comb = %d.\n", LogN, nVars, nVarsReal, sat_solver_nclauses(pSat), nVars * (nVars-1)/2 + nVars + 1 ); while ( 1 ) { int i, status = sat_solver_solve( pSat, &Lit, &Lit+1, 0, 0, 0, 0 ); if ( status != l_True ) break; Vec_IntClear( vLits ); printf( "%3d : ", Count++ ); for ( i = 0; i < nVars; i++ ) { Vec_IntPush( vLits, Abc_Var2Lit(i, sat_solver_var_value(pSat, i)) ); printf( "%d", sat_solver_var_value(pSat, i) ); } printf( "\n" ); status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + nVars ); if ( status == 0 ) break; } sat_solver_delete( pSat ); Vec_IntFree( vVars ); Vec_IntFree( vLits ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sbm_Man_t * Sbm_ManAlloc( int LogN ) { Sbm_Man_t * p = ABC_CALLOC( Sbm_Man_t, 1 ); p->pSat = Sbm_AddCardinSolver( LogN, &p->vCardVars ); p->LogN = LogN; p->FirstVar = sat_solver_nvars( p->pSat ); // window p->vRoots = Vec_IntAlloc( 100 ); p->vCuts = Vec_WecAlloc( 1000 ); p->vObjCuts = Vec_WecAlloc( 1000 ); p->vSolCuts = Vec_IntAlloc( 100 ); p->vCutGates = Vec_IntAlloc( 100 ); p->vCutAreas = Vec_WrdAlloc( 100 ); // solver p->vAssump = Vec_IntAlloc( 100 ); p->vPolar = Vec_IntAlloc( 100 ); // timing p->vArrs = Vec_IntAlloc( 100 ); p->vReqs = Vec_IntAlloc( 100 ); // internal p->vLit2Used = Vec_IntAlloc( 100 ); p->vDelays = Vec_IntAlloc( 100 ); p->vReason = Vec_IntAlloc( 100 ); return p; } void Sbm_ManStop( Sbm_Man_t * p ) { sat_solver_delete( p->pSat ); Vec_IntFree( p->vCardVars ); // internal Vec_IntFree( p->vRoots ); Vec_WecFree( p->vCuts ); Vec_WecFree( p->vObjCuts ); Vec_IntFree( p->vSolCuts ); Vec_IntFree( p->vCutGates ); Vec_WrdFree( p->vCutAreas ); // internal Vec_IntFree( p->vAssump ); Vec_IntFree( p->vPolar ); // internal Vec_IntFree( p->vArrs ); Vec_IntFree( p->vReqs ); // internal Vec_IntFree( p->vLit2Used ); Vec_IntFree( p->vDelays ); Vec_IntFree( p->vReason ); ABC_FREE( p ); } int Sbm_ManTestSat( void * pMan ) { abctime clk = Abc_Clock(), clk2; int i, k, Lit, LogN = 7, nVars = 1 << LogN, status, Root; Sbm_Man_t * p = Sbm_ManAlloc( LogN ); word InvArea = 0; int fKeepTrying = 1; int StartSol; // derive window extern int Nf_ManExtractWindow( void * pMan, Vec_Int_t * vRoots, Vec_Wec_t * vCuts, Vec_Wec_t * vObjCuts, Vec_Int_t * vSolCuts, Vec_Int_t * vCutGates, Vec_Wrd_t * vCutAreas, word * pInvArea, int StartVar, int nVars ); p->nInputs = Nf_ManExtractWindow( pMan, p->vRoots, p->vCuts, p->vObjCuts, p->vSolCuts, p->vCutGates, p->vCutAreas, &InvArea, p->FirstVar, nVars ); p->LitShift = 2*p->nInputs+2; assert( Vec_WecSize(p->vObjCuts) + p->nInputs <= nVars ); // print-out // Vec_WecPrint( p->vCuts, 0 ); // printf( "\n" ); // Vec_WecPrint( p->vObjCuts, 0 ); // printf( "\n" ); Vec_IntPrint( p->vSolCuts ); printf( "All clauses = %d. Multi clauses = %d. Binary clauses = %d. Other clauses = %d.\n", sat_solver_nclauses(p->pSat), Vec_WecSize(p->vObjCuts), Vec_WecSizeSize(p->vCuts), sat_solver_nclauses(p->pSat) - Vec_WecSize(p->vObjCuts) - Vec_WecSizeSize(p->vCuts) ); // creating CNF if ( !Sbm_ManCreateCnf(p) ) return 0; // create assumptions // cardinality Vec_IntClear( p->vAssump ); Vec_IntPush( p->vAssump, -1 ); // unused variables for ( i = Vec_WecSize(p->vObjCuts) + p->nInputs; i < nVars; i++ ) Vec_IntPush( p->vAssump, Abc_Var2Lit(i, 1) ); // root variables Vec_IntForEachEntry( p->vRoots, Root, i ) Vec_IntPush( p->vAssump, Abc_Var2Lit(Root, 0) ); // Vec_IntPrint( p->vAssump ); StartSol = Vec_IntSize(p->vSolCuts); // StartSol = 30; while ( fKeepTrying && StartSol-fKeepTrying > 0 ) { printf( "Trying to find mapping with %d gates.\n", StartSol-fKeepTrying ); // for ( i = Vec_IntSize(p->vSolCuts)-5; i < nVars; i++ ) // Vec_IntPush( p->vAssump, Abc_Var2Lit(Vec_IntEntry(p->vCardVars, i), 1) ); Vec_IntWriteEntry( p->vAssump, 0, Abc_Var2Lit(Vec_IntEntry(p->vCardVars, StartSol-fKeepTrying), 1) ); // solve the problem clk2 = Abc_Clock(); status = sat_solver_solve( p->pSat, Vec_IntArray(p->vAssump), Vec_IntLimit(p->vAssump), 0, 0, 0, 0 ); if ( status == l_True ) { word AreaNew = 0; int Count = 0; printf( "AND Lits = %d. Inputs = %d. Vars = %d. All vars = %d.\n", Vec_WecSize(p->vObjCuts), p->nInputs, Vec_WecSize(p->vObjCuts) + p->nInputs, nVars ); // for ( i = 0; i < nVars; i++ ) // printf( "%d", sat_solver_var_value(p->pSat, i) ); // printf( "\n" ); for ( i = 0; i < nVars; i++ ) if ( sat_solver_var_value(p->pSat, i) ) { printf( "%d=%d ", i, sat_solver_var_value(p->pSat, i) ); Count++; if ( i >= Vec_WecSize(p->vObjCuts) ) AreaNew += InvArea; } printf( "Count = %d\n", Count ); // for ( i = p->FirstVar; i < sat_solver_nvars(p->pSat); i++ ) // printf( "%d", sat_solver_var_value(p->pSat, i) ); // printf( "\n" ); Count = 1; for ( i = p->FirstVar; i < sat_solver_nvars(p->pSat); i++ ) if ( sat_solver_var_value(p->pSat, i) ) { Vec_Int_t * vCutOne = Vec_WecEntry(p->vCuts, i-p->FirstVar); printf( "%2d : Cut %3d (Gate %2d) ", Count, i-p->FirstVar, Vec_IntEntry(p->vCutGates, i-p->FirstVar) ); Vec_IntForEachEntry( vCutOne, Lit, k ) printf( "%d(%d) ", Lit - 2*(p->nInputs+1), Abc_Lit2Var(Lit) ); printf( "\n" ); Count++; AreaNew += Vec_WrdEntry(p->vCutAreas, i-p->FirstVar); } printf( "Area = %7.2f\n", Scl_Int2Flt((int)AreaNew) ); } if ( status == l_False ) printf( "UNSAT " ), fKeepTrying = 0; else if ( status == l_True ) printf( "SAT " ), fKeepTrying++; Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 ); Abc_PrintTime( 1, "Total time", Abc_Clock() - clk ); printf( "\n" ); } Sbm_ManStop( p ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSatSyn.c000066400000000000000000000032531477524141600163400ustar00rootroot00000000000000/**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 abc-0.52/src/aig/gia/giaSatoko.c000066400000000000000000000201501477524141600163520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaSatoko.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Interface to Satoko solver.] Author [Alan Mishchenko, Bruno Schmitt] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaSatoko.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "sat/cnf/cnf.h" #include "misc/extra/extra.h" #include "sat/satoko/satoko.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCollectVars_rec( int Var, Vec_Int_t * vMapping, Vec_Int_t * vRes, Vec_Bit_t * vVisit ) { int * pCut, i; if ( Vec_BitEntry(vVisit, Var) ) return; Vec_BitWriteEntry(vVisit, Var, 1); if ( Vec_IntEntry(vMapping, Var) ) // primary input or constant 0 { pCut = Vec_IntEntryP( vMapping, Vec_IntEntry(vMapping, Var) ); for ( i = 1; i <= pCut[0]; i++ ) Gia_ManCollectVars_rec( pCut[i], vMapping, vRes, vVisit ); } Vec_IntPush( vRes, Var ); } Vec_Int_t * Gia_ManCollectVars( int Root, Vec_Int_t * vMapping, int nVars ) { Vec_Int_t * vRes = Vec_IntAlloc( 100 ); Vec_Bit_t * vVisit = Vec_BitStart( nVars ); assert( Vec_IntEntry(vMapping, Root) ); Gia_ManCollectVars_rec( Root, vMapping, vRes, vVisit ); Vec_BitFree( vVisit ); return vRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSatokoReport( int iOutput, int status, abctime clk ) { if ( iOutput >= 0 ) Abc_Print( 1, "Output %6d : ", iOutput ); else Abc_Print( 1, "Total: " ); if ( status == SATOKO_UNDEC ) Abc_Print( 1, "UNDECIDED " ); else if ( status == SATOKO_SAT ) Abc_Print( 1, "SATISFIABLE " ); else Abc_Print( 1, "UNSATISFIABLE " ); Abc_PrintTime( 1, "Time", clk ); } satoko_t * Gia_ManSatokoFromDimacs( char * pFileName, satoko_opts_t * opts ) { satoko_t * pSat = satoko_create(); char * pBuffer = Extra_FileReadContents( pFileName ); Vec_Int_t * vLits = Vec_IntAlloc( 100 ); char * pTemp; int fComp, Var, VarMax = 0; for ( pTemp = pBuffer; *pTemp; pTemp++ ) { if ( *pTemp == 'c' || *pTemp == 'p' ) { while ( *pTemp != '\n' ) pTemp++; continue; } while ( *pTemp == ' ' || *pTemp == '\t' || *pTemp == '\r' || *pTemp == '\n' ) pTemp++; fComp = 0; if ( *pTemp == '-' ) fComp = 1, pTemp++; if ( *pTemp == '+' ) pTemp++; Var = atoi( pTemp ); if ( Var == 0 ) { if ( Vec_IntSize(vLits) > 0 ) { satoko_setnvars( pSat, VarMax+1 ); if ( !satoko_add_clause( pSat, Vec_IntArray(vLits), Vec_IntSize(vLits) ) ) { satoko_destroy(pSat); Vec_IntFree( vLits ); ABC_FREE( pBuffer ); return NULL; } Vec_IntClear( vLits ); } } else { Var--; VarMax = Abc_MaxInt( VarMax, Var ); Vec_IntPush( vLits, Abc_Var2Lit(Var, fComp) ); } while ( *pTemp >= '0' && *pTemp <= '9' ) pTemp++; } ABC_FREE( pBuffer ); Vec_IntFree( vLits ); return pSat; } void Gia_ManSatokoDimacs( char * pFileName, satoko_opts_t * opts ) { abctime clk = Abc_Clock(); int status = SATOKO_UNSAT; satoko_t * pSat = Gia_ManSatokoFromDimacs( pFileName, opts ); if ( pSat ) { status = satoko_solve( pSat ); satoko_destroy( pSat ); } Gia_ManSatokoReport( -1, status, Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ satoko_t * Gia_ManSatokoInit( Cnf_Dat_t * pCnf, satoko_opts_t * opts ) { satoko_t * pSat = satoko_create(); int i; //sat_solver_setnvars( pSat, p->nVars ); for ( i = 0; i < pCnf->nClauses; i++ ) { if ( !satoko_add_clause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1]-pCnf->pClauses[i] ) ) { satoko_destroy( pSat ); return NULL; } } satoko_configure(pSat, opts); return pSat; } satoko_t * Gia_ManSatokoCreate( Gia_Man_t * p, satoko_opts_t * opts ) { Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 1, 0, 0 ); satoko_t * pSat = Gia_ManSatokoInit( pCnf, opts ); int status = pSat ? satoko_simplify(pSat) : SATOKO_OK; Cnf_DataFree( pCnf ); if ( status == SATOKO_OK ) return pSat; satoko_destroy( pSat ); return NULL; } int Gia_ManSatokoCallOne( Gia_Man_t * p, satoko_opts_t * opts, int iOutput ) { abctime clk = Abc_Clock(); satoko_t * pSat; int status = SATOKO_UNSAT, Cost = 0; pSat = Gia_ManSatokoCreate( p, opts ); if ( pSat ) { status = satoko_solve( pSat ); Cost = satoko_stats(pSat)->n_conflicts; satoko_destroy( pSat ); } Gia_ManSatokoReport( iOutput, status, Abc_Clock() - clk ); return Cost; } void Gia_ManSatokoCall( Gia_Man_t * p, satoko_opts_t * opts, int fSplit, int fIncrem ) { int fUseCone = 1; Gia_Man_t * pOne; Gia_Obj_t * pRoot; Vec_Int_t * vCone; int i, iLit, status; if ( fIncrem ) { abctime clk = Abc_Clock(); Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 0, fUseCone, 0 ); satoko_t * pSat = Gia_ManSatokoInit( pCnf, opts ); Gia_ManForEachCo( p, pRoot, i ) { abctime clk = Abc_Clock(); iLit = Abc_Var2Lit( i+1, 0 ); satoko_assump_push( pSat, iLit ); if ( fUseCone ) { vCone = Gia_ManCollectVars( i+1, pCnf->vMapping, pCnf->nVars ); satoko_mark_cone( pSat, Vec_IntArray(vCone), Vec_IntSize(vCone) ); printf( "Cone has %6d vars (out of %6d). ", Vec_IntSize(vCone), pCnf->nVars ); status = satoko_solve( pSat ); satoko_unmark_cone( pSat, Vec_IntArray(vCone), Vec_IntSize(vCone) ); Vec_IntFree( vCone ); } else { status = satoko_solve( pSat ); } satoko_assump_pop( pSat ); Gia_ManSatokoReport( i, status, Abc_Clock() - clk ); } Cnf_DataFree( pCnf ); satoko_destroy( pSat ); Abc_PrintTime( 1, "Total time", Abc_Clock() - clk ); return; } if ( fSplit ) { abctime clk = Abc_Clock(); Gia_ManForEachCo( p, pRoot, i ) { pOne = Gia_ManDupDfsCone( p, pRoot ); Gia_ManSatokoCallOne( pOne, opts, i ); Gia_ManStop( pOne ); } Abc_PrintTime( 1, "Total time", Abc_Clock() - clk ); return; } Gia_ManSatokoCallOne( p, opts, -1 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaScl.c000066400000000000000000000214061477524141600156400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaScl.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Sequential cleanup.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaScl.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Marks unreachable internal nodes and returns their number.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCombMarkUsed_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( pObj == NULL ) return 0; if ( !pObj->fMark0 ) return 0; pObj->fMark0 = 0; assert( Gia_ObjIsAnd(pObj) ); assert( !Gia_ObjIsBuf(pObj) ); return 1 + Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin0(pObj) ) + Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin1(pObj) ) + (p->pNexts ? Gia_ManCombMarkUsed_rec( p, Gia_ObjNextObj(p, Gia_ObjId(p, pObj)) ) : 0) + (p->pSibls ? Gia_ManCombMarkUsed_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)) ) : 0) + (p->pMuxes ? Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin2(p, pObj) ) : 0); } int Gia_ManCombMarkUsed( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, nNodes = 0; Gia_ManForEachObj( p, pObj, i ) pObj->fMark0 = Gia_ObjIsAnd(pObj) && !Gia_ObjIsBuf(pObj); Gia_ManForEachBuf( p, pObj, i ) nNodes += Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin0(pObj) ); Gia_ManForEachCo( p, pObj, i ) nNodes += Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin0(pObj) ); return nNodes; } /**Function************************************************************* Synopsis [Performs combinational cleanup.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManCleanup( Gia_Man_t * p ) { Gia_ManCombMarkUsed( p ); return Gia_ManDupMarked( p ); } /**Function************************************************************* Synopsis [Skip the first outputs during cleanup.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManCleanupOutputs( Gia_Man_t * p, int nOutputs ) { Gia_Obj_t * pObj; int i; assert( Gia_ManRegNum(p) == 0 ); assert( nOutputs < Gia_ManCoNum(p) ); Gia_ManCombMarkUsed( p ); Gia_ManForEachCo( p, pObj, i ) if ( i < nOutputs ) pObj->fMark0 = 1; else break; return Gia_ManDupMarked( p ); } /**Function************************************************************* Synopsis [Marks CIs/COs/ANDs unreachable from POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSeqMarkUsed_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vRoots ) { if ( !pObj->fMark0 ) return 0; pObj->fMark0 = 0; if ( Gia_ObjIsCo(pObj) ) return Gia_ManSeqMarkUsed_rec( p, Gia_ObjFanin0(pObj), vRoots ); if ( Gia_ObjIsRo(p, pObj) ) { Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) ); return 0; } assert( Gia_ObjIsAnd(pObj) ); return 1 + Gia_ManSeqMarkUsed_rec( p, Gia_ObjFanin0(pObj), vRoots ) + Gia_ManSeqMarkUsed_rec( p, Gia_ObjFanin1(pObj), vRoots ); } /**Function************************************************************* Synopsis [Marks CIs/COs/ANDs unreachable from POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSeqMarkUsed( Gia_Man_t * p ) { Vec_Int_t * vRoots; Gia_Obj_t * pObj; int i, nNodes = 0; Gia_ManSetMark0( p ); Gia_ManConst0(p)->fMark0 = 0; Gia_ManForEachPi( p, pObj, i ) pObj->fMark0 = 0; vRoots = Gia_ManCollectPoIds( p ); Gia_ManForEachObjVec( vRoots, p, pObj, i ) nNodes += Gia_ManSeqMarkUsed_rec( p, pObj, vRoots ); Vec_IntFree( vRoots ); return nNodes; } /**Function************************************************************* Synopsis [Performs sequential cleanup.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManSeqCleanup( Gia_Man_t * p ) { Gia_ManSeqMarkUsed( p ); return Gia_ManDupMarked( p ); } /**Function************************************************************* Synopsis [Find representatives due to identical fanins.] Description [Returns the old manager if there is no changes.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManReduceEquiv( Gia_Man_t * p, int fVerbose ) { Gia_Man_t * pNew; Gia_Obj_t * pObjRi, * pObjRo; unsigned * pCi2Lit, * pMaps; int i, iLit, nFanins = 1, Counter0 = 0, Counter = 0; Gia_ManForEachRi( p, pObjRi, i ) Gia_ObjFanin0(pObjRi)->Value = 0; Gia_ManForEachRi( p, pObjRi, i ) if ( Gia_ObjFanin0(pObjRi)->Value == 0 ) Gia_ObjFanin0(pObjRi)->Value = 2*nFanins++; pCi2Lit = ABC_FALLOC( unsigned, Gia_ManCiNum(p) ); pMaps = ABC_FALLOC( unsigned, 2 * nFanins ); Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) { iLit = Gia_ObjFanin0Copy( pObjRi ); if ( Gia_ObjFaninId0p(p, pObjRi) == 0 && Gia_ObjFaninC0(pObjRi) == 0 ) // const 0 pCi2Lit[Gia_ManPiNum(p)+i] = 0, Counter0++; else if ( ~pMaps[iLit] ) // in this case, ID(pObj) > ID(pRepr) pCi2Lit[Gia_ManPiNum(p)+i] = pMaps[iLit], Counter++; else pMaps[iLit] = Abc_Var2Lit( Gia_ObjId(p, pObjRo), 0 ); } /* Gia_ManForEachCi( p, pObjRo, i ) { if ( ~pCi2Lit[i] ) { Gia_Obj_t * pObj0 = Gia_ObjRoToRi(p, pObjRo); Gia_Obj_t * pObj1 = Gia_ObjRoToRi(p, Gia_ManObj(p, pCi2Lit[i])); Gia_Obj_t * pFan0 = Gia_ObjChild0( p, Gia_ObjRoToRi(p, pObjRo) ); Gia_Obj_t * pFan1 = Gia_ObjChild0( p, Gia_ObjRoToRi(p, Gia_ManObj(p, pCi2Lit[i])) ); assert( pFan0 == pFan1 ); } } */ // if ( fVerbose ) // printf( "ReduceEquiv detected %d constant regs and %d equivalent regs.\n", Counter0, Counter ); ABC_FREE( pMaps ); if ( Counter0 || Counter ) pNew = Gia_ManDupDfsCiMap( p, (int *)pCi2Lit, NULL ); else pNew = p; ABC_FREE( pCi2Lit ); return pNew; } /**Function************************************************************* Synopsis [Performs sequential cleanup.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManSeqStructSweep( Gia_Man_t * p, int fConst, int fEquiv, int fVerbose ) { Gia_Man_t * pTemp; if ( Gia_ManRegNum(p) == 0 ) return Gia_ManCleanup( p ); if ( fVerbose ) printf( "Performing sequential cleanup.\n" ); p = Gia_ManSeqCleanup( pTemp = p ); if ( fVerbose ) Gia_ManReportImprovement( pTemp, p ); if ( fConst && Gia_ManRegNum(p) ) { p = Gia_ManReduceConst( pTemp = p, fVerbose ); if ( fVerbose ) Gia_ManReportImprovement( pTemp, p ); Gia_ManStop( pTemp ); } if ( fVerbose && fEquiv ) printf( "Merging combinationally equivalent flops.\n" ); if ( fEquiv ) while ( 1 ) { p = Gia_ManSeqCleanup( pTemp = p ); if ( fVerbose ) Gia_ManReportImprovement( pTemp, p ); Gia_ManStop( pTemp ); if ( Gia_ManRegNum(p) == 0 ) break; p = Gia_ManReduceEquiv( pTemp = p, fVerbose ); if ( p == pTemp ) break; Gia_ManStop( pTemp ); } return p; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaScript.c000066400000000000000000000713661477524141600163750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaScript.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Various hardcoded scripts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaScript.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "giaAig.h" #include "base/main/main.h" #include "base/cmd/cmd.h" #include "proof/dch/dch.h" #include "opt/dau/dau.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Synthesis script.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManAigPrintPiLevels( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachPi( p, pObj, i ) printf( "%d ", Gia_ObjLevel(p, pObj) ); printf( "\n" ); } /**Function************************************************************* Synopsis [Synthesis script.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManAigSyn2( Gia_Man_t * pInit, int fOldAlgo, int fCoarsen, int fCutMin, int nRelaxRatio, int fDelayMin, int fVerbose, int fVeryVerbose ) { Gia_Man_t * p, * pNew, * pTemp; Jf_Par_t Pars, * pPars = &Pars; if ( fOldAlgo ) { Jf_ManSetDefaultPars( pPars ); pPars->fCutMin = fCutMin; } else { Lf_ManSetDefaultPars( pPars ); pPars->fCutMin = fCutMin; pPars->fCoarsen = fCoarsen; pPars->nRelaxRatio = nRelaxRatio; pPars->nAreaTuner = 1; pPars->nCutNum = 4; } if ( fVerbose ) Gia_ManPrintStats( pInit, NULL ); p = Gia_ManDup( pInit ); Gia_ManTransferTiming( p, pInit ); if ( Gia_ManAndNum(p) == 0 ) { pNew = Gia_ManDup(p); Gia_ManTransferTiming( pNew, p ); Gia_ManStop( p ); return pNew; } // delay optimization if ( fDelayMin && p->pManTime == NULL ) { int Area0, Area1, Delay0, Delay1; int fCutMin = pPars->fCutMin; int fCoarsen = pPars->fCoarsen; int nRelaxRatio = pPars->nRelaxRatio; pPars->fCutMin = 0; pPars->fCoarsen = 0; pPars->nRelaxRatio = 0; // perform mapping if ( fOldAlgo ) Jf_ManPerformMapping( p, pPars ); else Lf_ManPerformMapping( p, pPars ); Area0 = (int)pPars->Area; Delay0 = (int)pPars->Delay; // perform balancing pNew = Gia_ManPerformDsdBalance( p, 6, 4, 0, 0 ); // perform mapping again if ( fOldAlgo ) Jf_ManPerformMapping( pNew, pPars ); else Lf_ManPerformMapping( pNew, pPars ); Area1 = (int)pPars->Area; Delay1 = (int)pPars->Delay; // choose the best result if ( Delay1 < Delay0 - 1 || (Delay1 == Delay0 + 1 && 100.0 * (Area1 - Area0) / Area1 < 3.0) ) { Gia_ManStop( p ); p = pNew; } else { Gia_ManStop( pNew ); Vec_IntFreeP( &p->vMapping ); } // reset params pPars->fCutMin = fCutMin; pPars->fCoarsen = fCoarsen; pPars->nRelaxRatio = nRelaxRatio; } // perform balancing pNew = Gia_ManAreaBalance( p, 0, ABC_INFINITY, fVeryVerbose, 0 ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); Gia_ManStop( p ); // perform mapping if ( fOldAlgo ) pNew = Jf_ManPerformMapping( pTemp = pNew, pPars ); else pNew = Lf_ManPerformMapping( pTemp = pNew, pPars ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); if ( pTemp != pNew ) Gia_ManStop( pTemp ); // perform balancing pNew = Gia_ManAreaBalance( pTemp = pNew, 0, ABC_INFINITY, fVeryVerbose, 0 ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); Gia_ManStop( pTemp ); return pNew; } Gia_Man_t * Gia_ManAigSyn3( Gia_Man_t * p, int fVerbose, int fVeryVerbose ) { Gia_Man_t * pNew, * pTemp; Jf_Par_t Pars, * pPars = &Pars; Jf_ManSetDefaultPars( pPars ); pPars->nRelaxRatio = 40; if ( fVerbose ) Gia_ManPrintStats( p, NULL ); if ( Gia_ManAndNum(p) == 0 ) { 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 ); // perform mapping pPars->nLutSize = 6; pNew = Jf_ManPerformMapping( pTemp = pNew, pPars ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); // Gia_ManStop( pTemp ); // perform balancing pNew = Gia_ManAreaBalance( pTemp = pNew, 0, ABC_INFINITY, fVeryVerbose, 0 ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); Gia_ManStop( pTemp ); // perform mapping pPars->nLutSize = 4; pNew = Jf_ManPerformMapping( pTemp = pNew, pPars ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); // Gia_ManStop( pTemp ); // perform balancing pNew = Gia_ManAreaBalance( pTemp = pNew, 0, ABC_INFINITY, fVeryVerbose, 0 ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); Gia_ManStop( pTemp ); return pNew; } Gia_Man_t * Gia_ManAigSyn4( Gia_Man_t * p, int fVerbose, int fVeryVerbose ) { Gia_Man_t * pNew, * pTemp; Jf_Par_t Pars, * pPars = &Pars; Jf_ManSetDefaultPars( pPars ); pPars->nRelaxRatio = 40; if ( fVerbose ) Gia_ManPrintStats( p, NULL ); if ( Gia_ManAndNum(p) == 0 ) { 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 ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); // perform mapping pPars->nLutSize = 7; pNew = Jf_ManPerformMapping( pTemp = pNew, pPars ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); // Gia_ManStop( pTemp ); // perform extraction pNew = Gia_ManPerformFx( pTemp = pNew, ABC_INFINITY, 0, 0, fVeryVerbose, 0 ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); Gia_ManStop( pTemp ); // perform balancing pNew = Gia_ManAreaBalance( pTemp = pNew, 0, ABC_INFINITY, fVeryVerbose, 0 ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); Gia_ManStop( pTemp ); // perform mapping pPars->nLutSize = 5; pNew = Jf_ManPerformMapping( pTemp = pNew, pPars ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); // Gia_ManStop( pTemp ); // perform extraction pNew = Gia_ManPerformFx( pTemp = pNew, ABC_INFINITY, 0, 0, fVeryVerbose, 0 ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); Gia_ManStop( pTemp ); // perform balancing pNew = Gia_ManAreaBalance( pTemp = pNew, 0, ABC_INFINITY, fVeryVerbose, 0 ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); Gia_ManStop( pTemp ); //Gia_ManAigPrintPiLevels( pNew ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [This duplicator works for AIGs with choices.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Gia_ManOrderPios( Aig_Man_t * p, Gia_Man_t * pOrder ) { Vec_Ptr_t * vPios; Gia_Obj_t * pObj; int i; assert( Aig_ManCiNum(p) == Gia_ManCiNum(pOrder) ); assert( Aig_ManCoNum(p) == Gia_ManCoNum(pOrder) ); vPios = Vec_PtrAlloc( Aig_ManCiNum(p) + Aig_ManCoNum(p) ); Gia_ManForEachObj( pOrder, pObj, i ) { if ( Gia_ObjIsCi(pObj) ) Vec_PtrPush( vPios, Aig_ManCi(p, Gia_ObjCioId(pObj)) ); else if ( Gia_ObjIsCo(pObj) ) Vec_PtrPush( vPios, Aig_ManCo(p, Gia_ObjCioId(pObj)) ); } return vPios; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupFromBarBufs( Gia_Man_t * p ) { Vec_Int_t * vBufObjs; Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, k = 0; assert( Gia_ManBufNum(p) > 0 ); assert( Gia_ManRegNum(p) == 0 ); assert( !Gia_ManHasChoices(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 ); vBufObjs = Vec_IntAlloc( Gia_ManBufNum(p) ); for ( i = 0; i < Gia_ManBufNum(p); i++ ) Vec_IntPush( vBufObjs, Gia_ManAppendCi(pNew) ); Gia_ManForEachAnd( p, pObj, i ) { if ( Gia_ObjIsBuf(pObj) ) { pObj->Value = Vec_IntEntry( vBufObjs, k ); Vec_IntWriteEntry( vBufObjs, k++, Gia_ObjFanin0Copy(pObj) ); } else pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } assert( k == Gia_ManBufNum(p) ); for ( i = 0; i < Gia_ManBufNum(p); i++ ) Gia_ManAppendCo( pNew, Vec_IntEntry(vBufObjs, i) ); Vec_IntFree( vBufObjs ); Gia_ManForEachCo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); return pNew; } Gia_Man_t * Gia_ManDupToBarBufs( Gia_Man_t * p, int nBarBufs ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int nPiReal = Gia_ManCiNum(p) - nBarBufs; int nPoReal = Gia_ManCoNum(p) - nBarBufs; int i, k = 0; assert( Gia_ManBufNum(p) == 0 ); assert( Gia_ManRegNum(p) == 0 ); assert( Gia_ManHasChoices(p) ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); if ( Gia_ManHasChoices(p) ) pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManFillValue(p); Gia_ManConst0(p)->Value = 0; for ( i = 0; i < nPiReal; i++ ) Gia_ManCi(p, i)->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachAnd( p, pObj, i ) { for ( ; k < nBarBufs; k++ ) if ( ~Gia_ObjFanin0(Gia_ManCo(p, k))->Value ) Gia_ManCi(p, nPiReal + k)->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(Gia_ManCo(p, k)) ); else break; pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) ) pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))->Value); } for ( ; k < nBarBufs; k++ ) if ( ~Gia_ObjFanin0Copy(Gia_ManCo(p, k)) ) Gia_ManCi(p, nPiReal + k)->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(Gia_ManCo(p, k)) ); assert( k == nBarBufs ); for ( i = 0; i < nPoReal; i++ ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManCo(p, nBarBufs+i)) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); assert( Gia_ManBufNum(pNew) == nBarBufs ); assert( Gia_ManCiNum(pNew) == nPiReal ); assert( Gia_ManCoNum(pNew) == nPoReal ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManAigSynch2Choices( Gia_Man_t * pGia1, Gia_Man_t * pGia2, Gia_Man_t * pGia3, Dch_Pars_t * pPars ) { Aig_Man_t * pMan, * pTemp; Gia_Man_t * pGia, * pMiter; // derive miter Vec_Ptr_t * vPios, * vGias = Vec_PtrAlloc( 3 ); if ( pGia3 ) Vec_PtrPush( vGias, pGia3 ); if ( pGia2 ) Vec_PtrPush( vGias, pGia2 ); if ( pGia1 ) Vec_PtrPush( vGias, pGia1 ); pMiter = Gia_ManChoiceMiter( vGias ); Vec_PtrFree( vGias ); // transform into an AIG pMan = Gia_ManToAigSkip( pMiter, 3 ); Gia_ManStop( pMiter ); // compute choices pMan = Dch_ComputeChoices( pTemp = pMan, pPars ); Aig_ManStop( pTemp ); // reconstruct the network vPios = Gia_ManOrderPios( pMan, pGia1 ); pMan = Aig_ManDupDfsGuided( pTemp = pMan, vPios ); Aig_ManStop( pTemp ); Vec_PtrFree( vPios ); // convert to GIA pGia = Gia_ManFromAigChoices( pMan ); Aig_ManStop( pMan ); return pGia; } Gia_Man_t * Gia_ManAigSynch2( Gia_Man_t * pInit, void * pPars0, int nLutSize, int nRelaxRatio ) { extern Gia_Man_t * Gia_ManLutBalance( Gia_Man_t * p, int nLutSize, int fUseMuxes, int fRecursive, int fOptArea, int fVerbose ); Dch_Pars_t * pParsDch = (Dch_Pars_t *)pPars0; Gia_Man_t * pGia1, * pGia2, * pGia3, * pNew, * pTemp; int fVerbose = pParsDch->fVerbose; Jf_Par_t Pars, * pPars = &Pars; Lf_ManSetDefaultPars( pPars ); pPars->fCutMin = 1; pPars->fCoarsen = 1; pPars->nRelaxRatio = nRelaxRatio; pPars->nAreaTuner = 5; pPars->nCutNum = 12; pPars->fVerbose = fVerbose; if ( fVerbose ) Gia_ManPrintStats( pInit, NULL ); pGia1 = Gia_ManDup( pInit ); if ( Gia_ManAndNum(pGia1) == 0 ) { Gia_ManTransferTiming( pGia1, pInit ); return pGia1; } if ( pGia1->pManTime && pGia1->vLevels == NULL ) Gia_ManLevelWithBoxes( pGia1 ); // unmap if mapped if ( Gia_ManHasMapping(pInit) ) { Gia_ManTransferMapping( pGia1, pInit ); pGia1 = (Gia_Man_t *)Dsm_ManDeriveGia( pTemp = pGia1, 0 ); Gia_ManStop( pTemp ); } // perform balancing if ( Gia_ManBufNum(pGia1) || 1 ) pGia2 = Gia_ManAreaBalance( pGia1, 0, ABC_INFINITY, 0, 0 ); else { pGia2 = Gia_ManLutBalance( pGia1, nLutSize, 1, 1, 1, 0 ); pGia2 = Gia_ManAreaBalance( pTemp = pGia2, 0, ABC_INFINITY, 0, 0 ); Gia_ManStop( pTemp ); } if ( fVerbose ) Gia_ManPrintStats( pGia2, NULL ); // perform mapping pGia2 = Lf_ManPerformMapping( pTemp = pGia2, pPars ); if ( fVerbose ) Gia_ManPrintStats( pGia2, NULL ); if ( pTemp != pGia2 ) Gia_ManStop( pTemp ); // perform balancing if ( pParsDch->fLightSynth || Gia_ManBufNum(pGia2) ) pGia3 = Gia_ManAreaBalance( pGia2, 0, ABC_INFINITY, 0, 0 ); else { assert( Gia_ManBufNum(pGia2) == 0 ); pGia2 = Gia_ManAreaBalance( pTemp = pGia2, 0, ABC_INFINITY, 0, 0 ); if ( fVerbose ) Gia_ManPrintStats( pGia2, NULL ); Gia_ManStop( pTemp ); // perform DSD balancing pGia3 = Gia_ManPerformDsdBalance( pGia2, 6, 8, 0, 0 ); } if ( fVerbose ) Gia_ManPrintStats( pGia3, NULL ); // perform choice computation if ( Gia_ManBufNum(pInit) ) { assert( Gia_ManBufNum(pInit) == Gia_ManBufNum(pGia1) ); pGia1 = Gia_ManDupFromBarBufs( pTemp = pGia1 ); Gia_ManStop( pTemp ); assert( Gia_ManBufNum(pInit) == Gia_ManBufNum(pGia2) ); pGia2 = Gia_ManDupFromBarBufs( pTemp = pGia2 ); Gia_ManStop( pTemp ); assert( Gia_ManBufNum(pInit) == Gia_ManBufNum(pGia3) ); pGia3 = Gia_ManDupFromBarBufs( pTemp = pGia3 ); Gia_ManStop( pTemp ); } pNew = Gia_ManAigSynch2Choices( pGia1, pGia2, pGia3, pParsDch ); Gia_ManStop( pGia1 ); Gia_ManStop( pGia2 ); Gia_ManStop( pGia3 ); if ( Gia_ManBufNum(pInit) ) { pNew = Gia_ManDupToBarBufs( pTemp = pNew, Gia_ManBufNum(pInit) ); Gia_ManStop( pTemp ); } // copy names ABC_FREE( pNew->pName ); ABC_FREE( pNew->pSpec ); pNew->pName = Abc_UtilStrsav(pInit->pName); pNew->pSpec = Abc_UtilStrsav(pInit->pSpec); Gia_ManTransferTiming( pNew, pInit ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPerformMap( int nAnds, int nLutSize, int nCutNum, int fMinAve, int fUseMfs, int fVerbose ) { char Command[200]; sprintf( Command, "&unmap; &lf -K %d -C %d -k %s; &save", nLutSize, nCutNum, fMinAve?"-t":"" ); // sprintf( Command, "&unmap; &if -K %d -C %d %s; &save", nLutSize, nCutNum, fMinAve?"-t":"" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); if ( fVerbose ) { printf( "MAPPING:\n" ); printf( "Mapping with &lf -k:\n" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); } sprintf( Command, "&unmap; &lf -K %d -C %d %s; &save", nLutSize, nCutNum, fMinAve?"-t":"" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); if ( fVerbose ) { printf( "Mapping with &lf:\n" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); } if ( (nLutSize == 4 && nAnds < 100000) || (nLutSize == 6 && nAnds < 2000) ) { sprintf( Command, "&unmap; &if -sz -S %d%d -K %d -C %d %s", nLutSize, nLutSize, 2*nLutSize-1, 2*nCutNum, fMinAve?"-t":"" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); Vec_IntFreeP( &Abc_FrameReadGia(Abc_FrameGetGlobalFrame())->vPacking ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&save" ); if ( fVerbose ) { printf( "Mapping with &if -sz -S %d%d -K %d -C %d %s:\n", nLutSize, nLutSize, 2*nLutSize-1, 2*nCutNum, fMinAve?"-t":"" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); } } Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&load" ); if ( fUseMfs ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&put; mfs2 -W 4 -M 500 -C 7000; &get -m" ); if ( fVerbose ) { printf( "Mapping final:\n" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); } } void Gia_ManPerformRound( int fIsMapped, int nAnds, int nLevels, int nLutSize, int nCutNum, int fMinAve, int fUseMfs, int fVerbose ) { char Command[200]; // perform AIG-based synthesis if ( nAnds < 50000 ) { Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "" ); sprintf( Command, "&dsdb; &dch -C 500; &if -K %d -C %d %s; &save", nLutSize, nCutNum, fMinAve?"-t":"" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); if ( fVerbose ) { printf( "Mapping with &dch -C 500; &if -K %d -C %d %s:\n", nLutSize, nCutNum, fMinAve?"-t":"" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); } Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); } // perform AIG-based synthesis if ( nAnds < 20000 ) { Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "" ); sprintf( Command, "&dsdb; &dch -C 500; &if -K %d -C %d %s; &save", nLutSize, nCutNum, fMinAve?"-t":"" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); if ( fVerbose ) { printf( "Mapping with &dch -C 500; &if -K %d -C %d %s:\n", nLutSize, nCutNum, fMinAve?"-t":"" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); } Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); } // perform first round of mapping Gia_ManPerformMap( nAnds, nLutSize, nCutNum, fMinAve, fUseMfs, fVerbose ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); // perform synthesis Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&dsdb" ); // perform second round of mapping Gia_ManPerformMap( nAnds, nLutSize, nCutNum, fMinAve, fUseMfs, fVerbose ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); // perform synthesis Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&syn2 -m -R 10; &dsdb" ); // prepare for final mapping sprintf( Command, "&blut -a -K %d", nLutSize ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); // perform third round of mapping Gia_ManPerformMap( nAnds, nLutSize, nCutNum, fMinAve, fUseMfs, fVerbose ); } void Gia_ManPerformFlow( int fIsMapped, int nAnds, int nLevels, int nLutSize, int nCutNum, int fMinAve, int fUseMfs, int fVerbose ) { // remove comb equivs if ( fIsMapped ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); // if ( Abc_FrameReadGia(Abc_FrameGetGlobalFrame())->pManTime ) // Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&sweep" ); // else // Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&fraig -c" ); // perform first round Gia_ManPerformRound( fIsMapped, nAnds, nLevels, nLutSize, nCutNum, fMinAve, fUseMfs, fVerbose ); // perform synthesis Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st; &sopb" ); // perform first round Gia_ManPerformRound( fIsMapped, nAnds, nLevels, nLutSize, nCutNum, fMinAve, fUseMfs, fVerbose ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPerformFlow2( int fIsMapped, int nAnds, int nLevels, int nLutSize, int nCutNum, int fBalance, int fMinAve, int fUseMfs, int fVerbose ) { 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 ) printf( "Trying synthesis...\n" ); if ( fIsMapped ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm1 ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); // perform synthesis Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm2 ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); // return the result Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&load" ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); // perform balancing if ( fBalance ) { if ( fVerbose ) printf( "Trying SOP balancing...\n" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st; &sopb -R 10 -C 4" ); } // perform synthesis Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm3 ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); // perform synthesis Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm2 ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); // return the result Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&load" ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); if ( nAnds > 100000 ) return; // perform balancing if ( fBalance ) { if ( fVerbose ) printf( "Trying SOP balancing...\n" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st; &sopb -R 10" ); } // perform synthesis Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm3 ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); // perform synthesis Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm2 ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); // return the result Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&load" ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); if ( nAnds > 50000 ) return; // perform balancing if ( fBalance ) { if ( fVerbose ) printf( "Trying SOP balancing...\n" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st; &sopb -R 10" ); } // perform synthesis Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm3 ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); // perform synthesis Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm2 ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); // return the result Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&load" ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPerformFlow3( int nLutSize, int nCutNum, int fBalance, int fMinAve, int fUseMfs, int fUseLutLib, int fVerbose ) { char Comm1[200], Comm2[200], Comm3[200]; if ( fUseLutLib ) sprintf( Comm1, "&st; &if -C %d; &save; &st; &syn2; &if -C %d; &save; &load", nCutNum, nCutNum ); else sprintf( Comm1, "&st; &if -C %d -K %d; &save; &st; &syn2; &if -C %d -K %d; &save; &load", nCutNum, nLutSize, nCutNum, nLutSize ); if ( fUseLutLib ) sprintf( Comm2, "&st; &if -%s -K 6; &dch -f; &if -C %d; %s&save; &load", Abc_NtkRecIsRunning3() ? "y" : "g", nCutNum, fUseMfs ? "&mfs; ":"" ); else sprintf( Comm2, "&st; &if -%s -K 6; &dch -f; &if -C %d -K %d; %s&save; &load", Abc_NtkRecIsRunning3() ? "y" : "g", nCutNum, nLutSize, fUseMfs ? "&mfs; ":"" ); if ( fUseLutLib ) sprintf( Comm3, "&st; &if -%s -K 6; &synch2; &if -C %d; %s&save; &load", Abc_NtkRecIsRunning3() ? "y" : "g", nCutNum, fUseMfs ? "&mfs; ":"" ); else sprintf( Comm3, "&st; &if -%s -K 6; &synch2; &if -C %d -K %d; %s&save; &load", Abc_NtkRecIsRunning3() ? "y" : "g", nCutNum, nLutSize, fUseMfs ? "&mfs; ":"" ); if ( fVerbose ) printf( "Trying simple synthesis with %s...\n", Abc_NtkRecIsRunning3() ? "LMS" : "SOP balancing" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm1 ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); if ( Gia_ManAndNum( Abc_FrameReadGia(Abc_FrameGetGlobalFrame()) ) < 200000 ) { if ( fVerbose ) printf( "Trying medium synthesis...\n" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm2 ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); } if ( Gia_ManAndNum( Abc_FrameReadGia(Abc_FrameGetGlobalFrame()) ) < 10000 ) { if ( fVerbose ) printf( "Trying harder synthesis...\n" ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm3 ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); } if ( fVerbose ) printf( "Final result...\n" ); if ( fVerbose ) Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaShow.c000066400000000000000000001245311477524141600160420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaShow.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [AIG visualization.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: giaShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "proof/cec/cec.h" #include "proof/acec/acec.h" #include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define NODE_MAX 2000 //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Writes the graph structure of AIG for DOT.] Description [Useful for graph visualization using tools such as GraphViz: http://www.graphviz.org/] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ShowPath( Gia_Man_t * p, char * pFileName ) { FILE * pFile; Gia_Obj_t * pNode; Vec_Bit_t * vPath = Vec_BitStart( Gia_ManObjNum(p) ); int i, k, iFan, LevelMax, nLevels, * pLevels, Level, Prev; int nLuts = 0, nNodes = 0, nEdges = 0; assert( Gia_ManHasMapping(p) ); // set critical CO drivers nLevels = Gia_ManLutLevel( p, &pLevels ); Gia_ManForEachCoDriverId( p, iFan, i ) if ( pLevels[iFan] == nLevels ) Vec_BitWriteEntry( vPath, iFan, 1 ); // set critical internal nodes Gia_ManForEachLutReverse( p, i ) { nLuts++; if ( !Vec_BitEntry(vPath, i) ) continue; nNodes++; Gia_LutForEachFanin( p, i, iFan, k ) { if ( pLevels[iFan] +1 < pLevels[i] ) continue; assert( pLevels[iFan] + 1 == pLevels[i] ); Vec_BitWriteEntry( vPath, iFan, 1 ); nEdges++; //printf( "%d -> %d\n", i, iFan ); } } if ( nNodes > NODE_MAX ) { ABC_FREE( pLevels ); Vec_BitFree( vPath ); fprintf( stdout, "Cannot visualize AIG with more than %d critical nodes.\n", NODE_MAX ); return; } if ( (pFile = fopen( pFileName, "w" )) == NULL ) { ABC_FREE( pLevels ); Vec_BitFree( vPath ); fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); return; } Vec_IntFreeP( &p->vLevels ); p->vLevels = Vec_IntAllocArray( pLevels, Gia_ManObjNum(p) ); // compute CO levels LevelMax = 1 + nLevels; Gia_ManForEachCo( p, pNode, i ) Vec_IntWriteEntry( p->vLevels, Gia_ObjId(p, pNode), LevelMax ); // write the DOT header fprintf( pFile, "# %s\n", "AIG structure generated by GIA package" ); fprintf( pFile, "\n" ); fprintf( pFile, "digraph AIG {\n" ); fprintf( pFile, "size = \"7.5,10\";\n" ); // fprintf( pFile, "ranksep = 0.5;\n" ); // fprintf( pFile, "nodesep = 0.5;\n" ); fprintf( pFile, "center = true;\n" ); // fprintf( pFile, "orientation = landscape;\n" ); // fprintf( pFile, "edge [fontsize = 10];\n" ); // fprintf( pFile, "edge [dir = none];\n" ); fprintf( pFile, "edge [dir = back];\n" ); fprintf( pFile, "\n" ); // labels on the left of the picture fprintf( pFile, "{\n" ); fprintf( pFile, " node [shape = plaintext];\n" ); fprintf( pFile, " edge [style = invis];\n" ); fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); // generate node names with labels for ( Level = LevelMax; Level >= 0; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); fprintf( pFile, " [label = " ); // label name fprintf( pFile, "\"" ); fprintf( pFile, "\"" ); fprintf( pFile, "];\n" ); } // genetate the sequence of visible/invisible nodes to mark levels fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); for ( Level = LevelMax; Level >= 0; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); // the connector if ( Level != 0 ) fprintf( pFile, " ->" ); else fprintf( pFile, ";" ); } fprintf( pFile, "\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate title box on top fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); fprintf( pFile, " LevelTitle1;\n" ); fprintf( pFile, " title1 [shape=plaintext,\n" ); fprintf( pFile, " fontsize=20,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); fprintf( pFile, "%s", "AIG structure visualized by ABC" ); fprintf( pFile, "\\n" ); fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); // fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate statistics box fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); fprintf( pFile, " LevelTitle2;\n" ); fprintf( pFile, " title2 [shape=plaintext,\n" ); fprintf( pFile, " fontsize=18,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); fprintf( pFile, "The critical path contains %d LUTs with %d critical edges and spans %d levels.", nNodes, nEdges, nLevels ); fprintf( pFile, "\\n" ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate the COs fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMax ); // generate the CO nodes Gia_ManForEachCo( p, pNode, i ) { if ( Gia_ObjLevel(p, Gia_ObjFanin0(pNode)) < nLevels ) continue; assert( Gia_ObjLevel(p, Gia_ObjFanin0(pNode)) == nLevels ); fprintf( pFile, " Node%d [label = \"%d\"", Gia_ObjId(p, pNode), Gia_ObjId(p, pNode) ); fprintf( pFile, ", shape = %s", "invtriangle" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate nodes of each rank for ( Level = LevelMax - 1; Level > 0; Level-- ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", Level ); Gia_ManForEachObj( p, pNode, i ) { if ( (int)Gia_ObjLevel(p, pNode) != Level || !Vec_BitEntry(vPath, i) ) continue; fprintf( pFile, " Node%d [label = \"%d:%d\"", i, Vec_IntSize(p->vIdsOrig)?Vec_IntEntry(p->vIdsOrig,i):i, Gia_ObjIsAnd(pNode)?Gia_ObjLutSize(p, i):0 ); fprintf( pFile, ", shape = ellipse" ); if ( pNode->fMark0 ) fprintf( pFile, ", style = filled" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); } // generate the CI nodes fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", 0 ); // generate the CI nodes Gia_ManForEachCi( p, pNode, i ) { if ( !Vec_BitEntry(vPath, Gia_ObjId(p, pNode)) ) continue; fprintf( pFile, " Node%d [label = \"%d\"", Gia_ObjId(p, pNode), Gia_ObjId(p, pNode) ); fprintf( pFile, ", shape = %s", "triangle" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate invisible edges from the square down fprintf( pFile, "title1 -> title2 [style = invis];\n" ); Gia_ManForEachCo( p, pNode, i ) { if ( Gia_ObjLevel(p, Gia_ObjFanin0(pNode)) < nLevels ) continue; fprintf( pFile, "title2 -> Node%d [style = invis];\n", Gia_ObjId(p, pNode) ); } // generate invisible edges among the COs Prev = -1; Gia_ManForEachCo( p, pNode, i ) { if ( Gia_ObjLevel(p, Gia_ObjFanin0(pNode)) < nLevels ) continue; assert( Gia_ObjLevel(p, Gia_ObjFanin0(pNode)) == nLevels ); if ( Prev >= 0 ) fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, Gia_ObjId(p, pNode) ); Prev = Gia_ObjId(p, pNode); } // generate invisible edges among the CIs Prev = -1; Gia_ManForEachCi( p, pNode, i ) { if ( !Vec_BitEntry(vPath, Gia_ObjId(p, pNode)) ) continue; if ( Prev >= 0 ) fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, Gia_ObjId(p, pNode) ); Prev = Gia_ObjId(p, pNode); } // generate edges Gia_ManForEachObj( p, pNode, i ) { if ( Gia_ObjIsCo(pNode) ) { if ( Gia_ObjLevel(p, Gia_ObjFanin0(pNode)) == nLevels ) { // generate the edge from this node to the next fprintf( pFile, "Node%d", i ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", Gia_ObjFaninId0p(p, pNode) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", "solid" ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); } continue; } if ( !Gia_ObjIsAnd(pNode) || !Vec_BitEntry(vPath, i) ) continue; Gia_LutForEachFanin( p, i, iFan, k ) { if ( pLevels[iFan] + 1 < pLevels[i] ) continue; assert( pLevels[iFan] + 1 == pLevels[i] ); // generate the edge from this node to the next fprintf( pFile, "Node%d", i ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", iFan ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", "solid" ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); } } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); fclose( pFile ); Vec_IntFreeP( &p->vLevels ); Vec_BitFree( vPath ); } /**Function************************************************************* Synopsis [Writes the graph structure of AIG for DOT.] Description [Useful for graph visualization using tools such as GraphViz: http://www.graphviz.org/] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_WriteDotAigSimple( Gia_Man_t * p, char * pFileName, Vec_Int_t * vBold ) { FILE * pFile; Gia_Obj_t * pNode;//, * pTemp, * pPrev; int LevelMax, Prev, Level, i; int fConstIsUsed = 0; if ( Gia_ManAndNum(p) > NODE_MAX ) { fprintf( stdout, "Cannot visualize AIG with more than %d nodes.\n", NODE_MAX ); return; } if ( (pFile = fopen( pFileName, "w" )) == NULL ) { fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); return; } // mark the nodes if ( vBold ) Gia_ManForEachObjVec( vBold, p, pNode, i ) pNode->fMark0 = 1; else if ( p->nXors || p->nMuxes ) Gia_ManForEachObj( p, pNode, i ) if ( Gia_ObjIsXor(pNode) || Gia_ObjIsMux(p, pNode) ) pNode->fMark0 = 1; // compute levels LevelMax = 1 + Gia_ManLevelNum( p ); Gia_ManForEachCo( p, pNode, i ) Vec_IntWriteEntry( p->vLevels, Gia_ObjId(p, pNode), LevelMax ); // write the DOT header fprintf( pFile, "# %s\n", "AIG structure generated by GIA package" ); fprintf( pFile, "\n" ); fprintf( pFile, "digraph AIG {\n" ); fprintf( pFile, "size = \"7.5,10\";\n" ); // fprintf( pFile, "ranksep = 0.5;\n" ); // fprintf( pFile, "nodesep = 0.5;\n" ); fprintf( pFile, "center = true;\n" ); // fprintf( pFile, "orientation = landscape;\n" ); // fprintf( pFile, "edge [fontsize = 10];\n" ); // fprintf( pFile, "edge [dir = none];\n" ); fprintf( pFile, "edge [dir = back];\n" ); fprintf( pFile, "\n" ); // labels on the left of the picture fprintf( pFile, "{\n" ); fprintf( pFile, " node [shape = plaintext];\n" ); fprintf( pFile, " edge [style = invis];\n" ); fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); // generate node names with labels for ( Level = LevelMax; Level >= 0; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); fprintf( pFile, " [label = " ); // label name fprintf( pFile, "\"" ); fprintf( pFile, "\"" ); fprintf( pFile, "];\n" ); } // genetate the sequence of visible/invisible nodes to mark levels fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); for ( Level = LevelMax; Level >= 0; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); // the connector if ( Level != 0 ) fprintf( pFile, " ->" ); else fprintf( pFile, ";" ); } fprintf( pFile, "\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate title box on top fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); fprintf( pFile, " LevelTitle1;\n" ); fprintf( pFile, " title1 [shape=plaintext,\n" ); fprintf( pFile, " fontsize=20,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); fprintf( pFile, "%s", "AIG structure visualized by ABC" ); fprintf( pFile, "\\n" ); fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); // fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate statistics box fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); fprintf( pFile, " LevelTitle2;\n" ); fprintf( pFile, " title2 [shape=plaintext,\n" ); fprintf( pFile, " fontsize=18,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); fprintf( pFile, "The AIG contains %d nodes and spans %d levels.", Gia_ManAndNum(p), LevelMax-1 ); fprintf( pFile, "\\n" ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate the COs fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMax ); // generate the CO nodes Gia_ManForEachCo( p, pNode, i ) { if ( Gia_ObjFaninId0p(p, pNode) == 0 ) fConstIsUsed = 1; /* if ( fHaig || pNode->pEquiv == NULL ) fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, (Gia_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Gia_ObjIsLatch(pNode)? "_in":"") ); else fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, (Gia_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Gia_ObjIsLatch(pNode)? "_in":""), Gia_Regular(pNode->pEquiv)->Id, Gia_IsComplement(pNode->pEquiv)? "\'":"" ); */ fprintf( pFile, " Node%d [label = \"%d\"", Gia_ObjId(p, pNode), Gia_ObjId(p, pNode) ); fprintf( pFile, ", shape = %s", "invtriangle" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate nodes of each rank for ( Level = LevelMax - 1; Level > 0; Level-- ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", Level ); Gia_ManForEachObj( p, pNode, i ) { if ( (int)Gia_ObjLevel(p, pNode) != Level ) continue; /* if ( fHaig || pNode->pEquiv == NULL ) fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); else fprintf( pFile, " Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id, Gia_Regular(pNode->pEquiv)->Id, Gia_IsComplement(pNode->pEquiv)? "\'":"" ); */ fprintf( pFile, " Node%d [label = \"%d\"", i, i ); if ( Gia_ObjIsXor(pNode) ) fprintf( pFile, ", shape = doublecircle" ); else if ( Gia_ObjIsMux(p, pNode) ) fprintf( pFile, ", shape = trapezium" ); else fprintf( pFile, ", shape = ellipse" ); if ( pNode->fMark0 ) fprintf( pFile, ", style = filled" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); } // generate the CI nodes fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", 0 ); // generate constant node if ( fConstIsUsed ) { // check if the costant node is present fprintf( pFile, " Node%d [label = \"Const0\"", 0 ); fprintf( pFile, ", shape = ellipse" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } // generate the CI nodes Gia_ManForEachCi( p, pNode, i ) { /* if ( fHaig || pNode->pEquiv == NULL ) fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, (Gia_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Gia_ObjIsLatch(pNode)? "_out":"") ); else fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, (Gia_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Gia_ObjIsLatch(pNode)? "_out":""), Gia_Regular(pNode->pEquiv)->Id, Gia_IsComplement(pNode->pEquiv)? "\'":"" ); */ fprintf( pFile, " Node%d [label = \"%d\"", Gia_ObjId(p, pNode), Gia_ObjId(p, pNode) ); fprintf( pFile, ", shape = %s", "triangle" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate invisible edges from the square down fprintf( pFile, "title1 -> title2 [style = invis];\n" ); Gia_ManForEachCo( p, pNode, i ) fprintf( pFile, "title2 -> Node%d [style = invis];\n", Gia_ObjId(p, pNode) ); // generate invisible edges among the COs Prev = -1; Gia_ManForEachCo( p, pNode, i ) { if ( i > 0 ) fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, Gia_ObjId(p, pNode) ); Prev = Gia_ObjId(p, pNode); } // generate invisible edges among the CIs Prev = -1; Gia_ManForEachCi( p, pNode, i ) { if ( i > 0 ) fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, Gia_ObjId(p, pNode) ); Prev = Gia_ObjId(p, pNode); } // generate edges Gia_ManForEachObj( p, pNode, i ) { if ( !Gia_ObjIsAnd(pNode) && !Gia_ObjIsCo(pNode) && !Gia_ObjIsBuf(pNode) ) continue; // generate the edge from this node to the next fprintf( pFile, "Node%d", i ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", Gia_ObjFaninId0(pNode, i) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", Gia_ObjFaninC0(pNode)? "dotted" : "solid" ); // if ( Gia_NtkIsSeq(pNode->p) && Seq_ObjFaninL0(pNode) > 0 ) // fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); if ( !Gia_ObjIsAnd(pNode) ) continue; // generate the edge from this node to the next fprintf( pFile, "Node%d", i ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", Gia_ObjFaninId1(pNode, i) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", Gia_ObjFaninC1(pNode)? "dotted" : "solid" ); // if ( Gia_NtkIsSeq(pNode->p) && Seq_ObjFaninL1(pNode) > 0 ) // fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); if ( !Gia_ObjIsMux(p, pNode) ) continue; // generate the edge from this node to the next fprintf( pFile, "Node%d", i ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", Gia_ObjFaninId2(p, i) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", Gia_ObjFaninC2(p, pNode)? "dotted" : "bold" ); // if ( Gia_NtkIsSeq(pNode->p) && Seq_ObjFaninL1(pNode) > 0 ) // fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); /* // generate the edges between the equivalent nodes if ( fHaig && pNode->pEquiv && Gia_ObjRefs(pNode) > 0 ) { pPrev = pNode; for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Gia_Regular(pTemp->pEquiv) ) { fprintf( pFile, "Node%d", pPrev->Id ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", pTemp->Id ); fprintf( pFile, " [style = %s]", Gia_IsComplement(pTemp->pEquiv)? "dotted" : "solid" ); fprintf( pFile, ";\n" ); pPrev = pTemp; } // connect the last node with the first fprintf( pFile, "Node%d", pPrev->Id ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", pNode->Id ); fprintf( pFile, " [style = %s]", Gia_IsComplement(pPrev->pEquiv)? "dotted" : "solid" ); fprintf( pFile, ";\n" ); } */ } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); fclose( pFile ); // unmark nodes if ( vBold ) Gia_ManForEachObjVec( vBold, p, pNode, i ) pNode->fMark0 = 0; else if ( p->nXors || p->nMuxes ) Gia_ManCleanMark0( p ); Vec_IntFreeP( &p->vLevels ); } /**Function************************************************************* Synopsis [Writes the graph structure of AIG for DOT.] Description [Useful for graph visualization using tools such as GraphViz: http://www.graphviz.org/] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ShowAddOut( Vec_Int_t * vAdds, Vec_Int_t * vMapAdds, int Node ) { int iBox = Vec_IntEntry( vMapAdds, Node ); if ( iBox >= 0 ) return Vec_IntEntry( vAdds, 6*iBox+4 ); return Node; } void Gia_WriteDotAig( Gia_Man_t * p, char * pFileName, Vec_Int_t * vBold, Vec_Int_t * vAdds, Vec_Int_t * vXors, Vec_Int_t * vMapAdds, Vec_Int_t * vMapXors, Vec_Int_t * vOrder ) { FILE * pFile; Gia_Obj_t * pNode;//, * pTemp, * pPrev; int LevelMax, Prev, Level, i; int fConstIsUsed = 0; int nFadds = Ree_ManCountFadds( vAdds ); if ( Gia_ManAndNum(p) > NODE_MAX ) { fprintf( stdout, "Cannot visualize AIG with more than %d nodes.\n", NODE_MAX ); return; } if ( (pFile = fopen( pFileName, "w" )) == NULL ) { fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); return; } // mark the nodes if ( vBold ) Gia_ManForEachObjVec( vBold, p, pNode, i ) pNode->fMark0 = 1; // compute levels LevelMax = 1 + p->nLevels; Gia_ManForEachCo( p, pNode, i ) Vec_IntWriteEntry( p->vLevels, Gia_ObjId(p, pNode), LevelMax ); // write the DOT header fprintf( pFile, "# %s\n", "AIG structure generated by GIA package" ); fprintf( pFile, "\n" ); fprintf( pFile, "digraph AIG {\n" ); fprintf( pFile, "size = \"7.5,10\";\n" ); // fprintf( pFile, "ranksep = 0.5;\n" ); // fprintf( pFile, "nodesep = 0.5;\n" ); fprintf( pFile, "center = true;\n" ); // fprintf( pFile, "orientation = landscape;\n" ); // fprintf( pFile, "edge [fontsize = 10];\n" ); // fprintf( pFile, "edge [dir = none];\n" ); fprintf( pFile, "edge [dir = back];\n" ); fprintf( pFile, "\n" ); // labels on the left of the picture fprintf( pFile, "{\n" ); fprintf( pFile, " node [shape = plaintext];\n" ); fprintf( pFile, " edge [style = invis];\n" ); fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); // generate node names with labels for ( Level = LevelMax; Level >= 0; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); fprintf( pFile, " [label = " ); // label name fprintf( pFile, "\"" ); fprintf( pFile, "\"" ); fprintf( pFile, "];\n" ); } // genetate the sequence of visible/invisible nodes to mark levels fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); for ( Level = LevelMax; Level >= 0; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); // the connector if ( Level != 0 ) fprintf( pFile, " ->" ); else fprintf( pFile, ";" ); } fprintf( pFile, "\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate title box on top fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); fprintf( pFile, " LevelTitle1;\n" ); fprintf( pFile, " title1 [shape=plaintext,\n" ); fprintf( pFile, " fontsize=20,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); fprintf( pFile, "%s", "AIG structure visualized by ABC" ); fprintf( pFile, "\\n" ); fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); // fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate statistics box fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); fprintf( pFile, " LevelTitle2;\n" ); fprintf( pFile, " title2 [shape=plaintext,\n" ); fprintf( pFile, " fontsize=18,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); fprintf( pFile, "The AIG contains %d nodes, %d full-adders, and %d half-adders, and spans %d levels.", Gia_ManAndNum(p), nFadds, Vec_IntSize(vAdds)/6-nFadds, LevelMax-1 ); fprintf( pFile, "\\n" ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate the COs fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMax ); // generate the CO nodes Gia_ManForEachCo( p, pNode, i ) { if ( Gia_ObjFaninId0p(p, pNode) == 0 ) fConstIsUsed = 1; fprintf( pFile, " Node%d [label = \"%d\"", Gia_ObjId(p, pNode), Gia_ObjId(p, pNode) ); fprintf( pFile, ", shape = %s", "invtriangle" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate nodes of each rank for ( Level = LevelMax - 1; Level > 0; Level-- ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", Level ); Gia_ManForEachObjVec( vOrder, p, pNode, i ) { int iNode = Gia_ObjId( p, pNode ); if ( (int)Gia_ObjLevel(p, pNode) != Level ) continue; /* fprintf( pFile, " Node%d [label = \"%d\"", Gia_ObjId(p, pNode), Gia_ObjId(p, pNode) ); if ( Gia_ObjIsXor(pNode) ) fprintf( pFile, ", shape = doublecircle" ); else if ( Gia_ObjIsMux(p, pNode) ) fprintf( pFile, ", shape = trapezium" ); else fprintf( pFile, ", shape = ellipse" ); */ if ( !pNode->fMark0 && Vec_IntEntry(vMapAdds, iNode) >= 0 ) { int iBox = Vec_IntEntry(vMapAdds, iNode); fprintf( pFile, " Node%d [label = \"%d_%d\"", Gia_ShowAddOut(vAdds, vMapAdds, iNode), Vec_IntEntry(vAdds, 6*iBox+3), Vec_IntEntry(vAdds, 6*iBox+4) ); if ( Vec_IntEntry(vAdds, 6*iBox+2) == 0 ) fprintf( pFile, ", shape = octagon" ); else fprintf( pFile, ", shape = doubleoctagon" ); } else if ( Vec_IntEntry(vMapXors, iNode) >= 0 ) { fprintf( pFile, " Node%d [label = \"%d\"", iNode, iNode ); fprintf( pFile, ", shape = doublecircle" ); } else if ( Gia_ObjIsXor(pNode) ) { fprintf( pFile, " Node%d [label = \"%d\"", iNode, iNode ); fprintf( pFile, ", shape = doublecircle" ); } else if ( Gia_ObjIsMux(p, pNode) ) { fprintf( pFile, " Node%d [label = \"%d\"", iNode, iNode ); fprintf( pFile, ", shape = trapezium" ); } else { fprintf( pFile, " Node%d [label = \"%d\"", iNode, iNode ); fprintf( pFile, ", shape = ellipse" ); } if ( pNode->fMark0 ) fprintf( pFile, ", style = filled" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); } // generate the CI nodes fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", 0 ); // generate constant node if ( fConstIsUsed ) { // check if the costant node is present fprintf( pFile, " Node%d [label = \"Const0\"", 0 ); fprintf( pFile, ", shape = ellipse" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } // generate the CI nodes Gia_ManForEachCi( p, pNode, i ) { fprintf( pFile, " Node%d [label = \"%d\"", Gia_ObjId(p, pNode), Gia_ObjId(p, pNode) ); fprintf( pFile, ", shape = %s", "triangle" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate invisible edges from the square down fprintf( pFile, "title1 -> title2 [style = invis];\n" ); Gia_ManForEachCo( p, pNode, i ) fprintf( pFile, "title2 -> Node%d [style = invis];\n", Gia_ObjId(p, pNode) ); // generate invisible edges among the COs Prev = -1; Gia_ManForEachCo( p, pNode, i ) { if ( i > 0 ) fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, Gia_ObjId(p, pNode) ); Prev = Gia_ObjId(p, pNode); } // generate invisible edges among the CIs Prev = -1; Gia_ManForEachCi( p, pNode, i ) { if ( i > 0 ) fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, Gia_ObjId(p, pNode) ); Prev = Gia_ObjId(p, pNode); } // generate edges Gia_ManForEachCo( p, pNode, i ) { int iNode = Gia_ObjId( p, pNode ); fprintf( pFile, "Node%d", iNode ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", Gia_ShowAddOut(vAdds, vMapAdds, Gia_ObjFaninId0(pNode, iNode)) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", Gia_ObjFaninC0(pNode)? "dotted" : "solid" ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); } Gia_ManForEachObjVec( vOrder, p, pNode, i ) { int iNode = Gia_ObjId( p, pNode ); if ( Vec_IntEntry(vMapAdds, Gia_ObjId(p, pNode)) >= 0 ) { int k, iBox = Vec_IntEntry(vMapAdds, iNode); for ( k = 0; k < 3; k++ ) if ( Vec_IntEntry(vAdds, 6*iBox+k) ) { int iBox2 = Vec_IntEntry(vMapAdds, Vec_IntEntry(vAdds, 6*iBox+k)); int fXor2 = iBox2 >= 0 ? (int)(Vec_IntEntry(vAdds, 6*iBox2+3) == Vec_IntEntry(vAdds, 6*iBox+k)) : 0; fprintf( pFile, "Node%d", Gia_ShowAddOut(vAdds, vMapAdds, iNode) ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", Gia_ShowAddOut(vAdds, vMapAdds, Vec_IntEntry(vAdds, 6*iBox+k)) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", fXor2? "bold" : "solid" ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); } continue; } if ( Vec_IntEntry(vMapXors, Gia_ObjId(p, pNode)) >= 0 ) { int k, iXor = Vec_IntEntry(vMapXors, iNode); for ( k = 1; k < 4; k++ ) if ( Vec_IntEntry(vXors, 4*iXor+k) ) { int iXor2 = Vec_IntEntry(vMapXors, Vec_IntEntry(vXors, 4*iXor+k)); fprintf( pFile, "Node%d", iNode ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", Gia_ShowAddOut(vAdds, vMapAdds, Vec_IntEntry(vXors, 4*iXor+k)) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", iXor2 >= 0? "bold" : "solid" ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); } continue; } // generate the edge from this node to the next fprintf( pFile, "Node%d", iNode ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", Gia_ShowAddOut(vAdds, vMapAdds, Gia_ObjFaninId0(pNode, iNode)) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", Gia_ObjFaninC0(pNode)? "dotted" : "solid" ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); if ( !Gia_ObjIsAnd(pNode) ) continue; // generate the edge from this node to the next fprintf( pFile, "Node%d", iNode ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", Gia_ShowAddOut(vAdds, vMapAdds, Gia_ObjFaninId1(pNode, iNode)) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", Gia_ObjFaninC1(pNode)? "dotted" : "solid" ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); if ( !Gia_ObjIsMux(p, pNode) ) continue; // generate the edge from this node to the next fprintf( pFile, "Node%d", iNode ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", Gia_ShowAddOut(vAdds, vMapAdds, Gia_ObjFaninId2(p, iNode)) ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", Gia_ObjFaninC2(p, pNode)? "dotted" : "solid" ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); fclose( pFile ); // unmark nodes if ( vBold ) Gia_ManForEachObjVec( vBold, p, pNode, i ) pNode->fMark0 = 0; Vec_IntFreeP( &p->vLevels ); } /**Function************************************************************* Synopsis [Returns DFS ordered array of objects and their levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ShowMapAdds( Gia_Man_t * p, Vec_Int_t * vAdds, int fFadds, Vec_Int_t * vBold ) { Vec_Bit_t * vIsBold = Vec_BitStart( Gia_ManObjNum(p) ); Vec_Int_t * vMapAdds = Vec_IntStartFull( Gia_ManObjNum(p) ); int i, Entry; if ( vBold ) Vec_IntForEachEntry( vBold, Entry, i ) Vec_BitWriteEntry( vIsBold, Entry, 1 ); for ( i = 0; 6*i < Vec_IntSize(vAdds); i++ ) { if ( fFadds && Vec_IntEntry(vAdds, 6*i+2) == 0 ) continue; if ( Vec_BitEntry(vIsBold, Vec_IntEntry(vAdds, 6*i+3)) || Vec_BitEntry(vIsBold, Vec_IntEntry(vAdds, 6*i+4)) ) continue; Vec_IntWriteEntry( vMapAdds, Vec_IntEntry(vAdds, 6*i+3), i ); Vec_IntWriteEntry( vMapAdds, Vec_IntEntry(vAdds, 6*i+4), i ); } Vec_BitFree( vIsBold ); return vMapAdds; } Vec_Int_t * Gia_ShowMapXors( Gia_Man_t * p, Vec_Int_t * vXors ) { Vec_Int_t * vMapXors = Vec_IntStartFull( Gia_ManObjNum(p) ); int i; for ( i = 0; 4*i < Vec_IntSize(vXors); i++ ) Vec_IntWriteEntry( vMapXors, Vec_IntEntry(vXors, 4*i), i ); return vMapXors; } int Gia_ShowCollectObjs_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vAdds, Vec_Int_t * vXors, Vec_Int_t * vMapAdds, Vec_Int_t * vMapXors, Vec_Int_t * vOrder ) { int Level0, Level1, Level2 = 0, Level = 0; if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return Gia_ObjLevel(p, pObj); Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) return 0; if ( Vec_IntEntry(vMapAdds, Gia_ObjId(p, pObj)) >= 0 ) { int iBox = Vec_IntEntry(vMapAdds, Gia_ObjId(p, pObj)); Gia_ObjSetTravIdCurrentId(p, Vec_IntEntry(vAdds, 6*iBox+3) ); Gia_ObjSetTravIdCurrentId(p, Vec_IntEntry(vAdds, 6*iBox+4) ); Level0 = Gia_ShowCollectObjs_rec( p, Gia_ManObj( p, Vec_IntEntry(vAdds, 6*iBox+0) ), vAdds, vXors, vMapAdds, vMapXors, vOrder ); Level1 = Gia_ShowCollectObjs_rec( p, Gia_ManObj( p, Vec_IntEntry(vAdds, 6*iBox+1) ), vAdds, vXors, vMapAdds, vMapXors, vOrder ); if ( Vec_IntEntry(vAdds, 6*iBox+2) ) Level2 = Gia_ShowCollectObjs_rec( p, Gia_ManObj( p, Vec_IntEntry(vAdds, 6*iBox+2) ), vAdds, vXors, vMapAdds, vMapXors, vOrder ); Level = 1 + Abc_MaxInt( Abc_MaxInt(Level0, Level1), Level2 ); Gia_ObjSetLevelId( p, Vec_IntEntry(vAdds, 6*iBox+3), Level ); Gia_ObjSetLevelId( p, Vec_IntEntry(vAdds, 6*iBox+4), Level ); pObj = Gia_ManObj( p, Vec_IntEntry(vAdds, 6*iBox+4) ); } else if ( Vec_IntEntry(vMapXors, Gia_ObjId(p, pObj)) >= 0 ) { int iXor = Vec_IntEntry(vMapXors, Gia_ObjId(p, pObj)); Level0 = Gia_ShowCollectObjs_rec( p, Gia_ManObj( p, Vec_IntEntry(vXors, 4*iXor+1) ), vAdds, vXors, vMapAdds, vMapXors, vOrder ); Level1 = Gia_ShowCollectObjs_rec( p, Gia_ManObj( p, Vec_IntEntry(vXors, 4*iXor+2) ), vAdds, vXors, vMapAdds, vMapXors, vOrder ); if ( Vec_IntEntry(vXors, 4*iXor+3) ) Level2 = Gia_ShowCollectObjs_rec( p, Gia_ManObj( p, Vec_IntEntry(vXors, 4*iXor+3) ), vAdds, vXors, vMapAdds, vMapXors, vOrder ); Level = 1 + Abc_MaxInt( Abc_MaxInt(Level0, Level1), Level2 ); Gia_ObjSetLevel( p, pObj, Level ); } else { assert( !Gia_ObjIsMux(p, pObj) ); Level0 = Gia_ShowCollectObjs_rec( p, Gia_ObjFanin0(pObj), vAdds, vXors, vMapAdds, vMapXors, vOrder ); Level1 = Gia_ShowCollectObjs_rec( p, Gia_ObjFanin1(pObj), vAdds, vXors, vMapAdds, vMapXors, vOrder ); Level = 1 + Abc_MaxInt(Level0, Level1); Gia_ObjSetLevel( p, pObj, Level ); } Vec_IntPush( vOrder, Gia_ObjId(p, pObj) ); p->nLevels = Abc_MaxInt( p->nLevels, Level ); return Level; } Vec_Int_t * Gia_ShowCollectObjs( Gia_Man_t * p, Vec_Int_t * vAdds, Vec_Int_t * vXors, Vec_Int_t * vMapAdds, Vec_Int_t * vMapXors ) { Gia_Obj_t * pObj; int i; Vec_Int_t * vOrder = Vec_IntAlloc( 100 ); Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); p->nLevels = 0; Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent(p, Gia_ManConst0(p)); Gia_ManForEachCi( p, pObj, i ) Gia_ObjSetTravIdCurrent(p, pObj); Gia_ManForEachCo( p, pObj, i ) Gia_ShowCollectObjs_rec( p, Gia_ObjFanin0(pObj), vAdds, vXors, vMapAdds, vMapXors, vOrder ); return vOrder; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ShowProcess( Gia_Man_t * p, char * pFileName, Vec_Int_t * vBold, Vec_Int_t * vAdds, Vec_Int_t * vXors, int fFadds ) { Vec_Int_t * vMapAdds = Gia_ShowMapAdds( p, vAdds, fFadds, vBold ); Vec_Int_t * vMapXors = Gia_ShowMapXors( p, vXors ); Vec_Int_t * vOrder = Gia_ShowCollectObjs( p, vAdds, vXors, vMapAdds, vMapXors ); Gia_WriteDotAig( p, pFileName, vBold, vAdds, vXors, vMapAdds, vMapXors, vOrder ); Vec_IntFree( vMapAdds ); Vec_IntFree( vMapXors ); Vec_IntFree( vOrder ); } void Gia_ManShow( Gia_Man_t * pMan, Vec_Int_t * vBold, int fAdders, int fFadds, int fPath ) { 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; sprintf( FileNameDot, "%s", Extra_FileNameGenericAppend(pMan->pName ? pMan->pName : (char *)"unknown", ".dot") ); // check that the file can be opened if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) { fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); return; } fclose( pFile ); // generate the file if ( fPath ) Gia_ShowPath( pMan, FileNameDot ); else if ( fAdders ) Gia_ShowProcess( pMan, FileNameDot, vBold, vAdds, vXors, fFadds ); else Gia_WriteDotAigSimple( pMan, FileNameDot, vBold ); // visualize the file Abc_ShowFile( FileNameDot, 0 ); Vec_IntFreeP( &vAdds ); Vec_IntFreeP( &vXors ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaShrink.c000066400000000000000000000124661477524141600163630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaShrink.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Implementation of mapShrink based on ideas of Niklas Een.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaShrink.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "aig/aig/aig.h" #include "opt/dar/dar.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern int Dar_LibEvalBuild( Gia_Man_t * p, Vec_Int_t * vCut, unsigned uTruth, int fKeepLevel, Vec_Int_t * vLeavesBest ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs AIG shrinking using the current mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManMapShrink4( Gia_Man_t * p, int fKeepLevel, int fVerbose ) { Vec_Int_t * vLeaves, * vTruth, * vVisited, * vLeavesBest; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pFanin; unsigned * pTruth; int i, k, iFan; abctime clk = Abc_Clock(); // int ClassCounts[222] = {0}; int * pLutClass, Counter = 0; assert( Gia_ManHasMapping(p) ); if ( Gia_ManLutSizeMax( p ) > 4 ) { printf( "Resynthesis is not performed when nodes have more than 4 inputs.\n" ); return NULL; } pLutClass = ABC_CALLOC( int, Gia_ManObjNum(p) ); vLeaves = Vec_IntAlloc( 0 ); vTruth = Vec_IntAlloc( (1<<16) ); vVisited = Vec_IntAlloc( 0 ); vLeavesBest = Vec_IntAlloc( 4 ); // prepare the library Dar_LibPrepare( 5 ); // clean the old manager Gia_ManCleanTruth( p ); Gia_ManSetPhase( p ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; // start the new manager pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); Gia_ManCleanLevels( pNew, Gia_ManObjNum(p) ); Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsCi(pObj) ) { pObj->Value = Gia_ManAppendCi( pNew ); if ( p->vLevels ) Gia_ObjSetLevel( pNew, Gia_ObjFromLit(pNew, Gia_ObjValue(pObj)), Gia_ObjLevel(p, pObj) ); } else if ( Gia_ObjIsCo(pObj) ) { pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } else if ( Gia_ObjIsLut(p, i) ) { Counter++; // collect leaves of this gate Vec_IntClear( vLeaves ); Gia_LutForEachFanin( p, i, iFan, k ) Vec_IntPush( vLeaves, iFan ); for ( ; k < 4; k++ ) Vec_IntPush( vLeaves, 0 ); //.compute the truth table pTruth = Gia_ManConvertAigToTruth( p, pObj, vLeaves, vTruth, vVisited ); // change from node IDs to their literals Gia_ManForEachObjVec( vLeaves, p, pFanin, k ) { // assert( Gia_ObjValue(pFanin) != ~0 ); Vec_IntWriteEntry( vLeaves, k, Gia_ObjValue(pFanin) != ~0 ? Gia_ObjValue(pFanin) : 0 ); } // derive new structre if ( Gia_ManTruthIsConst0(pTruth, Vec_IntSize(vLeaves)) ) pObj->Value = 0; else if ( Gia_ManTruthIsConst1(pTruth, Vec_IntSize(vLeaves)) ) pObj->Value = 1; else { pObj->Value = Dar_LibEvalBuild( pNew, vLeaves, 0xffff & *pTruth, fKeepLevel, vLeavesBest ); pObj->Value = Abc_LitNotCond( pObj->Value, Gia_ObjPhaseRealLit(pNew, pObj->Value) ^ pObj->fPhase ); } } } // cleanup the AIG Gia_ManHashStop( pNew ); // check the presence of dangling nodes if ( Gia_ManHasDangling(pNew) ) { pNew = Gia_ManCleanup( pTemp = pNew ); if ( fVerbose && Gia_ManAndNum(pNew) != Gia_ManAndNum(pTemp) ) printf( "Gia_ManMapShrink4() node reduction after sweep %6d -> %6d.\n", Gia_ManAndNum(pTemp), Gia_ManAndNum(pNew) ); Gia_ManStop( pTemp ); } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); Vec_IntFree( vLeaves ); Vec_IntFree( vTruth ); Vec_IntFree( vVisited ); Vec_IntFree( vLeavesBest ); if ( fVerbose ) { printf( "Total gain in AIG nodes = %d. ", Gia_ManObjNum(p)-Gia_ManObjNum(pNew) ); ABC_PRT( "Total runtime", Abc_Clock() - clk ); } ABC_FREE( pLutClass ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaShrink6.c000066400000000000000000000414661477524141600164530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaShrink6.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Implementation of DAG-aware unmapping for 6-input cuts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaShrink6.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "bool/bdc/bdc.h" #include "bool/rsb/rsb.h" //#include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static word Truth[8] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF) }; // fanout structure typedef struct Shr_Fan_t_ Shr_Fan_t; struct Shr_Fan_t_ { int iFan; // fanout ID int Next; // next structure }; // operation manager typedef struct Shr_Man_t_ Shr_Man_t; struct Shr_Man_t_ { Gia_Man_t * pGia; // user's AIG Gia_Man_t * pNew; // constructed AIG int nDivMax; // max number of divisors int nNewSize; // max growth size // dynamic fanout (can only grow) Vec_Wrd_t * vFanMem; // fanout memory Vec_Int_t * vObj2Fan; // fanout Shr_Fan_t * pFanTemp; // temporary fanout // divisors Vec_Int_t * vDivs; // divisors Vec_Int_t * vPrio; // priority queue Vec_Int_t * vDivResub; // resubstitution Vec_Int_t * vLeaves; // cut leaves // truth tables Vec_Wrd_t * vTruths; // truth tables Vec_Wrd_t * vDivTruths; // truth tables // bidecomposition Rsb_Man_t * pManRsb; Bdc_Man_t * pManDec; Bdc_Par_t Pars; // statistics }; #define Shr_ObjForEachFanout( p, iNode, iFan ) \ for ( iFan = Shr_ManFanIterStart(p, iNode); iFan; iFan = Shr_ManFanIterNext(p) ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Shr_Man_t * Shr_ManAlloc( Gia_Man_t * pGia ) { Shr_Man_t * p; p = ABC_CALLOC( Shr_Man_t, 1 ); p->nDivMax = 64; p->nNewSize = 2 * Gia_ManObjNum(pGia); p->pGia = pGia; p->vFanMem = Vec_WrdAlloc( 1000 ); Vec_WrdPush(p->vFanMem, -1); p->vObj2Fan = Vec_IntStart( p->nNewSize ); p->vDivs = Vec_IntAlloc( 1000 ); p->vPrio = Vec_IntAlloc( 1000 ); p->vTruths = Vec_WrdStart( p->nNewSize ); p->vDivTruths = Vec_WrdAlloc( 100 ); p->vDivResub = Vec_IntAlloc( 6 ); p->vLeaves = Vec_IntAlloc( 6 ); // start new manager p->pNew = Gia_ManStart( p->nNewSize ); p->pNew->pName = Abc_UtilStrsav( pGia->pName ); p->pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); Gia_ManHashAlloc( p->pNew ); Gia_ManCleanLevels( p->pNew, p->nNewSize ); // allocate traversal IDs p->pNew->nObjs = p->nNewSize; Gia_ManIncrementTravId( p->pNew ); p->pNew->nObjs = 1; // start decompostion p->Pars.nVarsMax = 6; p->Pars.fVerbose = 0; p->pManDec = Bdc_ManAlloc( &p->Pars ); p->pManRsb = Rsb_ManAlloc( 6, p->nDivMax, 4, 1 ); return p; } Gia_Man_t * Shr_ManFree( Shr_Man_t * p ) { // prepare the manager Gia_Man_t * pTemp; Gia_ManHashStop( p->pNew ); Vec_IntFreeP( &p->pNew->vLevels ); if ( Gia_ManHasDangling(p->pNew) ) { p->pNew = Gia_ManCleanup( pTemp = p->pNew ); if ( Gia_ManAndNum(p->pNew) != Gia_ManAndNum(pTemp) ) printf( "Node reduction after sweep %6d -> %6d.\n", Gia_ManAndNum(pTemp), Gia_ManAndNum(p->pNew) ); Gia_ManStop( pTemp ); } Gia_ManSetRegNum( p->pNew, Gia_ManRegNum(p->pGia) ); pTemp = p->pNew; p->pNew = NULL; // free data structures Rsb_ManFree( p->pManRsb ); Bdc_ManFree( p->pManDec ); Gia_ManStopP( &p->pNew ); Vec_WrdFree( p->vFanMem ); Vec_IntFree( p->vObj2Fan ); Vec_IntFree( p->vDivs ); Vec_IntFree( p->vPrio ); Vec_WrdFree( p->vTruths ); Vec_WrdFree( p->vDivTruths ); Vec_IntFree( p->vDivResub ); Vec_IntFree( p->vLeaves ); ABC_FREE( p ); return pTemp; } /**Function************************************************************* Synopsis [Fanout manipulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Shr_ManAddFanout( Shr_Man_t * p, int iFanin, int iFanout ) { union { Shr_Fan_t sFan; word sWord; } FanStr; FanStr.sFan.iFan = iFanout; FanStr.sFan.Next = Vec_IntEntry(p->vObj2Fan, iFanin); Vec_IntWriteEntry( p->vObj2Fan, iFanin, Vec_WrdSize(p->vFanMem) ); Vec_WrdPush(p->vFanMem, FanStr.sWord ); } static inline int Shr_ManFanIterStart( Shr_Man_t * p, int iNode ) { if ( Vec_IntEntry(p->vObj2Fan, iNode) == 0 ) return 0; p->pFanTemp = (Shr_Fan_t *)Vec_WrdEntryP( p->vFanMem, Vec_IntEntry(p->vObj2Fan, iNode) ); return p->pFanTemp->iFan; } static inline int Shr_ManFanIterNext( Shr_Man_t * p ) { if ( p->pFanTemp->Next == 0 ) return 0; p->pFanTemp = (Shr_Fan_t *)Vec_WrdEntryP( p->vFanMem, p->pFanTemp->Next ); return p->pFanTemp->iFan; } /**Function************************************************************* Synopsis [Collect divisors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Shr_ManDivPushOrderByLevel( Shr_Man_t * p, int iDiv ) { int iPlace, * pArray; Vec_IntPush( p->vPrio, iDiv ); if ( Vec_IntSize(p->vPrio) == 1 ) return 0; pArray = Vec_IntArray(p->vPrio); for ( iPlace = Vec_IntSize(p->vPrio) - 1; iPlace > 0; iPlace-- ) if ( Gia_ObjLevel(p->pNew, Gia_ManObj(p->pNew, pArray[iPlace-1])) > Gia_ObjLevel(p->pNew, Gia_ManObj(p->pNew, pArray[iPlace])) ) ABC_SWAP( int, pArray[iPlace-1], pArray[iPlace] ) else break; return iPlace; // the place of the new divisor } static inline int Shr_ManCollectDivisors( Shr_Man_t * p, Vec_Int_t * vLeaves, int Limit, int nFanoutMax ) { Gia_Obj_t * pFan; int i, c, iDiv, iFan, iPlace; assert( Limit > 6 ); Vec_IntClear( p->vDivs ); Vec_IntClear( p->vPrio ); Gia_ManIncrementTravId( p->pNew ); Vec_IntForEachEntry( vLeaves, iDiv, i ) { Vec_IntPush( p->vDivs, iDiv ); Shr_ManDivPushOrderByLevel( p, iDiv ); Gia_ObjSetTravIdCurrentId( p->pNew, iDiv ); } Vec_IntForEachEntry( p->vPrio, iDiv, i ) { c = 0; assert( Gia_ObjIsTravIdCurrentId(p->pNew, iDiv) ); Shr_ObjForEachFanout( p, iDiv, iFan ) { if ( c++ == nFanoutMax ) break; if ( Gia_ObjIsTravIdCurrentId(p->pNew, iFan) ) continue; pFan = Gia_ManObj( p->pNew, iFan ); assert( Gia_ObjIsAnd(pFan) ); assert( Gia_ObjLevel(p->pNew, Gia_ManObj(p->pNew, iDiv)) < Gia_ObjLevel(p->pNew, pFan) ); if ( !Gia_ObjIsTravIdCurrentId(p->pNew, Gia_ObjFaninId0(pFan, iFan)) || !Gia_ObjIsTravIdCurrentId(p->pNew, Gia_ObjFaninId1(pFan, iFan)) ) continue; Vec_IntPush( p->vDivs, iFan ); Gia_ObjSetTravIdCurrentId( p->pNew, iFan ); iPlace = Shr_ManDivPushOrderByLevel( p, iFan ); assert( i < iPlace ); if ( Vec_IntSize(p->vDivs) == Limit ) return Vec_IntSize(p->vDivs); } } return Vec_IntSize(p->vDivs); } /**Function************************************************************* Synopsis [Resynthesizes nodes using bi-decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Shr_ObjPerformBidec( Shr_Man_t * p, Bdc_Man_t * pManDec, Gia_Man_t * pNew, Vec_Int_t * vLeafLits, word uTruth1, word uTruthC ) { Bdc_Fun_t * pFunc; Gia_Obj_t * pObj; int i, iVar, iLit, nNodes, iLast; int nVars = Vec_IntSize(vLeafLits); assert( uTruth1 != 0 && uTruthC != 0 ); Bdc_ManDecompose( pManDec, (unsigned *)&uTruth1, (unsigned *)&uTruthC, nVars, NULL, 1000 ); Bdc_FuncSetCopyInt( Bdc_ManFunc(pManDec, 0), 1 ); Vec_IntForEachEntry( vLeafLits, iVar, i ) Bdc_FuncSetCopyInt( Bdc_ManFunc(pManDec, i+1), Abc_Var2Lit(iVar, 0) ); nNodes = Bdc_ManNodeNum( pManDec ); for ( i = nVars + 1; i < nNodes; i++ ) { pFunc = Bdc_ManFunc( pManDec, i ); iLast = Gia_ManObjNum(pNew); iLit = Gia_ManHashAnd( pNew, Bdc_FunFanin0Copy(pFunc), Bdc_FunFanin1Copy(pFunc) ); Bdc_FuncSetCopyInt( pFunc, iLit ); if ( iLast == Gia_ManObjNum(pNew) ) continue; assert( iLast + 1 == Gia_ManObjNum(pNew) ); pObj = Gia_ManObj(pNew, Abc_Lit2Var(iLit)); Gia_ObjSetAndLevel( pNew, pObj ); Shr_ManAddFanout( p, Gia_ObjFaninId0p(pNew, pObj), Gia_ObjId(pNew, pObj) ); Shr_ManAddFanout( p, Gia_ObjFaninId1p(pNew, pObj), Gia_ObjId(pNew, pObj) ); assert( Gia_ManObjNum(pNew) < p->nNewSize ); } return Bdc_FunObjCopy( Bdc_ManRoot(pManDec) ); } /**Function************************************************************* Synopsis [Compute truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word Shr_ManComputeTruth6_rec( Gia_Man_t * p, int iNode, Vec_Wrd_t * vTruths ) { Gia_Obj_t * pObj; word Truth0, Truth1; if ( Gia_ObjIsTravIdCurrentId(p, iNode) ) return Vec_WrdEntry(vTruths, iNode); Gia_ObjSetTravIdCurrentId(p, iNode); pObj = Gia_ManObj( p, iNode ); assert( Gia_ObjIsAnd(pObj) ); Truth0 = Shr_ManComputeTruth6_rec( p, Gia_ObjFaninId0p(p, pObj), vTruths ); Truth1 = Shr_ManComputeTruth6_rec( p, Gia_ObjFaninId1p(p, pObj), vTruths ); if ( Gia_ObjFaninC0(pObj) ) Truth0 = ~Truth0; if ( Gia_ObjFaninC1(pObj) ) Truth1 = ~Truth1; Vec_WrdWriteEntry( vTruths, iNode, Truth0 & Truth1 ); return Truth0 & Truth1; } word Shr_ManComputeTruth6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, Vec_Wrd_t * vTruths ) { int i, iLeaf; assert( Gia_ObjIsAnd(pObj) ); Gia_ManIncrementTravId( p ); Vec_IntForEachEntry( vLeaves, iLeaf, i ) { Gia_ObjSetTravIdCurrentId( p, iLeaf ); Vec_WrdWriteEntry( vTruths, iLeaf, Truth[i] ); } return Shr_ManComputeTruth6_rec( p, Gia_ObjId(p, pObj), vTruths ); } /**Function************************************************************* Synopsis [Compute truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Shr_ManComputeTruths( Gia_Man_t * p, int nVars, Vec_Int_t * vDivs, Vec_Wrd_t * vDivTruths, Vec_Wrd_t * vTruths ) { Gia_Obj_t * pObj; word Truth0, Truth1;//, Truthh; int i, iDiv; Vec_WrdClear( vDivTruths ); Vec_IntForEachEntryStop( vDivs, iDiv, i, nVars ) { Vec_WrdWriteEntry( vTruths, iDiv, Truth[i] ); Vec_WrdPush( vDivTruths, Truth[i] ); } Vec_IntForEachEntryStart( vDivs, iDiv, i, nVars ) { pObj = Gia_ManObj( p, iDiv ); Truth0 = Vec_WrdEntry( vTruths, Gia_ObjFaninId0(pObj, iDiv) ); Truth1 = Vec_WrdEntry( vTruths, Gia_ObjFaninId1(pObj, iDiv) ); if ( Gia_ObjFaninC0(pObj) ) Truth0 = ~Truth0; if ( Gia_ObjFaninC1(pObj) ) Truth1 = ~Truth1; Vec_WrdWriteEntry( vTruths, iDiv, Truth0 & Truth1 ); Vec_WrdPush( vDivTruths, Truth0 & Truth1 ); // Truthh = Truth0 & Truth1; // Abc_TtPrintBinary( &Truthh, nVars ); //printf( "\n" ); // Kit_DsdPrintFromTruth( &Truthh, nVars ); printf( "\n" ); } // printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManMapShrink6( Gia_Man_t * p, int nFanoutMax, int fKeepLevel, int fVerbose ) { Shr_Man_t * pMan; Gia_Obj_t * pObj, * pFanin; word uTruth, uTruth0, uTruth1; int i, k, nDivs, iNode; int RetValue, Counter1 = 0, Counter2 = 0; abctime clk2, clk = Abc_Clock(); abctime timeFanout = 0; assert( Gia_ManHasMapping(p) ); pMan = Shr_ManAlloc( p ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsCi(pObj) ) { pObj->Value = Gia_ManAppendCi( pMan->pNew ); if ( p->vLevels ) Gia_ObjSetLevel( pMan->pNew, Gia_ObjFromLit(pMan->pNew, Gia_ObjValue(pObj)), Gia_ObjLevel(p, pObj) ); } else if ( Gia_ObjIsCo(pObj) ) { pObj->Value = Gia_ManAppendCo( pMan->pNew, Gia_ObjFanin0Copy(pObj) ); } else if ( Gia_ObjIsLut(p, i) ) { // collect leaves of this gate Vec_IntClear( pMan->vLeaves ); Gia_LutForEachFanin( p, i, iNode, k ) Vec_IntPush( pMan->vLeaves, iNode ); assert( Vec_IntSize(pMan->vLeaves) <= 6 ); // compute truth table uTruth = Shr_ManComputeTruth6( pMan->pGia, pObj, pMan->vLeaves, pMan->vTruths ); assert( pObj->Value == ~0 ); if ( uTruth == 0 || ~uTruth == 0 ) pObj->Value = Abc_LitNotCond( 0, ~uTruth == 0 ); else Gia_ManForEachObjVec( pMan->vLeaves, p, pFanin, k ) if ( uTruth == Truth[k] || ~uTruth == Truth[k] ) pObj->Value = Abc_LitNotCond( pFanin->Value, ~uTruth == Truth[k] ); if ( pObj->Value != ~0 ) continue; // translate into new nodes Gia_ManForEachObjVec( pMan->vLeaves, p, pFanin, k ) { if ( Abc_LitIsCompl(pFanin->Value) ) uTruth = ((uTruth & Truth[k]) >> (1 << k)) | ((uTruth & ~Truth[k]) << (1 << k)); Vec_IntWriteEntry( pMan->vLeaves, k, Abc_Lit2Var(pFanin->Value) ); } // compute divisors clk2 = Abc_Clock(); nDivs = Shr_ManCollectDivisors( pMan, pMan->vLeaves, pMan->nDivMax, nFanoutMax ); assert( nDivs <= pMan->nDivMax ); timeFanout += Abc_Clock() - clk2; // compute truth tables Shr_ManComputeTruths( pMan->pNew, Vec_IntSize(pMan->vLeaves), pMan->vDivs, pMan->vDivTruths, pMan->vTruths ); // perform resubstitution RetValue = Rsb_ManPerformResub6( pMan->pManRsb, Vec_IntSize(pMan->vLeaves), uTruth, pMan->vDivTruths, &uTruth0, &uTruth1, 0 ); if ( RetValue ) // resub exists { Vec_Int_t * vResult = Rsb_ManGetFanins(pMan->pManRsb); Vec_IntClear( pMan->vDivResub ); Vec_IntForEachEntry( vResult, iNode, k ) Vec_IntPush( pMan->vDivResub, Vec_IntEntry(pMan->vDivs, iNode) ); pObj->Value = Shr_ObjPerformBidec( pMan, pMan->pManDec, pMan->pNew, pMan->vDivResub, uTruth1, uTruth0 | uTruth1 ); Counter1++; } else { pObj->Value = Shr_ObjPerformBidec( pMan, pMan->pManDec, pMan->pNew, pMan->vLeaves, uTruth, ~(word)0 ); Counter2++; } } } if ( fVerbose ) { printf( "Performed %d resubs and %d decomps. ", Counter1, Counter2 ); printf( "Gain in AIG nodes = %d. ", Gia_ManObjNum(p)-Gia_ManObjNum(pMan->pNew) ); ABC_PRT( "Runtime", Abc_Clock() - clk ); // ABC_PRT( "Divisors", timeFanout ); } return Shr_ManFree( pMan ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaShrink7.c000066400000000000000000000307161477524141600164500ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaShrink7.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Implementation of DAG-aware unmapping for 6-input cuts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaShrink6.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/vec/vecHash.h" #include "misc/util/utilTruth.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // operation manager typedef struct Unm_Man_t_ Unm_Man_t; struct Unm_Man_t_ { Gia_Man_t * pGia; // user's AIG Gia_Man_t * pNew; // constructed AIG Hash_IntMan_t * pHash; // hash table int nNewSize; // expected size of new manager Vec_Int_t * vUsed; // used nodes Vec_Int_t * vId2Used; // mapping of obj IDs into used node IDs Vec_Wrd_t * vTruths; // truth tables Vec_Int_t * vLeaves; // temporary storage for leaves abctime clkStart; // starting the clock }; extern word Shr_ManComputeTruth6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, Vec_Wrd_t * vTruths ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Unm_Man_t * Unm_ManAlloc( Gia_Man_t * pGia ) { Unm_Man_t * p; p = ABC_CALLOC( Unm_Man_t, 1 ); p->clkStart = Abc_Clock(); p->nNewSize = 3 * Gia_ManObjNum(pGia) / 2; p->pGia = pGia; p->pNew = Gia_ManStart( p->nNewSize ); p->pNew->pName = Abc_UtilStrsav( pGia->pName ); p->pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); Gia_ManHashAlloc( p->pNew ); Gia_ManCleanLevels( p->pNew, p->nNewSize ); // allocate traversal IDs p->pNew->nObjs = p->nNewSize; Gia_ManIncrementTravId( p->pNew ); p->pNew->nObjs = 1; // start hashing p->pHash = Hash_IntManStart( 1000 ); // truth tables p->vLeaves = Vec_IntStart( 10 ); return p; } Gia_Man_t * Unm_ManFree( Unm_Man_t * p ) { Gia_Man_t * pTemp = p->pNew; p->pNew = NULL; Gia_ManHashStop( pTemp ); Vec_IntFreeP( &pTemp->vLevels ); Gia_ManSetRegNum( pTemp, Gia_ManRegNum(p->pGia) ); // truth tables Vec_WrdFreeP( &p->vTruths ); Vec_IntFreeP( &p->vLeaves ); Vec_IntFreeP( &p->vUsed ); Vec_IntFreeP( &p->vId2Used ); // free data structures Hash_IntManStop( p->pHash ); ABC_FREE( p ); Gia_ManStop( pTemp ); pTemp = NULL; return pTemp; } /**Function************************************************************* Synopsis [Computes information about node pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Unm_ManPrintPairStats( Hash_IntMan_t * pHash, int nTotal0, int nPairs0, int nPairs1, int fUseLit ) { int i, Num, nRefs, nPairs = 0, nTotal = 0, Counter[21] = {0}; Num = Hash_IntManEntryNum( pHash ); for ( i = 1; i <= Num; i++ ) { nRefs = Abc_MinInt( 20, Hash_IntObjData2(pHash, i) ); nTotal += nRefs; Counter[nRefs]++; nPairs += (nRefs > 1); /* if ( fUseLit ) printf( "(%c%c, %c%c) %d\n", Abc_LitIsCompl(Hash_IntObjData0(pHash, i)-2) ? '!' : ' ', 'a' + Abc_Lit2Var(Hash_IntObjData0(pHash, i)-2), Abc_LitIsCompl(Hash_IntObjData1(pHash, i)-2) ? '!' : ' ', 'a' + Abc_Lit2Var(Hash_IntObjData1(pHash, i)-2), nRefs ); else printf( "( %c, %c) %d\n", 'a' + Hash_IntObjData0(pHash, i)-1, 'a' + Hash_IntObjData1(pHash, i)-1, nRefs ); */ // printf( "(%4d, %4d) %d\n", Hash_IntObjData0(pHash, i), Hash_IntObjData1(pHash, i), nRefs ); } printf( "Statistics for pairs appearing less than 20 times:\n" ); for ( i = 0; i < 21; i++ ) if ( Counter[i] > 0 ) printf( "%3d : %7d %7.2f %%\n", i, Counter[i], 100.0 * Counter[i] * i / Abc_MaxInt(nTotal, 1) ); printf( "Pairs: Total = %8d Init = %8d %7.2f %% Final = %8d %7.2f %% Real = %8d %7.2f %%\n", nTotal0, nPairs0, 100.0 * nPairs0 / Abc_MaxInt(nTotal0, 1), nPairs, 100.0 * nPairs / Abc_MaxInt(nTotal0, 1), nPairs1, 100.0 * nPairs1 / Abc_MaxInt(nTotal0, 1) ); return nPairs; } Vec_Int_t * Unm_ManComputePairs( Unm_Man_t * p, int fVerbose ) { Gia_Obj_t * pObj; Vec_Int_t * vPairs = Vec_IntAlloc( 1000 ); Vec_Int_t * vNum2Obj = Vec_IntStart( 1 ); Hash_IntMan_t * pHash = Hash_IntManStart( 1000 ); int nTotal = 0, nPairs0 = 0, nPairs = 0; int i, k, j, FanK, FanJ, Num, nRefs; Gia_ManSetRefsMapped( p->pGia ); Gia_ManForEachLut( p->pGia, i ) { nTotal += Gia_ObjLutSize(p->pGia, i) * (Gia_ObjLutSize(p->pGia, i) - 1) / 2; pObj = Gia_ManObj( p->pGia, i ); // collect leaves of this gate Vec_IntClear( p->vLeaves ); Gia_LutForEachFanin( p->pGia, i, Num, k ) if ( Gia_ObjRefNumId(p->pGia, Num) > 1 ) Vec_IntPush( p->vLeaves, Num ); if ( Vec_IntSize(p->vLeaves) < 2 ) continue; nPairs0 += Vec_IntSize(p->vLeaves) * (Vec_IntSize(p->vLeaves) - 1) / 2; // enumerate pairs Vec_IntForEachEntry( p->vLeaves, FanK, k ) Vec_IntForEachEntryStart( p->vLeaves, FanJ, j, k+1 ) { if ( FanK > FanJ ) ABC_SWAP( int, FanK, FanJ ); Num = Hash_Int2ManInsert( pHash, FanK, FanJ, 0 ); nRefs = Hash_Int2ObjInc(pHash, Num); if ( nRefs == 0 ) { assert( Num == Hash_IntManEntryNum(pHash) ); assert( Num == Vec_IntSize(vNum2Obj) ); Vec_IntPush( vNum2Obj, i ); continue; } if ( nRefs == 1 ) { assert( Num < Vec_IntSize(vNum2Obj) ); Vec_IntPush( vPairs, Vec_IntEntry(vNum2Obj, Num) ); Vec_IntPush( vPairs, FanK ); Vec_IntPush( vPairs, FanJ); } Vec_IntPush( vPairs, i ); Vec_IntPush( vPairs, FanK ); Vec_IntPush( vPairs, FanJ ); } } Vec_IntFree( vNum2Obj ); if ( fVerbose ) nPairs = Unm_ManPrintPairStats( pHash, nTotal, nPairs0, Vec_IntSize(vPairs) / 3, 0 ); Hash_IntManStop( pHash ); return vPairs; } // finds used nodes Vec_Int_t * Unm_ManFindUsedNodes( Vec_Int_t * vPairs, int nObjs ) { Vec_Int_t * vNodes = Vec_IntAlloc( 1000 ); Vec_Str_t * vMarks = Vec_StrStart( nObjs ); int i; for ( i = 0; i < Vec_IntSize(vPairs); i += 3 ) Vec_StrWriteEntry( vMarks, Vec_IntEntry(vPairs, i), 1 ); for ( i = 0; i < nObjs; i++ ) if ( Vec_StrEntry( vMarks, i ) ) Vec_IntPush( vNodes, i ); Vec_StrFree( vMarks ); printf( "The number of used nodes = %d\n", Vec_IntSize(vNodes) ); return vNodes; } // computes truth table for selected nodes Vec_Wrd_t * Unm_ManComputeTruths( Unm_Man_t * p ) { Vec_Wrd_t * vTruthsTemp, * vTruths; int i, k, iObj, iNode; word uTruth; vTruths = Vec_WrdAlloc( Vec_IntSize(p->vUsed) ); vTruthsTemp = Vec_WrdStart( Gia_ManObjNum(p->pGia) ); Vec_IntForEachEntry( p->vUsed, iObj, i ) { assert( Gia_ObjIsLut(p->pGia, iObj) ); // collect leaves of this gate Vec_IntClear( p->vLeaves ); Gia_LutForEachFanin( p->pGia, iObj, iNode, k ) Vec_IntPush( p->vLeaves, iNode ); assert( Vec_IntSize(p->vLeaves) <= 6 ); // compute truth table uTruth = Shr_ManComputeTruth6( p->pGia, Gia_ManObj(p->pGia, iObj), p->vLeaves, vTruthsTemp ); Vec_WrdPush( vTruths, uTruth ); // if ( i % 100 == 0 ) // Kit_DsdPrintFromTruth( (unsigned *)&uTruth, 6 ), printf( "\n" ); } Vec_WrdFreeP( &vTruthsTemp ); return vTruths; } /**Function************************************************************* Synopsis [Collects decomposable pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Unm_ManCollectDecomp( Unm_Man_t * p, Vec_Int_t * vPairs, int fVerbose ) { word uTruth; int nNonUnique = 0; int i, k, j, s, iObj, iNode, iUsed, FanK, FanJ, Res, Num, nRefs; Vec_Int_t * vNum2Obj = Vec_IntStart( 1 ); Vec_Int_t * vPairs2 = Vec_IntAlloc( 1000 ); assert( Hash_IntManEntryNum(p->pHash) == 0 ); for ( i = 0; i < Vec_IntSize(vPairs); i += 3 ) { iObj = Vec_IntEntry( vPairs, i ); assert( Gia_ObjIsLut(p->pGia, iObj) ); // collect leaves of this gate Vec_IntClear( p->vLeaves ); Gia_LutForEachFanin( p->pGia, iObj, iNode, s ) Vec_IntPush( p->vLeaves, iNode ); assert( Vec_IntSize(p->vLeaves) <= 6 ); FanK = Vec_IntEntry(vPairs, i+1); FanJ = Vec_IntEntry(vPairs, i+2); k = Vec_IntFind( p->vLeaves, FanK ); j = Vec_IntFind( p->vLeaves, FanJ ); assert( FanK < FanJ ); iUsed = Vec_IntEntry( p->vId2Used, iObj ); uTruth = Vec_WrdEntry( p->vTruths, iUsed ); Res = Abc_TtCheckDsdAnd( uTruth, k, j, NULL ); if ( Res == -1 ) continue; // derive literals FanK = Abc_Var2Lit( FanK, ((Res >> 0) & 1) ); FanJ = Abc_Var2Lit( FanJ, ((Res >> 1) & 1) ); if ( Res == 4 ) ABC_SWAP( int, FanK, FanJ ); Num = Hash_Int2ManInsert( p->pHash, FanK, FanJ, 0 ); nRefs = Hash_Int2ObjInc(p->pHash, Num); if ( nRefs == 0 ) { assert( Num == Hash_IntManEntryNum(p->pHash) ); assert( Num == Vec_IntSize(vNum2Obj) ); Vec_IntPush( vNum2Obj, iObj ); continue; } if ( nRefs == 1 ) { assert( Num < Vec_IntSize(vNum2Obj) ); Vec_IntPush( vPairs2, Vec_IntEntry(vNum2Obj, Num) ); Vec_IntPush( vPairs2, FanK ); Vec_IntPush( vPairs2, FanJ ); nNonUnique++; } Vec_IntPush( vPairs2, iObj ); Vec_IntPush( vPairs2, FanK ); Vec_IntPush( vPairs2, FanJ ); } Vec_IntFree( vNum2Obj ); if ( fVerbose ) Unm_ManPrintPairStats( p->pHash, Vec_IntSize(vPairs)/3, Hash_IntManEntryNum(p->pHash), Vec_IntSize(vPairs2)/3, 1 ); // Hash_IntManStop( pHash ); return vPairs2; } /**Function************************************************************* Synopsis [Compute truth tables for the selected nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Unm_ManWork( Unm_Man_t * p ) { Vec_Int_t * vPairs, * vPairs2; // find the duplicated pairs vPairs = Unm_ManComputePairs( p, 1 ); // find the used nodes p->vUsed = Unm_ManFindUsedNodes( vPairs, Gia_ManObjNum(p->pGia) ); p->vId2Used = Vec_IntInvert( p->vUsed, -1 ); Vec_IntFillExtra( p->vId2Used, Gia_ManObjNum(p->pGia), -1 ); // compute truth tables for used nodes p->vTruths = Unm_ManComputeTruths( p ); // derive new pairs vPairs2 = Unm_ManCollectDecomp( p, vPairs, 1 ); Vec_IntFreeP( &vPairs ); Vec_IntFreeP( &vPairs2 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Unm_ManTest( Gia_Man_t * pGia ) { Unm_Man_t * p; p = Unm_ManAlloc( pGia ); Unm_ManWork( p ); Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); return Unm_ManFree( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSif.c000066400000000000000000000627761477524141600156570ustar00rootroot00000000000000/**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, Stop, 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 ); if ( p->vStopsF ) Vec_StrForEachEntry( p->vStopsF, Stop, i ) if ( Stop ) Vec_IntWriteEntry( vTimes, i, 0 ); 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; if ( p->vStopsB ) Vec_StrForEachEntry( p->vStopsB, Stop, i ) if ( Stop && Vec_IntEntry(vTimes, i) > 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 ); //Gia_ManTransferTiming( pNew, p ); if ( p->vNamesIn ) { char * pName; int i; pNew->vNamesIn = p->vNamesIn; p->vNamesIn = NULL; Vec_PtrForEachEntryStart( char *, pNew->vNamesIn, pName, i, Gia_ManPiNum(pNew) ) ABC_FREE( pName ); Vec_PtrShrink( pNew->vNamesIn, Gia_ManPiNum(pNew) ); for ( i = 0; i < Gia_ManRegNum(pNew); i++ ) Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsavNum("_fo", i) ); } if ( p->vNamesOut ) { char * pName; int i; pNew->vNamesOut = p->vNamesOut; p->vNamesOut = NULL; Vec_PtrForEachEntryStart( char *, pNew->vNamesOut, pName, i, Gia_ManPoNum(pNew) ) ABC_FREE( pName ); Vec_PtrShrink( pNew->vNamesOut, Gia_ManPoNum(pNew) ); for ( i = 0; i < Gia_ManRegNum(pNew); i++ ) Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsavNum("_fi", i) ); } return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSim.c000066400000000000000000001265561477524141600156630ustar00rootroot00000000000000/**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" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline unsigned * Gia_SimData( Gia_ManSim_t * p, int i ) { return p->pDataSim + i * p->nWords; } static inline unsigned * Gia_SimDataCi( Gia_ManSim_t * p, int i ) { return p->pDataSimCis + i * p->nWords; } static inline unsigned * Gia_SimDataCo( Gia_ManSim_t * p, int i ) { return p->pDataSimCos + i * p->nWords; } unsigned * Gia_SimDataExt( Gia_ManSim_t * p, int i ) { return Gia_SimData(p, i); } unsigned * Gia_SimDataCiExt( Gia_ManSim_t * p, int i ) { return Gia_SimDataCi(p, i); } unsigned * Gia_SimDataCoExt( Gia_ManSim_t * p, int i ) { return Gia_SimDataCo(p, i); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSimCollect_rec( Gia_Man_t * pGia, Gia_Obj_t * pObj, Vec_Int_t * vVec ) { Vec_IntPush( vVec, Gia_ObjToLit(pGia, pObj) ); if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManSimCollect_rec( pGia, Gia_ObjChild0(pObj), vVec ); Gia_ManSimCollect_rec( pGia, Gia_ObjChild1(pObj), vVec ); } /**Function************************************************************* Synopsis [Derives signal implications.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSimCollect( Gia_Man_t * pGia, Gia_Obj_t * pObj, Vec_Int_t * vVec ) { Vec_IntClear( vVec ); Gia_ManSimCollect_rec( pGia, pObj, vVec ); Vec_IntUniqify( vVec ); } /**Function************************************************************* Synopsis [Finds signals, which reset flops to have constant values.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManSimDeriveResets( Gia_Man_t * pGia ) { int nImpLimit = 5; Vec_Int_t * vResult; Vec_Int_t * vCountLits, * vSuperGate; Gia_Obj_t * pObj; int i, k, Lit, Count; int Counter0 = 0, Counter1 = 0; int CounterPi0 = 0, CounterPi1 = 0; abctime clk = Abc_Clock(); // create reset counters for each literal vCountLits = Vec_IntStart( 2 * Gia_ManObjNum(pGia) ); // collect implications for each flop input driver vSuperGate = Vec_IntAlloc( 1000 ); Gia_ManForEachRi( pGia, pObj, i ) { if ( Gia_ObjFaninId0p(pGia, pObj) == 0 ) continue; Vec_IntAddToEntry( vCountLits, Gia_ObjToLit(pGia, Gia_ObjChild0(pObj)), 1 ); Gia_ManSimCollect( pGia, Gia_ObjFanin0(pObj), vSuperGate ); Vec_IntForEachEntry( vSuperGate, Lit, k ) Vec_IntAddToEntry( vCountLits, Lit, 1 ); } Vec_IntFree( vSuperGate ); // label signals whose counter if more than the limit vResult = Vec_IntStartFull( Gia_ManObjNum(pGia) ); Vec_IntForEachEntry( vCountLits, Count, Lit ) { if ( Count < nImpLimit ) continue; pObj = Gia_ManObj( pGia, Abc_Lit2Var(Lit) ); if ( Abc_LitIsCompl(Lit) ) // const 0 { // Ssm_ObjSetLogic0( pObj ); Vec_IntWriteEntry( vResult, Abc_Lit2Var(Lit), 0 ); CounterPi0 += Gia_ObjIsPi(pGia, pObj); Counter0++; } else { // Ssm_ObjSetLogic1( pObj ); Vec_IntWriteEntry( vResult, Abc_Lit2Var(Lit), 1 ); CounterPi1 += Gia_ObjIsPi(pGia, pObj); Counter1++; } // if ( Gia_ObjIsPi(pGia, pObj) ) // printf( "%d ", Count ); } // printf( "\n" ); Vec_IntFree( vCountLits ); printf( "Logic0 = %d (%d). Logic1 = %d (%d). ", Counter0, CounterPi0, Counter1, CounterPi1 ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return vResult; } /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSimSetDefaultParams( Gia_ParSim_t * p ) { memset( p, 0, sizeof(Gia_ParSim_t) ); // user-controlled parameters p->nWords = 8; // the number of machine words p->nIters = 32; // the number of timeframes p->RandSeed = 0; // the seed to generate random numbers p->TimeLimit = 60; // time limit in seconds p->fCheckMiter = 0; // check if miter outputs are non-zero p->fVerbose = 0; // enables verbose output p->iOutFail = -1; // index of the failed output } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSimDelete( Gia_ManSim_t * p ) { Vec_IntFreeP( &p->vConsts ); Vec_IntFreeP( &p->vCis2Ids ); Gia_ManStopP( &p->pAig ); ABC_FREE( p->pDataSim ); ABC_FREE( p->pDataSimCis ); ABC_FREE( p->pDataSimCos ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates fast simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_ManSim_t * Gia_ManSimCreate( Gia_Man_t * pAig, Gia_ParSim_t * pPars ) { Gia_ManSim_t * p; int Entry, i; p = ABC_ALLOC( Gia_ManSim_t, 1 ); memset( p, 0, sizeof(Gia_ManSim_t) ); // look for reset signals if ( pPars->fVerbose ) p->vConsts = Gia_ManSimDeriveResets( pAig ); // derive the frontier p->pAig = Gia_ManFront( pAig ); p->pPars = pPars; p->nWords = pPars->nWords; p->pDataSim = ABC_ALLOC( unsigned, p->nWords * p->pAig->nFront ); p->pDataSimCis = ABC_ALLOC( unsigned, p->nWords * Gia_ManCiNum(p->pAig) ); p->pDataSimCos = ABC_ALLOC( unsigned, p->nWords * Gia_ManCoNum(p->pAig) ); if ( !p->pDataSim || !p->pDataSimCis || !p->pDataSimCos ) { Abc_Print( 1, "Simulator could not allocate %.2f GB for simulation info.\n", 4.0 * p->nWords * (p->pAig->nFront + Gia_ManCiNum(p->pAig) + Gia_ManCoNum(p->pAig)) / (1<<30) ); Gia_ManSimDelete( p ); return NULL; } p->vCis2Ids = Vec_IntAlloc( Gia_ManCiNum(p->pAig) ); Vec_IntForEachEntry( pAig->vCis, Entry, i ) Vec_IntPush( p->vCis2Ids, i ); // do we need p->vCis2Ids? if ( pPars->fVerbose ) Abc_Print( 1, "AIG = %7.2f MB. Front mem = %7.2f MB. Other mem = %7.2f MB.\n", 12.0*Gia_ManObjNum(p->pAig)/(1<<20), 4.0*p->nWords*p->pAig->nFront/(1<<20), 4.0*p->nWords*(Gia_ManCiNum(p->pAig) + Gia_ManCoNum(p->pAig))/(1<<20) ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSimInfoRandom( Gia_ManSim_t * p, unsigned * pInfo ) { int w; for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = Gia_ManRandom( 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSimInfoZero( Gia_ManSim_t * p, unsigned * pInfo ) { int w; for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = 0; } /**Function************************************************************* Synopsis [Returns index of the first pattern that failed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManSimInfoIsZero( Gia_ManSim_t * p, unsigned * pInfo ) { int w; for ( w = 0; w < p->nWords; w++ ) if ( pInfo[w] ) return 32*w + Gia_WordFindFirstBit( pInfo[w] ); return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSimInfoOne( Gia_ManSim_t * p, unsigned * pInfo ) { int w; for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = ~0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSimInfoCopy( Gia_ManSim_t * p, unsigned * pInfo, unsigned * pInfo0 ) { int w; for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSimulateCi( Gia_ManSim_t * p, Gia_Obj_t * pObj, int iCi ) { unsigned * pInfo = Gia_SimData( p, Gia_ObjValue(pObj) ); unsigned * pInfo0 = Gia_SimDataCi( p, iCi ); int w; for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSimulateCo( Gia_ManSim_t * p, int iCo, Gia_Obj_t * pObj ) { unsigned * pInfo = Gia_SimDataCo( p, iCo ); unsigned * pInfo0 = Gia_SimData( p, Gia_ObjDiff0(pObj) ); int w; if ( Gia_ObjFaninC0(pObj) ) for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = ~pInfo0[w]; else for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSimulateNode( Gia_ManSim_t * p, Gia_Obj_t * pObj ) { unsigned * pInfo = Gia_SimData( p, Gia_ObjValue(pObj) ); unsigned * pInfo0 = Gia_SimData( p, Gia_ObjDiff0(pObj) ); unsigned * pInfo1 = Gia_SimData( p, Gia_ObjDiff1(pObj) ); int w; if ( Gia_ObjFaninC0(pObj) ) { if ( Gia_ObjFaninC1(pObj) ) for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = ~(pInfo0[w] | pInfo1[w]); else for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = ~pInfo0[w] & pInfo1[w]; } else { if ( Gia_ObjFaninC1(pObj) ) for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w] & ~pInfo1[w]; else for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w] & pInfo1[w]; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSimInfoInit( Gia_ManSim_t * p ) { int iPioNum, i; Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) { if ( iPioNum < Gia_ManPiNum(p->pAig) ) Gia_ManSimInfoRandom( p, Gia_SimDataCi(p, i) ); else Gia_ManSimInfoZero( p, Gia_SimDataCi(p, i) ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSimInfoTransfer( Gia_ManSim_t * p ) { int iPioNum, i; Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) { if ( iPioNum < Gia_ManPiNum(p->pAig) ) Gia_ManSimInfoRandom( p, Gia_SimDataCi(p, i) ); else Gia_ManSimInfoCopy( p, Gia_SimDataCi(p, i), Gia_SimDataCo(p, Gia_ManPoNum(p->pAig)+iPioNum-Gia_ManPiNum(p->pAig)) ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSimulateRound( Gia_ManSim_t * p ) { Gia_Obj_t * pObj; int i, iCis = 0, iCos = 0; assert( p->pAig->nFront > 0 ); assert( Gia_ManConst0(p->pAig)->Value == 0 ); Gia_ManSimInfoZero( p, Gia_SimData(p, 0) ); Gia_ManForEachObj1( p->pAig, pObj, i ) { if ( Gia_ObjIsAndOrConst0(pObj) ) { assert( Gia_ObjValue(pObj) < p->pAig->nFront ); Gia_ManSimulateNode( p, pObj ); } else if ( Gia_ObjIsCo(pObj) ) { assert( Gia_ObjValue(pObj) == GIA_NONE ); Gia_ManSimulateCo( p, iCos++, pObj ); } else // if ( Gia_ObjIsCi(pObj) ) { assert( Gia_ObjValue(pObj) < p->pAig->nFront ); Gia_ManSimulateCi( p, pObj, iCis++ ); } } assert( Gia_ManCiNum(p->pAig) == iCis ); assert( Gia_ManCoNum(p->pAig) == iCos ); } /**Function************************************************************* Synopsis [Returns index of the PO and pattern that failed it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManCheckPos( Gia_ManSim_t * p, int * piPo, int * piPat ) { int i, iPat; for ( i = 0; i < Gia_ManPoNum(p->pAig); i++ ) { iPat = Gia_ManSimInfoIsZero( p, Gia_SimDataCo(p, i) ); if ( iPat >= 0 ) { *piPo = i; *piPat = iPat; return 1; } } return 0; } /**Function************************************************************* Synopsis [Returns the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Gia_ManGenerateCounter( Gia_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat, Vec_Int_t * vCis2Ids ) { Abc_Cex_t * p; unsigned * pData; int f, i, w, iPioId, Counter; p = Abc_CexAlloc( Gia_ManRegNum(pAig), Gia_ManPiNum(pAig), iFrame+1 ); p->iFrame = iFrame; p->iPo = iOut; // fill in the binary data Counter = p->nRegs; pData = ABC_ALLOC( unsigned, nWords ); for ( f = 0; f <= iFrame; f++, Counter += p->nPis ) for ( i = 0; i < Gia_ManPiNum(pAig); i++ ) { iPioId = Vec_IntEntry( vCis2Ids, i ); if ( iPioId >= p->nPis ) continue; for ( w = nWords-1; w >= 0; w-- ) pData[w] = Gia_ManRandom( 0 ); if ( Abc_InfoHasBit( pData, iPat ) ) Abc_InfoSetBit( p->pData, Counter + iPioId ); } ABC_FREE( pData ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManResetRandom( Gia_ParSim_t * pPars ) { int i; Gia_ManRandom( 1 ); for ( i = 0; i < pPars->RandSeed; i++ ) Gia_ManRandom( 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSimSimulate( Gia_Man_t * pAig, Gia_ParSim_t * pPars ) { extern int Gia_ManSimSimulateEquiv( Gia_Man_t * pAig, Gia_ParSim_t * pPars ); Gia_ManSim_t * p; abctime clkTotal = Abc_Clock(); int i, iOut, iPat, RetValue = 0; abctime nTimeToStop = pPars->TimeLimit ? pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; if ( pAig->pReprs && pAig->pNexts ) return Gia_ManSimSimulateEquiv( pAig, pPars ); ABC_FREE( pAig->pCexSeq ); p = Gia_ManSimCreate( pAig, pPars ); Gia_ManResetRandom( pPars ); Gia_ManSimInfoInit( p ); for ( i = 0; i < pPars->nIters; i++ ) { Gia_ManSimulateRound( p ); if ( pPars->fVerbose ) { Abc_Print( 1, "Frame %4d out of %4d and timeout %3d sec. ", i+1, pPars->nIters, pPars->TimeLimit ); Abc_Print( 1, "Time = %7.2f sec\r", (1.0*Abc_Clock()-clkTotal)/CLOCKS_PER_SEC ); } if ( pPars->fCheckMiter && Gia_ManCheckPos( p, &iOut, &iPat ) ) { Gia_ManResetRandom( pPars ); pPars->iOutFail = iOut; pAig->pCexSeq = Gia_ManGenerateCounter( pAig, i, iOut, p->nWords, iPat, p->vCis2Ids ); Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", iOut, pAig->pName, i ); if ( !Gia_ManVerifyCex( pAig, pAig->pCexSeq, 0 ) ) { // Abc_Print( 1, "\n" ); Abc_Print( 1, "\nGenerated counter-example is INVALID. " ); // Abc_Print( 1, "\n" ); } else { // Abc_Print( 1, "\n" ); // if ( pPars->fVerbose ) // Abc_Print( 1, "\nGenerated counter-example is verified correctly. " ); // Abc_Print( 1, "\n" ); } RetValue = 1; break; } if ( Abc_Clock() > nTimeToStop ) { i++; break; } if ( i < pPars->nIters - 1 ) Gia_ManSimInfoTransfer( p ); } Gia_ManSimDelete( p ); if ( pAig->pCexSeq == NULL ) Abc_Print( 1, "No bug detected after simulating %d frames with %d words. ", i, pPars->nWords ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManSimReadFile( char * pFileIn ) { int c; Vec_Int_t * vPat; FILE * pFile = fopen( pFileIn, "rb" ); if ( pFile == NULL ) { printf( "Cannot open input file.\n" ); return NULL; } vPat = Vec_IntAlloc( 1000 ); while ( (c = fgetc(pFile)) != EOF ) if ( c == '0' || c == '1' ) Vec_IntPush( vPat, c - '0' ); fclose( pFile ); return vPat; } int Gia_ManSimWriteFile( char * pFileOut, Vec_Int_t * vPat, int nOuts ) { int c, i; FILE * pFile = fopen( pFileOut, "wb" ); if ( pFile == NULL ) { printf( "Cannot open output file.\n" ); return 0; } assert( Vec_IntSize(vPat) % nOuts == 0 ); Vec_IntForEachEntry( vPat, c, i ) { fputc( '0' + c, pFile ); if ( i % nOuts == nOuts - 1 ) fputc( '\n', pFile ); } fclose( pFile ); return 1; } Vec_Int_t * Gia_ManSimSimulateOne( Gia_Man_t * p, Vec_Int_t * vPat ) { Vec_Int_t * vPatOut; Gia_Obj_t * pObj, * pObjRo; int i, k, f; assert( Vec_IntSize(vPat) % Gia_ManPiNum(p) == 0 ); Gia_ManConst0(p)->fMark1 = 0; Gia_ManForEachRo( p, pObj, i ) pObj->fMark1 = 0; vPatOut = Vec_IntAlloc( 1000 ); for ( k = f = 0; f < Vec_IntSize(vPat) / Gia_ManPiNum(p); f++ ) { Gia_ManForEachPi( p, pObj, i ) pObj->fMark1 = Vec_IntEntry( vPat, k++ ); Gia_ManForEachAnd( p, pObj, i ) pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)); Gia_ManForEachCo( p, pObj, i ) pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)); Gia_ManForEachPo( p, pObj, i ) Vec_IntPush( vPatOut, pObj->fMark1 ); Gia_ManForEachRiRo( p, pObj, pObjRo, i ) pObjRo->fMark1 = pObj->fMark1; } assert( k == Vec_IntSize(vPat) ); Gia_ManForEachObj( p, pObj, i ) pObj->fMark1 = 0; return vPatOut; } void Gia_ManSimSimulatePattern( Gia_Man_t * p, char * pFileIn, char * pFileOut ) { Vec_Int_t * vPat, * vPatOut; vPat = Gia_ManSimReadFile( pFileIn ); if ( vPat == NULL ) return; if ( Vec_IntSize(vPat) % Gia_ManPiNum(p) ) { printf( "The number of 0s and 1s in the input file (%d) does not evenly divide by the number of primary inputs (%d).\n", Vec_IntSize(vPat), Gia_ManPiNum(p) ); Vec_IntFree( vPat ); return; } vPatOut = Gia_ManSimSimulateOne( p, vPat ); if ( Gia_ManSimWriteFile( pFileOut, vPatOut, Gia_ManPoNum(p) ) ) printf( "Output patterns are written into file \"%s\".\n", pFileOut ); Vec_IntFree( vPat ); Vec_IntFree( vPatOut ); } /**Function************************************************************* Synopsis [Bit-parallel simulation during AIG construction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline word * Gia_ManBuiltInDataPi( Gia_Man_t * p, int iCiId ) { return Vec_WrdEntryP( p->vSimsPi, p->nSimWords * iCiId ); } static inline word * Gia_ManBuiltInData( Gia_Man_t * p, int iObj ) { return Vec_WrdEntryP( p->vSims, p->nSimWords * iObj ); } static inline void Gia_ManBuiltInDataPrint( Gia_Man_t * p, int iObj ) { // printf( "Obj %6d : ", iObj ); Extra_PrintBinary( stdout, Gia_ManBuiltInData(p, iObj), p->nSimWords * 64 ); printf( "\n" ); } void Gia_ManBuiltInSimStart( Gia_Man_t * p, int nWords, int nObjs ) { int i, k; assert( !p->fBuiltInSim ); assert( Gia_ManAndNum(p) == 0 ); p->fBuiltInSim = 1; p->iPatsPi = 0; p->iPastPiMax = 0; p->nSimWords = nWords; p->nSimWordsMax = 8; Gia_ManRandomW( 1 ); // init PI care info p->vSimsPi = Vec_WrdAlloc( p->nSimWords * Gia_ManCiNum(p) ); Vec_WrdFill( p->vSimsPi, p->nSimWords * Gia_ManCiNum(p), 0 ); // init object sim info p->vSims = Vec_WrdAlloc( p->nSimWords * nObjs ); Vec_WrdFill( p->vSims, p->nSimWords, 0 ); for ( i = 0; i < Gia_ManCiNum(p); i++ ) for ( k = 0; k < p->nSimWords; k++ ) Vec_WrdPush( p->vSims, Gia_ManRandomW(0) ); } void Gia_ManBuiltInSimPerformInt( Gia_Man_t * p, int iObj ) { Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); int w; word * pInfo = Gia_ManBuiltInData( p, iObj ); word * pInfo0 = Gia_ManBuiltInData( p, Gia_ObjFaninId0(pObj, iObj) ); word * pInfo1 = Gia_ManBuiltInData( p, Gia_ObjFaninId1(pObj, iObj) ); assert( p->fBuiltInSim || p->fIncrSim ); if ( Gia_ObjFaninC0(pObj) ) { if ( Gia_ObjFaninC1(pObj) ) for ( w = 0; w < p->nSimWords; w++ ) pInfo[w] = ~(pInfo0[w] | pInfo1[w]); else for ( w = 0; w < p->nSimWords; w++ ) pInfo[w] = ~pInfo0[w] & pInfo1[w]; } else { if ( Gia_ObjFaninC1(pObj) ) for ( w = 0; w < p->nSimWords; w++ ) pInfo[w] = pInfo0[w] & ~pInfo1[w]; else for ( w = 0; w < p->nSimWords; w++ ) pInfo[w] = pInfo0[w] & pInfo1[w]; } assert( Vec_WrdSize(p->vSims) == Gia_ManObjNum(p) * p->nSimWords ); } void Gia_ManBuiltInSimPerform( Gia_Man_t * p, int iObj ) { int w; for ( w = 0; w < p->nSimWords; w++ ) Vec_WrdPush( p->vSims, 0 ); Gia_ManBuiltInSimPerformInt( p, iObj ); } void Gia_ManBuiltInSimResimulateCone_rec( Gia_Man_t * p, int iObj ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) return; Gia_ObjSetTravIdCurrentId(p, iObj); pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjIsCi(pObj) ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManBuiltInSimResimulateCone_rec( p, Gia_ObjFaninId0(pObj, iObj) ); Gia_ManBuiltInSimResimulateCone_rec( p, Gia_ObjFaninId1(pObj, iObj) ); Gia_ManBuiltInSimPerformInt( p, iObj ); } void Gia_ManBuiltInSimResimulateCone( Gia_Man_t * p, int iLit0, int iLit1 ) { Gia_ManIncrementTravId( p ); Gia_ManBuiltInSimResimulateCone_rec( p, Abc_Lit2Var(iLit0) ); Gia_ManBuiltInSimResimulateCone_rec( p, Abc_Lit2Var(iLit1) ); } void Gia_ManBuiltInSimResimulate( Gia_Man_t * p ) { Gia_Obj_t * pObj; int iObj; Gia_ManForEachAnd( p, pObj, iObj ) Gia_ManBuiltInSimPerformInt( p, iObj ); } int Gia_ManBuiltInSimCheckOver( Gia_Man_t * p, int iLit0, int iLit1 ) { word * pInfo0 = Gia_ManBuiltInData( p, Abc_Lit2Var(iLit0) ); word * pInfo1 = Gia_ManBuiltInData( p, Abc_Lit2Var(iLit1) ); int w; assert( p->fBuiltInSim || p->fIncrSim ); // printf( "%d %d\n", Abc_LitIsCompl(iLit0), Abc_LitIsCompl(iLit1) ); // Extra_PrintBinary( stdout, pInfo0, 64*p->nSimWords ); printf( "\n" ); // Extra_PrintBinary( stdout, pInfo1, 64*p->nSimWords ); printf( "\n" ); // printf( "\n" ); if ( Abc_LitIsCompl(iLit0) ) { if ( Abc_LitIsCompl(iLit1) ) { for ( w = 0; w < p->nSimWords; w++ ) if ( ~pInfo0[w] & ~pInfo1[w] ) return 1; } else { for ( w = 0; w < p->nSimWords; w++ ) if ( ~pInfo0[w] & pInfo1[w] ) return 1; } } else { if ( Abc_LitIsCompl(iLit1) ) { for ( w = 0; w < p->nSimWords; w++ ) if ( pInfo0[w] & ~pInfo1[w] ) return 1; } else { for ( w = 0; w < p->nSimWords; w++ ) if ( pInfo0[w] & pInfo1[w] ) return 1; } } return 0; } int Gia_ManBuiltInSimCheckEqual( Gia_Man_t * p, int iLit0, int iLit1 ) { word * pInfo0 = Gia_ManBuiltInData( p, Abc_Lit2Var(iLit0) ); word * pInfo1 = Gia_ManBuiltInData( p, Abc_Lit2Var(iLit1) ); int w; assert( p->fBuiltInSim || p->fIncrSim ); // printf( "%d %d\n", Abc_LitIsCompl(iLit0), Abc_LitIsCompl(iLit1) ); // Extra_PrintBinary( stdout, pInfo0, 64*p->nSimWords ); printf( "\n" ); // Extra_PrintBinary( stdout, pInfo1, 64*p->nSimWords ); printf( "\n" ); // printf( "\n" ); if ( Abc_LitIsCompl(iLit0) ) { if ( Abc_LitIsCompl(iLit1) ) { for ( w = 0; w < p->nSimWords; w++ ) if ( ~pInfo0[w] != ~pInfo1[w] ) return 0; } else { for ( w = 0; w < p->nSimWords; w++ ) if ( ~pInfo0[w] != pInfo1[w] ) return 0; } } else { if ( Abc_LitIsCompl(iLit1) ) { for ( w = 0; w < p->nSimWords; w++ ) if ( pInfo0[w] != ~pInfo1[w] ) return 0; } else { for ( w = 0; w < p->nSimWords; w++ ) if ( pInfo0[w] != pInfo1[w] ) return 0; } } return 1; } int Gia_ManBuiltInSimPack( Gia_Man_t * p, Vec_Int_t * vPat ) { int i, k, iLit; assert( Vec_IntSize(vPat) > 0 ); //printf( "%d ", Vec_IntSize(vPat) ); for ( i = 0; i < p->iPatsPi; i++ ) { Vec_IntForEachEntry( vPat, iLit, k ) if ( Abc_TtGetBit(Gia_ManBuiltInDataPi(p, Abc_Lit2Var(iLit)), i) && Abc_TtGetBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), i) == Abc_LitIsCompl(iLit) ) break; if ( k == Vec_IntSize(vPat) ) return i; // success } return -1; // failure } // adds PI pattern to storage; the pattern comes in terms of CiIds int Gia_ManBuiltInSimAddPat( Gia_Man_t * p, Vec_Int_t * vPat ) { int Period = 0xF; int fOverflow = p->iPatsPi == 64 * p->nSimWords && p->nSimWords == p->nSimWordsMax; int k, iLit, iPat = Gia_ManBuiltInSimPack( p, vPat ); if ( iPat == -1 ) { if ( fOverflow ) { if ( (p->iPastPiMax & Period) == 0 ) Gia_ManBuiltInSimResimulate( p ); iPat = p->iPastPiMax; //if ( p->iPastPiMax == 64 * p->nSimWordsMax - 1 ) // printf( "Completed the cycle.\n" ); p->iPastPiMax = p->iPastPiMax == 64 * p->nSimWordsMax - 1 ? 0 : p->iPastPiMax + 1; } else { if ( p->iPatsPi && (p->iPatsPi & Period) == 0 ) Gia_ManBuiltInSimResimulate( p ); if ( p->iPatsPi == 64 * p->nSimWords ) { Vec_Wrd_t * vTemp = Vec_WrdAlloc( 2 * Vec_WrdSize(p->vSims) ); word Data; int w, Count = 0, iObj = 0; Vec_WrdForEachEntry( p->vSims, Data, w ) { Vec_WrdPush( vTemp, Data ); if ( ++Count == p->nSimWords ) { Gia_Obj_t * pObj = Gia_ManObj(p, iObj++); if ( Gia_ObjIsCi(pObj) ) Vec_WrdPush( vTemp, Gia_ManRandomW(0) ); // Vec_WrdPush( vTemp, 0 ); else if ( Gia_ObjIsAnd(pObj) ) Vec_WrdPush( vTemp, pObj->fPhase ? ~(word)0 : 0 ); else Vec_WrdPush( vTemp, 0 ); Count = 0; } } assert( iObj == Gia_ManObjNum(p) ); Vec_WrdFree( p->vSims ); p->vSims = vTemp; vTemp = Vec_WrdAlloc( 2 * Vec_WrdSize(p->vSimsPi) ); Count = 0; Vec_WrdForEachEntry( p->vSimsPi, Data, w ) { Vec_WrdPush( vTemp, Data ); if ( ++Count == p->nSimWords ) { Vec_WrdPush( vTemp, 0 ); Count = 0; } } Vec_WrdFree( p->vSimsPi ); p->vSimsPi = vTemp; // update the word count p->nSimWords++; assert( Vec_WrdSize(p->vSims) == p->nSimWords * Gia_ManObjNum(p) ); assert( Vec_WrdSize(p->vSimsPi) == p->nSimWords * Gia_ManCiNum(p) ); //printf( "Resizing to %d words.\n", p->nSimWords ); } iPat = p->iPatsPi++; } } assert( iPat >= 0 && iPat < p->iPatsPi ); // add literals if ( fOverflow ) { int iVar; Vec_IntForEachEntry( &p->vSuppVars, iVar, k ) if ( Abc_TtGetBit(Gia_ManBuiltInDataPi(p, iVar), iPat) ) Abc_TtXorBit(Gia_ManBuiltInDataPi(p, iVar), iPat); Vec_IntForEachEntry( vPat, iLit, k ) { if ( Abc_TtGetBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), iPat) == Abc_LitIsCompl(iLit) ) Abc_TtXorBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), iPat); Abc_TtXorBit(Gia_ManBuiltInDataPi(p, Abc_Lit2Var(iLit)), iPat); } } else { Vec_IntForEachEntry( vPat, iLit, k ) { if ( Abc_TtGetBit(Gia_ManBuiltInDataPi(p, Abc_Lit2Var(iLit)), iPat) ) assert( Abc_TtGetBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), iPat) != Abc_LitIsCompl(iLit) ); else { if ( Abc_TtGetBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), iPat) == Abc_LitIsCompl(iLit) ) Abc_TtXorBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), iPat); Abc_TtXorBit(Gia_ManBuiltInDataPi(p, Abc_Lit2Var(iLit)), iPat); } } } return 1; } /**Function************************************************************* Synopsis [Finds a satisfying assignment.] Description [Returns 1 if a sat assignment is found; 0 otherwise.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManObjCheckSat_rec( Gia_Man_t * p, int iLit, Vec_Int_t * vObjs ) { int iObj = Abc_Lit2Var(iLit); Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); if ( pObj->fMark0 ) return pObj->fMark1 == (unsigned)Abc_LitIsCompl(iLit); pObj->fMark0 = 1; pObj->fMark1 = Abc_LitIsCompl(iLit); Vec_IntPush( vObjs, iObj ); if ( Gia_ObjIsAnd(pObj) ) { if ( pObj->fMark1 == 0 ) // node value is 1 { if ( !Gia_ManObjCheckSat_rec( p, Gia_ObjFaninLit0(pObj, iObj), vObjs ) ) return 0; if ( !Gia_ManObjCheckSat_rec( p, Gia_ObjFaninLit1(pObj, iObj), vObjs ) ) return 0; } else { if ( !Gia_ManObjCheckSat_rec( p, Abc_LitNot(Gia_ObjFaninLit0(pObj, iObj)), vObjs ) ) return 0; } } return 1; } int Gia_ManObjCheckOverlap1( Gia_Man_t * p, int iLit0, int iLit1, Vec_Int_t * vObjs ) { Gia_Obj_t * pObj; int i, Res0, Res1 = 0; // Gia_ManForEachObj( p, pObj, i ) // assert( pObj->fMark0 == 0 && pObj->fMark1 == 0 ); Vec_IntClear( vObjs ); Res0 = Gia_ManObjCheckSat_rec( p, iLit0, vObjs ); if ( Res0 ) Res1 = Gia_ManObjCheckSat_rec( p, iLit1, vObjs ); Gia_ManForEachObjVec( vObjs, p, pObj, i ) pObj->fMark0 = pObj->fMark1 = 0; return Res0 && Res1; } int Gia_ManObjCheckOverlap( Gia_Man_t * p, int iLit0, int iLit1, Vec_Int_t * vObjs ) { if ( Gia_ManObjCheckOverlap1( p, iLit0, iLit1, vObjs ) ) return 1; return Gia_ManObjCheckOverlap1( p, iLit1, iLit0, vObjs ); } /**Function************************************************************* Synopsis [Bit-parallel simulation during AIG construction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManIncrSimUpdate( Gia_Man_t * p ) { int i, k; // extend timestamp info assert( Vec_IntSize(p->vTimeStamps) <= Gia_ManObjNum(p) ); Vec_IntFillExtra( p->vTimeStamps, Gia_ManObjNum(p), 0 ); // extend simulation info assert( Vec_WrdSize(p->vSims) <= Gia_ManObjNum(p) * p->nSimWords ); Vec_WrdFillExtra( p->vSims, Gia_ManObjNum(p) * p->nSimWords, 0 ); // extend PI info assert( p->iNextPi <= Gia_ManCiNum(p) ); for ( i = p->iNextPi; i < Gia_ManCiNum(p); i++ ) { word * pSims = Gia_ManBuiltInData( p, Gia_ManCiIdToId(p, i) ); for ( k = 0; k < p->nSimWords; k++ ) pSims[k] = Gia_ManRandomW(0); } p->iNextPi = Gia_ManCiNum(p); } void Gia_ManIncrSimStart( Gia_Man_t * p, int nWords, int nObjs ) { assert( !p->fIncrSim ); p->fIncrSim = 1; p->iPatsPi = 0; p->nSimWords = nWords; // init time stamps p->iTimeStamp = 1; p->vTimeStamps = Vec_IntAlloc( p->nSimWords ); // init object sim info p->iNextPi = 0; p->vSims = Vec_WrdAlloc( p->nSimWords * nObjs ); Gia_ManRandomW( 1 ); } void Gia_ManIncrSimStop( Gia_Man_t * p ) { assert( p->fIncrSim ); p->fIncrSim = 0; p->iPatsPi = 0; p->nSimWords = 0; p->iTimeStamp = 1; Vec_IntFreeP( &p->vTimeStamps ); Vec_WrdFreeP( &p->vSims ); } void Gia_ManIncrSimSet( Gia_Man_t * p, Vec_Int_t * vObjLits ) { int i, iLit; assert( Vec_IntSize(vObjLits) > 0 ); p->iTimeStamp++; Vec_IntForEachEntry( vObjLits, iLit, i ) { word * pSims = Gia_ManBuiltInData( p, Abc_Lit2Var(iLit) ); if ( Gia_ObjIsAnd(Gia_ManObj(p, Abc_Lit2Var(iLit))) ) continue; //assert( Vec_IntEntry(p->vTimeStamps, Abc_Lit2Var(iLit)) == p->iTimeStamp-1 ); Vec_IntWriteEntry(p->vTimeStamps, Abc_Lit2Var(iLit), p->iTimeStamp); if ( Abc_TtGetBit(pSims, p->iPatsPi) == Abc_LitIsCompl(iLit) ) Abc_TtXorBit(pSims, p->iPatsPi); } p->iPatsPi = (p->iPatsPi == p->nSimWords * 64 - 1) ? 0 : p->iPatsPi + 1; } void Gia_ManIncrSimCone_rec( Gia_Man_t * p, int iObj ) { Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjIsCi(pObj) ) return; if ( Vec_IntEntry(p->vTimeStamps, iObj) == p->iTimeStamp ) return; assert( Vec_IntEntry(p->vTimeStamps, iObj) < p->iTimeStamp ); Vec_IntWriteEntry( p->vTimeStamps, iObj, p->iTimeStamp ); assert( Gia_ObjIsAnd(pObj) ); Gia_ManIncrSimCone_rec( p, Gia_ObjFaninId0(pObj, iObj) ); Gia_ManIncrSimCone_rec( p, Gia_ObjFaninId1(pObj, iObj) ); Gia_ManBuiltInSimPerformInt( p, iObj ); } int Gia_ManIncrSimCheckOver( Gia_Man_t * p, int iLit0, int iLit1 ) { assert( iLit0 > 1 && iLit1 > 1 ); Gia_ManIncrSimUpdate( p ); Gia_ManIncrSimCone_rec( p, Abc_Lit2Var(iLit0) ); Gia_ManIncrSimCone_rec( p, Abc_Lit2Var(iLit1) ); // return 0; // disable return Gia_ManBuiltInSimCheckOver( p, iLit0, iLit1 ); } int Gia_ManIncrSimCheckEqual( Gia_Man_t * p, int iLit0, int iLit1 ) { assert( iLit0 > 1 && iLit1 > 1 ); Gia_ManIncrSimUpdate( p ); Gia_ManIncrSimCone_rec( p, Abc_Lit2Var(iLit0) ); Gia_ManIncrSimCone_rec( p, Abc_Lit2Var(iLit1) ); // return 1; // disable return Gia_ManBuiltInSimCheckEqual( p, iLit0, 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 /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSim2.c000066400000000000000000000464221477524141600157360ustar00rootroot00000000000000/**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" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Gia_Sim2_t_ Gia_Sim2_t; struct Gia_Sim2_t_ { Gia_Man_t * pAig; Gia_ParSim_t * pPars; int nWords; unsigned * pDataSim; Vec_Int_t * vClassOld; Vec_Int_t * vClassNew; }; static inline unsigned * Gia_Sim2Data( Gia_Sim2_t * p, int i ) { return p->pDataSim + i * p->nWords; } extern void Gia_ManResetRandom( Gia_ParSim_t * pPars ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_Sim2Delete( Gia_Sim2_t * p ) { Vec_IntFreeP( &p->vClassOld ); Vec_IntFreeP( &p->vClassNew ); ABC_FREE( p->pDataSim ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates fast simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Sim2_t * Gia_Sim2Create( Gia_Man_t * pAig, Gia_ParSim_t * pPars ) { Gia_Sim2_t * p; Gia_Obj_t * pObj; int i; p = ABC_CALLOC( Gia_Sim2_t, 1 ); p->pAig = pAig; p->pPars = pPars; p->nWords = pPars->nWords; p->pDataSim = ABC_ALLOC( unsigned, p->nWords * Gia_ManObjNum(p->pAig) ); if ( !p->pDataSim ) { Abc_Print( 1, "Simulator could not allocate %.2f GB for simulation info.\n", 4.0 * p->nWords * Gia_ManObjNum(p->pAig) / (1<<30) ); Gia_Sim2Delete( p ); return NULL; } p->vClassOld = Vec_IntAlloc( 100 ); p->vClassNew = Vec_IntAlloc( 100 ); if ( pPars->fVerbose ) Abc_Print( 1, "Memory: AIG = %7.2f MB. SimInfo = %7.2f MB.\n", 12.0*Gia_ManObjNum(p->pAig)/(1<<20), 4.0*p->nWords*Gia_ManObjNum(p->pAig)/(1<<20) ); // prepare AIG Gia_ManSetPhase( pAig ); Gia_ManForEachObj( pAig, pObj, i ) pObj->Value = i; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_Sim2InfoRandom( Gia_Sim2_t * p, unsigned * pInfo ) { int w; for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = Gia_ManRandom( 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_Sim2InfoZero( Gia_Sim2_t * p, unsigned * pInfo ) { int w; for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_Sim2InfoOne( Gia_Sim2_t * p, unsigned * pInfo ) { int w; for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = ~0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_Sim2InfoCopy( Gia_Sim2_t * p, unsigned * pInfo, unsigned * pInfo0 ) { int w; for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_Sim2SimulateCo( Gia_Sim2_t * p, Gia_Obj_t * pObj ) { unsigned * pInfo = Gia_Sim2Data( p, Gia_ObjValue(pObj) ); unsigned * pInfo0 = Gia_Sim2Data( p, Gia_ObjFaninId0(pObj, Gia_ObjValue(pObj)) ); int w; if ( Gia_ObjFaninC0(pObj) ) for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = ~pInfo0[w]; else for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_Sim2SimulateNode( Gia_Sim2_t * p, Gia_Obj_t * pObj ) { unsigned * pInfo = Gia_Sim2Data( p, Gia_ObjValue(pObj) ); unsigned * pInfo0 = Gia_Sim2Data( p, Gia_ObjFaninId0(pObj, Gia_ObjValue(pObj)) ); unsigned * pInfo1 = Gia_Sim2Data( p, Gia_ObjFaninId1(pObj, Gia_ObjValue(pObj)) ); int w; if ( Gia_ObjFaninC0(pObj) ) { if ( Gia_ObjFaninC1(pObj) ) for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = ~(pInfo0[w] | pInfo1[w]); else for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = ~pInfo0[w] & pInfo1[w]; } else { if ( Gia_ObjFaninC1(pObj) ) for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w] & ~pInfo1[w]; else for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w] & pInfo1[w]; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_Sim2InfoTransfer( Gia_Sim2_t * p ) { Gia_Obj_t * pObjRo, * pObjRi; unsigned * pInfo0, * pInfo1; int i; Gia_ManForEachRiRo( p->pAig, pObjRi, pObjRo, i ) { pInfo0 = Gia_Sim2Data( p, Gia_ObjValue(pObjRo) ); pInfo1 = Gia_Sim2Data( p, Gia_ObjValue(pObjRi) ); Gia_Sim2InfoCopy( p, pInfo0, pInfo1 ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_Sim2SimulateRound( Gia_Sim2_t * p ) { Gia_Obj_t * pObj; int i; pObj = Gia_ManConst0(p->pAig); assert( Gia_ObjValue(pObj) == 0 ); Gia_Sim2InfoZero( p, Gia_Sim2Data(p, Gia_ObjValue(pObj)) ); Gia_ManForEachPi( p->pAig, pObj, i ) Gia_Sim2InfoRandom( p, Gia_Sim2Data(p, Gia_ObjValue(pObj)) ); Gia_ManForEachAnd( p->pAig, pObj, i ) { assert( Gia_ObjValue(pObj) == i ); Gia_Sim2SimulateNode( p, pObj ); } Gia_ManForEachCo( p->pAig, pObj, i ) Gia_Sim2SimulateCo( p, pObj ); } /**Function************************************************************* Synopsis [Compares simulation info of two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_Sim2CompareEqual( unsigned * p0, unsigned * p1, int nWords, int fCompl ) { int w; if ( !fCompl ) { for ( w = 0; w < nWords; w++ ) if ( p0[w] != p1[w] ) return 0; return 1; } else { for ( w = 0; w < nWords; w++ ) if ( p0[w] != ~p1[w] ) return 0; return 1; } } /**Function************************************************************* Synopsis [Compares simulation info of one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_Sim2CompareZero( unsigned * p0, int nWords, int fCompl ) { int w; if ( !fCompl ) { for ( w = 0; w < nWords; w++ ) if ( p0[w] != 0 ) return 0; return 1; } else { for ( w = 0; w < nWords; w++ ) if ( p0[w] != ~0 ) return 0; return 1; } } /**Function************************************************************* Synopsis [Creates equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_Sim2ClassCreate( Gia_Man_t * p, Vec_Int_t * vClass ) { int Repr = GIA_VOID, EntPrev = -1, Ent, i; assert( Vec_IntSize(vClass) > 0 ); Vec_IntForEachEntry( vClass, Ent, i ) { if ( i == 0 ) { Repr = Ent; Gia_ObjSetRepr( p, Ent, GIA_VOID ); EntPrev = Ent; } else { assert( Repr < Ent ); Gia_ObjSetRepr( p, Ent, Repr ); Gia_ObjSetNext( p, EntPrev, Ent ); EntPrev = Ent; } } Gia_ObjSetNext( p, EntPrev, 0 ); } /**Function************************************************************* Synopsis [Refines one equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_Sim2ClassRefineOne( Gia_Sim2_t * p, int i ) { Gia_Obj_t * pObj0, * pObj1; unsigned * pSim0, * pSim1; int Ent; Vec_IntClear( p->vClassOld ); Vec_IntClear( p->vClassNew ); Vec_IntPush( p->vClassOld, i ); pObj0 = Gia_ManObj( p->pAig, i ); pSim0 = Gia_Sim2Data( p, i ); Gia_ClassForEachObj1( p->pAig, i, Ent ) { pObj1 = Gia_ManObj( p->pAig, Ent ); pSim1 = Gia_Sim2Data( p, Ent ); if ( Gia_Sim2CompareEqual( pSim0, pSim1, p->nWords, Gia_ObjPhase(pObj0) ^ Gia_ObjPhase(pObj1) ) ) Vec_IntPush( p->vClassOld, Ent ); else Vec_IntPush( p->vClassNew, Ent ); } if ( Vec_IntSize( p->vClassNew ) == 0 ) return 0; Gia_Sim2ClassCreate( p->pAig, p->vClassOld ); Gia_Sim2ClassCreate( p->pAig, p->vClassNew ); if ( Vec_IntSize(p->vClassNew) > 1 ) return 1 + Gia_Sim2ClassRefineOne( p, Vec_IntEntry(p->vClassNew,0) ); return 1; } /**Function************************************************************* Synopsis [Computes hash key of the simuation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_Sim2HashKey( unsigned * pSim, int nWords, int nTableSize ) { static int s_Primes[16] = { 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 }; unsigned uHash = 0; int i; if ( pSim[0] & 1 ) for ( i = 0; i < nWords; i++ ) uHash ^= ~pSim[i] * s_Primes[i & 0xf]; else for ( i = 0; i < nWords; i++ ) uHash ^= pSim[i] * s_Primes[i & 0xf]; return (int)(uHash % nTableSize); } /**Function************************************************************* Synopsis [Refines nodes belonging to candidate constant class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_Sim2ProcessRefined( Gia_Sim2_t * p, Vec_Int_t * vRefined ) { unsigned * pSim; int * pTable, nTableSize, i, k, Key; if ( Vec_IntSize(vRefined) == 0 ) return; nTableSize = Abc_PrimeCudd( 1000 + Vec_IntSize(vRefined) / 3 ); pTable = ABC_CALLOC( int, nTableSize ); Vec_IntForEachEntry( vRefined, i, k ) { pSim = Gia_Sim2Data( p, i ); Key = Gia_Sim2HashKey( pSim, p->nWords, nTableSize ); if ( pTable[Key] == 0 ) { assert( Gia_ObjRepr(p->pAig, i) == 0 ); assert( Gia_ObjNext(p->pAig, i) == 0 ); Gia_ObjSetRepr( p->pAig, i, GIA_VOID ); } else { Gia_ObjSetNext( p->pAig, pTable[Key], i ); Gia_ObjSetRepr( p->pAig, i, Gia_ObjRepr(p->pAig, pTable[Key]) ); if ( Gia_ObjRepr(p->pAig, i) == GIA_VOID ) Gia_ObjSetRepr( p->pAig, i, pTable[Key] ); assert( Gia_ObjRepr(p->pAig, i) > 0 ); } pTable[Key] = i; } /* Vec_IntForEachEntry( vRefined, i, k ) { if ( Gia_ObjIsHead( p->pAig, i ) ) Gia_Sim2ClassRefineOne( p, i ); } */ ABC_FREE( pTable ); } /**Function************************************************************* Synopsis [Refines equivalences after one simulation round.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_Sim2InfoRefineEquivs( Gia_Sim2_t * p ) { Vec_Int_t * vRefined; Gia_Obj_t * pObj; unsigned * pSim; int i, Count = 0; // process constant candidates vRefined = Vec_IntAlloc( 100 ); Gia_ManForEachObj1( p->pAig, pObj, i ) { if ( !Gia_ObjIsConst(p->pAig, i) ) continue; pSim = Gia_Sim2Data( p, i ); //Extra_PrintBinary( stdout, pSim, 32 * p->nWords ); printf( "\n" ); if ( !Gia_Sim2CompareZero( pSim, p->nWords, Gia_ObjPhase(pObj) ) ) { Vec_IntPush( vRefined, i ); Count++; } } Gia_Sim2ProcessRefined( p, vRefined ); Vec_IntFree( vRefined ); // process other classes Gia_ManForEachClass( p->pAig, i ) Count += Gia_Sim2ClassRefineOne( p, i ); // if ( Count ) // printf( "Refined %d times.\n", Count ); } /**Function************************************************************* Synopsis [Returns index of the first pattern that failed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_Sim2InfoIsZero( Gia_Sim2_t * p, unsigned * pInfo ) { int w; for ( w = 0; w < p->nWords; w++ ) if ( pInfo[w] ) return 32*w + Gia_WordFindFirstBit( pInfo[w] ); return -1; } /**Function************************************************************* Synopsis [Returns index of the PO and pattern that failed it.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_Sim2CheckPos( Gia_Sim2_t * p, int * piPo, int * piPat ) { Gia_Obj_t * pObj; int i, iPat; Gia_ManForEachPo( p->pAig, pObj, i ) { iPat = Gia_Sim2InfoIsZero( p, Gia_Sim2Data( p, Gia_ObjValue(pObj) ) ); if ( iPat >= 0 ) { *piPo = i; *piPat = iPat; return 1; } } return 0; } /**Function************************************************************* Synopsis [Returns the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Gia_Sim2GenerateCounter( Gia_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat ) { Abc_Cex_t * p; unsigned * pData; int f, i, w, Counter; p = Abc_CexAlloc( Gia_ManRegNum(pAig), Gia_ManPiNum(pAig), iFrame+1 ); p->iFrame = iFrame; p->iPo = iOut; // fill in the binary data Counter = p->nRegs; pData = ABC_ALLOC( unsigned, nWords ); for ( f = 0; f <= iFrame; f++, Counter += p->nPis ) for ( i = 0; i < Gia_ManPiNum(pAig); i++ ) { for ( w = nWords-1; w >= 0; w-- ) pData[w] = Gia_ManRandom( 0 ); if ( Abc_InfoHasBit( pData, iPat ) ) Abc_InfoSetBit( p->pData, Counter + i ); } ABC_FREE( pData ); return p; } /**Function************************************************************* Synopsis [Performs simulation to refine equivalence classes.] Description [Returns 1 if counter-example is detected.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSimSimulateEquiv( Gia_Man_t * pAig, Gia_ParSim_t * pPars ) { Gia_Sim2_t * p; Gia_Obj_t * pObj; abctime clkTotal = Abc_Clock(); int i, RetValue = 0, iOut, iPat; abctime nTimeToStop = pPars->TimeLimit ? pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; assert( pAig->pReprs && pAig->pNexts ); ABC_FREE( pAig->pCexSeq ); p = Gia_Sim2Create( pAig, pPars ); Gia_ManResetRandom( pPars ); Gia_ManForEachRo( p->pAig, pObj, i ) Gia_Sim2InfoZero( p, Gia_Sim2Data(p, Gia_ObjValue(pObj)) ); for ( i = 0; i < pPars->nIters; i++ ) { Gia_Sim2SimulateRound( p ); if ( pPars->fVerbose ) { Abc_Print( 1, "Frame %4d out of %4d and timeout %3d sec. ", i+1, pPars->nIters, pPars->TimeLimit ); if ( pAig->pReprs && pAig->pNexts ) Abc_Print( 1, "Lits = %4d. ", Gia_ManEquivCountLitsAll(pAig) ); Abc_Print( 1, "Time = %7.2f sec\r", (1.0*Abc_Clock()-clkTotal)/CLOCKS_PER_SEC ); } if ( pPars->fCheckMiter && Gia_Sim2CheckPos( p, &iOut, &iPat ) ) { Gia_ManResetRandom( pPars ); pPars->iOutFail = iOut; pAig->pCexSeq = Gia_Sim2GenerateCounter( pAig, i, iOut, p->nWords, iPat ); Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", iOut, pAig->pName, i ); if ( !Gia_ManVerifyCex( pAig, pAig->pCexSeq, 0 ) ) { // Abc_Print( 1, "\n" ); Abc_Print( 1, "\nGenerated counter-example is INVALID. " ); // Abc_Print( 1, "\n" ); } else { // Abc_Print( 1, "\n" ); // if ( pPars->fVerbose ) // Abc_Print( 1, "\nGenerated counter-example is verified correctly. " ); // Abc_Print( 1, "\n" ); } RetValue = 1; break; } if ( pAig->pReprs && pAig->pNexts ) Gia_Sim2InfoRefineEquivs( p ); if ( Abc_Clock() > nTimeToStop ) { i++; break; } if ( i < pPars->nIters - 1 ) Gia_Sim2InfoTransfer( p ); } Gia_Sim2Delete( p ); if ( pAig->pCexSeq == NULL ) Abc_Print( 1, "No bug detected after simulating %d frames with %d words. ", i, pPars->nWords ); Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSimBase.c000066400000000000000000004063711477524141600164520ustar00rootroot00000000000000/**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 fCard, char * pGuide ); 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, 0, NULL ); 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, char * pFileName ); extern Gia_Man_t * Gia_ManDupMini( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts, Mini_Aig_t * pMini ); Gia_Man_t * pNew = NULL; 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, NULL ); 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 abc-0.52/src/aig/gia/giaSort.c000066400000000000000000000166221477524141600160520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [gia.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 [This is implementation of qsort in MiniSat.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int num_cmp1( int * x, int * y) { return ((*x) < (*y)) ? -1 : (((*x) > (*y)) ? 1 : 0); } static int num_cmp2( int * x, int * y) { return (*x) < (*y); } static inline void selectionsort(int* array, int size, int(*comp)(const void *, const void *)) { int i, j, best_i; int tmp; for (i = 0; i < size-1; i++){ best_i = i; for (j = i+1; j < size; j++){ if (comp(array + j, array + best_i)) best_i = j; } tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; } } static void sort_rec(int* array, int size, int(*comp)(const void *, const void *)) { if (size <= 15) selectionsort(array, size, comp); else{ int pivot = array[size/2]; int tmp; int i = -1; int j = size; for(;;){ do i++; while(comp(array + i, &pivot)); do j--; while(comp(&pivot, array + j)); if (i >= j) break; tmp = array[i]; array[i] = array[j]; array[j] = tmp; } sort_rec(array , i , comp); sort_rec(&array[i], size-i, comp); } } void minisat_sort(int* array, int size, int(*comp)(const void *, const void *)) { sort_rec(array,size,comp); } /**Function************************************************************* Synopsis [This is implementation of qsort in MiniSat.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void selectionsort2(int* array, int size) { int i, j, best_i; int tmp; for (i = 0; i < size-1; i++){ best_i = i; for (j = i+1; j < size; j++){ if (array[j] < array[best_i]) best_i = j; } tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; } } static void sort_rec2(int* array, int size) { if (size <= 15) selectionsort2(array, size); else{ int pivot = array[size/2]; int tmp; int i = -1; int j = size; for(;;){ do i++; while(array[i] < pivot); do j--; while(pivot < array[j]); if (i >= j) break; tmp = array[i]; array[i] = array[j]; array[j] = tmp; } sort_rec2(array , i ); sort_rec2(&array[i], size-i); } } void minisat_sort2(int* array, int size) { sort_rec2(array,size); } /**Function************************************************************* Synopsis [This is implementation of qsort in MiniSat.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Gia_SortGetTest( int nSize ) { int i, * pArray; srand( 0 ); pArray = ABC_ALLOC( int, nSize ); for ( i = 0; i < nSize; i++ ) pArray[i] = rand(); return pArray; } void Gia_SortVerifySorted( int * pArray, int nSize ) { int i; for ( i = 1; i < nSize; i++ ) assert( pArray[i-1] <= pArray[i] ); } void Gia_SortTest() { int nSize = 100000000; int * pArray; abctime clk = Abc_Clock(); printf( "Sorting %d integers\n", nSize ); pArray = Gia_SortGetTest( nSize ); clk = Abc_Clock(); 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 ); pArray = Gia_SortGetTest( nSize ); clk = Abc_Clock(); minisat_sort( pArray, nSize, (int (*)(const void *, const void *)) num_cmp2 ); ABC_PRT( "minisat", Abc_Clock() - clk ); Gia_SortVerifySorted( pArray, nSize ); ABC_FREE( pArray ); pArray = Gia_SortGetTest( nSize ); clk = Abc_Clock(); minisat_sort2( pArray, nSize ); ABC_PRT( "minisat with inlined comparison", Abc_Clock() - clk ); Gia_SortVerifySorted( pArray, nSize ); ABC_FREE( pArray ); } /**Function************************************************************* Synopsis [This is implementation of qsort in MiniSat.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void selectionsort3(float* array, int* perm, int size) { float tmpf; int tmpi; int i, j, best_i; for (i = 0; i < size-1; i++){ best_i = i; for (j = i+1; j < size; j++){ if (array[j] < array[best_i]) best_i = j; } tmpf = array[i]; array[i] = array[best_i]; array[best_i] = tmpf; tmpi = perm[i]; perm[i] = perm[best_i]; perm[best_i] = tmpi; } } static void sort_rec3(float* array, int* perm, int size) { if (size <= 15) selectionsort3(array, perm, size); else{ float pivot = array[size/2]; float tmpf; int tmpi; int i = -1; int j = size; for(;;){ do i++; while(array[i] < pivot); do j--; while(pivot < array[j]); if (i >= j) break; tmpf = array[i]; array[i] = array[j]; array[j] = tmpf; tmpi = perm[i]; perm[i] = perm[j]; perm[j] = tmpi; } sort_rec3(array , perm, i ); sort_rec3(&array[i], &perm[i], size-i); } } void minisat_sort3(float* array, int* perm, int size) { sort_rec3(array, perm, size); } /**Function************************************************************* Synopsis [Sorts the array of floating point numbers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Gia_SortFloats( float * pArray, int * pPerm, int nSize ) { int i; if ( pPerm == NULL ) { pPerm = ABC_ALLOC( int, nSize ); for ( i = 0; i < nSize; i++ ) pPerm[i] = i; } minisat_sort3( pArray, pPerm, nSize ); // for ( i = 1; i < nSize; i++ ) // assert( pArray[i-1] <= pArray[i] ); return pPerm; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSpeedup.c000066400000000000000000000664251477524141600165360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [gia.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" #include "map/if/if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Sorts the pins in the decreasing order of delays.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_LutDelayTraceSortPins( Gia_Man_t * p, int iObj, int * pPinPerm, float * pPinDelays ) { int iFanin, i, j, best_i, temp; assert( Gia_ObjIsLut(p, iObj) ); // start the trivial permutation and collect pin delays Gia_LutForEachFanin( p, iObj, iFanin, i ) { pPinPerm[i] = i; pPinDelays[i] = Gia_ObjTimeArrival(p, iFanin); } // selection sort the pins in the decreasible order of delays // this order will match the increasing order of LUT input pins for ( i = 0; i < Gia_ObjLutSize(p, iObj)-1; i++ ) { best_i = i; for ( j = i+1; j < Gia_ObjLutSize(p, iObj); j++ ) if ( pPinDelays[pPinPerm[j]] > pPinDelays[pPinPerm[best_i]] ) best_i = j; if ( best_i == i ) continue; temp = pPinPerm[i]; pPinPerm[i] = pPinPerm[best_i]; pPinPerm[best_i] = temp; } // verify assert( Gia_ObjLutSize(p, iObj) == 0 || pPinPerm[0] < Gia_ObjLutSize(p, iObj) ); for ( i = 1; i < Gia_ObjLutSize(p, iObj); i++ ) { assert( pPinPerm[i] < Gia_ObjLutSize(p, iObj) ); assert( pPinDelays[pPinPerm[i-1]] >= pPinDelays[pPinPerm[i]] ); } } /**Function************************************************************* Synopsis [Sorts the pins in the decreasing order of delays.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_LutWhereIsPin( Gia_Man_t * p, int iFanout, int iFanin, int * pPinPerm ) { int i; for ( i = 0; i < Gia_ObjLutSize(p, iFanout); i++ ) if ( Gia_ObjLutFanin(p, iFanout, pPinPerm[i]) == iFanin ) return i; return -1; } /**Function************************************************************* Synopsis [Computes the arrival times for the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Gia_ObjComputeArrival( Gia_Man_t * p, int iObj, int fUseSorting ) { If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib; Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); int k, iFanin, pPinPerm[32]; float pPinDelays[32]; float tArrival, * pDelays; if ( Gia_ObjIsCi(pObj) ) return Gia_ObjTimeArrival(p, iObj); if ( Gia_ObjIsCo(pObj) ) return Gia_ObjTimeArrival(p, Gia_ObjFaninId0p(p, pObj) ); assert( Gia_ObjIsLut(p, iObj) ); tArrival = -TIM_ETERNITY; if ( pLutLib == NULL ) { Gia_LutForEachFanin( p, iObj, iFanin, k ) if ( tArrival < Gia_ObjTimeArrival(p, iFanin) + 1.0 ) tArrival = Gia_ObjTimeArrival(p, iFanin) + 1.0; } else if ( !pLutLib->fVarPinDelays ) { pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)]; Gia_LutForEachFanin( p, iObj, iFanin, k ) if ( tArrival < Gia_ObjTimeArrival(p, iFanin) + pDelays[0] ) tArrival = Gia_ObjTimeArrival(p, iFanin) + pDelays[0]; } else { pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)]; if ( fUseSorting ) { Gia_LutDelayTraceSortPins( p, iObj, pPinPerm, pPinDelays ); Gia_LutForEachFanin( p, iObj, iFanin, k ) if ( tArrival < Gia_ObjTimeArrival( p, Gia_ObjLutFanin(p,iObj,pPinPerm[k])) + pDelays[k] ) tArrival = Gia_ObjTimeArrival( p, Gia_ObjLutFanin(p,iObj,pPinPerm[k])) + pDelays[k]; } else { Gia_LutForEachFanin( p, iObj, iFanin, k ) if ( tArrival < Gia_ObjTimeArrival(p, iFanin) + pDelays[k] ) tArrival = Gia_ObjTimeArrival(p, iFanin) + pDelays[k]; } } if ( Gia_ObjLutSize(p, iObj) == 0 ) tArrival = 0.0; return tArrival; } /**Function************************************************************* Synopsis [Propagates the required times through the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Gia_ObjPropagateRequired( Gia_Man_t * p, int iObj, int fUseSorting ) { If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib; int k, iFanin, pPinPerm[32]; float pPinDelays[32]; float tRequired = 0.0; // Suppress "might be used uninitialized" float * pDelays; assert( Gia_ObjIsLut(p, iObj) ); if ( pLutLib == NULL ) { tRequired = Gia_ObjTimeRequired( p, iObj) - (float)1.0; Gia_LutForEachFanin( p, iObj, iFanin, k ) if ( Gia_ObjTimeRequired(p, iFanin) > tRequired ) Gia_ObjSetTimeRequired( p, iFanin, tRequired ); } else if ( !pLutLib->fVarPinDelays ) { pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)]; tRequired = Gia_ObjTimeRequired(p, iObj) - pDelays[0]; Gia_LutForEachFanin( p, iObj, iFanin, k ) if ( Gia_ObjTimeRequired(p, iFanin) > tRequired ) Gia_ObjSetTimeRequired( p, iFanin, tRequired ); } else { pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)]; if ( fUseSorting ) { Gia_LutDelayTraceSortPins( p, iObj, pPinPerm, pPinDelays ); Gia_LutForEachFanin( p, iObj, iFanin, k ) { tRequired = Gia_ObjTimeRequired( p, iObj) - pDelays[k]; if ( Gia_ObjTimeRequired( p, Gia_ObjLutFanin(p, iObj,pPinPerm[k])) > tRequired ) Gia_ObjSetTimeRequired( p, Gia_ObjLutFanin(p, iObj,pPinPerm[k]), tRequired ); } } else { Gia_LutForEachFanin( p, iObj, iFanin, k ) { tRequired = Gia_ObjTimeRequired(p, iObj) - pDelays[k]; if ( Gia_ObjTimeRequired(p, iFanin) > tRequired ) Gia_ObjSetTimeRequired( p, iFanin, tRequired ); } } } return tRequired; } /**Function************************************************************* Synopsis [Computes the delay trace of the given network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Gia_ManDelayTraceLut( Gia_Man_t * p ) { int fUseSorting = 1; If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib; Vec_Int_t * vObjs; Gia_Obj_t * pObj; float tArrival, tArrivalCur, tRequired, tSlack; int i, iObj; // get the library if ( pLutLib && pLutLib->LutMax < Gia_ManLutSizeMax(p) ) { printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", pLutLib->LutMax, Gia_ManLutSizeMax(p) ); return -TIM_ETERNITY; } // initialize the arrival times Gia_ManTimeStart( p ); Gia_ManLevelNum( p ); // propagate arrival times if ( p->pManTime ) Tim_ManIncrementTravId( (Tim_Man_t *)p->pManTime ); Gia_ManForEachObj( p, pObj, i ) { if ( !Gia_ObjIsCi(pObj) && !Gia_ObjIsCo(pObj) && !Gia_ObjIsLut(p, i) ) continue; tArrival = Gia_ObjComputeArrival( p, i, fUseSorting ); if ( Gia_ObjIsCi(pObj) && p->pManTime ) { tArrival = Tim_ManGetCiArrival( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj) ); //printf( "%.3f ", tArrival ); } if ( Gia_ObjIsCo(pObj) && p->pManTime ) Tim_ManSetCoArrival( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj), tArrival ); Gia_ObjSetTimeArrival( p, i, tArrival ); } // get the latest arrival times tArrival = -TIM_ETERNITY; Gia_ManForEachCo( p, pObj, i ) { tArrivalCur = Gia_ObjTimeArrivalObj( p, Gia_ObjFanin0(pObj) ); Gia_ObjSetTimeArrival( p, Gia_ObjId(p,pObj), tArrivalCur ); if ( tArrival < tArrivalCur ) tArrival = tArrivalCur; } // initialize the required times if ( p->pManTime ) { Tim_ManIncrementTravId( (Tim_Man_t *)p->pManTime ); Tim_ManInitPoRequiredAll( (Tim_Man_t *)p->pManTime, tArrival ); } else { Gia_ManForEachCo( p, pObj, i ) Gia_ObjSetTimeRequiredObj( p, pObj, tArrival ); } // propagate the required times vObjs = Gia_ManOrderReverse( p ); Vec_IntForEachEntry( vObjs, iObj, i ) { pObj = Gia_ManObj(p, iObj); if ( Gia_ObjIsLut(p, iObj) ) { Gia_ObjPropagateRequired( p, iObj, fUseSorting ); } else if ( Gia_ObjIsCi(pObj) ) { if ( p->pManTime ) Tim_ManSetCiRequired( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj), Gia_ObjTimeRequired(p, iObj) ); } else if ( Gia_ObjIsCo(pObj) ) { if ( p->pManTime ) { tRequired = Tim_ManGetCoRequired( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj) ); Gia_ObjSetTimeRequired( p, iObj, tRequired ); } if ( Gia_ObjTimeRequired(p, Gia_ObjFaninId0p(p, pObj)) > Gia_ObjTimeRequired(p, iObj) ) Gia_ObjSetTimeRequired(p, Gia_ObjFaninId0p(p, pObj), Gia_ObjTimeRequired(p, iObj) ); } // set slack for this object tSlack = Gia_ObjTimeRequired(p, iObj) - Gia_ObjTimeArrival(p, iObj); assert( tSlack + 0.01 > 0.0 ); Gia_ObjSetTimeSlack( p, iObj, tSlack < 0.0 ? 0.0 : tSlack ); } Vec_IntFree( vObjs ); return tArrival; } #if 0 /**Function************************************************************* Synopsis [Computes the required times for the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Gia_ObjComputeRequired( Gia_Man_t * p, int iObj, int fUseSorting ) { If_LibLut_t * pLutLib = p->pLutLib; int pPinPerm[32]; float pPinDelays[32]; Gia_Obj_t * pFanout; float tRequired, tDelay, * pDelays; int k, iFanin; if ( Gia_ObjIsCo(iObj) ) return Gia_ObjTimeRequired( p, iObj); tRequired = TIM_ETERNITY; if ( pLutLib == NULL ) { Gia_ObjForEachFanout( iObj, pFanout, k ) { tDelay = Gia_ObjIsCo(pFanout)? 0.0 : 1.0; if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay ) tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay; } } else if ( !pLutLib->fVarPinDelays ) { Gia_ObjForEachFanout( iObj, pFanout, k ) { pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, pFanout)]; tDelay = Gia_ObjIsCo(pFanout)? 0.0 : pDelays[0]; if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay ) tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay; } } else { if ( fUseSorting ) { Gia_ObjForEachFanout( iObj, pFanout, k ) { pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, pFanout)]; Gia_LutDelayTraceSortPins( p, pFanout, pPinPerm, pPinDelays ); iFanin = Gia_LutWhereIsPin( p, pFanout, iObj, pPinPerm ); assert( Gia_ObjLutFanin( p, pFanout, pPinPerm[iFanin]) == iObj ); tDelay = Gia_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin]; if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay ) tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay; } } else { Gia_ObjForEachFanout( iObj, pFanout, k ) { pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, pFanout)]; iFanin = Gia_ObjFindFanin( p, pFanout, iObj ); assert( Gia_ObjLutFanin(p, pFanout, iFanin) == iObj ); tDelay = Gia_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin]; if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay ) tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay; } } } return tRequired; } /**Function************************************************************* Synopsis [Computes the arrival times for the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_LutVerifyTiming( Gia_Man_t * p ) { int iObj; float tArrival, tRequired; int i; Gia_LutForEachObj( p, iObj, i ) { if ( Gia_ObjIsCi(iObj) && Gia_ObjFanoutNum(iObj) == 0 ) continue; tArrival = Gia_ObjComputeArrival( p, iObj, 1 ); tRequired = Gia_ObjComputeRequired( p, iObj, 1 ); if ( !Gia_LutTimeEqual( tArrival, Gia_ObjTimeArrival( p, iObj), (float)0.01 ) ) printf( "Gia_LutVerifyTiming(): Object %d has different arrival time (%.2f) from computed (%.2f).\n", iObj->Id, Gia_ObjTimeArrival( p, iObj), tArrival ); if ( !Gia_LutTimeEqual( tRequired, Gia_ObjTimeRequired( p, iObj), (float)0.01 ) ) printf( "Gia_LutVerifyTiming(): Object %d has different required time (%.2f) from computed (%.2f).\n", iObj->Id, Gia_ObjTimeRequired( p, iObj), tRequired ); } return 1; } #endif /**Function************************************************************* Synopsis [Prints the delay trace for the given network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Gia_ManDelayTraceLutPrint( Gia_Man_t * p, int fVerbose ) { If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib; int i, Nodes, * pCounters; float tArrival, tDelta, nSteps, Num; // get the library if ( pLutLib && pLutLib->LutMax < Gia_ManLutSizeMax(p) ) { printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", pLutLib->LutMax, Gia_ManLutSizeMax(p) ); return -ABC_INFINITY; } // decide how many steps nSteps = pLutLib ? 20 : Gia_ManLutLevel(p, NULL); pCounters = ABC_ALLOC( int, nSteps + 1 ); memset( pCounters, 0, sizeof(int)*(nSteps + 1) ); // perform delay trace tArrival = Gia_ManDelayTraceLut( p ); tDelta = tArrival / nSteps; // count how many nodes have slack in the corresponding intervals Gia_ManForEachLut( p, i ) { if ( Gia_ObjLutSize(p, i) == 0 ) continue; Num = Gia_ObjTimeSlack(p, i) / tDelta; if ( Num > nSteps ) continue; assert( Num >=0 && Num <= nSteps ); pCounters[(int)Num]++; } // print the results if ( fVerbose ) { printf( "Max delay = %6.2f. Delay trace using %s model:\n", tArrival, pLutLib? "LUT library" : "unit-delay" ); Nodes = 0; for ( i = 0; i < nSteps; i++ ) { Nodes += pCounters[i]; printf( "%3d %s : %5d (%6.2f %%)\n", pLutLib? 5*(i+1) : i+1, pLutLib? "%":"lev", Nodes, 100.0*Nodes/Gia_ManLutNum(p) ); } } ABC_FREE( pCounters ); Gia_ManTimeStop( p ); return tArrival; } /**Function************************************************************* Synopsis [Determines timing-critical edges of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Gia_LutDelayTraceTCEdges( Gia_Man_t * p, int iObj, float tDelta ) { If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib; int pPinPerm[32]; float pPinDelays[32]; float tRequired, * pDelays; unsigned uResult = 0; int k, iFanin; tRequired = Gia_ObjTimeRequired( p, iObj ); if ( pLutLib == NULL ) { Gia_LutForEachFanin( p, iObj, iFanin, k ) if ( tRequired < Gia_ObjTimeArrival(p, iFanin) + 1.0 + tDelta ) uResult |= (1 << k); } else if ( !pLutLib->fVarPinDelays ) { pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)]; Gia_LutForEachFanin( p, iObj, iFanin, k ) if ( tRequired < Gia_ObjTimeArrival(p, iFanin) + pDelays[0] + tDelta ) uResult |= (1 << k); } else { pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)]; Gia_LutDelayTraceSortPins( p, iObj, pPinPerm, pPinDelays ); Gia_LutForEachFanin( p, iObj, iFanin, k ) if ( tRequired < Gia_ObjTimeArrival( p, Gia_ObjLutFanin(p, iObj,pPinPerm[k])) + pDelays[k] + tDelta ) uResult |= (1 << pPinPerm[k]); } return uResult; } /**Function************************************************************* Synopsis [Adds strashed nodes for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSpeedupObj_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 1; Gia_ObjSetTravIdCurrent( p, pObj ); if ( Gia_ObjIsCi(pObj) ) return 0; assert( Gia_ObjIsAnd(pObj) ); if ( !Gia_ManSpeedupObj_rec( p, Gia_ObjFanin0(pObj), vNodes ) ) return 0; if ( !Gia_ManSpeedupObj_rec( p, Gia_ObjFanin1(pObj), vNodes ) ) return 0; Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); return 1; } /**Function************************************************************* Synopsis [Adds strashed nodes for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSpeedupObj( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, Vec_Int_t * vTimes ) { Vec_Int_t * vNodes; Gia_Obj_t * pTemp = NULL; int pCofs[32], nCofs, nSkip, i, k, iResult, iObj; // mark the leaves Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); Gia_ManForEachObjVec( vLeaves, p, pTemp, i ) Gia_ObjSetTravIdCurrent( p, pTemp ); // collect the AIG nodes vNodes = Vec_IntAlloc( 100 ); if ( !Gia_ManSpeedupObj_rec( p, pObj, vNodes ) ) { printf( "Bad node!!!\n" ); Vec_IntFree( vNodes ); return; } // derive cofactors nCofs = (1 << Vec_IntSize(vTimes)); for ( i = 0; i < nCofs; i++ ) { Gia_ManForEachObjVec( vLeaves, p, pTemp, k ) pTemp->Value = Abc_Var2Lit( Gia_ObjId(p, pTemp), 0 ); Gia_ManForEachObjVec( vTimes, p, pTemp, k ) pTemp->Value = ((i & (1<Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pTemp), Gia_ObjFanin1Copy(pTemp) ); pCofs[i] = pTemp->Value; } Vec_IntFree( vNodes ); // collect the resulting tree Gia_ManForEachObjVec( vTimes, p, pTemp, k ) for ( nSkip = (1<pLutLib != NULL); void * pTempTim = NULL; unsigned * puTCEdges; assert( Gia_ManHasMapping(p) ); if ( !fUseLutLib && p->pManTime ) { pTempTim = p->pManTime; p->pManTime = Tim_ManDup( (Tim_Man_t *)pTempTim, 1 ); } // perform delay trace tArrival = Gia_ManDelayTraceLut( p ); tDelta = fUseLutLib ? tArrival*Percentage/100.0 : 1.0; if ( fVerbose ) { printf( "Max delay = %.2f. Delta = %.2f. ", tArrival, tDelta ); printf( "Using %s model. ", fUseLutLib ? "LUT library" : "unit-delay" ); if ( fUseLutLib ) printf( "Percentage = %d. ", Percentage ); printf( "\n" ); } // mark the timing critical nodes and edges puTCEdges = ABC_CALLOC( unsigned, Gia_ManObjNum(p) ); Gia_ManForEachLut( p, iObj ) { if ( Gia_ObjTimeSlack(p, iObj) >= tDelta ) continue; puTCEdges[iObj] = Gia_LutDelayTraceTCEdges( p, iObj, tDelta ); } if ( fVerbose ) { Counter = CounterRes = 0; Gia_ManForEachLut( p, iObj ) { Gia_LutForEachFanin( p, iObj, iFanin, k ) if ( !Gia_ObjIsCi(Gia_ManObj(p, iFanin)) && Gia_ObjTimeSlack(p, iFanin) < tDelta ) Counter++; CounterRes += Gia_WordCountOnes( puTCEdges[iObj] ); } printf( "Edges: Total = %7d. 0-slack = %7d. Critical = %7d. Ratio = %4.2f\n", Gia_ManLutFaninCount(p), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 ); } // start the resulting network pNew = Gia_ManDup( p ); Gia_ManHashStart( pNew ); nNodesNew = 1000 + 3 * Gia_ManObjNum(pNew); pNew->pNexts = ABC_CALLOC( int, nNodesNew ); pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, nNodesNew ); for ( i = 0; i < nNodesNew; i++ ) Gia_ObjSetRepr( pNew, i, GIA_VOID ); // collect nodes to be used for resynthesis Counter = CounterRes = 0; vTimeCries = Vec_IntAlloc( 16 ); vTimeFanins = Vec_IntAlloc( 16 ); Gia_ManForEachLut( p, iObj ) { if ( Gia_ObjTimeSlack(p, iObj) >= tDelta ) continue; // count the number of non-PI timing-critical nodes nTimeCris = 0; Gia_LutForEachFanin( p, iObj, iFanin, k ) if ( !Gia_ObjIsCi(Gia_ManObj(p, iFanin)) && (puTCEdges[iObj] & (1< Degree) ) if ( (Vec_IntSize(vTimeCries) == 0 || Vec_IntSize(vTimeCries) > Degree) ) continue; CounterRes++; // collect second generation nodes Vec_IntClear( vTimeFanins ); Gia_LutForEachFanin( p, iObj, iFanin, k ) { if ( Gia_ObjIsCi(Gia_ManObj(p, iFanin)) ) Vec_IntPushUnique( vTimeFanins, iFanin ); else Gia_LutForEachFanin( p, iFanin, iFanin2, k2 ) Vec_IntPushUnique( vTimeFanins, iFanin2 ); } // print the results if ( fVeryVerbose ) { printf( "%5d Node %5d : %d %2d %2d ", Counter, iObj, nTimeCris, Vec_IntSize(vTimeCries), Vec_IntSize(vTimeFanins) ); Gia_LutForEachFanin( p, iObj, iFanin, k ) printf( "%d(%.2f)%s ", iFanin, Gia_ObjTimeSlack(p, iFanin), (puTCEdges[iObj] & (1< Degree ) continue; // order the fanins in the increasing order of criticalily if ( Vec_IntSize(vTimeCries) > 1 ) { iFanin = Vec_IntEntry( vTimeCries, 0 ); iFanin2 = Vec_IntEntry( vTimeCries, 1 ); if ( Gia_ObjTimeSlack(p, iFanin) < Gia_ObjTimeSlack(p, iFanin2) ) { Vec_IntWriteEntry( vTimeCries, 0, iFanin2 ); Vec_IntWriteEntry( vTimeCries, 1, iFanin ); } } if ( Vec_IntSize(vTimeCries) > 2 ) { iFanin = Vec_IntEntry( vTimeCries, 1 ); iFanin2 = Vec_IntEntry( vTimeCries, 2 ); if ( Gia_ObjTimeSlack(p, iFanin) < Gia_ObjTimeSlack(p, iFanin2) ) { Vec_IntWriteEntry( vTimeCries, 1, iFanin2 ); Vec_IntWriteEntry( vTimeCries, 2, iFanin ); } iFanin = Vec_IntEntry( vTimeCries, 0 ); iFanin2 = Vec_IntEntry( vTimeCries, 1 ); if ( Gia_ObjTimeSlack(p, iFanin) < Gia_ObjTimeSlack(p, iFanin2) ) { Vec_IntWriteEntry( vTimeCries, 0, iFanin2 ); Vec_IntWriteEntry( vTimeCries, 1, iFanin ); } } // add choice Gia_ManSpeedupObj( pNew, p, Gia_ManObj(p,iObj), vTimeFanins, vTimeCries ); // quit if the number of nodes is large if ( Gia_ManObjNum(pNew) > nNodesNew - 100 ) { printf( "Speedup stopped adding choices because there was too many to add.\n" ); break; } } Gia_ManTimeStop( p ); Vec_IntFree( vTimeCries ); Vec_IntFree( vTimeFanins ); ABC_FREE( puTCEdges ); if ( fVerbose ) printf( "Nodes: Total = %7d. 0-slack = %7d. Workable = %7d. Ratio = %4.2f\n", Gia_ManLutNum(p), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 ); if ( pTempTim ) { Tim_ManStop( (Tim_Man_t *)p->pManTime ); p->pManTime = pTempTim; } // derive AIG with choices //Gia_ManPrintStats( pNew, 0 ); pTemp = Gia_ManEquivToChoices( pNew, 1 ); Gia_ManStop( pNew ); //Gia_ManPrintStats( pTemp, 0 ); // pNew = Gia_ManDupOrderDfsChoices( pTemp ); // Gia_ManStop( pTemp ); //Gia_ManPrintStats( pNew, 0 ); // return pNew; return pTemp; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSplit.c000066400000000000000000000444321477524141600162160ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaSplit.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Structural AIG splitting.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaSplit.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Spl_Man_t_ Spl_Man_t; struct Spl_Man_t_ { // input data Gia_Man_t * pGia; // user AIG with nodes marked int iObj; // object ID int Limit; // limit on AIG nodes int fReverse; // enable reverse search // intermediate Vec_Bit_t * vMarksCIO; // CI/CO marks Vec_Bit_t * vMarksIn; // input marks Vec_Bit_t * vMarksNo; // node marks Vec_Bit_t * vMarksAnd; // AND node marks Vec_Int_t * vRoots; // nodes pointing to Nodes Vec_Int_t * vNodes; // nodes used in the window Vec_Int_t * vLeaves; // nodes pointed by Nodes Vec_Int_t * vAnds; // AND nodes used in the window // temporary Vec_Int_t * vFanouts; // fanouts of the node Vec_Int_t * vCands; // candidate nodes Vec_Int_t * vInputs; // non-trivial inputs }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Transforming to the internal LUT representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wec_t * Spl_ManToWecMapping( Gia_Man_t * p ) { Vec_Wec_t * vMapping = Vec_WecStart( Gia_ManObjNum(p) ); int Obj, Fanin, k; assert( Gia_ManHasMapping(p) ); Gia_ManForEachLut( p, Obj ) Gia_LutForEachFanin( p, Obj, Fanin, k ) Vec_WecPush( vMapping, Obj, Fanin ); return vMapping; } Vec_Int_t * Spl_ManFromWecMapping( Gia_Man_t * p, Vec_Wec_t * vMap ) { Vec_Int_t * vMapping, * vVec; int i, k, Obj; assert( Gia_ManHasMapping2(p) ); vMapping = Vec_IntAlloc( Gia_ManObjNum(p) + Vec_WecSizeSize(vMap) + 2*Vec_WecSizeUsed(vMap) ); Vec_IntFill( vMapping, Gia_ManObjNum(p), 0 ); Vec_WecForEachLevel( vMap, vVec, i ) if ( Vec_IntSize(vVec) > 0 ) { Vec_IntWriteEntry( vMapping, i, Vec_IntSize(vMapping) ); Vec_IntPush( vMapping, Vec_IntSize(vVec) ); Vec_IntForEachEntry( vVec, Obj, k ) Vec_IntPush( vMapping, Obj ); Vec_IntPush( vMapping, i ); } assert( Vec_IntSize(vMapping) < 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); return vMapping; } /**Function************************************************************* Synopsis [Creating manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Spl_Man_t * Spl_ManAlloc( Gia_Man_t * pGia, int Limit, int fReverse ) { int i, iObj; Spl_Man_t * p = ABC_CALLOC( Spl_Man_t, 1 ); p->pGia = pGia; p->Limit = Limit; p->fReverse = fReverse; // intermediate p->vMarksCIO = Vec_BitStart( Gia_ManObjNum(pGia) ); p->vMarksIn = Vec_BitStart( Gia_ManObjNum(pGia) ); p->vMarksNo = Vec_BitStart( Gia_ManObjNum(pGia) ); p->vMarksAnd = Vec_BitStart( Gia_ManObjNum(pGia) ); p->vRoots = Vec_IntAlloc( 100 ); p->vNodes = Vec_IntAlloc( 100 ); p->vLeaves = Vec_IntAlloc( 100 ); p->vAnds = Vec_IntAlloc( 100 ); // temporary p->vFanouts = Vec_IntAlloc( 100 ); p->vCands = Vec_IntAlloc( 100 ); p->vInputs = Vec_IntAlloc( 100 ); // mark CIs/COs Vec_BitWriteEntry( p->vMarksCIO, 0, 1 ); Gia_ManForEachCiId( pGia, iObj, i ) Vec_BitWriteEntry( p->vMarksCIO, iObj, 1 ); Gia_ManForEachCoId( pGia, iObj, i ) Vec_BitWriteEntry( p->vMarksCIO, iObj, 1 ); // mapping ABC_FREE( pGia->pRefs ); Gia_ManCreateRefs( pGia ); Gia_ManSetLutRefs( pGia ); assert( Gia_ManHasMapping(pGia) ); assert( !Gia_ManHasMapping2(pGia) ); pGia->vMapping2 = Spl_ManToWecMapping( pGia ); Vec_IntFreeP( &pGia->vMapping ); // fanout Gia_ManStaticFanoutStart( pGia ); return p; } void Spl_ManStop( Spl_Man_t * p ) { // fanout Gia_ManStaticFanoutStop( p->pGia ); // mapping assert( !Gia_ManHasMapping(p->pGia) ); assert( Gia_ManHasMapping2(p->pGia) ); p->pGia->vMapping = Spl_ManFromWecMapping( p->pGia, p->pGia->vMapping2 ); Vec_WecFreeP( &p->pGia->vMapping2 ); // intermediate Vec_BitFree( p->vMarksCIO ); Vec_BitFree( p->vMarksIn ); Vec_BitFree( p->vMarksNo ); Vec_BitFree( p->vMarksAnd ); Vec_IntFree( p->vRoots ); Vec_IntFree( p->vNodes ); Vec_IntFree( p->vLeaves ); Vec_IntFree( p->vAnds ); // temporary Vec_IntFree( p->vFanouts ); Vec_IntFree( p->vCands ); Vec_IntFree( p->vInputs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Takes Nodes and Marks. Returns Leaves and Roots.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Spl_ManWinFindLeavesRoots( Spl_Man_t * p ) { Vec_Int_t * vVec; int iObj, iFan, i, k; // collect leaves /* Vec_IntClear( p->vLeaves ); Gia_ManForEachLut2Vec( p->vNodes, p->pGia, vVec, iObj, i ) { assert( Vec_BitEntry(p->vMarksNo, iObj) ); Vec_IntForEachEntry( vVec, iFan, k ) if ( !Vec_BitEntry(p->vMarksNo, iFan) ) { Vec_BitWriteEntry(p->vMarksNo, iFan, 1); Vec_IntPush( p->vLeaves, iFan ); } } Vec_IntForEachEntry( p->vLeaves, iFan, i ) Vec_BitWriteEntry(p->vMarksNo, iFan, 0); */ Vec_IntClear( p->vLeaves ); Vec_IntForEachEntry( p->vAnds, iObj, i ) { Gia_Obj_t * pObj = Gia_ManObj( p->pGia, iObj ); assert( Vec_BitEntry(p->vMarksAnd, iObj) ); iFan = Gia_ObjFaninId0( pObj, iObj ); if ( !Vec_BitEntry(p->vMarksAnd, iFan) ) { assert( Gia_ObjIsLut2(p->pGia, iFan) || Vec_BitEntry(p->vMarksCIO, iFan) ); Vec_BitWriteEntry(p->vMarksAnd, iFan, 1); Vec_IntPush( p->vLeaves, iFan ); } iFan = Gia_ObjFaninId1( pObj, iObj ); if ( !Vec_BitEntry(p->vMarksAnd, iFan) ) { assert( Gia_ObjIsLut2(p->pGia, iFan) || Vec_BitEntry(p->vMarksCIO, iFan) ); Vec_BitWriteEntry(p->vMarksAnd, iFan, 1); Vec_IntPush( p->vLeaves, iFan ); } } Vec_IntForEachEntry( p->vLeaves, iFan, i ) Vec_BitWriteEntry(p->vMarksAnd, iFan, 0); // collect roots Vec_IntClear( p->vRoots ); Gia_ManForEachLut2Vec( p->vNodes, p->pGia, vVec, iObj, i ) Vec_IntForEachEntry( vVec, iFan, k ) Gia_ObjLutRefDecId( p->pGia, iFan ); Vec_IntForEachEntry( p->vAnds, iObj, i ) if ( Gia_ObjLutRefNumId(p->pGia, iObj) ) Vec_IntPush( p->vRoots, iObj ); Gia_ManForEachLut2Vec( p->vNodes, p->pGia, vVec, iObj, i ) Vec_IntForEachEntry( vVec, iFan, k ) Gia_ObjLutRefIncId( p->pGia, iFan ); } /**Function************************************************************* Synopsis [Computes LUTs that are fanouts of the node outside of the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Spl_ManLutFanouts_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vFanouts, Vec_Bit_t * vMarksNo, Vec_Bit_t * vMarksCIO ) { int iFanout, i; if ( Vec_BitEntry(vMarksNo, iObj) || Vec_BitEntry(vMarksCIO, iObj) ) return; if ( Gia_ObjIsLut2(p, iObj) ) { Vec_BitWriteEntry( vMarksCIO, iObj, 1 ); Vec_IntPush( vFanouts, iObj ); return; } Gia_ObjForEachFanoutStaticId( p, iObj, iFanout, i ) Spl_ManLutFanouts_rec( p, iFanout, vFanouts, vMarksNo, vMarksCIO ); } int Spl_ManLutFanouts( Gia_Man_t * p, int iObj, Vec_Int_t * vFanouts, Vec_Bit_t * vMarksNo, Vec_Bit_t * vMarksCIO ) { int i, iFanout; assert( Gia_ObjIsLut2(p, iObj) ); Vec_IntClear( vFanouts ); Gia_ObjForEachFanoutStaticId( p, iObj, iFanout, i ) Spl_ManLutFanouts_rec( p, iFanout, vFanouts, vMarksNo, vMarksCIO ); // clean up Vec_IntForEachEntry( vFanouts, iFanout, i ) Vec_BitWriteEntry( vMarksCIO, iFanout, 0 ); return Vec_IntSize(vFanouts); } /**Function************************************************************* Synopsis [Returns the number of fanins beloning to the set.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Spl_ManCountMarkedFanins( Gia_Man_t * p, int iObj, Vec_Bit_t * vMarks ) { int i, iFan, Count = 0; Vec_Int_t * vFanins = Gia_ObjLutFanins2(p, iObj); Vec_IntForEachEntry( vFanins, iFan, i ) if ( Vec_BitEntry(vMarks, iFan) ) Count++; return Count; } int Spl_ManFindGoodCand( Spl_Man_t * p ) { int i, iObj; int Res = 0, InCount, InCountMax = -1; // mark leaves Vec_IntForEachEntry( p->vInputs, iObj, i ) Vec_BitWriteEntry( p->vMarksIn, iObj, 1 ); // find candidate with maximum input overlap Vec_IntForEachEntry( p->vCands, iObj, i ) { InCount = Spl_ManCountMarkedFanins( p->pGia, iObj, p->vMarksIn ); if ( InCountMax < InCount ) { InCountMax = InCount; Res = iObj; } } // unmark leaves Vec_IntForEachEntry( p->vInputs, iObj, i ) Vec_BitWriteEntry( p->vMarksIn, iObj, 0 ); return Res; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Spl_ManFindOne( Spl_Man_t * p ) { Vec_Int_t * vVec; int nFanouts, iObj, iFan, i, k; int Res = 0; // deref Gia_ManForEachLut2Vec( p->vNodes, p->pGia, vVec, iObj, i ) Vec_IntForEachEntry( vVec, iFan, k ) Gia_ObjLutRefDecId( p->pGia, iFan ); // collect external nodes if ( p->fReverse && (Vec_IntSize(p->vNodes) & 1) ) { Vec_IntForEachEntry( p->vNodes, iObj, i ) { if ( Gia_ObjLutRefNumId(p->pGia, iObj) == 0 ) continue; assert( Gia_ObjLutRefNumId(p->pGia, iObj) > 0 ); if ( Gia_ObjLutRefNumId(p->pGia, iObj) >= 5 ) // skip nodes with high fanout! continue; nFanouts = Spl_ManLutFanouts( p->pGia, iObj, p->vFanouts, p->vMarksNo, p->vMarksCIO ); if ( Gia_ObjLutRefNumId(p->pGia, iObj) == 1 && nFanouts == 1 ) { Res = Vec_IntEntry(p->vFanouts, 0); goto finish; } //Vec_IntAppend( p->vCands, p->vFanouts ); } } // consider LUT inputs - get one that has no refs Vec_IntClear( p->vCands ); Vec_IntClear( p->vInputs ); Gia_ManForEachLut2Vec( p->vNodes, p->pGia, vVec, iObj, i ) Vec_IntForEachEntry( vVec, iFan, k ) if ( !Vec_BitEntry(p->vMarksNo, iFan) && !Vec_BitEntry(p->vMarksCIO, iFan) && !Gia_ObjLutRefNumId(p->pGia, iFan) ) { Vec_IntPush( p->vCands, iFan ); Vec_IntPush( p->vInputs, iFan ); } Res = Spl_ManFindGoodCand( p ); if ( Res ) goto finish; // collect candidates Vec_IntClear( p->vCands ); Vec_IntClear( p->vInputs ); Gia_ManForEachLut2Vec( p->vNodes, p->pGia, vVec, iObj, i ) Vec_IntForEachEntry( vVec, iFan, k ) if ( !Vec_BitEntry(p->vMarksNo, iFan) && !Vec_BitEntry(p->vMarksCIO, iFan) ) { Vec_IntPush( p->vCands, iFan ); Vec_IntPush( p->vInputs, iFan ); } // all inputs have refs - collect external nodes Vec_IntForEachEntry( p->vNodes, iObj, i ) { if ( Gia_ObjLutRefNumId(p->pGia, iObj) == 0 ) continue; assert( Gia_ObjLutRefNumId(p->pGia, iObj) > 0 ); if ( Gia_ObjLutRefNumId(p->pGia, iObj) >= 5 ) // skip nodes with high fanout! continue; nFanouts = Spl_ManLutFanouts( p->pGia, iObj, p->vFanouts, p->vMarksNo, p->vMarksCIO ); if ( Gia_ObjLutRefNumId(p->pGia, iObj) == 1 && nFanouts == 1 ) { Res = Vec_IntEntry(p->vFanouts, 0); goto finish; } Vec_IntAppend( p->vCands, p->vFanouts ); } // choose among not-so-good ones Res = Spl_ManFindGoodCand( p ); if ( Res ) goto finish; // get the first candidate if ( Res == 0 && Vec_IntSize(p->vCands) > 0 ) Res = Vec_IntEntry( p->vCands, 0 ); finish: // ref Gia_ManForEachLut2Vec( p->vNodes, p->pGia, vVec, iObj, i ) Vec_IntForEachEntry( vVec, iFan, k ) Gia_ObjLutRefIncId( p->pGia, iFan ); return Res; } /**Function************************************************************* Synopsis [Computing window for one pivot node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Spl_ManLutMffcSize( Gia_Man_t * p, int iObj, Vec_Int_t * vTemp, Vec_Bit_t * vMarksAnd ) { int iTemp, i, k = 0; assert( Gia_ObjIsLut2(p, iObj) ); //Vec_IntPrint( Gia_ObjLutFanins2(p, iObj) ); Gia_ManIncrementTravId( p ); Gia_ManCollectAnds( p, &iObj, 1, vTemp, Gia_ObjLutFanins2(p, iObj) ); Vec_IntForEachEntry( vTemp, iTemp, i ) if ( !Vec_BitEntry(vMarksAnd, iTemp) ) Vec_IntWriteEntry( vTemp, k++, iTemp ); Vec_IntShrink( vTemp, k ); return k; } void Spl_ManAddNode( Spl_Man_t * p, int iPivot, Vec_Int_t * vCands ) { int i, iObj; Vec_IntPush( p->vNodes, iPivot ); Vec_BitWriteEntry( p->vMarksNo, iPivot, 1 ); Vec_IntAppend( p->vAnds, vCands ); Vec_IntForEachEntry( vCands, iObj, i ) Vec_BitWriteEntry( p->vMarksAnd, iObj, 1 ); } int Spl_ManComputeOne( Spl_Man_t * p, int iPivot ) { int CountAdd, iObj, i; assert( Gia_ObjIsLut2(p->pGia, iPivot) ); //Gia_ManPrintCone2( p->pGia, Gia_ManObj(p->pGia, iPivot) ); // assume it was previously filled in Vec_IntForEachEntry( p->vNodes, iObj, i ) Vec_BitWriteEntry( p->vMarksNo, iObj, 0 ); Vec_IntForEachEntry( p->vAnds, iObj, i ) Vec_BitWriteEntry( p->vMarksAnd, iObj, 0 ); // double check that it is empty //Gia_ManForEachLut2( p->pGia, iObj ) // assert( !Vec_BitEntry(p->vMarksNo, iObj) ); //Gia_ManForEachLut2( p->pGia, iObj ) // assert( !Vec_BitEntry(p->vMarksAnd, iObj) ); // clean arrays Vec_IntClear( p->vNodes ); Vec_IntClear( p->vAnds ); // add root node Spl_ManLutMffcSize( p->pGia, iPivot, p->vCands, p->vMarksAnd ); Spl_ManAddNode( p, iPivot, p->vCands ); if ( Vec_IntSize(p->vAnds) > p->Limit ) return 0; //printf( "%d ", iPivot ); // add one node at a time while ( (iObj = Spl_ManFindOne(p)) ) { assert( Gia_ObjIsLut2(p->pGia, iObj) ); assert( !Vec_BitEntry(p->vMarksNo, iObj) ); CountAdd = Spl_ManLutMffcSize( p->pGia, iObj, p->vCands, p->vMarksAnd ); if ( Vec_IntSize(p->vAnds) + CountAdd > p->Limit ) break; Spl_ManAddNode( p, iObj, p->vCands ); //printf( "+%d ", iObj ); } //printf( "\n" ); Vec_IntSort( p->vNodes, 0 ); Vec_IntSort( p->vAnds, 0 ); Spl_ManWinFindLeavesRoots( p ); Vec_IntSort( p->vLeaves, 0 ); Vec_IntSort( p->vRoots, 0 ); return 1; } /**Function************************************************************* Synopsis [External procedures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManComputeOneWin( Gia_Man_t * pGia, int iPivot, Vec_Int_t ** pvRoots, Vec_Int_t ** pvNodes, Vec_Int_t ** pvLeaves, Vec_Int_t ** pvAnds ) { Spl_Man_t * p = (Spl_Man_t *)pGia->pSatlutWinman; assert( p != NULL ); if ( iPivot == -1 ) { Spl_ManStop( p ); pGia->pSatlutWinman = NULL; return 0; } if ( !Spl_ManComputeOne( p, iPivot ) ) { *pvRoots = NULL; *pvNodes = NULL; *pvLeaves = NULL; *pvAnds = NULL; return 0; } *pvRoots = p->vRoots; *pvNodes = p->vNodes; *pvLeaves = p->vLeaves; *pvAnds = p->vAnds; // Vec_IntPrint( p->vNodes ); return Vec_IntSize(p->vAnds); } void Gia_ManComputeOneWinStart( Gia_Man_t * pGia, int nAnds, int fReverse ) { assert( pGia->pSatlutWinman == NULL ); pGia->pSatlutWinman = Spl_ManAlloc( pGia, nAnds, fReverse ); } /**Function************************************************************* Synopsis [Testing procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Spl_ManComputeOneTest( Gia_Man_t * pGia ) { int iLut, Count; Gia_ManComputeOneWinStart( pGia, 64, 0 ); Gia_ManForEachLut2( pGia, iLut ) { Vec_Int_t * vRoots, * vNodes, * vLeaves, * vAnds; Count = Gia_ManComputeOneWin( pGia, iLut, &vRoots, &vNodes, &vLeaves, &vAnds ); printf( "Obj = %6d : Leaf = %2d. Node = %2d. Root = %2d. AND = %3d.\n", iLut, Vec_IntSize(vLeaves), Vec_IntSize(vNodes), Vec_IntSize(vRoots), Count ); } Gia_ManComputeOneWin( pGia, -1, NULL, NULL, NULL, NULL ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaStg.c000066400000000000000000000375211477524141600156610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [gia.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" #include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintStateEncoding( Vec_Vec_t * vCodes, int nBits ) { char * pBuffer; Vec_Int_t * vVec; int i, k, Bit; pBuffer = ABC_ALLOC( char, nBits + 1 ); pBuffer[nBits] = 0; Vec_VecForEachLevelInt( vCodes, vVec, i ) { printf( "%6d : ", i+1 ); memset( pBuffer, '-', (size_t)nBits ); Vec_IntForEachEntry( vVec, Bit, k ) { assert( Bit < nBits ); pBuffer[Bit] = '1'; } printf( "%s\n", pBuffer ); } ABC_FREE( pBuffer ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCreateOrGate( Gia_Man_t * p, Vec_Int_t * vLits ) { if ( Vec_IntSize(vLits) == 0 ) return 0; while ( Vec_IntSize(vLits) > 1 ) { int i, k = 0, Lit1, Lit2, LitRes; Vec_IntForEachEntryDouble( vLits, Lit1, Lit2, i ) { LitRes = Gia_ManHashOr( p, Lit1, Lit2 ); Vec_IntWriteEntry( vLits, k++, LitRes ); } if ( Vec_IntSize(vLits) & 1 ) Vec_IntWriteEntry( vLits, k++, Vec_IntEntryLast(vLits) ); Vec_IntShrink( vLits, k ); } assert( Vec_IntSize(vLits) == 1 ); return Vec_IntEntry(vLits, 0); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Gia_ManAssignCodes( int kHot, int nStates, int * pnBits ) { Vec_Vec_t * vCodes; int s, i1, i2, i3, i4, i5, nBits; assert( nStates > 0 ); assert( kHot >= 1 && kHot <= 5 ); vCodes = Vec_VecStart( nStates ); *pnBits = -1; if ( kHot == 1 ) { for ( i1 = 0; i1 < nStates; i1++ ) Vec_VecPushInt( vCodes, i1, i1 ); *pnBits = nStates; return vCodes; } if ( kHot == 2 ) { for ( nBits = kHot; nBits < ABC_INFINITY; nBits++ ) if ( nBits * (nBits-1) / 2 >= nStates ) break; *pnBits = nBits; s = 0; for ( i1 = 0; i1 < nBits; i1++ ) for ( i2 = i1 + 1; i2 < nBits; i2++ ) { Vec_VecPushInt( vCodes, s, i1 ); Vec_VecPushInt( vCodes, s, i2 ); if ( ++s == nStates ) return vCodes; } } if ( kHot == 3 ) { for ( nBits = kHot; nBits < ABC_INFINITY; nBits++ ) if ( nBits * (nBits-1) * (nBits-2) / 6 >= nStates ) break; *pnBits = nBits; s = 0; for ( i1 = 0; i1 < nBits; i1++ ) for ( i2 = i1 + 1; i2 < nBits; i2++ ) for ( i3 = i2 + 1; i3 < nBits; i3++ ) { Vec_VecPushInt( vCodes, s, i1 ); Vec_VecPushInt( vCodes, s, i2 ); Vec_VecPushInt( vCodes, s, i3 ); if ( ++s == nStates ) return vCodes; } } if ( kHot == 4 ) { for ( nBits = kHot; nBits < ABC_INFINITY; nBits++ ) if ( nBits * (nBits-1) * (nBits-2) * (nBits-3) / 24 >= nStates ) break; *pnBits = nBits; s = 0; for ( i1 = 0; i1 < nBits; i1++ ) for ( i2 = i1 + 1; i2 < nBits; i2++ ) for ( i3 = i2 + 1; i3 < nBits; i3++ ) for ( i4 = i3 + 1; i4 < nBits; i4++ ) { Vec_VecPushInt( vCodes, s, i1 ); Vec_VecPushInt( vCodes, s, i2 ); Vec_VecPushInt( vCodes, s, i3 ); Vec_VecPushInt( vCodes, s, i4 ); if ( ++s == nStates ) return vCodes; } } if ( kHot == 5 ) { for ( nBits = kHot; nBits < ABC_INFINITY; nBits++ ) if ( nBits * (nBits-1) * (nBits-2) * (nBits-3) * (nBits-4) / 120 >= nStates ) break; *pnBits = nBits; s = 0; for ( i1 = 0; i1 < nBits; i1++ ) for ( i2 = i1 + 1; i2 < nBits; i2++ ) for ( i3 = i2 + 1; i3 < nBits; i3++ ) for ( i4 = i3 + 1; i4 < nBits; i4++ ) for ( i5 = i4 + 1; i5 < nBits; i5++ ) { Vec_VecPushInt( vCodes, s, i1 ); Vec_VecPushInt( vCodes, s, i2 ); Vec_VecPushInt( vCodes, s, i3 ); Vec_VecPushInt( vCodes, s, i4 ); Vec_VecPushInt( vCodes, s, i5 ); if ( ++s == nStates ) return vCodes; } } assert( 0 ); return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManStgKHot( Vec_Int_t * vLines, int nIns, int nOuts, int nStates, int kHot, int fVerbose ) { Gia_Man_t * p, * pTemp; Vec_Int_t * vInMints, * vCurs, * vVec; Vec_Vec_t * vLitsNext, * vLitsOuts, * vCodes; int i, b, k, nBits, LitC, Lit; assert( Vec_IntSize(vLines) % 4 == 0 ); // produce state encoding vCodes = Gia_ManAssignCodes( kHot, nStates, &nBits ); assert( Vec_VecSize(vCodes) == nStates ); if ( fVerbose ) Gia_ManPrintStateEncoding( vCodes, nBits ); // start manager p = Gia_ManStart( 10000 ); p->pName = Abc_UtilStrsav( "stg" ); for ( i = 0; i < nIns + nBits; i++ ) Gia_ManAppendCi(p); // create input minterms Gia_ManHashAlloc( p ); vInMints = Vec_IntAlloc( 1 << nIns ); for ( i = 0; i < (1 << nIns); i++ ) { for ( Lit = 1, b = 0; b < nIns; b++ ) Lit = Gia_ManHashAnd( p, Lit, Abc_Var2Lit( b+1, !((i >> b) & 1) ) ); Vec_IntPush( vInMints, Lit ); } // create current states vCurs = Vec_IntAlloc( nStates ); Vec_VecForEachLevelInt( vCodes, vVec, i ) { Lit = 1; Vec_IntForEachEntry( vVec, b, k ) { assert( b >= 0 && b < nBits ); Lit = Gia_ManHashAnd( p, Lit, Abc_Var2Lit(1+nIns+b, (b= 0 && iMint < (1<= 0 && iCur < nStates ); assert( iNext >= 0 && iNext < nStates ); assert( iOut >= 0 && iOut < (1<> b) & 1 ) Vec_VecPushInt( vLitsOuts, b, LitC ); } Vec_IntFree( vInMints ); Vec_IntFree( vCurs ); Vec_VecFree( vCodes ); // create POs Vec_VecForEachLevelInt( vLitsOuts, vVec, b ) Gia_ManAppendCo( p, Gia_ManCreateOrGate(p, vVec) ); Vec_VecFree( vLitsOuts ); // create next states Vec_VecForEachLevelInt( vLitsNext, vVec, b ) Gia_ManAppendCo( p, Abc_LitNotCond( Gia_ManCreateOrGate(p, vVec), (bpName = Abc_UtilStrsav( "stg" ); for ( i = 0; i < nIns + nStates; i++ ) Gia_ManAppendCi(p); // create input minterms Gia_ManHashAlloc( p ); vInMints = Vec_IntAlloc( 1 << nIns ); for ( i = 0; i < (1 << nIns); i++ ) { for ( Lit = 1, b = 0; b < nIns; b++ ) Lit = Gia_ManHashAnd( p, Lit, Abc_Var2Lit( b+1, !((i >> b) & 1) ) ); Vec_IntPush( vInMints, Lit ); } // create current states vCurs = Vec_IntAlloc( nStates ); for ( i = 0; i < nStates; i++ ) Vec_IntPush( vCurs, Abc_Var2Lit( 1+nIns+i, !i ) ); // go through the lines vLitsNext = Vec_VecStart( nStates ); vLitsOuts = Vec_VecStart( nOuts ); for ( i = 0; i < Vec_IntSize(vLines); ) { int iMint = Vec_IntEntry(vLines, i++); int iCur = Vec_IntEntry(vLines, i++) - 1; int iNext = Vec_IntEntry(vLines, i++) - 1; int iOut = Vec_IntEntry(vLines, i++); assert( iMint >= 0 && iMint < (1<= 0 && iCur < nStates ); assert( iNext >= 0 && iNext < nStates ); assert( iOut >= 0 && iOut < (1<> b) & 1 ) { // Lit = Gia_ManHashOr( p, LitC, Vec_IntEntry(vOuts, b) ); // Vec_IntWriteEntry( vOuts, b, Lit ); Vec_VecPushInt( vLitsOuts, b, LitC ); } } Vec_IntFree( vInMints ); Vec_IntFree( vCurs ); // create POs Vec_VecForEachLevelInt( vLitsOuts, vVec, i ) Gia_ManAppendCo( p, Gia_ManCreateOrGate(p, vVec) ); Vec_VecFree( vLitsOuts ); // create next states Vec_VecForEachLevelInt( vLitsNext, vVec, i ) Gia_ManAppendCo( p, Abc_LitNotCond( Gia_ManCreateOrGate(p, vVec), !i ) ); Vec_VecFree( vLitsNext ); Gia_ManSetRegNum( p, nStates ); Gia_ManHashStop( p ); p = Gia_ManCleanup( pTemp = p ); Gia_ManStop( pTemp ); assert( !Gia_ManHasDangling(p) ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManStgPrint( FILE * pFile, Vec_Int_t * vLines, int nIns, int nOuts, int nStates ) { int i, nDigits = Abc_Base10Log( nStates ); assert( Vec_IntSize(vLines) % 4 == 0 ); for ( i = 0; i < Vec_IntSize(vLines); i += 4 ) { int iMint = Vec_IntEntry(vLines, i ); int iCur = Vec_IntEntry(vLines, i+1) - 1; int iNext = Vec_IntEntry(vLines, i+2) - 1; int iOut = Vec_IntEntry(vLines, i+3); assert( iMint >= 0 && iMint < (1<= 0 && iCur < nStates ); assert( iNext >= 0 && iNext < nStates ); assert( iOut >= 0 && iOut < (1< #define unlink _unlink #else #include #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Processing on a single core.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_StochProcessSingle( Gia_Man_t * p, char * pScript, int Rand, int TimeSecs ) { Gia_Man_t * pTemp, * pNew = Gia_ManDup( p ); Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), Gia_ManDup(p) ); if ( Abc_FrameIsBatchMode() ) { if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) { Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); return NULL; } } else { Abc_FrameSetBatchMode( 1 ); if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) { Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); return NULL; } Abc_FrameSetBatchMode( 0 ); } pTemp = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); if ( Gia_ManAndNum(pNew) > Gia_ManAndNum(pTemp) ) { Gia_ManStop( pNew ); pNew = Gia_ManDup( pTemp ); } return pNew; } 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_StochProcessSingle( pGia, pScript, Vec_IntEntry(vRands, i), TimeSecs ); Gia_ManStop( pGia ); Vec_PtrWriteEntry( vGias, i, pNew ); } Vec_IntFree( vRands ); } /**Function************************************************************* Synopsis [Processing on many cores.] 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 defined(__wasm) if ( 1 ) #else if ( system( (char *)Command ) ) #endif { fprintf( stderr, "The following command has returned non-zero exit status:\n" ); fprintf( stderr, "\"%s\"\n", (char *)Command ); 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); } /**Function************************************************************* Synopsis [Generic concurrent processing.] Description [User-defined problem-specific data and the way to process it.] SideEffects [] SeeAlso [] ***********************************************************************/ typedef struct StochSynData_t_ { Gia_Man_t * pIn; Gia_Man_t * pOut; char * pScript; int Rand; int TimeOut; } StochSynData_t; int Gia_StochProcess1( void * p ) { StochSynData_t * pData = (StochSynData_t *)p; assert( pData->pIn != NULL ); assert( pData->pOut == NULL ); pData->pOut = Gia_StochProcessOne( pData->pIn, pData->pScript, pData->Rand, pData->TimeOut ); return 1; } void Gia_StochProcess( Vec_Ptr_t * vGias, char * pScript, int nProcs, int TimeSecs, int fVerbose ) { if ( nProcs <= 2 ) { if ( fVerbose ) printf( "Running non-concurrent synthesis.\n" ), fflush(stdout); Gia_StochProcessArray( vGias, pScript, TimeSecs, fVerbose ); return; } StochSynData_t * pData = ABC_CALLOC( StochSynData_t, Vec_PtrSize(vGias) ); Vec_Ptr_t * vData = Vec_PtrAlloc( Vec_PtrSize(vGias) ); Gia_Man_t * pGia; int i; Abc_Random(1); Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) { pData[i].pIn = pGia; pData[i].pOut = NULL; pData[i].pScript = pScript; pData[i].Rand = Abc_Random(0) % 0x1000000; pData[i].TimeOut = TimeSecs; Vec_PtrPush( vData, pData+i ); } if ( fVerbose ) printf( "Running concurrent synthesis with %d processes.\n", nProcs ), fflush(stdout); Util_ProcessThreads( Gia_StochProcess1, vData, nProcs, TimeSecs, fVerbose ); // replace old AIGs by new AIGs Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) { Gia_ManStop( pGia ); Vec_PtrWriteEntry( vGias, i, pData[i].pOut ); } Vec_PtrFree( vData ); ABC_FREE( pData ); } /**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 abc-0.52/src/aig/gia/giaStr.c000066400000000000000000002046241477524141600156740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaStr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [AIG structuring.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaStr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/util/utilNam.h" #include "misc/vec/vecWec.h" #include "misc/tim/tim.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define STR_SUPER 100 #define MAX_TREE 10000 enum { STR_NONE = 0, STR_CONST0 = 1, STR_PI = 2, STR_AND = 3, STR_XOR = 4, STR_MUX = 5, STR_BUF = 6, STR_PO = 7, STR_UNUSED = 8 }; typedef struct Str_Obj_t_ Str_Obj_t; struct Str_Obj_t_ { unsigned Type : 4; // object type unsigned nFanins : 28; // fanin count int iOffset; // place where fanins are stored int iTop; // top level MUX int iCopy; // copy of this node }; typedef struct Str_Ntk_t_ Str_Ntk_t; struct Str_Ntk_t_ { int nObjs; // object count int nObjsAlloc; // alloc objects Str_Obj_t * pObjs; // objects Vec_Int_t vFanins; // object fanins int nObjCount[STR_UNUSED]; int nTrees; int nGroups; int DelayGain; }; typedef struct Str_Man_t_ Str_Man_t; struct Str_Man_t_ { // user data Gia_Man_t * pOld; // manager int nLutSize; // LUT size int fCutMin; // cut minimization // internal data Str_Ntk_t * pNtk; // balanced network // AIG under construction Gia_Man_t * pNew; // newly constructed Vec_Int_t * vDelays; // delays of each object }; static inline Str_Obj_t * Str_NtkObj( Str_Ntk_t * p, int i ) { assert( i < p->nObjs ); return p->pObjs + i; } static inline int Str_ObjFaninId( Str_Ntk_t * p, Str_Obj_t * pObj, int i ) { return Abc_Lit2Var( Vec_IntEntry(&p->vFanins, pObj->iOffset + i) ); } static inline Str_Obj_t * Str_ObjFanin( Str_Ntk_t * p, Str_Obj_t * pObj, int i ) { return Str_NtkObj( p, Str_ObjFaninId(p, pObj, i) ); } static inline int Str_ObjFaninC( Str_Ntk_t * p, Str_Obj_t * pObj, int i ) { return Abc_LitIsCompl( Vec_IntEntry(&p->vFanins, pObj->iOffset + i) ); } static inline int Str_ObjFaninCopy( Str_Ntk_t * p, Str_Obj_t * pObj, int i ) { return Abc_LitNotCond( Str_ObjFanin(p, pObj, i)->iCopy, Str_ObjFaninC(p, pObj, i) ); } static inline int Str_ObjId( Str_Ntk_t * p, Str_Obj_t * pObj ) { return pObj - p->pObjs; } #define Str_NtkManForEachObj( p, pObj ) \ for ( pObj = p->pObjs; Str_ObjId(p, pObj) < p->nObjs; pObj++ ) #define Str_NtkManForEachObjVec( vVec, p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Str_NtkObj(p, Vec_IntEntry(vVec,i))); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Logic network manipulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Str_ObjCreate( Str_Ntk_t * p, int Type, int nFanins, int * pFanins ) { Str_Obj_t * pObj = p->pObjs + p->nObjs; int i; assert( p->nObjs < p->nObjsAlloc ); pObj->Type = Type; pObj->nFanins = nFanins; pObj->iOffset = Vec_IntSize(&p->vFanins); pObj->iTop = pObj->iCopy = -1; for ( i = 0; i < nFanins; i++ ) { Vec_IntPush( &p->vFanins, pFanins[i] ); assert( pFanins[i] >= 0 ); } p->nObjCount[Type]++; return Abc_Var2Lit( p->nObjs++, 0 ); } static inline Str_Ntk_t * Str_NtkCreate( int nObjsAlloc, int nFaninsAlloc ) { Str_Ntk_t * p; p = ABC_CALLOC( Str_Ntk_t, 1 ); p->pObjs = ABC_ALLOC( Str_Obj_t, nObjsAlloc ); p->nObjsAlloc = nObjsAlloc; Str_ObjCreate( p, STR_CONST0, 0, NULL ); Vec_IntGrow( &p->vFanins, nFaninsAlloc ); return p; } static inline void Str_NtkDelete( Str_Ntk_t * p ) { // printf( "Total delay gain = %d.\n", p->DelayGain ); ABC_FREE( p->vFanins.pArray ); ABC_FREE( p->pObjs ); ABC_FREE( p ); } static inline void Str_NtkPs( Str_Ntk_t * p, abctime clk ) { printf( "Network contains %d ands, %d xors, %d muxes (%d trees in %d groups). ", p->nObjCount[STR_AND], p->nObjCount[STR_XOR], p->nObjCount[STR_MUX], p->nTrees, p->nGroups ); Abc_PrintTime( 1, "Time", clk ); } static inline void Str_ObjReadGroup( Str_Ntk_t * p, Str_Obj_t * pObj, int * pnGroups, int * pnMuxes ) { Str_Obj_t * pObj1, * pObj2; *pnGroups = *pnMuxes = 0; if ( pObj->iTop == 0 ) return; pObj1 = Str_NtkObj( p, pObj->iTop ); pObj2 = Str_NtkObj( p, pObj1->iTop ); *pnMuxes = pObj1 - pObj + 1; *pnGroups = (pObj2 - pObj + 1) / *pnMuxes; } static inline void Str_NtkPrintGroups( Str_Ntk_t * p ) { Str_Obj_t * pObj; int nGroups, nMuxes; Str_NtkManForEachObj( p, pObj ) if ( pObj->Type == STR_MUX && pObj->iTop > 0 ) { Str_ObjReadGroup( p, pObj, &nGroups, &nMuxes ); pObj += nGroups * nMuxes - 1; printf( "%d x %d ", nGroups, nMuxes ); } printf( "\n" ); } Gia_Man_t * Str_NtkToGia( Gia_Man_t * pGia, Str_Ntk_t * p ) { Gia_Man_t * pNew, * pTemp; Str_Obj_t * pObj; int k; assert( pGia->pMuxes == NULL ); pNew = Gia_ManStart( 3 * Gia_ManObjNum(pGia) / 2 ); pNew->pName = Abc_UtilStrsav( pGia->pName ); pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); Gia_ManHashStart( pNew ); Str_NtkManForEachObj( p, pObj ) { if ( pObj->Type == STR_PI ) pObj->iCopy = Gia_ManAppendCi( pNew ); else if ( pObj->Type == STR_AND ) { pObj->iCopy = 1; for ( k = 0; k < (int)pObj->nFanins; k++ ) pObj->iCopy = Gia_ManHashAnd( pNew, pObj->iCopy, Str_ObjFaninCopy(p, pObj, k) ); } else if ( pObj->Type == STR_XOR ) { pObj->iCopy = 0; for ( k = 0; k < (int)pObj->nFanins; k++ ) pObj->iCopy = Gia_ManHashXor( pNew, pObj->iCopy, Str_ObjFaninCopy(p, pObj, k) ); } else if ( pObj->Type == STR_MUX ) pObj->iCopy = Gia_ManHashMux( pNew, Str_ObjFaninCopy(p, pObj, 2), Str_ObjFaninCopy(p, pObj, 1), Str_ObjFaninCopy(p, pObj, 0) ); else if ( pObj->Type == STR_PO ) pObj->iCopy = Gia_ManAppendCo( pNew, Str_ObjFaninCopy(p, pObj, 0) ); else if ( pObj->Type == STR_CONST0 ) pObj->iCopy = 0; else assert( 0 ); } Gia_ManHashStop( pNew ); // assert( Gia_ManObjNum(pNew) <= Gia_ManObjNum(pGia) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Constructs a normalized AIG without structural hashing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupMuxesNoHash( Gia_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj, * pFan0, * pFan1, * pFanC; int i, iLit0, iLit1, fCompl; assert( p->pMuxes == NULL ); ABC_FREE( p->pRefs ); Gia_ManCreateRefs( p ); // discount nodes with one fanout pointed to by MUX type Gia_ManForEachAnd( p, pObj, i ) { if ( !Gia_ObjIsMuxType(pObj) ) continue; Gia_ObjRefDec(p, Gia_ObjFanin0(pObj)); Gia_ObjRefDec(p, Gia_ObjFanin1(pObj)); } // 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_ManFillValue(p); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); Gia_ManForEachAnd( p, pObj, i ) { if ( !Gia_ObjRefNumId(p, i) ) continue; if ( !Gia_ObjIsMuxType(pObj) ) pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) { iLit0 = Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)); iLit1 = Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)); fCompl = Abc_LitIsCompl(iLit0) ^ Abc_LitIsCompl(iLit1); pObj->Value = fCompl ^ Gia_ManAppendXorReal( pNew, Abc_LitRegular(iLit0), Abc_LitRegular(iLit1) ); } else { pFanC = Gia_ObjRecognizeMux( pObj, &pFan1, &pFan0 ); iLit0 = Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)); iLit1 = Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)); if ( iLit0 == iLit1 ) pObj->Value = iLit0; else if ( Abc_Lit2Var(iLit0) == Abc_Lit2Var(iLit1) ) { iLit1 = Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFanC)); fCompl = Abc_LitIsCompl(iLit0) ^ Abc_LitIsCompl(iLit1); pObj->Value = fCompl ^ Gia_ManAppendXorReal( pNew, Abc_LitRegular(iLit0), Abc_LitRegular(iLit1) ); } else pObj->Value = Gia_ManAppendMuxReal( pNew, Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFanC)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)) ); } } Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); assert( !Gia_ManHasDangling(pNew) ); return pNew; } /**Function************************************************************* Synopsis [Constructs AIG ordered for balancing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Str_MuxInputsCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) { if ( !pObj->fMark0 ) { Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); return; } Vec_IntPush( vNodes, Gia_ObjFaninId2p(p, pObj) ); Str_MuxInputsCollect_rec( p, Gia_ObjFanin0(pObj), vNodes ); Str_MuxInputsCollect_rec( p, Gia_ObjFanin1(pObj), vNodes ); } void Str_MuxInputsCollect( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) { assert( !pObj->fMark0 ); pObj->fMark0 = 1; Vec_IntClear( vNodes ); Str_MuxInputsCollect_rec( p, pObj, vNodes ); pObj->fMark0 = 0; } void Str_MuxStructCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) { if ( !pObj->fMark0 ) return; Str_MuxStructCollect_rec( p, Gia_ObjFanin0(pObj), vNodes ); Str_MuxStructCollect_rec( p, Gia_ObjFanin1(pObj), vNodes ); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); } void Str_MuxStructCollect( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) { assert( !pObj->fMark0 ); pObj->fMark0 = 1; Vec_IntClear( vNodes ); Str_MuxStructCollect_rec( p, pObj, vNodes ); pObj->fMark0 = 0; } void Str_MuxStructDump_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Str_t * vStr ) { if ( !pObj->fMark0 ) return; Vec_StrPush( vStr, '[' ); Vec_StrPush( vStr, '(' ); Vec_StrPrintNum( vStr, Gia_ObjFaninId2p(p, pObj) ); Vec_StrPush( vStr, ')' ); Str_MuxStructDump_rec( p, Gia_ObjFaninC2(p, pObj) ? Gia_ObjFanin0(pObj) : Gia_ObjFanin1(pObj), vStr ); Vec_StrPush( vStr, '|' ); Str_MuxStructDump_rec( p, Gia_ObjFaninC2(p, pObj) ? Gia_ObjFanin1(pObj) : Gia_ObjFanin0(pObj), vStr ); Vec_StrPush( vStr, ']' ); } void Str_MuxStructDump( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Str_t * vStr ) { assert( !pObj->fMark0 ); pObj->fMark0 = 1; Vec_StrClear( vStr ); Str_MuxStructDump_rec( p, pObj, vStr ); Vec_StrPush( vStr, '\0' ); pObj->fMark0 = 0; } int Str_ManMuxCountOne( char * p ) { int Count = 0; for ( ; *p; p++ ) Count += (*p == '['); return Count; } Vec_Wec_t * Str_ManDeriveTrees( Gia_Man_t * p ) { int fPrintStructs = 0; Abc_Nam_t * pNames; Vec_Wec_t * vGroups; Vec_Str_t * vStr; Gia_Obj_t * pObj, * pFanin; int i, iStructId, fFound; assert( p->pMuxes != NULL ); // mark MUXes whose only fanout is a MUX ABC_FREE( p->pRefs ); Gia_ManCreateRefs( p ); Gia_ManForEachMuxId( p, i ) { pObj = Gia_ManObj(p, i); pFanin = Gia_ObjFanin0(pObj); if ( Gia_ObjIsMux(p, pFanin) && Gia_ObjRefNum(p, pFanin) == 1 ) pFanin->fMark0 = 1; pFanin = Gia_ObjFanin1(pObj); if ( Gia_ObjIsMux(p, pFanin) && Gia_ObjRefNum(p, pFanin) == 1 ) pFanin->fMark0 = 1; } // traverse for top level MUXes vStr = Vec_StrAlloc( 1000 ); pNames = Abc_NamStart( 10000, 50 ); vGroups = Vec_WecAlloc( 1000 ); Vec_WecPushLevel( vGroups ); Gia_ManForEachMuxId( p, i ) { // skip internal pObj = Gia_ManObj(p, i); if ( pObj->fMark0 ) continue; // skip trees of size one if ( !Gia_ObjFanin0(pObj)->fMark0 && !Gia_ObjFanin1(pObj)->fMark0 ) continue; // hash the tree Str_MuxStructDump( p, pObj, vStr ); iStructId = Abc_NamStrFindOrAdd( pNames, Vec_StrArray(vStr), &fFound ); if ( !fFound ) Vec_WecPushLevel( vGroups ); assert( Abc_NamObjNumMax(pNames) == Vec_WecSize(vGroups) ); Vec_IntPush( Vec_WecEntry(vGroups, iStructId), i ); } if ( fPrintStructs ) { char * pTemp; Abc_NamManForEachObj( pNames, pTemp, i ) { printf( "%5d : ", i ); printf( "Occur = %4d ", Vec_IntSize(Vec_WecEntry(vGroups,i)) ); printf( "Size = %4d ", Str_ManMuxCountOne(pTemp) ); printf( "%s\n", pTemp ); } } Abc_NamStop( pNames ); Vec_StrFree( vStr ); return vGroups; } Vec_Int_t * Str_ManCreateRoots( Vec_Wec_t * vGroups, int nObjs ) { // map tree MUXes into their classes Vec_Int_t * vRoots; Vec_Int_t * vGroup; int i, k, Entry; vRoots = Vec_IntStartFull( nObjs ); Vec_WecForEachLevel( vGroups, vGroup, i ) Vec_IntForEachEntry( vGroup, Entry, k ) Vec_IntWriteEntry( vRoots, Entry, i ); return vRoots; } void Str_MuxTraverse_rec( Gia_Man_t * p, int i ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId(p, i) ) return; Gia_ObjSetTravIdCurrentId(p, i); pObj = Gia_ManObj(p, i); if ( !Gia_ObjIsAnd(pObj) ) return; Str_MuxTraverse_rec(p, Gia_ObjFaninId0(pObj, i) ); Str_MuxTraverse_rec(p, Gia_ObjFaninId1(pObj, i) ); if ( Gia_ObjIsMux(p, pObj) ) Str_MuxTraverse_rec(p, Gia_ObjFaninId2(p, i) ); } void Str_ManCheckOverlap( Gia_Man_t * p, Vec_Wec_t * vGroups ) { // check that members of each group are not in the TFI of each other Vec_Int_t * vGroup, * vGroup2; int i, k, n, iObj, iObj2; // vGroup = Vec_WecEntry(vGroups, 7); // Vec_IntForEachEntry( vGroup, iObj, n ) // Gia_ManPrintCone2( p, Gia_ManObj(p, iObj) ), printf( "\n" ); Vec_WecForEachLevel( vGroups, vGroup, i ) Vec_IntForEachEntry( vGroup, iObj, k ) { if ( Vec_IntSize(vGroup) == 1 ) continue; // high light the cone Gia_ManIncrementTravId( p ); Str_MuxTraverse_rec( p, iObj ); // check that none of the others are highlighted Vec_IntForEachEntry( vGroup, iObj2, n ) if ( iObj != iObj2 && Gia_ObjIsTravIdCurrentId(p, iObj2) ) break; if ( n == Vec_IntSize(vGroup) ) continue; // split the group into individual trees Vec_IntForEachEntryStart( vGroup, iObj2, n, 1 ) { vGroup2 = Vec_WecPushLevel( vGroups ); vGroup = Vec_WecEntry( vGroups, i ); Vec_IntPush( vGroup2, iObj2 ); } Vec_IntShrink( vGroup, 1 ); /* // this does not work because there can be a pair of independent trees // with another tree squeezed in between them, so that there is a combo loop // divide this group nNew = 0; vGroup2 = Vec_WecPushLevel( vGroups ); vGroup = Vec_WecEntry( vGroups, i ); Vec_IntForEachEntry( vGroup, iObj2, n ) { if ( iObj != iObj2 && Gia_ObjIsTravIdCurrentId(p, iObj2) ) Vec_IntPush( vGroup2, iObj2 ); else Vec_IntWriteEntry( vGroup, nNew++, iObj2 ); } Vec_IntShrink( vGroup, nNew ); i--; break; */ /* // check that none of the others are highlighted Vec_IntForEachEntry( vGroup, iObj, n ) if ( n != k && Gia_ObjIsTravIdCurrentId(p, iObj) ) { printf( "Overlap of TFI cones of trees %d and %d in group %d of size %d!\n", k, n, i, Vec_IntSize(vGroup) ); Vec_IntShrink( vGroup, 1 ); break; } */ } } /**Function************************************************************* Synopsis [Simplify multi-input AND/XOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSimplifyXor( Vec_Int_t * vSuper ) { int i, k = 0, Prev = -1, This, fCompl = 0; Vec_IntForEachEntry( vSuper, This, i ) { if ( This == 0 ) continue; if ( This == 1 ) fCompl ^= 1; else if ( Prev != This ) Vec_IntWriteEntry( vSuper, k++, This ), Prev = This; else Prev = -1, k--; } Vec_IntShrink( vSuper, k ); if ( Vec_IntSize( vSuper ) == 0 ) Vec_IntPush( vSuper, fCompl ); else if ( fCompl ) Vec_IntWriteEntry( vSuper, 0, Abc_LitNot(Vec_IntEntry(vSuper, 0)) ); } static inline void Gia_ManSimplifyAnd( Vec_Int_t * vSuper ) { int i, k = 0, Prev = -1, This; Vec_IntForEachEntry( vSuper, This, i ) { if ( This == 0 ) { Vec_IntFill(vSuper, 1, 0); return; } if ( This == 1 ) continue; if ( Prev == -1 || Abc_Lit2Var(Prev) != Abc_Lit2Var(This) ) Vec_IntWriteEntry( vSuper, k++, This ), Prev = This; else if ( Prev != This ) { Vec_IntFill(vSuper, 1, 0); return; } } Vec_IntShrink( vSuper, k ); if ( Vec_IntSize( vSuper ) == 0 ) Vec_IntPush( vSuper, 1 ); } /**Function************************************************************* Synopsis [Collect multi-input AND/XOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSuperCollectXor_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( !Gia_IsComplement(pObj) ); if ( !Gia_ObjIsXor(pObj) || Gia_ObjRefNum(p, pObj) > 1 || // Gia_ObjRefNum(p, pObj) > 3 || // (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || Vec_IntSize(p->vSuper) > STR_SUPER ) { Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) ); return; } assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ); Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj) ); Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj) ); } static inline void Gia_ManSuperCollectAnd_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_IsComplement(pObj) || !Gia_ObjIsAndReal(p, pObj) || Gia_ObjRefNum(p, pObj) > 1 || // Gia_ObjRefNum(p, pObj) > 3 || // (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || Vec_IntSize(p->vSuper) > STR_SUPER ) { Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) ); return; } Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj) ); Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj) ); } static inline void Gia_ManSuperCollect( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( p->vSuper == NULL ) p->vSuper = Vec_IntAlloc( STR_SUPER ); else Vec_IntClear( p->vSuper ); if ( Gia_ObjIsXor(pObj) ) { assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ); Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj) ); Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj) ); Vec_IntSort( p->vSuper, 0 ); Gia_ManSimplifyXor( p->vSuper ); } else if ( Gia_ObjIsAndReal(p, pObj) ) { Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj) ); Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj) ); Vec_IntSort( p->vSuper, 0 ); Gia_ManSimplifyAnd( p->vSuper ); } else assert( 0 ); assert( Vec_IntSize(p->vSuper) > 0 ); } /**Function************************************************************* Synopsis [Constructs AIG ordered for balancing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Str_ManNormalize_rec( Str_Ntk_t * pNtk, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Wec_t * vGroups, Vec_Int_t * vRoots ) { int i, k, iVar, iLit, iBeg, iEnd; if ( ~pObj->Value ) return; pObj->Value = 0; assert( Gia_ObjIsAnd(pObj) ); if ( Gia_ObjIsMux(p, pObj) ) { Vec_Int_t * vGroup; Gia_Obj_t * pRoot, * pMux; int pFanins[3]; if ( Vec_IntEntry(vRoots, Gia_ObjId(p, pObj)) == -1 ) { Str_ManNormalize_rec( pNtk, p, Gia_ObjFanin0(pObj), vGroups, vRoots ); Str_ManNormalize_rec( pNtk, p, Gia_ObjFanin1(pObj), vGroups, vRoots ); Str_ManNormalize_rec( pNtk, p, Gia_ObjFanin2(p, pObj), vGroups, vRoots ); pFanins[0] = Gia_ObjFanin0Copy(pObj); pFanins[1] = Gia_ObjFanin1Copy(pObj); pFanins[2] = Gia_ObjFanin2Copy(p, pObj); if ( Abc_LitIsCompl(pFanins[2]) ) { pFanins[2] = Abc_LitNot(pFanins[2]); ABC_SWAP( int, pFanins[0], pFanins[1] ); } pObj->Value = Str_ObjCreate( pNtk, STR_MUX, 3, pFanins ); return; } vGroup = Vec_WecEntry( vGroups, Vec_IntEntry(vRoots, Gia_ObjId(p, pObj)) ); // build data-inputs for each tree Gia_ManForEachObjVec( vGroup, p, pRoot, i ) { Str_MuxInputsCollect( p, pRoot, p->vSuper ); iBeg = Vec_IntSize( p->vStore ); Vec_IntAppend( p->vStore, p->vSuper ); iEnd = Vec_IntSize( p->vStore ); Vec_IntForEachEntryStartStop( p->vStore, iVar, k, iBeg, iEnd ) Str_ManNormalize_rec( pNtk, p, Gia_ManObj(p, iVar), vGroups, vRoots ); Vec_IntShrink( p->vStore, iBeg ); } // build internal structures Gia_ManForEachObjVec( vGroup, p, pRoot, i ) { Str_MuxStructCollect( p, pRoot, p->vSuper ); Gia_ManForEachObjVec( p->vSuper, p, pMux, k ) { pFanins[0] = Gia_ObjFanin0Copy(pMux); pFanins[1] = Gia_ObjFanin1Copy(pMux); pFanins[2] = Gia_ObjFanin2Copy(p, pMux); if ( Abc_LitIsCompl(pFanins[2]) ) { pFanins[2] = Abc_LitNot(pFanins[2]); ABC_SWAP( int, pFanins[0], pFanins[1] ); } pMux->Value = Str_ObjCreate( pNtk, STR_MUX, 3, pFanins ); } assert( ~pRoot->Value ); // set mapping Gia_ManForEachObjVec( p->vSuper, p, pMux, k ) Str_NtkObj(pNtk, Abc_Lit2Var(pMux->Value))->iTop = Abc_Lit2Var(pRoot->Value); pNtk->nTrees++; } assert( ~pObj->Value ); // set mapping pObj = Gia_ManObj( p, Vec_IntEntryLast(vGroup) ); Gia_ManForEachObjVec( vGroup, p, pRoot, i ) Str_NtkObj(pNtk, Abc_Lit2Var(pRoot->Value))->iTop = Abc_Lit2Var(pObj->Value); pNtk->nGroups++; //printf( "%d x %d ", Vec_IntSize(vGroup), Vec_IntSize(p->vSuper) ); return; } // find supergate Gia_ManSuperCollect( p, pObj ); // save entries iBeg = Vec_IntSize( p->vStore ); Vec_IntAppend( p->vStore, p->vSuper ); iEnd = Vec_IntSize( p->vStore ); // call recursively Vec_IntForEachEntryStartStop( p->vStore, iLit, i, iBeg, iEnd ) { Gia_Obj_t * pTemp = Gia_ManObj( p, Abc_Lit2Var(iLit) ); Str_ManNormalize_rec( pNtk, p, pTemp, vGroups, vRoots ); Vec_IntWriteEntry( p->vStore, i, Abc_LitNotCond(pTemp->Value, Abc_LitIsCompl(iLit)) ); } assert( Vec_IntSize(p->vStore) == iEnd ); // consider general case pObj->Value = Str_ObjCreate( pNtk, Gia_ObjIsXor(pObj) ? STR_XOR : STR_AND, iEnd-iBeg, Vec_IntEntryP(p->vStore, iBeg) ); Vec_IntShrink( p->vStore, iBeg ); } Str_Ntk_t * Str_ManNormalizeInt( Gia_Man_t * p, Vec_Wec_t * vGroups, Vec_Int_t * vRoots ) { Str_Ntk_t * pNtk; Gia_Obj_t * pObj; int i, iFanin; assert( p->pMuxes != NULL ); if ( p->vSuper == NULL ) p->vSuper = Vec_IntAlloc( STR_SUPER ); if ( p->vStore == NULL ) p->vStore = Vec_IntAlloc( STR_SUPER ); Gia_ManFillValue( 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 ) { if ( Gia_ObjIsCi(pObj) ) pObj->Value = Str_ObjCreate( pNtk, STR_PI, 0, NULL ); else if ( Gia_ObjIsCo(pObj) ) { Str_ManNormalize_rec( pNtk, p, Gia_ObjFanin0(pObj), vGroups, vRoots ); iFanin = Gia_ObjFanin0Copy(pObj); pObj->Value = Str_ObjCreate( pNtk, STR_PO, 1, &iFanin ); } } //assert( pNtk->nObjs <= Gia_ManObjNum(p) ); return pNtk; } Str_Ntk_t * Str_ManNormalize( Gia_Man_t * p ) { Str_Ntk_t * pNtk; Gia_Man_t * pMuxes = Gia_ManDupMuxes( p, 5 ); Vec_Wec_t * vGroups = Str_ManDeriveTrees( pMuxes ); Vec_Int_t * vRoots; Str_ManCheckOverlap( pMuxes, vGroups ); vRoots = Str_ManCreateRoots( vGroups, Gia_ManObjNum(pMuxes) ); pNtk = Str_ManNormalizeInt( pMuxes, vGroups, vRoots ); Gia_ManCleanMark0( pMuxes ); Gia_ManStop( pMuxes ); Vec_IntFree( vRoots ); Vec_WecFree( vGroups ); return pNtk; } /**Function************************************************************* Synopsis [Delay computation] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Str_Delay2( int d0, int d1, int nLutSize ) { int n, d = Abc_MaxInt( d0 >> 4, d1 >> 4 ); n = (d == (d0 >> 4)) ? (d0 & 15) : 1; n += (d == (d1 >> 4)) ? (d1 & 15) : 1; return (d << 4) + (n > nLutSize ? 18 : n); } static inline int Str_Delay3( int d0, int d1, int d2, int nLutSize ) { int n, d = Abc_MaxInt( Abc_MaxInt(d0 >> 4, d1 >> 4), d2 >> 4 ); n = (d == (d0 >> 4)) ? (d0 & 15) : 1; n += (d == (d1 >> 4)) ? (d1 & 15) : 1; n += (d == (d2 >> 4)) ? (d2 & 15) : 1; return (d << 4) + (n > nLutSize ? 19 : n); } static inline int Str_ObjDelay( Gia_Man_t * pNew, int iObj, int nLutSize, Vec_Int_t * vDelay ) { int Delay = Vec_IntEntry( vDelay, iObj ); if ( Delay == 0 ) { if ( Gia_ObjIsMuxId(pNew, iObj) ) { int d0 = Vec_IntEntry( vDelay, Gia_ObjFaninId0(Gia_ManObj(pNew, iObj), iObj) ); int d1 = Vec_IntEntry( vDelay, Gia_ObjFaninId1(Gia_ManObj(pNew, iObj), iObj) ); int d2 = Vec_IntEntry( vDelay, Gia_ObjFaninId2(pNew, iObj) ); Delay = Str_Delay3( d0, d1, d2, nLutSize ); } else { int d0 = Vec_IntEntry( vDelay, Gia_ObjFaninId0(Gia_ManObj(pNew, iObj), iObj) ); int d1 = Vec_IntEntry( vDelay, Gia_ObjFaninId1(Gia_ManObj(pNew, iObj), iObj) ); Delay = Str_Delay2( d0, d1, nLutSize ); } Vec_IntWriteEntry( vDelay, iObj, Delay ); } return Delay; } /**Function************************************************************* Synopsis [Transposing 64-bit matrix.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void transpose64( word A[64] ) { int j, k; word t, m = 0x00000000FFFFFFFF; for ( j = 32; j != 0; j = j >> 1, m = m ^ (m << j) ) { for ( k = 0; k < 64; k = (k + j + 1) & ~j ) { t = (A[k] ^ (A[k+j] >> j)) & m; A[k] = A[k] ^ t; A[k+j] = A[k+j] ^ (t << j); } } } /**Function************************************************************* Synopsis [Perform affinity computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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, int nLimit ) { int fVerbose = 0; 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 ) { Gia_ObjSetTravIdCurrentId( p, Abc_Lit2Var(iLit) ); Str_ManSetNum( p, Abc_Lit2Var(iLit), i ); Matrix[i] = ((word)1) << (63-i); Levels[i] = 0; } // collect 64 nodes Vec_IntForEachEntry( vSuper, iLit, i ) { Gia_Obj_t * pObj = Gia_ManObj( p, Abc_Lit2Var(iLit) ); if ( Gia_ObjIsAnd(pObj) ) { for ( k = 0; k < 2; k++ ) { iFanin = k ? Gia_ObjFaninId1p(p, pObj) : Gia_ObjFaninId0p(p, pObj); if ( !Gia_ObjIsTravIdCurrentId(p, iFanin) ) { if ( Vec_IntSize(vSuper) == nLimit ) break; Gia_ObjSetTravIdCurrentId( p, iFanin ); Matrix[Vec_IntSize(vSuper)] = 0; Levels[Vec_IntSize(vSuper)] = nLevels; Str_ManSetNum( p, iFanin, Vec_IntSize(vSuper) ); Vec_IntPush( vSuper, Abc_Var2Lit(iFanin, 0) ); } Matrix[Str_ManNum(p, iFanin)] |= Matrix[i]; } } if ( Gia_ObjIsMux(p, pObj) ) { iFanin = Gia_ObjFaninId2p(p, pObj); if ( !Gia_ObjIsTravIdCurrentId(p, iFanin) ) { if ( Vec_IntSize(vSuper) == nLimit ) break; Gia_ObjSetTravIdCurrentId( p, iFanin ); Matrix[Vec_IntSize(vSuper)] = 0; Levels[Vec_IntSize(vSuper)] = nLevels; Str_ManSetNum( p, iFanin, Vec_IntSize(vSuper) ); Vec_IntPush( vSuper, Abc_Var2Lit(iFanin, 0) ); } Matrix[Str_ManNum(p, iFanin)] |= Matrix[i]; } if ( Prev == i ) Prev = Vec_IntSize(vSuper), nLevels++; if ( nLevels == 8 ) break; } // remove those that have all 1s or only one 1 Mask = (~(word)0) << (64 - nSize); for ( k = i = 0; i < Vec_IntSize(vSuper); i++ ) { assert( Matrix[i] ); if ( (Matrix[i] & (Matrix[i] - 1)) == 0 ) continue; if ( Matrix[i] == Mask ) continue; Matrix[k] = Matrix[i]; Levels[k] = Levels[i]; k++; if ( k == 64 ) break; } // clean the remaining ones for ( i = k; i < 64; i++ ) Matrix[i] = 0; nSizeNew = k; if ( nSizeNew == 0 ) { Vec_IntShrink( vSuper, nSize ); ABC_FREE( Levels ); return 0; } /* // report if ( fVerbose && nSize > 20 ) { for ( i = 0; i < nSizeNew; i++ ) Extra_PrintBinary( stdout, Matrix+i, 64 ), printf( "\n" ); printf( "\n" ); } */ transpose64( Matrix ); // report if ( fVerbose && nSize > 10 ) { printf( "Gate inputs = %d. Collected fanins = %d. All = %d. Good = %d. Levels = %d\n", nSize, Vec_IntSize(vSuper) - nSize, Vec_IntSize(vSuper), nSizeNew, nLevels ); printf( " " ); for ( i = 0; i < nSizeNew; i++ ) printf( "%d", Levels[i] ); printf( "\n" ); for ( i = 0; i < nSize; i++ ) { printf( "%6d : ", Abc_Lit2Var(Vec_IntEntry(vSuper, i)) ); printf( "%3d ", Vec_IntEntry(vDelay, i) >> 4 ); printf( "%3d ", Vec_IntEntry(vDelay, i) & 15 ); // Extra_PrintBinary( stdout, Matrix+i, 64 ), printf( "\n" ); } i = 0; } ABC_FREE( Levels ); Vec_IntShrink( vSuper, nSize ); return nSizeNew; } /**Function************************************************************* Synopsis [Count 1s.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Str_CountBits( word i ) { if ( i == 0 ) return 0; i = (i & (i - 1)); if ( i == 0 ) return 1; i = (i & (i - 1)); if ( i == 0 ) return 2; i = i - ((i >> 1) & 0x5555555555555555); i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); return (i*(0x0101010101010101))>>56; } static inline void Str_PrintState( int * pCost, int * pSuper, word * pMatrix, int nSize ) { int i; for ( i = 0; i < nSize; i++ ) { printf( "%6d : ", i ); printf( "%6d : ", Abc_Lit2Var(pSuper[i]) ); printf( "%3d ", pCost[i] >> 4 ); printf( "%3d ", pCost[i] & 15 ); // Extra_PrintBinary( stdout, pMatrix+i, 64 ), printf( "\n" ); } printf( "\n" ); } /**Function************************************************************* Synopsis [Perform balancing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Str_NtkBalanceMulti2( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec_Int_t * vDelay, int nLutSize ) { int k; pObj->iCopy = (pObj->Type == STR_AND); for ( k = 0; k < (int)pObj->nFanins; k++ ) { if ( pObj->Type == STR_AND ) pObj->iCopy = Gia_ManHashAnd( pNew, pObj->iCopy, Str_ObjFaninCopy(p, pObj, k) ); else pObj->iCopy = Gia_ManHashXorReal( pNew, pObj->iCopy, Str_ObjFaninCopy(p, pObj, k) ); Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay ); } } int Str_NtkBalanceTwo( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, int i, int j, Vec_Int_t * vDelay, int * pCost, int * pSuper, word * pMatrix, int nSize, int nLutSize, int CostBest ) { int k, iLitRes, Delay; assert( i < j ); // printf( "Merging node %d and %d\n", i, j ); if ( pObj->Type == STR_AND ) iLitRes = Gia_ManHashAnd( pNew, pSuper[i], pSuper[j] ); else iLitRes = Gia_ManHashXorReal( pNew, pSuper[i], pSuper[j] ); Delay = Str_ObjDelay( pNew, Abc_Lit2Var(iLitRes), nLutSize, vDelay ); // update pCost[i] = Delay; pSuper[i] = iLitRes; pMatrix[i] |= pMatrix[j]; // assert( (pCost[i] & 15) == CostBest || CostBest == -1 ); // remove entry j nSize--; for ( k = j; k < nSize; k++ ) { pCost[k] = pCost[k+1]; pSuper[k] = pSuper[k+1]; pMatrix[k] = pMatrix[k+1]; } // move up the first one nSize--; for ( k = 0; k < nSize; k++ ) { if ( pCost[k] <= pCost[k+1] ) break; ABC_SWAP( int, pCost[k], pCost[k+1] ); ABC_SWAP( int, pSuper[k], pSuper[k+1] ); ABC_SWAP( word, pMatrix[k], pMatrix[k+1] ); } return iLitRes; } void Str_NtkBalanceMulti( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec_Int_t * vDelay, int nLutSize ) { 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( (int)pObj->nFanins <= Vec_IntCap(vSuper) ); assert( (int)pObj->nFanins <= Vec_IntCap(vCosts) ); // collect nodes Vec_IntClear( vSuper ); for ( k = 0; k < (int)pObj->nFanins; k++ ) Vec_IntPush( vSuper, Str_ObjFaninCopy(p, pObj, k) ); Vec_IntSort( vSuper, 0 ); if ( pObj->Type == STR_AND ) Gia_ManSimplifyAnd( vSuper ); else Gia_ManSimplifyXor( vSuper ); assert( Vec_IntSize(vSuper) > 0 ); 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; } // sort by cost Vec_IntClear( vCosts ); Vec_IntForEachEntry( vSuper, iLit, k ) Vec_IntPush( vCosts, Vec_IntEntry(vDelay, Abc_Lit2Var(iLit)) ); Vec_IntSelectSortCost2( pSuper, Vec_IntSize(vSuper), pCost ); // compute affinity if ( Vec_IntSize(vSuper) < 64 ) MatrixSize = Str_ManVectorAffinity( pNew, vSuper, vCosts, pMatrix, pObj->nFanins ); // start the new product while ( Vec_IntSize(vSuper) > 2 ) { // pair the first entry with another one on the same level int i, iStop, iBest,iBest2; int CostNew, CostBest, CostBest2; int OccurNew, OccurBest, OccurBest2; if ( Vec_IntSize(vSuper) > 64 ) { Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, -1 ); vSuper->nSize--; vCosts->nSize--; continue; } // compute affinity if ( Vec_IntSize(vSuper) == 64 ) MatrixSize = Str_ManVectorAffinity( pNew, vSuper, vCosts, pMatrix, pObj->nFanins ); assert( Vec_IntSize(vSuper) <= 64 ); // Str_PrintState( pCost, pSuper, pMatrix, Vec_IntSize(vSuper) ); // if the first two are PIs group them if ( pCost[0] == 17 && pCost[1] == 17 ) { Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, 2 ); vSuper->nSize--; vCosts->nSize--; continue; } // find the end of the level for ( iStop = 0; iStop < Vec_IntSize(vSuper); iStop++ ) if ( (pCost[iStop] >> 4) != (pCost[0] >> 4) ) break; // if there is only one this level, pair it with the best match in the next level if ( iStop == 1 ) { iBest = iStop, OccurBest = Str_CountBits(pMatrix[0] & pMatrix[iStop]); for ( i = iStop + 1; i < Vec_IntSize(vSuper); i++ ) { if ( (pCost[i] >> 4) != (pCost[iStop] >> 4) ) break; OccurNew = Str_CountBits(pMatrix[0] & pMatrix[i]); if ( OccurBest < OccurNew ) iBest = i, OccurBest = OccurNew; } assert( iBest > 0 && iBest < Vec_IntSize(vSuper) ); Str_NtkBalanceTwo( pNew, p, pObj, 0, iBest, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, -1 ); vSuper->nSize--; vCosts->nSize--; continue; } // pair the first entry with another one on the same level iBest = -1; CostBest = -1; OccurBest2 = -1; OccurBest = -1; for ( i = 1; i < iStop; i++ ) { CostNew = (pCost[0] & 15) + (pCost[i] & 15); if ( CostNew > nLutSize ) continue; OccurNew = Str_CountBits(pMatrix[0] & pMatrix[i]); if ( CostBest < CostNew || (CostBest == CostNew && OccurBest < OccurNew) ) CostBest = CostNew, iBest = i, OccurBest = OccurNew; } // if the best found is perfect, take it if ( CostBest == nLutSize ) { assert( iBest > 0 && iBest < Vec_IntSize(vSuper) ); Str_NtkBalanceTwo( pNew, p, pObj, 0, iBest, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, CostBest ); vSuper->nSize--; vCosts->nSize--; continue; } // find the best pair on this level iBest = iBest2 = -1; CostBest = CostBest2 = -1, OccurBest = OccurBest2 = -1; for ( i = 0; i < iStop; i++ ) for ( k = i+1; k < iStop; k++ ) { CostNew = (pCost[i] & 15) + (pCost[k] & 15); OccurNew = Str_CountBits(pMatrix[i] & pMatrix[k]); if ( CostNew <= nLutSize ) // the same level { if ( OccurBest < OccurNew || (OccurBest == OccurNew && CostBest < CostNew )) CostBest = CostNew, iBest = (i << 16) | k, OccurBest = OccurNew; } else // overflow to the next level { if ( OccurBest2 < OccurNew || (OccurBest2 == OccurNew && CostBest2 < CostNew) ) CostBest2 = CostNew, iBest2 = (i << 16) | k, OccurBest2 = OccurNew; } } if ( iBest >= 0 ) { assert( iBest > 0 ); Str_NtkBalanceTwo( pNew, p, pObj, iBest>>16, iBest&0xFFFF, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, CostBest ); vSuper->nSize--; vCosts->nSize--; continue; } // take any remaining pair assert( iBest2 > 0 ); Str_NtkBalanceTwo( pNew, p, pObj, iBest2>>16, iBest2&0xFFFF, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, -1 ); vSuper->nSize--; vCosts->nSize--; continue; } pObj->iCopy = Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, 2, nLutSize, -1 ); ABC_FREE( pMatrix ); /* // simple pObj->iCopy = (pObj->Type == STR_AND); for ( k = 0; k < Vec_IntSize(vSuper); k++ ) { if ( pObj->Type == STR_AND ) pObj->iCopy = Gia_ManHashAnd( pNew, pObj->iCopy, Vec_IntEntry(vSuper, k) ); else pObj->iCopy = Gia_ManHashXorReal( pNew, pObj->iCopy, Vec_IntEntry(vSuper, k) ); Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay ); } */ } void Str_NtkBalanceMux( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec_Int_t * vDelay, int nLutSize, int nGroups, int nMuxes, int fRecursive, int fOptArea, int fVerbose ) { extern int Str_MuxRestructure( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fRecursive, int fOptArea, int fVerbose ); int n, m, iRes, fUseRestruct = 1; if ( fUseRestruct ) { for ( n = 0; n < nGroups; n++ ) { iRes = Str_MuxRestructure( pNew, p, Str_ObjId(p, pObj), nMuxes, vDelay, nLutSize, fRecursive, fOptArea, fVerbose ); if ( iRes == -1 ) { for ( m = 0; m < nMuxes; m++, pObj++ ) { pObj->iCopy = Gia_ManHashMuxReal( pNew, Str_ObjFaninCopy(p, pObj, 2), Str_ObjFaninCopy(p, pObj, 1), Str_ObjFaninCopy(p, pObj, 0) ); Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay ); } } else { pObj += nMuxes - 1; pObj->iCopy = iRes; pObj++; } } } else { for ( n = 0; n < nGroups * nMuxes; n++, pObj++ ) { pObj->iCopy = Gia_ManHashMuxReal( pNew, Str_ObjFaninCopy(p, pObj, 2), Str_ObjFaninCopy(p, pObj, 1), Str_ObjFaninCopy(p, pObj, 0) ); Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay ); } } } Gia_Man_t * Str_NtkBalance( Gia_Man_t * pGia, Str_Ntk_t * p, int nLutSize, int fUseMuxes, int fRecursive, int fOptArea, int fVerbose ) { Gia_Man_t * pNew, * pTemp; Vec_Int_t * vDelay; Str_Obj_t * pObj; int nGroups, nMuxes, CioId; int arrTime, Delay = 0; assert( nLutSize < 16 ); assert( pGia->pMuxes == NULL ); pNew = Gia_ManStart( Gia_ManObjNum(pGia) ); pNew->pName = Abc_UtilStrsav( pGia->pName ); pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); Vec_IntFill( &pNew->vCopies, pNew->nObjsAlloc, -1 ); if ( pNew->vSuper == NULL ) pNew->vSuper = Vec_IntAlloc( 1000 ); if ( pNew->vStore == NULL ) pNew->vStore = Vec_IntAlloc( 1000 ); vDelay = Vec_IntStart( 2*pNew->nObjsAlloc ); Gia_ManHashStart( pNew ); if ( pGia->pManTime != NULL ) // Tim_Man with unit delay 16 { Tim_ManInitPiArrivalAll( (Tim_Man_t *)pGia->pManTime, 17 ); Tim_ManIncrementTravId( (Tim_Man_t *)pGia->pManTime ); } Str_NtkManForEachObj( p, pObj ) { if ( pObj->Type == STR_PI ) { pObj->iCopy = Gia_ManAppendCi( pNew ); arrTime = 17; if ( pGia->pManTime != NULL ) { CioId = Gia_ObjCioId( Gia_ManObj(pNew, Abc_Lit2Var(pObj->iCopy)) ); arrTime = (int)Tim_ManGetCiArrival( (Tim_Man_t *)pGia->pManTime, CioId ); } Vec_IntWriteEntry( vDelay, Abc_Lit2Var(pObj->iCopy), arrTime ); } else if ( pObj->Type == STR_AND || pObj->Type == STR_XOR ) Str_NtkBalanceMulti( pNew, p, pObj, vDelay, nLutSize ); else if ( pObj->Type == STR_MUX && pObj->iTop >= 0 && fUseMuxes ) { Str_ObjReadGroup( p, pObj, &nGroups, &nMuxes ); assert( nGroups * nMuxes >= 2 ); Str_NtkBalanceMux( pNew, p, pObj, vDelay, nLutSize, nGroups, nMuxes, fRecursive, fOptArea, fVerbose ); pObj += nGroups * nMuxes - 1; } else if ( pObj->Type == STR_MUX ) { pObj->iCopy = Gia_ManHashMuxReal( pNew, Str_ObjFaninCopy(p, pObj, 2), Str_ObjFaninCopy(p, pObj, 1), Str_ObjFaninCopy(p, pObj, 0) ); Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay ); } else if ( pObj->Type == STR_PO ) { pObj->iCopy = Gia_ManAppendCo( pNew, Str_ObjFaninCopy(p, pObj, 0) ); arrTime = Vec_IntEntry(vDelay, Abc_Lit2Var(Str_ObjFaninCopy(p, pObj, 0)) ); Delay = Abc_MaxInt( Delay, arrTime ); if ( pGia->pManTime != NULL ) { CioId = Gia_ObjCioId( Gia_ManObj(pNew, Abc_Lit2Var(pObj->iCopy)) ); Tim_ManSetCoArrival( (Tim_Man_t *)pGia->pManTime, CioId, (float)arrTime ); } } else if ( pObj->Type == STR_CONST0 ) pObj->iCopy = 0, Vec_IntWriteEntry(vDelay, 0, 17); else assert( 0 ); } if ( fVerbose ) printf( "Max delay = %d. Old objs = %d. New objs = %d.\n", Delay >> 4, Gia_ManObjNum(pGia), Gia_ManObjNum(pNew) ); Vec_IntFree( vDelay ); ABC_FREE( pNew->vCopies.pArray ); Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); pNew = Gia_ManDupNoMuxes( pTemp = pNew, 0 ); Gia_ManStop( pTemp ); // if ( pGia->pManTime != NULL ) // pNew->pManTime = Tim_ManDup( (Tim_Man_t *)pGia->pManTime, 0 ); return pNew; } /**Function************************************************************* Synopsis [Test normalization procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManLutBalance( Gia_Man_t * p, int nLutSize, int fUseMuxes, int fRecursive, int fOptArea, int fVerbose ) { Str_Ntk_t * pNtk; Gia_Man_t * pNew; abctime clk = Abc_Clock(); if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) && Gia_ManIsNormalized(p) ) { Tim_Man_t * pTimOld = (Tim_Man_t *)p->pManTime; p->pManTime = Tim_ManDup( pTimOld, 16 ); pNew = Gia_ManDupUnnormalize( p ); if ( pNew == NULL ) return NULL; Gia_ManTransferTiming( pNew, p ); p = pNew; // optimize pNtk = Str_ManNormalize( p ); pNew = Str_NtkBalance( p, pNtk, nLutSize, fUseMuxes, fRecursive, fOptArea, fVerbose ); Gia_ManTransferTiming( pNew, p ); Gia_ManStop( p ); // normalize pNew = Gia_ManDupNormalize( p = pNew, 0 ); Gia_ManTransferTiming( pNew, p ); Gia_ManStop( p ); // cleanup Tim_ManStop( (Tim_Man_t *)pNew->pManTime ); pNew->pManTime = pTimOld; assert( Gia_ManIsNormalized(pNew) ); } else { pNtk = Str_ManNormalize( p ); // Str_NtkPrintGroups( pNtk ); pNew = Str_NtkBalance( p, pNtk, nLutSize, fUseMuxes, fRecursive, fOptArea, fVerbose ); Gia_ManTransferTiming( pNew, p ); } if ( fVerbose ) Str_NtkPs( pNtk, Abc_Clock() - clk ); Str_NtkDelete( pNtk ); return pNew; } /**Function************************************************************* Synopsis [Perform MUX restructuring.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ typedef struct Str_Edg_t_ Str_Edg_t; struct Str_Edg_t_ { int Fan; // fanin ID int fCompl; // fanin complement int FanDel; // fanin delay int Copy; // fanin copy }; typedef struct Str_Mux_t_ Str_Mux_t; // 64 bytes struct Str_Mux_t_ { int Id; // node ID int Delay; // node delay int Copy; // node copy int nLutSize; // LUT size Str_Edg_t Edge[3]; // fanins }; static inline Str_Mux_t * Str_MuxFanin( Str_Mux_t * pMux, int i ) { return pMux - pMux->Id + pMux->Edge[i].Fan; } static inline int Str_MuxHasFanin( Str_Mux_t * pMux, int i ) { return pMux->Edge[i].Fan > 0 && Str_MuxFanin(pMux, i)->Copy != -2; } void Str_MuxDelayPrint_rec( Str_Mux_t * pMux, int i ) { int fShowDelay = 1; Str_Mux_t * pFanin; if ( pMux->Edge[i].Fan <= 0 ) { printf( "%d", -pMux->Edge[i].Fan ); if ( fShowDelay ) printf( "{%d}", pMux->Edge[i].FanDel ); return; } pFanin = Str_MuxFanin( pMux, i ); printf( "[ " ); if ( pFanin->Edge[0].fCompl ) printf( "!" ); Str_MuxDelayPrint_rec( pFanin, 0 ); printf( "|" ); if ( pFanin->Edge[1].fCompl ) printf( "!" ); Str_MuxDelayPrint_rec( pFanin, 1 ); printf( "(" ); if ( pFanin->Edge[2].fCompl ) printf( "!" ); Str_MuxDelayPrint_rec( pFanin, 2 ); printf( ")" ); printf( " ]" ); } int Str_MuxDelayEdge_rec( Str_Mux_t * pMux, int i ) { if ( pMux->Edge[i].Fan > 0 ) { Str_Mux_t * pFanin = Str_MuxFanin( pMux, i ); Str_MuxDelayEdge_rec( pFanin, 0 ); Str_MuxDelayEdge_rec( pFanin, 1 ); pMux->Edge[i].FanDel = Str_Delay3( pFanin->Edge[0].FanDel, pFanin->Edge[1].FanDel, pFanin->Edge[2].FanDel, pFanin->nLutSize ); } return pMux->Edge[i].FanDel; } void Str_MuxCreate( Str_Mux_t * pTree, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize ) { Str_Obj_t * pObj; Str_Mux_t * pMux; int i, k, nPis = 0; assert( nMuxes >= 2 ); memset( pTree, 0, sizeof(Str_Mux_t) * (nMuxes + 1) ); pTree->nLutSize = nLutSize; pTree->Edge[0].Fan = 1; for ( i = 1; i <= nMuxes; i++ ) { pMux = pTree + i; pMux->Id = i; pMux->nLutSize = nLutSize; pMux->Delay = pMux->Copy = -1; // assign fanins pObj = Str_NtkObj( pNtk, iMux + nMuxes - i ); assert( pObj->Type == STR_MUX ); for ( k = 0; k < 3; k++ ) { pMux->Edge[k].fCompl = Str_ObjFaninC(pNtk, pObj, k); if ( Str_ObjFaninId(pNtk, pObj, k) >= iMux ) pMux->Edge[k].Fan = iMux + nMuxes - Str_ObjFaninId(pNtk, pObj, k); else { pMux->Edge[k].Fan = -nPis++; // count external inputs, including controls pMux->Edge[k].Copy = Str_ObjFanin(pNtk, pObj, k)->iCopy; pMux->Edge[k].FanDel = Vec_IntEntry( vDelay, Abc_Lit2Var(pMux->Edge[k].Copy) ); } } } } int Str_MuxToGia_rec( Gia_Man_t * pNew, Str_Mux_t * pMux, int i, Vec_Int_t * vDelay ) { if ( pMux->Edge[i].Fan > 0 ) { Str_Mux_t * pFanin = Str_MuxFanin( pMux, i ); int iLit0 = Str_MuxToGia_rec( pNew, pFanin, 0, vDelay ); int iLit1 = Str_MuxToGia_rec( pNew, pFanin, 1, vDelay ); assert( pFanin->Edge[2].Fan <= 0 ); assert( pFanin->Edge[2].fCompl == 0 ); pMux->Edge[i].Copy = Gia_ManHashMuxReal( pNew, pFanin->Edge[2].Copy, iLit1, iLit0 ); Str_ObjDelay( pNew, Abc_Lit2Var(pMux->Edge[i].Copy), pFanin->nLutSize, vDelay ); } return Abc_LitNotCond( pMux->Edge[i].Copy, pMux->Edge[i].fCompl ); } void Str_MuxChangeOnce( Str_Mux_t * pTree, int * pPath, int i, int k, Str_Mux_t * pBackup, Gia_Man_t * pNew, Vec_Int_t * vDelay ) { Str_Mux_t * pSpots[3]; int pInds[3], MidFan, MidCom, MidDel, MidCop, c; int iRes, iCond, fCompl; // save backup assert( i + 1 < k ); if ( pBackup ) { pBackup[0] = pTree[ Abc_Lit2Var(pPath[k]) ]; pBackup[1] = pTree[ Abc_Lit2Var(pPath[i+1])]; pBackup[2] = pTree[ Abc_Lit2Var(pPath[i]) ]; } // perform changes pSpots[0] = pTree + Abc_Lit2Var(pPath[k]); pSpots[1] = pTree + Abc_Lit2Var(pPath[i+1]); pSpots[2] = pTree + Abc_Lit2Var(pPath[i]); pInds[0] = Abc_LitIsCompl(pPath[k]); pInds[1] = Abc_LitIsCompl(pPath[i+1]); pInds[2] = Abc_LitIsCompl(pPath[i]); // check assert( pSpots[0]->Edge[pInds[0]].Fan > 0 ); assert( pSpots[1]->Edge[pInds[1]].Fan > 0 ); // collect complement fCompl = 0; for ( c = i+1; c < k; c++ ) fCompl ^= pTree[Abc_Lit2Var(pPath[c])].Edge[Abc_LitIsCompl(pPath[c])].fCompl; // remember bottom side MidFan = pSpots[2]->Edge[!pInds[2]].Fan; MidCom = pSpots[2]->Edge[!pInds[2]].fCompl; MidDel = pSpots[2]->Edge[!pInds[2]].FanDel; MidCop = pSpots[2]->Edge[!pInds[2]].Copy; // update bottom pSpots[2]->Edge[!pInds[2]].Fan = pSpots[0]->Edge[pInds[0]].Fan; pSpots[2]->Edge[!pInds[2]].fCompl = 0; // update top pSpots[0]->Edge[pInds[0]].Fan = pSpots[2]->Id; // update middle pSpots[1]->Edge[pInds[1]].Fan = MidFan; pSpots[1]->Edge[pInds[1]].fCompl ^= MidCom; pSpots[1]->Edge[pInds[1]].FanDel = MidDel; pSpots[1]->Edge[pInds[1]].Copy = MidCop; // update delay of the control for ( c = i + 1; c < k; c++ ) pSpots[2]->Edge[2].FanDel = Str_Delay2( pSpots[2]->Edge[2].FanDel, pTree[Abc_Lit2Var(pPath[c])].Edge[2].FanDel, pTree->nLutSize ); if ( pNew == NULL ) return; // create AND gates iRes = 1; for ( c = i; c < k; c++ ) { assert( pTree[Abc_Lit2Var(pPath[c])].Edge[2].fCompl == 0 ); iCond = pTree[Abc_Lit2Var(pPath[c])].Edge[2].Copy; iCond = Abc_LitNotCond( iCond, !Abc_LitIsCompl(pPath[c]) ); iRes = Gia_ManHashAnd( pNew, iRes, iCond ); Str_ObjDelay( pNew, Abc_Lit2Var(iRes), pTree->nLutSize, vDelay ); } // complement the condition pSpots[2]->Edge[2].Copy = Abc_LitNotCond( iRes, !Abc_LitIsCompl(pPath[i]) ); // complement the path pSpots[2]->Edge[pInds[2]].fCompl ^= fCompl; } void Str_MuxChangeUndo( Str_Mux_t * pTree, int * pPath, int i, int k, Str_Mux_t * pBackup ) { pTree[ Abc_Lit2Var(pPath[k]) ] = pBackup[0]; pTree[ Abc_Lit2Var(pPath[i+1])] = pBackup[1]; pTree[ Abc_Lit2Var(pPath[i]) ] = pBackup[2]; } int Str_MuxFindPathEdge_rec( Str_Mux_t * pMux, int i, int * pPath, int * pnLength ) { extern int Str_MuxFindPath_rec( Str_Mux_t * pMux, int * pPath, int * pnLength ); if ( pMux->Edge[i].Fan > 0 && !Str_MuxFindPath_rec(Str_MuxFanin(pMux, i), pPath, pnLength) ) return 0; pPath[ (*pnLength)++ ] = Abc_Var2Lit(pMux->Id, i); return 1; } int Str_MuxFindPath_rec( Str_Mux_t * pMux, int * pPath, int * pnLength ) { int i, DelayMax = Abc_MaxInt( pMux->Edge[0].FanDel, Abc_MaxInt(pMux->Edge[1].FanDel, pMux->Edge[2].FanDel) ); for ( i = 0; i < 2; i++ ) if ( pMux->Edge[i].FanDel == DelayMax ) return Str_MuxFindPathEdge_rec( pMux, i, pPath, pnLength ); if ( pMux->Edge[2].FanDel == DelayMax ) return 0; assert( 0 ); return -1; } // return node whose both branches are non-trivial Str_Mux_t * Str_MuxFindBranching( Str_Mux_t * pRoot, int i ) { Str_Mux_t * pMux; if ( pRoot->Edge[i].Fan <= 0 ) return NULL; pMux = Str_MuxFanin( pRoot, i ); while ( 1 ) { if ( pMux->Edge[0].Fan <= 0 && pMux->Edge[1].Fan <= 0 ) return NULL; if ( pMux->Edge[0].Fan > 0 && pMux->Edge[1].Fan > 0 ) return pMux; if ( pMux->Edge[0].Fan > 0 ) pMux = Str_MuxFanin( pMux, 0 ); if ( pMux->Edge[1].Fan > 0 ) pMux = Str_MuxFanin( pMux, 1 ); } assert( 0 ); return NULL; } int Str_MuxTryOnce( Gia_Man_t * pNew, Str_Ntk_t * pNtk, Str_Mux_t * pTree, Str_Mux_t * pRoot, int Edge, Vec_Int_t * vDelay, int fVerbose ) { int pPath[MAX_TREE]; Str_Mux_t pBackup[3]; int Delay, DelayBest = Str_MuxDelayEdge_rec( pRoot, Edge ), DelayInit = DelayBest; int i, k, nLength = 0, ForkBest = -1, nChecks = 0; int RetValue = Str_MuxFindPathEdge_rec( pRoot, Edge, pPath, &nLength ); if ( RetValue == 0 ) return 0; if ( fVerbose ) printf( "Trying node %d with path of length %d.\n", pRoot->Id, nLength ); for ( i = 0; i < nLength; i++ ) for ( k = i+2; k < nLength; k++ ) { Str_MuxChangeOnce( pTree, pPath, i, k, pBackup, NULL, NULL ); Delay = Str_MuxDelayEdge_rec( pRoot, Edge ); Str_MuxChangeUndo( pTree, pPath, i, k, pBackup ); if ( DelayBest > Delay || (ForkBest > 0 && DelayBest == Delay) ) DelayBest = Delay, ForkBest = (i << 16) | k; if ( fVerbose ) printf( "%2d %2d -> %3d (%3d)\n", i, k, Delay, DelayBest ); nChecks++; } if ( ForkBest == -1 ) { if ( fVerbose ) printf( "Did not find!\n" ); return 0; } // Str_MuxDelayPrint_rec( pRoot, Edge ); printf( "\n" ); Str_MuxChangeOnce( pTree, pPath, ForkBest >> 16, ForkBest & 0xFFFF, NULL, pNew, vDelay ); // Str_MuxDelayPrint_rec( pRoot, Edge ); printf( "\n" ); if ( fVerbose ) printf( "Node %6d (%3d %3d) : Checks = %d. Delay: %d -> %d.\n", pRoot->Id, ForkBest >> 16, ForkBest & 0xFFFF, nChecks, DelayInit, DelayBest ); if ( fVerbose ) printf( "\n" ); return 1; } int Str_MuxRestruct_rec( Gia_Man_t * pNew, Str_Ntk_t * pNtk, Str_Mux_t * pTree, Str_Mux_t * pRoot, int Edge, Vec_Int_t * vDelay, int fVerbose ) { int fChanges = 0; Str_Mux_t * pMux = Str_MuxFindBranching( pRoot, Edge ); if ( pMux != NULL ) fChanges |= Str_MuxRestruct_rec( pNew, pNtk, pTree, pMux, 0, vDelay, fVerbose ); if ( pMux != NULL ) fChanges |= Str_MuxRestruct_rec( pNew, pNtk, pTree, pMux, 1, vDelay, fVerbose ); fChanges |= Str_MuxTryOnce( pNew, pNtk, pTree, pRoot, Edge, vDelay, fVerbose ); return fChanges; } int Str_MuxRestructure2( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose ) { int Limit = MAX_TREE; Str_Mux_t pTree[MAX_TREE]; int Delay, Delay2, fChanges = 0; if ( nMuxes >= Limit ) return -1; assert( nMuxes < Limit ); Str_MuxCreate( pTree, pNtk, iMux, nMuxes, vDelay, nLutSize ); Delay = Str_MuxDelayEdge_rec( pTree, 0 ); while ( 1 ) { if ( !Str_MuxRestruct_rec(pNew, pNtk, pTree, pTree, 0, vDelay, fVerbose) ) break; fChanges = 1; } if ( !fChanges ) return -1; Delay2 = Str_MuxDelayEdge_rec( pTree, 0 ); // printf( "Improved delay for tree %d with %d MUXes (%d -> %d).\n", iMux, nMuxes, Delay, Delay2 ); pNtk->DelayGain += Delay - Delay2; return Str_MuxToGia_rec( pNew, pTree, 0, vDelay ); } int Str_MuxRestructure1( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose ) { int Limit = MAX_TREE; Str_Mux_t pTree[MAX_TREE]; int Delay, Delay2, fChanges = 0; if ( nMuxes >= Limit ) return -1; assert( nMuxes < Limit ); Str_MuxCreate( pTree, pNtk, iMux, nMuxes, vDelay, nLutSize ); Delay = Str_MuxDelayEdge_rec( pTree, 0 ); while ( 1 ) { if ( !Str_MuxTryOnce(pNew, pNtk, pTree, pTree, 0, vDelay, fVerbose) ) break; fChanges = 1; } if ( !fChanges ) return -1; Delay2 = Str_MuxDelayEdge_rec( pTree, 0 ); // printf( "Improved delay for tree %d with %d MUXes (%d -> %d).\n", iMux, nMuxes, Delay, Delay2 ); pNtk->DelayGain += Delay - Delay2; return Str_MuxToGia_rec( pNew, pTree, 0, vDelay ); } int Str_MuxRestructure( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fRecursive, int fOptArea, int fVerbose ) { extern int Str_MuxRestructureArea( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose ); if ( fOptArea ) { if ( nMuxes < 2 ) return Str_MuxRestructure1( pNew, pNtk, iMux, nMuxes, vDelay, nLutSize, fVerbose ); return Str_MuxRestructureArea( pNew, pNtk, iMux, nMuxes, vDelay, nLutSize, fVerbose ); } if ( fRecursive ) return Str_MuxRestructure2( pNew, pNtk, iMux, nMuxes, vDelay, nLutSize, fVerbose ); return Str_MuxRestructure1( pNew, pNtk, iMux, nMuxes, vDelay, nLutSize, fVerbose ); } /**Function************************************************************* Synopsis [Perform MUX restructuring for area.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Str_MuxRestructAreaThree( Gia_Man_t * pNew, Str_Mux_t * pMux, Vec_Int_t * vDelay, int fVerbose ) { int iRes; Str_Mux_t * pFanin0 = Str_MuxFanin( pMux, 0 ); Str_Mux_t * pFanin1 = Str_MuxFanin( pMux, 1 ); assert( pMux->Copy == -1 ); pMux->Copy = -2; if ( pFanin0->Edge[2].Copy == pFanin1->Edge[2].Copy ) return 0; iRes = Gia_ManHashMuxReal( pNew, pMux->Edge[2].Copy, pFanin1->Edge[2].Copy, pFanin0->Edge[2].Copy ); Str_ObjDelay( pNew, Abc_Lit2Var(iRes), pMux->nLutSize, vDelay ); pFanin0->Edge[2].Copy = pFanin1->Edge[2].Copy = iRes; // printf( "Created triple\n" ); return 0; } int Str_MuxRestructArea_rec( Gia_Man_t * pNew, Str_Mux_t * pTree, Str_Mux_t * pRoot, int i, Vec_Int_t * vDelay, int fVerbose ) { int Path[4]; int fSkipMoving = 1; Str_Mux_t * pMux, * pFanin0, * pFanin1; int nMuxes0, nMuxes1; if ( pRoot->Edge[i].Fan <= 0 ) return 0; pMux = Str_MuxFanin( pRoot, i ); nMuxes0 = Str_MuxRestructArea_rec( pNew, pTree, pMux, 0, vDelay, fVerbose ); nMuxes1 = Str_MuxRestructArea_rec( pNew, pTree, pMux, 1, vDelay, fVerbose ); if ( nMuxes0 + nMuxes1 < 2 ) return 1 + nMuxes0 + nMuxes1; if ( nMuxes0 + nMuxes1 == 2 ) { if ( nMuxes0 == 2 || nMuxes1 == 2 ) { pFanin0 = Str_MuxFanin( pMux, (int)(nMuxes1 == 2) ); assert( Str_MuxHasFanin(pFanin0, 0) != Str_MuxHasFanin(pFanin0, 1) ); Path[2] = Abc_Var2Lit(pRoot->Id, i); Path[1] = Abc_Var2Lit(pMux->Id, (int)(nMuxes1 == 2) ); Path[0] = Abc_Var2Lit(pFanin0->Id, Str_MuxHasFanin(pFanin0, 1)); Str_MuxChangeOnce( pTree, Path, 0, 2, NULL, pNew, vDelay ); } Str_MuxRestructAreaThree( pNew, Str_MuxFanin(pRoot, i), vDelay, fVerbose ); return 0; } assert( nMuxes0 + nMuxes1 == 3 || nMuxes0 + nMuxes1 == 4 ); assert( nMuxes0 == 2 || nMuxes1 == 2 ); if ( fSkipMoving ) { Str_MuxRestructAreaThree( pNew, pMux, vDelay, fVerbose ); return 0; } if ( nMuxes0 == 2 ) { pFanin0 = Str_MuxFanin( pMux, 0 ); assert( Str_MuxHasFanin(pFanin0, 0) != Str_MuxHasFanin(pFanin0, 1) ); Path[3] = Abc_Var2Lit(pRoot->Id, i); Path[2] = Abc_Var2Lit(pMux->Id, 0 ); Path[1] = Abc_Var2Lit(pFanin0->Id, Str_MuxHasFanin(pFanin0, 1)); pFanin1 = Str_MuxFanin( pFanin0, Str_MuxHasFanin(pFanin0, 1) ); assert( !Str_MuxHasFanin(pFanin1, 0) && !Str_MuxHasFanin(pFanin1, 1) ); Path[0] = Abc_Var2Lit(pFanin1->Id, 0); Str_MuxChangeOnce( pTree, Path, 0, 3, NULL, pNew, vDelay ); } if ( nMuxes1 == 2 ) { pFanin0 = Str_MuxFanin( pMux, 1 ); assert( Str_MuxHasFanin(pFanin0, 0) != Str_MuxHasFanin(pFanin0, 1) ); Path[3] = Abc_Var2Lit(pRoot->Id, i); Path[2] = Abc_Var2Lit(pMux->Id, 1 ); Path[1] = Abc_Var2Lit(pFanin0->Id, Str_MuxHasFanin(pFanin0, 1)); pFanin1 = Str_MuxFanin( pFanin0, Str_MuxHasFanin(pFanin0, 1) ); assert( !Str_MuxHasFanin(pFanin1, 0) && !Str_MuxHasFanin(pFanin1, 1) ); Path[0] = Abc_Var2Lit(pFanin1->Id, 0); Str_MuxChangeOnce( pTree, Path, 0, 3, NULL, pNew, vDelay ); } Str_MuxRestructAreaThree( pNew, pMux, vDelay, fVerbose ); return nMuxes0 + nMuxes1 - 2; } int Str_MuxRestructureArea( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose ) { int Limit = MAX_TREE; Str_Mux_t pTree[MAX_TREE]; int Result; if ( nMuxes >= Limit ) return -1; assert( nMuxes < Limit ); Str_MuxCreate( pTree, pNtk, iMux, nMuxes, vDelay, nLutSize ); Result = Str_MuxRestructArea_rec( pNew, pTree, pTree, 0, vDelay, fVerbose ); assert( Result >= 0 && Result <= 2 ); return Str_MuxToGia_rec( pNew, pTree, 0, vDelay ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSupMin.c000066400000000000000000000114121477524141600163260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaSupMin.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Support minimization for AIGs with don't-cares.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaSupMin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "bool/kit/kit.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // decomposition manager typedef struct Gia_ManSup_t_ Gia_ManSup_t; struct Gia_ManSup_t_ { int nVarsMax; // the max number of variables int nWordsMax; // the max number of words Vec_Ptr_t * vTruthVars; // elementary truth tables Vec_Ptr_t * vTruthNodes; // internal truth tables // current problem Gia_Man_t * pGia; int iData; int iCare; Vec_Int_t * vConeCare; Vec_Int_t * vConeData; unsigned * pTruthIn; unsigned * pTruthOut; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts Decmetry manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_ManSup_t * Gia_ManSupStart( int nVarsMax ) { Gia_ManSup_t * p; assert( nVarsMax <= 20 ); p = ABC_CALLOC( Gia_ManSup_t, 1 ); p->nVarsMax = nVarsMax; p->nWordsMax = Kit_TruthWordNum( p->nVarsMax ); p->vTruthVars = Vec_PtrAllocTruthTables( p->nVarsMax ); p->vTruthNodes = Vec_PtrAllocSimInfo( 512, p->nWordsMax ); p->vConeCare = Vec_IntAlloc( 512 ); p->vConeData = Vec_IntAlloc( 512 ); p->pTruthIn = ABC_ALLOC( unsigned, p->nWordsMax ); p->pTruthOut = ABC_ALLOC( unsigned, p->nWordsMax ); return p; } /**Function************************************************************* Synopsis [Stops Decmetry manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSupStop( Gia_ManSup_t * p ) { ABC_FREE( p->pTruthIn ); ABC_FREE( p->pTruthOut ); Vec_IntFreeP( &p->vConeCare ); Vec_IntFreeP( &p->vConeData ); Vec_PtrFreeP( &p->vTruthVars ); Vec_PtrFreeP( &p->vTruthNodes ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSupExperimentOne( Gia_ManSup_t * p, Gia_Obj_t * pData, Gia_Obj_t * pCare ) { int iData = Gia_ObjId( p->pGia, Gia_Regular(pData) ); int iCare = Gia_ObjId( p->pGia, Gia_Regular(pCare) ); if ( !Gia_ObjIsAnd(Gia_Regular(pCare)) ) { Abc_Print( 1, "Enable is not an AND.\n" ); return; } Abc_Print( 1, "DataSupp = %6d. DataCone = %6d. CareSupp = %6d. CareCone = %6d.", Gia_ManSuppSize( p->pGia, &iData, 1 ), Gia_ManConeSize( p->pGia, &iData, 1 ), Gia_ManSuppSize( p->pGia, &iCare, 1 ), Gia_ManConeSize( p->pGia, &iCare, 1 ) ); Abc_Print( 1, "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSupExperiment( Gia_Man_t * pGia, Vec_Int_t * vPairs ) { Gia_ManSup_t * p; Gia_Obj_t * pData, * pCare; int i; p = Gia_ManSupStart( 16 ); p->pGia = pGia; assert( Vec_IntSize(vPairs) % 2 == 0 ); for ( i = 0; i < Vec_IntSize(vPairs)/2; i++ ) { Abc_Print( 1, "%6d : ", i ); pData = Gia_ManPo( pGia, Vec_IntEntry(vPairs, 2*i+0) ); pCare = Gia_ManPo( pGia, Vec_IntEntry(vPairs, 2*i+1) ); Gia_ManSupExperimentOne( p, Gia_ObjChild0(pData), Gia_ObjChild0(pCare) ); } Gia_ManSupStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSupp.c000066400000000000000000000741611477524141600160540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaSupp.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Support minimization for AIGs.] 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 "gia.h" #include "sat/satoko/satoko.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD struct Gia_ManMin_t_ { // problem formulation Gia_Man_t * pGia; int iLits[2]; // structural information Vec_Int_t * vCis[2]; Vec_Int_t * vObjs[2]; Vec_Int_t * vCleared; // intermediate functions DdManager * dd; Vec_Ptr_t * vFuncs; Vec_Int_t * vSupp; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Create/delete the data representation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_ManMin_t * Gia_ManSuppStart( Gia_Man_t * pGia ) { Gia_ManMin_t * p; p = ABC_CALLOC( Gia_ManMin_t, 1 ); p->pGia = pGia; p->vCis[0] = Vec_IntAlloc( 512 ); p->vCis[1] = Vec_IntAlloc( 512 ); p->vObjs[0] = Vec_IntAlloc( 512 ); p->vObjs[1] = Vec_IntAlloc( 512 ); p->vCleared = Vec_IntAlloc( 512 ); p->dd = Cudd_Init( 0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); // Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); Cudd_AutodynDisable( p->dd ); p->vFuncs = Vec_PtrAlloc( 10000 ); p->vSupp = Vec_IntAlloc( 10000 ); return p; } void Gia_ManSuppStop( Gia_ManMin_t * p ) { Vec_IntFreeP( &p->vCis[0] ); Vec_IntFreeP( &p->vCis[1] ); Vec_IntFreeP( &p->vObjs[0] ); Vec_IntFreeP( &p->vObjs[1] ); Vec_IntFreeP( &p->vCleared ); Vec_PtrFreeP( &p->vFuncs ); Vec_IntFreeP( &p->vSupp ); printf( "Refs = %d. \n", Cudd_CheckZeroRef( p->dd ) ); Cudd_Quit( p->dd ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Compute variables, which are not in the support.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFindRemoved( Gia_ManMin_t * p ) { extern void ddSupportStep2( DdNode * f, int * support ); extern void ddClearFlag2( DdNode * f ); //int fVerbose = 1; int nBddLimit = 100000; int nPart0 = Vec_IntSize(p->vCis[0]); int n, i, iObj, nVars = 0; DdNode * bFunc0, * bFunc1, * bFunc; Vec_PtrFillExtra( p->vFuncs, Gia_ManObjNum(p->pGia), NULL ); // assign variables for ( n = 0; n < 2; n++ ) Vec_IntForEachEntry( p->vCis[n], iObj, i ) Vec_PtrWriteEntry( p->vFuncs, iObj, Cudd_bddIthVar(p->dd, nVars++) ); // create nodes for ( n = 0; n < 2; n++ ) Vec_IntForEachEntry( p->vObjs[n], iObj, i ) { Gia_Obj_t * pObj = Gia_ManObj( p->pGia, iObj ); bFunc0 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(p->vFuncs, Gia_ObjFaninId0(pObj, iObj)), Gia_ObjFaninC0(pObj) ); bFunc1 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(p->vFuncs, Gia_ObjFaninId1(pObj, iObj)), Gia_ObjFaninC1(pObj) ); bFunc = Cudd_bddAndLimit( p->dd, bFunc0, bFunc1, nBddLimit ); assert( bFunc != NULL ); Cudd_Ref( bFunc ); Vec_PtrWriteEntry( p->vFuncs, iObj, bFunc ); } // create new node bFunc0 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(p->vFuncs, Abc_Lit2Var(p->iLits[0])), Abc_LitIsCompl(p->iLits[0]) ); bFunc1 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(p->vFuncs, Abc_Lit2Var(p->iLits[1])), Abc_LitIsCompl(p->iLits[1]) ); bFunc = Cudd_bddAndLimit( p->dd, bFunc0, bFunc1, nBddLimit ); assert( bFunc != NULL ); Cudd_Ref( bFunc ); //if ( fVerbose ) Extra_bddPrint( p->dd, bFunc ), printf( "\n" ); // collect support Vec_IntFill( p->vSupp, nVars, 0 ); ddSupportStep2( Cudd_Regular(bFunc), Vec_IntArray(p->vSupp) ); ddClearFlag2( Cudd_Regular(bFunc) ); // find variables not present in the support Vec_IntClear( p->vCleared ); for ( i = 0; i < nVars; i++ ) if ( Vec_IntEntry(p->vSupp, i) == 0 ) Vec_IntPush( p->vCleared, i < nPart0 ? Vec_IntEntry(p->vCis[0], i) : Vec_IntEntry(p->vCis[1], i-nPart0) ); //printf( "%d(%d)%d ", Cudd_SupportSize(p->dd, bFunc), Vec_IntSize(p->vCleared), Cudd_DagSize(bFunc) ); // deref results Cudd_RecursiveDeref( p->dd, bFunc ); for ( n = 0; n < 2; n++ ) Vec_IntForEachEntry( p->vObjs[n], iObj, i ) Cudd_RecursiveDeref( p->dd, (DdNode *)Vec_PtrEntry(p->vFuncs, iObj) ); //Vec_IntPrint( p->vCleared ); return Vec_IntSize(p->vCleared); } /**Function************************************************************* Synopsis [Compute variables, which are not in the support.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManRebuildOne( Gia_ManMin_t * p, int n ) { int i, iObj, iGiaLitNew = -1; Vec_Int_t * vTempIns = p->vCis[n]; Vec_Int_t * vTempNds = p->vObjs[n]; Vec_Int_t * vCopies = &p->pGia->vCopies; Vec_IntFillExtra( vCopies, Gia_ManObjNum(p->pGia), -1 ); assert( p->iLits[n] >= 2 ); // process inputs Vec_IntForEachEntry( vTempIns, iObj, i ) Vec_IntWriteEntry( vCopies, iObj, Abc_Var2Lit(iObj, 0) ); // process constants assert( Vec_IntSize(p->vCleared) > 0 ); Vec_IntForEachEntry( p->vCleared, iObj, i ) Vec_IntWriteEntry( vCopies, iObj, 0 ); if ( Vec_IntSize(vTempNds) == 0 ) iGiaLitNew = Vec_IntEntry( vCopies, Abc_Lit2Var(p->iLits[n]) ); else { Vec_IntForEachEntry( vTempNds, iObj, i ) { Gia_Obj_t * pObj = Gia_ManObj( p->pGia, iObj ); int iGiaLit0 = Vec_IntEntry( vCopies, Gia_ObjFaninId0p(p->pGia, pObj) ); int iGiaLit1 = Vec_IntEntry( vCopies, Gia_ObjFaninId1p(p->pGia, pObj) ); iGiaLit0 = Abc_LitNotCond( iGiaLit0, Gia_ObjFaninC0(pObj) ); iGiaLit1 = Abc_LitNotCond( iGiaLit1, Gia_ObjFaninC1(pObj) ); iGiaLitNew = Gia_ManHashAnd( p->pGia, iGiaLit0, iGiaLit1 ); Vec_IntWriteEntry( vCopies, iObj, iGiaLitNew ); } assert( Abc_Lit2Var(p->iLits[n]) == iObj ); } return Abc_LitNotCond( iGiaLitNew, Abc_LitIsCompl(p->iLits[n]) ); } /**Function************************************************************* Synopsis [Collect nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManGatherSupp_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vCis, Vec_Int_t * vObjs ) { int Val0, Val1; Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdPreviousId(p, iObj) ) return 1; if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) return 0; Gia_ObjSetTravIdCurrentId(p, iObj); pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjIsCi(pObj) ) { Vec_IntPush( vCis, iObj ); return 0; } assert( Gia_ObjIsAnd(pObj) ); Val0 = Gia_ManGatherSupp_rec( p, Gia_ObjFaninId0(pObj, iObj), vCis, vObjs ); Val1 = Gia_ManGatherSupp_rec( p, Gia_ObjFaninId1(pObj, iObj), vCis, vObjs ); Vec_IntPush( vObjs, iObj ); return Val0 || Val1; } int Gia_ManGatherSupp( Gia_ManMin_t * p ) { int n, Overlap = 0; Gia_ManIncrementTravId( p->pGia ); for ( n = 0; n < 2; n++ ) { Vec_IntClear( p->vCis[n] ); Vec_IntClear( p->vObjs[n] ); Gia_ManIncrementTravId( p->pGia ); Overlap = Gia_ManGatherSupp_rec( p->pGia, Abc_Lit2Var(p->iLits[n]), p->vCis[n], p->vObjs[n] ); assert( n || !Overlap ); } return Overlap; } /**Function************************************************************* Synopsis [Takes a literal and returns a support-minized literal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManSupportAnd( Gia_ManMin_t * p, int iLit0, int iLit1 ) { int iLitNew0, iLitNew1; p->iLits[0] = iLit0; p->iLits[1] = iLit1; if ( iLit0 < 2 || iLit1 < 2 || !Gia_ManGatherSupp(p) || !Gia_ManFindRemoved(p) ) return Gia_ManHashAnd( p->pGia, iLit0, iLit1 ); iLitNew0 = Gia_ManRebuildOne( p, 0 ); iLitNew1 = Gia_ManRebuildOne( p, 1 ); return Gia_ManHashAnd( p->pGia, iLitNew0, iLitNew1 ); } #else Gia_ManMin_t * Gia_ManSuppStart( Gia_Man_t * pGia ) { return NULL; } int Gia_ManSupportAnd( Gia_ManMin_t * p, int iLit0, int iLit1 ) { return 0; } void Gia_ManSuppStop( Gia_ManMin_t * p ) {} #endif /**Function************************************************************* Synopsis [Testbench.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManSupportAndTest( Gia_Man_t * pGia ) { Gia_ManMin_t * pMan; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; Gia_ManFillValue( pGia ); pNew = Gia_ManStart( Gia_ManObjNum(pGia) ); pNew->pName = Abc_UtilStrsav( pGia->pName ); pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); Gia_ManHashAlloc( pNew ); Gia_ManConst0(pGia)->Value = 0; pMan = Gia_ManSuppStart( pNew ); Gia_ManForEachObj1( pGia, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) { // pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); pObj->Value = Gia_ManSupportAnd( pMan, 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) ); else assert( 0 ); if ( i % 10000 == 0 ) printf( "%d\n", i ); } Gia_ManSuppStop( pMan ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } struct Gia_Man2Min_t_ { // problem formulation Gia_Man_t * pGia; int iLits[2]; // structural information Vec_Int_t * vCis[2]; Vec_Int_t * vObjs[2]; // SAT solving satoko_t * pSat; // SAT solver Vec_Wrd_t * vSims; // simulation Vec_Ptr_t * vFrontier; // CNF construction Vec_Ptr_t * vFanins; // CNF construction Vec_Int_t * vSatVars; // nodes int nCisOld; // previous number of CIs int iPattern; // the next pattern to write int nSatSat; int nSatUnsat; int nCalls; int nSims; int nSupps; }; static inline int Gia_Min2ObjSatId( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjCopyArray(p, Gia_ObjId(p, pObj)); } static inline int Gia_Min2ObjSetSatId( Gia_Man_t * p, Gia_Obj_t * pObj, int Num ) { assert(Gia_Min2ObjSatId(p, pObj) == -1); Gia_ObjSetCopyArray(p, Gia_ObjId(p, pObj), Num); return Num; } static inline void Gia_Min2ObjCleanSatId( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert(Gia_Min2ObjSatId(p, pObj) != -1); Gia_ObjSetCopyArray(p, Gia_ObjId(p, pObj), -1); } /**Function************************************************************* Synopsis [Create/delete the data representation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man2Min_t * Gia_Man2SuppStart( Gia_Man_t * pGia ) { Gia_Man2Min_t * p; p = ABC_CALLOC( Gia_Man2Min_t, 1 ); p->pGia = pGia; p->vCis[0] = Vec_IntAlloc( 512 ); p->vCis[1] = Vec_IntAlloc( 512 ); p->vObjs[0] = Vec_IntAlloc( 512 ); p->vObjs[1] = Vec_IntAlloc( 512 ); // SAT solving p->pSat = satoko_create(); p->vSims = Vec_WrdAlloc( 1000 ); p->vFrontier = Vec_PtrAlloc( 1000 ); p->vFanins = Vec_PtrAlloc( 100 ); p->vSatVars = Vec_IntAlloc( 100 ); p->iPattern = 1; satoko_options(p->pSat)->learnt_ratio = 0; // prevent garbage collection return p; } void Gia_Man2SuppStop( Gia_Man2Min_t * p ) { // printf( "Total calls = %8d. Supps = %6d. Sims = %6d. SAT = %6d. UNSAT = %6d.\n", // p->nCalls, p->nSupps, p->nSims, p->nSatSat, p->nSatUnsat ); Vec_IntFreeP( &p->vCis[0] ); Vec_IntFreeP( &p->vCis[1] ); Vec_IntFreeP( &p->vObjs[0] ); Vec_IntFreeP( &p->vObjs[1] ); Gia_ManCleanMark01( p->pGia ); satoko_destroy( p->pSat ); Vec_WrdFreeP( &p->vSims ); Vec_PtrFreeP( &p->vFrontier ); Vec_PtrFreeP( &p->vFanins ); Vec_IntFreeP( &p->vSatVars ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Adds clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_Min2AddClausesMux( Gia_Man_t * p, Gia_Obj_t * pNode, satoko_t * pSat ) { int fPolarFlip = 0; Gia_Obj_t * pNodeI, * pNodeT, * pNodeE; int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; assert( !Gia_IsComplement( pNode ) ); assert( pNode->fMark0 ); // get nodes (I = if, T = then, E = else) pNodeI = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); // get the variable numbers VarF = Gia_Min2ObjSatId(p, pNode); VarI = Gia_Min2ObjSatId(p, pNodeI); VarT = Gia_Min2ObjSatId(p, Gia_Regular(pNodeT)); VarE = Gia_Min2ObjSatId(p, Gia_Regular(pNodeE)); // get the complementation flags fCompT = Gia_IsComplement(pNodeT); fCompE = Gia_IsComplement(pNodeE); // f = ITE(i, t, e) // i' + t' + f // i' + t + f' // i + e' + f // i + e + f' // create four clauses pLits[0] = Abc_Var2Lit(VarI, 1); pLits[1] = Abc_Var2Lit(VarT, 1^fCompT); pLits[2] = Abc_Var2Lit(VarF, 0); if ( fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); } RetValue = satoko_add_clause( pSat, pLits, 3 ); assert( RetValue ); pLits[0] = Abc_Var2Lit(VarI, 1); pLits[1] = Abc_Var2Lit(VarT, 0^fCompT); pLits[2] = Abc_Var2Lit(VarF, 1); if ( fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); } RetValue = satoko_add_clause( pSat, pLits, 3 ); assert( RetValue ); pLits[0] = Abc_Var2Lit(VarI, 0); pLits[1] = Abc_Var2Lit(VarE, 1^fCompE); pLits[2] = Abc_Var2Lit(VarF, 0); if ( fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); } RetValue = satoko_add_clause( pSat, pLits, 3 ); assert( RetValue ); pLits[0] = Abc_Var2Lit(VarI, 0); pLits[1] = Abc_Var2Lit(VarE, 0^fCompE); pLits[2] = Abc_Var2Lit(VarF, 1); if ( fPolarFlip ) { if ( pNodeI->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); } RetValue = satoko_add_clause( pSat, pLits, 3 ); assert( RetValue ); // two additional clauses // t' & e' -> f' // t & e -> f // t + e + f' // t' + e' + f if ( VarT == VarE ) { // assert( fCompT == !fCompE ); return; } pLits[0] = Abc_Var2Lit(VarT, 0^fCompT); pLits[1] = Abc_Var2Lit(VarE, 0^fCompE); pLits[2] = Abc_Var2Lit(VarF, 1); if ( fPolarFlip ) { if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); } RetValue = satoko_add_clause( pSat, pLits, 3 ); assert( RetValue ); pLits[0] = Abc_Var2Lit(VarT, 1^fCompT); pLits[1] = Abc_Var2Lit(VarE, 1^fCompE); pLits[2] = Abc_Var2Lit(VarF, 0); if ( fPolarFlip ) { if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); } RetValue = satoko_add_clause( pSat, pLits, 3 ); assert( RetValue ); } void Gia_Min2AddClausesSuper( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Ptr_t * vSuper, satoko_t * pSat ) { int fPolarFlip = 0; Gia_Obj_t * pFanin; int * pLits, nLits, RetValue, i; assert( !Gia_IsComplement(pNode) ); assert( Gia_ObjIsAnd( pNode ) ); // create storage for literals nLits = Vec_PtrSize(vSuper) + 1; pLits = ABC_ALLOC( int, nLits ); // suppose AND-gate is A & B = C // add !A => !C or A + !C Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i ) { pLits[0] = Abc_Var2Lit(Gia_Min2ObjSatId(p, Gia_Regular(pFanin)), Gia_IsComplement(pFanin)); pLits[1] = Abc_Var2Lit(Gia_Min2ObjSatId(p, pNode), 1); if ( fPolarFlip ) { if ( Gia_Regular(pFanin)->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); if ( pNode->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); } RetValue = satoko_add_clause( pSat, pLits, 2 ); assert( RetValue ); } // add A & B => C or !A + !B + C Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i ) { pLits[i] = Abc_Var2Lit(Gia_Min2ObjSatId(p, Gia_Regular(pFanin)), !Gia_IsComplement(pFanin)); if ( fPolarFlip ) { if ( Gia_Regular(pFanin)->fPhase ) pLits[i] = Abc_LitNot( pLits[i] ); } } pLits[nLits-1] = Abc_Var2Lit(Gia_Min2ObjSatId(p, pNode), 0); if ( fPolarFlip ) { if ( pNode->fPhase ) pLits[nLits-1] = Abc_LitNot( pLits[nLits-1] ); } RetValue = satoko_add_clause( pSat, pLits, nLits ); assert( RetValue ); ABC_FREE( pLits ); } /**Function************************************************************* Synopsis [Adds clauses and returns CNF variable of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_Min2CollectSuper_rec( Gia_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) { // if the new node is complemented or a PI, another gate begins if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) || (!fFirst && Gia_ObjValue(pObj) > 1) || (fUseMuxes && pObj->fMark0) ) { Vec_PtrPushUnique( vSuper, pObj ); return; } // go through the branches Gia_Min2CollectSuper_rec( Gia_ObjChild0(pObj), vSuper, 0, fUseMuxes ); Gia_Min2CollectSuper_rec( Gia_ObjChild1(pObj), vSuper, 0, fUseMuxes ); } void Gia_Min2CollectSuper( Gia_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper ) { assert( !Gia_IsComplement(pObj) ); assert( !Gia_ObjIsCi(pObj) ); Vec_PtrClear( vSuper ); Gia_Min2CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); } void Gia_Min2ObjAddToFrontier( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vFrontier, satoko_t * pSat, Vec_Int_t * vSatVars ) { assert( !Gia_IsComplement(pObj) ); assert( !Gia_ObjIsConst0(pObj) ); if ( Gia_Min2ObjSatId(p, pObj) >= 0 ) return; assert( Gia_Min2ObjSatId(p, pObj) == -1 ); Vec_IntPush( vSatVars, Gia_ObjId(p, pObj) ); Gia_Min2ObjSetSatId( p, pObj, satoko_add_variable(pSat, 0) ); if ( Gia_ObjIsAnd(pObj) ) Vec_PtrPush( vFrontier, pObj ); } int Gia_Min2ObjGetCnfVar( Gia_Man2Min_t * p, int iObj ) { Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); Gia_Obj_t * pNode, * pFanin; int i, k, fUseMuxes = 1; if ( Gia_Min2ObjSatId(p->pGia, pObj) >= 0 ) return Gia_Min2ObjSatId(p->pGia, pObj); if ( Gia_ObjIsCi(pObj) ) { Vec_IntPush( p->vSatVars, iObj ); return Gia_Min2ObjSetSatId( p->pGia, pObj, satoko_add_variable(p->pSat, 0) ); } assert( Gia_ObjIsAnd(pObj) ); // start the frontier Vec_PtrClear( p->vFrontier ); Gia_Min2ObjAddToFrontier( p->pGia, pObj, p->vFrontier, p->pSat, p->vSatVars ); // explore nodes in the frontier Vec_PtrForEachEntry( Gia_Obj_t *, p->vFrontier, pNode, i ) { assert( Gia_Min2ObjSatId(p->pGia,pNode) >= 0 ); if ( fUseMuxes && pNode->fMark0 ) { Vec_PtrClear( p->vFanins ); Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin0(pNode) ) ); Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin1(pNode) ) ); Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin0(pNode) ) ); Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin1(pNode) ) ); Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k ) Gia_Min2ObjAddToFrontier( p->pGia, Gia_Regular(pFanin), p->vFrontier, p->pSat, p->vSatVars ); Gia_Min2AddClausesMux( p->pGia, pNode, p->pSat ); } else { Gia_Min2CollectSuper( pNode, fUseMuxes, p->vFanins ); Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k ) Gia_Min2ObjAddToFrontier( p->pGia, Gia_Regular(pFanin), p->vFrontier, p->pSat, p->vSatVars ); Gia_Min2AddClausesSuper( p->pGia, pNode, p->vFanins, p->pSat ); } assert( Vec_PtrSize(p->vFanins) > 1 ); } return Gia_Min2ObjSatId(p->pGia,pObj); } /**Function************************************************************* Synopsis [Returns 0 if the node is not a constant.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_Min2ManSimulate( Gia_Man2Min_t * p ) { word Sim0, Sim1; int n, i, iObj; p->nSims++; // add random values to new CIs Vec_WrdFillExtra( p->vSims, Gia_ManObjNum(p->pGia), 0 ); for ( i = p->nCisOld; i < Gia_ManCiNum(p->pGia); i++ ) Vec_WrdWriteEntry( p->vSims, Gia_ManCiIdToId(p->pGia, i), Gia_ManRandomW( 0 ) << 1 ); p->nCisOld = Gia_ManCiNum(p->pGia); // simulate internal nodes for ( n = 0; n < 2; n++ ) Vec_IntForEachEntry( p->vObjs[n], iObj, i ) { Gia_Obj_t * pObj = Gia_ManObj( p->pGia, iObj ); Sim0 = Vec_WrdEntry( p->vSims, Gia_ObjFaninId0p(p->pGia, pObj) ); Sim1 = Vec_WrdEntry( p->vSims, Gia_ObjFaninId1p(p->pGia, pObj) ); Sim0 = Gia_ObjFaninC0(pObj) ? ~Sim0 : Sim0; Sim1 = Gia_ObjFaninC1(pObj) ? ~Sim1 : Sim1; Vec_WrdWriteEntry( p->vSims, iObj, Sim0 & Sim1 ); } Sim0 = Vec_WrdEntry( p->vSims, Abc_Lit2Var(p->iLits[0]) ); Sim1 = Vec_WrdEntry( p->vSims, Abc_Lit2Var(p->iLits[1]) ); Sim0 = Abc_LitIsCompl(p->iLits[0]) ? ~Sim0 : Sim0; Sim1 = Abc_LitIsCompl(p->iLits[1]) ? ~Sim1 : Sim1; // assert( (Sim0 & Sim1) != ~0 ); return (Sim0 & Sim1) == 0; } /**Function************************************************************* Synopsis [Internal simulation APIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_Min2SimSetInputBit( Gia_Man2Min_t * p, int iObj, int Bit, int iPattern ) { word * pSim = Vec_WrdEntryP( p->vSims, iObj ); assert( iPattern > 0 && iPattern < 64 ); if ( Abc_InfoHasBit( (unsigned*)pSim, iPattern ) != Bit ) Abc_InfoXorBit( (unsigned*)pSim, iPattern ); } int Gia_Min2ManSolve( Gia_Man2Min_t * p ) { int iObj0 = Abc_Lit2Var(p->iLits[0]); int iObj1 = Abc_Lit2Var(p->iLits[1]); int n, i, status, iVar0, iVar1, iTemp; assert( iObj0 > 0 && iObj1 > 0 ); // Vec_IntForEachEntry( &p->pGia->vCopies, iTemp, i ) // assert( iTemp == -1 ); Vec_IntFillExtra( &p->pGia->vCopies, Gia_ManObjNum(p->pGia), -1 ); Vec_IntClear( p->vSatVars ); assert( satoko_varnum(p->pSat) == 0 ); iVar0 = Gia_Min2ObjGetCnfVar( p, iObj0 ); iVar1 = Gia_Min2ObjGetCnfVar( p, iObj1 ); satoko_assump_push( p->pSat, Abc_Var2Lit(iVar0, Abc_LitIsCompl(p->iLits[0])) ); satoko_assump_push( p->pSat, Abc_Var2Lit(iVar1, Abc_LitIsCompl(p->iLits[1])) ); status = satoko_solve( p->pSat ); satoko_assump_pop( p->pSat ); satoko_assump_pop( p->pSat ); if ( status == SATOKO_SAT ) { //printf( "Disproved %d %d\n", p->iLits[0], p->iLits[1] ); assert( Gia_Min2ManSimulate(p) == 1 ); for ( n = 0; n < 2; n++ ) Vec_IntForEachEntry( p->vCis[n], iTemp, i ) Gia_Min2SimSetInputBit( p, iTemp, satoko_var_polarity(p->pSat, Gia_Min2ObjSatId(p->pGia, Gia_ManObj(p->pGia, iTemp))) == SATOKO_LIT_TRUE, p->iPattern ); //assert( Gia_Min2ManSimulate(p) == 0 ); p->iPattern = p->iPattern == 63 ? 1 : p->iPattern + 1; p->nSatSat++; } //printf( "supp %d node %d vars %d\n", // Vec_IntSize(p->vCis[0]) + Vec_IntSize(p->vCis[1]), // Vec_IntSize(p->vObjs[0]) + Vec_IntSize(p->vObjs[1]), // Vec_IntSize(p->vSatVars) ); satoko_rollback( p->pSat ); Vec_IntForEachEntry( p->vSatVars, iTemp, i ) Gia_Min2ObjCleanSatId( p->pGia, Gia_ManObj(p->pGia, iTemp) ); return status == SATOKO_UNSAT; } /**Function************************************************************* Synopsis [Collect nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_Min2ManGatherSupp_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vCis, Vec_Int_t * vObjs ) { int Val0, Val1; Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdPreviousId(p, iObj) ) return 1; if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) return 0; Gia_ObjSetTravIdCurrentId(p, iObj); pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjIsCi(pObj) ) { Vec_IntPush( vCis, iObj ); return 0; } assert( Gia_ObjIsAnd(pObj) ); Val0 = Gia_Min2ManGatherSupp_rec( p, Gia_ObjFaninId0(pObj, iObj), vCis, vObjs ); Val1 = Gia_Min2ManGatherSupp_rec( p, Gia_ObjFaninId1(pObj, iObj), vCis, vObjs ); Vec_IntPush( vObjs, iObj ); return Val0 || Val1; } int Gia_Min2ManGatherSupp( Gia_Man2Min_t * p ) { int n, Overlap = 0; p->nSupps++; Gia_ManIncrementTravId( p->pGia ); for ( n = 0; n < 2; n++ ) { Vec_IntClear( p->vCis[n] ); Vec_IntClear( p->vObjs[n] ); Gia_ManIncrementTravId( p->pGia ); Overlap = Gia_Min2ManGatherSupp_rec( p->pGia, Abc_Lit2Var(p->iLits[n]), p->vCis[n], p->vObjs[n] ); assert( n || !Overlap ); } return Overlap; } /**Function************************************************************* Synopsis [Takes a literal and returns a support-minized literal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_Man2SupportAnd( Gia_Man2Min_t * p, int iLit0, int iLit1 ) { p->nCalls++; //return Gia_ManHashAnd( p->pGia, iLit0, iLit1 ); p->iLits[0] = iLit0; p->iLits[1] = iLit1; if ( iLit0 < 2 || iLit1 < 2 || Abc_Lit2Var(iLit0) == Abc_Lit2Var(iLit1) || Gia_ManHashLookupInt(p->pGia, iLit0, iLit1) || !Gia_Min2ManGatherSupp(p) || !Gia_Min2ManSimulate(p) || !Gia_Min2ManSolve(p) ) return Gia_ManHashAnd( p->pGia, iLit0, iLit1 ); //printf( "%d %d\n", iLit0, iLit1 ); p->nSatUnsat++; return 0; } /**Function************************************************************* Synopsis [Testbench.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_Man2SupportAndTest( Gia_Man_t * pGia ) { Gia_Man2Min_t * pMan; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i; Gia_ManRandomW( 1 ); Gia_ManFillValue( pGia ); pNew = Gia_ManStart( Gia_ManObjNum(pGia) ); pNew->pName = Abc_UtilStrsav( pGia->pName ); pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); Gia_ManHashAlloc( pNew ); Gia_ManConst0(pGia)->Value = 0; pMan = Gia_Man2SuppStart( pNew ); Gia_ManForEachObj1( pGia, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) { // pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); pObj->Value = Gia_Man2SupportAnd( pMan, 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) ); else assert( 0 ); //if ( i % 10000 == 0 ) // printf( "%d\n", i ); } Gia_Man2SuppStop( pMan ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSupps.c000066400000000000000000001230401477524141600162260ustar00rootroot00000000000000/**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 "base/io/ioResub.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; } int Supp_DeriveLines2( Supp_Man_t * p ) { assert( Vec_WrdSize(p->vSims) % p->nWords == 0 ); int n, nDivWords = Abc_Bit6WordNum( Vec_WrdSize(p->vSims) / p->nWords ); for ( n = 0; n < 2; n++ ) { p->vDivs[n] = Vec_WrdStart( 64*p->nWords*nDivWords ); p->vPats[n] = Vec_WrdStart( 64*p->nWords*nDivWords ); Abc_TtCopy( Vec_WrdArray(p->vDivs[n]), Vec_WrdArray(p->vSims), Vec_WrdSize(p->vSims), !n ); Extra_BitMatrixTransposeP( p->vDivs[n], p->nWords, p->vPats[n], nDivWords ); } return nDivWords; } Supp_Man_t * Supp_ManCreate2( Vec_Wrd_t * vIsfs, Vec_Wrd_t * vSims, Vec_Int_t * vWeights, int nWords, int nIters, int nRounds ) { Supp_Man_t * p = ABC_CALLOC( Supp_Man_t, 1 ); assert( Vec_WrdSize(vSims)%nWords == 0 ); p->nIters = nIters; p->nRounds = nRounds; p->nWords = nWords; p->vIsfs = vIsfs; p->vCands = Vec_IntStartNatural( Vec_WrdSize(vSims)/nWords ); p->vWeights = NULL; p->vSims = vSims; p->vSimsC = NULL; p->pGia = NULL; // computed data p->nDivWords = Supp_DeriveLines2( p ); p->vMatrix = Vec_PtrAlloc( 100 ); p->vMask = Vec_WrdAlloc( 100 ); p->vRowTemp = Vec_WrdStart( 64*p->nDivWords ); p->vCosts = Vec_IntStart( Vec_IntSize(p->vCands) ); p->pHash = Hsh_VecManStart( 1000 ); p->vSFuncs = Vec_WrdAlloc( 1000 ); p->vSStarts = Vec_IntAlloc( 1000 ); p->vSCount = Vec_IntAlloc( 1000 ); p->vSPairs = Vec_IntAlloc( 1000 ); p->vSolutions = Vec_WecStart( 16 ); p->vTemp = Vec_IntAlloc( 10 ); p->vTempSets = Vec_IntAlloc( 10 ); p->vTempPairs = Vec_IntAlloc( 10 ); Supp_ManInit( p ); return p; } void Supp_ManCleanMatrix( Supp_Man_t * p ) { Vec_Wrd_t * vTemp; int i; 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 ); if ( p->vSims == NULL ) Vec_IntFreeP( &p->vCands ); 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 ); // return -1 if the pair cannot be distinguished by any divisor // in this case the original resub problem has no solution if ( iDiv == ABC_INFINITY ) return -1; 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 ); if ( iDiv == -1 ) return -1; 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 [] ***********************************************************************/ void Supp_DeriveDumpProb2( Vec_Wrd_t * vIsfs, Vec_Wrd_t * vDivs, int nWords, Vec_Int_t * vSupp, Vec_Int_t * vRes ) { char Buffer[100]; int i, k, Temp, nDivs = Vec_WrdSize(vDivs)/nWords; int RetValue = sprintf( Buffer, "%02d.pla", s_Counter ); FILE * pFile = fopen( Buffer, "wb" ); if ( pFile == NULL ) printf( "Cannot open output file.\n" ); // fprintf( pFile, "resyn %d %d %d %d\n", 0, nDivs, 1, 64*nWords ); fprintf( pFile, ".i %d\n", nDivs ); fprintf( pFile, ".o %d\n", 1 ); fprintf( pFile, ".p %d\n", 64*nWords ); for ( i = 0; i < 64*nWords; i++ ) { for ( k = 0; k < nDivs; k++ ) fprintf( pFile, "%d", Abc_TtGetBit(Vec_WrdEntryP(vDivs, k*nWords), i) ); // fprintf( pFile, " %d\n", Abc_TtGetBit(Vec_WrdEntryP(vIsfs, 1*nWords), i) ); if ( Abc_TtGetBit(Vec_WrdEntryP(vIsfs, 0*nWords), i) ) fprintf( pFile, " 0\n" ); else if ( Abc_TtGetBit(Vec_WrdEntryP(vIsfs, 1*nWords), i) ) fprintf( pFile, " 1\n" ); else fprintf( pFile, " -\n" ); } fprintf( pFile, ".e\n" ); fprintf( pFile, "\n.s" ); Vec_IntForEachEntryStart( vSupp, Temp, i, 2 ) fprintf( pFile, " %d", Temp ); fprintf( pFile, "\n.a" ); Vec_IntForEachEntry( vRes, Temp, i ) fprintf( pFile, " %d", Temp ); fprintf( pFile, "\n" ); fclose ( pFile ); RetValue = 0; } /**Function************************************************************* Synopsis [] 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 * vDivs2 = Vec_IntAlloc( 100 ); Vec_Int_t * vSet = Hsh_VecReadEntry( p->pHash, iSolBest ); int i, iObj; vRes = Gia_ManDeriveSolutionOne( p->pGia, p->vSims, p->vIsfs, p->vCands, vSet, p->nWords, CostBest & 3 ); assert( !vRes || Vec_IntSize(vRes) == 2*(CostBest >> 2)+1 ); if ( vRes && pvDivs ) { Vec_IntClear( *pvDivs ); Vec_IntPushTwo( *pvDivs, -1, -1 ); Vec_IntPushTwo( vDivs2, -1, -1 ); Vec_IntForEachEntry( vSet, iObj, i ) { Vec_IntPush( *pvDivs, Vec_IntEntry(p->vCands, iObj) ); Vec_IntPush( vDivs2, iObj ); } } //Supp_DeriveDumpProbC( p->vIsfs, p->vDivsC, p->nWords ); //Supp_DeriveDumpProb( p->vIsfs, p->vDivs[1], p->nWords ); //Supp_DeriveDumpSol( vSet, vRes, Vec_WrdSize(p->vDivs[1])/p->nWords ); //Supp_DeriveDumpProb2( p->vIsfs, p->vDivs[1], p->nWords, vDivs2, vRes ); Vec_IntFree( vDivs2 ); 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; if ( vCands ) p = Supp_ManCreate( vIsfs, vCands, vWeights, vSims, vSimsC, nWords, pGia, nIters, nRounds ); else p = Supp_ManCreate2( vIsfs, vSims, NULL, nWords, nIters, nRounds ); if ( Supp_SetFuncNum(p, 0) == 0 ) { Supp_ManDelete( p ); 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( "Using %d divisors with %d words. Problem has %d functions and %d minterm pairs.\n", Vec_IntSize(p->vCands), p->nWords, Supp_SetFuncNum(p, 0), Supp_SetPairNum(p, 0) ); //iBest = Supp_FindGivenOne( p ); if ( iBest == -1 ) for ( i = 0; i < p->nIters; i++ ) { Supp_ManAddPatternsFunc( p, i ); iSet = Supp_ManRandomSolution( p, 0, fVeryVerbose ); if ( iSet == -1 ) { Supp_ManDelete( p ); return NULL; } 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 ( iSet == -1 ) { Supp_ManDelete( p ); return NULL; } } 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 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Supp_RecordSolution( char * pFileName, Vec_Int_t * vDivs, Vec_Int_t * vRes ) { FILE * pFile = fopen( pFileName, "ab" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; } int i, Temp; fprintf( pFile, "\n.s" ); Vec_IntForEachEntryStart( vDivs, Temp, i, 2 ) fprintf( pFile, " %d", Temp ); fprintf( pFile, "\n.a" ); Vec_IntForEachEntry( vRes, Temp, i ) fprintf( pFile, " %d", Temp-2 ); fprintf( pFile, "\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Supp_GenerateGia( Vec_Int_t * vRes, Vec_Int_t * vDivs ) { int i, nAddOn = 2, nIns = Vec_IntSize(vDivs)-2; int iLit0, iLit1, iTopLit = Vec_IntEntryLast(vRes); assert( Vec_IntSize(vRes) > 0 ); assert( Vec_IntSize(vRes) % 2 == 1 ); Gia_Man_t * pNew = Gia_ManStart( 100 ); pNew->pName = Abc_UtilStrsav( "resub" ); for ( i = 0; i < nIns; i++ ) Gia_ManAppendCi(pNew); Vec_IntForEachEntryDouble( vRes, iLit0, iLit1, i ) { if ( iLit0 < iLit1 ) Gia_ManAppendAnd( pNew, iLit0-nAddOn, iLit1-nAddOn ); else if ( iLit0 > iLit1 ) Gia_ManAppendXor( pNew, iLit0-nAddOn, iLit1-nAddOn ); else assert( 0 ); } Gia_ManAppendCo(pNew, iTopLit-nAddOn); return pNew; } Gia_Man_t * Supp_ManSolveOne( char * pFileName, int nIters, int nRounds, int fWriteSol, int fVerbose ) { //Abc_Random(1); Abc_RData_t * p = Abc_ReadPla( pFileName ); if ( p == NULL ) return NULL; assert( p->nOuts == 1 ); Vec_Int_t * vDivs = Vec_IntAlloc( 100 ); Vec_Int_t * vRes = Supp_ManCompute( p->vSimsOut, NULL, NULL, p->vSimsIn, NULL, p->nSimWords, NULL, &vDivs, nIters, nRounds, fVerbose ); if ( fVerbose && vDivs ) printf( "Divisors: " ), Vec_IntPrint( vDivs ); if ( fVerbose && vRes ) printf( "Solution: " ), Vec_IntPrint( vRes ); Gia_Man_t * pNew = vRes ? Supp_GenerateGia( vRes, vDivs ) : NULL; if ( fWriteSol && vDivs && vRes ) Supp_RecordSolution( pFileName, vDivs, vRes ); Vec_IntFreeP( &vRes ); Vec_IntFreeP( &vDivs ); Abc_RDataStop( p ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSweep.c000066400000000000000000000667551477524141600162220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaSweep.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Sweeping of GIA manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaSweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "giaAig.h" #include "proof/dch/dch.h" #include "misc/tim/tim.h" #include "proof/cec/cec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Mark GIA nodes that feed into POs.] Description [Returns the array of classes of remaining registers.] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManMarkSeqGiaWithBoxes_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vRoots ) { Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; int i, iBox, nBoxIns, nBoxOuts, iShift, nRealCis; if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsAnd(pObj) ) { Gia_ManMarkSeqGiaWithBoxes_rec( p, Gia_ObjFanin0(pObj), vRoots ); Gia_ManMarkSeqGiaWithBoxes_rec( p, Gia_ObjFanin1(pObj), vRoots ); return; } assert( Gia_ObjIsCi(pObj) ); nRealCis = Tim_ManPiNum(pManTime); if ( Gia_ObjCioId(pObj) < nRealCis ) { int nRegs = Gia_ManRegBoxNum(p); int iFlop = Gia_ObjCioId(pObj) - (nRealCis - nRegs); assert( iFlop >= 0 && iFlop < nRegs ); pObj = Gia_ManCo( p, Gia_ManPoNum(p) - nRegs + iFlop ); Vec_IntPush( vRoots, Gia_ObjId(p, pObj) ); return; } // get the box iBox = Tim_ManBoxForCi( pManTime, Gia_ObjCioId(pObj) ); nBoxIns = Tim_ManBoxInputNum(pManTime, iBox); nBoxOuts = Tim_ManBoxOutputNum(pManTime, iBox); // mark all outputs iShift = Tim_ManBoxOutputFirst(pManTime, iBox); for ( i = 0; i < nBoxOuts; i++ ) Gia_ObjSetTravIdCurrent(p, Gia_ManCi(p, iShift + i)); // traverse from inputs iShift = Tim_ManBoxInputFirst(pManTime, iBox); for ( i = 0; i < nBoxIns; i++ ) Gia_ObjSetTravIdCurrent(p, Gia_ManCo(p, iShift + i)); for ( i = 0; i < nBoxIns; i++ ) Gia_ManMarkSeqGiaWithBoxes_rec( p, Gia_ObjFanin0(Gia_ManCo(p, iShift + i)), vRoots ); } void Gia_ManMarkSeqGiaWithBoxes( Gia_Man_t * p, int fSeq ) { // CI order: real PIs + flop outputs + box outputs // CO order: box inputs + real POs + flop inputs Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; Vec_Int_t * vRoots; Gia_Obj_t * pObj; int nRealCis = Tim_ManPiNum(pManTime); int nRealCos = Tim_ManPoNum(pManTime); int i, nRegs = fSeq ? Gia_ManRegBoxNum(p) : 0; assert( Gia_ManRegNum(p) == 0 ); assert( Gia_ManBoxNum(p) > 0 ); // mark the terminals Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); for ( i = 0; i < nRealCis - nRegs; i++ ) Gia_ObjSetTravIdCurrent( p, Gia_ManPi(p, i) ); // collect flops reachable from the POs vRoots = Vec_IntAlloc( Gia_ManRegBoxNum(p) ); for ( i = Gia_ManPoNum(p) - nRealCos; i < Gia_ManPoNum(p) - nRegs; i++ ) { Gia_ObjSetTravIdCurrent( p, Gia_ManPo(p, i) ); Gia_ManMarkSeqGiaWithBoxes_rec( p, Gia_ObjFanin0(Gia_ManPo(p, i)), vRoots ); } // collect flops reachable from roots if ( fSeq ) { Gia_ManForEachObjVec( vRoots, p, pObj, i ) { assert( Gia_ObjIsCo(pObj) ); Gia_ObjSetTravIdCurrent( p, pObj ); Gia_ManMarkSeqGiaWithBoxes_rec( p, Gia_ObjFanin0(pObj), vRoots ); } //printf( "Explored %d flops\n", Vec_IntSize(vRoots) ); } Vec_IntFree( vRoots ); } Gia_Man_t * Gia_ManDupWithBoxes( Gia_Man_t * p, int fSeq ) { Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; Gia_Man_t * pNew; Gia_Obj_t * pObj; Vec_Int_t * vBoxesLeft; int curCi, curCo, nBoxIns, nBoxOuts; int i, k, iShift, nMarked; assert( Gia_ManBoxNum(p) > 0 ); // mark useful boxes Gia_ManMarkSeqGiaWithBoxes( p, fSeq ); // duplicate marked entries 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_ObjIsTravIdCurrent(p, pObj) ) continue; if ( Gia_ObjIsCi(pObj) ) pObj->Value = Gia_ManAppendCi(pNew); else 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 ); } assert( !Gia_ManHasDangling(pNew) ); // collect remaining flops if ( fSeq ) { pNew->vRegClasses = Vec_IntAlloc( Gia_ManRegBoxNum(p) ); if ( p->vRegInits ) pNew->vRegInits = Vec_IntAlloc( Gia_ManRegBoxNum(p) ); iShift = Gia_ManPoNum(p) - Gia_ManRegBoxNum(p); for ( i = 0; i < Gia_ManRegBoxNum(p); i++ ) if ( Gia_ObjIsTravIdCurrent(p, Gia_ManCo(p, iShift + i)) ) { Vec_IntPush( pNew->vRegClasses, Vec_IntEntry(p->vRegClasses, i) ); if ( p->vRegInits ) Vec_IntPush( pNew->vRegInits, Vec_IntEntry(p->vRegInits, i) ); } } else { if ( p->vRegClasses ) pNew->vRegClasses = Vec_IntDup( p->vRegClasses ); if ( p->vRegInits ) pNew->vRegInits = Vec_IntDup( p->vRegInits ); } // collect remaining boxes vBoxesLeft = Vec_IntAlloc( Gia_ManBoxNum(p) ); curCi = Tim_ManPiNum(pManTime); curCo = 0; for ( i = 0; i < Gia_ManBoxNum(p); i++ ) { nBoxIns = Tim_ManBoxInputNum(pManTime, i); nBoxOuts = Tim_ManBoxOutputNum(pManTime, i); nMarked = 0; for ( k = 0; k < nBoxIns; k++ ) nMarked += Gia_ObjIsTravIdCurrent( p, Gia_ManCo(p, curCo + k) ); for ( k = 0; k < nBoxOuts; k++ ) nMarked += Gia_ObjIsTravIdCurrent( p, Gia_ManCi(p, curCi + k) ); curCo += nBoxIns; curCi += nBoxOuts; // check presence assert( nMarked == 0 || nMarked == nBoxIns + nBoxOuts ); if ( nMarked ) Vec_IntPush( vBoxesLeft, i ); } curCo += Tim_ManPoNum(pManTime); assert( curCi == Gia_ManCiNum(p) ); assert( curCo == Gia_ManCoNum(p) ); // update timing manager pNew->pManTime = Gia_ManUpdateTimMan2( p, vBoxesLeft, Gia_ManRegBoxNum(p) - Gia_ManRegBoxNum(pNew) ); // update extra STG assert( p->pAigExtra != NULL ); assert( pNew->pAigExtra == NULL ); 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; } /**Function************************************************************* Synopsis [Mark GIA nodes that feed into POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFraigCheckCis( Gia_Man_t * p, Gia_Obj_t * pObj ) { for ( assert( Gia_ObjIsCi(pObj) ); Gia_ObjIsCi(pObj); pObj-- ) if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 1; return 0; } Gia_Obj_t * Gia_ManFraigMarkCis( Gia_Man_t * p, Gia_Obj_t * pObj, int fMark ) { for ( assert( Gia_ObjIsCi(pObj) ); Gia_ObjIsCi(pObj); pObj-- ) if ( fMark ) Gia_ObjSetTravIdCurrent( p, pObj ); return pObj; } Gia_Obj_t * Gia_ManFraigMarkCos( Gia_Man_t * p, Gia_Obj_t * pObj, int fMark ) { for ( assert( Gia_ObjIsCo(pObj) ); Gia_ObjIsCo(pObj); pObj-- ) if ( fMark ) { Gia_ObjSetTravIdCurrent( p, pObj ); Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) ); } return pObj; } Gia_Obj_t * Gia_ManFraigMarkAnd( Gia_Man_t * p, Gia_Obj_t * pObj ) { for ( assert( Gia_ObjIsAnd(pObj) ); Gia_ObjIsAnd(pObj); pObj-- ) if ( Gia_ObjIsTravIdCurrent(p, pObj) ) { Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) ); Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin1(pObj) ); } return pObj; } Gia_Man_t * Gia_ManFraigCreateGia( Gia_Man_t * p ) { Vec_Int_t * vBoxPres; Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, fLabelPos; assert( p->pManTime != NULL ); // start marks Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); vBoxPres = Vec_IntAlloc( 1000 ); // mark primary outputs fLabelPos = 1; pObj = Gia_ManObj( p, Gia_ManObjNum(p) - 1 ); assert( Gia_ObjIsCo(pObj) ); while ( Gia_ObjIsCo(pObj) ) { pObj = Gia_ManFraigMarkCos( p, pObj, fLabelPos ); if ( Gia_ObjIsAnd(pObj) ) pObj = Gia_ManFraigMarkAnd( p, pObj ); assert( Gia_ObjIsCi(pObj) ); fLabelPos = Gia_ManFraigCheckCis(p, pObj); pObj = Gia_ManFraigMarkCis( p, pObj, fLabelPos ); Vec_IntPush( vBoxPres, fLabelPos ); } Vec_IntPop( vBoxPres ); Vec_IntReverseOrder( vBoxPres ); assert( Gia_ObjIsConst0(pObj) ); // mark primary inputs Gia_ManForEachObj1( p, pObj, i ) if ( Gia_ObjIsCi(pObj) ) Gia_ObjSetTravIdCurrent( p, pObj ); else break; // duplicate marked entries 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_ObjIsTravIdCurrent(p, pObj) ) continue; if ( Gia_ObjIsCi(pObj) ) pObj->Value = Gia_ManAppendCi(pNew); else 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 ); } // update timing manager pNew->pManTime = Gia_ManUpdateTimMan( p, vBoxPres ); // update extra STG assert( p->pAigExtra != NULL ); assert( pNew->pAigExtra == NULL ); pNew->pAigExtra = Gia_ManUpdateExtraAig( p->pManTime, p->pAigExtra, vBoxPres ); Vec_IntFree( vBoxPres ); // assert( Gia_ManPiNum(pNew) == Tim_ManCiNum(pNew->pManTime) ); // assert( Gia_ManPoNum(pNew) == Tim_ManCoNum(pNew->pManTime) ); // assert( Gia_ManPiNum(pNew) == Tim_ManPiNum(pNew->pManTime) + Gia_ManPoNum(pNew->pAigExtra) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ObjFanin0CopyRepr( Gia_Man_t * p, Gia_Obj_t * pObj, int * pReprs ) { int fanId = Gia_ObjFaninId0p( p, pObj ); if ( pReprs[fanId] == -1 ) return Gia_ObjFanin0Copy( pObj ); assert( Abc_Lit2Var(pReprs[fanId]) < Gia_ObjId(p, pObj) ); return Abc_LitNotCond( Gia_ObjValue(Gia_ManObj(p, Abc_Lit2Var(pReprs[fanId]))), Gia_ObjFaninC0(pObj) ^ Abc_LitIsCompl(pReprs[fanId]) ); } int Gia_ObjFanin1CopyRepr( Gia_Man_t * p, Gia_Obj_t * pObj, int * pReprs ) { int fanId = Gia_ObjFaninId1p( p, pObj ); if ( pReprs[fanId] == -1 ) return Gia_ObjFanin1Copy( pObj ); assert( Abc_Lit2Var(pReprs[fanId]) < Gia_ObjId(p, pObj) ); return Abc_LitNotCond( Gia_ObjValue(Gia_ManObj(p, Abc_Lit2Var(pReprs[fanId]))), Gia_ObjFaninC1(pObj) ^ Abc_LitIsCompl(pReprs[fanId]) ); } Gia_Man_t * Gia_ManFraigReduceGia( Gia_Man_t * p, int * pReprs ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; assert( pReprs != NULL ); 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_ManHashAlloc( pNew ); Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0CopyRepr(p, pObj, pReprs), Gia_ObjFanin1CopyRepr(p, pObj, pReprs) ); else if ( Gia_ObjIsCi(pObj) ) pObj->Value = Gia_ManAppendCi( pNew ); else if ( Gia_ObjIsCo(pObj) ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0CopyRepr(p, pObj, pReprs) ); else if ( Gia_ObjIsConst0(pObj) ) pObj->Value = 0; else assert( 0 ); } Gia_ManHashStop( pNew ); return pNew; } /**Function************************************************************* Synopsis [Compute the set of CIs representing carry-outs of boxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManComputeCarryOuts( Gia_Man_t * p ) { Gia_Obj_t * pObj; 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 ); pObj = Gia_ObjFanin0( Gia_ManCo(p, iLast) ); if ( !Gia_ObjIsCi(pObj) ) continue; iBox = Tim_ManBoxForCi( pManTime, Gia_ObjCioId(pObj) ); if ( iBox == -1 ) continue; assert( Gia_ObjIsCi(pObj) ); 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; } /**Function************************************************************* Synopsis [Checks integriting of complex flops and carry-chains.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCheckIntegrityWithBoxes( Gia_Man_t * p ) { Gia_Obj_t * pObj; Vec_Int_t * vCarryOuts; int i, nCountReg = 0, nCountCarry = 0; if ( p->pManTime == NULL ) return; ABC_FREE( p->pRefs ); Gia_ManCreateRefs( p ); for ( i = Gia_ManPoNum(p) - Gia_ManRegBoxNum(p); i < Gia_ManPoNum(p); i++ ) { pObj = Gia_ObjFanin0( Gia_ManPo(p, i) ); assert( Gia_ObjIsCi(pObj) ); if ( Gia_ObjRefNum(p, pObj) > 1 ) nCountReg++; } vCarryOuts = Gia_ManComputeCarryOuts( p ); Gia_ManForEachObjVec( vCarryOuts, p, pObj, i ) if ( Gia_ObjRefNum(p, pObj) > 1 ) nCountCarry++; Vec_IntFree( vCarryOuts ); if ( nCountReg || nCountCarry ) printf( "Warning: AIG with boxes has internal fanout in %d complex flops and %d carries.\n", nCountReg, nCountCarry ); ABC_FREE( p->pRefs ); } /**Function************************************************************* Synopsis [Computes representatives in terms of the original objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Gia_ManFraigSelectReprs( Gia_Man_t * p, Gia_Man_t * pClp, int fVerbose, int pFlopTypes[3] ) { Gia_Obj_t * pObj; Vec_Int_t * vCarryOuts; Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; int * pReprs = ABC_FALLOC( int, Gia_ManObjNum(p) ); int * pClp2Gia = ABC_FALLOC( int, Gia_ManObjNum(pClp) ); int i, iLitClp, iLitClp2, iReprClp, fCompl; int nConsts = 0, nReprs = 0; assert( pManTime != NULL ); // count the number of equivalent objects Gia_ManForEachObj1( pClp, pObj, i ) { if ( Gia_ObjIsCo(pObj) ) continue; if ( i == Gia_ObjReprSelf(pClp, i) ) continue; if ( Gia_ObjReprSelf(pClp, i) == 0 ) nConsts++; else nReprs++; } if ( fVerbose ) printf( "Computed %d const objects and %d other objects.\n", nConsts, nReprs ); nConsts = nReprs = 0; // mark flop input boxes Gia_ManCleanMark0( p ); for ( i = Gia_ManPoNum(p) - Gia_ManRegBoxNum(p); i < Gia_ManPoNum(p); i++ ) { pObj = Gia_ObjFanin0( Gia_ManPo(p, i) ); assert( Gia_ObjIsCi(pObj) ); pObj->fMark0 = 1; } // mark connects between last box inputs and first box outputs vCarryOuts = Gia_ManComputeCarryOuts( p ); Gia_ManForEachObjVec( vCarryOuts, p, pObj, i ) pObj->fMark0 = 1; if ( fVerbose ) printf( "Fixed %d flop inputs and %d box/box connections (out of %d non-flop boxes).\n", Gia_ManRegBoxNum(p), Vec_IntSize(vCarryOuts), Gia_ManNonRegBoxNum(p) ); Vec_IntFree( vCarryOuts ); // collect equivalent node info pFlopTypes[0] = pFlopTypes[1] = pFlopTypes[2] = 0; Gia_ManForEachRo( pClp, pObj, i ) { Gia_Obj_t * pRepr = Gia_ObjReprObj(pClp, i); if ( pRepr && pRepr != pObj ) { if ( pRepr == Gia_ManConst0(pClp) ) pFlopTypes[0]++; else if ( Gia_ObjIsRo(pClp, pRepr) ) pFlopTypes[1]++; } } // compute representatives pClp2Gia[0] = 0; Gia_ManSetPhase( pClp ); Gia_ManForEachObj1( p, pObj, i ) { if ( Gia_ObjIsCo(pObj) ) continue; if ( Gia_ObjIsCi(pObj) && pObj->fMark0 ) // skip CI pointed by CO continue; assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) ); iLitClp = Gia_ObjValue(pObj); if ( iLitClp == -1 ) continue; iReprClp = Gia_ObjReprSelf( pClp, Abc_Lit2Var(iLitClp) ); if ( pClp2Gia[iReprClp] == -1 ) pClp2Gia[iReprClp] = i; else { iLitClp2 = Gia_ObjValue( Gia_ManObj(p, pClp2Gia[iReprClp]) ); assert( Gia_ObjReprSelf(pClp, Abc_Lit2Var(iLitClp)) == Gia_ObjReprSelf(pClp, Abc_Lit2Var(iLitClp2)) ); fCompl = Abc_LitIsCompl(iLitClp) ^ Abc_LitIsCompl(iLitClp2); fCompl ^= Gia_ManObj(pClp, Abc_Lit2Var(iLitClp))->fPhase; fCompl ^= Gia_ManObj(pClp, Abc_Lit2Var(iLitClp2))->fPhase; pReprs[i] = Abc_Var2Lit( pClp2Gia[iReprClp], fCompl ); assert( Abc_Lit2Var(pReprs[i]) < i ); if ( pClp2Gia[iReprClp] == 0 ) nConsts++; else nReprs++; } } ABC_FREE( pClp2Gia ); Gia_ManForEachCi( p, pObj, i ) pObj->fMark0 = 0; if ( fVerbose ) printf( "Found %d const objects and %d other objects.\n", nConsts, nReprs ); return pReprs; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFraigSweepPerform( Gia_Man_t * p, void * pPars ) { Aig_Man_t * pNew; pNew = Gia_ManToAigSimple( p ); assert( Gia_ManObjNum(p) == Aig_ManObjNum(pNew) ); Dch_ComputeEquivalences( pNew, (Dch_Pars_t *)pPars ); Gia_ManReprFromAigRepr( pNew, p ); Aig_ManStop( pNew ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManFraigSweepSimple( Gia_Man_t * p, void * pPars ) { Gia_Man_t * pNew; assert( p->pManTime == NULL || Gia_ManBoxNum(p) == 0 ); Gia_ManFraigSweepPerform( p, pPars ); pNew = Gia_ManEquivReduce( p, 1, 0, 0, 0 ); if ( pNew == NULL ) pNew = Gia_ManDup(p); Gia_ManTransferTiming( pNew, p ); return pNew; } /**Function************************************************************* Synopsis [Computes equivalences for one clock domain.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSweepComputeOneDomainEquivs( Gia_Man_t * p, Vec_Int_t * vRegClasses, int iDom, void * pParsS, int fConst, int fEquiv, int fVerbose ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; Vec_Int_t * vPerm; int i, Class, nFlops; int nDoms = Vec_IntFindMax(vRegClasses); assert( iDom >= 1 && iDom <= nDoms ); assert( p->pManTime == NULL ); assert( Gia_ManRegNum(p) > 0 ); // create required flop permutation vPerm = Vec_IntAlloc( Gia_ManRegNum(p) ); Vec_IntForEachEntry( vRegClasses, Class, i ) if ( Class != iDom ) Vec_IntPush( vPerm, i ); nFlops = Vec_IntSize( vPerm ); Vec_IntForEachEntry( vRegClasses, Class, i ) if ( Class == iDom ) Vec_IntPush( vPerm, i ); nFlops = Vec_IntSize(vPerm) - nFlops; assert( Vec_IntSize(vPerm) == Gia_ManRegNum(p) ); // derive new AIG pNew = Gia_ManDupPermFlop( p, vPerm ); assert( Gia_ManObjNum(pNew) == Gia_ManObjNum(p) ); Vec_IntFree( vPerm ); // perform computation of equivalences pNew->nRegs = nFlops; if ( pParsS ) Cec_ManLSCorrespondenceClasses( pNew, (Cec_ParCor_t *)pParsS ); else Gia_ManSeqCleanupClasses( pNew, fConst, fEquiv, fVerbose ); pNew->nRegs = Gia_ManRegNum(p); // 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); } // transfer Gia_ManDupRemapEquiv( p, pNew ); Gia_ManStop( pNew ); } Gia_Man_t * Gia_ManSweepWithBoxesAndDomains( Gia_Man_t * p, void * pParsS, int fConst, int fEquiv, int fVerbose, int fVerbEquivs ) { Gia_Man_t * pClp, * pNew, * pTemp; int nDoms = Vec_IntFindMax(p->vRegClasses); int * pReprs, iDom, pFlopTypes[3] = {0}; assert( Gia_ManRegNum(p) == 0 ); assert( p->pAigExtra != NULL ); assert( nDoms > 1 ); // order AIG objects pNew = Gia_ManDupUnnormalize( p ); if ( pNew == NULL ) return NULL; Gia_ManTransferTiming( pNew, p ); // iterate over domains for ( iDom = 1; iDom <= nDoms; iDom++ ) { int nFlopsNew, nFlops = Vec_IntCountEntry(pNew->vRegClasses, iDom); if ( nFlops < 2 ) continue; // find global equivalences pClp = Gia_ManDupCollapse( pNew, pNew->pAigExtra, NULL, 1 ); //Gia_DumpAiger( pClp, p->pSpec, iDom, 2 ); //Gia_ManPrintStats( pClp, NULL ); // compute equivalences Gia_ManSweepComputeOneDomainEquivs( pClp, pNew->vRegClasses, iDom, pParsS, fConst, fEquiv, fVerbose ); // transfer equivalences pReprs = Gia_ManFraigSelectReprs( pNew, pClp, fVerbose, pFlopTypes ); Gia_ManStop( pClp ); // reduce AIG Gia_ManTransferTiming( p, pNew ); pNew = Gia_ManFraigReduceGia( pTemp = pNew, pReprs ); Gia_ManTransferTiming( pNew, p ); Gia_ManStop( pTemp ); ABC_FREE( pReprs ); // derive new AIG pNew = Gia_ManDupWithBoxes( pTemp = pNew, 1 ); Gia_ManStop( pTemp ); // report nFlopsNew = Vec_IntCountEntry(pNew->vRegClasses, iDom); pFlopTypes[2] = nFlops - nFlopsNew - (pFlopTypes[0] + pFlopTypes[1]); if ( fVerbEquivs ) { printf( "Domain %2d : %5d -> %5d : ", iDom, nFlops, nFlopsNew ); printf( "EqConst =%4d. EqFlop =%4d. Dangling =%4d. Unused =%4d.\n", pFlopTypes[0], pFlopTypes[1], Abc_MaxInt(0, pFlopTypes[2]), Abc_MaxInt(0, -pFlopTypes[2]) ); //Gia_ManPrintStats( pNew, NULL ); } } // normalize the result pNew = Gia_ManDupNormalize( pTemp = pNew, 0 ); Gia_ManTransferTiming( pNew, pTemp ); Gia_ManStop( pTemp ); // check integrity //Gia_ManCheckIntegrityWithBoxes( pNew ); return pNew; } /**Function************************************************************* Synopsis [Reduces root model with scorr.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManSweepWithBoxes( Gia_Man_t * p, void * pParsC, void * pParsS, int fConst, int fEquiv, int fVerbose, int fVerbEquivs ) { Gia_Man_t * pClp, * pNew, * pTemp; int * pReprs, pFlopTypes[3] = {0}; int nFlopsNew, nFlops; assert( Gia_ManRegNum(p) == 0 ); assert( p->pAigExtra != NULL ); // consider seq synthesis with multiple clock domains if ( pParsC == NULL && Gia_ManClockDomainNum(p) > 1 ) return Gia_ManSweepWithBoxesAndDomains( p, pParsS, fConst, fEquiv, fVerbose, fVerbEquivs ); // order AIG objects pNew = Gia_ManDupUnnormalize( p ); if ( pNew == NULL ) return NULL; Gia_ManTransferTiming( pNew, p ); nFlops = Vec_IntCountEntry(pNew->vRegClasses, 1); // find global equivalences pClp = Gia_ManDupCollapse( pNew, pNew->pAigExtra, NULL, pParsC ? 0 : 1 ); //Gia_DumpAiger( pClp, p->pSpec, 1, 1 ); // compute equivalences if ( pParsC ) Gia_ManFraigSweepPerform( pClp, pParsC ); else if ( pParsS ) Cec_ManLSCorrespondenceClasses( pClp, (Cec_ParCor_t *)pParsS ); else Gia_ManSeqCleanupClasses( pClp, fConst, fEquiv, fVerbose ); // transfer equivalences pReprs = Gia_ManFraigSelectReprs( pNew, pClp, fVerbose, pFlopTypes ); Gia_ManStop( pClp ); // reduce AIG Gia_ManTransferTiming( p, pNew ); pNew = Gia_ManFraigReduceGia( pTemp = pNew, pReprs ); Gia_ManTransferTiming( pNew, p ); Gia_ManStop( pTemp ); ABC_FREE( pReprs ); // derive new AIG pNew = Gia_ManDupWithBoxes( pTemp = pNew, pParsC ? 0 : 1 ); Gia_ManStop( pTemp ); // report nFlopsNew = Vec_IntCountEntry(pNew->vRegClasses, 1); pFlopTypes[2] = nFlops - nFlopsNew - (pFlopTypes[0] + pFlopTypes[1]); if ( fVerbEquivs ) { printf( "Domain %2d : %5d -> %5d : ", 1, nFlops, nFlopsNew ); printf( "EqConst =%4d. EqFlop =%4d. Dangling =%4d. Unused =%4d.\n", pFlopTypes[0], pFlopTypes[1], Abc_MaxInt(0, pFlopTypes[2]), Abc_MaxInt(0, -pFlopTypes[2]) ); } // normalize the result pNew = Gia_ManDupNormalize( pTemp = pNew, 0 ); Gia_ManTransferTiming( pNew, pTemp ); Gia_ManStop( pTemp ); // check integrity //Gia_ManCheckIntegrityWithBoxes( pNew ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSweeper.c000066400000000000000000001176101477524141600165340ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaSweeper.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Incremental SAT sweeper.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaSweeper.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "base/main/main.h" #include "sat/bsat/satSolver.h" #include "proof/ssc/ssc.h" ABC_NAMESPACE_IMPL_START /* SAT sweeping/equivalence checking requires the following steps: - Creating probes These APIs should be called for all internal points in the logic, which may be used as - nodes representing conditions to be used as constraints - nodes representing functions to be equivalence checked - nodes representing functions needed by the user at the end of SAT sweeping Creating new probe using Gia_SweeperProbeCreate(): int Gia_SweeperProbeCreate( Gia_Man_t * p, int iLit ); Delete existing probe using Gia_SweeperProbeDelete(): int Gia_SweeperProbeDelete( Gia_Man_t * p, int ProbeId ); Update existing probe using Gia_SweeperProbeUpdate(): int Gia_SweeperProbeUpdate( Gia_Man_t * p, int ProbeId, int iLit ); Comments: - a probe is identified by its 0-based ID, which is returned by above procedures - GIA literal of the probe is returned by int Gia_SweeperProbeLit( Gia_Man_t * p, int ProbeId ) - Adding/removing conditions on the current path by calling Gia_SweeperCondPush() and Gia_SweeperCondPop() extern void Gia_SweeperCondPush( Gia_Man_t * p, int ProbeId ); extern void Gia_SweeperCondPop( Gia_Man_t * p ); - Performing equivalence checking by calling int Gia_SweeperCheckEquiv( Gia_Man_t * pGia, int Probe1, int Probe2 ) (resource limits, such as the number of conflicts, will be controllable by dedicated GIA APIs) - The resulting AIG to be returned to the user by calling Gia_SweeperExtractUserLogic() Gia_Man_t * Gia_SweeperExtractUserLogic( Gia_Man_t * p, Vec_Int_t * vProbeIds, Vec_Ptr_t * vOutNames ) */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Swp_Man_t_ Swp_Man_t; struct Swp_Man_t_ { Gia_Man_t * pGia; // GIA manager under construction int nConfMax; // conflict limit in seconds int nTimeOut; // runtime limit in seconds Vec_Int_t * vProbes; // probes Vec_Int_t * vCondProbes; // conditions as probes Vec_Int_t * vCondAssump; // conditions as SAT solver literals // equivalence checking sat_solver * pSat; // SAT solver Vec_Int_t * vId2Lit; // mapping of Obj IDs into SAT literal Vec_Int_t * vFront; // temporary frontier Vec_Int_t * vFanins; // temporary fanins Vec_Int_t * vCexSwp; // sweeper counter-example Vec_Int_t * vCexUser; // user-visible counter-example int nSatVars; // counter of SAT variables // statistics int nSatCalls; int nSatCallsSat; int nSatCallsUnsat; int nSatCallsUndec; int nSatProofs; abctime timeStart; abctime timeTotal; abctime timeCnf; abctime timeSat; abctime timeSatSat; abctime timeSatUnsat; abctime timeSatUndec; }; static inline int Swp_ManObj2Lit( Swp_Man_t * p, int Id ) { return Vec_IntGetEntry( p->vId2Lit, Id ); } static inline int Swp_ManLit2Lit( Swp_Man_t * p, int Lit ) { assert( Vec_IntEntry(p->vId2Lit, Abc_Lit2Var(Lit)) ); return Abc_Lit2LitL( Vec_IntArray(p->vId2Lit), Lit ); } static inline void Swp_ManSetObj2Lit( Swp_Man_t * p, int Id, int Lit ) { assert( Lit > 0 ); Vec_IntSetEntry( p->vId2Lit, Id, Lit ); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creating/deleting the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Swp_Man_t * Swp_ManStart( Gia_Man_t * pGia ) { Swp_Man_t * p; int Lit; assert( Vec_IntSize(&pGia->vHTable) ); pGia->pData = p = ABC_CALLOC( Swp_Man_t, 1 ); p->pGia = pGia; p->nConfMax = 1000; p->vProbes = Vec_IntAlloc( 100 ); p->vCondProbes = Vec_IntAlloc( 100 ); p->vCondAssump = Vec_IntAlloc( 100 ); p->vId2Lit = Vec_IntAlloc( 10000 ); p->vFront = Vec_IntAlloc( 100 ); p->vFanins = Vec_IntAlloc( 100 ); p->vCexSwp = Vec_IntAlloc( 100 ); p->pSat = sat_solver_new(); p->nSatVars = 1; sat_solver_setnvars( p->pSat, 1000 ); Swp_ManSetObj2Lit( p, 0, (Lit = Abc_Var2Lit(p->nSatVars++, 0)) ); Lit = Abc_LitNot(Lit); sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); p->timeStart = Abc_Clock(); return p; } static inline void Swp_ManStop( Gia_Man_t * pGia ) { Swp_Man_t * p = (Swp_Man_t *)pGia->pData; sat_solver_delete( p->pSat ); Vec_IntFree( p->vFanins ); Vec_IntFree( p->vCexSwp ); Vec_IntFree( p->vId2Lit ); Vec_IntFree( p->vFront ); Vec_IntFree( p->vProbes ); Vec_IntFree( p->vCondProbes ); Vec_IntFree( p->vCondAssump ); ABC_FREE( p ); pGia->pData = NULL; } Gia_Man_t * Gia_SweeperStart( Gia_Man_t * pGia ) { if ( pGia == NULL ) pGia = Gia_ManStart( 10000 ); if ( Vec_IntSize(&pGia->vHTable) == 0 ) Gia_ManHashStart( pGia ); // recompute fPhase and fMark1 to mark multiple fanout nodes if AIG is already defined!!! Swp_ManStart( pGia ); pGia->fSweeper = 1; return pGia; } void Gia_SweeperStop( Gia_Man_t * pGia ) { pGia->fSweeper = 0; Swp_ManStop( pGia ); Gia_ManHashStop( pGia ); // Gia_ManStop( pGia ); } int Gia_SweeperIsRunning( Gia_Man_t * pGia ) { return (pGia->pData != NULL); } double Gia_SweeperMemUsage( Gia_Man_t * pGia ) { Swp_Man_t * p = (Swp_Man_t *)pGia->pData; double nMem = sizeof(Swp_Man_t); nMem += Vec_IntCap(p->vProbes); nMem += Vec_IntCap(p->vCondProbes); nMem += Vec_IntCap(p->vCondAssump); nMem += Vec_IntCap(p->vId2Lit); nMem += Vec_IntCap(p->vFront); nMem += Vec_IntCap(p->vFanins); nMem += Vec_IntCap(p->vCexSwp); return 4.0 * nMem; } void Gia_SweeperPrintStats( Gia_Man_t * pGia ) { Swp_Man_t * p = (Swp_Man_t *)pGia->pData; double nMemSwp = Gia_SweeperMemUsage(pGia); double nMemGia = (double)Gia_ManObjNum(pGia)*(sizeof(Gia_Obj_t) + sizeof(int)); double nMemSat = sat_solver_memory(p->pSat); double nMemTot = nMemSwp + nMemGia + nMemSat; printf( "SAT sweeper statistics:\n" ); printf( "Memory usage:\n" ); ABC_PRMP( "Sweeper ", nMemSwp, nMemTot ); ABC_PRMP( "AIG manager ", nMemGia, nMemTot ); ABC_PRMP( "SAT solver ", nMemSat, nMemTot ); ABC_PRMP( "TOTAL ", nMemTot, nMemTot ); printf( "Runtime usage:\n" ); p->timeTotal = Abc_Clock() - p->timeStart; ABC_PRTP( "CNF construction", p->timeCnf, p->timeTotal ); ABC_PRTP( "SAT solving ", p->timeSat, p->timeTotal ); ABC_PRTP( " Sat ", p->timeSatSat, p->timeTotal ); ABC_PRTP( " Unsat ", p->timeSatUnsat, p->timeTotal ); ABC_PRTP( " Undecided ", p->timeSatUndec, p->timeTotal ); ABC_PRTP( "TOTAL RUNTIME ", p->timeTotal, p->timeTotal ); printf( "GIA: " ); Gia_ManPrintStats( pGia, NULL ); printf( "SAT calls = %d. Sat = %d. Unsat = %d. Undecided = %d. Proofs = %d.\n", p->nSatCalls, p->nSatCallsSat, p->nSatCallsUnsat, p->nSatCallsUndec, p->nSatProofs ); Sat_SolverPrintStats( stdout, p->pSat ); } /**Function************************************************************* Synopsis [Setting resource limits.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_SweeperSetConflictLimit( Gia_Man_t * p, int nConfMax ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; pSwp->nConfMax = nConfMax; } void Gia_SweeperSetRuntimeLimit( Gia_Man_t * p, int nSeconds ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; pSwp->nTimeOut = nSeconds; } Vec_Int_t * Gia_SweeperGetCex( Gia_Man_t * p ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; assert( pSwp->vCexUser == NULL || Vec_IntSize(pSwp->vCexUser) == Gia_ManPiNum(p) ); return pSwp->vCexUser; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ // create new probe int Gia_SweeperProbeCreate( Gia_Man_t * p, int iLit ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; int ProbeId = Vec_IntSize(pSwp->vProbes); assert( iLit >= 0 ); Vec_IntPush( pSwp->vProbes, iLit ); return ProbeId; } // delete existing probe int Gia_SweeperProbeDelete( Gia_Man_t * p, int ProbeId ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; int iLit = Vec_IntEntry(pSwp->vProbes, ProbeId); assert( iLit >= 0 ); Vec_IntWriteEntry(pSwp->vProbes, ProbeId, -1); return iLit; } // update existing probe int Gia_SweeperProbeUpdate( Gia_Man_t * p, int ProbeId, int iLitNew ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; int iLit = Vec_IntEntry(pSwp->vProbes, ProbeId); assert( iLit >= 0 ); Vec_IntWriteEntry(pSwp->vProbes, ProbeId, iLitNew); return iLit; } // returns literal associated with the probe int Gia_SweeperProbeLit( Gia_Man_t * p, int ProbeId ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; int iLit = Vec_IntEntry(pSwp->vProbes, ProbeId); assert( iLit >= 0 ); return iLit; } /**Function************************************************************* Synopsis [This procedure returns indexes of all currently defined valid probes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_SweeperCollectValidProbeIds( Gia_Man_t * p ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; Vec_Int_t * vProbeIds = Vec_IntAlloc( 1000 ); int iLit, ProbeId; Vec_IntForEachEntry( pSwp->vProbes, iLit, ProbeId ) { if ( iLit < 0 ) continue; Vec_IntPush( vProbeIds, ProbeId ); } return vProbeIds; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_SweeperCondPush( Gia_Man_t * p, int ProbeId ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; Vec_IntPush( pSwp->vCondProbes, ProbeId ); } int Gia_SweeperCondPop( Gia_Man_t * p ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; return Vec_IntPop( pSwp->vCondProbes ); } Vec_Int_t * Gia_SweeperCondVector( Gia_Man_t * p ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; return pSwp->vCondProbes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Gia_ManExtract_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjIds ) { if ( !Gia_ObjIsAnd(pObj) ) return; if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); Gia_ManExtract_rec( p, Gia_ObjFanin0(pObj), vObjIds ); Gia_ManExtract_rec( p, Gia_ObjFanin1(pObj), vObjIds ); Vec_IntPush( vObjIds, Gia_ObjId(p, pObj) ); } Gia_Man_t * Gia_SweeperExtractUserLogic( Gia_Man_t * p, Vec_Int_t * vProbeIds, Vec_Ptr_t * vInNames, Vec_Ptr_t * vOutNames ) { Vec_Int_t * vObjIds, * vValues; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, ProbeId; assert( vInNames == NULL || Gia_ManPiNum(p) == Vec_PtrSize(vInNames) ); assert( vOutNames == NULL || Vec_IntSize(vProbeIds) == Vec_PtrSize(vOutNames) ); // create new Gia_ManIncrementTravId( p ); vObjIds = Vec_IntAlloc( 1000 ); Vec_IntForEachEntry( vProbeIds, ProbeId, i ) { pObj = Gia_Lit2Obj( p, Gia_SweeperProbeLit(p, ProbeId) ); Gia_ManExtract_rec( p, Gia_Regular(pObj), vObjIds ); } // create new manager pNew = Gia_ManStart( 1 + Gia_ManPiNum(p) + Vec_IntSize(vObjIds) + Vec_IntSize(vProbeIds) + 100 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); // create internal nodes Gia_ManHashStart( pNew ); vValues = Vec_IntAlloc( Vec_IntSize(vObjIds) ); Gia_ManForEachObjVec( vObjIds, p, pObj, i ) { Vec_IntPush( vValues, pObj->Value ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } Gia_ManHashStop( pNew ); // create outputs Vec_IntForEachEntry( vProbeIds, ProbeId, i ) { pObj = Gia_Lit2Obj( p, Gia_SweeperProbeLit(p, ProbeId) ); Gia_ManAppendCo( pNew, Gia_Regular(pObj)->Value ^ Gia_IsComplement(pObj) ); } // return the values back Gia_ManForEachPi( p, pObj, i ) pObj->Value = 0; Gia_ManForEachObjVec( vObjIds, p, pObj, i ) pObj->Value = Vec_IntEntry( vValues, i ); Vec_IntFree( vObjIds ); Vec_IntFree( vValues ); // duplicate if needed if ( Gia_ManHasDangling(pNew) ) { pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); } // copy names if present if ( vInNames ) pNew->vNamesIn = Vec_PtrDupStr( vInNames ); if ( vOutNames ) pNew->vNamesOut = Vec_PtrDupStr( vOutNames ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_SweeperLogicDump( Gia_Man_t * p, Vec_Int_t * vProbeIds, int fDumpConds, char * pFileName ) { Gia_Man_t * pGiaOuts = Gia_SweeperExtractUserLogic( p, vProbeIds, NULL, NULL ); Vec_Int_t * vProbeConds = Gia_SweeperCondVector( p ); printf( "Dumping logic cones" ); if ( fDumpConds && Vec_IntSize(vProbeConds) > 0 ) { Gia_Man_t * pGiaCond = Gia_SweeperExtractUserLogic( p, vProbeConds, NULL, NULL ); Gia_ManDupAppendShare( pGiaOuts, pGiaCond ); pGiaOuts->nConstrs = Gia_ManPoNum(pGiaCond); Gia_ManHashStop( pGiaOuts ); Gia_ManStop( pGiaCond ); printf( " and conditions" ); } Gia_AigerWrite( pGiaOuts, pFileName, 0, 0, 0 ); Gia_ManStop( pGiaOuts ); printf( " into file \"%s\".\n", pFileName ); } /**Function************************************************************* Synopsis [Sweeper cleanup.] Description [Returns new GIA with sweeper defined, which is the same as the original sweeper, with all the dangling logic removed and SAT solver restarted. The probe IDs are guaranteed to have the same logic functions as in the original manager.] SideEffects [The input manager is deleted inside this procedure.] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_SweeperCleanup( Gia_Man_t * p, char * pCommLime ) { Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; Vec_Int_t * vObjIds; Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iLit, ProbeId; // collect all internal nodes pointed to by currently-used probes Gia_ManIncrementTravId( p ); vObjIds = Vec_IntAlloc( 1000 ); Vec_IntForEachEntry( pSwp->vProbes, iLit, ProbeId ) { if ( iLit < 0 ) continue; pObj = Gia_Lit2Obj( p, iLit ); Gia_ManExtract_rec( p, Gia_Regular(pObj), vObjIds ); } // create new manager pNew = Gia_ManStart( 1 + Gia_ManPiNum(p) + Vec_IntSize(vObjIds) + 100 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachPi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); // create internal nodes Gia_ManHashStart( pNew ); Gia_ManForEachObjVec( vObjIds, p, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); Gia_ManHashStop( pNew ); // create outputs Vec_IntForEachEntry( pSwp->vProbes, iLit, ProbeId ) { if ( iLit < 0 ) continue; pObj = Gia_Lit2Obj( p, iLit ); iLit = Gia_Regular(pObj)->Value ^ Gia_IsComplement(pObj); Vec_IntWriteEntry( pSwp->vProbes, ProbeId, iLit ); } Vec_IntFree( vObjIds ); // duplicate if needed if ( Gia_ManHasDangling(pNew) ) { pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); } // execute command line if ( pCommLime ) { // set pNew to be current GIA in ABC Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew ); // execute command line pCommLine using Abc_CmdCommandExecute() Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), pCommLime ); // get pNew to be current GIA in ABC pNew = Abc_FrameGetGia( Abc_FrameGetGlobalFrame() ); } // restart the SAT solver Vec_IntClear( pSwp->vId2Lit ); sat_solver_delete( pSwp->pSat ); pSwp->pSat = sat_solver_new(); pSwp->nSatVars = 1; sat_solver_setnvars( pSwp->pSat, 1000 ); Swp_ManSetObj2Lit( pSwp, 0, (iLit = Abc_Var2Lit(pSwp->nSatVars++, 0)) ); iLit = Abc_LitNot(iLit); sat_solver_addclause( pSwp->pSat, &iLit, &iLit + 1 ); pSwp->timeStart = Abc_Clock(); // return the result pNew->pData = p->pData; p->pData = NULL; Gia_ManStop( p ); return pNew; } /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Gia_ManAddClausesMux( Swp_Man_t * p, Gia_Obj_t * pNode ) { Gia_Obj_t * pNodeI, * pNodeT, * pNodeE; int pLits[4], LitF, LitI, LitT, LitE, RetValue; assert( !Gia_IsComplement( pNode ) ); assert( Gia_ObjIsMuxType( pNode ) ); // get nodes (I = if, T = then, E = else) pNodeI = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); // get the Litiable numbers LitF = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNode) ); LitI = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNodeI) ); LitT = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNodeT) ); LitE = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNodeE) ); // f = ITE(i, t, e) // i' + t' + f // i' + t + f' // i + e' + f // i + e + f' // create four clauses pLits[0] = Abc_LitNotCond(LitI, 1); pLits[1] = Abc_LitNotCond(LitT, 1); pLits[2] = Abc_LitNotCond(LitF, 0); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = Abc_LitNotCond(LitI, 1); pLits[1] = Abc_LitNotCond(LitT, 0); pLits[2] = Abc_LitNotCond(LitF, 1); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = Abc_LitNotCond(LitI, 0); pLits[1] = Abc_LitNotCond(LitE, 1); pLits[2] = Abc_LitNotCond(LitF, 0); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = Abc_LitNotCond(LitI, 0); pLits[1] = Abc_LitNotCond(LitE, 0); pLits[2] = Abc_LitNotCond(LitF, 1); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); // two additional clauses // t' & e' -> f' // t & e -> f // t + e + f' // t' + e' + f if ( LitT == LitE ) { // assert( fCompT == !fCompE ); return; } pLits[0] = Abc_LitNotCond(LitT, 0); pLits[1] = Abc_LitNotCond(LitE, 0); pLits[2] = Abc_LitNotCond(LitF, 1); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = Abc_LitNotCond(LitT, 1); pLits[1] = Abc_LitNotCond(LitE, 1); pLits[2] = Abc_LitNotCond(LitF, 0); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); } /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Gia_ManAddClausesSuper( Swp_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSuper ) { int i, RetValue, Lit, LitNode, pLits[2]; assert( !Gia_IsComplement(pNode) ); assert( Gia_ObjIsAnd( pNode ) ); // suppose AND-gate is A & B = C // add !A => !C or A + !C // add !B => !C or B + !C LitNode = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNode) ); Vec_IntForEachEntry( vSuper, Lit, i ) { pLits[0] = Swp_ManLit2Lit( p, Lit ); pLits[1] = Abc_LitNot( LitNode ); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( RetValue ); // update literals Vec_IntWriteEntry( vSuper, i, Abc_LitNot(pLits[0]) ); } // add A & B => C or !A + !B + C Vec_IntPush( vSuper, LitNode ); RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vSuper), Vec_IntArray(vSuper) + Vec_IntSize(vSuper) ); assert( RetValue ); (void) RetValue; } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Gia_ManCollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) { // stop at complements, shared, PIs, and MUXes if ( Gia_IsComplement(pObj) || pObj->fMark1 || Gia_ObjIsCi(pObj) || Gia_ObjIsMuxType(pObj) ) { Vec_IntPushUnique( vSuper, Gia_Obj2Lit(p, pObj) ); return; } Gia_ManCollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper ); Gia_ManCollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper ); } static void Gia_ManCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) { assert( !Gia_IsComplement(pObj) ); assert( Gia_ObjIsAnd(pObj) ); Vec_IntClear( vSuper ); Gia_ManCollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper ); Gia_ManCollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper ); } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Gia_ManObjAddToFrontier( Swp_Man_t * p, int Id, Vec_Int_t * vFront ) { Gia_Obj_t * pObj; if ( Id == 0 || Swp_ManObj2Lit(p, Id) ) return; pObj = Gia_ManObj( p->pGia, Id ); Swp_ManSetObj2Lit( p, Id, Abc_Var2Lit(p->nSatVars++, pObj->fPhase) ); sat_solver_setnvars( p->pSat, p->nSatVars + 100 ); if ( Gia_ObjIsAnd(pObj) ) Vec_IntPush( vFront, Id ); } static void Gia_ManCnfNodeAddToSolver( Swp_Man_t * p, int NodeId ) { Gia_Obj_t * pNode; int i, k, Id, Lit; abctime clk; // quit if CNF is ready if ( NodeId == 0 || Swp_ManObj2Lit(p, NodeId) ) return; clk = Abc_Clock(); // start the frontier Vec_IntClear( p->vFront ); Gia_ManObjAddToFrontier( p, NodeId, p->vFront ); // explore nodes in the frontier Gia_ManForEachObjVec( p->vFront, p->pGia, pNode, i ) { // create the supergate assert( Swp_ManObj2Lit(p, Gia_ObjId(p->pGia, pNode)) ); if ( Gia_ObjIsMuxType(pNode) ) { Vec_IntClear( p->vFanins ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId0p( p->pGia, Gia_ObjFanin0(pNode) ) ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId0p( p->pGia, Gia_ObjFanin1(pNode) ) ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId1p( p->pGia, Gia_ObjFanin0(pNode) ) ); Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId1p( p->pGia, Gia_ObjFanin1(pNode) ) ); Vec_IntForEachEntry( p->vFanins, Id, k ) Gia_ManObjAddToFrontier( p, Id, p->vFront ); Gia_ManAddClausesMux( p, pNode ); } else { Gia_ManCollectSuper( p->pGia, pNode, p->vFanins ); Vec_IntForEachEntry( p->vFanins, Lit, k ) Gia_ManObjAddToFrontier( p, Abc_Lit2Var(Lit), p->vFront ); Gia_ManAddClausesSuper( p, pNode, p->vFanins ); } assert( Vec_IntSize(p->vFanins) > 1 ); } p->timeCnf += Abc_Clock() - clk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Vec_Int_t * Gia_ManGetCex( Gia_Man_t * pGia, Vec_Int_t * vId2Lit, sat_solver * pSat, Vec_Int_t * vCex ) { Gia_Obj_t * pObj; int i, LitSat, Value; Vec_IntClear( vCex ); Gia_ManForEachPi( pGia, pObj, i ) { if ( Gia_ObjId(pGia, pObj) >= Vec_IntSize(vId2Lit) ) { Vec_IntPush( vCex, 2 ); continue; } LitSat = Vec_IntEntry( vId2Lit, Gia_ObjId(pGia, pObj) ); if ( LitSat == 0 ) { Vec_IntPush( vCex, 2 ); continue; } assert( LitSat > 0 ); Value = sat_solver_var_value(pSat, Abc_Lit2Var(LitSat)) ^ Abc_LitIsCompl(LitSat); Vec_IntPush( vCex, Value ); } return vCex; } /**Function************************************************************* Synopsis [Runs equivalence test for probes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_SweeperCheckEquiv( Gia_Man_t * pGia, int Probe1, int Probe2 ) { Swp_Man_t * p = (Swp_Man_t *)pGia->pData; int iLitOld, iLitNew, iLitAig, pLitsSat[2], RetValue, RetValue1, ProbeId, i; abctime clk; p->nSatCalls++; assert( p->pSat != NULL ); p->vCexUser = NULL; // get the literals iLitOld = Gia_SweeperProbeLit( pGia, Probe1 ); iLitNew = Gia_SweeperProbeLit( pGia, Probe2 ); // if the literals are identical, the probes are equivalent if ( iLitOld == iLitNew ) return 1; // if the literals are opposites, the probes are not equivalent if ( Abc_LitRegular(iLitOld) == Abc_LitRegular(iLitNew) ) { Vec_IntFill( p->vCexSwp, Gia_ManPiNum(pGia), 2 ); p->vCexUser = p->vCexSwp; return 0; } // order the literals if ( iLitOld < iLitNew ) ABC_SWAP( int, iLitOld, iLitNew ); assert( iLitOld > iLitNew ); // create logic cones and the array of assumptions Vec_IntClear( p->vCondAssump ); Vec_IntForEachEntry( p->vCondProbes, ProbeId, i ) { iLitAig = Gia_SweeperProbeLit( pGia, ProbeId ); Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitAig) ); Vec_IntPush( p->vCondAssump, Abc_LitNot(Swp_ManLit2Lit(p, iLitAig)) ); } Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitOld) ); Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitNew) ); sat_solver_compress( p->pSat ); // set the SAT literals pLitsSat[0] = Swp_ManLit2Lit( p, iLitOld ); pLitsSat[1] = Swp_ManLit2Lit( p, iLitNew ); // solve under assumptions // A = 1; B = 0 OR A = 1; B = 1 Vec_IntPush( p->vCondAssump, pLitsSat[0] ); Vec_IntPush( p->vCondAssump, Abc_LitNot(pLitsSat[1]) ); // set runtime limit for this call if ( p->nTimeOut ) sat_solver_set_runtime_limit( p->pSat, p->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() ); clk = Abc_Clock(); RetValue1 = sat_solver_solve( p->pSat, Vec_IntArray(p->vCondAssump), Vec_IntArray(p->vCondAssump) + Vec_IntSize(p->vCondAssump), (ABC_INT64_T)p->nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); Vec_IntShrink( p->vCondAssump, Vec_IntSize(p->vCondAssump) - 2 ); p->timeSat += Abc_Clock() - clk; if ( RetValue1 == l_False ) { pLitsSat[0] = Abc_LitNot( pLitsSat[0] ); RetValue = sat_solver_addclause( p->pSat, pLitsSat, pLitsSat + 2 ); assert( RetValue ); pLitsSat[0] = Abc_LitNot( pLitsSat[0] ); p->timeSatUnsat += Abc_Clock() - clk; p->nSatCallsUnsat++; } else if ( RetValue1 == l_True ) { p->vCexUser = Gia_ManGetCex( p->pGia, p->vId2Lit, p->pSat, p->vCexSwp ); p->timeSatSat += Abc_Clock() - clk; p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; p->nSatCallsUndec++; return -1; } // if the old node was constant 0, we already know the answer if ( Gia_ManIsConstLit(iLitNew) ) { p->nSatProofs++; return 1; } // solve under assumptions // A = 0; B = 1 OR A = 0; B = 0 Vec_IntPush( p->vCondAssump, Abc_LitNot(pLitsSat[0]) ); Vec_IntPush( p->vCondAssump, pLitsSat[1] ); clk = Abc_Clock(); RetValue1 = sat_solver_solve( p->pSat, Vec_IntArray(p->vCondAssump), Vec_IntArray(p->vCondAssump) + Vec_IntSize(p->vCondAssump), (ABC_INT64_T)p->nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); Vec_IntShrink( p->vCondAssump, Vec_IntSize(p->vCondAssump) - 2 ); p->timeSat += Abc_Clock() - clk; if ( RetValue1 == l_False ) { pLitsSat[1] = Abc_LitNot( pLitsSat[1] ); RetValue = sat_solver_addclause( p->pSat, pLitsSat, pLitsSat + 2 ); assert( RetValue ); pLitsSat[1] = Abc_LitNot( pLitsSat[1] ); p->timeSatUnsat += Abc_Clock() - clk; p->nSatCallsUnsat++; } else if ( RetValue1 == l_True ) { p->vCexUser = Gia_ManGetCex( p->pGia, p->vId2Lit, p->pSat, p->vCexSwp ); p->timeSatSat += Abc_Clock() - clk; p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; p->nSatCallsUndec++; return -1; } // return SAT proof p->nSatProofs++; return 1; } /**Function************************************************************* Synopsis [Returns 1 if the set of conditions is UNSAT (0 if SAT; -1 if undecided).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_SweeperCondCheckUnsat( Gia_Man_t * pGia ) { Swp_Man_t * p = (Swp_Man_t *)pGia->pData; int RetValue, ProbeId, iLitAig, i; abctime clk; assert( p->pSat != NULL ); p->nSatCalls++; p->vCexUser = NULL; // create logic cones and the array of assumptions Vec_IntClear( p->vCondAssump ); Vec_IntForEachEntry( p->vCondProbes, ProbeId, i ) { iLitAig = Gia_SweeperProbeLit( pGia, ProbeId ); Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitAig) ); Vec_IntPush( p->vCondAssump, Abc_LitNot(Swp_ManLit2Lit(p, iLitAig)) ); } sat_solver_compress( p->pSat ); // set runtime limit for this call if ( p->nTimeOut ) sat_solver_set_runtime_limit( p->pSat, p->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() ); clk = Abc_Clock(); RetValue = sat_solver_solve( p->pSat, Vec_IntArray(p->vCondAssump), Vec_IntArray(p->vCondAssump) + Vec_IntSize(p->vCondAssump), (ABC_INT64_T)p->nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); p->timeSat += Abc_Clock() - clk; if ( RetValue == l_False ) { assert( Vec_IntSize(p->vCondProbes) > 0 ); p->timeSatUnsat += Abc_Clock() - clk; p->nSatCallsUnsat++; p->nSatProofs++; return 1; } else if ( RetValue == l_True ) { p->vCexUser = Gia_ManGetCex( p->pGia, p->vId2Lit, p->pSat, p->vCexSwp ); p->timeSatSat += Abc_Clock() - clk; p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatUndec += Abc_Clock() - clk; p->nSatCallsUndec++; return -1; } } /**Function************************************************************* Synopsis [Performs grafting from another manager.] Description [Returns the array of resulting literals in the destination manager.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_SweeperGraft( Gia_Man_t * pDst, Vec_Int_t * vProbes, Gia_Man_t * pSrc ) { Vec_Int_t * vOutLits; Gia_Obj_t * pObj; int i; assert( Gia_SweeperIsRunning(pDst) ); if ( vProbes ) assert( Vec_IntSize(vProbes) == Gia_ManPiNum(pSrc) ); else assert( Gia_ManPiNum(pDst) == Gia_ManPiNum(pSrc) ); Gia_ManForEachPi( pSrc, pObj, i ) pObj->Value = vProbes ? Gia_SweeperProbeLit(pDst, Vec_IntEntry(vProbes, i)) : Gia_Obj2Lit(pDst,Gia_ManPi(pDst, i)); Gia_ManForEachAnd( pSrc, pObj, i ) pObj->Value = Gia_ManHashAnd( pDst, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); vOutLits = Vec_IntAlloc( Gia_ManPoNum(pSrc) ); Gia_ManForEachPo( pSrc, pObj, i ) Vec_IntPush( vOutLits, Gia_ObjFanin0Copy(pObj) ); return vOutLits; } /**Function************************************************************* Synopsis [Performs conditional sweeping of the cone.] Description [Returns the result as a new GIA manager with as many inputs as the original manager and as many outputs as there are logic cones.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_SweeperSweep( Gia_Man_t * p, Vec_Int_t * vProbeOuts, int nWords, int nConfs, int fVerify, int fVerbose ) { Vec_Int_t * vProbeConds; Gia_Man_t * pGiaCond, * pGiaOuts, * pGiaRes; Ssc_Pars_t Pars, * pPars = &Pars; Ssc_ManSetDefaultParams( pPars ); pPars->nWords = nWords; pPars->nBTLimit = nConfs; pPars->fVerify = fVerify; pPars->fVerbose = fVerbose; // sweeper is running assert( Gia_SweeperIsRunning(p) ); // extract conditions and logic cones vProbeConds = Gia_SweeperCondVector( p ); pGiaCond = Gia_SweeperExtractUserLogic( p, vProbeConds, NULL, NULL ); pGiaOuts = Gia_SweeperExtractUserLogic( p, vProbeOuts, NULL, NULL ); Gia_ManSetPhase( pGiaOuts ); // if there is no conditions, define constant true constraint (constant 0 output) if ( Gia_ManPoNum(pGiaCond) == 0 ) Gia_ManAppendCo( pGiaCond, Gia_ManConst0Lit() ); // perform sweeping under constraints pGiaRes = Ssc_PerformSweeping( pGiaOuts, pGiaCond, pPars ); Gia_ManStop( pGiaCond ); Gia_ManStop( pGiaOuts ); return pGiaRes; } /**Function************************************************************* Synopsis [Procedure to perform conditional fraig sweeping on separate logic cones.] Description [The procedure takes GIA with the sweeper defined. The sweeper is assumed to have some conditions currently pushed, which will be used as constraints for fraig sweeping. The second argument (vProbes) contains the array of probe IDs pointing to the user's logic cones to be SAT swept. Finally, the optional command line (pCommLine) is an ABC command line to be applied to the resulting GIA after SAT sweeping before it is grafted back into the original GIA manager. The return value is the status (success/failure) and the array of original probes possibly pointing to the new literals in the original GIA manager, corresponding to the user's logic cones after sweeping, synthesis and grafting.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_SweeperFraig( Gia_Man_t * p, Vec_Int_t * vProbeIds, char * pCommLime, int nWords, int nConfs, int fVerify, int fVerbose ) { Gia_Man_t * pNew; Vec_Int_t * vLits; int ProbeId, i; // sweeper is running assert( Gia_SweeperIsRunning(p) ); // sweep the logic pNew = Gia_SweeperSweep( p, vProbeIds, nWords, nConfs, fVerify, fVerbose ); if ( pNew == NULL ) return 0; // execute command line if ( pCommLime ) { // set pNew to be current GIA in ABC Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew ); // execute command line pCommLine using Abc_CmdCommandExecute() Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), pCommLime ); // get pNew to be current GIA in ABC pNew = Abc_FrameGetGia( Abc_FrameGetGlobalFrame() ); } // return logic back into the main manager vLits = Gia_SweeperGraft( p, NULL, pNew ); Gia_ManStop( pNew ); // update the array of probes Vec_IntForEachEntry( vProbeIds, ProbeId, i ) Gia_SweeperProbeUpdate( p, ProbeId, Vec_IntEntry(vLits, i) ); Vec_IntFree( vLits ); return 1; } /**Function************************************************************* Synopsis [Executes given command line for the logic defined by the probes.] Description [ ] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_SweeperRun( Gia_Man_t * p, Vec_Int_t * vProbeIds, char * pCommLime, int fVerbose ) { Gia_Man_t * pNew; Vec_Int_t * vLits; int ProbeId, i; // sweeper is running assert( Gia_SweeperIsRunning(p) ); // sweep the logic pNew = Gia_SweeperExtractUserLogic( p, vProbeIds, NULL, NULL ); // execute command line if ( pCommLime ) { if ( fVerbose ) printf( "GIA manager statistics before and after applying \"%s\":\n", pCommLime ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); // set pNew to be current GIA in ABC Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew ); // execute command line pCommLine using Abc_CmdCommandExecute() Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), pCommLime ); // get pNew to be current GIA in ABC pNew = Abc_FrameGetGia( Abc_FrameGetGlobalFrame() ); if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); } // return logic back into the main manager vLits = Gia_SweeperGraft( p, NULL, pNew ); Gia_ManStop( pNew ); // update the array of probes Vec_IntForEachEntry( vProbeIds, ProbeId, i ) Gia_SweeperProbeUpdate( p, ProbeId, Vec_IntEntry(vLits, i) ); Vec_IntFree( vLits ); return 1; } /**Function************************************************************* Synopsis [Sweeper sweeper test.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_SweeperFraigTest( Gia_Man_t * pInit, int nWords, int nConfs, int fVerbose ) { Gia_Man_t * p, * pGia; Gia_Obj_t * pObj; Vec_Int_t * vOuts; int i; // add one-hotness constraints p = Gia_ManDupOneHot( pInit ); // create sweeper Gia_SweeperStart( p ); // collect outputs and create conditions vOuts = Vec_IntAlloc( Gia_ManPoNum(p) ); Gia_ManForEachPo( p, pObj, i ) if ( i < Gia_ManPoNum(p) - p->nConstrs ) // this is the user's output Vec_IntPush( vOuts, Gia_SweeperProbeCreate( p, Gia_ObjFaninLit0p(p, pObj) ) ); else // this is a constraint Gia_SweeperCondPush( p, Gia_SweeperProbeCreate( p, Gia_ObjFaninLit0p(p, pObj) ) ); // perform the sweeping pGia = Gia_SweeperSweep( p, vOuts, nWords, nConfs, fVerbose, 0 ); // pGia = Gia_ManDup( p ); Vec_IntFree( vOuts ); // sop the sweeper Gia_SweeperStop( p ); Gia_ManStop( p ); return pGia; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaSwitch.c000066400000000000000000000653661477524141600163750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaSwitch.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Computing switching activity.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "giaAig.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // switching estimation parameters typedef struct Gia_ParSwi_t_ Gia_ParSwi_t; struct Gia_ParSwi_t_ { // user-controlled parameters int nWords; // the number of machine words int nIters; // the number of timeframes int nPref; // the number of first timeframes to skip int nRandPiFactor; // PI trans prob (-1=3/8; 0=1/2; 1=1/4; 2=1/8, etc) int fProbOne; // collect probability of one int fProbTrans; // collect probatility of Swiing int fVerbose; // enables verbose output }; typedef struct Gia_ManSwi_t_ Gia_ManSwi_t; struct Gia_ManSwi_t_ { Gia_Man_t * pAig; Gia_ParSwi_t * pPars; int nWords; // simulation information unsigned * pDataSim; // simulation data unsigned * pDataSimCis; // simulation data for CIs unsigned * pDataSimCos; // simulation data for COs int * pData1; // switching data }; static inline unsigned * Gia_SwiData( Gia_ManSwi_t * p, int i ) { return p->pDataSim + i * p->nWords; } static inline unsigned * Gia_SwiDataCi( Gia_ManSwi_t * p, int i ) { return p->pDataSimCis + i * p->nWords; } static inline unsigned * Gia_SwiDataCo( Gia_ManSwi_t * p, int i ) { return p->pDataSimCos + i * p->nWords; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [This procedure sets default parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSetDefaultParamsSwi( Gia_ParSwi_t * p ) { memset( p, 0, sizeof(Gia_ParSwi_t) ); p->nWords = 10; // the number of machine words of simulatation data p->nIters = 48; // the number of all timeframes to simulate p->nPref = 16; // the number of first timeframes to skip when computing switching p->nRandPiFactor = 0; // primary input transition probability (-1=3/8; 0=1/2; 1=1/4; 2=1/8, etc) p->fProbOne = 0; // compute probability of signal being one (if 0, compute probability of switching) p->fProbTrans = 1; // compute signal transition probability (if 0, compute transition probability using probability of being one) p->fVerbose = 0; // enables verbose output } /**Function************************************************************* Synopsis [Creates fast simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_ManSwi_t * Gia_ManSwiCreate( Gia_Man_t * pAig, Gia_ParSwi_t * pPars ) { Gia_ManSwi_t * p; p = ABC_ALLOC( Gia_ManSwi_t, 1 ); memset( p, 0, sizeof(Gia_ManSwi_t) ); p->pAig = Gia_ManFront( pAig ); p->pPars = pPars; p->nWords = pPars->nWords; p->pDataSim = ABC_ALLOC( unsigned, p->nWords * p->pAig->nFront ); p->pDataSimCis = ABC_ALLOC( unsigned, p->nWords * Gia_ManCiNum(p->pAig) ); p->pDataSimCos = ABC_ALLOC( unsigned, p->nWords * Gia_ManCoNum(p->pAig) ); p->pData1 = ABC_CALLOC( int, Gia_ManObjNum(pAig) ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSwiDelete( Gia_ManSwi_t * p ) { Gia_ManStop( p->pAig ); ABC_FREE( p->pData1 ); ABC_FREE( p->pDataSim ); ABC_FREE( p->pDataSimCis ); ABC_FREE( p->pDataSimCos ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSwiSimInfoRandom( Gia_ManSwi_t * p, unsigned * pInfo, int nProbNum ) { unsigned Mask = 0; int w, i; if ( nProbNum == -1 ) { // 3/8 = 1/4 + 1/8 Mask = (Gia_ManRandom( 0 ) & Gia_ManRandom( 0 )) | (Gia_ManRandom( 0 ) & Gia_ManRandom( 0 ) & Gia_ManRandom( 0 )); for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] ^= Mask; } else if ( nProbNum > 0 ) { Mask = Gia_ManRandom( 0 ); for ( i = 0; i < nProbNum; i++ ) Mask &= Gia_ManRandom( 0 ); for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] ^= Mask; } else if ( nProbNum == 0 ) { for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = Gia_ManRandom( 0 ); } else assert( 0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSwiSimInfoRandomShift( Gia_ManSwi_t * p, unsigned * pInfo, int nProbNum ) { unsigned Mask = 0; int w, i; if ( nProbNum == -1 ) { // 3/8 = 1/4 + 1/8 Mask = (Gia_ManRandom( 0 ) & Gia_ManRandom( 0 )) | (Gia_ManRandom( 0 ) & Gia_ManRandom( 0 ) & Gia_ManRandom( 0 )); } else if ( nProbNum >= 0 ) { Mask = Gia_ManRandom( 0 ); for ( i = 0; i < nProbNum; i++ ) Mask &= Gia_ManRandom( 0 ); } else assert( 0 ); for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = (pInfo[w] << 16) | ((pInfo[w] ^ Mask) & 0xffff); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSwiSimInfoZero( Gia_ManSwi_t * p, unsigned * pInfo ) { int w; for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSwiSimInfoOne( Gia_ManSwi_t * p, unsigned * pInfo ) { int w; for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = ~0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSwiSimInfoCopy( Gia_ManSwi_t * p, unsigned * pInfo, unsigned * pInfo0 ) { int w; for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSwiSimInfoCopyShift( Gia_ManSwi_t * p, unsigned * pInfo, unsigned * pInfo0 ) { int w; for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = (pInfo[w] << 16) | (pInfo0[w] & 0xffff); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSwiSimulateCi( Gia_ManSwi_t * p, Gia_Obj_t * pObj, int iCi ) { unsigned * pInfo = Gia_SwiData( p, Gia_ObjValue(pObj) ); unsigned * pInfo0 = Gia_SwiDataCi( p, iCi ); int w; for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSwiSimulateCo( Gia_ManSwi_t * p, int iCo, Gia_Obj_t * pObj ) { unsigned * pInfo = Gia_SwiDataCo( p, iCo ); unsigned * pInfo0 = Gia_SwiData( p, Gia_ObjDiff0(pObj) ); int w; if ( Gia_ObjFaninC0(pObj) ) for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = ~pInfo0[w]; else for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSwiSimulateNode( Gia_ManSwi_t * p, Gia_Obj_t * pObj ) { unsigned * pInfo = Gia_SwiData( p, Gia_ObjValue(pObj) ); unsigned * pInfo0 = Gia_SwiData( p, Gia_ObjDiff0(pObj) ); unsigned * pInfo1 = Gia_SwiData( p, Gia_ObjDiff1(pObj) ); int w; if ( Gia_ObjFaninC0(pObj) ) { if ( Gia_ObjFaninC1(pObj) ) for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = ~(pInfo0[w] | pInfo1[w]); else for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = ~pInfo0[w] & pInfo1[w]; } else { if ( Gia_ObjFaninC1(pObj) ) for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w] & ~pInfo1[w]; else for ( w = p->nWords-1; w >= 0; w-- ) pInfo[w] = pInfo0[w] & pInfo1[w]; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSwiSimInfoInit( Gia_ManSwi_t * p ) { int i = 0; for ( ; i < Gia_ManPiNum(p->pAig); i++ ) Gia_ManSwiSimInfoRandom( p, Gia_SwiDataCi(p, i), 0 ); for ( ; i < Gia_ManCiNum(p->pAig); i++ ) Gia_ManSwiSimInfoZero( p, Gia_SwiDataCi(p, i) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSwiSimInfoTransfer( Gia_ManSwi_t * p, int nProbNum ) { int i = 0, nShift = Gia_ManPoNum(p->pAig)-Gia_ManPiNum(p->pAig); for ( ; i < Gia_ManPiNum(p->pAig); i++ ) Gia_ManSwiSimInfoRandom( p, Gia_SwiDataCi(p, i), nProbNum ); for ( ; i < Gia_ManCiNum(p->pAig); i++ ) Gia_ManSwiSimInfoCopy( p, Gia_SwiDataCi(p, i), Gia_SwiDataCo(p, nShift+i) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSwiSimInfoTransferShift( Gia_ManSwi_t * p, int nProbNum ) { int i = 0, nShift = Gia_ManPoNum(p->pAig)-Gia_ManPiNum(p->pAig); for ( ; i < Gia_ManPiNum(p->pAig); i++ ) Gia_ManSwiSimInfoRandomShift( p, Gia_SwiDataCi(p, i), nProbNum ); for ( ; i < Gia_ManCiNum(p->pAig); i++ ) Gia_ManSwiSimInfoCopyShift( p, Gia_SwiDataCi(p, i), Gia_SwiDataCo(p, nShift+i) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManSwiSimInfoCountOnes( Gia_ManSwi_t * p, int iPlace ) { unsigned * pInfo; int w, Counter = 0; pInfo = Gia_SwiData( p, iPlace ); for ( w = p->nWords-1; w >= 0; w-- ) Counter += Gia_WordCountOnes( pInfo[w] ); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Gia_ManSwiSimInfoCountTrans( Gia_ManSwi_t * p, int iPlace ) { unsigned * pInfo; int w, Counter = 0; pInfo = Gia_SwiData( p, iPlace ); for ( w = p->nWords-1; w >= 0; w-- ) Counter += 2*Gia_WordCountOnes( (pInfo[w] ^ (pInfo[w] >> 16)) & 0xffff ); return Counter; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManSwiSimulateRound( Gia_ManSwi_t * p, int fCount ) { Gia_Obj_t * pObj; int i;//, iCis = 0, iCos = 0; assert( p->pAig->nFront > 0 ); assert( Gia_ManConst0(p->pAig)->Value == 0 ); Gia_ManSwiSimInfoZero( p, Gia_SwiData(p, 0) ); Gia_ManForEachObj1( p->pAig, pObj, i ) { if ( Gia_ObjIsAndOrConst0(pObj) ) { assert( Gia_ObjValue(pObj) < p->pAig->nFront ); Gia_ManSwiSimulateNode( p, pObj ); } else if ( Gia_ObjIsCo(pObj) ) { assert( Gia_ObjValue(pObj) == GIA_NONE ); // Gia_ManSwiSimulateCo( p, iCos++, pObj ); Gia_ManSwiSimulateCo( p, Gia_ObjCioId(pObj), pObj ); } else // if ( Gia_ObjIsCi(pObj) ) { assert( Gia_ObjValue(pObj) < p->pAig->nFront ); // Gia_ManSwiSimulateCi( p, pObj, iCis++ ); Gia_ManSwiSimulateCi( p, pObj, Gia_ObjCioId(pObj) ); } if ( fCount && !Gia_ObjIsCo(pObj) ) { if ( p->pPars->fProbTrans ) p->pData1[i] += Gia_ManSwiSimInfoCountTrans( p, Gia_ObjValue(pObj) ); else p->pData1[i] += Gia_ManSwiSimInfoCountOnes( p, Gia_ObjValue(pObj) ); } } // assert( Gia_ManCiNum(p->pAig) == iCis ); // assert( Gia_ManCoNum(p->pAig) == iCos ); } /**Function************************************************************* Synopsis [Computes switching activity of one node.] Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] SideEffects [] SeeAlso [] ***********************************************************************/ float Gia_ManSwiComputeSwitching( int nOnes, int nSimWords ) { int nTotal = 32 * nSimWords; return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal; } /**Function************************************************************* Synopsis [Computes switching activity of one node.] Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] SideEffects [] SeeAlso [] ***********************************************************************/ float Gia_ManSwiComputeProbOne( int nOnes, int nSimWords ) { int nTotal = 32 * nSimWords; return (float)nOnes / nTotal; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManSwiSimulate( Gia_Man_t * pAig, Gia_ParSwi_t * pPars ) { Gia_ManSwi_t * p; Gia_Obj_t * pObj; Vec_Int_t * vSwitching; float * pSwitching; int i; abctime clk, clkTotal = Abc_Clock(); if ( pPars->fProbOne && pPars->fProbTrans ) printf( "Conflict of options: Can either compute probability of 1, or probability of switching by observing transitions.\n" ); // create manager clk = Abc_Clock(); p = Gia_ManSwiCreate( pAig, pPars ); if ( pPars->fVerbose ) { printf( "Obj = %8d (%8d). F = %6d. ", pAig->nObjs, Gia_ManCiNum(pAig) + Gia_ManAndNum(pAig), p->pAig->nFront ); printf( "AIG = %7.2f MB. F-mem = %7.2f MB. Other = %7.2f MB. ", 12.0*Gia_ManObjNum(p->pAig)/(1<<20), 4.0*p->nWords*p->pAig->nFront/(1<<20), 4.0*p->nWords*(Gia_ManCiNum(p->pAig) + Gia_ManCoNum(p->pAig))/(1<<20) ); ABC_PRT( "Time", Abc_Clock() - clk ); } // perform simulation Gia_ManRandom( 1 ); Gia_ManSwiSimInfoInit( p ); for ( i = 0; i < pPars->nIters; i++ ) { Gia_ManSwiSimulateRound( p, i >= pPars->nPref ); if ( i == pPars->nIters - 1 ) break; if ( pPars->fProbTrans ) Gia_ManSwiSimInfoTransferShift( p, pPars->nRandPiFactor ); else Gia_ManSwiSimInfoTransfer( p, pPars->nRandPiFactor ); } if ( pPars->fVerbose ) { printf( "Simulated %d frames with %d words. ", pPars->nIters, pPars->nWords ); ABC_PRT( "Simulation time", Abc_Clock() - clkTotal ); } // derive the result vSwitching = Vec_IntStart( Gia_ManObjNum(pAig) ); pSwitching = (float *)vSwitching->pArray; if ( pPars->fProbOne ) { Gia_ManForEachObj( pAig, pObj, i ) pSwitching[i] = Gia_ManSwiComputeProbOne( p->pData1[i], pPars->nWords*(pPars->nIters-pPars->nPref) ); Gia_ManForEachCo( pAig, pObj, i ) { if ( Gia_ObjFaninC0(pObj) ) pSwitching[Gia_ObjId(pAig,pObj)] = (float)1.0-pSwitching[Gia_ObjId(pAig,Gia_ObjFanin0(pObj))]; else pSwitching[Gia_ObjId(pAig,pObj)] = pSwitching[Gia_ObjId(pAig,Gia_ObjFanin0(pObj))]; } } else if ( pPars->fProbTrans ) { Gia_ManForEachObj( pAig, pObj, i ) pSwitching[i] = Gia_ManSwiComputeSwitching( p->pData1[i], pPars->nWords*(pPars->nIters-pPars->nPref) ); } else { Gia_ManForEachObj( pAig, pObj, i ) pSwitching[i] = Gia_ManSwiComputeSwitching( p->pData1[i], pPars->nWords*(pPars->nIters-pPars->nPref) ); } /* printf( "PI: " ); Gia_ManForEachPi( pAig, pObj, i ) printf( "%d=%d (%f) ", i, p->pData1[Gia_ObjId(pAig,pObj)], pSwitching[Gia_ObjId(pAig,pObj)] ); printf( "\n" ); printf( "LO: " ); Gia_ManForEachRo( pAig, pObj, i ) printf( "%d=%d (%f) ", i, p->pData1[Gia_ObjId(pAig,pObj)], pSwitching[Gia_ObjId(pAig,pObj)] ); printf( "\n" ); printf( "PO: " ); Gia_ManForEachPo( pAig, pObj, i ) printf( "%d=%d (%f) ", i, p->pData1[Gia_ObjId(pAig,pObj)], pSwitching[Gia_ObjId(pAig,pObj)] ); printf( "\n" ); printf( "LI: " ); Gia_ManForEachRi( pAig, pObj, i ) printf( "%d=%d (%f) ", i, p->pData1[Gia_ObjId(pAig,pObj)], pSwitching[Gia_ObjId(pAig,pObj)] ); printf( "\n" ); */ Gia_ManSwiDelete( p ); return vSwitching; } /**Function************************************************************* Synopsis [Computes probability of switching (or of being 1).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManComputeSwitchProbs( Gia_Man_t * pGia, int nFrames, int nPref, int fProbOne ) { Gia_ParSwi_t Pars, * pPars = &Pars; // set the default parameters Gia_ManSetDefaultParamsSwi( pPars ); // override some of the defaults pPars->nIters = nFrames; // set number of total timeframes if ( Abc_FrameReadFlag("seqsimframes") ) pPars->nIters = atoi( Abc_FrameReadFlag("seqsimframes") ); pPars->nPref = nPref; // set number of first timeframes to skip // decide what should be computed if ( fProbOne ) { // if the user asked to compute propability of 1, we do not need transition information pPars->fProbOne = 1; // enable computing probabiblity of being one pPars->fProbTrans = 0; // disable computing transition probability } else { // if the user asked for transition propabability, we do not need to compute probability of 1 pPars->fProbOne = 0; // disable computing probabiblity of being one pPars->fProbTrans = 1; // enable computing transition probability } // perform the computation of switching activity return Gia_ManSwiSimulate( pGia, pPars ); } Vec_Int_t * Gia_ManComputeSwitchProbs2( Gia_Man_t * pGia, int nFrames, int nPref, int fProbOne, int nRandPiFactor ) { Gia_ParSwi_t Pars, * pPars = &Pars; // set the default parameters Gia_ManSetDefaultParamsSwi( pPars ); pPars->nRandPiFactor = nRandPiFactor; // override some of the defaults pPars->nIters = nFrames; // set number of total timeframes if ( Abc_FrameReadFlag("seqsimframes") ) pPars->nIters = atoi( Abc_FrameReadFlag("seqsimframes") ); pPars->nPref = nPref; // set number of first timeframes to skip // decide what should be computed if ( fProbOne ) { // if the user asked to compute propability of 1, we do not need transition information pPars->fProbOne = 1; // enable computing probabiblity of being one pPars->fProbTrans = 0; // disable computing transition probability } else { // if the user asked for transition propabability, we do not need to compute probability of 1 pPars->fProbOne = 0; // disable computing probabiblity of being one pPars->fProbTrans = 1; // enable computing transition probability } // perform the computation of switching activity return Gia_ManSwiSimulate( pGia, pPars ); } Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * pAig, int nFrames, int nPref, int fProbOne ) { Vec_Int_t * vSwitching, * vResult; Gia_Man_t * p; Aig_Obj_t * pObj; int i; // translate AIG into the intermediate form (takes care of choices if present!) p = Gia_ManFromAigSwitch( pAig ); // perform the computation of switching activity vSwitching = Gia_ManComputeSwitchProbs( p, nFrames, nPref, fProbOne ); // transfer the computed result to the original AIG vResult = Vec_IntStart( Aig_ManObjNumMax(pAig) ); Aig_ManForEachObj( pAig, pObj, i ) { // if ( Aig_ObjIsCo(pObj) ) // printf( "%d=%f\n", i, Abc_Int2Float( Vec_IntEntry(vSwitching, Abc_Lit2Var(pObj->iData)) ) ); Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vSwitching, Abc_Lit2Var(pObj->iData)) ); } // delete intermediate results Vec_IntFree( vSwitching ); Gia_ManStop( p ); return vResult; } /**Function************************************************************* Synopsis [Computes probability of switching (or of being 1).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Gia_ManEvaluateSwitching( Gia_Man_t * p ) { Gia_Obj_t * pObj; float SwitchTotal = 0.0; int i; assert( p->pSwitching ); ABC_FREE( p->pRefs ); Gia_ManCreateRefs( p ); Gia_ManForEachObj( p, pObj, i ) SwitchTotal += (float)Gia_ObjRefNum(p, pObj) * p->pSwitching[i] / 255; return SwitchTotal; } /**Function************************************************************* Synopsis [Computes probability of switching (or of being 1).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* float Gia_ManComputeSwitching( Gia_Man_t * p, int nFrames, int nPref, int fProbOne ) { Gia_Man_t * pDfs; Gia_Obj_t * pObj, * pObjDfs; Vec_Int_t * vSwitching; float * pSwitching, Switch, SwitchTotal = 0.0; int i; // derives the DFS ordered AIG if ( Gia_ManHasMapping(p) ) Gia_ManSetRefsMapped(p); else Gia_ManCreateRefs( p ); // pDfs = Gia_ManDupOrderDfs( p ); pDfs = Gia_ManDup( p ); assert( Gia_ManObjNum(pDfs) == Gia_ManObjNum(p) ); // perform the computation of switching activity vSwitching = Gia_ManComputeSwitchProbs( pDfs, nFrames, nPref, fProbOne ); // transfer the computed result to the original AIG ABC_FREE( p->pSwitching ); p->pSwitching = ABC_CALLOC( unsigned char, Gia_ManObjNum(p) ); pSwitching = (float *)vSwitching->pArray; Gia_ManForEachObj( p, pObj, i ) { pObjDfs = Gia_ObjFromLit( pDfs, pObj->Value ); Switch = pSwitching[ Gia_ObjId(pDfs, pObjDfs) ]; p->pSwitching[i] = (char)((Switch >= 1.0) ? 255 : (int)((0.002 + Switch) * 255)); // 0.00196 = (1/255)/2 if ( Gia_ObjIsCi(pObj) || (Gia_ObjIsAnd(pObj) && (!Gia_ManHasMapping(p) || Gia_ObjIsLut(p, i))) ) { SwitchTotal += (float)Gia_ObjRefNum(p, pObj) * p->pSwitching[i] / 255; // printf( "%d = %.2f\n", i, (float)Gia_ObjRefNum(p, pObj) * p->pSwitching[i] / 255 ); } } Vec_IntFree( vSwitching ); Gia_ManStop( pDfs ); return SwitchTotal; } */ float Gia_ManComputeSwitching( Gia_Man_t * p, int nFrames, int nPref, int fProbOne ) { Vec_Int_t * vSwitching = Gia_ManComputeSwitchProbs( p, nFrames, nPref, fProbOne ); float * pSwi = (float *)Vec_IntArray(vSwitching), SwiTotal = 0; Gia_Obj_t * pObj; int i, k, iFan; if ( Gia_ManHasMapping(p) ) { Gia_ManForEachLut( p, i ) Gia_LutForEachFanin( p, i, iFan, k ) SwiTotal += pSwi[iFan]; } else { 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; } /**Function************************************************************* Synopsis [Determine probability of being 1 at the outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Flt_t * Gia_ManPrintOutputProb( Gia_Man_t * p ) { Vec_Flt_t * vSimData; Gia_Man_t * pDfs = Gia_ManDup( p ); assert( Gia_ManObjNum(pDfs) == Gia_ManObjNum(p) ); vSimData = (Vec_Flt_t *)Gia_ManComputeSwitchProbs( pDfs, (Gia_ManRegNum(p) ? 16 : 1), 0, 1 ); Gia_ManStop( pDfs ); return vSimData; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaTim.c000066400000000000000000001125111477524141600156460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaTim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Procedures with hierarchy/timing manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaTim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "giaAig.h" #include "misc/tim/tim.h" #include "misc/extra/extra.h" #include "proof/cec/cec.h" #include "proof/fra/fra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the number of boxes in the AIG with boxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManBoxNum( Gia_Man_t * p ) { return p->pManTime ? Tim_ManBoxNum((Tim_Man_t *)p->pManTime) : 0; } int Gia_ManRegBoxNum( Gia_Man_t * p ) { return p->vRegClasses ? Vec_IntSize(p->vRegClasses) : 0; } int Gia_ManNonRegBoxNum( Gia_Man_t * p ) { return Gia_ManBoxNum(p) - Gia_ManRegBoxNum(p); } int Gia_ManBlackBoxNum( Gia_Man_t * p ) { return Tim_ManBlackBoxNum((Tim_Man_t *)p->pManTime); } int Gia_ManBoxCiNum( Gia_Man_t * p ) { return p->pManTime ? Gia_ManCiNum(p) - Tim_ManPiNum((Tim_Man_t *)p->pManTime) : 0; } int Gia_ManBoxCoNum( Gia_Man_t * p ) { return p->pManTime ? Gia_ManCoNum(p) - Tim_ManPoNum((Tim_Man_t *)p->pManTime) : 0; } int Gia_ManClockDomainNum( Gia_Man_t * p ) { int i, nDoms, Count = 0; if ( p->vRegClasses == NULL ) return 0; nDoms = Vec_IntFindMax(p->vRegClasses); assert( Vec_IntCountEntry(p->vRegClasses, 0) == 0 ); for ( i = 1; i <= nDoms; i++ ) if ( Vec_IntCountEntry(p->vRegClasses, i) > 0 ) Count++; return Count; } /**Function************************************************************* Synopsis [Returns one if this is a seq AIG with non-trivial boxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManIsSeqWithBoxes( Gia_Man_t * p ) { return (Gia_ManRegNum(p) > 0 && Gia_ManBoxNum(p) > 0); } /**Function************************************************************* Synopsis [Makes sure the manager is normalized.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManIsNormalized( Gia_Man_t * p ) { int i, nOffset; nOffset = 1; for ( i = 0; i < Gia_ManCiNum(p); i++ ) if ( !Gia_ObjIsCi( Gia_ManObj(p, nOffset+i) ) ) return 0; nOffset = 1 + Gia_ManCiNum(p) + Gia_ManAndNum(p); for ( i = 0; i < Gia_ManCoNum(p); i++ ) if ( !Gia_ObjIsCo( Gia_ManObj(p, nOffset+i) ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Duplicates AIG in the DFS order while putting CIs first.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupNormalize( Gia_Man_t * p, int fHashMapping ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; 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; if ( !Gia_ManIsSeqWithBoxes(p) ) { Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); } else { // current CI order: PIs + FOs + NewCIs // desired reorder: PIs + NewCIs + FOs int nCIs = Tim_ManPiNum( (Tim_Man_t *)p->pManTime ); int nAll = Tim_ManCiNum( (Tim_Man_t *)p->pManTime ); int nPis = nCIs - Gia_ManRegNum(p); assert( nAll == Gia_ManCiNum(p) ); assert( nPis > 0 ); // copy PIs first for ( i = 0; i < nPis; i++ ) Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew); // copy new CIs second for ( i = nCIs; i < nAll; i++ ) Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew); // copy flops last for ( i = nCIs - Gia_ManRegNum(p); i < nCIs; i++ ) Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew); printf( "Warning: Shuffled CI order to be correct sequential AIG.\n" ); } if ( fHashMapping ) Gia_ManHashAlloc( pNew ); Gia_ManForEachAnd( p, pObj, i ) if ( Gia_ObjIsBuf(pObj) ) pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); else if ( fHashMapping ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( fHashMapping ) Gia_ManHashStop( pNew ); Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew->nConstrs = p->nConstrs; assert( Gia_ManIsNormalized(pNew) ); Gia_ManDupRemapEquiv( pNew, p ); return pNew; } /**Function************************************************************* Synopsis [Reorders flops for sequential AIGs with boxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupUnshuffleInputs( Gia_Man_t * p ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, nCIs, nAll, nPis; // sanity checks assert( Gia_ManIsNormalized(p) ); assert( Gia_ManIsSeqWithBoxes(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; // change input order // desired reorder: PIs + NewCIs + FOs // current CI order: PIs + FOs + NewCIs nCIs = Tim_ManPiNum( (Tim_Man_t *)p->pManTime ); nAll = Tim_ManCiNum( (Tim_Man_t *)p->pManTime ); nPis = nCIs - Gia_ManRegNum(p); assert( nAll == Gia_ManCiNum(p) ); assert( nPis > 0 ); // copy PIs first for ( i = 0; i < nPis; i++ ) Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew); // copy flops second for ( i = nAll - Gia_ManRegNum(p); i < nAll; i++ ) Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew); // copy new CIs last for ( i = nPis; i < nAll - Gia_ManRegNum(p); i++ ) Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew); printf( "Warning: Unshuffled CI order to be correct AIG with boxes.\n" ); // other things 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) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew->nConstrs = p->nConstrs; assert( Gia_ManIsNormalized(pNew) ); Gia_ManDupRemapEquiv( pNew, p ); return pNew; } /**Function************************************************************* Synopsis [Find the ordering of AIG objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManOrderWithBoxes_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 0; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) { p->iData2 = Gia_ObjCioId(pObj); return 1; } assert( Gia_ObjIsAnd(pObj) ); if ( Gia_ObjIsBuf(pObj) ) { if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin0(pObj), vNodes ) ) return 1; Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); return 0; } if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) ) if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)), vNodes ) ) return 1; if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin0(pObj), vNodes ) ) return 1; if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin1(pObj), vNodes ) ) return 1; Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); return 0; } Vec_Int_t * Gia_ManOrderWithBoxes( Gia_Man_t * p ) { Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; Vec_Int_t * vNodes; Gia_Obj_t * pObj; int i, k, curCi, curCo; assert( pManTime != NULL ); assert( Gia_ManIsNormalized( p ) ); // start trav IDs Gia_ManIncrementTravId( p ); // start the array vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); // include constant Vec_IntPush( vNodes, 0 ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); // include primary inputs for ( i = 0; i < Tim_ManPiNum(pManTime); i++ ) { pObj = Gia_ManCi( p, i ); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); Gia_ObjSetTravIdCurrent( p, pObj ); assert( Gia_ObjId(p, pObj) == i+1 ); } // for each box, include box nodes curCi = Tim_ManPiNum(pManTime); curCo = 0; for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ ) { // add internal nodes for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ ) { pObj = Gia_ManCo( p, curCo + k ); if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin0(pObj), vNodes ) ) { int iCiNum = p->iData2; int iBoxNum = Tim_ManBoxFindFromCiNum( pManTime, iCiNum ); printf( "The command has to terminate. Boxes are not in a topological order.\n" ); printf( "The following information may help debugging (numbers are 0-based):\n" ); printf( "Input %d of BoxA %d (1stCI = %d; 1stCO = %d) has TFI with CI %d,\n", k, i, Tim_ManBoxOutputFirst(pManTime, i), Tim_ManBoxInputFirst(pManTime, i), iCiNum ); printf( "which corresponds to output %d of BoxB %d (1stCI = %d; 1stCO = %d).\n", iCiNum - Tim_ManBoxOutputFirst(pManTime, iBoxNum), iBoxNum, Tim_ManBoxOutputFirst(pManTime, iBoxNum), Tim_ManBoxInputFirst(pManTime, iBoxNum) ); printf( "In a correct topological order, BoxB should precede BoxA.\n" ); Vec_IntFree( vNodes ); p->iData2 = 0; return NULL; } } // add POs corresponding to box inputs for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ ) { pObj = Gia_ManCo( p, curCo + k ); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); } curCo += Tim_ManBoxInputNum(pManTime, i); // add PIs corresponding to box outputs for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ ) { pObj = Gia_ManCi( p, curCi + k ); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); Gia_ObjSetTravIdCurrent( p, pObj ); } curCi += Tim_ManBoxOutputNum(pManTime, i); } // add remaining nodes for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ ) { pObj = Gia_ManCo( p, i ); Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin0(pObj), vNodes ); } // add POs for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ ) { pObj = Gia_ManCo( p, i ); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); } curCo += Tim_ManPoNum(pManTime); // verify counts assert( curCi == Gia_ManCiNum(p) ); assert( curCo == Gia_ManCoNum(p) ); //assert( Vec_IntSize(vNodes) == Gia_ManObjNum(p) ); return vNodes; } /**Function************************************************************* Synopsis [Duplicates AIG according to the timing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManDupUnnormalize( Gia_Man_t * p ) { Vec_Int_t * vNodes; Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; assert( !Gia_ManBufNum(p) ); vNodes = Gia_ManOrderWithBoxes( p ); if ( vNodes == NULL ) return NULL; Gia_ManFillValue( p ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); if ( Gia_ManHasChoices(p) ) pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachObjVec( vNodes, p, 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) ); if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) ) pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))->Value); } else 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_ObjIsConst0(pObj) ) pObj->Value = 0; else assert( 0 ); } Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); Vec_IntFree( vNodes ); return pNew; } /**Function************************************************************* Synopsis [Remaps the AIG from the old manager into the new manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCleanupRemap( Gia_Man_t * p, Gia_Man_t * pGia ) { Gia_Obj_t * pObj, * pObjGia; int i, iPrev; Gia_ManForEachObj1( p, pObj, i ) { iPrev = Gia_ObjValue(pObj); if ( iPrev == ~0 ) continue; pObjGia = Gia_ManObj( pGia, Abc_Lit2Var(iPrev) ); if ( pObjGia->Value == ~0 ) Gia_ObjSetValue( pObj, pObjGia->Value ); else Gia_ObjSetValue( pObj, Abc_LitNotCond(pObjGia->Value, Abc_LitIsCompl(iPrev)) ); } } /**Function************************************************************* Synopsis [Computes level with boxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManLevelWithBoxes_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 0; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) return 1; assert( Gia_ObjIsAnd(pObj) ); if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) ) Gia_ManLevelWithBoxes_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)) ); if ( Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) ) ) return 1; if ( Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin1(pObj) ) ) return 1; Gia_ObjSetAndLevel( p, pObj ); return 0; } int Gia_ManLevelWithBoxes( Gia_Man_t * p ) { int nAnd2Delay = p->nAnd2Delay ? p->nAnd2Delay : 1; Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; Gia_Obj_t * pObj, * pObjIn; int i, k, j, curCi, curCo, LevelMax; assert( Gia_ManRegNum(p) == 0 ); assert( Gia_ManBufNum(p) == 0 ); // copy const and real PIs Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); Gia_ObjSetLevel( p, Gia_ManConst0(p), 0 ); Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); for ( i = 0; i < Tim_ManPiNum(pManTime); i++ ) { pObj = Gia_ManCi( p, i ); Gia_ObjSetLevel( p, pObj, Tim_ManGetCiArrival(pManTime, i) / nAnd2Delay ); Gia_ObjSetTravIdCurrent( p, pObj ); } // create logic for each box curCi = Tim_ManPiNum(pManTime); curCo = 0; for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ ) { int nBoxInputs = Tim_ManBoxInputNum( pManTime, i ); int nBoxOutputs = Tim_ManBoxOutputNum( pManTime, i ); float * pDelayTable = Tim_ManBoxDelayTable( pManTime, i ); // compute level for TFI of box inputs for ( k = 0; k < nBoxInputs; k++ ) { pObj = Gia_ManCo( p, curCo + k ); if ( Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) ) ) { printf( "Boxes are not in a topological order. Switching to level computation without boxes.\n" ); return Gia_ManLevelNum( p ); } // set box input level Gia_ObjSetCoLevel( p, pObj ); } // compute level for box outputs for ( k = 0; k < nBoxOutputs; k++ ) { pObj = Gia_ManCi( p, curCi + k ); Gia_ObjSetTravIdCurrent( p, pObj ); // evaluate delay of this output LevelMax = 0; assert( nBoxInputs == (int)pDelayTable[1] ); for ( j = 0; j < nBoxInputs && (pObjIn = Gia_ManCo(p, curCo + j)); j++ ) if ( (int)pDelayTable[3+k*nBoxInputs+j] != -ABC_INFINITY ) LevelMax = Abc_MaxInt( LevelMax, Gia_ObjLevel(p, pObjIn) + ((int)pDelayTable[3+k*nBoxInputs+j] / nAnd2Delay) ); // set box output level Gia_ObjSetLevel( p, pObj, LevelMax ); } curCo += nBoxInputs; curCi += nBoxOutputs; } // add remaining nodes p->nLevels = 0; for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ ) { pObj = Gia_ManCo( p, i ); Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) ); Gia_ObjSetCoLevel( p, pObj ); p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) ); } curCo += Tim_ManPoNum(pManTime); // verify counts assert( curCi == Gia_ManCiNum(p) ); assert( curCo == Gia_ManCoNum(p) ); // printf( "Max level is %d.\n", p->nLevels ); return p->nLevels; } /**Function************************************************************* Synopsis [Computes level with boxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManLutLevelWithBoxes_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { int iObj, k, iFan, Level = 0; if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 0; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) return 1; assert( Gia_ObjIsAnd(pObj) ); iObj = Gia_ObjId( p, pObj ); Gia_LutForEachFanin( p, iObj, iFan, k ) { if ( Gia_ManLutLevelWithBoxes_rec( p, Gia_ManObj(p, iFan) ) ) return 1; Level = Abc_MaxInt( Level, Gia_ObjLevelId(p, iFan) ); } Gia_ObjSetLevelId( p, iObj, Level + 1 ); return 0; } int Gia_ManLutLevelWithBoxes( Gia_Man_t * p ) { // int nAnd2Delay = p->nAnd2Delay ? p->nAnd2Delay : 1; Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; Gia_Obj_t * pObj, * pObjIn; int i, k, j, curCi, curCo, LevelMax; assert( Gia_ManRegNum(p) == 0 ); if ( pManTime == NULL ) return Gia_ManLutLevel(p, NULL); // copy const and real PIs Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); Gia_ObjSetLevel( p, Gia_ManConst0(p), 0 ); Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); for ( i = 0; i < Tim_ManPiNum(pManTime); i++ ) { pObj = Gia_ManCi( p, i ); // Gia_ObjSetLevel( p, pObj, Tim_ManGetCiArrival(pManTime, i) / nAnd2Delay ); Gia_ObjSetLevel( p, pObj, 0 ); Gia_ObjSetTravIdCurrent( p, pObj ); } // create logic for each box curCi = Tim_ManPiNum(pManTime); curCo = 0; for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ ) { int nBoxInputs = Tim_ManBoxInputNum( pManTime, i ); int nBoxOutputs = Tim_ManBoxOutputNum( pManTime, i ); float * pDelayTable = Tim_ManBoxDelayTable( pManTime, i ); // compute level for TFI of box inputs for ( k = 0; k < nBoxInputs; k++ ) { pObj = Gia_ManCo( p, curCo + k ); if ( Gia_ManLutLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) ) ) { printf( "Boxes are not in a topological order. Switching to level computation without boxes.\n" ); return Gia_ManLevelNum( p ); } // set box input level Gia_ObjSetCoLevel( p, pObj ); } // compute level for box outputs for ( k = 0; k < nBoxOutputs; k++ ) { pObj = Gia_ManCi( p, curCi + k ); Gia_ObjSetTravIdCurrent( p, pObj ); // evaluate delay of this output LevelMax = 0; assert( nBoxInputs == (int)pDelayTable[1] ); for ( j = 0; j < nBoxInputs && (pObjIn = Gia_ManCo(p, curCo + j)); j++ ) if ( (int)pDelayTable[3+k*nBoxInputs+j] != -ABC_INFINITY ) // LevelMax = Abc_MaxInt( LevelMax, Gia_ObjLevel(p, pObjIn) + ((int)pDelayTable[3+k*nBoxInputs+j] / nAnd2Delay) ); LevelMax = Abc_MaxInt( LevelMax, Gia_ObjLevel(p, pObjIn) + 1 ); // set box output level Gia_ObjSetLevel( p, pObj, LevelMax ); } curCo += nBoxInputs; curCi += nBoxOutputs; } // add remaining nodes p->nLevels = 0; for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ ) { pObj = Gia_ManCo( p, i ); Gia_ManLutLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) ); Gia_ObjSetCoLevel( p, pObj ); p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) ); } curCo += Tim_ManPoNum(pManTime); // verify counts assert( curCi == Gia_ManCiNum(p) ); assert( curCo == Gia_ManCoNum(p) ); // printf( "Max level is %d.\n", p->nLevels ); return p->nLevels; } /**Function************************************************************* Synopsis [Update hierarchy/timing manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Gia_ManUpdateTimMan( Gia_Man_t * p, Vec_Int_t * vBoxPres ) { Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; assert( pManTime != NULL ); assert( Vec_IntSize(vBoxPres) == Tim_ManBoxNum(pManTime) ); return Tim_ManTrim( pManTime, vBoxPres ); } void * Gia_ManUpdateTimMan2( Gia_Man_t * p, Vec_Int_t * vBoxesLeft, int nTermsDiff ) { Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; assert( pManTime != NULL ); assert( Vec_IntSize(vBoxesLeft) <= Tim_ManBoxNum(pManTime) ); return Tim_ManReduce( pManTime, vBoxesLeft, nTermsDiff ); } /**Function************************************************************* Synopsis [Update AIG of the holes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManUpdateExtraAig( void * pTime, Gia_Man_t * p, Vec_Int_t * vBoxPres ) { Gia_Man_t * pNew; Tim_Man_t * pManTime = (Tim_Man_t *)pTime; Vec_Int_t * vOutPres = Vec_IntAlloc( 100 ); int i, k, curPo = 0; assert( Vec_IntSize(vBoxPres) == Tim_ManBoxNum(pManTime) ); assert( Gia_ManCoNum(p) == Tim_ManCiNum(pManTime) - Tim_ManPiNum(pManTime) ); for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ ) { for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ ) Vec_IntPush( vOutPres, Vec_IntEntry(vBoxPres, i) ); curPo += Tim_ManBoxOutputNum(pManTime, i); } assert( curPo == Gia_ManCoNum(p) ); pNew = Gia_ManDupOutputVec( p, vOutPres ); Vec_IntFree( vOutPres ); return pNew; } Gia_Man_t * Gia_ManUpdateExtraAig2( void * pTime, Gia_Man_t * p, Vec_Int_t * vBoxesLeft ) { Gia_Man_t * pNew; Tim_Man_t * pManTime = (Tim_Man_t *)pTime; int nRealPis = Tim_ManPiNum(pManTime); Vec_Int_t * vOutsLeft = Vec_IntAlloc( 100 ); int i, k, iBox, iOutFirst; assert( Vec_IntSize(vBoxesLeft) <= Tim_ManBoxNum(pManTime) ); assert( Gia_ManCoNum(p) == Tim_ManCiNum(pManTime) - nRealPis ); Vec_IntForEachEntry( vBoxesLeft, iBox, i ) { iOutFirst = Tim_ManBoxOutputFirst(pManTime, iBox) - nRealPis; for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, iBox); k++ ) Vec_IntPush( vOutsLeft, iOutFirst + k ); } pNew = Gia_ManDupSelectedOutputs( p, vOutsLeft ); Vec_IntFree( vOutsLeft ); 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManDupCollapse_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Man_t * pNew ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); assert( Gia_ObjIsAnd(pObj) ); if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) ) Gia_ManDupCollapse_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)), pNew ); Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew ); Gia_ManDupCollapse_rec( p, Gia_ObjFanin1(pObj), pNew ); // assert( !~pObj->Value ); pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) ) pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))->Value); } Gia_Man_t * Gia_ManDupCollapse( Gia_Man_t * p, Gia_Man_t * pBoxes, Vec_Int_t * vBoxPres, int fSeq ) { // this procedure assumes that sequential AIG with boxes is unshuffled to have valid boxes 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, nNewPis = 0; assert( !fSeq || p->vRegClasses ); //assert( Gia_ManRegNum(p) == 0 ); assert( Gia_ManCiNum(p) == Tim_ManPiNum(pManTime) + Gia_ManCoNum(pBoxes) ); pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); if ( Gia_ManHasChoices(p) ) pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManHashAlloc( pNew ); // copy const and real PIs Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManIncrementTravId( p ); Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); for ( i = 0; i < Tim_ManPiNum(pManTime); i++ ) { pObj = Gia_ManCi( p, i ); pObj->Value = Gia_ManAppendCi(pNew); Gia_ObjSetTravIdCurrent( p, pObj ); } // create logic for each box curCi = Tim_ManPiNum(pManTime); curCo = 0; for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ ) { // clean boxes Gia_ManIncrementTravId( pBoxes ); Gia_ObjSetTravIdCurrent( pBoxes, Gia_ManConst0(pBoxes) ); Gia_ManConst0(pBoxes)->Value = 0; // add internal nodes //printf( "%d ", Tim_ManBoxIsBlack(pManTime, i) ); if ( Tim_ManBoxIsBlack(pManTime, i) ) { int fSkip = (vBoxPres != NULL && !Vec_IntEntry(vBoxPres, i)); for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ ) { pObj = Gia_ManCo( p, curCo + k ); Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew ); pObj->Value = fSkip ? -1 : Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); nBBouts++; } for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ ) { pObj = Gia_ManCi( p, curCi + k ); pObj->Value = fSkip ? 0 : Gia_ManAppendCi(pNew); Gia_ObjSetTravIdCurrent( p, pObj ); nBBins++; nNewPis += !fSkip; } } else { for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ ) { // build logic pObj = Gia_ManCo( p, curCo + k ); Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew ); // transfer to the PI pObjBox = Gia_ManCi( pBoxes, k ); pObjBox->Value = Gia_ObjFanin0Copy(pObj); Gia_ObjSetTravIdCurrent( pBoxes, pObjBox ); } for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ ) { // build logic pObjBox = Gia_ManCo( pBoxes, curCi - Tim_ManPiNum(pManTime) + k ); Gia_ManDupCollapse_rec( pBoxes, Gia_ObjFanin0(pObjBox), pNew ); // transfer to the PI pObj = Gia_ManCi( p, curCi + k ); pObj->Value = Gia_ObjFanin0Copy(pObjBox); Gia_ObjSetTravIdCurrent( p, pObj ); } } curCo += Tim_ManBoxInputNum(pManTime, i); curCi += Tim_ManBoxOutputNum(pManTime, i); } //printf( "\n" ); // add remaining nodes for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ ) { pObj = Gia_ManCo( p, i ); Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew ); pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); } curCo += Tim_ManPoNum(pManTime); // verify counts assert( curCi == Gia_ManCiNum(p) ); assert( curCo == Gia_ManCoNum(p) ); Gia_ManSetRegNum( pNew, (fSeq && p->vRegClasses) ? Vec_IntSize(p->vRegClasses) : Gia_ManRegNum(p) ); Gia_ManHashStop( pNew ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManCleanupRemap( p, pTemp ); Gia_ManStop( pTemp ); 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) ) { char * pInit = ABC_ALLOC( char, Vec_IntSize(p->vRegInits) + 1 ); Gia_Obj_t * pObj; int i; assert( Vec_IntSize(p->vRegInits) == Gia_ManRegNum(pNew) ); Gia_ManForEachRo( pNew, pObj, i ) { if ( Vec_IntEntry(p->vRegInits, i) == 0 ) pInit[i] = '0'; else if ( Vec_IntEntry(p->vRegInits, i) == 1 ) pInit[i] = '1'; else pInit[i] = 'X'; } pInit[i] = 0; pNew = Gia_ManDupZeroUndc( pTemp = pNew, pInit, 0, 0, 1 ); pNew->nConstrs = pTemp->nConstrs; pTemp->nConstrs = 0; Gia_ManStop( pTemp ); ABC_FREE( pInit ); } return pNew; } /**Function************************************************************* Synopsis [Verify XAIG against its spec.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManVerifyWithBoxes( Gia_Man_t * pGia, int nBTLimit, int nTimeLim, int fSeq, int fDumpFiles, int fVerbose, char * pFileSpec ) { int Status = -1; Gia_Man_t * pSpec, * pGia0, * pGia1, * pMiter; Vec_Int_t * vBoxPres = NULL; if ( pFileSpec == NULL && pGia->pSpec == NULL ) { printf( "Spec file is not given. Use standard flow.\n" ); return Status; } if ( Gia_ManBoxNum(pGia) && pGia->pAigExtra == NULL ) { printf( "Design has no box logic. Use standard flow.\n" ); return Status; } // read original AIG pSpec = Gia_AigerRead( pFileSpec ? pFileSpec : pGia->pSpec, 0, 0, 0 ); if ( Gia_ManBoxNum(pSpec) && pSpec->pAigExtra == NULL ) { Gia_ManStop( pSpec ); printf( "Spec has no box logic. Use standard flow.\n" ); return Status; } // prepare miter if ( pGia->pManTime == NULL && pSpec->pManTime == NULL ) { pGia0 = Gia_ManDup( pSpec ); pGia1 = Gia_ManDup( pGia ); } else { // if timing managers have different number of black boxes, // it is possible that some of the boxes are swept away if ( pSpec->pManTime && Tim_ManBlackBoxNum((Tim_Man_t *)pSpec->pManTime) > 0 && Gia_ManBoxNum(pGia) > 0 ) { // specification cannot have fewer boxes than implementation if ( Gia_ManBoxNum(pSpec) < Gia_ManBoxNum(pGia) ) { printf( "Spec has less boxes than the design. Cannot proceed.\n" ); return Status; } // to align the boxes, find what boxes of pSpec are dropped in pGia if ( Gia_ManBoxNum(pSpec) > Gia_ManBoxNum(pGia) ) { vBoxPres = Tim_ManAlignTwo( (Tim_Man_t *)pSpec->pManTime, (Tim_Man_t *)pGia->pManTime ); if ( vBoxPres == NULL ) { printf( "Boxes of spec and design cannot be aligned. Cannot proceed.\n" ); return Status; } } } // collapse two designs if ( Gia_ManBoxNum(pSpec) > 0 ) pGia0 = Gia_ManDupCollapse( pSpec, pSpec->pAigExtra, vBoxPres, fSeq ); else pGia0 = Gia_ManDup( pSpec ); if ( Gia_ManBoxNum(pGia) > 0 ) pGia1 = Gia_ManDupCollapse( pGia, pGia->pAigExtra, NULL, fSeq ); else pGia1 = Gia_ManDup( pGia ); Vec_IntFreeP( &vBoxPres ); } if ( fDumpFiles ) { char pFileName0[1000], pFileName1[1000]; 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, 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 ); } // compute the miter if ( fSeq ) { pMiter = Gia_ManMiter( pGia0, pGia1, 0, 0, 1, 0, fVerbose ); if ( pMiter ) { Aig_Man_t * pMan; Fra_Sec_t SecPar, * pSecPar = &SecPar; Fra_SecSetDefaultParams( pSecPar ); pSecPar->fRetimeFirst = 0; pSecPar->nBTLimit = nBTLimit; pSecPar->TimeLimit = nTimeLim; pSecPar->fVerbose = fVerbose; pMan = Gia_ManToAig( pMiter, 0 ); Gia_ManStop( pMiter ); Status = Fra_FraigSec( pMan, pSecPar, NULL ); Aig_ManStop( pMan ); } } else { pMiter = Gia_ManMiter( pGia0, pGia1, 0, 1, 0, 0, fVerbose ); if ( pMiter ) { Cec_ParCec_t ParsCec, * pPars = &ParsCec; Cec_ManCecSetDefaultParams( pPars ); pPars->nBTLimit = nBTLimit; pPars->TimeLimit = nTimeLim; pPars->fVerbose = fVerbose; Status = Cec_ManVerify( pMiter, pPars ); if ( pPars->iOutFail >= 0 ) Abc_Print( 1, "Verification failed for at least one output (%d).\n", pPars->iOutFail ); Gia_ManStop( pMiter ); } } Gia_ManStop( pGia0 ); Gia_ManStop( pGia1 ); Gia_ManStop( pSpec ); return Status; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaTis.c000066400000000000000000000150201477524141600156510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaTis.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Technology independent synthesis.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaTis.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives GIA with MUXes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManTisDupMuxes( Gia_Man_t * p ) { Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pFan0, * pFan1, * pFanC; int i; assert( p->pMuxes == NULL ); ABC_FREE( p->pRefs ); Gia_ManCreateRefs( p ); // start the new manager pNew = Gia_ManStart( 5000 ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); // create constant Gia_ManConst0(p)->Value = 0; // create PIs Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi( pNew ); // create internal nodes Gia_ManHashStart( pNew ); Gia_ManForEachAnd( p, pObj, i ) { if ( !Gia_ObjIsMuxType(pObj) || (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) > 1 && Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) > 1) ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); else if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) pObj->Value = Gia_ManHashXorReal( pNew, Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)) ); else { pFanC = Gia_ObjRecognizeMux( pObj, &pFan1, &pFan0 ); pObj->Value = Gia_ManHashMuxReal( pNew, Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFanC)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)) ); } } Gia_ManHashStop( pNew ); // create ROs Gia_ManForEachCo( p, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); // perform cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManTisCollectMffc_rec( Gia_Man_t * p, int Id, Vec_Int_t * vMffc, Vec_Int_t * vLeaves ) { Gia_Obj_t * pObj; if ( Gia_ObjIsTravIdCurrentId(p, Id) ) return; Gia_ObjSetTravIdCurrentId(p, Id); if ( Gia_ObjRefNumId(p, Id) > 1 ) { Vec_IntPush( vLeaves, Id ); return; } pObj = Gia_ManObj( p, Id ); if ( Gia_ObjIsCi(pObj) ) { Vec_IntPush( vLeaves, Id ); return; } assert( Gia_ObjIsAnd(pObj) ); Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId0(pObj, Id), vMffc, vLeaves ); Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId1(pObj, Id), vMffc, vLeaves ); if ( Gia_ObjIsMuxId(p, Id) ) Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId2(p, Id), vMffc, vLeaves ); Vec_IntPush( vMffc, Id ); } void Gia_ManTisCollectMffc( Gia_Man_t * p, int Id, Vec_Int_t * vMffc, Vec_Int_t * vLeaves ) { Gia_Obj_t * pObj = Gia_ManObj( p, Id ); assert( Gia_ObjIsAnd(pObj) ); Vec_IntClear( vMffc ); Vec_IntClear( vLeaves ); Gia_ManIncrementTravId( p ); Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId0(pObj, Id), vMffc, vLeaves ); Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId1(pObj, Id), vMffc, vLeaves ); if ( Gia_ObjIsMuxId(p, Id) ) Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId2(p, Id), vMffc, vLeaves ); Vec_IntPush( vMffc, Id ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManTisPrintMffc( Gia_Man_t * p, int Id, Vec_Int_t * vMffc, Vec_Int_t * vLeaves ) { Gia_Obj_t * pObj; int i; printf( "MFFC %d has %d nodes and %d leaves:\n", Id, Vec_IntSize(vMffc), Vec_IntSize(vLeaves) ); Gia_ManForEachObjVecReverse( vMffc, p, pObj, i ) { printf( "Node %2d : ", Vec_IntSize(vMffc) - 1 - i ); Gia_ObjPrint( p, pObj ); } Gia_ManForEachObjVec( vLeaves, p, pObj, i ) { printf( "Leaf %2d : ", i ); Gia_ObjPrint( p, pObj ); } printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManTisTest( Gia_Man_t * pInit ) { Gia_Man_t * p; Gia_Obj_t * pObj; Vec_Int_t * vMffc, * vLeaves; int i; vMffc = Vec_IntAlloc( 10 ); vLeaves = Vec_IntAlloc( 10 ); p = Gia_ManTisDupMuxes( pInit ); Gia_ManCreateRefs( p ); Gia_ManForEachAnd( p, pObj, i ) { if ( Gia_ObjRefNumId(p, i) == 1 ) continue; Gia_ManTisCollectMffc( p, i, vMffc, vLeaves ); Gia_ManTisPrintMffc( p, i, vMffc, vLeaves ); } Gia_ManForEachCo( p, pObj, i ) { if ( Gia_ObjRefNumId(p, Gia_ObjFaninId0p(p, pObj)) > 1 ) continue; Gia_ManTisCollectMffc( p, Gia_ObjFaninId0p(p, pObj), vMffc, vLeaves ); Gia_ManTisPrintMffc( p, Gia_ObjFaninId0p(p, pObj), vMffc, vLeaves ); } Gia_ManStop( p ); Vec_IntFree( vMffc ); Vec_IntFree( vLeaves ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaTranStoch.c000066400000000000000000000310771477524141600170310ustar00rootroot00000000000000/**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 ); ABC_FREE( pBest->pName ); ABC_FREE( pBest->pSpec ); pBest->pName = Abc_UtilStrsav( pGia->pName ); pBest->pSpec = Abc_UtilStrsav( pGia->pSpec ); return pBest; } ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaTransduction.cpp000066400000000000000000000106651477524141600201410ustar00rootroot00000000000000/**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 abc-0.52/src/aig/gia/giaTransduction.h000066400000000000000000001570271477524141600176120ustar00rootroot00000000000000/**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 abc-0.52/src/aig/gia/giaTruth.c000066400000000000000000000705641477524141600162360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaTruth.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Truth table computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaTruth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/vec/vecMem.h" #include "misc/vec/vecWec.h" #include "misc/util/utilTruth.h" #include "opt/dau/dau.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static word s_Truth6[6] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000) }; static inline word * Gla_ObjTruthElem( Gia_Man_t * p, int i ) { return (word *)Vec_PtrEntry( p->vTtInputs, i ); } static inline word * Gla_ObjTruthNodeId( Gia_Man_t * p, int Id ) { return Vec_WrdArray(p->vTtMemory) + p->nTtWords * Id; } static inline word * Gla_ObjTruthNode( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Vec_WrdArray(p->vTtMemory) + p->nTtWords * Gia_ObjNum(p, pObj); } static inline word * Gla_ObjTruthFree1( Gia_Man_t * p ) { return Vec_WrdArray(p->vTtMemory) + Vec_WrdSize(p->vTtMemory) - p->nTtWords * 1; } static inline word * Gla_ObjTruthFree2( Gia_Man_t * p ) { return Vec_WrdArray(p->vTtMemory) + Vec_WrdSize(p->vTtMemory) - p->nTtWords * 2; } static inline word * Gla_ObjTruthConst0( Gia_Man_t * p, word * pDst ) { int w; for ( w = 0; w < p->nTtWords; w++ ) pDst[w] = 0; return pDst; } static inline word * Gla_ObjTruthDup( Gia_Man_t * p, word * pDst, word * pSrc, int c ) { int w; for ( w = 0; w < p->nTtWords; w++ ) pDst[w] = c ? ~pSrc[w] : pSrc[w]; return pDst; } //////////////////////////////////////////////////////////////////////// /// 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word Gia_LutComputeTruth6_rec( Gia_Man_t * p, int iNode, Vec_Wrd_t * vTruths ) { Gia_Obj_t * pObj; word Truth0, Truth1; if ( Gia_ObjIsTravIdCurrentId(p, iNode) ) return Vec_WrdEntry(vTruths, iNode); Gia_ObjSetTravIdCurrentId(p, iNode); pObj = Gia_ManObj( p, iNode ); assert( Gia_ObjIsAnd(pObj) ); Truth0 = Gia_LutComputeTruth6_rec( p, Gia_ObjFaninId0p(p, pObj), vTruths ); Truth1 = Gia_LutComputeTruth6_rec( p, Gia_ObjFaninId1p(p, pObj), vTruths ); if ( Gia_ObjFaninC0(pObj) ) Truth0 = ~Truth0; if ( Gia_ObjFaninC1(pObj) ) Truth1 = ~Truth1; Vec_WrdWriteEntry( vTruths, iNode, Truth0 & Truth1 ); return Truth0 & Truth1; } word Gia_LutComputeTruth6( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTruths ) { int k, iFan; assert( Gia_ObjIsLut(p, iObj) ); Gia_ManIncrementTravId( p ); Gia_LutForEachFanin( p, iObj, iFan, k ) { Vec_WrdWriteEntry( vTruths, iFan, s_Truths6[k] ); Gia_ObjSetTravIdCurrentId( p, iFan ); } return Gia_LutComputeTruth6_rec( p, iObj, vTruths ); } /**Function************************************************************* Synopsis [Computes truth table of a 6-LUT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ObjComputeTruthTable6Lut_rec( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTemp ) { word uTruth0, uTruth1; Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) return; Gia_ObjSetTravIdCurrentId(p, iObj); assert( Gia_ObjIsAnd(pObj) ); Gia_ObjComputeTruthTable6Lut_rec( p, Gia_ObjFaninId0p(p, pObj), vTemp ); Gia_ObjComputeTruthTable6Lut_rec( p, Gia_ObjFaninId1p(p, pObj), vTemp ); uTruth0 = Vec_WrdEntry( vTemp, Gia_ObjFaninId0p(p, pObj) ); uTruth0 = Gia_ObjFaninC0(pObj) ? ~uTruth0 : uTruth0; uTruth1 = Vec_WrdEntry( vTemp, Gia_ObjFaninId1p(p, pObj) ); uTruth1 = Gia_ObjFaninC1(pObj) ? ~uTruth1 : uTruth1; Vec_WrdWriteEntry( vTemp, iObj, uTruth0 & uTruth1 ); } word Gia_ObjComputeTruthTable6Lut( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTemp ) { int i, Fanin; assert( Vec_WrdSize(vTemp) == Gia_ManObjNum(p) ); assert( Gia_ObjIsLut(p, iObj) ); Gia_ManIncrementTravId( p ); Gia_LutForEachFanin( p, iObj, Fanin, i ) { Gia_ObjSetTravIdCurrentId( p, Fanin ); Vec_WrdWriteEntry( vTemp, Fanin, s_Truth6[i] ); } assert( i <= 6 ); Gia_ObjComputeTruthTable6Lut_rec( p, iObj, vTemp ); return Vec_WrdEntry( vTemp, iObj ); } /**Function************************************************************* Synopsis [Computes truth table up to 6 inputs in terms of CIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word Gia_ObjComputeTruth6( Gia_Man_t * p, int iObj, Vec_Int_t * vSupp, Vec_Wrd_t * vTemp ) { int i, Fanin; assert( Vec_WrdSize(vTemp) == Gia_ManObjNum(p) ); assert( Vec_IntSize(vSupp) <= 6 ); Gia_ManIncrementTravId( p ); Vec_IntForEachEntry( vSupp, Fanin, i ) { Gia_ObjSetTravIdCurrentId( p, Fanin ); Vec_WrdWriteEntry( vTemp, Fanin, s_Truth6[i] ); } Gia_ObjComputeTruthTable6Lut_rec( p, iObj, vTemp ); return Vec_WrdEntry( vTemp, iObj ); } void Gia_ObjComputeTruth6CisSupport_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vSupp ) { Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) return; Gia_ObjSetTravIdCurrentId(p, iObj); if ( Gia_ObjIsCi(pObj) ) { Vec_IntPushOrder( vSupp, iObj ); return; } assert( Gia_ObjIsAnd(pObj) ); Gia_ObjComputeTruth6CisSupport_rec( p, Gia_ObjFaninId0p(p, pObj), vSupp ); Gia_ObjComputeTruth6CisSupport_rec( p, Gia_ObjFaninId1p(p, pObj), vSupp ); } word Gia_ObjComputeTruth6Cis( Gia_Man_t * p, int iLit, Vec_Int_t * vSupp, Vec_Wrd_t * vTemp ) { int iObj = Abc_Lit2Var(iLit); Vec_IntClear( vSupp ); if ( !iObj ) return Abc_LitIsCompl(iLit) ? ~(word)0 : (word)0; Gia_ManIncrementTravId( p ); Gia_ObjComputeTruth6CisSupport_rec( p, iObj, vSupp ); if ( Vec_IntSize(vSupp) > 6 ) return 0; Gia_ObjComputeTruth6( p, iObj, vSupp, vTemp ); return Abc_LitIsCompl(iLit) ? ~Vec_WrdEntry(vTemp, iObj) : Vec_WrdEntry(vTemp, iObj); } /**Function************************************************************* Synopsis [Computes truth table up to 6 inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ObjComputeTruthTable6_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Wrd_t * vTruths ) { word uTruth0, uTruth1; if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return; Gia_ObjSetTravIdCurrent(p, pObj); assert( !pObj->fMark0 ); assert( Gia_ObjIsAnd(pObj) ); Gia_ObjComputeTruthTable6_rec( p, Gia_ObjFanin0(pObj), vTruths ); Gia_ObjComputeTruthTable6_rec( p, Gia_ObjFanin1(pObj), vTruths ); uTruth0 = Vec_WrdEntry( vTruths, Gia_ObjFanin0(pObj)->Value ); uTruth0 = Gia_ObjFaninC0(pObj) ? ~uTruth0 : uTruth0; uTruth1 = Vec_WrdEntry( vTruths, Gia_ObjFanin1(pObj)->Value ); uTruth1 = Gia_ObjFaninC1(pObj) ? ~uTruth1 : uTruth1; pObj->Value = Vec_WrdSize(vTruths); Vec_WrdPush( vTruths, uTruth0 & uTruth1 ); } word Gia_ObjComputeTruthTable6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp, Vec_Wrd_t * vTruths ) { Gia_Obj_t * pLeaf; int i; assert( Vec_IntSize(vSupp) <= 6 ); assert( Gia_ObjIsAnd(pObj) ); assert( !pObj->fMark0 ); Vec_WrdClear( vTruths ); Gia_ManIncrementTravId( p ); Gia_ManForEachObjVec( vSupp, p, pLeaf, i ) { assert( pLeaf->fMark0 || Gia_ObjIsRo(p, pLeaf) ); pLeaf->Value = Vec_WrdSize(vTruths); Vec_WrdPush( vTruths, s_Truth6[i] ); Gia_ObjSetTravIdCurrent(p, pLeaf); } Gia_ObjComputeTruthTable6_rec( p, pObj, vTruths ); return Vec_WrdEntryLast( vTruths ); } /**Function************************************************************* Synopsis [Collects internal nodes reachable from the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ObjCollectInternal_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( !Gia_ObjIsAnd(pObj) ) return; if ( pObj->fMark0 ) return; pObj->fMark0 = 1; Gia_ObjCollectInternal_rec( p, Gia_ObjFanin0(pObj) ); Gia_ObjCollectInternal_rec( p, Gia_ObjFanin1(pObj) ); Gia_ObjSetNum( p, pObj, Vec_IntSize(p->vTtNodes) ); Vec_IntPush( p->vTtNodes, Gia_ObjId(p, pObj) ); } void Gia_ObjCollectInternal( Gia_Man_t * p, Gia_Obj_t * pObj ) { Vec_IntClear( p->vTtNodes ); Gia_ObjCollectInternal_rec( p, pObj ); } /**Function************************************************************* Synopsis [Computing the truth table for GIA object.] Description [The truth table should be used by the calling application (or saved into the user's storage) before this procedure is called again.] SideEffects [] SeeAlso [] ***********************************************************************/ word * Gia_ObjComputeTruthTable( Gia_Man_t * p, Gia_Obj_t * pObj ) { Gia_Obj_t * pTemp, * pRoot; word * pTruth, * pTruthL, * pTruth0, * pTruth1; int i; if ( p->vTtMemory == NULL ) { p->nTtVars = Gia_ManPiNum( p ); p->nTtWords = Abc_Truth6WordNum( p->nTtVars ); p->vTtNums = Vec_IntStart( Gia_ManObjNum(p) + 1000 ); p->vTtNodes = Vec_IntAlloc( 256 ); p->vTtInputs = Vec_PtrAllocTruthTables( Abc_MaxInt(6, p->nTtVars) ); p->vTtMemory = Vec_WrdStart( p->nTtWords * 256 ); } else { // make sure the number of primary inputs did not change // since the truth table computation storage was prepared assert( p->nTtVars == Gia_ManPiNum(p) ); } // extend ID numbers if ( Vec_IntSize(p->vTtNums) < Gia_ManObjNum(p) ) Vec_IntFillExtra( p->vTtNums, Gia_ManObjNum(p), 0 ); // collect internal nodes pRoot = Gia_ObjIsCo(pObj) ? Gia_ObjFanin0(pObj) : pObj; Gia_ObjCollectInternal( p, pRoot ); // extend TT storage if ( Vec_WrdSize(p->vTtMemory) < p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2) ) Vec_WrdFillExtra( p->vTtMemory, p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2), 0 ); // compute the truth table for internal nodes Gia_ManForEachObjVec( p->vTtNodes, p, pTemp, i ) { pTemp->fMark0 = 0; // unmark nodes marked by Gia_ObjCollectInternal() pTruth = Gla_ObjTruthNode(p, pTemp); pTruthL = pTruth + p->nTtWords; pTruth0 = Gia_ObjIsAnd(Gia_ObjFanin0(pTemp)) ? Gla_ObjTruthNode(p, Gia_ObjFanin0(pTemp)) : Gla_ObjTruthElem(p, Gia_ObjCioId(Gia_ObjFanin0(pTemp)) ); pTruth1 = Gia_ObjIsAnd(Gia_ObjFanin1(pTemp)) ? Gla_ObjTruthNode(p, Gia_ObjFanin1(pTemp)) : Gla_ObjTruthElem(p, Gia_ObjCioId(Gia_ObjFanin1(pTemp)) ); if ( Gia_ObjFaninC0(pTemp) ) { if ( Gia_ObjFaninC1(pTemp) ) while ( pTruth < pTruthL ) *pTruth++ = ~*pTruth0++ & ~*pTruth1++; else while ( pTruth < pTruthL ) *pTruth++ = ~*pTruth0++ & *pTruth1++; } else { if ( Gia_ObjFaninC1(pTemp) ) while ( pTruth < pTruthL ) *pTruth++ = *pTruth0++ & ~*pTruth1++; else while ( pTruth < pTruthL ) *pTruth++ = *pTruth0++ & *pTruth1++; } } // compute the final table if ( Gia_ObjIsConst0(pRoot) ) pTruth = Gla_ObjTruthConst0( p, Gla_ObjTruthFree1(p) ); else if ( Gia_ObjIsPi(p, pRoot) ) pTruth = Gla_ObjTruthElem( p, Gia_ObjCioId(pRoot) ); else if ( Gia_ObjIsAnd(pRoot) ) pTruth = Gla_ObjTruthNode( p, pRoot ); else pTruth = NULL; return Gla_ObjTruthDup( p, Gla_ObjTruthFree2(p), pTruth, Gia_ObjIsCo(pObj) && Gia_ObjFaninC0(pObj) ); } /**Function************************************************************* Synopsis [Testing truth table computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ObjComputeTruthTableTest( Gia_Man_t * p ) { Gia_Obj_t * pObj; unsigned * pTruth; abctime clk = Abc_Clock(); int i; Gia_ManForEachPo( p, pObj, i ) { pTruth = (unsigned *)Gia_ObjComputeTruthTable( p, pObj ); // Extra_PrintHex( stdout, pTruth, Gia_ManPiNum(p) ); printf( "\n" ); } Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ObjComputeTruthTableStart( Gia_Man_t * p, int nVarsMax ) { assert( p->vTtMemory == NULL ); p->nTtVars = nVarsMax; p->nTtWords = Abc_Truth6WordNum( p->nTtVars ); p->vTtNodes = Vec_IntAlloc( 256 ); p->vTtInputs = Vec_PtrAllocTruthTables( Abc_MaxInt(6, p->nTtVars) ); p->vTtMemory = Vec_WrdStart( p->nTtWords * 64 ); p->vTtNums = Vec_IntAlloc( Gia_ManObjNum(p) + 1000 ); Vec_IntFill( p->vTtNums, Vec_IntCap(p->vTtNums), -ABC_INFINITY ); if ( nVarsMax >= 6 ) { word * pTruth; int i; Vec_PtrForEachEntry( word *, p->vTtInputs, pTruth, i ) Abc_TtFlipVar5( pTruth, nVarsMax ); } } void Gia_ObjComputeTruthTableStop( Gia_Man_t * p ) { p->nTtVars = 0; p->nTtWords = 0; Vec_IntFreeP( &p->vTtNums ); Vec_IntFreeP( &p->vTtNodes ); Vec_PtrFreeP( &p->vTtInputs ); Vec_WrdFreeP( &p->vTtMemory ); } /**Function************************************************************* Synopsis [Collects internal nodes reachable from the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ObjCollectInternalCut_rec( Gia_Man_t * p, int iObj ) { if ( Gia_ObjHasNumId(p, iObj) ) return; assert( Gia_ObjIsAnd(Gia_ManObj(p, iObj)) ); Gia_ObjCollectInternalCut_rec( p, Gia_ObjFaninId0(Gia_ManObj(p, iObj), iObj) ); Gia_ObjCollectInternalCut_rec( p, Gia_ObjFaninId1(Gia_ManObj(p, iObj), iObj) ); Gia_ObjSetNumId( p, iObj, Vec_IntSize(p->vTtNodes) ); Vec_IntPush( p->vTtNodes, iObj ); } void Gia_ObjCollectInternalCut( Gia_Man_t * p, int iRoot, Vec_Int_t * vLeaves ) { int i, iObj; assert( !Gia_ObjHasNumId(p, iRoot) ); assert( Gia_ObjIsAnd(Gia_ManObj(p, iRoot)) ); Vec_IntForEachEntry( vLeaves, iObj, i ) { if ( Gia_ObjHasNumId(p, iObj) ) // if cuts have repeated variables, skip continue; assert( !Gia_ObjHasNumId(p, iObj) ); Gia_ObjSetNumId( p, iObj, -i ); } assert( !Gia_ObjHasNumId(p, iRoot) ); // the root cannot be one of the leaves Vec_IntClear( p->vTtNodes ); Vec_IntPush( p->vTtNodes, -1 ); Gia_ObjCollectInternalCut_rec( p, iRoot ); } /**Function************************************************************* Synopsis [Computes the truth table of pRoot in terms of leaves.] Description [The root cannot be one of the leaves.] SideEffects [] SeeAlso [] ***********************************************************************/ word * Gia_ObjComputeTruthTableCut( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves ) { Gia_Obj_t * pTemp; word * pTruth, * pTruthL, * pTruth0, * pTruth1; 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 ); // collect internal nodes Gia_ObjCollectInternalCut( p, Gia_ObjId(p, pRoot), vLeaves ); // extend TT storage if ( Vec_WrdSize(p->vTtMemory) < p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2) ) Vec_WrdFillExtra( p->vTtMemory, p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2), 0 ); // compute the truth table for internal nodes Vec_IntForEachEntryStart( p->vTtNodes, iObj, i, 1 ) { assert( i == Gia_ObjNumId(p, iObj) ); pTemp = Gia_ManObj( p, iObj ); pTruth = Gla_ObjTruthNodeId( p, i ); pTruthL = pTruth + p->nTtWords; Id0 = Gia_ObjNumId( p, Gia_ObjFaninId0(pTemp, iObj) ); Id1 = Gia_ObjNumId( p, Gia_ObjFaninId1(pTemp, iObj) ); pTruth0 = (Id0 > 0) ? Gla_ObjTruthNodeId(p, Id0) : Gla_ObjTruthElem(p, -Id0); pTruth1 = (Id1 > 0) ? Gla_ObjTruthNodeId(p, Id1) : Gla_ObjTruthElem(p, -Id1); if ( Gia_ObjFaninC0(pTemp) ) { if ( Gia_ObjFaninC1(pTemp) ) while ( pTruth < pTruthL ) *pTruth++ = ~*pTruth0++ & ~*pTruth1++; else while ( pTruth < pTruthL ) *pTruth++ = ~*pTruth0++ & *pTruth1++; } else { if ( Gia_ObjFaninC1(pTemp) ) while ( pTruth < pTruthL ) *pTruth++ = *pTruth0++ & ~*pTruth1++; else while ( pTruth < pTruthL ) *pTruth++ = *pTruth0++ & *pTruth1++; } } pTruth = Gla_ObjTruthNode( p, pRoot ); // unmark leaves marked by Gia_ObjCollectInternal() Vec_IntForEachEntry( vLeaves, iObj, i ) Gia_ObjResetNumId( p, iObj ); Vec_IntForEachEntryStart( p->vTtNodes, iObj, i, 1 ) Gia_ObjResetNumId( p, iObj ); return pTruth; } /**Function************************************************************* Synopsis [Reduces GIA to contain isomorphic POs.] Description [The root cannot be one of the leaves.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManIsoNpnReduce( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, int fVerbose ) { char pCanonPerm[16]; int i, iObj, uCanonPhase, nVars, lastId, truthId; int IndexCon = -1, IndexVar = -1; Vec_Wec_t * vPosEquivs = Vec_WecAlloc( 100 ); word * pTruth; Gia_Obj_t * pObj; Vec_Mem_t * vTtMem[17]; // truth table memory and hash table Gia_Man_t * pNew = NULL; Vec_Int_t * vLeaves = Vec_IntAlloc( 16 ); Vec_Int_t * vFirsts; Vec_Int_t * vTt2Class[17]; for ( i = 0; i < 17; i++ ) { vTtMem[i] = Vec_MemAlloc( Abc_TtWordNum(i), 10 ); Vec_MemHashAlloc( vTtMem[i], 1000 ); vTt2Class[i] = Vec_IntStartFull( Gia_ManCoNum(p)+1 ); } Gia_ObjComputeTruthTableStart( p, 16 ); Gia_ManForEachPo( p, pObj, i ) { iObj = Gia_ObjId(p, pObj); Gia_ManCollectCis( p, &iObj, 1, vLeaves ); if ( Vec_IntSize(vLeaves) > 16 ) { Vec_IntPush( Vec_WecPushLevel(vPosEquivs), i ); continue; } pObj = Gia_ObjFanin0(pObj); if ( Gia_ObjIsConst0(pObj) ) { if ( IndexCon == -1 ) { IndexCon = Vec_WecSize(vPosEquivs); Vec_WecPushLevel(vPosEquivs); } Vec_WecPush( vPosEquivs, IndexCon, i ); continue; } if ( Gia_ObjIsCi(pObj) ) { if ( IndexVar == -1 ) { IndexVar = Vec_WecSize(vPosEquivs); Vec_WecPushLevel(vPosEquivs); } Vec_WecPush( vPosEquivs, IndexVar, i ); continue; } assert( Gia_ObjIsAnd(pObj) ); pTruth = Gia_ObjComputeTruthTableCut( p, pObj, vLeaves ); Abc_TtMinimumBase( pTruth, NULL, Vec_IntSize(vLeaves), &nVars ); if ( nVars == 0 ) { if ( IndexCon == -1 ) { IndexCon = Vec_WecSize(vPosEquivs); Vec_WecPushLevel(vPosEquivs); } Vec_WecPush( vPosEquivs, IndexCon, i ); continue; } if ( nVars == 1 ) { if ( IndexVar == -1 ) { IndexVar = Vec_WecSize(vPosEquivs); Vec_WecPushLevel(vPosEquivs); } Vec_WecPush( vPosEquivs, IndexVar, i ); continue; } uCanonPhase = Abc_TtCanonicize( pTruth, nVars, pCanonPerm ); lastId = Vec_MemEntryNum( vTtMem[nVars] ); truthId = Vec_MemHashInsert( vTtMem[nVars], pTruth ); if ( lastId != Vec_MemEntryNum( vTtMem[nVars] ) ) // new one { assert( Vec_IntEntry(vTt2Class[nVars], truthId) == -1 ); Vec_IntWriteEntry( vTt2Class[nVars], truthId, Vec_WecSize(vPosEquivs) ); Vec_WecPushLevel(vPosEquivs); } assert( Vec_IntEntry(vTt2Class[nVars], truthId) >= 0 ); Vec_WecPush( vPosEquivs, Vec_IntEntry(vTt2Class[nVars], truthId), i ); } Gia_ObjComputeTruthTableStop( p ); Vec_IntFree( vLeaves ); for ( i = 0; i < 17; i++ ) { Vec_MemHashFree( vTtMem[i] ); Vec_MemFree( vTtMem[i] ); Vec_IntFree( vTt2Class[i] ); } // find the first outputs and derive GIA vFirsts = Vec_WecCollectFirsts( vPosEquivs ); pNew = Gia_ManDupCones( p, Vec_IntArray(vFirsts), Vec_IntSize(vFirsts), 0 ); Vec_IntFree( vFirsts ); // report and return if ( fVerbose ) { printf( "Nontrivial classes:\n" ); Vec_WecPrint( vPosEquivs, 1 ); } if ( pvPosEquivs ) *pvPosEquivs = Vec_WecConvertToVecPtr( vPosEquivs ); Vec_WecFree( vPosEquivs ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaTsim.c000066400000000000000000000565601477524141600160440ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaTsim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Ternary simulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaTsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Gia_ManTerSimInfoGet( unsigned * pInfo, int i ) { return 3 & (pInfo[i >> 4] >> ((i & 15) << 1)); } static inline void Gia_ManTerSimInfoSet( unsigned * pInfo, int i, int Value ) { assert( Value >= GIA_ZER && Value <= GIA_UND ); Value ^= Gia_ManTerSimInfoGet( pInfo, i ); pInfo[i >> 4] ^= (Value << ((i & 15) << 1)); } static inline unsigned * Gia_ManTerStateNext( unsigned * pState, int nWords ) { return *((unsigned **)(pState + nWords)); } static inline void Gia_ManTerStateSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; } // ternary simulation manager typedef struct Gia_ManTer_t_ Gia_ManTer_t; struct Gia_ManTer_t_ { Gia_Man_t * pAig; int nIters; int nStateWords; Vec_Ptr_t * vStates; Vec_Ptr_t * vFlops; Vec_Int_t * vRetired; // retired registers char * pRetired; // retired registers int * pCount0; int * pCountX; // hash table for states int nBins; unsigned ** pBins; // simulation information unsigned * pDataSim; // simulation data unsigned * pDataSimCis; // simulation data for CIs unsigned * pDataSimCos; // simulation data for COs }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates fast simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_ManTer_t * Gia_ManTerCreate( Gia_Man_t * pAig ) { Gia_ManTer_t * p; p = ABC_CALLOC( Gia_ManTer_t, 1 ); p->pAig = Gia_ManFront( pAig ); p->nIters = 300; p->pDataSim = ABC_ALLOC( unsigned, Abc_BitWordNum(2*p->pAig->nFront) ); p->pDataSimCis = ABC_ALLOC( unsigned, Abc_BitWordNum(2*Gia_ManCiNum(p->pAig)) ); p->pDataSimCos = ABC_ALLOC( unsigned, Abc_BitWordNum(2*Gia_ManCoNum(p->pAig)) ); // allocate storage for terminary states p->nStateWords = Abc_BitWordNum( 2*Gia_ManRegNum(pAig) ); p->vStates = Vec_PtrAlloc( 1000 ); p->pCount0 = ABC_CALLOC( int, Gia_ManRegNum(pAig) ); p->pCountX = ABC_CALLOC( int, Gia_ManRegNum(pAig) ); p->nBins = Abc_PrimeCudd( 500 ); p->pBins = ABC_CALLOC( unsigned *, p->nBins ); p->vRetired = Vec_IntAlloc( 100 ); p->pRetired = ABC_CALLOC( char, Gia_ManRegNum(pAig) ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManTerStatesFree( Vec_Ptr_t * vStates ) { unsigned * pTemp; int i; Vec_PtrForEachEntry( unsigned *, vStates, pTemp, i ) ABC_FREE( pTemp ); Vec_PtrFree( vStates ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManTerDelete( Gia_ManTer_t * p ) { if ( p->vStates ) Gia_ManTerStatesFree( p->vStates ); if ( p->vFlops ) Gia_ManTerStatesFree( p->vFlops ); Gia_ManStop( p->pAig ); Vec_IntFree( p->vRetired ); ABC_FREE( p->pRetired ); ABC_FREE( p->pCount0 ); ABC_FREE( p->pCountX ); ABC_FREE( p->pBins ); ABC_FREE( p->pDataSim ); ABC_FREE( p->pDataSimCis ); ABC_FREE( p->pDataSimCos ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManTerSimulateCi( Gia_ManTer_t * p, Gia_Obj_t * pObj, int iCi ) { Gia_ManTerSimInfoSet( p->pDataSim, Gia_ObjValue(pObj), Gia_ManTerSimInfoGet(p->pDataSimCis, iCi) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManTerSimulateCo( Gia_ManTer_t * p, int iCo, Gia_Obj_t * pObj ) { int Value = Gia_ManTerSimInfoGet( p->pDataSim, Gia_ObjDiff0(pObj) ); Gia_ManTerSimInfoSet( p->pDataSimCos, iCo, Gia_XsimNotCond( Value, Gia_ObjFaninC0(pObj) ) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManTerSimulateNode( Gia_ManTer_t * p, Gia_Obj_t * pObj ) { int Value0 = Gia_ManTerSimInfoGet( p->pDataSim, Gia_ObjDiff0(pObj) ); int Value1 = Gia_ManTerSimInfoGet( p->pDataSim, Gia_ObjDiff1(pObj) ); Gia_ManTerSimInfoSet( p->pDataSim, Gia_ObjValue(pObj), Gia_XsimAndCond( Value0, Gia_ObjFaninC0(pObj), Value1, Gia_ObjFaninC1(pObj) ) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManTerSimInfoInit( Gia_ManTer_t * p ) { int i = 0; for ( ; i < Gia_ManPiNum(p->pAig); i++ ) Gia_ManTerSimInfoSet( p->pDataSimCis, i, GIA_UND ); for ( ; i < Gia_ManCiNum(p->pAig); i++ ) Gia_ManTerSimInfoSet( p->pDataSimCis, i, GIA_ZER ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManTerSimInfoTransfer( Gia_ManTer_t * p ) { int i = 0; for ( ; i < Gia_ManPiNum(p->pAig); i++ ) Gia_ManTerSimInfoSet( p->pDataSimCis, i, GIA_UND ); for ( ; i < Gia_ManCiNum(p->pAig); i++ ) Gia_ManTerSimInfoSet( p->pDataSimCis, i, Gia_ManTerSimInfoGet( p->pDataSimCos, Gia_ManCoNum(p->pAig)-Gia_ManCiNum(p->pAig)+i ) ); } /**Function************************************************************* Synopsis [Computes hash value of the node using its simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManTerStateHash( unsigned * pState, int nWords, int nTableSize ) { static int s_FPrimes[128] = { 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 }; unsigned uHash; int i; uHash = 0; for ( i = 0; i < nWords; i++ ) uHash ^= pState[i] * s_FPrimes[i & 0x7F]; return uHash % nTableSize; } /**Function************************************************************* Synopsis [Inserts value into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Gia_ManTerStateLookup( unsigned * pState, int nWords, unsigned ** pBins, int nBins ) { unsigned * pEntry; int Hash = Gia_ManTerStateHash( pState, nWords, nBins ); for ( pEntry = pBins[Hash]; pEntry; pEntry = Gia_ManTerStateNext(pEntry, nWords) ) if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) ) return pEntry; return NULL; } /**Function************************************************************* Synopsis [Inserts value into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManTerStateInsert( unsigned * pState, int nWords, unsigned ** pBins, int nBins ) { int Hash = Gia_ManTerStateHash( pState, nWords, nBins ); assert( !Gia_ManTerStateLookup( pState, nWords, pBins, nBins ) ); Gia_ManTerStateSetNext( pState, nWords, pBins[Hash] ); pBins[Hash] = pState; } /**Function************************************************************* Synopsis [Allocs new ternary state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Gia_ManTerStateAlloc( int nWords ) { return (unsigned *)ABC_CALLOC( char, sizeof(unsigned) * nWords + sizeof(unsigned *) ); } /**Function************************************************************* Synopsis [Creates new ternary state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Gia_ManTerStateCreate( Gia_ManTer_t * p ) { int i, Value, nPis = Gia_ManPiNum(p->pAig); unsigned * pRes = Gia_ManTerStateAlloc( p->nStateWords ); for ( i = nPis; i < Gia_ManCiNum(p->pAig); i++ ) { Value = Gia_ManTerSimInfoGet( p->pDataSimCis, i ); Gia_ManTerSimInfoSet( pRes, i-nPis, Value ); if ( Value == GIA_ZER ) p->pCount0[i-nPis]++; if ( Value == GIA_UND ) p->pCountX[i-nPis]++; } Vec_PtrPush( p->vStates, pRes ); return pRes; } /**Function************************************************************* Synopsis [Performs one round of ternary simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManTerSimulateRound( Gia_ManTer_t * p ) { Gia_Obj_t * pObj; int i, iCis = 0, iCos = 0; assert( p->pAig->nFront > 0 ); assert( Gia_ManConst0(p->pAig)->Value == 0 ); Gia_ManTerSimInfoSet( p->pDataSim, 0, GIA_ZER ); Gia_ManForEachObj1( p->pAig, pObj, i ) { if ( Gia_ObjIsAndOrConst0(pObj) ) { assert( Gia_ObjValue(pObj) < p->pAig->nFront ); Gia_ManTerSimulateNode( p, pObj ); } else if ( Gia_ObjIsCi(pObj) ) { assert( Gia_ObjValue(pObj) < p->pAig->nFront ); Gia_ManTerSimulateCi( p, pObj, iCis++ ); } else // if ( Gia_ObjIsCo(pObj) ) { assert( Gia_ObjValue(pObj) == GIA_NONE ); Gia_ManTerSimulateCo( p, iCos++, pObj ); } } assert( Gia_ManCiNum(p->pAig) == iCis ); assert( Gia_ManCoNum(p->pAig) == iCos ); } /**Function************************************************************* Synopsis [Retires a set of registers to speed up convergence.] Description [Retire all non-ternary registers which has max number of ternary values so far.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManTerRetire2( Gia_ManTer_t * p, unsigned * pState ) { int i, Entry, iMaxTerValue = -1; // find non-retired register with this value for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) if ( Gia_ManTerSimInfoGet( pState, i ) != GIA_UND && !p->pRetired[i] && iMaxTerValue < p->pCountX[i] ) iMaxTerValue = p->pCountX[i]; assert( iMaxTerValue >= 0 ); // retire the first registers with this value for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) if ( Gia_ManTerSimInfoGet( pState, i ) != GIA_UND && !p->pRetired[i] && iMaxTerValue == p->pCountX[i] ) { assert( p->pRetired[i] == 0 ); p->pRetired[i] = 1; Vec_IntPush( p->vRetired, i ); if ( iMaxTerValue == 0 ) break; } // update all the retired registers Vec_IntForEachEntry( p->vRetired, Entry, i ) Gia_ManTerSimInfoSet( p->pDataSimCis, Gia_ManPiNum(p->pAig)+Entry, GIA_UND ); return Vec_IntSize(p->vRetired); } /**Function************************************************************* Synopsis [Retires a set of registers to speed up convergence.] Description [Retire all non-ternary registers which has max number of ternary values so far.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManTerRetire( Gia_ManTer_t * p, unsigned * pThis, unsigned * pPrev ) { int i, Entry; // find registers whose value has changed Vec_IntClear( p->vRetired ); for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) if ( Gia_ManTerSimInfoGet( pThis, i ) != Gia_ManTerSimInfoGet( pPrev, i ) ) Vec_IntPush( p->vRetired, i ); // set all of them to zero Vec_IntForEachEntry( p->vRetired, Entry, i ) Gia_ManTerSimInfoSet( p->pDataSimCis, Gia_ManPiNum(p->pAig)+Entry, GIA_UND ); return Vec_IntSize(p->vRetired); } /**Function************************************************************* Synopsis [Inserts value into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManTerStatePrint( unsigned * pState, int nRegs, int iNum ) { int i, nZeros = 0, nOnes = 0, nDcs = 0; printf( " %4d : ", iNum ); for ( i = 0; i < nRegs; i++ ) { if ( Gia_ManTerSimInfoGet(pState, i) == GIA_ZER ) printf( "0" ), nZeros++; else if ( Gia_ManTerSimInfoGet(pState, i) == GIA_ONE ) printf( "1" ), nOnes++; else if ( Gia_ManTerSimInfoGet(pState, i) == GIA_UND ) printf( "x" ), nDcs++; else assert( 0 ); } printf( " (0=%4d, 1=%4d, x=%4d)\n", nZeros, nOnes, nDcs ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManTerAnalyze2( Vec_Ptr_t * vStates, int nRegs ) { unsigned * pTemp, * pStates = (unsigned *)Vec_PtrPop( vStates ); int i, w, nZeros, nConsts, nStateWords; // detect constant zero registers nStateWords = Abc_BitWordNum( 2*nRegs ); memset( pStates, 0, sizeof(int) * nStateWords ); Vec_PtrForEachEntry( unsigned *, vStates, pTemp, i ) for ( w = 0; w < nStateWords; w++ ) pStates[w] |= pTemp[w]; // count the number of zeros nZeros = 0; for ( i = 0; i < nRegs; i++ ) if ( Gia_ManTerSimInfoGet(pStates, i) == GIA_ZER ) nZeros++; printf( "Found %d constant registers.\n", nZeros ); // detect non-ternary registers memset( pStates, 0, sizeof(int) * nStateWords ); Vec_PtrForEachEntry( unsigned *, vStates, pTemp, i ) for ( w = 0; w < nStateWords; w++ ) pStates[w] |= (~(pTemp[w] ^ (pTemp[w] >> 1)) & 0x55555555); // count the nonternary registers nConsts = 0; for ( i = 0; i < nRegs; i++ ) if ( Gia_ManTerSimInfoGet(pStates, i) == 0 ) nConsts++; printf( "Found %d non-ternary registers.\n", nConsts ); // return the state back Vec_PtrPush( vStates, pStates ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManTerAnalyze( Gia_ManTer_t * p ) { int i, nZeros = 0, nConsts = 0; for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) if ( p->pCount0[i] == Vec_PtrSize(p->vStates) ) nZeros++; else if ( p->pCountX[i] == 0 ) nConsts++; // printf( "Found %d constant registers.\n", nZeros ); // printf( "Found %d non-ternary registers.\n", nConsts ); } /**Function************************************************************* Synopsis [Transposes state vector for non-ternary registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Gia_ManTerTranspose( Gia_ManTer_t * p ) { Vec_Ptr_t * vFlops; unsigned * pState, * pFlop; int i, k, nFlopWords; vFlops = Vec_PtrAlloc( 100 ); nFlopWords = Abc_BitWordNum( 2*Vec_PtrSize(p->vStates) ); for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) { if ( p->pCount0[i] == Vec_PtrSize(p->vStates) ) continue; if ( p->pCountX[i] > 0 ) continue; pFlop = Gia_ManTerStateAlloc( nFlopWords ); Vec_PtrPush( vFlops, pFlop ); Vec_PtrForEachEntry( unsigned *, p->vStates, pState, k ) Gia_ManTerSimInfoSet( pFlop, k, Gia_ManTerSimInfoGet(pState, i) ); //Gia_ManTerStatePrint( pFlop, Vec_PtrSize(p->vStates), i ); } return vFlops; } /**Function************************************************************* Synopsis [Transposes state vector for non-ternary registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFindEqualFlop( Vec_Ptr_t * vFlops, int iFlop, int nFlopWords ) { unsigned * pFlop, * pTemp; int i; pFlop = (unsigned *)Vec_PtrEntry( vFlops, iFlop ); Vec_PtrForEachEntryStop( unsigned *, vFlops, pTemp, i, iFlop ) if ( !memcmp( pTemp, pFlop, sizeof(unsigned) * nFlopWords ) ) return i; return -1; } /**Function************************************************************* Synopsis [Creates map of registers to replace.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Gia_ManTerCreateMap( Gia_ManTer_t * p, int fVerbose ) { int * pCi2Lit; Gia_Obj_t * pObj; Vec_Int_t * vMapKtoI; int i, iRepr, nFlopWords, Counter0 = 0, CounterE = 0; nFlopWords = Abc_BitWordNum( 2*Vec_PtrSize(p->vStates) ); p->vFlops = Gia_ManTerTranspose( p ); pCi2Lit = ABC_FALLOC( int, Gia_ManCiNum(p->pAig) ); vMapKtoI = Vec_IntAlloc( 100 ); for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) if ( p->pCount0[i] == Vec_PtrSize(p->vStates) ) pCi2Lit[Gia_ManPiNum(p->pAig)+i] = 0, Counter0++; else if ( p->pCountX[i] == 0 ) { iRepr = Gia_ManFindEqualFlop( p->vFlops, Vec_IntSize(vMapKtoI), nFlopWords ); Vec_IntPush( vMapKtoI, i ); if ( iRepr < 0 ) continue; pObj = Gia_ManCi( p->pAig, Gia_ManPiNum(p->pAig)+Vec_IntEntry(vMapKtoI, iRepr) ); pCi2Lit[Gia_ManPiNum(p->pAig)+i] = Abc_Var2Lit( Gia_ObjId( p->pAig, pObj ), 0 ); CounterE++; } Vec_IntFree( vMapKtoI ); if ( fVerbose ) printf( "Transforming %d const and %d equiv registers.\n", Counter0, CounterE ); return pCi2Lit; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_ManTer_t * Gia_ManTerSimulate( Gia_Man_t * pAig, int fVerbose ) { Gia_ManTer_t * p; unsigned * pState, * pPrev, * pLoop; int i, Counter; abctime clk, clkTotal = Abc_Clock(); assert( Gia_ManRegNum(pAig) > 0 ); // create manager clk = Abc_Clock(); p = Gia_ManTerCreate( pAig ); if ( 0 ) { printf( "Obj = %8d (%8d). F = %6d. ", pAig->nObjs, Gia_ManCiNum(pAig) + Gia_ManAndNum(pAig), p->pAig->nFront ); printf( "AIG = %7.2f MB. F-mem = %7.2f MB. Other = %7.2f MB. ", 12.0*Gia_ManObjNum(p->pAig)/(1<<20), 4.0*Abc_BitWordNum(2 * p->pAig->nFront)/(1<<20), 4.0*Abc_BitWordNum(2 * (Gia_ManCiNum(pAig) + Gia_ManCoNum(pAig)))/(1<<20) ); ABC_PRT( "Time", Abc_Clock() - clk ); } // perform simulation Gia_ManTerSimInfoInit( p ); // hash the first state pState = Gia_ManTerStateCreate( p ); Gia_ManTerStateInsert( pState, p->nStateWords, p->pBins, p->nBins ); //Gia_ManTerStatePrint( pState, Gia_ManRegNum(pAig), 0 ); // perform simuluation till convergence pPrev = NULL; for ( i = 0; ; i++ ) { Gia_ManTerSimulateRound( p ); Gia_ManTerSimInfoTransfer( p ); pState = Gia_ManTerStateCreate( p ); //Gia_ManTerStatePrint( pState, Gia_ManRegNum(pAig), i+1 ); if ( (pLoop = Gia_ManTerStateLookup(pState, p->nStateWords, p->pBins, p->nBins)) ) { pAig->nTerStates = Vec_PtrSize( p->vStates ); pAig->nTerLoop = Vec_PtrFind( p->vStates, pLoop ); break; } Gia_ManTerStateInsert( pState, p->nStateWords, p->pBins, p->nBins ); if ( i >= p->nIters && i % 10 == 0 ) { Counter = Gia_ManTerRetire( p, pState, pPrev ); // Counter = Gia_ManTerRetire2( p, pState ); // if ( fVerbose ) // printf( "Retired %d registers.\n", Counter ); } pPrev = pState; } if ( fVerbose ) { printf( "Ternary simulation saturated after %d iterations. ", i+1 ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManReduceConst( Gia_Man_t * pAig, int fVerbose ) { Gia_ManTer_t * p; Gia_Man_t * pNew = NULL; int * pCi2Lit; p = Gia_ManTerSimulate( pAig, fVerbose ); Gia_ManTerAnalyze( p ); pCi2Lit = Gia_ManTerCreateMap( p, fVerbose ); Gia_ManTerDelete( p ); pNew = Gia_ManDupDfsCiMap( pAig, pCi2Lit, NULL ); ABC_FREE( pCi2Lit ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaTtopt.cpp000066400000000000000000001047601477524141600165760ustar00rootroot00000000000000/**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 ); if ( nInputs == 0 ) { for ( k = 0; k < nOuts; k++ ) { pObj = Gia_ManCo( p, g+k ); pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); Gia_ManAppendCo( pNew, pTruth[0] & 1 ); } Vec_IntFree( vSupp ); continue; } Ttopt::TruthTableLevelTSM tt( nInputs, nOuts ); for ( k = 0; k < nOuts; k++ ) { 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 abc-0.52/src/aig/gia/giaUnate.c000066400000000000000000000214611477524141600161740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaUnate.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Computation of structural unateness.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaUnate.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Flips the first bit in all entries of the vector.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Vec_Int_t * Vec_IntFlopBit( Vec_Int_t * p ) { int i; for ( i = 0; i < p->nSize; i++ ) { if ( i+1 < p->nSize && Abc_Lit2Var(p->pArray[i]) == Abc_Lit2Var(p->pArray[i+1]) ) i++; // skip variable appearing as both pos and neg literal else p->pArray[i] ^= 1; } return p; } /**Function************************************************************* Synopsis [Compute unateness for all outputs in terms of inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Wec_t * Gia_ManCheckUnateVec( Gia_Man_t * p, Vec_Int_t * vCiIds, Vec_Int_t * vCoIds ) { Vec_Int_t * vCiVec = vCiIds ? Vec_IntDup(vCiIds) : Vec_IntStartNatural(Gia_ManCiNum(p)); Vec_Int_t * vCoVec = vCoIds ? Vec_IntDup(vCoIds) : Vec_IntStartNatural(Gia_ManCoNum(p)); Vec_Wec_t * vUnatesCo = Vec_WecStart( Vec_IntSize(vCoVec) ); Vec_Wec_t * vUnates = Vec_WecStart( Gia_ManObjNum(p) ); Vec_Int_t * vUnate0, * vUnate1; Gia_Obj_t * pObj; int i, CioId; Vec_IntForEachEntry( vCiVec, CioId, i ) { pObj = Gia_ManCi( p, CioId ); Vec_IntPush( Vec_WecEntry(vUnates, Gia_ObjId(p, pObj)), Abc_Var2Lit(CioId, 0) ); } Gia_ManForEachAnd( p, pObj, i ) { vUnate0 = Vec_WecEntry(vUnates, Gia_ObjFaninId0(pObj, i)); vUnate1 = Vec_WecEntry(vUnates, Gia_ObjFaninId1(pObj, i)); vUnate0 = Gia_ObjFaninC0(pObj) ? Vec_IntFlopBit(vUnate0) : vUnate0; vUnate1 = Gia_ObjFaninC1(pObj) ? Vec_IntFlopBit(vUnate1) : vUnate1; Vec_IntTwoMerge2( vUnate0, vUnate1, Vec_WecEntry(vUnates, i) ); vUnate0 = Gia_ObjFaninC0(pObj) ? Vec_IntFlopBit(vUnate0) : vUnate0; vUnate1 = Gia_ObjFaninC1(pObj) ? Vec_IntFlopBit(vUnate1) : vUnate1; } Vec_IntForEachEntry( vCoVec, CioId, i ) { pObj = Gia_ManCo( p, CioId ); vUnate0 = Vec_WecEntry(vUnates, Gia_ObjFaninId0p(p, pObj)); vUnate0 = Gia_ObjFaninC0(pObj) ? Vec_IntFlopBit(vUnate0) : vUnate0; Vec_IntAppend( Vec_WecEntry(vUnatesCo, i), vUnate0 ); vUnate0 = Gia_ObjFaninC0(pObj) ? Vec_IntFlopBit(vUnate0) : vUnate0; } Vec_WecFree( vUnates ); Vec_IntFree( vCiVec ); Vec_IntFree( vCoVec ); return vUnatesCo; } /**Function************************************************************* Synopsis [Checks unateness one function in one variable.] Description [Returns 0 if Co is not unate in Ci. Returns 1 if Co is neg-unate in Ci. Returns 2 if Co is pos-unate in Ci. Returns 3 if Co does not depend on Ci.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCheckUnate_rec( Gia_Man_t * p, int iObj ) { Gia_Obj_t * pObj; int Res0, Res1; if ( p->nTravIds - p->pTravIds[iObj] <= 3 ) return p->nTravIds - p->pTravIds[iObj]; pObj = Gia_ManObj( p, iObj ); p->pTravIds[iObj] = p->nTravIds - 3; if ( Gia_ObjIsCi(pObj) ) return 3; Res0 = Gia_ManCheckUnate_rec( p, Gia_ObjFaninId0(pObj, iObj) ); Res1 = Gia_ManCheckUnate_rec( p, Gia_ObjFaninId1(pObj, iObj) ); Res0 = ((Res0 == 1 || Res0 == 2) && Gia_ObjFaninC0(pObj)) ? Res0 ^ 3 : Res0; Res1 = ((Res1 == 1 || Res1 == 2) && Gia_ObjFaninC1(pObj)) ? Res1 ^ 3 : Res1; p->pTravIds[iObj] = p->nTravIds - (Res0 & Res1); assert( (Res0 & Res1) <= 3 ); return p->nTravIds - p->pTravIds[iObj]; } int Gia_ManCheckUnate( Gia_Man_t * p, int iCiId, int iCoId ) { int Res; int CiObjId = Gia_ObjId(p, Gia_ManCi(p, iCiId)); int CoObjId = Gia_ObjId(p, Gia_ManCo(p, iCoId)); Gia_Obj_t * pCoObj = Gia_ManCo(p, iCoId); Gia_ManIncrementTravId( p ); // Co does not depend on Ci. Gia_ManIncrementTravId( p ); // Co is pos-unate in Ci Gia_ObjSetTravIdCurrentId( p, CiObjId ); Gia_ManIncrementTravId( p ); // Co is neg-unate in Ci Gia_ManIncrementTravId( p ); // Co is not unate in Ci Res = Gia_ManCheckUnate_rec( p, Gia_ObjFaninId0(pCoObj, CoObjId) ); return ((Res == 1 || Res == 2) && Gia_ObjFaninC0(pCoObj)) ? Res ^ 3 : Res; } /**Function************************************************************* Synopsis [Testing procedure for all pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCheckUnateVecTest( Gia_Man_t * p, int fVerbose ) { abctime clk = Abc_Clock(); Vec_Wec_t * vUnates = Gia_ManCheckUnateVec( p, NULL, NULL ); int i, o, Var, nVars = Gia_ManCiNum(p); int nUnate = 0, nNonUnate = 0; char * pBuffer = ABC_CALLOC( char, nVars+1 ); if ( fVerbose ) { printf( "Inputs : " ); for ( i = 0; i < nVars; i++ ) printf( "%d", i % 10 ); printf( "\n" ); } for ( o = 0; o < Gia_ManCoNum(p); o++ ) { Vec_Int_t * vUnate = Vec_WecEntry( vUnates, o ); 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 else pBuffer[Abc_Lit2Var(Var)] = Abc_LitIsCompl(Var) ? 'n' : 'p', nUnate++; if ( fVerbose ) printf( "Out%4d : %s\n", o, pBuffer ); } ABC_FREE( pBuffer ); // print stats printf( "Ins/Outs = %4d/%4d. Total supp = %5d. Total unate = %5d.\n", Gia_ManCiNum(p), Gia_ManCoNum(p), nUnate+nNonUnate, nUnate ); ABC_PRT( "Total time", Abc_Clock() - clk ); //Vec_WecPrint( vUnates, 0 ); Vec_WecFree( vUnates ); } /**Function************************************************************* Synopsis [Testing procedure for one pair.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCheckUnateTest( Gia_Man_t * p, int fComputeAll, int fVerbose ) { if ( fComputeAll ) Gia_ManCheckUnateVecTest( p, fVerbose ); else { abctime clk = Abc_Clock(); int i, o, nVars = Gia_ManCiNum(p); int nUnate = 0, nNonUnate = 0; char * pBuffer = ABC_CALLOC( char, nVars+1 ); if ( fVerbose ) { printf( "Inputs : " ); for ( i = 0; i < nVars; i++ ) printf( "%d", i % 10 ); printf( "\n" ); } for ( o = 0; o < Gia_ManCoNum(p); o++ ) { for ( i = 0; i < nVars; i++ ) { int Res = Gia_ManCheckUnate( p, i, o ); if ( Res == 3 ) pBuffer[i] = ' '; else if ( Res == 2 ) pBuffer[i] = 'p', nUnate++; else if ( Res == 1 ) pBuffer[i] = 'n', nUnate++; else if ( Res == 0 ) pBuffer[i] = '.', nNonUnate++; else assert( 0 ); } if ( fVerbose ) printf( "Out%4d : %s\n", o, pBuffer ); } ABC_FREE( pBuffer ); // print stats printf( "Ins/Outs = %4d/%4d. Total supp = %5d. Total unate = %5d.\n", Gia_ManCiNum(p), Gia_ManCoNum(p), nUnate+nNonUnate, nUnate ); ABC_PRT( "Total time", Abc_Clock() - clk ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/giaUtil.c000066400000000000000000003354631477524141600160470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [giaUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [Various utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "base/main/mainInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define NUMBER1 3716960521u #define NUMBER2 2174103536u //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates a sequence or random numbers.] Description [] SideEffects [] SeeAlso [http://www.codeproject.com/KB/recipes/SimpleRNG.aspx] ***********************************************************************/ unsigned Gia_ManRandom( int fReset ) { #ifdef _MSC_VER static unsigned int m_z = NUMBER1; static unsigned int m_w = NUMBER2; #else static __thread unsigned int m_z = NUMBER1; static __thread unsigned int m_w = NUMBER2; #endif if ( fReset ) { m_z = NUMBER1; m_w = NUMBER2; } m_z = 36969 * (m_z & 65535) + (m_z >> 16); m_w = 18000 * (m_w & 65535) + (m_w >> 16); return (m_z << 16) + m_w; } word Gia_ManRandomW( int fReset ) { return ((word)Gia_ManRandom(fReset) << 32) | ((word)Gia_ManRandom(fReset) << 0); } /**Function************************************************************* Synopsis [Creates random info for the primary inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int iWordStop ) { unsigned * pInfo; int i, w; Vec_PtrForEachEntryStart( unsigned *, vInfo, pInfo, i, iInputStart ) for ( w = iWordStart; w < iWordStop; w++ ) pInfo[w] = Gia_ManRandom(0); } /**Function************************************************************* Synopsis [Returns the time stamp.] Description [The file should be closed.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Gia_TimeStamp() { static char Buffer[100]; char * TimeStamp; time_t ltime; // get the current time time( <ime ); TimeStamp = asctime( localtime( <ime ) ); TimeStamp[ strlen(TimeStamp) - 1 ] = 0; strcpy( Buffer, TimeStamp ); return Buffer; } /**Function************************************************************* Synopsis [Returns the composite name of the file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Gia_FileNameGenericAppend( char * pBase, char * pSuffix ) { static char Buffer[1000]; char * pDot; strcpy( Buffer, pBase ); if ( (pDot = strrchr( Buffer, '.' )) ) *pDot = 0; strcat( Buffer, pSuffix ); if ( (pDot = strrchr( Buffer, '\\' )) || (pDot = strrchr( Buffer, '/' )) ) return pDot+1; return Buffer; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Gia_GetFakeNames( int nNames, int fCaps ) { Vec_Ptr_t * vNames; char Buffer[5]; int i; vNames = Vec_PtrAlloc( nNames ); for ( i = 0; i < nNames; i++ ) { if ( nNames < 26 ) { Buffer[0] = (fCaps ? 'A' : 'a') + i; Buffer[1] = 0; } else { Buffer[0] = (fCaps ? 'A' : 'a') + i%26; Buffer[1] = '0' + i/26; Buffer[2] = 0; } Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) ); } return vNames; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManIncrementTravId( Gia_Man_t * p ) { if ( p->pTravIds == NULL ) { p->nTravIdsAlloc = Gia_ManObjNum(p) + 100; p->pTravIds = ABC_CALLOC( int, p->nTravIdsAlloc ); p->nTravIds = 0; } while ( p->nTravIdsAlloc < Gia_ManObjNum(p) ) { p->nTravIdsAlloc *= 2; p->pTravIds = ABC_REALLOC( int, p->pTravIds, p->nTravIdsAlloc ); memset( p->pTravIds + p->nTravIdsAlloc/2, 0, sizeof(int) * p->nTravIdsAlloc/2 ); } p->nTravIds++; } /**Function************************************************************* Synopsis [Sets phases of the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCleanMark01( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) pObj->fMark0 = pObj->fMark1 = 0; } /**Function************************************************************* Synopsis [Sets phases of the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSetMark0( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) pObj->fMark0 = 1; } /**Function************************************************************* Synopsis [Sets phases of the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCleanMark0( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) pObj->fMark0 = 0; } /**Function************************************************************* Synopsis [Sets phases of the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCheckMark0( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) assert( pObj->fMark0 == 0 ); } /**Function************************************************************* Synopsis [Sets phases of the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSetMark1( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) pObj->fMark1 = 1; } /**Function************************************************************* Synopsis [Sets phases of the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCleanMark1( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) pObj->fMark1 = 0; } /**Function************************************************************* Synopsis [Sets phases of the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCheckMark1( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) assert( pObj->fMark1 == 0 ); } /**Function************************************************************* Synopsis [Cleans the value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCleanValue( Gia_Man_t * p ) { int i; for ( i = 0; i < p->nObjs; i++ ) p->pObjs[i].Value = 0; } /**Function************************************************************* Synopsis [Cleans the value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManFillValue( Gia_Man_t * p ) { int i; for ( i = 0; i < p->nObjs; i++ ) p->pObjs[i].Value = ~0; } /**Function************************************************************* Synopsis [Sets the phase of one object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ObjSetPhase( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsAnd(pObj) ) { int fPhase0 = Gia_ObjPhase(Gia_ObjFanin0(pObj)) ^ Gia_ObjFaninC0(pObj); int fPhase1 = Gia_ObjPhase(Gia_ObjFanin1(pObj)) ^ Gia_ObjFaninC1(pObj); if ( Gia_ObjIsMux(p, pObj) ) { int fPhase2 = Gia_ObjPhase(Gia_ObjFanin2(p, pObj)) ^ Gia_ObjFaninC2(p, pObj); pObj->fPhase = (fPhase2 && fPhase1) || (!fPhase2 && fPhase0); } else if ( Gia_ObjIsXor(pObj) ) pObj->fPhase = fPhase0 ^ fPhase1; else pObj->fPhase = fPhase0 & fPhase1; } else if ( Gia_ObjIsCo(pObj) ) pObj->fPhase = (Gia_ObjPhase(Gia_ObjFanin0(pObj)) ^ Gia_ObjFaninC0(pObj)); else pObj->fPhase = 0; } /**Function************************************************************* Synopsis [Sets phases of the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSetPhase( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) Gia_ObjSetPhase( p, pObj ); } void Gia_ManSetPhasePattern( Gia_Man_t * p, Vec_Int_t * vCiValues ) { Gia_Obj_t * pObj; int i; assert( Gia_ManCiNum(p) == Vec_IntSize(vCiValues) ); Gia_ManForEachObj( p, pObj, i ) if ( Gia_ObjIsCi(pObj) ) pObj->fPhase = Vec_IntEntry( vCiValues, Gia_ObjCioId(pObj) ); else Gia_ObjSetPhase( p, pObj ); } /**Function************************************************************* Synopsis [Sets phases of the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSetPhase1( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachCi( p, pObj, i ) pObj->fPhase = 1; Gia_ManForEachObj( p, pObj, i ) if ( !Gia_ObjIsCi(pObj) ) Gia_ObjSetPhase( p, pObj ); } /**Function************************************************************* Synopsis [Sets phases of the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCleanPhase( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) pObj->fPhase = 0; } /**Function************************************************************* Synopsis [Returns the number of COs whose value is 1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCheckCoPhase( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, Counter = 0; Gia_ManForEachCo( p, pObj, i ) Counter += pObj->fPhase; return Counter; } /**Function************************************************************* Synopsis [Prepares copies for the model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCleanLevels( Gia_Man_t * p, int Size ) { if ( p->vLevels == NULL ) p->vLevels = Vec_IntAlloc( Size ); Vec_IntFill( p->vLevels, Size, 0 ); } /**Function************************************************************* Synopsis [Prepares copies for the model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCleanTruth( Gia_Man_t * p ) { if ( p->vTruths == NULL ) p->vTruths = Vec_IntAlloc( Gia_ManObjNum(p) ); Vec_IntFill( p->vTruths, Gia_ManObjNum(p), -1 ); } /**Function************************************************************* Synopsis [Assigns levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManLevelNum( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); p->nLevels = 0; Gia_ManForEachObj( p, pObj, i ) { if ( !p->fGiaSimple && Gia_ObjIsBuf(pObj) ) Gia_ObjSetBufLevel( p, pObj ); else if ( Gia_ObjIsAnd(pObj) ) Gia_ObjSetGateLevel( p, pObj ); else if ( Gia_ObjIsCo(pObj) ) Gia_ObjSetCoLevel( p, pObj ); else Gia_ObjSetLevel( p, pObj, 0 ); p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) ); } 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; int i, Ave = 0; assert( p->vLevels ); Gia_ManForEachCo( p, pObj, i ) Ave += Gia_ObjLevel(p, pObj); return (float)Ave / Gia_ManCoNum(p); } /**Function************************************************************* Synopsis [Assigns levels using CI level information.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManGetCiLevels( Gia_Man_t * p ) { Vec_Int_t * vCiLevels; Gia_Obj_t * pObj; int i; if ( p->vLevels == NULL ) return NULL; vCiLevels = Vec_IntAlloc( Gia_ManCiNum(p) ); Gia_ManForEachCi( p, pObj, i ) Vec_IntPush( vCiLevels, Gia_ObjLevel(p, pObj) ); return vCiLevels; } int Gia_ManSetLevels( Gia_Man_t * p, Vec_Int_t * vCiLevels ) { Gia_Obj_t * pObj; int i; if ( vCiLevels == NULL ) return Gia_ManLevelNum( p ); assert( Vec_IntSize(vCiLevels) == Gia_ManCiNum(p) ); Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); p->nLevels = 0; Gia_ManForEachCi( p, pObj, i ) { Gia_ObjSetLevel( p, pObj, Vec_IntEntry(vCiLevels, i) ); p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) ); } Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) Gia_ObjSetGateLevel( p, pObj ); else if ( Gia_ObjIsCo(pObj) ) Gia_ObjSetCoLevel( p, pObj ); else continue; p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) ); } return p->nLevels; } /**Function************************************************************* Synopsis [Compute reverse levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManReverseLevel( Gia_Man_t * p ) { Vec_Int_t * vLevelRev; Gia_Obj_t * pObj; int i; vLevelRev = Vec_IntStart( Gia_ManObjNum(p) ); Gia_ManForEachAndReverse( p, pObj, i ) { int LevelR = Vec_IntEntry( vLevelRev, i ); if ( Gia_ObjIsMux(p, pObj) ) { Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId0(pObj, i), LevelR + 2 ); Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId1(pObj, i), LevelR + 2 ); Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId2(p, i), LevelR + 2 ); } else if ( Gia_ObjIsXor(pObj) ) { Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId0(pObj, i), LevelR + 2 ); Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId1(pObj, i), LevelR + 2 ); } else if ( Gia_ObjIsBuf(pObj) ) { Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId0(pObj, i), LevelR ); } else { Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId0(pObj, i), LevelR + 1 ); Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId1(pObj, i), LevelR + 1 ); } } return vLevelRev; } /**Function************************************************************* Synopsis [Compute required levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManRequiredLevel( Gia_Man_t * p ) { Vec_Int_t * vRequired; Gia_Obj_t * pObj; int i, LevelMax = 0; vRequired = Gia_ManReverseLevel( p ); Gia_ManForEachCi( p, pObj, i ) LevelMax = Abc_MaxInt( LevelMax, Vec_IntEntry(vRequired, Gia_ObjId(p, pObj)) ); Gia_ManForEachObj( p, pObj, i ) Vec_IntWriteEntry( vRequired, i, LevelMax - Vec_IntEntry(vRequired, i) ); return vRequired; } /**Function************************************************************* Synopsis [Compute slacks measured using the number of AIG levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManComputeSlacks( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, nLevels = Gia_ManLevelNum( p ); Vec_Int_t * vLevelR = Gia_ManReverseLevel( p ); Vec_Int_t * vSlacks = Vec_IntAlloc( Gia_ManObjNum(p) ); Gia_ManForEachObj( p, pObj, i ) Vec_IntPush( vSlacks, nLevels - Gia_ObjLevelId(p, i) - Vec_IntEntry(vLevelR, i) ); assert( Vec_IntSize(vSlacks) == Gia_ManObjNum(p) ); Vec_IntFree( vLevelR ); return vSlacks; } /**Function************************************************************* Synopsis [Assigns levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCreateValueRefs( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) { pObj->Value = 0; if ( Gia_ObjIsAnd(pObj) ) { Gia_ObjFanin0(pObj)->Value++; if ( !Gia_ObjIsBuf(pObj) ) Gia_ObjFanin1(pObj)->Value++; } else if ( Gia_ObjIsCo(pObj) ) Gia_ObjFanin0(pObj)->Value++; } } /**Function************************************************************* Synopsis [Assigns references.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCreateRefs( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; assert( p->pRefs == NULL ); p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) { Gia_ObjRefFanin0Inc( p, pObj ); if ( !Gia_ObjIsBuf(pObj) ) Gia_ObjRefFanin1Inc( p, pObj ); if ( Gia_ObjIsMuxId(p, i) ) Gia_ObjRefFanin2Inc( p, pObj ); } else if ( Gia_ObjIsCo(pObj) ) Gia_ObjRefFanin0Inc( p, pObj ); } } void Gia_ManCreateLitRefs( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; assert( p->pRefs == NULL ); p->pRefs = ABC_CALLOC( int, 2*Gia_ManObjNum(p) ); Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) { p->pRefs[Gia_ObjFaninLit0(pObj, i)]++; p->pRefs[Gia_ObjFaninLit1(pObj, i)]++; } else if ( Gia_ObjIsCo(pObj) ) p->pRefs[Gia_ObjFaninLit0(pObj, i)]++; } } /**Function************************************************************* Synopsis [Assigns references.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Gia_ManCreateMuxRefs( Gia_Man_t * p ) { Gia_Obj_t * pObj, * pCtrl, * pFan0, * pFan1; int i, * pMuxRefs; pMuxRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjRecognizeExor( pObj, &pFan0, &pFan1 ) ) continue; if ( !Gia_ObjIsMuxType(pObj) ) continue; pCtrl = Gia_ObjRecognizeMux( pObj, &pFan0, &pFan1 ); pMuxRefs[ Gia_ObjId(p, Gia_Regular(pCtrl)) ]++; } return pMuxRefs; } /**Function************************************************************* Synopsis [Computes the maximum frontier size.] Description [] SideEffects [] 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) ) return; Gia_ObjSetTravIdCurrent(p, pObj); if ( Gia_ObjIsCi(pObj) ) { Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); return; } if ( Gia_ObjIsCo(pObj) ) { Gia_ObjFanin0(pObj)->Value++; Gia_ManDfsForCrossCut_rec( p, Gia_ObjFanin0(pObj), vNodes ); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); return; } assert( Gia_ObjIsAnd(pObj) ); Gia_ObjFanin0(pObj)->Value++; Gia_ObjFanin1(pObj)->Value++; Gia_ManDfsForCrossCut_rec( p, Gia_ObjFanin0(pObj), vNodes ); Gia_ManDfsForCrossCut_rec( p, Gia_ObjFanin1(pObj), vNodes ); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); } Vec_Int_t * Gia_ManDfsForCrossCut( Gia_Man_t * p, int fReverse ) { Vec_Int_t * vNodes; Gia_Obj_t * pObj; int i; Gia_ManCleanValue( p ); vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); Gia_ManIncrementTravId( p ); if ( fReverse ) { Gia_ManForEachCoReverse( p, pObj, i ) if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) Gia_ManDfsForCrossCut_rec( p, pObj, vNodes ); } else { Gia_ManForEachCo( p, pObj, i ) if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) Gia_ManDfsForCrossCut_rec( p, pObj, vNodes ); } return vNodes; } int Gia_ManCrossCut( Gia_Man_t * p, int fReverse ) { Vec_Int_t * vNodes; 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 ) nCutCur++; if ( nCutMax < nCutCur ) nCutMax = nCutCur; if ( Gia_ObjIsAnd(pObj) ) { if ( --Gia_ObjFanin0(pObj)->Value == 0 ) nCutCur--; if ( --Gia_ObjFanin1(pObj)->Value == 0 ) nCutCur--; } else if ( Gia_ObjIsCo(pObj) ) { if ( --Gia_ObjFanin0(pObj)->Value == 0 ) nCutCur--; } } Vec_IntFree( vNodes ); Gia_ManForEachObj( p, pObj, i ) assert( pObj->Value == 0 ); return nCutMax; } /**Function************************************************************* Synopsis [Collects PO Ids into one array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManCollectPoIds( Gia_Man_t * p ) { Vec_Int_t * vStart; int Entry, i; vStart = Vec_IntAlloc( Gia_ManPoNum(p) ); Vec_IntForEachEntryStop( p->vCos, Entry, i, Gia_ManPoNum(p) ) Vec_IntPush( vStart, Entry ); return vStart; } /**Function************************************************************* Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ObjIsMuxType( Gia_Obj_t * pNode ) { Gia_Obj_t * pNode0, * pNode1; // check that the node is regular assert( !Gia_IsComplement(pNode) ); // if the node is not AND, this is not MUX if ( !Gia_ObjIsAnd(pNode) || Gia_ObjIsBuf(pNode) ) return 0; // if the children are not complemented, this is not MUX if ( !Gia_ObjFaninC0(pNode) || !Gia_ObjFaninC1(pNode) ) return 0; // get children pNode0 = Gia_ObjFanin0(pNode); pNode1 = Gia_ObjFanin1(pNode); // if the children are not ANDs, this is not MUX if ( !Gia_ObjIsAnd(pNode0) || !Gia_ObjIsAnd(pNode1) ) return 0; // otherwise the node is MUX iff it has a pair of equal grandchildren return (Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1))) || (Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1))) || (Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1))) || (Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1))); } /**Function************************************************************* Synopsis [Recognizes what nodes are inputs of the EXOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ObjRecognizeExor( Gia_Obj_t * pObj, Gia_Obj_t ** ppFan0, Gia_Obj_t ** ppFan1 ) { Gia_Obj_t * p0, * p1; assert( !Gia_IsComplement(pObj) ); if ( !Gia_ObjIsAnd(pObj) || Gia_ObjIsBuf(pObj) ) return 0; assert( Gia_ObjIsAnd(pObj) ); p0 = Gia_ObjChild0(pObj); p1 = Gia_ObjChild1(pObj); if ( !Gia_IsComplement(p0) || !Gia_IsComplement(p1) ) return 0; p0 = Gia_Regular(p0); p1 = Gia_Regular(p1); if ( !Gia_ObjIsAnd(p0) || !Gia_ObjIsAnd(p1) ) return 0; if ( Gia_ObjFanin0(p0) != Gia_ObjFanin0(p1) || Gia_ObjFanin1(p0) != Gia_ObjFanin1(p1) ) return 0; if ( Gia_ObjFaninC0(p0) == Gia_ObjFaninC0(p1) || Gia_ObjFaninC1(p0) == Gia_ObjFaninC1(p1) ) return 0; if ( ppFan0 ) *ppFan0 = Gia_ObjChild0(p0); if ( ppFan1 ) *ppFan1 = Gia_ObjChild1(p0); return 1; } /**Function************************************************************* Synopsis [Recognizes what nodes are control and data inputs of a MUX.] Description [If the node is a MUX, returns the control variable C. Assigns nodes T and E to be the then and else variables of the MUX. Node C is never complemented. Nodes T and E can be complemented. This function also recognizes EXOR/NEXOR gates as MUXes.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Obj_t * Gia_ObjRecognizeMux( Gia_Obj_t * pNode, Gia_Obj_t ** ppNodeT, Gia_Obj_t ** ppNodeE ) { Gia_Obj_t * pNode0, * pNode1; assert( !Gia_IsComplement(pNode) ); assert( Gia_ObjIsMuxType(pNode) ); // get children pNode0 = Gia_ObjFanin0(pNode); pNode1 = Gia_ObjFanin1(pNode); // find the control variable if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1)) ) { // if ( FrGia_IsComplement(pNode1->p2) ) if ( Gia_ObjFaninC1(pNode0) ) { // pNode2->p2 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); *ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); return Gia_ObjChild1(pNode1);//pNode2->p2; } else { // pNode1->p2 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); *ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); return Gia_ObjChild1(pNode0);//pNode1->p2; } } else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1)) ) { // if ( FrGia_IsComplement(pNode1->p1) ) if ( Gia_ObjFaninC0(pNode0) ) { // pNode2->p1 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); *ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); return Gia_ObjChild0(pNode1);//pNode2->p1; } else { // pNode1->p1 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); *ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); return Gia_ObjChild0(pNode0);//pNode1->p1; } } else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1)) ) { // if ( FrGia_IsComplement(pNode1->p1) ) if ( Gia_ObjFaninC0(pNode0) ) { // pNode2->p2 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); *ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); return Gia_ObjChild1(pNode1);//pNode2->p2; } else { // pNode1->p1 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); *ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); return Gia_ObjChild0(pNode0);//pNode1->p1; } } else if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1)) ) { // if ( FrGia_IsComplement(pNode1->p2) ) if ( Gia_ObjFaninC1(pNode0) ) { // pNode2->p1 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); *ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); return Gia_ObjChild0(pNode1);//pNode2->p1; } else { // pNode1->p2 is positive phase of C *ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); *ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); return Gia_ObjChild1(pNode0);//pNode1->p2; } } assert( 0 ); // this is not MUX return NULL; } int Gia_ObjRecognizeMuxLits( Gia_Man_t * p, Gia_Obj_t * pNode, int * iLitT, int * iLitE ) { Gia_Obj_t * pNodeT, * pNodeE; Gia_Obj_t * pCtrl = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); assert( pCtrl != NULL ); *iLitT = Gia_Obj2Lit( p, pNodeT ); *iLitE = Gia_Obj2Lit( p, pNodeE ); return Gia_Obj2Lit( p, pCtrl ); } /**Function************************************************************* Synopsis [Dereferences the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_NodeDeref_rec( Gia_Man_t * p, Gia_Obj_t * pNode ) { Gia_Obj_t * pFanin; int Counter = 0; if ( Gia_ObjIsCi(pNode) ) return 0; assert( Gia_ObjIsAnd(pNode) ); pFanin = Gia_ObjFanin0(pNode); assert( Gia_ObjRefNum(p, pFanin) > 0 ); if ( Gia_ObjRefDec(p, pFanin) == 0 ) Counter += Gia_NodeDeref_rec( p, pFanin ); pFanin = Gia_ObjFanin1(pNode); assert( Gia_ObjRefNum(p, pFanin) > 0 ); if ( Gia_ObjRefDec(p, pFanin) == 0 ) Counter += Gia_NodeDeref_rec( p, pFanin ); return Counter + 1; } /**Function************************************************************* Synopsis [References the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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, fMark ); pFanin = Gia_ObjFanin1(pNode); if ( Gia_ObjRefInc(p, pFanin) == 0 ) Counter += Gia_NodeRef_rec( p, pFanin, fMark ); return Counter + 1; } /**Function************************************************************* Synopsis [References the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManPoMffcSize( Gia_Man_t * p ) { Gia_ManCreateRefs( p ); return Gia_NodeDeref_rec( p, Gia_ObjFanin0(Gia_ManPo(p, 0)) ); } /**Function************************************************************* Synopsis [Returns the number of internal nodes in the MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_NodeMffcSize( 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 ); 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; } /**Function************************************************************* Synopsis [Returns the number of internal nodes in the MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_NodeCollect_rec( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp ) { if ( Gia_ObjIsTravIdCurrent(p, pNode) ) return; Gia_ObjSetTravIdCurrent(p, pNode); if ( Gia_ObjRefNum(p, pNode) || Gia_ObjIsCi(pNode) ) { Vec_IntPush( vSupp, Gia_ObjId(p, pNode) ); return; } assert( Gia_ObjIsAnd(pNode) ); Gia_NodeCollect_rec( p, Gia_ObjFanin0(pNode), vSupp ); Gia_NodeCollect_rec( p, Gia_ObjFanin1(pNode), vSupp ); } int Gia_NodeMffcSizeSupp( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp ) { int ConeSize1, ConeSize2; assert( !Gia_IsComplement(pNode) ); assert( Gia_ObjIsAnd(pNode) ); Vec_IntClear( vSupp ); Gia_ManIncrementTravId( p ); 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, 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManHasDangling( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, Counter = 0; Gia_ManForEachObj( p, pObj, i ) { pObj->fMark0 = 0; if ( Gia_ObjIsCo(pObj) ) Gia_ObjFanin0(pObj)->fMark0 = 1; else if ( Gia_ObjIsMux(p, pObj) ) { Gia_ObjFanin0(pObj)->fMark0 = 1; Gia_ObjFanin1(pObj)->fMark0 = 1; Gia_ObjFanin2(p, pObj)->fMark0 = 1; } else if ( Gia_ObjIsAnd(pObj) ) { Gia_ObjFanin0(pObj)->fMark0 = 1; Gia_ObjFanin1(pObj)->fMark0 = 1; } } Gia_ManForEachAnd( p, pObj, i ) Counter += !pObj->fMark0; Gia_ManCleanMark0( p ); return Counter; } /**Function************************************************************* Synopsis [Returns 1 if AIG has dangling nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManMarkDangling( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, Counter = 0; Gia_ManForEachObj( p, pObj, i ) { pObj->fMark0 = 0; if ( Gia_ObjIsAnd(pObj) ) { Gia_ObjFanin0(pObj)->fMark0 = 1; Gia_ObjFanin1(pObj)->fMark0 = 1; } else if ( Gia_ObjIsCo(pObj) ) Gia_ObjFanin0(pObj)->fMark0 = 1; } Gia_ManForEachAnd( p, pObj, i ) Counter += !pObj->fMark0; return Counter; } /**Function************************************************************* Synopsis [Returns 1 if AIG has dangling nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManGetDangling( Gia_Man_t * p ) { Vec_Int_t * vDangles; Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) { pObj->fMark0 = 0; if ( Gia_ObjIsAnd(pObj) ) { Gia_ObjFanin0(pObj)->fMark0 = 1; Gia_ObjFanin1(pObj)->fMark0 = 1; } else if ( Gia_ObjIsCo(pObj) ) Gia_ObjFanin0(pObj)->fMark0 = 1; } vDangles = Vec_IntAlloc( 100 ); Gia_ManForEachAnd( p, pObj, i ) if ( !pObj->fMark0 ) Vec_IntPush( vDangles, i ); Gia_ManCleanMark0( p ); return vDangles; } /**Function************************************************************* Synopsis [Verbose printing of the AIG node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ObjPrint( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( pObj == NULL ) { printf( "Object is NULL." ); return; } if ( Gia_IsComplement(pObj) ) { printf( "Compl " ); pObj = Gia_Not(pObj); } assert( !Gia_IsComplement(pObj) ); printf( "Obj %4d : ", Gia_ObjId(p, pObj) ); if ( Gia_ObjIsConst0(pObj) ) printf( "constant 0" ); else if ( Gia_ObjIsPi(p, pObj) ) printf( "PI" ); else if ( Gia_ObjIsPo(p, pObj) ) printf( "PO( %4d%s )", Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") ); else if ( Gia_ObjIsCi(pObj) ) printf( "RO( %4d%s )", Gia_ObjFaninId0p(p, Gia_ObjRoToRi(p, pObj)), (Gia_ObjFaninC0(Gia_ObjRoToRi(p, pObj))? "\'" : " ") ); else if ( Gia_ObjIsCo(pObj) ) printf( "RI( %4d%s )", Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") ); // else if ( Gia_ObjIsBuf(pObj) ) // printf( "BUF( %d%s )", Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") ); else if ( Gia_ObjIsXor(pObj) ) printf( "XOR( %4d%s, %4d%s )", Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " "), Gia_ObjFaninId1p(p, pObj), (Gia_ObjFaninC1(pObj)? "\'" : " ") ); else if ( Gia_ObjIsMuxId(p, Gia_ObjId(p, pObj)) ) printf( "MUX( %4d%s, %4d%s, %4d%s )", Gia_ObjFaninId2p(p, pObj), (Gia_ObjFaninC2(p, pObj)? "\'" : " "), Gia_ObjFaninId1p(p, pObj), (Gia_ObjFaninC1(pObj)? "\'" : " "), Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") ); else printf( "AND( %4d%s, %4d%s )", Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " "), Gia_ObjFaninId1p(p, pObj), (Gia_ObjFaninC1(pObj)? "\'" : " ") ); if ( p->pRefs ) printf( " (refs = %3d)", Gia_ObjRefNum(p, pObj) ); if ( pObj->fMark0 ) printf( " mark0" ); if ( pObj->fMark1 ) printf( " mark1" ); if ( Gia_ManHasMapping(p) && Gia_ObjIsLut(p, Gia_ObjId(p, pObj)) ) { int i, iFan; printf( " Cut = { " ); Gia_LutForEachFanin( p, Gia_ObjId(p, pObj), iFan, i ) printf( "%d ", iFan ); printf( "}" ); } if ( Gia_ManHasMapping2(p) && Gia_ObjIsLut2(p, Gia_ObjId(p, pObj)) ) { int i, iFan; printf( " Cut = { " ); Gia_LutForEachFanin2( p, Gia_ObjId(p, pObj), iFan, i ) printf( "%d ", iFan ); printf( "}" ); } printf( "\n" ); /* if ( p->pRefs ) { Gia_Obj_t * pFanout; int i; int iFan = -1; // Suppress "might be used uninitialized" printf( "\nFanouts:\n" ); Gia_ObjForEachFanout( p, pObj, pFanout, iFan, i ) { printf( " " ); printf( "Node %4d : ", Gia_ObjId(pFanout) ); if ( Gia_ObjIsPo(pFanout) ) printf( "PO( %4d%s )", Gia_ObjFanin0(pFanout)->Id, (Gia_ObjFaninC0(pFanout)? "\'" : " ") ); else if ( Gia_ObjIsBuf(pFanout) ) printf( "BUF( %d%s )", Gia_ObjFanin0(pFanout)->Id, (Gia_ObjFaninC0(pFanout)? "\'" : " ") ); else printf( "AND( %4d%s, %4d%s )", Gia_ObjFanin0(pFanout)->Id, (Gia_ObjFaninC0(pFanout)? "\'" : " "), Gia_ObjFanin1(pFanout)->Id, (Gia_ObjFaninC1(pFanout)? "\'" : " ") ); printf( "\n" ); } return; } */ } void Gia_ManPrint( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; printf( "GIA manager has %d ANDs, %d XORs, %d MUXes.\n", Gia_ManAndNum(p) - Gia_ManXorNum(p) - Gia_ManMuxNum(p), Gia_ManXorNum(p), Gia_ManMuxNum(p) ); Gia_ManForEachObj( p, pObj, i ) Gia_ObjPrint( p, pObj ); } void Gia_ManPrintCo_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsAnd(pObj) ) { Gia_ManPrintCo_rec( p, Gia_ObjFanin0(pObj) ); Gia_ManPrintCo_rec( p, Gia_ObjFanin1(pObj) ); if ( Gia_ObjIsMux(p, pObj) ) Gia_ManPrintCo_rec( p, Gia_ObjFanin2(p, pObj) ); } Gia_ObjPrint( p, pObj ); } void Gia_ManPrintCo( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsCo(pObj) ); printf( "TFI cone of CO number %d:\n", Gia_ObjCioId(pObj) ); Gia_ManPrintCo_rec( p, Gia_ObjFanin0(pObj) ); Gia_ObjPrint( p, pObj ); } void Gia_ManPrintCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) { if ( Vec_IntFind(vNodes, Gia_ObjId(p, pObj)) >= 0 ) return; assert( Gia_ObjIsAnd(pObj) ); Gia_ManPrintCollect_rec( p, Gia_ObjFanin0(pObj), vNodes ); Gia_ManPrintCollect_rec( p, Gia_ObjFanin1(pObj), vNodes ); if ( Gia_ObjIsMux(p, pObj) ) Gia_ManPrintCollect_rec( p, Gia_ObjFanin2(p, pObj), vNodes ); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); } void Gia_ManPrintCone( Gia_Man_t * p, Gia_Obj_t * pObj, int * pLeaves, int nLeaves, Vec_Int_t * vNodes ) { int i; Vec_IntClear( vNodes ); for ( i = 0; i < nLeaves; i++ ) Vec_IntPush( vNodes, pLeaves[i] ); Gia_ManPrintCollect_rec( p, pObj, vNodes ); printf( "GIA logic cone for node %d:\n", Gia_ObjId(p, pObj) ); Gia_ManForEachObjVec( vNodes, p, pObj, i ) Gia_ObjPrint( p, pObj ); } void Gia_ManPrintConeMulti( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) { Gia_Obj_t * pObj; int i; Vec_IntClear( vNodes ); Vec_IntAppend( vNodes, vLeaves ); Gia_ManForEachObjVec( vObjs, p, pObj, i ) Gia_ManPrintCollect_rec( p, pObj, vNodes ); printf( "GIA logic cone for %d nodes:\n", Vec_IntSize(vObjs) ); Gia_ManForEachObjVec( vNodes, p, pObj, i ) Gia_ObjPrint( p, pObj ); } void Gia_ManPrintCollect2_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) { if ( Vec_IntFind(vNodes, Gia_ObjId(p, pObj)) >= 0 ) return; if ( Gia_ObjIsCo(pObj) || Gia_ObjIsAnd(pObj) ) Gia_ManPrintCollect2_rec( p, Gia_ObjFanin0(pObj), vNodes ); if ( Gia_ObjIsAnd(pObj) ) Gia_ManPrintCollect2_rec( p, Gia_ObjFanin1(pObj), vNodes ); if ( Gia_ObjIsMux(p, pObj) ) Gia_ManPrintCollect2_rec( p, Gia_ObjFanin2(p, pObj), vNodes ); Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); } void Gia_ManPrintCone2( Gia_Man_t * p, Gia_Obj_t * pObj ) { Vec_Int_t * vNodes; int i; vNodes = Vec_IntAlloc( 100 ); Gia_ManPrintCollect2_rec( p, pObj, vNodes ); printf( "GIA logic cone for node %d:\n", Gia_ObjId(p, pObj) ); Gia_ManForEachObjVec( vNodes, p, pObj, i ) Gia_ObjPrint( p, pObj ); Vec_IntFree( vNodes ); } /**Function************************************************************* Synopsis [Complements the constraint outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManInvertConstraints( Gia_Man_t * pAig ) { Gia_Obj_t * pObj; int i; if ( Gia_ManConstrNum(pAig) == 0 ) return; Gia_ManForEachPo( pAig, pObj, i ) if ( i >= Gia_ManPoNum(pAig) - Gia_ManConstrNum(pAig) ) Gia_ObjFlipFaninC0( pObj ); } void Gia_ManInvertPos( Gia_Man_t * pAig ) { Gia_Obj_t * pObj; int i; Gia_ManForEachPo( pAig, pObj, i ) Gia_ObjFlipFaninC0( pObj ); } /**Function************************************************************* Synopsis [Testing the speedup due to grouping POs into batches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCollectObjs_rec( Gia_Man_t * p, int iObjId, Vec_Int_t * vObjs, int Limit ) { Gia_Obj_t * pObj; if ( Vec_IntSize(vObjs) == Limit ) return; if ( Gia_ObjIsTravIdCurrentId(p, iObjId) ) return; Gia_ObjSetTravIdCurrentId(p, iObjId); pObj = Gia_ManObj( p, iObjId ); if ( Gia_ObjIsAnd(pObj) ) { Gia_ManCollectObjs_rec( p, Gia_ObjFaninId0p(p, pObj), vObjs, Limit ); if ( Vec_IntSize(vObjs) == Limit ) return; Gia_ManCollectObjs_rec( p, Gia_ObjFaninId1p(p, pObj), vObjs, Limit ); if ( Vec_IntSize(vObjs) == Limit ) return; } Vec_IntPush( vObjs, iObjId ); } unsigned * Gia_ManComputePoTruthTables( Gia_Man_t * p, int nBytesMax ) { int nVars = Gia_ManPiNum(p); int nTruthWords = Abc_TruthWordNum( nVars ); int nTruths = nBytesMax / (sizeof(unsigned) * nTruthWords); int nTotalNodes = 0, nRounds = 0; Vec_Int_t * vObjs; Gia_Obj_t * pObj; abctime clk = Abc_Clock(); int i; printf( "Var = %d. Words = %d. Truths = %d.\n", nVars, nTruthWords, nTruths ); vObjs = Vec_IntAlloc( nTruths ); Gia_ManIncrementTravId( p ); Gia_ManForEachPo( p, pObj, i ) { Gia_ManCollectObjs_rec( p, Gia_ObjFaninId0p(p, pObj), vObjs, nTruths ); if ( Vec_IntSize(vObjs) == nTruths ) { nRounds++; // printf( "%d ", i ); nTotalNodes += Vec_IntSize( vObjs ); Vec_IntClear( vObjs ); Gia_ManIncrementTravId( p ); } } // printf( "\n" ); nTotalNodes += Vec_IntSize( vObjs ); Vec_IntFree( vObjs ); printf( "Rounds = %d. Objects = %d. Total = %d. ", nRounds, Gia_ManObjNum(p), nTotalNodes ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return NULL; } /**Function************************************************************* Synopsis [Returns 1 if the manager are structural identical.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManCompare( Gia_Man_t * p1, Gia_Man_t * p2 ) { Gia_Obj_t * pObj1, * pObj2; int i; if ( Gia_ManObjNum(p1) != Gia_ManObjNum(p2) ) { printf( "AIGs have different number of objects.\n" ); return 0; } Gia_ManCleanValue( p1 ); Gia_ManCleanValue( p2 ); Gia_ManForEachObj( p1, pObj1, i ) { pObj2 = Gia_ManObj( p2, i ); if ( memcmp( pObj1, pObj2, sizeof(Gia_Obj_t) ) ) { printf( "Objects %d are different.\n", i ); return 0; } if ( p1->pReprs && p2->pReprs ) { if ( memcmp( &p1->pReprs[i], &p2->pReprs[i], sizeof(Gia_Rpr_t) ) ) { printf( "Representatives of objects %d are different.\n", i ); return 0; } } } return 1; } /**Function************************************************************* Synopsis [Marks nodes that appear as faninis of other nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManMarkFanoutDrivers( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) { pObj->fMark0 = 0; if ( Gia_ObjIsAnd(pObj) ) { Gia_ObjFanin0(pObj)->fMark0 = 1; Gia_ObjFanin1(pObj)->fMark0 = 1; } else if ( Gia_ObjIsCo(pObj) ) Gia_ObjFanin0(pObj)->fMark0 = 1; } } /**Function************************************************************* Synopsis [Swaps PO number 0 with PO number i.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManSwapPos( Gia_Man_t * p, int i ) { int Lit0, LitI; assert( i >= 0 && i < Gia_ManPoNum(p) ); if ( i == 0 ) return; Lit0 = Gia_ObjFaninLit0p( p, Gia_ManPo(p, 0) ); LitI = Gia_ObjFaninLit0p( p, Gia_ManPo(p, i) ); Gia_ManPatchCoDriver( p, 0, LitI ); Gia_ManPatchCoDriver( p, i, Lit0 ); } /**Function************************************************************* Synopsis [Save/load value from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManSaveValue( Gia_Man_t * p ) { Vec_Int_t * vValues; Gia_Obj_t * pObj; int i; vValues = Vec_IntAlloc( Gia_ManObjNum(p) ); Gia_ManForEachObj( p, pObj, i ) Vec_IntPush( vValues, pObj->Value ); return vValues; } void Gia_ManLoadValue( Gia_Man_t * p, Vec_Int_t * vValues ) { Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) pObj->Value = Vec_IntEntry(vValues, i); } /**Function************************************************************* Synopsis [Returns the array containing the first fanout of each object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManFirstFanouts( Gia_Man_t * p ) { Vec_Int_t * vFans = Vec_IntStart( Gia_ManObjNum(p) ); Gia_Obj_t * pObj; int i; Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjIsAnd(pObj) ) { if ( Vec_IntEntry(vFans, Gia_ObjFaninId0p(p, pObj)) == 0 ) Vec_IntWriteEntry(vFans, Gia_ObjFaninId0p(p, pObj), i); if ( Vec_IntEntry(vFans, Gia_ObjFaninId1p(p, pObj)) == 0 ) Vec_IntWriteEntry(vFans, Gia_ObjFaninId1p(p, pObj), i); if ( Gia_ObjIsMuxId(p, i) && Vec_IntEntry(vFans, Gia_ObjFaninId2p(p, pObj)) == 0 ) Vec_IntWriteEntry(vFans, Gia_ObjFaninId2p(p, pObj), i); } else if ( Gia_ObjIsCo(pObj) ) { if ( Vec_IntEntry(vFans, Gia_ObjFaninId0p(p, pObj)) == 0 ) Vec_IntWriteEntry(vFans, Gia_ObjFaninId0p(p, pObj), i); } } return vFans; } /**Function************************************************************* Synopsis [Returns 1 if AIG has choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManHasChoices_very_old( Gia_Man_t * p ) { Gia_Obj_t * pObj; int i, Counter1 = 0, Counter2 = 0; int nFailNoRepr = 0; int nFailHaveRepr = 0; int nChoiceNodes = 0; int nChoices = 0; if ( p->pReprs == NULL || p->pNexts == NULL ) return 0; // check if there are any representatives Gia_ManForEachObj( p, pObj, i ) { if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) ) { // printf( "%d ", i ); Counter1++; } // if ( Gia_ObjNext( p, Gia_ObjId(p, pObj) ) ) // Counter2++; } // printf( "\n" ); Gia_ManForEachObj( p, pObj, i ) { // if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) ) // Counter1++; if ( Gia_ObjNext( p, Gia_ObjId(p, pObj) ) ) { // printf( "%d ", i ); Counter2++; } } // printf( "\n" ); if ( Counter1 == 0 ) { printf( "Warning: AIG has repr data-strucure but not reprs.\n" ); return 0; } printf( "%d nodes have reprs.\n", Counter1 ); printf( "%d nodes have nexts.\n", Counter2 ); // check if there are any internal nodes without fanout // make sure all nodes without fanout have representatives // make sure all nodes with fanout have no representatives ABC_FREE( p->pRefs ); Gia_ManCreateRefs( p ); Gia_ManForEachAnd( p, pObj, i ) { if ( Gia_ObjRefNum(p, pObj) == 0 ) { if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) == NULL ) nFailNoRepr++; else nChoices++; } else { if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) != NULL ) nFailHaveRepr++; if ( Gia_ObjNextObj( p, Gia_ObjId(p, pObj) ) != NULL ) nChoiceNodes++; } if ( Gia_ObjReprObj( p, i ) ) assert( Gia_ObjRepr(p, i) < i ); } if ( nChoices == 0 ) return 0; if ( nFailNoRepr ) { printf( "Gia_ManHasChoices_very_old(): Error: %d internal nodes have no fanout and no repr.\n", nFailNoRepr ); // return 0; } if ( nFailHaveRepr ) { printf( "Gia_ManHasChoices_very_old(): Error: %d internal nodes have both fanout and repr.\n", nFailHaveRepr ); // return 0; } // printf( "Gia_ManHasChoices_very_old(): AIG has %d choice nodes with %d choices.\n", nChoiceNodes, nChoices ); return 1; } /**Function************************************************************* Synopsis [Proving multi-output properties.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManGroupProve( Gia_Man_t * pInit, char * pCommLine, int nGroupSize, int fVerbose ) { Abc_Frame_t * pAbc = Abc_FrameReadGlobalFrame(); Gia_Man_t * p = Gia_ManDup( pInit ); Gia_Man_t * pGroup; Vec_Int_t * vOuts; Vec_Int_t * vOutMap; Vec_Ptr_t * vCexes; int i, k, nGroupCur, nGroups; abctime clk, timeComm = 0; abctime timeStart = Abc_Clock(); // pre-conditions assert( nGroupSize > 0 ); assert( pCommLine != NULL ); assert( p->nConstrs == 0 ); Abc_Print( 1, "RUNNING MultiProve: Group size = %d. Command line = \"%s\".\n", nGroupSize, pCommLine ); // create output map vOuts = Vec_IntStartNatural( Gia_ManPoNum(p) ); vOutMap = Vec_IntAlloc( Gia_ManPoNum(p) ); vCexes = Vec_PtrAlloc( Gia_ManPoNum(p) ); nGroups = Gia_ManPoNum(p) / nGroupSize + (int)((Gia_ManPoNum(p) % nGroupSize) > 0); for ( i = 0; i < nGroups; i++ ) { // derive the group nGroupCur = ((i + 1) * nGroupSize < Gia_ManPoNum(p)) ? nGroupSize : Gia_ManPoNum(p) - i * nGroupSize; pGroup = Gia_ManDupCones( p, Vec_IntArray(vOuts) + i * nGroupSize, nGroupCur, 0 ); Abc_Print( 1, "GROUP %4d : %4d <= PoId < %4d : ", i, i * nGroupSize, i * nGroupSize + nGroupCur ); // set the current GIA Abc_FrameUpdateGia( pAbc, pGroup ); // solve the group clk = Abc_Clock(); Cmd_CommandExecute( pAbc, pCommLine ); timeComm += Abc_Clock() - clk; // get the solution status if ( nGroupSize == 1 ) { Vec_IntPush( vOutMap, Abc_FrameReadProbStatus(pAbc) ); Vec_PtrPush( vCexes, Abc_FrameReadCex(pAbc) ); } else // if ( nGroupSize > 1 ) { Vec_Int_t * vStatusCur = Abc_FrameReadPoStatuses( pAbc ); Vec_Ptr_t * vCexesCur = Abc_FrameReadCexVec( pAbc ); assert( vStatusCur != NULL ); // only works for "bmc3" and "pdr" // assert( vCexesCur != NULL ); for ( k = 0; k < nGroupCur; k++ ) { Vec_IntPush( vOutMap, Vec_IntEntry(vStatusCur, k) ); Vec_PtrPush( vCexes, vCexesCur ? Vec_PtrEntry(vCexesCur, k) : NULL ); } } } assert( Vec_PtrSize(vCexes) == Gia_ManPoNum(p) ); assert( Vec_IntSize(vOutMap) == Gia_ManPoNum(p) ); // set CEXes if ( Vec_PtrCountZero(vCexes) < Vec_PtrSize(vCexes) ) Abc_FrameReplaceCexVec( pAbc, &vCexes ); else // there is no CEXes Vec_PtrFree( vCexes ); // report the result Abc_Print( 1, "SUMMARY: " ); Abc_Print( 1, "Properties = %6d. ", Gia_ManPoNum(p) ); Abc_Print( 1, "UNSAT = %6d. ", Vec_IntCountEntry(vOutMap, 1) ); Abc_Print( 1, "SAT = %6d. ", Vec_IntCountEntry(vOutMap, 0) ); Abc_Print( 1, "UNDEC = %6d. ", Vec_IntCountEntry(vOutMap, -1) ); Abc_Print( 1, "\n" ); Abc_PrintTime( 1, "Command time", timeComm ); Abc_PrintTime( 1, "Total time ", Abc_Clock() - timeStart ); // cleanup Vec_IntFree( vOuts ); Gia_ManStop( p ); return vOutMap; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Gia_ManPoXSim( Gia_Man_t * p, int nFrames, int fVerbose ) { Vec_Int_t * vRes; Gia_Obj_t * pObj; int f, k, nLeft = Gia_ManPoNum(p); vRes = Vec_IntAlloc( Gia_ManPoNum(p) ); Vec_IntFill( vRes, Gia_ManPoNum(p), nFrames ); Gia_ObjTerSimSet0( Gia_ManConst0(p) ); Gia_ManForEachRi( p, pObj, k ) Gia_ObjTerSimSet0( pObj ); for ( f = 0; f < nFrames; f++ ) { Gia_ManForEachPi( p, pObj, k ) Gia_ObjTerSimSetX( pObj ); Gia_ManForEachRo( p, pObj, k ) Gia_ObjTerSimRo( p, pObj ); Gia_ManForEachAnd( p, pObj, k ) Gia_ObjTerSimAnd( pObj ); Gia_ManForEachCo( p, pObj, k ) Gia_ObjTerSimCo( pObj ); if ( fVerbose ) { Gia_ManForEachPo( p, pObj, k ) Gia_ObjTerSimPrint( pObj ); printf( "\n" ); } Gia_ManForEachPo( p, pObj, k ) if ( Vec_IntEntry(vRes, k) == nFrames && Gia_ObjTerSimGetX(pObj) ) Vec_IntWriteEntry(vRes, k, f), nLeft--; if ( nLeft == 0 ) break; } if ( fVerbose ) { if ( nLeft == 0 ) printf( "Simulation converged after %d frames.\n", f+1 ); else printf( "Simulation terminated after %d frames.\n", nFrames ); } // Vec_IntPrint( vRes ); return vRes; } #define MAX_LUT_SIZE 8 typedef struct Gia_MapLut_t_ { int Type; // node type: PI=1, PO=2, LUT=3 int Out; // ID int StartId; // -1 int nFans; // fanin count float Delay; // 0.0 int pFans[MAX_LUT_SIZE]; // fanin IDs unsigned pTruth[MAX_LUT_SIZE<6?1:(1<<(MAX_LUT_SIZE-5))]; // the truth table } Gia_MapLut_t; /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_AigerWriteLut( Gia_Man_t * p, char * pFileName ) { Gia_Obj_t * pObj; int i, k, iFan, iLut = 0; int LutSizeMax = Gia_ManLutSizeMax( p ); int nUints = Abc_TruthWordNum(LutSizeMax); int nLuts = 1 + Gia_ManCiNum(p) + Gia_ManCoNum(p) + Gia_ManLutNum(p); Gia_MapLut_t * pLuts = ABC_CALLOC( Gia_MapLut_t, nLuts ); Vec_Wrd_t * vTruths = Vec_WrdStart( Gia_ManObjNum(p) ); assert( LutSizeMax <= 6 ); // set obj numbers // constant pLuts->Type = 3; memset( pLuts->pTruth, 0xFF, sizeof(unsigned) * nUints ); Gia_ManFillValue(p); Gia_ManConst0(p)->Value = pLuts[iLut].Out = Abc_Var2Lit( iLut, 0 ); iLut++; // inputs Gia_ManForEachCi( p, pObj, i ) { pLuts[iLut].Type = 1; memset( pLuts[iLut].pTruth, 0xAA, sizeof(unsigned) * nUints ); pObj->Value = pLuts[iLut].Out = Abc_Var2Lit( iLut, 0 ); iLut++; } // nodes 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; truth = Gia_LutComputeTruth6(p, i, vTruths); memcpy( pLuts[iLut].pTruth, &truth, sizeof(word) ); pObj->Value = pLuts[iLut].Out = Abc_Var2Lit( iLut, 0 ); iLut++; } // outputs Gia_ManForEachCo( p, pObj, i ) { pLuts[iLut].Type = 2; pLuts[iLut].pFans[0] = Gia_ObjFanin0(pObj)->Value; if ( Gia_ObjFaninC0(pObj) ^ Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) memset( pLuts[iLut].pTruth, 0x55, sizeof(unsigned) * nUints ); else memset( pLuts[iLut].pTruth, 0xAA, sizeof(unsigned) * nUints ); pLuts[iLut].nFans = 1; pObj->Value = pLuts[iLut].Out = Abc_Var2Lit( iLut, 0 ); iLut++; } assert( iLut == nLuts ); // dump into a file { FILE * pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) printf( "Cannot open file \"%s\" for writing.\n", pFileName ); else { int nSize1 = nLuts * sizeof(Gia_MapLut_t); int nSize2 = fwrite( pLuts, 1, nSize1, pFile ); assert( nSize1 == nSize2 ); printf( "Successfully dumped %d bytes of binary data.\n", nSize1 ); } fclose( pFile ); } ABC_FREE( pLuts ); Vec_WrdFree( vTruths ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_DumpLutSizeDistrib( Gia_Man_t * p, char * pFileName ) { FILE * pTable = fopen( pFileName, "a+" ); int i, Counts[10] = {0}; Gia_ManForEachLut( p, i ) if ( Gia_ObjLutSize(p, i) > 0 && Gia_ObjLutSize(p, i) < 10 ) Counts[ Gia_ObjLutSize(p, i) ]++; fprintf( pTable, "%s", p->pName ); for ( i = 1; i < 10; i++ ) fprintf( pTable, " %d", Counts[i] ); fprintf( pTable, "\n" ); fclose( pTable ); } /**Function************************************************************* Synopsis [Check if two logic cones have overlap.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManCheckSuppMark_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( pObj->fMark0 ) return; pObj->fMark0 = 1; if ( Gia_ObjIsCi(pObj) ) return; Gia_ManCheckSuppMark_rec( p, Gia_ObjFanin0(pObj) ); Gia_ManCheckSuppMark_rec( p, Gia_ObjFanin1(pObj) ); } void Gia_ManCheckSuppUnmark_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( !pObj->fMark0 ) return; pObj->fMark0 = 0; if ( Gia_ObjIsCi(pObj) ) return; Gia_ManCheckSuppUnmark_rec( p, Gia_ObjFanin0(pObj) ); Gia_ManCheckSuppUnmark_rec( p, Gia_ObjFanin1(pObj) ); } int Gia_ManCheckSupp_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( pObj->fMark0 ) return 1; if ( Gia_ObjIsCi(pObj) ) return 0; if ( Gia_ManCheckSupp_rec( p, Gia_ObjFanin0(pObj) ) ) return 1; return Gia_ManCheckSupp_rec( p, Gia_ObjFanin1(pObj) ); } int Gia_ManCheckSuppOverlap( Gia_Man_t * p, int iNode1, int iNode2 ) { int Result; if ( iNode1 == 0 || iNode2 == 0 ) return 0; Gia_ManCheckSuppMark_rec( p, Gia_ManObj(p, iNode1) ); Result = Gia_ManCheckSupp_rec( p, Gia_ManObj(p, iNode2) ); Gia_ManCheckSuppUnmark_rec( p, Gia_ManObj(p, iNode1) ); 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" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_GetMValue( int i, int nIns, int Mint, unsigned Truth ) { assert( i >= 0 && i < 16 ); if ( i < nIns ) return (Mint >> i) & 1; if ( i == nIns ) { if ( Mint < (1 << nIns) ) return (Truth >> Mint) & 1; else return ((Truth >> (Mint-(1 << nIns))) & 1) == 0; } else return 1; } void Gia_ManTestProblem() { unsigned Truth = 0xFE; int i, j, k, c, nIns = 3, nAux = 3; int nTotal = nIns + 1 + nAux; int nPairs = nTotal * (nTotal - 1) / 2; int nMints = (1 << (nIns+1)); int M[64][100] = {{0}}; float Value[64] = {0}; float Solution[100] = {0}; assert( nMints <= 64 ); assert( nPairs <= 100 ); // 7 nodes: 3 inputs + 1 output + 3 aux // 7*6/2 = 21 pairs // 16 minterms for ( k = 0; k < nMints; k++ ) { for ( i = c = 0; i < nTotal; i++ ) for ( j = i+1; j < nTotal; j++ ) { int iVal = Gia_GetMValue( i, nIns, k, Truth ); int jVal = Gia_GetMValue( j, nIns, k, Truth ); M[k][c++] = iVal == jVal ? 1 : -1; } Value[k] = k < (1 << nIns) ? -1 : 1; assert( c == nPairs ); } for ( k = 0; k < nMints; k++ ) { for ( c = 0; c < nPairs; c++ ) printf( "%2d ", M[k][c] ); printf( "%3f\n", Value[k] ); } // solve float Delta = 0.02; for ( i = 0; i < 100; i++ ) { float Error = 0; for ( k = 0; k < nMints; k++ ) Error += Value[k] > 0 ? Value[k] : -Value[k]; printf( "Round %3d : Error = %5f ", i, Error ); for ( c = 0; c < nPairs; c++ ) printf( "%2f ", Solution[c] ); printf( "\n" ); //if ( Error < 1 ) // Delta /= 10; for ( c = 0; c < nPairs; c++ ) { int Count = 0; for ( k = 0; k < nMints; k++ ) if ( (M[k][c] > 0 && Value[k] > 0) || (M[k][c] < 0 && Value[k] < 0) ) Count++; else Count--; if ( Count == 0 ) continue; printf( "Count = %3d ", Count ); if ( Count > 0 ) { printf( "Increasing %d by %f\n", c, Delta ); Solution[c] += Delta; for ( k = 0; k < nMints; k++ ) if ( M[k][c] > 0 ) Value[k] -= Delta; else Value[k] -= Delta; } else { printf( "Reducing %d by %f\n", c, Delta ); Solution[c] -= Delta; for ( k = 0; k < nMints; k++ ) if ( M[k][c] > 0 ) Value[k] += Delta; else Value[k] += Delta; } } } } /**Function************************************************************* Synopsis [Returns 1 if this window has a topo error (forward path from an output to an input).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManWindowCheckTopoError_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( !Gia_ObjIsAnd(pObj) ) return 0; if ( Gia_ObjIsTravIdPrevious(p, pObj) ) return 1; // there is an error if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 0; // there is no error; visited this node before Gia_ObjSetTravIdPrevious(p, pObj); if ( Gia_ManWindowCheckTopoError_rec(p, Gia_ObjFanin0(pObj)) || Gia_ManWindowCheckTopoError_rec(p, Gia_ObjFanin1(pObj)) ) return 1; Gia_ObjSetTravIdCurrent(p, pObj); return 0; } int Gia_ManWindowCheckTopoError( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vOuts ) { Gia_Obj_t * pObj; int i, fError = 0; // outputs should be internal nodes Gia_ManForEachObjVec( vOuts, p, pObj, i ) assert(Gia_ObjIsAnd(pObj)); // mark outputs Gia_ManIncrementTravId( p ); Gia_ManForEachObjVec( vOuts, p, pObj, i ) Gia_ObjSetTravIdCurrent(p, pObj); // start from inputs and make sure we do not reach any of the outputs Gia_ManIncrementTravId( p ); Gia_ManForEachObjVec( vIns, p, pObj, i ) fError |= Gia_ManWindowCheckTopoError_rec(p, pObj); return fError; } /**Function************************************************************* Synopsis [Updates the AIG after multiple windows have been optimized.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManDupInsertWindows_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vMap, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vWins ) { if ( ~pObj->Value ) return pObj->Value; assert( Gia_ObjIsAnd(pObj) ); if ( Vec_IntEntry(vMap, Gia_ObjId(p, pObj)) == -1 ) // this is a regular node { Gia_ManDupInsertWindows_rec( pNew, p, Gia_ObjFanin0(pObj), vMap, vvIns, vvOuts, vWins ); Gia_ManDupInsertWindows_rec( pNew, p, Gia_ObjFanin1(pObj), vMap, vvIns, vvOuts, vWins ); return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); } // this node is an output of a window int iWin = Vec_IntEntry(vMap, Gia_ObjId(p, pObj)); Vec_Int_t * vIns = (Vec_Int_t *)Vec_PtrEntry(vvIns, iWin); Vec_Int_t * vOuts = (Vec_Int_t *)Vec_PtrEntry(vvOuts, iWin); Gia_Man_t * pWin = (Gia_Man_t *)Vec_PtrEntry(vWins, iWin); // build transinvite fanins of window inputs Gia_Obj_t * pNode; int i; Gia_ManConst0(pWin)->Value = 0; Gia_ManForEachObjVec( vIns, p, pNode, i ) Gia_ManPi(pWin, i)->Value = Gia_ManDupInsertWindows_rec( pNew, p, pNode, vMap, vvIns, vvOuts, vWins ); // add window nodes Gia_ManForEachAnd( pWin, pNode, i ) pNode->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pNode), Gia_ObjFanin1Copy(pNode) ); // transfer to window outputs Gia_ManForEachObjVec( vOuts, p, pNode, i ) pNode->Value = Gia_ObjFanin0Copy(Gia_ManPo(pWin, i)); assert( ~pObj->Value ); return pObj->Value; } Gia_Man_t * Gia_ManDupInsertWindows( Gia_Man_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vWins ) { // check consistency of input data Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, k, iNode; Vec_PtrForEachEntry( Gia_Man_t *, vWins, pTemp, i ) { Vec_Int_t * vIns = (Vec_Int_t *)Vec_PtrEntry(vvIns, i); Vec_Int_t * vOuts = (Vec_Int_t *)Vec_PtrEntry(vvOuts, i); assert( Vec_IntSize(vIns) == Gia_ManPiNum(pTemp) ); assert( Vec_IntSize(vOuts) == Gia_ManPoNum(pTemp) ); assert( !Gia_ManWindowCheckTopoError(p, vIns, vOuts) ); } // create mapping of window outputs into window IDs Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ), * vOuts; Vec_PtrForEachEntry( Vec_Int_t *, vvOuts, vOuts, i ) Vec_IntForEachEntry( vOuts, iNode, k ) Vec_IntWriteEntry( vMap, iNode, i ); // create the resulting AIG by performing DFS from the POs of the original AIG // it goes recursively through original nodes and windows until it reaches the PIs of the original AIG pNew = Gia_ManStart( Gia_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); Gia_ManHashAlloc( pNew ); Gia_ManFillValue( p ); Gia_ManConst0(p)->Value = 0; Gia_ManForEachCi( p, pObj, i ) pObj->Value = Gia_ManAppendCi(pNew); Gia_ManForEachCo( p, pObj, i ) Gia_ManDupInsertWindows_rec( pNew, p, Gia_ObjFanin0(pObj), vMap, vvIns, vvOuts, vWins ); Gia_ManForEachCo( p, pObj, i ) Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); // cleanup and return Vec_IntFree( vMap ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); //Gia_ManPrint( pNew ); return pNew; } /**Function************************************************************* Synopsis [Computing equivalent nodes across the two AIGs.] Description [Assumes that both AIGs are structurally hashed without dandling nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManCreateDualOutputMiter( Gia_Man_t * p0, Gia_Man_t * p1 ) { Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; assert( Gia_ManCiNum(p0) == Gia_ManCiNum(p1) ); assert( Gia_ManCoNum(p0) == Gia_ManCoNum(p1) ); // start the manager pNew = Gia_ManStart( Gia_ManObjNum(p0) + Gia_ManObjNum(p1) ); pNew->pName = Abc_UtilStrsav( "miter" ); Gia_ManFillValue( p0 ); Gia_ManFillValue( p1 ); // map combinational inputs Gia_ManConst0(p0)->Value = 0; Gia_ManConst0(p1)->Value = 0; Gia_ManForEachCi( p0, pObj, i ) Gia_ManCi(p1, i)->Value = pObj->Value = Gia_ManAppendCi( pNew ); // map internal nodes and outputs Gia_ManHashAlloc( pNew ); Gia_ManForEachAnd( p0, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); assert( Gia_ManAndNum(pNew) == Gia_ManAndNum(p0) ); // the input AIG p0 is structurally hashed Gia_ManForEachAnd( p1, pObj, i ) pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); // add the outputs Gia_ManForEachCo( p0, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); Gia_ManForEachCo( p1, pObj, i ) pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); printf( "The two AIGs have %d structurally equivalent nodes.\n", Gia_ManAndNum(p0) + Gia_ManAndNum(p1) - Gia_ManAndNum(pNew) ); // there should be no dangling nodes (otherwise, the second AIG may not be structurally hashed) int nDangling = Gia_ManMarkDangling(pNew); assert( nDangling == 0 ); Gia_ManCleanMark01(pNew); return pNew; } Vec_Int_t * Gia_ManFindMutualEquivs( Gia_Man_t * p0, Gia_Man_t * p1, int nConflictLimit, int fVerbose ) { Vec_Int_t * vPairs = Vec_IntAlloc( 100 ); // derive the miter Gia_Man_t * pMiter = Gia_ManCreateDualOutputMiter( p0, p1 ); //Gia_ManPrintStats( pMiter, NULL ); //Gia_AigerWrite( pMiter, "out.aig", 0, 0, 0 ); // perform SAT sweeping extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); Gia_Man_t * pNew = Cec4_ManSimulateTest3( pMiter, nConflictLimit, fVerbose ); Gia_ManStop( pNew ); // now, pMiter is annotated with the equiv class info // here we collect AIG node pairs with the following properties: // - the first node belongs to p0; the second node belongs to p1 // - both nodes are internal nodes of p0 and p1 (not primary inputs/outputs) // - these nodes are combinationally equivalent (possibly up to the complement) // - these nodes are "singleton" equivalences (no other nodes in p0 and p1 are equivalent to them) // - these nodes are not structurally equivalent (that is, they have structurally different TFI logic cones) // count the number of nodes in each equivalence class Vec_Int_t * vCounts = Vec_IntStart( Gia_ManObjNum(pMiter) ); Gia_Obj_t * pObj; int i, k; Gia_ManForEachClass( pMiter, i ) Gia_ClassForEachObj( pMiter, i, k ) Vec_IntAddToEntry( vCounts, i, 1 ); // map each miter node coming from p1 into the corresponding node in p1 Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(pMiter) ); int iStartP1 = 1 + Gia_ManPiNum(p0) + Gia_ManAndNum(p0); Gia_ManForEachAnd( p1, pObj, i ) if ( Abc_Lit2Var(pObj->Value) >= iStartP1 ) // node from p1 (not from p0) Vec_IntWriteEntry( vMap, Abc_Lit2Var(pObj->Value), i ); // go through functionally (not structurally!) equivalent nodes in the second AIG // and collect those node pairs from p0 and p1 whose equivalence class contains exactly two nodes for ( i = iStartP1; i < Gia_ManObjNum(pMiter) - Gia_ManCoNum(pMiter); i++ ) { assert( Gia_ObjIsAnd(Gia_ManObj(pMiter, i)) ); int Repr = Gia_ObjRepr(pMiter, i); if ( Repr == GIA_VOID || Repr >= iStartP1 || Vec_IntEntry(vCounts, Repr) != 2 ) continue; assert( Repr < iStartP1 ); // node in p0 assert( Vec_IntEntry(vMap, i) > 0 ); // node in p1 Vec_IntPushTwo( vPairs, Repr, Vec_IntEntry(vMap, i) ); } // cleanup Vec_IntFree( vMap ); Vec_IntFree( vCounts ); Gia_ManStop( pMiter ); return vPairs; } void Gia_ManFindMutualEquivsTest() { Gia_Man_t * p0 = Gia_AigerRead( "p0.aig", 0, 0, 0 ); Gia_Man_t * p1 = Gia_AigerRead( "p1.aig", 0, 0, 0 ); Vec_Int_t * vPairs = Gia_ManFindMutualEquivs( p0, p1, 0, 0 ); printf( "Pair Aig0 node Aig1 node\n" ); int i, Obj0, Obj1; Vec_IntForEachEntryDouble( vPairs, Obj0, Obj1, i ) printf( "%3d %6d %6d\n", i/2, Obj0, Obj1 ); Gia_ManStop( p0 ); Gia_ManStop( p1 ); Vec_IntFree( vPairs ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/gia/module.make000066400000000000000000000063431477524141600164210ustar00rootroot00000000000000SRC += src/aig/gia/giaAig.c \ src/aig/gia/giaAgi.c \ src/aig/gia/giaAiger.c \ src/aig/gia/giaAigerExt.c \ src/aig/gia/giaBalAig.c \ src/aig/gia/giaBalLut.c \ src/aig/gia/giaBalMap.c \ src/aig/gia/giaBidec.c \ src/aig/gia/giaCCof.c \ src/aig/gia/giaCex.c \ src/aig/gia/giaClp.c \ src/aig/gia/giaCof.c \ src/aig/gia/giaCone.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 \ src/aig/gia/giaEmbed.c \ src/aig/gia/giaEnable.c \ src/aig/gia/giaEquiv.c \ src/aig/gia/giaEra.c \ src/aig/gia/giaEra2.c \ src/aig/gia/giaEsop.c \ src/aig/gia/giaExist.c \ src/aig/gia/giaFalse.c \ src/aig/gia/giaFanout.c \ src/aig/gia/giaForce.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 \ src/aig/gia/giaIf.c \ src/aig/gia/giaIff.c \ src/aig/gia/giaIiff.c \ src/aig/gia/giaIso.c \ src/aig/gia/giaIso2.c \ src/aig/gia/giaIso3.c \ src/aig/gia/giaJf.c \ src/aig/gia/giaKf.c \ src/aig/gia/giaLf.c \ src/aig/gia/giaMf.c \ src/aig/gia/giaMan.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/giaMulFind.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/giaRrr.cpp \ src/aig/gia/giaSatEdge.c \ src/aig/gia/giaSatLE.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 \ src/aig/gia/giaShow.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 \ src/aig/gia/giaBound.c abc-0.52/src/aig/hop/000077500000000000000000000000001477524141600143155ustar00rootroot00000000000000abc-0.52/src/aig/hop/cudd2.c000066400000000000000000000240521477524141600154650ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cudd2.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Minimalistic And-Inverter Graph package.] Synopsis [Recording AIGs for the BDD operations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 3, 2006.] Revision [$Id: cudd2.c,v 1.00 2006/10/03 00:00:00 alanmi Exp $] ***********************************************************************/ #include "hop.h" #include "misc/st/st.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Aig_CuddMan_t_ Aig_CuddMan_t; struct Aig_CuddMan_t_ { Aig_Man_t * pAig; // internal AIG package st__table * pTable; // hash table mapping BDD nodes into AIG nodes }; // static Cudd AIG manager used in this experiment static Aig_CuddMan_t * s_pCuddMan = NULL; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Start AIG recording.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cudd2_Init( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd ) { int v; // start the BDD-to-AIG manager when the first BDD manager is allocated if ( s_pCuddMan != NULL ) return; s_pCuddMan = ALLOC( Aig_CuddMan_t, 1 ); s_pCuddMan->pAig = Aig_ManStart(); s_pCuddMan->pTable = st__init_table( st__ptrcmp, st__ptrhash ); for ( v = 0; v < (int)numVars; v++ ) Aig_ObjCreatePi( s_pCuddMan->pAig ); } /**Function************************************************************* Synopsis [Stops AIG recording.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cudd2_Quit( void * pCudd ) { assert( s_pCuddMan != NULL ); Aig_ManDumpBlif( s_pCuddMan->pAig, "aig_temp.blif", NULL, NULL ); Aig_ManStop( s_pCuddMan->pAig ); st__free_table( s_pCuddMan->pTable ); free( s_pCuddMan ); s_pCuddMan = NULL; } /**Function************************************************************* Synopsis [Fetches AIG node corresponding to the BDD node from the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static Aig_Obj_t * Cudd2_GetArg( void * pArg ) { Aig_Obj_t * pNode; assert( s_pCuddMan != NULL ); if ( ! st__lookup( s_pCuddMan->pTable, (char *)Aig_Regular(pArg), (char **)&pNode ) ) { printf( "Cudd2_GetArg(): An argument BDD is not in the hash table.\n" ); return NULL; } return Aig_NotCond( pNode, Aig_IsComplement(pArg) ); } /**Function************************************************************* Synopsis [Inserts the AIG node corresponding to the BDD node into the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Cudd2_SetArg( Aig_Obj_t * pNode, void * pResult ) { assert( s_pCuddMan != NULL ); if ( st__is_member( s_pCuddMan->pTable, (char *)Aig_Regular(pResult) ) ) return; pNode = Aig_NotCond( pNode, Aig_IsComplement(pResult) ); st__insert( s_pCuddMan->pTable, (char *)Aig_Regular(pResult), (char *)pNode ); } /**Function************************************************************* Synopsis [Registers constant 1 node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cudd2_bddOne( void * pCudd, void * pResult ) { Cudd2_SetArg( Aig_ManConst1(s_pCuddMan->pAig), pResult ); } /**Function************************************************************* Synopsis [Adds elementary variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cudd2_bddIthVar( void * pCudd, int iVar, void * pResult ) { int v; assert( s_pCuddMan != NULL ); for ( v = Aig_ManPiNum(s_pCuddMan->pAig); v <= iVar; v++ ) Aig_ObjCreatePi( s_pCuddMan->pAig ); Cudd2_SetArg( Aig_ManPi(s_pCuddMan->pAig, iVar), pResult ); } /**Function************************************************************* Synopsis [Performs BDD operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cudd2_bddAnd( void * pCudd, void * pArg0, void * pArg1, void * pResult ) { Aig_Obj_t * pNode0, * pNode1, * pNode; pNode0 = Cudd2_GetArg( pArg0 ); pNode1 = Cudd2_GetArg( pArg1 ); pNode = Aig_And( s_pCuddMan->pAig, pNode0, pNode1 ); Cudd2_SetArg( pNode, pResult ); } /**Function************************************************************* Synopsis [Performs BDD operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cudd2_bddOr( void * pCudd, void * pArg0, void * pArg1, void * pResult ) { Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), Aig_Not(pResult) ); } /**Function************************************************************* Synopsis [Performs BDD operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cudd2_bddNand( void * pCudd, void * pArg0, void * pArg1, void * pResult ) { Cudd2_bddAnd( pCudd, pArg0, pArg1, Aig_Not(pResult) ); } /**Function************************************************************* Synopsis [Performs BDD operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cudd2_bddNor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) { Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), pResult ); } /**Function************************************************************* Synopsis [Performs BDD operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cudd2_bddXor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) { Aig_Obj_t * pNode0, * pNode1, * pNode; pNode0 = Cudd2_GetArg( pArg0 ); pNode1 = Cudd2_GetArg( pArg1 ); pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 ); Cudd2_SetArg( pNode, pResult ); } /**Function************************************************************* Synopsis [Performs BDD operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cudd2_bddXnor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) { Cudd2_bddXor( pCudd, pArg0, pArg1, Aig_Not(pResult) ); } /**Function************************************************************* Synopsis [Performs BDD operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cudd2_bddIte( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult ) { Aig_Obj_t * pNode0, * pNode1, * pNode2, * pNode; pNode0 = Cudd2_GetArg( pArg0 ); pNode1 = Cudd2_GetArg( pArg1 ); pNode2 = Cudd2_GetArg( pArg2 ); pNode = Aig_Mux( s_pCuddMan->pAig, pNode0, pNode1, pNode2 ); Cudd2_SetArg( pNode, pResult ); } /**Function************************************************************* Synopsis [Performs BDD operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult ) { Aig_Obj_t * pNode0, * pNode1, * pNode; pNode0 = Cudd2_GetArg( pArg0 ); pNode1 = Cudd2_GetArg( pArg1 ); pNode = Aig_Compose( s_pCuddMan->pAig, pNode0, pNode1, v ); Cudd2_SetArg( pNode, pResult ); } /**Function************************************************************* Synopsis [Should be called after each containment check.] Description [Result should be 1 if Cudd2_bddLeq returned 1.] SideEffects [] SeeAlso [] ***********************************************************************/ void Cudd2_bddLeq( void * pCudd, void * pArg0, void * pArg1, int Result ) { Aig_Obj_t * pNode0, * pNode1, * pNode; pNode0 = Cudd2_GetArg( pArg0 ); pNode1 = Cudd2_GetArg( pArg1 ); pNode = Aig_And( s_pCuddMan->pAig, pNode0, Aig_Not(pNode1) ); Aig_ObjCreatePo( s_pCuddMan->pAig, pNode ); } /**Function************************************************************* Synopsis [Should be called after each equality check.] Description [Result should be 1 if they are equal.] SideEffects [] SeeAlso [] ***********************************************************************/ void Cudd2_bddEqual( void * pCudd, void * pArg0, void * pArg1, int Result ) { Aig_Obj_t * pNode0, * pNode1, * pNode; pNode0 = Cudd2_GetArg( pArg0 ); pNode1 = Cudd2_GetArg( pArg1 ); pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 ); Aig_ObjCreatePo( s_pCuddMan->pAig, pNode ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/hop/cudd2.h000066400000000000000000000067421477524141600155000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [cudd2.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Minimalistic And-Inverter Graph package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - October 3, 2006.] Revision [$Id: cudd2.h,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__hop__cudd2_h #define ABC__aig__hop__cudd2_h // HA: Added for printing messages #ifndef MSG #define MSG(msg) (printf("%s = \n",(msg))); #endif //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern void Cudd2_Init ( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd ); extern void Cudd2_Quit ( void * pCudd ); extern void Cudd2_bddOne ( void * pCudd, void * pResult ); extern void Cudd2_bddIthVar ( void * pCudd, int iVar, void * pResult ); extern void Cudd2_bddAnd ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); extern void Cudd2_bddOr ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); extern void Cudd2_bddNand ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); extern void Cudd2_bddNor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); extern void Cudd2_bddXor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); extern void Cudd2_bddXnor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); extern void Cudd2_bddIte ( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult ); extern void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult ); extern void Cudd2_bddLeq ( void * pCudd, void * pArg0, void * pArg1, int Result ); extern void Cudd2_bddEqual ( void * pCudd, void * pArg0, void * pArg1, int Result ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/aig/hop/hop.h000066400000000000000000000521441477524141600152620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hop.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Minimalistic And-Inverter Graph package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: hop.h,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__hop__hop_h #define ABC__aig__hop__hop_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "misc/vec/vec.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Hop_Man_t_ Hop_Man_t; typedef struct Hop_Obj_t_ Hop_Obj_t; typedef int Hop_Edge_t; // object types typedef enum { AIG_NONE, // 0: non-existent object AIG_CONST1, // 1: constant 1 AIG_PI, // 2: primary input AIG_PO, // 3: primary output AIG_AND, // 4: AND node AIG_EXOR, // 5: EXOR node AIG_VOID // 6: unused object } Hop_Type_t; // the AIG node struct Hop_Obj_t_ // 6 words { union { void * pData; // misc int iData; }; // misc union { Hop_Obj_t * pNext; // strashing table int PioNum; }; // the number of PI/PO Hop_Obj_t * pFanin0; // fanin Hop_Obj_t * pFanin1; // fanin unsigned int Type : 3; // object type unsigned int fPhase : 1; // value under 000...0 pattern unsigned int fMarkA : 1; // multipurpose mask unsigned int fMarkB : 1; // multipurpose mask unsigned int nRefs : 26; // reference count (level) int Id; // unique ID of the node }; // the AIG manager struct Hop_Man_t_ { // AIG nodes Vec_Ptr_t * vPis; // the array of PIs Vec_Ptr_t * vPos; // the array of POs Vec_Ptr_t * vObjs; // the array of all nodes (optional) Hop_Obj_t * pConst1; // the constant 1 node Hop_Obj_t Ghost; // the ghost node // AIG node counters int nObjs[AIG_VOID];// the number of objects by type int nCreated; // the number of created objects int nDeleted; // the number of deleted objects // stuctural hash table Hop_Obj_t ** pTable; // structural hash table int nTableSize; // structural hash table size // various data members void * pData; // the temporary data int nTravIds; // the current traversal ID int fRefCount; // enables reference counting int fCatchExor; // enables EXOR nodes // memory management Vec_Ptr_t * vChunks; // allocated memory pieces Vec_Ptr_t * vPages; // memory pages used by nodes Hop_Obj_t * pListFree; // the list of free nodes // timing statistics abctime time1; abctime time2; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// extern void Hop_ManAddMemory( Hop_Man_t * p ); static inline int Hop_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } static inline int Hop_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } static inline int Hop_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } static inline void Hop_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } static inline void Hop_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } static inline int Hop_Base2Log( unsigned n ) { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n >>= 1, r++ ) {}; return r; } static inline int Hop_Base10Log( unsigned n ) { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 10, r++ ) {}; return r; } static inline Hop_Obj_t * Hop_Regular( Hop_Obj_t * p ) { return (Hop_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } static inline Hop_Obj_t * Hop_Not( Hop_Obj_t * p ) { return (Hop_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } static inline Hop_Obj_t * Hop_NotCond( Hop_Obj_t * p, int c ) { return (Hop_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } static inline int Hop_IsComplement( Hop_Obj_t * p ) { return (int)((ABC_PTRUINT_T)(p) & 01); } static inline Hop_Obj_t * Hop_ManConst0( Hop_Man_t * p ) { return Hop_Not(p->pConst1); } static inline Hop_Obj_t * Hop_ManConst1( Hop_Man_t * p ) { return p->pConst1; } static inline Hop_Obj_t * Hop_ManGhost( Hop_Man_t * p ) { return &p->Ghost; } static inline Hop_Obj_t * Hop_ManPi( Hop_Man_t * p, int i ) { return (Hop_Obj_t *)Vec_PtrEntry(p->vPis, i); } static inline Hop_Obj_t * Hop_ManPo( Hop_Man_t * p, int i ) { return (Hop_Obj_t *)Vec_PtrEntry(p->vPos, i); } static inline Hop_Obj_t * Hop_ManObj( Hop_Man_t * p, int i ) { return p->vObjs ? (Hop_Obj_t *)Vec_PtrEntry(p->vObjs, i) : NULL; } static inline Hop_Edge_t Hop_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } static inline int Hop_EdgeId( Hop_Edge_t Edge ) { return Edge >> 1; } static inline int Hop_EdgeIsComplement( Hop_Edge_t Edge ) { return Edge & 1; } static inline Hop_Edge_t Hop_EdgeRegular( Hop_Edge_t Edge ) { return (Edge >> 1) << 1; } static inline Hop_Edge_t Hop_EdgeNot( Hop_Edge_t Edge ) { return Edge ^ 1; } static inline Hop_Edge_t Hop_EdgeNotCond( Hop_Edge_t Edge, int fCond ) { return Edge ^ fCond; } static inline int Hop_ManPiNum( Hop_Man_t * p ) { return p->nObjs[AIG_PI]; } static inline int Hop_ManPoNum( Hop_Man_t * p ) { return p->nObjs[AIG_PO]; } static inline int Hop_ManAndNum( Hop_Man_t * p ) { return p->nObjs[AIG_AND]; } static inline int Hop_ManExorNum( Hop_Man_t * p ) { return p->nObjs[AIG_EXOR]; } static inline int Hop_ManNodeNum( Hop_Man_t * p ) { return p->nObjs[AIG_AND]+p->nObjs[AIG_EXOR];} static inline int Hop_ManGetCost( Hop_Man_t * p ) { return p->nObjs[AIG_AND]+3*p->nObjs[AIG_EXOR]; } static inline int Hop_ManObjNum( Hop_Man_t * p ) { return p->nCreated - p->nDeleted; } static inline Hop_Type_t Hop_ObjType( Hop_Obj_t * pObj ) { return (Hop_Type_t)pObj->Type; } static inline int Hop_ObjIsNone( Hop_Obj_t * pObj ) { return pObj->Type == AIG_NONE; } static inline int Hop_ObjIsConst1( Hop_Obj_t * pObj ) { assert(!Hop_IsComplement(pObj)); return pObj->Type == AIG_CONST1; } static inline int Hop_ObjIsPi( Hop_Obj_t * pObj ) { return pObj->Type == AIG_PI; } static inline int Hop_ObjIsPo( Hop_Obj_t * pObj ) { return pObj->Type == AIG_PO; } static inline int Hop_ObjIsAnd( Hop_Obj_t * pObj ) { return pObj->Type == AIG_AND; } static inline int Hop_ObjIsExor( Hop_Obj_t * pObj ) { return pObj->Type == AIG_EXOR; } static inline int Hop_ObjIsNode( Hop_Obj_t * pObj ) { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR; } static inline int Hop_ObjIsTerm( Hop_Obj_t * pObj ) { return pObj->Type == AIG_PI || pObj->Type == AIG_PO || pObj->Type == AIG_CONST1; } static inline int Hop_ObjIsHash( Hop_Obj_t * pObj ) { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR; } static inline int Hop_ObjIsMarkA( Hop_Obj_t * pObj ) { return pObj->fMarkA; } static inline void Hop_ObjSetMarkA( Hop_Obj_t * pObj ) { pObj->fMarkA = 1; } static inline void Hop_ObjClearMarkA( Hop_Obj_t * pObj ) { pObj->fMarkA = 0; } static inline void Hop_ObjSetTravId( Hop_Obj_t * pObj, int TravId ) { pObj->pData = (void *)(ABC_PTRINT_T)TravId; } static inline void Hop_ObjSetTravIdCurrent( Hop_Man_t * p, Hop_Obj_t * pObj ) { pObj->pData = (void *)(ABC_PTRINT_T)p->nTravIds; } static inline void Hop_ObjSetTravIdPrevious( Hop_Man_t * p, Hop_Obj_t * pObj ) { pObj->pData = (void *)(ABC_PTRINT_T)(p->nTravIds - 1); } static inline int Hop_ObjIsTravIdCurrent( Hop_Man_t * p, Hop_Obj_t * pObj ) { return (int)((int)(ABC_PTRINT_T)pObj->pData == p->nTravIds); } static inline int Hop_ObjIsTravIdPrevious( Hop_Man_t * p, Hop_Obj_t * pObj ) { return (int)((int)(ABC_PTRINT_T)pObj->pData == p->nTravIds - 1); } static inline int Hop_ObjTravId( Hop_Obj_t * pObj ) { return (int)(ABC_PTRINT_T)pObj->pData; } static inline int Hop_ObjPhase( Hop_Obj_t * pObj ) { return pObj->fPhase; } static inline int Hop_ObjRefs( Hop_Obj_t * pObj ) { return pObj->nRefs; } static inline void Hop_ObjRef( Hop_Obj_t * pObj ) { pObj->nRefs++; } static inline void Hop_ObjDeref( Hop_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } static inline void Hop_ObjClearRef( Hop_Obj_t * pObj ) { pObj->nRefs = 0; } static inline int Hop_ObjFaninC0( Hop_Obj_t * pObj ) { return Hop_IsComplement(pObj->pFanin0); } static inline int Hop_ObjFaninC1( Hop_Obj_t * pObj ) { return Hop_IsComplement(pObj->pFanin1); } static inline Hop_Obj_t * Hop_ObjFanin0( Hop_Obj_t * pObj ) { return Hop_Regular(pObj->pFanin0); } static inline Hop_Obj_t * Hop_ObjFanin1( Hop_Obj_t * pObj ) { return Hop_Regular(pObj->pFanin1); } static inline Hop_Obj_t * Hop_ObjChild0( Hop_Obj_t * pObj ) { return pObj->pFanin0; } static inline Hop_Obj_t * Hop_ObjChild1( Hop_Obj_t * pObj ) { return pObj->pFanin1; } static inline Hop_Obj_t * Hop_ObjChild0Copy( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin0(pObj)? Hop_NotCond((Hop_Obj_t *)Hop_ObjFanin0(pObj)->pData, Hop_ObjFaninC0(pObj)) : NULL; } static inline Hop_Obj_t * Hop_ObjChild1Copy( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin1(pObj)? Hop_NotCond((Hop_Obj_t *)Hop_ObjFanin1(pObj)->pData, Hop_ObjFaninC1(pObj)) : NULL; } static inline int Hop_ObjChild0CopyI( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin0(pObj)? Abc_LitNotCond(Hop_ObjFanin0(pObj)->iData, Hop_ObjFaninC0(pObj)) : -1; } static inline int Hop_ObjChild1CopyI( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin1(pObj)? Abc_LitNotCond(Hop_ObjFanin1(pObj)->iData, Hop_ObjFaninC1(pObj)) : -1; } static inline int Hop_ObjLevel( Hop_Obj_t * pObj ) { return pObj->nRefs; } static inline int Hop_ObjLevelNew( Hop_Obj_t * pObj ) { return 1 + Hop_ObjIsExor(pObj) + Abc_MaxInt(Hop_ObjFanin0(pObj)->nRefs, Hop_ObjFanin1(pObj)->nRefs); } static inline int Hop_ObjPhaseCompl( Hop_Obj_t * pObj ) { return Hop_IsComplement(pObj)? !Hop_Regular(pObj)->fPhase : pObj->fPhase; } static inline void Hop_ObjClean( Hop_Obj_t * pObj ) { memset( pObj, 0, sizeof(Hop_Obj_t) ); } static inline int Hop_ObjWhatFanin( Hop_Obj_t * pObj, Hop_Obj_t * pFanin ) { if ( Hop_ObjFanin0(pObj) == pFanin ) return 0; if ( Hop_ObjFanin1(pObj) == pFanin ) return 1; assert(0); return -1; } static inline int Hop_ObjFanoutC( Hop_Obj_t * pObj, Hop_Obj_t * pFanout ) { if ( Hop_ObjFanin0(pFanout) == pObj ) return Hop_ObjFaninC0(pObj); if ( Hop_ObjFanin1(pFanout) == pObj ) return Hop_ObjFaninC1(pObj); assert(0); return -1; } // create the ghost of the new node static inline Hop_Obj_t * Hop_ObjCreateGhost( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type ) { Hop_Obj_t * pGhost; assert( Type != AIG_AND || !Hop_ObjIsConst1(Hop_Regular(p0)) ); assert( p1 == NULL || !Hop_ObjIsConst1(Hop_Regular(p1)) ); assert( Type == AIG_PI || Hop_Regular(p0) != Hop_Regular(p1) ); pGhost = Hop_ManGhost(p); pGhost->Type = Type; if ( Hop_Regular(p0)->Id < Hop_Regular(p1)->Id ) { pGhost->pFanin0 = p0; pGhost->pFanin1 = p1; } else { pGhost->pFanin0 = p1; pGhost->pFanin1 = p0; } return pGhost; } // internal memory manager static inline Hop_Obj_t * Hop_ManFetchMemory( Hop_Man_t * p ) { Hop_Obj_t * pTemp; if ( p->pListFree == NULL ) Hop_ManAddMemory( p ); pTemp = p->pListFree; p->pListFree = *((Hop_Obj_t **)pTemp); memset( pTemp, 0, sizeof(Hop_Obj_t) ); if ( p->vObjs ) { assert( p->nCreated == Vec_PtrSize(p->vObjs) ); Vec_PtrPush( p->vObjs, pTemp ); } pTemp->Id = p->nCreated++; return pTemp; } static inline void Hop_ManRecycleMemory( Hop_Man_t * p, Hop_Obj_t * pEntry ) { pEntry->Type = AIG_NONE; // distinquishes dead node from live node *((Hop_Obj_t **)pEntry) = p->pListFree; p->pListFree = pEntry; } //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// // iterator over the primary inputs #define Hop_ManForEachPi( p, pObj, i ) \ Vec_PtrForEachEntry( Hop_Obj_t *, p->vPis, pObj, i ) // iterator over the primary outputs #define Hop_ManForEachPo( p, pObj, i ) \ Vec_PtrForEachEntry( Hop_Obj_t *, p->vPos, pObj, i ) // iterator over all objects, including those currently not used #define Hop_ManForEachNode( p, pObj, i ) \ for ( i = 0; i < p->nTableSize; i++ ) \ if ( ((pObj) = p->pTable[i]) == NULL ) {} else //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== hopBalance.c ========================================================*/ extern Hop_Man_t * Hop_ManBalance( Hop_Man_t * p, int fUpdateLevel ); extern Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Type_t Type, int fUpdateLevel ); /*=== hopCheck.c ========================================================*/ extern int Hop_ManCheck( Hop_Man_t * p ); /*=== hopDfs.c ==========================================================*/ extern Vec_Ptr_t * Hop_ManDfs( Hop_Man_t * p ); extern Vec_Ptr_t * Hop_ManDfsNode( Hop_Man_t * p, Hop_Obj_t * pNode ); extern int Hop_ManCountLevels( Hop_Man_t * p ); extern void Hop_ManCreateRefs( Hop_Man_t * p ); extern int Hop_DagSize( Hop_Obj_t * pObj ); extern int Hop_ObjFanoutCount( Hop_Obj_t * pObj, Hop_Obj_t * pPivot ); extern void Hop_ConeUnmark_rec( Hop_Obj_t * pObj ); extern Hop_Obj_t * Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pObj, int nVars ); extern Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar ); extern Hop_Obj_t * Hop_Complement( Hop_Man_t * p, Hop_Obj_t * pRoot, int iVar ); extern Hop_Obj_t * Hop_Remap( Hop_Man_t * p, Hop_Obj_t * pRoot, unsigned uSupp, int nVars ); extern Hop_Obj_t * Hop_Permute( Hop_Man_t * p, Hop_Obj_t * pRoot, int nRootVars, int * pPermute ); /*=== hopMan.c ==========================================================*/ extern Hop_Man_t * Hop_ManStart(); extern Hop_Man_t * Hop_ManDup( Hop_Man_t * p ); extern void Hop_ManStop( Hop_Man_t * p ); extern int Hop_ManCleanup( Hop_Man_t * p ); extern void Hop_ManPrintStats( Hop_Man_t * p ); /*=== hopMem.c ==========================================================*/ extern void Hop_ManStartMemory( Hop_Man_t * p ); extern void Hop_ManStopMemory( Hop_Man_t * p ); /*=== hopObj.c ==========================================================*/ extern Hop_Obj_t * Hop_ObjCreatePi( Hop_Man_t * p ); extern Hop_Obj_t * Hop_ObjCreatePo( Hop_Man_t * p, Hop_Obj_t * pDriver ); extern Hop_Obj_t * Hop_ObjCreate( Hop_Man_t * p, Hop_Obj_t * pGhost ); extern void Hop_ObjConnect( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFan0, Hop_Obj_t * pFan1 ); extern void Hop_ObjDisconnect( Hop_Man_t * p, Hop_Obj_t * pObj ); extern void Hop_ObjDelete( Hop_Man_t * p, Hop_Obj_t * pObj ); extern void Hop_ObjDelete_rec( Hop_Man_t * p, Hop_Obj_t * pObj ); extern Hop_Obj_t * Hop_ObjRepr( Hop_Obj_t * pObj ); extern void Hop_ObjCreateChoice( Hop_Obj_t * pOld, Hop_Obj_t * pNew ); /*=== hopOper.c =========================================================*/ extern Hop_Obj_t * Hop_IthVar( Hop_Man_t * p, int i ); extern Hop_Obj_t * Hop_Oper( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type ); extern Hop_Obj_t * Hop_And( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ); extern Hop_Obj_t * Hop_Or( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ); extern Hop_Obj_t * Hop_Exor( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ); extern Hop_Obj_t * Hop_Mux( Hop_Man_t * p, Hop_Obj_t * pC, Hop_Obj_t * p1, Hop_Obj_t * p0 ); extern Hop_Obj_t * Hop_Maj( Hop_Man_t * p, Hop_Obj_t * pA, Hop_Obj_t * pB, Hop_Obj_t * pC ); extern Hop_Obj_t * Hop_Miter( Hop_Man_t * p, Vec_Ptr_t * vPairs ); extern Hop_Obj_t * Hop_CreateAnd( Hop_Man_t * p, int nVars ); extern Hop_Obj_t * Hop_CreateOr( Hop_Man_t * p, int nVars ); extern Hop_Obj_t * Hop_CreateExor( Hop_Man_t * p, int nVars ); /*=== hopTable.c ========================================================*/ extern Hop_Obj_t * Hop_TableLookup( Hop_Man_t * p, Hop_Obj_t * pGhost ); extern void Hop_TableInsert( Hop_Man_t * p, Hop_Obj_t * pObj ); extern void Hop_TableDelete( Hop_Man_t * p, Hop_Obj_t * pObj ); extern int Hop_TableCountEntries( Hop_Man_t * p ); extern void Hop_TableProfile( Hop_Man_t * p ); /*=== hopTruth.c ========================================================*/ extern unsigned * Hop_ManConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, int fMsbFirst ); extern word Hop_ManComputeTruth6( Hop_Man_t * p, Hop_Obj_t * pObj, int nVars ); /*=== hopUtil.c =========================================================*/ extern void Hop_ManIncrementTravId( Hop_Man_t * p ); extern void Hop_ManCleanData( Hop_Man_t * p ); extern void Hop_ObjCleanData_rec( Hop_Obj_t * pObj ); extern void Hop_ObjCollectMulti( Hop_Obj_t * pFunc, Vec_Ptr_t * vSuper ); extern int Hop_ObjIsMuxType( Hop_Obj_t * pObj ); extern int Hop_ObjRecognizeExor( Hop_Obj_t * pObj, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 ); extern Hop_Obj_t * Hop_ObjRecognizeMux( Hop_Obj_t * pObj, Hop_Obj_t ** ppObjT, Hop_Obj_t ** ppObjE ); extern void Hop_ObjPrintEqn( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); extern void Hop_ObjPrintVerilog( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level, int fOnlyAnds ); extern void Hop_ObjPrintVerbose( Hop_Obj_t * pObj, int fHaig ); extern void Hop_ManPrintVerbose( Hop_Man_t * p, int fHaig ); extern void Hop_ManDumpBlif( Hop_Man_t * p, char * pFileName ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/aig/hop/hopBalance.c000066400000000000000000000332631477524141600165240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hopBalance.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Minimalistic And-Inverter Graph package.] Synopsis [Algebraic AIG balancing.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: hopBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "hop.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel ); static Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level ); static int Hop_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ); static void Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ); static void Hop_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Hop_Obj_t * pObj ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs algebraic balancing of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Man_t * Hop_ManBalance( Hop_Man_t * p, int fUpdateLevel ) { Hop_Man_t * pNew; Hop_Obj_t * pObj, * pObjNew; Vec_Vec_t * vStore; int i; // create the new manager pNew = Hop_ManStart(); pNew->fRefCount = 0; // map the PI nodes Hop_ManCleanData( p ); Hop_ManConst1(p)->pData = Hop_ManConst1(pNew); Hop_ManForEachPi( p, pObj, i ) pObj->pData = Hop_ObjCreatePi(pNew); // balance the AIG vStore = Vec_VecAlloc( 50 ); Hop_ManForEachPo( p, pObj, i ) { pObjNew = Hop_NodeBalance_rec( pNew, Hop_ObjFanin0(pObj), vStore, 0, fUpdateLevel ); Hop_ObjCreatePo( pNew, Hop_NotCond( pObjNew, Hop_ObjFaninC0(pObj) ) ); } Vec_VecFree( vStore ); // remove dangling nodes // Hop_ManCreateRefs( pNew ); // if ( i = Hop_ManCleanup( pNew ) ) // printf( "Cleanup after balancing removed %d dangling nodes.\n", i ); // check the resulting AIG if ( !Hop_ManCheck(pNew) ) printf( "Hop_ManBalance(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Returns the new node constructed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) { Hop_Obj_t * pObjNew; Vec_Ptr_t * vSuper; int i; assert( !Hop_IsComplement(pObjOld) ); // return if the result is known if ( pObjOld->pData ) return (Hop_Obj_t *)pObjOld->pData; assert( Hop_ObjIsNode(pObjOld) ); // get the implication supergate vSuper = Hop_NodeBalanceCone( pObjOld, vStore, Level ); // check if supergate contains two nodes in the opposite polarity if ( vSuper->nSize == 0 ) return (Hop_Obj_t *)(pObjOld->pData = Hop_ManConst0(pNew)); if ( Vec_PtrSize(vSuper) < 2 ) printf( "BUG!\n" ); // for each old node, derive the new well-balanced node for ( i = 0; i < Vec_PtrSize(vSuper); i++ ) { pObjNew = Hop_NodeBalance_rec( pNew, Hop_Regular((Hop_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); vSuper->pArray[i] = Hop_NotCond( pObjNew, Hop_IsComplement((Hop_Obj_t *)vSuper->pArray[i]) ); } // build the supergate pObjNew = Hop_NodeBalanceBuildSuper( pNew, vSuper, Hop_ObjType(pObjOld), fUpdateLevel ); // make sure the balanced node is not assigned // assert( pObjOld->Level >= Hop_Regular(pObjNew)->Level ); assert( pObjOld->pData == NULL ); return (Hop_Obj_t *)(pObjOld->pData = pObjNew); } /**Function************************************************************* Synopsis [Collects the nodes of the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hop_NodeBalanceCone_rec( Hop_Obj_t * pRoot, Hop_Obj_t * pObj, Vec_Ptr_t * vSuper ) { int RetValue1, RetValue2, i; // check if the node is visited if ( Hop_Regular(pObj)->fMarkB ) { // check if the node occurs in the same polarity for ( i = 0; i < vSuper->nSize; i++ ) if ( vSuper->pArray[i] == pObj ) return 1; // check if the node is present in the opposite polarity for ( i = 0; i < vSuper->nSize; i++ ) if ( vSuper->pArray[i] == Hop_Not(pObj) ) return -1; assert( 0 ); return 0; } // if the new node is complemented or a PI, another gate begins if ( pObj != pRoot && (Hop_IsComplement(pObj) || Hop_ObjType(pObj) != Hop_ObjType(pRoot) || Hop_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) ) { Vec_PtrPush( vSuper, pObj ); Hop_Regular(pObj)->fMarkB = 1; return 0; } assert( !Hop_IsComplement(pObj) ); assert( Hop_ObjIsNode(pObj) ); // go through the branches RetValue1 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild0(pObj), vSuper ); RetValue2 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild1(pObj), vSuper ); if ( RetValue1 == -1 || RetValue2 == -1 ) return -1; // return 1 if at least one branch has a duplicate return RetValue1 || RetValue2; } /**Function************************************************************* Synopsis [Collects the nodes of the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) { Vec_Ptr_t * vNodes; int RetValue, i; assert( !Hop_IsComplement(pObj) ); // extend the storage if ( Vec_VecSize( vStore ) <= Level ) Vec_VecPush( vStore, Level, 0 ); // get the temporary array of nodes vNodes = Vec_VecEntry( vStore, Level ); Vec_PtrClear( vNodes ); // collect the nodes in the implication supergate RetValue = Hop_NodeBalanceCone_rec( pObj, pObj, vNodes ); assert( vNodes->nSize > 1 ); // unmark the visited nodes Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i ) Hop_Regular(pObj)->fMarkB = 0; // if we found the node and its complement in the same implication supergate, // return empty set of nodes (meaning that we should use constant-0 node) if ( RetValue == -1 ) vNodes->nSize = 0; return vNodes; } /**Function************************************************************* Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hop_NodeCompareLevelsDecrease( Hop_Obj_t ** pp1, Hop_Obj_t ** pp2 ) { int Diff = Hop_ObjLevel(Hop_Regular(*pp1)) - Hop_ObjLevel(Hop_Regular(*pp2)); if ( Diff > 0 ) return -1; if ( Diff < 0 ) return 1; Diff = Hop_Regular(*pp1)->Id - Hop_Regular(*pp2)->Id; if ( Diff > 0 ) return -1; if ( Diff < 0 ) return 1; return 0; } /**Function************************************************************* Synopsis [Builds implication supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Type_t Type, int fUpdateLevel ) { Hop_Obj_t * pObj1, * pObj2; int LeftBound; assert( vSuper->nSize > 1 ); // sort the new nodes by level in the decreasing order Vec_PtrSort( vSuper, (int (*)(const void *, const void *))Hop_NodeCompareLevelsDecrease ); // balance the nodes while ( vSuper->nSize > 1 ) { // find the left bound on the node to be paired LeftBound = (!fUpdateLevel)? 0 : Hop_NodeBalanceFindLeft( vSuper ); // find the node that can be shared (if no such node, randomize choice) Hop_NodeBalancePermute( p, vSuper, LeftBound, Type == AIG_EXOR ); // pull out the last two nodes pObj1 = (Hop_Obj_t *)Vec_PtrPop(vSuper); pObj2 = (Hop_Obj_t *)Vec_PtrPop(vSuper); Hop_NodeBalancePushUniqueOrderByLevel( vSuper, Hop_Oper(p, pObj1, pObj2, Type) ); } return (Hop_Obj_t *)Vec_PtrEntry(vSuper, 0); } /**Function************************************************************* Synopsis [Finds the left bound on the next candidate to be paired.] Description [The nodes in the array are in the decreasing order of levels. The last node in the array has the smallest level. By default it would be paired with the next node on the left. However, it may be possible to pair it with some other node on the left, in such a way that the new node is shared. This procedure finds the index of the left-most node, which can be paired with the last node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Hop_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) { Hop_Obj_t * pObjRight, * pObjLeft; int Current; // if two or less nodes, pair with the first if ( Vec_PtrSize(vSuper) < 3 ) return 0; // set the pointer to the one before the last Current = Vec_PtrSize(vSuper) - 2; pObjRight = (Hop_Obj_t *)Vec_PtrEntry( vSuper, Current ); // go through the nodes to the left of this one for ( Current--; Current >= 0; Current-- ) { // get the next node on the left pObjLeft = (Hop_Obj_t *)Vec_PtrEntry( vSuper, Current ); // if the level of this node is different, quit the loop if ( Hop_ObjLevel(Hop_Regular(pObjLeft)) != Hop_ObjLevel(Hop_Regular(pObjRight)) ) break; } Current++; // get the node, for which the equality holds pObjLeft = (Hop_Obj_t *)Vec_PtrEntry( vSuper, Current ); assert( Hop_ObjLevel(Hop_Regular(pObjLeft)) == Hop_ObjLevel(Hop_Regular(pObjRight)) ); return Current; } /**Function************************************************************* Synopsis [Moves closer to the end the node that is best for sharing.] Description [If there is no node with sharing, randomly chooses one of the legal nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) { Hop_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; int RightBound, i; // get the right bound RightBound = Vec_PtrSize(vSuper) - 2; assert( LeftBound <= RightBound ); if ( LeftBound == RightBound ) return; // get the two last nodes pObj1 = (Hop_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 ); pObj2 = (Hop_Obj_t *)Vec_PtrEntry( vSuper, RightBound ); if ( Hop_Regular(pObj1) == p->pConst1 || Hop_Regular(pObj2) == p->pConst1 ) return; // find the first node that can be shared for ( i = RightBound; i >= LeftBound; i-- ) { pObj3 = (Hop_Obj_t *)Vec_PtrEntry( vSuper, i ); if ( Hop_Regular(pObj3) == p->pConst1 ) { Vec_PtrWriteEntry( vSuper, i, pObj2 ); Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); return; } pGhost = Hop_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_EXOR : AIG_AND ); if ( Hop_TableLookup( p, pGhost ) ) { if ( pObj3 == pObj2 ) return; Vec_PtrWriteEntry( vSuper, i, pObj2 ); Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); return; } } /* // we did not find the node to share, randomize choice { int Choice = rand() % (RightBound - LeftBound + 1); pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); if ( pObj3 == pObj2 ) return; Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); } */ } /**Function************************************************************* Synopsis [Inserts a new node in the order by levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Hop_Obj_t * pObj ) { Hop_Obj_t * pObj1, * pObj2; int i; if ( Vec_PtrPushUnique(vStore, pObj) ) return; // find the p of the node for ( i = vStore->nSize-1; i > 0; i-- ) { pObj1 = (Hop_Obj_t *)vStore->pArray[i ]; pObj2 = (Hop_Obj_t *)vStore->pArray[i-1]; if ( Hop_ObjLevel(Hop_Regular(pObj1)) <= Hop_ObjLevel(Hop_Regular(pObj2)) ) break; vStore->pArray[i ] = pObj2; vStore->pArray[i-1] = pObj1; } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/hop/hopCheck.c000066400000000000000000000067241477524141600162160ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hopCheck.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Minimalistic And-Inverter Graph package.] Synopsis [AIG checking procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: hopCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "hop.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks the consistency of the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hop_ManCheck( Hop_Man_t * p ) { Hop_Obj_t * pObj, * pObj2; int i; // check primary inputs Hop_ManForEachPi( p, pObj, i ) { if ( Hop_ObjFanin0(pObj) || Hop_ObjFanin1(pObj) ) { printf( "Hop_ManCheck: The PI node \"%p\" has fanins.\n", pObj ); return 0; } } // check primary outputs Hop_ManForEachPo( p, pObj, i ) { if ( !Hop_ObjFanin0(pObj) ) { printf( "Hop_ManCheck: The PO node \"%p\" has NULL fanin.\n", pObj ); return 0; } if ( Hop_ObjFanin1(pObj) ) { printf( "Hop_ManCheck: The PO node \"%p\" has second fanin.\n", pObj ); return 0; } } // check internal nodes Hop_ManForEachNode( p, pObj, i ) { if ( !Hop_ObjFanin0(pObj) || !Hop_ObjFanin1(pObj) ) { printf( "Hop_ManCheck: The AIG has internal node \"%p\" with a NULL fanin.\n", pObj ); return 0; } if ( Hop_ObjFanin0(pObj)->Id >= Hop_ObjFanin1(pObj)->Id ) { printf( "Hop_ManCheck: The AIG has node \"%p\" with a wrong ordering of fanins.\n", pObj ); return 0; } pObj2 = Hop_TableLookup( p, pObj ); if ( pObj2 != pObj ) { printf( "Hop_ManCheck: Node \"%p\" is not in the structural hashing table.\n", pObj ); return 0; } } // count the total number of nodes if ( Hop_ManObjNum(p) != 1 + Hop_ManPiNum(p) + Hop_ManPoNum(p) + Hop_ManAndNum(p) + Hop_ManExorNum(p) ) { printf( "Hop_ManCheck: The number of created nodes is wrong.\n" ); return 0; } // count the number of nodes in the table if ( Hop_TableCountEntries(p) != Hop_ManAndNum(p) + Hop_ManExorNum(p) ) { printf( "Hop_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); return 0; } // if ( !Hop_ManIsAcyclic(p) ) // return 0; return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/hop/hopDfs.c000066400000000000000000000423571477524141600157170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hopDfs.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Minimalistic And-Inverter Graph package.] Synopsis [DFS traversal procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: hopDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "hop.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collects internal nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ManDfs_rec( Hop_Obj_t * pObj, Vec_Ptr_t * vNodes ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; Hop_ManDfs_rec( Hop_ObjFanin0(pObj), vNodes ); Hop_ManDfs_rec( Hop_ObjFanin1(pObj), vNodes ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA(pObj); Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [Collects internal nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Hop_ManDfs( Hop_Man_t * p ) { Vec_Ptr_t * vNodes; Hop_Obj_t * pObj; int i; vNodes = Vec_PtrAlloc( Hop_ManNodeNum(p) ); Hop_ManForEachNode( p, pObj, i ) Hop_ManDfs_rec( pObj, vNodes ); Hop_ManForEachNode( p, pObj, i ) Hop_ObjClearMarkA(pObj); return vNodes; } /**Function************************************************************* Synopsis [Collects internal nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Hop_ManDfsNode( Hop_Man_t * p, Hop_Obj_t * pNode ) { Vec_Ptr_t * vNodes; Hop_Obj_t * pObj; int i; assert( !Hop_IsComplement(pNode) ); vNodes = Vec_PtrAlloc( 16 ); Hop_ManDfs_rec( pNode, vNodes ); Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i ) Hop_ObjClearMarkA(pObj); return vNodes; } /**Function************************************************************* Synopsis [Computes the max number of levels in the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hop_ManCountLevels( Hop_Man_t * p ) { Vec_Ptr_t * vNodes; Hop_Obj_t * pObj; int i, LevelsMax, Level0, Level1; // initialize the levels Hop_ManConst1(p)->pData = NULL; Hop_ManForEachPi( p, pObj, i ) pObj->pData = NULL; // compute levels in a DFS order vNodes = Hop_ManDfs( p ); Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i ) { Level0 = (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData; Level1 = (int)(ABC_PTRUINT_T)Hop_ObjFanin1(pObj)->pData; pObj->pData = (void *)(ABC_PTRUINT_T)(1 + Hop_ObjIsExor(pObj) + Abc_MaxInt(Level0, Level1)); } Vec_PtrFree( vNodes ); // get levels of the POs LevelsMax = 0; Hop_ManForEachPo( p, pObj, i ) LevelsMax = Abc_MaxInt( LevelsMax, (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData ); return LevelsMax; } /**Function************************************************************* Synopsis [Creates correct reference counters at each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ManCreateRefs( Hop_Man_t * p ) { Hop_Obj_t * pObj; int i; if ( p->fRefCount ) return; p->fRefCount = 1; // clear refs Hop_ObjClearRef( Hop_ManConst1(p) ); Hop_ManForEachPi( p, pObj, i ) Hop_ObjClearRef( pObj ); Hop_ManForEachNode( p, pObj, i ) Hop_ObjClearRef( pObj ); Hop_ManForEachPo( p, pObj, i ) Hop_ObjClearRef( pObj ); // set refs Hop_ManForEachNode( p, pObj, i ) { Hop_ObjRef( Hop_ObjFanin0(pObj) ); Hop_ObjRef( Hop_ObjFanin1(pObj) ); } Hop_ManForEachPo( p, pObj, i ) Hop_ObjRef( Hop_ObjFanin0(pObj) ); } /**Function************************************************************* Synopsis [Counts the number of AIG nodes rooted at this cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ConeMark_rec( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; Hop_ConeMark_rec( Hop_ObjFanin0(pObj) ); Hop_ConeMark_rec( Hop_ObjFanin1(pObj) ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); } /**Function************************************************************* Synopsis [Counts the number of AIG nodes rooted at this cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ConeCleanAndMark_rec( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; Hop_ConeCleanAndMark_rec( Hop_ObjFanin0(pObj) ); Hop_ConeCleanAndMark_rec( Hop_ObjFanin1(pObj) ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); pObj->pData = NULL; } /**Function************************************************************* Synopsis [Counts the number of AIG nodes rooted at this cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hop_ConeCountAndMark_rec( Hop_Obj_t * pObj ) { int Counter; assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return 0; Counter = 1 + Hop_ConeCountAndMark_rec( Hop_ObjFanin0(pObj) ) + Hop_ConeCountAndMark_rec( Hop_ObjFanin1(pObj) ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); return Counter; } /**Function************************************************************* Synopsis [Counts the number of AIG nodes rooted at this cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ConeUnmark_rec( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) return; Hop_ConeUnmark_rec( Hop_ObjFanin0(pObj) ); Hop_ConeUnmark_rec( Hop_ObjFanin1(pObj) ); assert( Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjClearMarkA( pObj ); } /**Function************************************************************* Synopsis [Counts the number of AIG nodes rooted at this cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hop_DagSize( Hop_Obj_t * pObj ) { int Counter; Counter = Hop_ConeCountAndMark_rec( Hop_Regular(pObj) ); Hop_ConeUnmark_rec( Hop_Regular(pObj) ); return Counter; } /**Function************************************************************* Synopsis [Counts how many fanout the given node has.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hop_ObjFanoutCount_rec( Hop_Obj_t * pObj, Hop_Obj_t * pPivot ) { int Counter; assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return (int)(pObj == pPivot); Counter = Hop_ObjFanoutCount_rec( Hop_ObjFanin0(pObj), pPivot ) + Hop_ObjFanoutCount_rec( Hop_ObjFanin1(pObj), pPivot ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); return Counter; } int Hop_ObjFanoutCount( Hop_Obj_t * pObj, Hop_Obj_t * pPivot ) { int Counter; assert( !Hop_IsComplement(pPivot) ); Counter = Hop_ObjFanoutCount_rec( Hop_Regular(pObj), pPivot ); Hop_ConeUnmark_rec( Hop_Regular(pObj) ); return Counter; } /**Function************************************************************* Synopsis [Transfers the AIG from one manager into another.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_Transfer_rec( Hop_Man_t * pDest, Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; Hop_Transfer_rec( pDest, Hop_ObjFanin0(pObj) ); Hop_Transfer_rec( pDest, Hop_ObjFanin1(pObj) ); pObj->pData = Hop_And( pDest, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); } /**Function************************************************************* Synopsis [Transfers the AIG from one manager into another.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pRoot, int nVars ) { Hop_Obj_t * pObj; int i; // solve simple cases if ( pSour == pDest ) return pRoot; if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) return Hop_NotCond( Hop_ManConst1(pDest), Hop_IsComplement(pRoot) ); // set the PI mapping Hop_ManForEachPi( pSour, pObj, i ) { if ( i == nVars ) break; pObj->pData = Hop_IthVar(pDest, i); } // transfer and set markings Hop_Transfer_rec( pDest, Hop_Regular(pRoot) ); // clear the markings Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); } /**Function************************************************************* Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_Compose_rec( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFunc, Hop_Obj_t * pVar ) { assert( !Hop_IsComplement(pObj) ); if ( Hop_ObjIsMarkA(pObj) ) return; if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) ) { pObj->pData = pObj == pVar ? pFunc : pObj; return; } Hop_Compose_rec( p, Hop_ObjFanin0(pObj), pFunc, pVar ); Hop_Compose_rec( p, Hop_ObjFanin1(pObj), pFunc, pVar ); pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); } /**Function************************************************************* Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar ) { // quit if the PI variable is not defined if ( iVar >= Hop_ManPiNum(p) ) { printf( "Hop_Compose(): The PI variable %d is not defined.\n", iVar ); return NULL; } // recursively perform composition Hop_Compose_rec( p, Hop_Regular(pRoot), pFunc, Hop_ManPi(p, iVar) ); // clear the markings Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); } /**Function************************************************************* Synopsis [Complements the AIG (pRoot) with the function (pFunc) using PI var (iVar).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_Complement_rec( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pVar ) { assert( !Hop_IsComplement(pObj) ); if ( Hop_ObjIsMarkA(pObj) ) return; if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) ) { pObj->pData = pObj == pVar ? Hop_Not(pObj) : pObj; return; } Hop_Complement_rec( p, Hop_ObjFanin0(pObj), pVar ); Hop_Complement_rec( p, Hop_ObjFanin1(pObj), pVar ); pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); } /**Function************************************************************* Synopsis [Complements the AIG (pRoot) with the function (pFunc) using PI var (iVar).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_Complement( Hop_Man_t * p, Hop_Obj_t * pRoot, int iVar ) { // quit if the PI variable is not defined if ( iVar >= Hop_ManPiNum(p) ) { printf( "Hop_Complement(): The PI variable %d is not defined.\n", iVar ); return NULL; } // recursively perform composition Hop_Complement_rec( p, Hop_Regular(pRoot), Hop_ManPi(p, iVar) ); // clear the markings Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); } /**Function************************************************************* Synopsis [Remaps the AIG (pRoot) to have the given support (uSupp).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_Remap_rec( Hop_Man_t * p, Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; Hop_Remap_rec( p, Hop_ObjFanin0(pObj) ); Hop_Remap_rec( p, Hop_ObjFanin1(pObj) ); pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); } /**Function************************************************************* Synopsis [Remaps the AIG (pRoot) to have the given support (uSupp).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_Remap( Hop_Man_t * p, Hop_Obj_t * pRoot, unsigned uSupp, int nVars ) { Hop_Obj_t * pObj; int i, k; // quit if the PI variable is not defined if ( nVars > Hop_ManPiNum(p) ) { printf( "Hop_Remap(): The number of variables (%d) is more than the manager size (%d).\n", nVars, Hop_ManPiNum(p) ); return NULL; } // return if constant if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) return pRoot; if ( uSupp == 0 ) return Hop_NotCond( Hop_ManConst0(p), Hop_ObjPhaseCompl(pRoot) ); // set the PI mapping k = 0; Hop_ManForEachPi( p, pObj, i ) { if ( i == nVars ) break; if ( uSupp & (1 << i) ) pObj->pData = Hop_IthVar(p, k++); else pObj->pData = Hop_ManConst0(p); } assert( k > 0 && k < nVars ); // recursively perform composition Hop_Remap_rec( p, Hop_Regular(pRoot) ); // clear the markings Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); } /**Function************************************************************* Synopsis [Permute the AIG according to the given permutation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_Permute( Hop_Man_t * p, Hop_Obj_t * pRoot, int nRootVars, int * pPermute ) { Hop_Obj_t * pObj; int i; // return if constant if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) return pRoot; // create mapping Hop_ManForEachPi( p, pObj, i ) { if ( i == nRootVars ) break; assert( pPermute[i] >= 0 && pPermute[i] < Hop_ManPiNum(p) ); pObj->pData = Hop_IthVar( p, pPermute[i] ); } // recursively perform composition Hop_Remap_rec( p, Hop_Regular(pRoot) ); // clear the markings Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/hop/hopMan.c000066400000000000000000000114071477524141600157060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hopMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Minimalistic And-Inverter Graph package.] Synopsis [AIG manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: hopMan.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "hop.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Man_t * Hop_ManStart() { Hop_Man_t * p; // start the manager p = ABC_ALLOC( Hop_Man_t, 1 ); memset( p, 0, sizeof(Hop_Man_t) ); // perform initializations p->nTravIds = 1; p->fRefCount = 1; p->fCatchExor = 0; // allocate arrays for nodes p->vPis = Vec_PtrAlloc( 100 ); p->vPos = Vec_PtrAlloc( 100 ); // prepare the internal memory manager Hop_ManStartMemory( p ); // create the constant node p->pConst1 = Hop_ManFetchMemory( p ); p->pConst1->Type = AIG_CONST1; p->pConst1->fPhase = 1; p->nCreated = 1; // start the table // p->nTableSize = 107; p->nTableSize = 10007; p->pTable = ABC_ALLOC( Hop_Obj_t *, p->nTableSize ); memset( p->pTable, 0, sizeof(Hop_Obj_t *) * p->nTableSize ); return p; } /**Function************************************************************* Synopsis [Stops the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ManStop( Hop_Man_t * p ) { Hop_Obj_t * pObj; int i; // make sure the nodes have clean marks pObj = Hop_ManConst1(p); assert( !pObj->fMarkA && !pObj->fMarkB ); Hop_ManForEachPi( p, pObj, i ) assert( !pObj->fMarkA && !pObj->fMarkB ); Hop_ManForEachPo( p, pObj, i ) assert( !pObj->fMarkA && !pObj->fMarkB ); Hop_ManForEachNode( p, pObj, i ) assert( !pObj->fMarkA && !pObj->fMarkB ); // print time if ( p->time1 ) { ABC_PRT( "time1", p->time1 ); } if ( p->time2 ) { ABC_PRT( "time2", p->time2 ); } // Hop_TableProfile( p ); if ( p->vChunks ) Hop_ManStopMemory( p ); if ( p->vPis ) Vec_PtrFree( p->vPis ); if ( p->vPos ) Vec_PtrFree( p->vPos ); if ( p->vObjs ) Vec_PtrFree( p->vObjs ); ABC_FREE( p->pTable ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Returns the number of dangling nodes removed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hop_ManCleanup( Hop_Man_t * p ) { Vec_Ptr_t * vObjs; Hop_Obj_t * pNode; int i, nNodesOld; assert( p->fRefCount ); nNodesOld = Hop_ManNodeNum(p); // collect roots of dangling nodes vObjs = Vec_PtrAlloc( 100 ); Hop_ManForEachNode( p, pNode, i ) if ( Hop_ObjRefs(pNode) == 0 ) Vec_PtrPush( vObjs, pNode ); // recursively remove dangling nodes Vec_PtrForEachEntry( Hop_Obj_t *, vObjs, pNode, i ) Hop_ObjDelete_rec( p, pNode ); Vec_PtrFree( vObjs ); return nNodesOld - Hop_ManNodeNum(p); } /**Function************************************************************* Synopsis [Stops the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ManPrintStats( Hop_Man_t * p ) { printf( "PI/PO = %d/%d. ", Hop_ManPiNum(p), Hop_ManPoNum(p) ); printf( "A = %7d. ", Hop_ManAndNum(p) ); printf( "X = %5d. ", Hop_ManExorNum(p) ); printf( "Cre = %7d. ", p->nCreated ); printf( "Del = %7d. ", p->nDeleted ); printf( "Lev = %3d. ", Hop_ManCountLevels(p) ); printf( "\n" ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/hop/hopMem.c000066400000000000000000000070061477524141600157110ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hopMem.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Minimalistic And-Inverter Graph package.] Synopsis [Memory management for the AIG nodes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: hopMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "hop.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // memory management #define IVY_PAGE_SIZE 12 // page size containing 2^IVY_PAGE_SIZE nodes #define IVY_PAGE_MASK 4095 // page bitmask (2^IVY_PAGE_SIZE)-1 //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the internal memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ManStartMemory( Hop_Man_t * p ) { p->vChunks = Vec_PtrAlloc( 128 ); p->vPages = Vec_PtrAlloc( 128 ); } /**Function************************************************************* Synopsis [Stops the internal memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ManStopMemory( Hop_Man_t * p ) { void * pMemory; int i; Vec_PtrForEachEntry( void *, p->vChunks, pMemory, i ) ABC_FREE( pMemory ); Vec_PtrFree( p->vChunks ); Vec_PtrFree( p->vPages ); p->pListFree = NULL; } /**Function************************************************************* Synopsis [Allocates additional memory for the nodes.] Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. Records the pointer to the AIG manager in the -1 entry.] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ManAddMemory( Hop_Man_t * p ) { char * pMemory; int i, nBytes; assert( sizeof(Hop_Obj_t) <= 64 ); assert( p->pListFree == NULL ); // assert( (Hop_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); // allocate new memory page nBytes = sizeof(Hop_Obj_t) * (1<vChunks, pMemory ); // align memory at the 32-byte boundary pMemory = pMemory + 64 - (((int)(ABC_PTRUINT_T)pMemory) & 63); // remember the manager in the first entry Vec_PtrPush( p->vPages, pMemory ); // break the memory down into nodes p->pListFree = (Hop_Obj_t *)pMemory; for ( i = 1; i <= IVY_PAGE_MASK; i++ ) { *((char **)pMemory) = pMemory + sizeof(Hop_Obj_t); pMemory += sizeof(Hop_Obj_t); } *((char **)pMemory) = NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/hop/hopObj.c000066400000000000000000000172321477524141600157070ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hopObj.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Minimalistic And-Inverter Graph package.] Synopsis [Adding/removing objects.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: hopObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "hop.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates primary input.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_ObjCreatePi( Hop_Man_t * p ) { Hop_Obj_t * pObj; pObj = Hop_ManFetchMemory( p ); pObj->Type = AIG_PI; pObj->PioNum = Vec_PtrSize( p->vPis ); Vec_PtrPush( p->vPis, pObj ); p->nObjs[AIG_PI]++; return pObj; } /**Function************************************************************* Synopsis [Creates primary output with the given driver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_ObjCreatePo( Hop_Man_t * p, Hop_Obj_t * pDriver ) { Hop_Obj_t * pObj; pObj = Hop_ManFetchMemory( p ); pObj->Type = AIG_PO; Vec_PtrPush( p->vPos, pObj ); // add connections pObj->pFanin0 = pDriver; if ( p->fRefCount ) Hop_ObjRef( Hop_Regular(pDriver) ); else pObj->nRefs = Hop_ObjLevel( Hop_Regular(pDriver) ); // set the phase pObj->fPhase = Hop_ObjPhaseCompl(pDriver); // update node counters of the manager p->nObjs[AIG_PO]++; return pObj; } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_ObjCreate( Hop_Man_t * p, Hop_Obj_t * pGhost ) { Hop_Obj_t * pObj; assert( !Hop_IsComplement(pGhost) ); assert( Hop_ObjIsNode(pGhost) ); assert( pGhost == &p->Ghost ); // get memory for the new object pObj = Hop_ManFetchMemory( p ); pObj->Type = pGhost->Type; // add connections Hop_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); // update node counters of the manager p->nObjs[Hop_ObjType(pObj)]++; assert( pObj->pData == NULL ); return pObj; } /**Function************************************************************* Synopsis [Connect the object to the fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ObjConnect( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFan0, Hop_Obj_t * pFan1 ) { assert( !Hop_IsComplement(pObj) ); assert( Hop_ObjIsNode(pObj) ); // add the first fanin pObj->pFanin0 = pFan0; pObj->pFanin1 = pFan1; // increment references of the fanins and add their fanouts if ( p->fRefCount ) { if ( pFan0 != NULL ) Hop_ObjRef( Hop_ObjFanin0(pObj) ); if ( pFan1 != NULL ) Hop_ObjRef( Hop_ObjFanin1(pObj) ); } else pObj->nRefs = Hop_ObjLevelNew( pObj ); // set the phase pObj->fPhase = Hop_ObjPhaseCompl(pFan0) & Hop_ObjPhaseCompl(pFan1); // add the node to the structural hash table Hop_TableInsert( p, pObj ); } /**Function************************************************************* Synopsis [Connect the object to the fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ObjDisconnect( Hop_Man_t * p, Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); assert( Hop_ObjIsNode(pObj) ); // remove connections if ( pObj->pFanin0 != NULL ) Hop_ObjDeref(Hop_ObjFanin0(pObj)); if ( pObj->pFanin1 != NULL ) Hop_ObjDeref(Hop_ObjFanin1(pObj)); // remove the node from the structural hash table Hop_TableDelete( p, pObj ); // add the first fanin pObj->pFanin0 = NULL; pObj->pFanin1 = NULL; } /**Function************************************************************* Synopsis [Deletes the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ObjDelete( Hop_Man_t * p, Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); assert( !Hop_ObjIsTerm(pObj) ); assert( Hop_ObjRefs(pObj) == 0 ); // update node counters of the manager p->nObjs[pObj->Type]--; p->nDeleted++; // remove connections Hop_ObjDisconnect( p, pObj ); // remove PIs/POs from the arrays if ( Hop_ObjIsPi(pObj) ) Vec_PtrRemove( p->vPis, pObj ); // free the node Hop_ManRecycleMemory( p, pObj ); } /**Function************************************************************* Synopsis [Deletes the MFFC of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ObjDelete_rec( Hop_Man_t * p, Hop_Obj_t * pObj ) { Hop_Obj_t * pFanin0, * pFanin1; assert( !Hop_IsComplement(pObj) ); if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) ) return; assert( Hop_ObjIsNode(pObj) ); pFanin0 = Hop_ObjFanin0(pObj); pFanin1 = Hop_ObjFanin1(pObj); Hop_ObjDelete( p, pObj ); if ( pFanin0 && !Hop_ObjIsNone(pFanin0) && Hop_ObjRefs(pFanin0) == 0 ) Hop_ObjDelete_rec( p, pFanin0 ); if ( pFanin1 && !Hop_ObjIsNone(pFanin1) && Hop_ObjRefs(pFanin1) == 0 ) Hop_ObjDelete_rec( p, pFanin1 ); } /**Function************************************************************* Synopsis [Returns the representative of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_ObjRepr( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( pObj->pData == NULL || pObj->pData == pObj ) return pObj; return Hop_ObjRepr( (Hop_Obj_t *)pObj->pData ); } /**Function************************************************************* Synopsis [Sets an equivalence relation between the nodes.] Description [Makes the representative of pNew point to the representaive of pOld.] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ObjCreateChoice( Hop_Obj_t * pOld, Hop_Obj_t * pNew ) { Hop_Obj_t * pOldRepr; Hop_Obj_t * pNewRepr; assert( pOld != NULL && pNew != NULL ); pOldRepr = Hop_ObjRepr(pOld); pNewRepr = Hop_ObjRepr(pNew); if ( pNewRepr != pOldRepr ) pNewRepr->pData = pOldRepr; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/hop/hopOper.c000066400000000000000000000262151477524141600161030ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hopOper.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Minimalistic And-Inverter Graph package.] Synopsis [AIG operations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: hopOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "hop.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // procedure to detect an EXOR gate static inline int Hop_ObjIsExorType( Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 ) { if ( !Hop_IsComplement(p0) || !Hop_IsComplement(p1) ) return 0; p0 = Hop_Regular(p0); p1 = Hop_Regular(p1); if ( !Hop_ObjIsAnd(p0) || !Hop_ObjIsAnd(p1) ) return 0; if ( Hop_ObjFanin0(p0) != Hop_ObjFanin0(p1) || Hop_ObjFanin1(p0) != Hop_ObjFanin1(p1) ) return 0; if ( Hop_ObjFaninC0(p0) == Hop_ObjFaninC0(p1) || Hop_ObjFaninC1(p0) == Hop_ObjFaninC1(p1) ) return 0; *ppFan0 = Hop_ObjChild0(p0); *ppFan1 = Hop_ObjChild1(p0); return 1; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns i-th elementary variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_IthVar( Hop_Man_t * p, int i ) { int v; for ( v = Hop_ManPiNum(p); v <= i; v++ ) Hop_ObjCreatePi( p ); assert( i < Vec_PtrSize(p->vPis) ); return Hop_ManPi( p, i ); } /**Function************************************************************* Synopsis [Perform one operation.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_Oper( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type ) { if ( Type == AIG_AND ) return Hop_And( p, p0, p1 ); if ( Type == AIG_EXOR ) return Hop_Exor( p, p0, p1 ); assert( 0 ); return NULL; } /**Function************************************************************* Synopsis [Performs canonicization step.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_And( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ) { Hop_Obj_t * pGhost, * pResult; // Hop_Obj_t * pFan0, * pFan1; // check trivial cases if ( p0 == p1 ) return p0; if ( p0 == Hop_Not(p1) ) return Hop_Not(p->pConst1); if ( Hop_Regular(p0) == p->pConst1 ) return p0 == p->pConst1 ? p1 : Hop_Not(p->pConst1); if ( Hop_Regular(p1) == p->pConst1 ) return p1 == p->pConst1 ? p0 : Hop_Not(p->pConst1); // check if it can be an EXOR gate // if ( Hop_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) // return Hop_Exor( p, pFan0, pFan1 ); // check the table pGhost = Hop_ObjCreateGhost( p, p0, p1, AIG_AND ); if ( (pResult = Hop_TableLookup( p, pGhost )) ) return pResult; return Hop_ObjCreate( p, pGhost ); } /**Function************************************************************* Synopsis [Performs canonicization step.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_Exor( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ) { /* Hop_Obj_t * pGhost, * pResult; // check trivial cases if ( p0 == p1 ) return Hop_Not(p->pConst1); if ( p0 == Hop_Not(p1) ) return p->pConst1; if ( Hop_Regular(p0) == p->pConst1 ) return Hop_NotCond( p1, p0 == p->pConst1 ); if ( Hop_Regular(p1) == p->pConst1 ) return Hop_NotCond( p0, p1 == p->pConst1 ); // check the table pGhost = Hop_ObjCreateGhost( p, p0, p1, AIG_EXOR ); if ( pResult = Hop_TableLookup( p, pGhost ) ) return pResult; return Hop_ObjCreate( p, pGhost ); */ return Hop_Or( p, Hop_And(p, p0, Hop_Not(p1)), Hop_And(p, Hop_Not(p0), p1) ); } /**Function************************************************************* Synopsis [Implements Boolean OR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_Or( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ) { return Hop_Not( Hop_And( p, Hop_Not(p0), Hop_Not(p1) ) ); } /**Function************************************************************* Synopsis [Implements ITE operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_Mux( Hop_Man_t * p, Hop_Obj_t * pC, Hop_Obj_t * p1, Hop_Obj_t * p0 ) { /* Hop_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; int Count0, Count1; // consider trivial cases if ( p0 == Hop_Not(p1) ) return Hop_Exor( p, pC, p0 ); // other cases can be added // implement the first MUX (F = C * x1 + C' * x0) // check for constants here!!! pTempA1 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, pC, p1, AIG_AND) ); pTempA2 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pC), p0, AIG_AND) ); if ( pTempA1 && pTempA2 ) { pTemp = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pTempA1), Hop_Not(pTempA2), AIG_AND) ); if ( pTemp ) return Hop_Not(pTemp); } Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); // implement the second MUX (F' = C * x1' + C' * x0') pTempB1 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, pC, Hop_Not(p1), AIG_AND) ); pTempB2 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pC), Hop_Not(p0), AIG_AND) ); if ( pTempB1 && pTempB2 ) { pTemp = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pTempB1), Hop_Not(pTempB2), AIG_AND) ); if ( pTemp ) return pTemp; } Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); // compare and decide which one to implement if ( Count0 >= Count1 ) { pTempA1 = pTempA1? pTempA1 : Hop_And(p, pC, p1); pTempA2 = pTempA2? pTempA2 : Hop_And(p, Hop_Not(pC), p0); return Hop_Or( p, pTempA1, pTempA2 ); } pTempB1 = pTempB1? pTempB1 : Hop_And(p, pC, Hop_Not(p1)); pTempB2 = pTempB2? pTempB2 : Hop_And(p, Hop_Not(pC), Hop_Not(p0)); return Hop_Not( Hop_Or( p, pTempB1, pTempB2 ) ); */ return Hop_Or( p, Hop_And(p, pC, p1), Hop_And(p, Hop_Not(pC), p0) ); } /**Function************************************************************* Synopsis [Implements ITE operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_Maj( Hop_Man_t * p, Hop_Obj_t * pA, Hop_Obj_t * pB, Hop_Obj_t * pC ) { return Hop_Or( p, Hop_Or(p, Hop_And(p, pA, pB), Hop_And(p, pA, pC)), Hop_And(p, pB, pC) ); } /**Function************************************************************* Synopsis [Constructs the well-balanced tree of gates.] Description [Disregards levels and possible logic sharing.] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_Multi_rec( Hop_Man_t * p, Hop_Obj_t ** ppObjs, int nObjs, Hop_Type_t Type ) { Hop_Obj_t * pObj1, * pObj2; if ( nObjs == 1 ) return ppObjs[0]; pObj1 = Hop_Multi_rec( p, ppObjs, nObjs/2, Type ); pObj2 = Hop_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); return Hop_Oper( p, pObj1, pObj2, Type ); } /**Function************************************************************* Synopsis [Old code.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_Multi( Hop_Man_t * p, Hop_Obj_t ** pArgs, int nArgs, Hop_Type_t Type ) { assert( Type == AIG_AND || Type == AIG_EXOR ); assert( nArgs > 0 ); return Hop_Multi_rec( p, pArgs, nArgs, Type ); } /**Function************************************************************* Synopsis [Implements the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_Miter( Hop_Man_t * p, Vec_Ptr_t * vPairs ) { int i; assert( vPairs->nSize > 0 ); assert( vPairs->nSize % 2 == 0 ); // go through the cubes of the node's SOP for ( i = 0; i < vPairs->nSize; i += 2 ) vPairs->pArray[i/2] = Hop_Not( Hop_Exor( p, (Hop_Obj_t *)vPairs->pArray[i], (Hop_Obj_t *)vPairs->pArray[i+1] ) ); vPairs->nSize = vPairs->nSize/2; return Hop_Not( Hop_Multi_rec( p, (Hop_Obj_t **)vPairs->pArray, vPairs->nSize, AIG_AND ) ); } /**Function************************************************************* Synopsis [Creates AND function with nVars inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_CreateAnd( Hop_Man_t * p, int nVars ) { Hop_Obj_t * pFunc; int i; pFunc = Hop_ManConst1( p ); for ( i = 0; i < nVars; i++ ) pFunc = Hop_And( p, pFunc, Hop_IthVar(p, i) ); return pFunc; } /**Function************************************************************* Synopsis [Creates AND function with nVars inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_CreateOr( Hop_Man_t * p, int nVars ) { Hop_Obj_t * pFunc; int i; pFunc = Hop_ManConst0( p ); for ( i = 0; i < nVars; i++ ) pFunc = Hop_Or( p, pFunc, Hop_IthVar(p, i) ); return pFunc; } /**Function************************************************************* Synopsis [Creates AND function with nVars inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_CreateExor( Hop_Man_t * p, int nVars ) { Hop_Obj_t * pFunc; int i; pFunc = Hop_ManConst0( p ); for ( i = 0; i < nVars; i++ ) pFunc = Hop_Exor( p, pFunc, Hop_IthVar(p, i) ); return pFunc; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/hop/hopTable.c000066400000000000000000000157051477524141600162270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hopTable.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Minimalistic And-Inverter Graph package.] Synopsis [Structural hashing table.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006. ] Revision [$Id: hopTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "hop.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // hashing the node static unsigned long Hop_Hash( Hop_Obj_t * pObj, int TableSize ) { unsigned long Key = Hop_ObjIsExor(pObj) * 1699; Key ^= Hop_ObjFanin0(pObj)->Id * 7937; Key ^= Hop_ObjFanin1(pObj)->Id * 2971; Key ^= Hop_ObjFaninC0(pObj) * 911; Key ^= Hop_ObjFaninC1(pObj) * 353; return Key % TableSize; } // returns the place where this node is stored (or should be stored) static Hop_Obj_t ** Hop_TableFind( Hop_Man_t * p, Hop_Obj_t * pObj ) { Hop_Obj_t ** ppEntry; assert( Hop_ObjChild0(pObj) && Hop_ObjChild1(pObj) ); assert( Hop_ObjFanin0(pObj)->Id < Hop_ObjFanin1(pObj)->Id ); for ( ppEntry = p->pTable + Hop_Hash(pObj, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext ) if ( *ppEntry == pObj ) return ppEntry; assert( *ppEntry == NULL ); return ppEntry; } static void Hop_TableResize( Hop_Man_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks if a node with the given attributes is in the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_TableLookup( Hop_Man_t * p, Hop_Obj_t * pGhost ) { Hop_Obj_t * pEntry; assert( !Hop_IsComplement(pGhost) ); assert( Hop_ObjChild0(pGhost) && Hop_ObjChild1(pGhost) ); assert( Hop_ObjFanin0(pGhost)->Id < Hop_ObjFanin1(pGhost)->Id ); if ( p->fRefCount && (!Hop_ObjRefs(Hop_ObjFanin0(pGhost)) || !Hop_ObjRefs(Hop_ObjFanin1(pGhost))) ) return NULL; for ( pEntry = p->pTable[Hop_Hash(pGhost, p->nTableSize)]; pEntry; pEntry = pEntry->pNext ) { if ( Hop_ObjChild0(pEntry) == Hop_ObjChild0(pGhost) && Hop_ObjChild1(pEntry) == Hop_ObjChild1(pGhost) && Hop_ObjType(pEntry) == Hop_ObjType(pGhost) ) return pEntry; } return NULL; } /**Function************************************************************* Synopsis [Adds the new node to the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_TableInsert( Hop_Man_t * p, Hop_Obj_t * pObj ) { Hop_Obj_t ** ppPlace; assert( !Hop_IsComplement(pObj) ); assert( Hop_TableLookup(p, pObj) == NULL ); if ( (pObj->Id & 0xFF) == 0 && 2 * p->nTableSize < Hop_ManNodeNum(p) ) Hop_TableResize( p ); ppPlace = Hop_TableFind( p, pObj ); assert( *ppPlace == NULL ); *ppPlace = pObj; } /**Function************************************************************* Synopsis [Deletes the node from the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_TableDelete( Hop_Man_t * p, Hop_Obj_t * pObj ) { Hop_Obj_t ** ppPlace; assert( !Hop_IsComplement(pObj) ); ppPlace = Hop_TableFind( p, pObj ); assert( *ppPlace == pObj ); // node should be in the table // remove the node *ppPlace = pObj->pNext; pObj->pNext = NULL; } /**Function************************************************************* Synopsis [Count the number of nodes in the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hop_TableCountEntries( Hop_Man_t * p ) { Hop_Obj_t * pEntry; int i, Counter = 0; for ( i = 0; i < p->nTableSize; i++ ) for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Resizes the table.] Description [Typically this procedure should not be called.] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_TableResize( Hop_Man_t * p ) { Hop_Obj_t * pEntry, * pNext; Hop_Obj_t ** pTableOld, ** ppPlace; int nTableSizeOld, Counter, nEntries, i; abctime clk; clk = Abc_Clock(); // save the old table pTableOld = p->pTable; nTableSizeOld = p->nTableSize; // get the new table p->nTableSize = Abc_PrimeCudd( 2 * Hop_ManNodeNum(p) ); p->pTable = ABC_ALLOC( Hop_Obj_t *, p->nTableSize ); memset( p->pTable, 0, sizeof(Hop_Obj_t *) * p->nTableSize ); // rehash the entries from the old table Counter = 0; for ( i = 0; i < nTableSizeOld; i++ ) for ( pEntry = pTableOld[i], pNext = pEntry? pEntry->pNext : NULL; pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL ) { // get the place where this entry goes in the table ppPlace = Hop_TableFind( p, pEntry ); assert( *ppPlace == NULL ); // should not be there // add the entry to the list *ppPlace = pEntry; pEntry->pNext = NULL; Counter++; } nEntries = Hop_ManNodeNum(p); assert( Counter == nEntries ); // printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); // ABC_PRT( "Time", Abc_Clock() - clk ); // replace the table and the parameters ABC_FREE( pTableOld ); } /**Function******************************************************************** Synopsis [Profiles the hash table.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Hop_TableProfile( Hop_Man_t * p ) { Hop_Obj_t * pEntry; int i, Counter; for ( i = 0; i < p->nTableSize; i++ ) { Counter = 0; for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) Counter++; if ( Counter ) printf( "%d ", Counter ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/hop/hopTruth.c000066400000000000000000000222121477524141600162750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hopTruth.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Minimalistic And-Inverter Graph package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: hopTruth.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "hop.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Hop_ManTruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } static inline void Hop_ManTruthCopy( unsigned * pOut, unsigned * pIn, int nVars ) { int w; for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = pIn[w]; } static inline void Hop_ManTruthClear( unsigned * pOut, int nVars ) { int w; for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = 0; } static inline void Hop_ManTruthFill( unsigned * pOut, int nVars ) { int w; for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~(unsigned)0; } static inline void Hop_ManTruthNot( unsigned * pOut, unsigned * pIn, int nVars ) { int w; for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- ) pOut[w] = ~pIn[w]; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Construct BDDs and mark AIG nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hop_ManConvertAigToTruth_rec1( Hop_Obj_t * pObj ) { int Counter = 0; assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return 0; Counter += Hop_ManConvertAigToTruth_rec1( Hop_ObjFanin0(pObj) ); Counter += Hop_ManConvertAigToTruth_rec1( Hop_ObjFanin1(pObj) ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); return Counter + 1; } /**Function************************************************************* Synopsis [Computes truth table of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Hop_ManConvertAigToTruth_rec2( Hop_Obj_t * pObj, Vec_Int_t * vTruth, int nWords ) { unsigned * pTruth, * pTruth0, * pTruth1; int i; assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) return (unsigned *)pObj->pData; // compute the truth tables of the fanins pTruth0 = Hop_ManConvertAigToTruth_rec2( Hop_ObjFanin0(pObj), vTruth, nWords ); pTruth1 = Hop_ManConvertAigToTruth_rec2( Hop_ObjFanin1(pObj), vTruth, nWords ); // creat the truth table of the node pTruth = Vec_IntFetch( vTruth, nWords ); if ( Hop_ObjIsExor(pObj) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] ^ pTruth1[i]; else if ( !Hop_ObjFaninC0(pObj) && !Hop_ObjFaninC1(pObj) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] & pTruth1[i]; else if ( !Hop_ObjFaninC0(pObj) && Hop_ObjFaninC1(pObj) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] & ~pTruth1[i]; else if ( Hop_ObjFaninC0(pObj) && !Hop_ObjFaninC1(pObj) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = ~pTruth0[i] & pTruth1[i]; else // if ( Hop_ObjFaninC0(pObj) && Hop_ObjFaninC1(pObj) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; assert( Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjClearMarkA( pObj ); pObj->pData = pTruth; return pTruth; } /**Function************************************************************* Synopsis [Computes truth table of the node.] Description [Assumes that the structural support is no more than 8 inputs. Uses array vTruth to store temporary truth tables. The returned pointer should be used immediately.] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Hop_ManConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, int fMsbFirst ) { static unsigned uTruths[8][8] = { // elementary truth tables { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } }; Hop_Obj_t * pObj; unsigned * pTruth, * pTruth2; int i, nWords, nNodes; Vec_Ptr_t * vTtElems; // if the number of variables is more than 8, allocate truth tables if ( nVars > 8 ) vTtElems = Vec_PtrAllocTruthTables( nVars ); else vTtElems = NULL; // clear the data fields and set marks nNodes = Hop_ManConvertAigToTruth_rec1( Hop_Regular(pRoot) ); // prepare memory nWords = Hop_TruthWordNum( nVars ); Vec_IntClear( vTruth ); Vec_IntGrow( vTruth, nWords * (nNodes+1) ); pTruth = Vec_IntFetch( vTruth, nWords ); // check the case of a constant if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) { assert( nNodes == 0 ); if ( Hop_IsComplement(pRoot) ) Hop_ManTruthClear( pTruth, nVars ); else Hop_ManTruthFill( pTruth, nVars ); return pTruth; } // set elementary truth tables at the leaves assert( nVars <= Hop_ManPiNum(p) ); // assert( Hop_ManPiNum(p) <= 8 ); if ( fMsbFirst ) { // Hop_ManForEachPi( p, pObj, i ) for ( i = 0; i < nVars; i++ ) { pObj = Hop_ManPi( p, i ); if ( vTtElems ) pObj->pData = Vec_PtrEntry(vTtElems, nVars-1-i); else pObj->pData = (void *)uTruths[nVars-1-i]; } } else { // Hop_ManForEachPi( p, pObj, i ) for ( i = 0; i < nVars; i++ ) { pObj = Hop_ManPi( p, i ); if ( vTtElems ) pObj->pData = Vec_PtrEntry(vTtElems, i); else pObj->pData = (void *)uTruths[i]; } } // clear the marks and compute the truth table pTruth2 = Hop_ManConvertAigToTruth_rec2( Hop_Regular(pRoot), vTruth, nWords ); // copy the result Hop_ManTruthCopy( pTruth, pTruth2, nVars ); if ( Hop_IsComplement(pRoot) ) Hop_ManTruthNot( pTruth, pTruth, nVars ); if ( vTtElems ) Vec_PtrFree( vTtElems ); return pTruth; } /**Function************************************************************* Synopsis [Compute truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static word Truth[8] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF) }; word Hop_ManComputeTruth6_rec( Hop_Man_t * p, Hop_Obj_t * pObj ) { word Truth0, Truth1; if ( Hop_ObjIsPi(pObj) ) return Truth[pObj->iData]; assert( Hop_ObjIsNode(pObj) ); Truth0 = Hop_ManComputeTruth6_rec( p, Hop_ObjFanin0(pObj) ); Truth1 = Hop_ManComputeTruth6_rec( p, Hop_ObjFanin1(pObj) ); Truth0 = Hop_ObjFaninC0(pObj) ? ~Truth0 : Truth0; Truth1 = Hop_ObjFaninC1(pObj) ? ~Truth1 : Truth1; return Truth0 & Truth1; } word Hop_ManComputeTruth6( Hop_Man_t * p, Hop_Obj_t * pObj, int nVars ) { word Truth; int i; if ( Hop_ObjIsConst1( Hop_Regular(pObj) ) ) return Hop_IsComplement(pObj) ? 0 : ~(word)0; for ( i = 0; i < nVars; i++ ) Hop_ManPi( p, i )->iData = i; Truth = Hop_ManComputeTruth6_rec( p, Hop_Regular(pObj) ); return Hop_IsComplement(pObj) ? ~Truth : Truth; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/hop/hopUtil.c000066400000000000000000000455541477524141600161220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hopUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Various procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: hopUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "hop.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Increments the current traversal ID of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ManIncrementTravId( Hop_Man_t * p ) { if ( p->nTravIds >= (1<<30)-1 ) Hop_ManCleanData( p ); p->nTravIds++; } /**Function************************************************************* Synopsis [Cleans the data pointers for the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ManCleanData( Hop_Man_t * p ) { Hop_Obj_t * pObj; int i; p->nTravIds = 1; Hop_ManConst1(p)->pData = NULL; Hop_ManForEachPi( p, pObj, i ) pObj->pData = NULL; Hop_ManForEachPo( p, pObj, i ) pObj->pData = NULL; Hop_ManForEachNode( p, pObj, i ) pObj->pData = NULL; } /**Function************************************************************* Synopsis [Recursively cleans the data pointers in the cone of the node.] Description [Applicable to small AIGs only because no caching is performed.] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ObjCleanData_rec( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); assert( !Hop_ObjIsPo(pObj) ); if ( Hop_ObjIsAnd(pObj) ) { Hop_ObjCleanData_rec( Hop_ObjFanin0(pObj) ); Hop_ObjCleanData_rec( Hop_ObjFanin1(pObj) ); } pObj->pData = NULL; } /**Function************************************************************* Synopsis [Detects multi-input gate rooted at this node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ObjCollectMulti_rec( Hop_Obj_t * pRoot, Hop_Obj_t * pObj, Vec_Ptr_t * vSuper ) { if ( pRoot != pObj && (Hop_IsComplement(pObj) || Hop_ObjIsPi(pObj) || Hop_ObjType(pRoot) != Hop_ObjType(pObj)) ) { Vec_PtrPushUnique(vSuper, pObj); return; } Hop_ObjCollectMulti_rec( pRoot, Hop_ObjChild0(pObj), vSuper ); Hop_ObjCollectMulti_rec( pRoot, Hop_ObjChild1(pObj), vSuper ); } /**Function************************************************************* Synopsis [Detects multi-input gate rooted at this node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ObjCollectMulti( Hop_Obj_t * pRoot, Vec_Ptr_t * vSuper ) { assert( !Hop_IsComplement(pRoot) ); Vec_PtrClear( vSuper ); Hop_ObjCollectMulti_rec( pRoot, pRoot, vSuper ); } /**Function************************************************************* Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hop_ObjIsMuxType( Hop_Obj_t * pNode ) { Hop_Obj_t * pNode0, * pNode1; // check that the node is regular assert( !Hop_IsComplement(pNode) ); // if the node is not AND, this is not MUX if ( !Hop_ObjIsAnd(pNode) ) return 0; // if the children are not complemented, this is not MUX if ( !Hop_ObjFaninC0(pNode) || !Hop_ObjFaninC1(pNode) ) return 0; // get children pNode0 = Hop_ObjFanin0(pNode); pNode1 = Hop_ObjFanin1(pNode); // if the children are not ANDs, this is not MUX if ( !Hop_ObjIsAnd(pNode0) || !Hop_ObjIsAnd(pNode1) ) return 0; // otherwise the node is MUX iff it has a pair of equal grandchildren return (Hop_ObjFanin0(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC0(pNode1))) || (Hop_ObjFanin0(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC1(pNode1))) || (Hop_ObjFanin1(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC0(pNode1))) || (Hop_ObjFanin1(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC1(pNode1))); } /**Function************************************************************* Synopsis [Recognizes what nodes are inputs of the EXOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Hop_ObjRecognizeExor( Hop_Obj_t * pObj, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 ) { Hop_Obj_t * p0, * p1; assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) ) return 0; if ( Hop_ObjIsExor(pObj) ) { *ppFan0 = Hop_ObjChild0(pObj); *ppFan1 = Hop_ObjChild1(pObj); return 1; } assert( Hop_ObjIsAnd(pObj) ); p0 = Hop_ObjChild0(pObj); p1 = Hop_ObjChild1(pObj); if ( !Hop_IsComplement(p0) || !Hop_IsComplement(p1) ) return 0; p0 = Hop_Regular(p0); p1 = Hop_Regular(p1); if ( !Hop_ObjIsAnd(p0) || !Hop_ObjIsAnd(p1) ) return 0; if ( Hop_ObjFanin0(p0) != Hop_ObjFanin0(p1) || Hop_ObjFanin1(p0) != Hop_ObjFanin1(p1) ) return 0; if ( Hop_ObjFaninC0(p0) == Hop_ObjFaninC0(p1) || Hop_ObjFaninC1(p0) == Hop_ObjFaninC1(p1) ) return 0; *ppFan0 = Hop_ObjChild0(p0); *ppFan1 = Hop_ObjChild1(p0); return 1; } /**Function************************************************************* Synopsis [Recognizes what nodes are control and data inputs of a MUX.] Description [If the node is a MUX, returns the control variable C. Assigns nodes T and E to be the then and else variables of the MUX. Node C is never complemented. Nodes T and E can be complemented. This function also recognizes EXOR/NEXOR gates as MUXes.] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Hop_ObjRecognizeMux( Hop_Obj_t * pNode, Hop_Obj_t ** ppNodeT, Hop_Obj_t ** ppNodeE ) { Hop_Obj_t * pNode0, * pNode1; assert( !Hop_IsComplement(pNode) ); assert( Hop_ObjIsMuxType(pNode) ); // get children pNode0 = Hop_ObjFanin0(pNode); pNode1 = Hop_ObjFanin1(pNode); // find the control variable if ( Hop_ObjFanin1(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC1(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p2) ) if ( Hop_ObjFaninC1(pNode0) ) { // pNode2->p2 is positive phase of C *ppNodeT = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); *ppNodeE = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); return Hop_ObjChild1(pNode1);//pNode2->p2; } else { // pNode1->p2 is positive phase of C *ppNodeT = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); *ppNodeE = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); return Hop_ObjChild1(pNode0);//pNode1->p2; } } else if ( Hop_ObjFanin0(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC0(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p1) ) if ( Hop_ObjFaninC0(pNode0) ) { // pNode2->p1 is positive phase of C *ppNodeT = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); *ppNodeE = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); return Hop_ObjChild0(pNode1);//pNode2->p1; } else { // pNode1->p1 is positive phase of C *ppNodeT = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); *ppNodeE = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); return Hop_ObjChild0(pNode0);//pNode1->p1; } } else if ( Hop_ObjFanin0(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC1(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p1) ) if ( Hop_ObjFaninC0(pNode0) ) { // pNode2->p2 is positive phase of C *ppNodeT = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); *ppNodeE = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); return Hop_ObjChild1(pNode1);//pNode2->p2; } else { // pNode1->p1 is positive phase of C *ppNodeT = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); *ppNodeE = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); return Hop_ObjChild0(pNode0);//pNode1->p1; } } else if ( Hop_ObjFanin1(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC0(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p2) ) if ( Hop_ObjFaninC1(pNode0) ) { // pNode2->p1 is positive phase of C *ppNodeT = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); *ppNodeE = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); return Hop_ObjChild0(pNode1);//pNode2->p1; } else { // pNode1->p2 is positive phase of C *ppNodeT = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); *ppNodeE = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); return Hop_ObjChild1(pNode0);//pNode1->p2; } } assert( 0 ); // this is not MUX return NULL; } /**Function************************************************************* Synopsis [Prints Eqn formula for the AIG rooted at this node.] Description [The formula is in terms of PIs, which should have their names assigned in pObj->pData fields.] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ObjPrintEqn( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) { Vec_Ptr_t * vSuper; Hop_Obj_t * pFanin; int fCompl, i; // store the complemented attribute fCompl = Hop_IsComplement(pObj); pObj = Hop_Regular(pObj); // constant case if ( Hop_ObjIsConst1(pObj) ) { fprintf( pFile, "%d", !fCompl ); return; } // PI case if ( Hop_ObjIsPi(pObj) ) { fprintf( pFile, "%s%s", fCompl? "!" : "", (char*)pObj->pData ); return; } // AND case Vec_VecExpand( vLevels, Level ); vSuper = Vec_VecEntry(vLevels, Level); Hop_ObjCollectMulti( pObj, vSuper ); fprintf( pFile, "%s", (Level==0? "" : "(") ); Vec_PtrForEachEntry( Hop_Obj_t *, vSuper, pFanin, i ) { Hop_ObjPrintEqn( pFile, Hop_NotCond(pFanin, fCompl), vLevels, Level+1 ); if ( i < Vec_PtrSize(vSuper) - 1 ) fprintf( pFile, " %s ", fCompl? "+" : "*" ); } fprintf( pFile, "%s", (Level==0? "" : ")") ); return; } /**Function************************************************************* Synopsis [Prints Verilog formula for the AIG rooted at this node.] Description [The formula is in terms of PIs, which should have their names assigned in pObj->pData fields.] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ObjPrintVerilog( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level, int fOnlyAnds ) { Vec_Ptr_t * vSuper; Hop_Obj_t * pFanin, * pFanin0, * pFanin1, * pFaninC; int fCompl, i; // store the complemented attribute fCompl = Hop_IsComplement(pObj); pObj = Hop_Regular(pObj); // constant case if ( Hop_ObjIsConst1(pObj) ) { fprintf( pFile, "1\'b%d", !fCompl ); return; } // PI case if ( Hop_ObjIsPi(pObj) ) { fprintf( pFile, "%s%s", fCompl? "~" : "", (char*)pObj->pData ); return; } // EXOR case if ( !fOnlyAnds && Hop_ObjIsExor(pObj) ) { Vec_VecExpand( vLevels, Level ); vSuper = Vec_VecEntry( vLevels, Level ); Hop_ObjCollectMulti( pObj, vSuper ); fprintf( pFile, "%s", (Level==0? "" : "(") ); Vec_PtrForEachEntry( Hop_Obj_t *, vSuper, pFanin, i ) { Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin, (fCompl && i==0)), vLevels, Level+1, fOnlyAnds ); if ( i < Vec_PtrSize(vSuper) - 1 ) fprintf( pFile, " ^ " ); } fprintf( pFile, "%s", (Level==0? "" : ")") ); return; } // MUX case if ( !fOnlyAnds && Hop_ObjIsMuxType(pObj) ) { if ( Hop_ObjRecognizeExor( pObj, &pFanin0, &pFanin1 ) ) { fprintf( pFile, "%s", (Level==0? "" : "(") ); Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin0, fCompl), vLevels, Level+1, fOnlyAnds ); fprintf( pFile, " ^ " ); Hop_ObjPrintVerilog( pFile, pFanin1, vLevels, Level+1, fOnlyAnds ); fprintf( pFile, "%s", (Level==0? "" : ")") ); } else { pFaninC = Hop_ObjRecognizeMux( pObj, &pFanin1, &pFanin0 ); fprintf( pFile, "%s", (Level==0? "" : "(") ); Hop_ObjPrintVerilog( pFile, pFaninC, vLevels, Level+1, fOnlyAnds ); fprintf( pFile, " ? " ); Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin1, fCompl), vLevels, Level+1, fOnlyAnds ); fprintf( pFile, " : " ); Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin0, fCompl), vLevels, Level+1, fOnlyAnds ); fprintf( pFile, "%s", (Level==0? "" : ")") ); } return; } // AND case Vec_VecExpand( vLevels, Level ); vSuper = Vec_VecEntry(vLevels, Level); Hop_ObjCollectMulti( pObj, vSuper ); fprintf( pFile, "%s", (Level==0? "" : "(") ); Vec_PtrForEachEntry( Hop_Obj_t *, vSuper, pFanin, i ) { Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin, fCompl), vLevels, Level+1, fOnlyAnds ); if ( i < Vec_PtrSize(vSuper) - 1 ) fprintf( pFile, " %s ", fCompl? "|" : "&" ); } fprintf( pFile, "%s", (Level==0? "" : ")") ); return; } /**Function************************************************************* Synopsis [Prints node in HAIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ObjPrintVerbose( Hop_Obj_t * pObj, int fHaig ) { assert( !Hop_IsComplement(pObj) ); printf( "Node %p : ", pObj ); if ( Hop_ObjIsConst1(pObj) ) printf( "constant 1" ); else if ( Hop_ObjIsPi(pObj) ) printf( "PI" ); else printf( "AND( %p%s, %p%s )", Hop_ObjFanin0(pObj), (Hop_ObjFaninC0(pObj)? "\'" : " "), Hop_ObjFanin1(pObj), (Hop_ObjFaninC1(pObj)? "\'" : " ") ); printf( " (refs = %3d)", Hop_ObjRefs(pObj) ); } /**Function************************************************************* Synopsis [Prints node in HAIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ManPrintVerbose( Hop_Man_t * p, int fHaig ) { Vec_Ptr_t * vNodes; Hop_Obj_t * pObj; int i; printf( "PIs: " ); Hop_ManForEachPi( p, pObj, i ) printf( " %p", pObj ); printf( "\n" ); vNodes = Hop_ManDfs( p ); Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i ) Hop_ObjPrintVerbose( pObj, fHaig ), printf( "\n" ); printf( "\n" ); Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Writes the AIG into the BLIF file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ManDumpBlif( Hop_Man_t * p, char * pFileName ) { FILE * pFile; Vec_Ptr_t * vNodes; Hop_Obj_t * pObj, * pConst1 = NULL; int i, nDigits, Counter = 0; if ( Hop_ManPoNum(p) == 0 ) { printf( "Hop_ManDumpBlif(): AIG manager does not have POs.\n" ); return; } // collect nodes in the DFS order vNodes = Hop_ManDfs( p ); // assign IDs to objects Hop_ManConst1(p)->pData = (void *)(ABC_PTRUINT_T)Counter++; Hop_ManForEachPi( p, pObj, i ) pObj->pData = (void *)(ABC_PTRUINT_T)Counter++; Hop_ManForEachPo( p, pObj, i ) pObj->pData = (void *)(ABC_PTRUINT_T)Counter++; Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i ) pObj->pData = (void *)(ABC_PTRUINT_T)Counter++; nDigits = Hop_Base10Log( Counter ); // write the file pFile = fopen( pFileName, "w" ); fprintf( pFile, "# BLIF file written by procedure Hop_ManDumpBlif() in ABC\n" ); fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); fprintf( pFile, ".model test\n" ); // write PIs fprintf( pFile, ".inputs" ); Hop_ManForEachPi( p, pObj, i ) fprintf( pFile, " n%0*d", nDigits, (int)(ABC_PTRUINT_T)pObj->pData ); fprintf( pFile, "\n" ); // write POs fprintf( pFile, ".outputs" ); Hop_ManForEachPo( p, pObj, i ) fprintf( pFile, " n%0*d", nDigits, (int)(ABC_PTRUINT_T)pObj->pData ); fprintf( pFile, "\n" ); // write nodes Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i ) { fprintf( pFile, ".names n%0*d n%0*d n%0*d\n", nDigits, (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData, nDigits, (int)(ABC_PTRUINT_T)Hop_ObjFanin1(pObj)->pData, nDigits, (int)(ABC_PTRUINT_T)pObj->pData ); fprintf( pFile, "%d%d 1\n", !Hop_ObjFaninC0(pObj), !Hop_ObjFaninC1(pObj) ); } // write POs Hop_ManForEachPo( p, pObj, i ) { fprintf( pFile, ".names n%0*d n%0*d\n", nDigits, (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData, nDigits, (int)(ABC_PTRUINT_T)pObj->pData ); fprintf( pFile, "%d 1\n", !Hop_ObjFaninC0(pObj) ); if ( Hop_ObjIsConst1(Hop_ObjFanin0(pObj)) ) pConst1 = Hop_ManConst1(p); } if ( pConst1 ) fprintf( pFile, ".names n%0*d\n 1\n", nDigits, (int)(ABC_PTRUINT_T)pConst1->pData ); fprintf( pFile, ".end\n\n" ); fclose( pFile ); Vec_PtrFree( vNodes ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/hop/hop_.c000066400000000000000000000026651477524141600154170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [hop_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Minimalistic And-Inverter Graph package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: hop_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "hop.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/hop/module.make000066400000000000000000000004371477524141600164450ustar00rootroot00000000000000SRC += src/aig/hop/hopBalance.c \ src/aig/hop/hopCheck.c \ src/aig/hop/hopDfs.c \ src/aig/hop/hopMan.c \ src/aig/hop/hopMem.c \ src/aig/hop/hopObj.c \ src/aig/hop/hopOper.c \ src/aig/hop/hopTable.c \ src/aig/hop/hopTruth.c \ src/aig/hop/hopUtil.c abc-0.52/src/aig/ioa/000077500000000000000000000000001477524141600142775ustar00rootroot00000000000000abc-0.52/src/aig/ioa/ioa.h000066400000000000000000000062041477524141600152220ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioa.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: ioa.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__ioa__ioa_h #define ABC__aig__ioa__ioa_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "misc/vec/vec.h" //#include "bar.h" #include "aig/aig/aig.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== ioaReadAig.c ========================================================*/ extern Aig_Man_t * Ioa_ReadAigerFromMemory( char * pContents, int nFileSize, int fCheck ); extern Aig_Man_t * Ioa_ReadAiger( char * pFileName, int fCheck ); /*=== ioaWriteAig.c =======================================================*/ extern Vec_Str_t * Ioa_WriteAigerIntoMemoryStr( Aig_Man_t * pMan ); extern char * Ioa_WriteAigerIntoMemory( Aig_Man_t * pMan, int * pnSize ); extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); /*=== ioaUtil.c =======================================================*/ extern int Ioa_FileSize( char * pFileName ); extern char * Ioa_FileNameGeneric( char * FileName ); extern char * Ioa_FileNameGenericAppend( char * pBase, char * pSuffix ); extern char * Ioa_TimeStamp(); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/aig/ioa/ioaReadAig.c000066400000000000000000000351271477524141600164400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioaReadAiger.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to read binary AIGER format developed by Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - December 16, 2006.] Revision [$Id: ioaReadAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioa.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Extracts one unsigned AIG edge from the input buffer.] Description [This procedure is a slightly modified version of Armin Biere's procedure "unsigned decode (FILE * file)". ] SideEffects [Updates the current reading position.] SeeAlso [] ***********************************************************************/ unsigned Ioa_ReadAigerDecode( char ** ppPos ) { unsigned x = 0, i = 0; unsigned char ch; // while ((ch = getnoneofch (file)) & 0x80) while ((ch = *(*ppPos)++) & 0x80) x |= (ch & 0x7f) << (7 * i++); return x | (ch << (7 * i)); } /**Function************************************************************* Synopsis [Decodes the encoded array of literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Ioa_WriteDecodeLiterals( char ** ppPos, int nEntries ) { Vec_Int_t * vLits; int Lit, LitPrev, Diff, i; vLits = Vec_IntAlloc( nEntries ); LitPrev = Ioa_ReadAigerDecode( ppPos ); Vec_IntPush( vLits, LitPrev ); for ( i = 1; i < nEntries; i++ ) { // Diff = Lit - LitPrev; // Diff = (Lit < LitPrev)? -Diff : Diff; // Diff = ((2 * Diff) << 1) | (int)(Lit < LitPrev); Diff = Ioa_ReadAigerDecode( ppPos ); Diff = (Diff & 1)? -(Diff >> 1) : Diff >> 1; Lit = Diff + LitPrev; Vec_IntPush( vLits, Lit ); LitPrev = Lit; } return vLits; } /**Function************************************************************* Synopsis [Reads the AIG in from the memory buffer.] Description [The buffer constains the AIG in AIGER format. The size gives the number of bytes in the buffer. The buffer is allocated by the user and not deallocated by this procedure.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Ioa_ReadAigerFromMemory( char * pContents, int nFileSize, int fCheck ) { Vec_Int_t * vLits = NULL; Vec_Ptr_t * vNodes, * vDrivers;//, * vTerms; Aig_Obj_t * pObj, * pNode0, * pNode1; Aig_Man_t * pNew; int nTotal, nInputs, nOutputs, nLatches, nAnds, i;//, iTerm, nDigits; int nBad = 0, nConstr = 0, nJust = 0, nFair = 0; char * pDrivers, * pSymbols, * pCur;//, * pType; unsigned uLit0, uLit1, uLit; // check if the input file format is correct if ( strncmp(pContents, "aig", 3) != 0 || (pContents[3] != ' ' && pContents[3] != '2') ) { fprintf( stdout, "Wrong input file format.\n" ); return NULL; } // read the parameters (M I L O A + B C J F) pCur = pContents; while ( *pCur != ' ' ) pCur++; pCur++; // read the number of objects nTotal = atoi( pCur ); while ( *pCur != ' ' ) pCur++; pCur++; // read the number of inputs nInputs = atoi( pCur ); while ( *pCur != ' ' ) pCur++; pCur++; // read the number of latches nLatches = atoi( pCur ); while ( *pCur != ' ' ) pCur++; pCur++; // read the number of outputs nOutputs = atoi( pCur ); while ( *pCur != ' ' ) pCur++; pCur++; // read the number of nodes nAnds = atoi( pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; if ( *pCur == ' ' ) { assert( nOutputs == 0 ); // read the number of properties pCur++; nBad = atoi( pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; nOutputs += nBad; } if ( *pCur == ' ' ) { // read the number of properties pCur++; nConstr = atoi( pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; nOutputs += nConstr; } if ( *pCur == ' ' ) { // read the number of properties pCur++; nJust = atoi( pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; nOutputs += nJust; } if ( *pCur == ' ' ) { // read the number of properties pCur++; nFair = atoi( pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; nOutputs += nFair; } if ( *pCur != '\n' ) { fprintf( stdout, "The parameter line is in a wrong format.\n" ); return NULL; } pCur++; // check the parameters if ( nTotal != nInputs + nLatches + nAnds ) { fprintf( stdout, "The number of objects does not match.\n" ); return NULL; } if ( nJust || nFair ) { fprintf( stdout, "Reading AIGER files with liveness properties are currently not supported.\n" ); return NULL; } if ( nConstr ) { if ( nConstr == 1 ) fprintf( stdout, "Warning: The last output is interpreted as a constraint.\n" ); else fprintf( stdout, "Warning: The last %d outputs are interpreted as constraints.\n", nConstr ); } // allocate the empty AIG pNew = Aig_ManStart( nAnds ); pNew->nConstrs = nConstr; // prepare the array of nodes vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds ); Vec_PtrPush( vNodes, Aig_ManConst0(pNew) ); // create the PIs for ( i = 0; i < nInputs + nLatches; i++ ) { pObj = Aig_ObjCreateCi(pNew); Vec_PtrPush( vNodes, pObj ); } /* // create the POs for ( i = 0; i < nOutputs + nLatches; i++ ) { pObj = Aig_ObjCreateCo(pNew); } */ // create the latches pNew->nRegs = nLatches; /* nDigits = Ioa_Base10Log( nLatches ); for ( i = 0; i < nLatches; i++ ) { pObj = Aig_ObjCreateLatch(pNew); Aig_LatchSetInit0( pObj ); pNode0 = Aig_ObjCreateBi(pNew); pNode1 = Aig_ObjCreateBo(pNew); Aig_ObjAddFanin( pObj, pNode0 ); Aig_ObjAddFanin( pNode1, pObj ); Vec_PtrPush( vNodes, pNode1 ); // assign names to latch and its input // Aig_ObjAssignName( pObj, Aig_ObjNameDummy("_L", i, nDigits), NULL ); // printf( "Creating latch %s with input %d and output %d.\n", Aig_ObjName(pObj), pNode0->Id, pNode1->Id ); } */ // remember the beginning of latch/PO literals pDrivers = pCur; if ( pContents[3] == ' ' ) // standard AIGER { // scroll to the beginning of the binary data for ( i = 0; i < nLatches + nOutputs; ) if ( *pCur++ == '\n' ) i++; } else // modified AIGER { vLits = Ioa_WriteDecodeLiterals( &pCur, nLatches + nOutputs ); } // create the AND gates // pProgress = Bar_ProgressStart( stdout, nAnds ); for ( i = 0; i < nAnds; i++ ) { // Bar_ProgressUpdate( pProgress, i, NULL ); uLit = ((i + 1 + nInputs + nLatches) << 1); uLit1 = uLit - Ioa_ReadAigerDecode( &pCur ); uLit0 = uLit1 - Ioa_ReadAigerDecode( &pCur ); // assert( uLit1 > uLit0 ); pNode0 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); pNode1 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); assert( Vec_PtrSize(vNodes) == i + 1 + nInputs + nLatches ); Vec_PtrPush( vNodes, Aig_And(pNew, pNode0, pNode1) ); } // Bar_ProgressStop( pProgress ); // remember the place where symbols begin pSymbols = pCur; // read the latch driver literals vDrivers = Vec_PtrAlloc( nLatches + nOutputs ); if ( pContents[3] == ' ' ) // standard AIGER { pCur = pDrivers; for ( i = 0; i < nLatches; i++ ) { uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); pNode0 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); Vec_PtrPush( vDrivers, pNode0 ); } // read the PO driver literals for ( i = 0; i < nOutputs; i++ ) { uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); pNode0 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); Vec_PtrPush( vDrivers, pNode0 ); } } else { // read the latch driver literals for ( i = 0; i < nLatches; i++ ) { uLit0 = Vec_IntEntry( vLits, i ); pNode0 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); Vec_PtrPush( vDrivers, pNode0 ); } // read the PO driver literals for ( i = 0; i < nOutputs; i++ ) { uLit0 = Vec_IntEntry( vLits, i+nLatches ); pNode0 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); Vec_PtrPush( vDrivers, pNode0 ); } Vec_IntFree( vLits ); } // create the POs for ( i = 0; i < nOutputs; i++ ) Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vDrivers, nLatches + i) ); for ( i = 0; i < nLatches; i++ ) Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vDrivers, i) ); Vec_PtrFree( vDrivers ); /* // read the names if present pCur = pSymbols; if ( *pCur != 'c' ) { int Counter = 0; while ( pCur < pContents + nFileSize && *pCur != 'c' ) { // get the terminal type pType = pCur; if ( *pCur == 'i' ) vTerms = pNew->vPis; else if ( *pCur == 'l' ) vTerms = pNew->vBoxes; else if ( *pCur == 'o' ) vTerms = pNew->vPos; else { fprintf( stdout, "Wrong terminal type.\n" ); return NULL; } // get the terminal number iTerm = atoi( ++pCur ); while ( *pCur++ != ' ' ); // get the node if ( iTerm >= Vec_PtrSize(vTerms) ) { fprintf( stdout, "The number of terminal is out of bound.\n" ); return NULL; } pObj = Vec_PtrEntry( vTerms, iTerm ); if ( *pType == 'l' ) pObj = Aig_ObjFanout0(pObj); // assign the name pName = pCur; while ( *pCur++ != '\n' ); // assign this name *(pCur-1) = 0; Aig_ObjAssignName( pObj, pName, NULL ); if ( *pType == 'l' ) { Aig_ObjAssignName( Aig_ObjFanin0(pObj), Aig_ObjName(pObj), "L" ); Aig_ObjAssignName( Aig_ObjFanin0(Aig_ObjFanin0(pObj)), Aig_ObjName(pObj), "_in" ); } // mark the node as named pObj->pCopy = (Aig_Obj_t *)Aig_ObjName(pObj); } // assign the remaining names Aig_ManForEachCi( pNew, pObj, i ) { if ( pObj->pCopy ) continue; Aig_ObjAssignName( pObj, Aig_ObjName(pObj), NULL ); Counter++; } Aig_ManForEachLatchOutput( pNew, pObj, i ) { if ( pObj->pCopy ) continue; Aig_ObjAssignName( pObj, Aig_ObjName(pObj), NULL ); Aig_ObjAssignName( Aig_ObjFanin0(pObj), Aig_ObjName(pObj), "L" ); Aig_ObjAssignName( Aig_ObjFanin0(Aig_ObjFanin0(pObj)), Aig_ObjName(pObj), "_in" ); Counter++; } Aig_ManForEachCo( pNew, pObj, i ) { if ( pObj->pCopy ) continue; Aig_ObjAssignName( pObj, Aig_ObjName(pObj), NULL ); Counter++; } if ( Counter ) printf( "Ioa_ReadAiger(): Added %d default names for nameless I/O/register objects.\n", Counter ); } else { // printf( "Ioa_ReadAiger(): I/O/register names are not given. Generating short names.\n" ); Aig_ManShortNames( pNew ); } */ pCur = pSymbols; if ( pCur + 1 < pContents + nFileSize && *pCur == 'c' ) { pCur++; if ( *pCur == 'n' ) { pCur++; // read model name ABC_FREE( pNew->pName ); pNew->pName = Abc_UtilStrsav( pCur ); } } // skipping the comments Vec_PtrFree( vNodes ); // remove the extra nodes Aig_ManCleanup( pNew ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(pNew) ); // update polarity of the additional outputs if ( nBad || nConstr || nJust || nFair ) Aig_ManInvertConstraints( pNew ); // check the result if ( fCheck && !Aig_ManCheck( pNew ) ) { printf( "Ioa_ReadAiger: The network check has failed.\n" ); Aig_ManStop( pNew ); return NULL; } return pNew; } /**Function************************************************************* Synopsis [Reads the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Ioa_ReadAiger( char * pFileName, int fCheck ) { FILE * pFile; Aig_Man_t * pNew; char * pName, * pContents; int nFileSize, RetValue; // read the file into the buffer nFileSize = Ioa_FileSize( pFileName ); pFile = fopen( pFileName, "rb" ); pContents = ABC_CALLOC( char, nFileSize+1 ); RetValue = fread( pContents, nFileSize, 1, pFile ); fclose( pFile ); pNew = Ioa_ReadAigerFromMemory( pContents, nFileSize, fCheck ); ABC_FREE( pContents ); if ( pNew ) { pName = Ioa_FileNameGeneric( pFileName ); ABC_FREE( pNew->pName ); pNew->pName = Abc_UtilStrsav( pName ); pNew->pSpec = Abc_UtilStrsav( pFileName ); ABC_FREE( pName ); } return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ioa/ioaUtil.c000066400000000000000000000074461477524141600160640ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioaUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to read binary AIGER format developed by Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - December 16, 2006.] Revision [$Id: ioaUtil.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioa.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the file size.] Description [The file should be closed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ioa_FileSize( char * pFileName ) { FILE * pFile; int nFileSize; pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { printf( "Ioa_FileSize(): The file is unavailable (absent or open).\n" ); return 0; } fseek( pFile, 0, SEEK_END ); nFileSize = ftell( pFile ); fclose( pFile ); return nFileSize; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Ioa_FileNameGeneric( char * FileName ) { char * pDot, * pRes; pRes = Abc_UtilStrsav( FileName ); if ( (pDot = strrchr( pRes, '.' )) ) *pDot = 0; return pRes; } /**Function************************************************************* Synopsis [Returns the composite name of the file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Ioa_FileNameGenericAppend( char * pBase, char * pSuffix ) { static char Buffer[1000]; char * pDot; if ( pBase == NULL ) { strcpy( Buffer, pSuffix ); return Buffer; } strcpy( Buffer, pBase ); if ( (pDot = strrchr( Buffer, '.' )) ) *pDot = 0; strcat( Buffer, pSuffix ); // find the last occurrance of slash for ( pDot = Buffer + strlen(Buffer) - 1; pDot >= Buffer; pDot-- ) if (!((*pDot >= '0' && *pDot <= '9') || (*pDot >= 'a' && *pDot <= 'z') || (*pDot >= 'A' && *pDot <= 'Z') || *pDot == '_' || *pDot == '.') ) break; return pDot + 1; } /**Function************************************************************* Synopsis [Returns the time stamp.] Description [The file should be closed.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Ioa_TimeStamp() { static char Buffer[100]; char * TimeStamp; time_t ltime; // get the current time time( <ime ); TimeStamp = asctime( localtime( <ime ) ); TimeStamp[ strlen(TimeStamp) - 1 ] = 0; strcpy( Buffer, TimeStamp ); return Buffer; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ioa/ioaWriteAig.c000066400000000000000000000516551477524141600166630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ioaWriteAiger.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Command processing package.] Synopsis [Procedures to write binary AIGER format developed by Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - December 16, 2006.] Revision [$Id: ioaWriteAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ioa.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /* The following is taken from the AIGER format description, which can be found at http://fmv.jku.at/aiger */ /* The AIGER And-Inverter Graph (AIG) Format Version 20061129 ---------------------------------------------------------- Armin Biere, Johannes Kepler University, 2006 This report describes the AIG file format as used by the AIGER library. The purpose of this report is not only to motivate and document the format, but also to allow independent implementations of writers and readers by giving precise and unambiguous definitions. ... Introduction The name AIGER contains as one part the acronym AIG of And-Inverter Graphs and also if pronounced in German sounds like the name of the 'Eiger', a mountain in the Swiss alps. This choice should emphasize the origin of this format. It was first openly discussed at the Alpine Verification Meeting 2006 in Ascona as a way to provide a simple, compact file format for a model checking competition affiliated to CAV 2007. ... Binary Format Definition The binary format is semantically a subset of the ASCII format with a slightly different syntax. The binary format may need to reencode literals, but translating a file in binary format into ASCII format and then back in to binary format will result in the same file. The main differences of the binary format to the ASCII format are as follows. After the header the list of input literals and all the current state literals of a latch can be omitted. Furthermore the definitions of the AND gates are binary encoded. However, the symbol table and the comment section are as in the ASCII format. The header of an AIGER file in binary format has 'aig' as format identifier, but otherwise is identical to the ASCII header. The standard file extension for the binary format is therefore '.aig'. A header for the binary format is still in ASCII encoding: aig M I L O A Constants, variables and literals are handled in the same way as in the ASCII format. The first simplifying restriction is on the variable indices of inputs and latches. The variable indices of inputs come first, followed by the pseudo-primary inputs of the latches and then the variable indices of all LHS of AND gates: input variable indices 1, 2, ... , I latch variable indices I+1, I+2, ... , (I+L) AND variable indices I+L+1, I+L+2, ... , (I+L+A) == M The corresponding unsigned literals are input literals 2, 4, ... , 2*I latch literals 2*I+2, 2*I+4, ... , 2*(I+L) AND literals 2*(I+L)+2, 2*(I+L)+4, ... , 2*(I+L+A) == 2*M All literals have to be defined, and therefore 'M = I + L + A'. With this restriction it becomes possible that the inputs and the current state literals of the latches do not have to be listed explicitly. Therefore, after the header only the list of 'L' next state literals follows, one per latch on a single line, and then the 'O' outputs, again one per line. In the binary format we assume that the AND gates are ordered and respect the child parent relation. AND gates with smaller literals on the LHS come first. Therefore we can assume that the literals on the right-hand side of a definition of an AND gate are smaller than the LHS literal. Furthermore we can sort the literals on the RHS, such that the larger literal comes first. A definition thus consists of three literals lhs rhs0 rhs1 with 'lhs' even and 'lhs > rhs0 >= rhs1'. Also the variable indices are pairwise different to avoid combinational self loops. Since the LHS indices of the definitions are all consecutive (as even integers), the binary format does not have to keep 'lhs'. In addition, we can use the order restriction and only write the differences 'delta0' and 'delta1' instead of 'rhs0' and 'rhs1', with delta0 = lhs - rhs0, delta1 = rhs0 - rhs1 The differences will all be strictly positive, and in practice often very small. We can take advantage of this fact by the simple little-endian encoding of unsigned integers of the next section. After the binary delta encoding of the RHSs of all AND gates, the optional symbol table and optional comment section start in the same format as in the ASCII case. ... */ static int Ioa_ObjMakeLit( int Var, int fCompl ) { return (Var << 1) | fCompl; } static int Ioa_ObjAigerNum( Aig_Obj_t * pObj ) { return pObj->iData; } static void Ioa_ObjSetAigerNum( Aig_Obj_t * pObj, unsigned Num ) { pObj->iData = Num; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Adds one unsigned AIG edge to the output buffer.] Description [This procedure is a slightly modified version of Armin Biere's procedure "void encode (FILE * file, unsigned x)" ] SideEffects [Returns the current writing position.] SeeAlso [] ***********************************************************************/ int Ioa_WriteAigerEncode( unsigned char * pBuffer, int Pos, unsigned x ) { unsigned char ch; while (x & ~0x7f) { ch = (x & 0x7f) | 0x80; // putc (ch, file); pBuffer[Pos++] = ch; x >>= 7; } ch = x; // putc (ch, file); pBuffer[Pos++] = ch; return Pos; } /**Function************************************************************* Synopsis [Adds one unsigned AIG edge to the output buffer.] Description [This procedure is a slightly modified version of Armin Biere's procedure "void encode (FILE * file, unsigned x)" ] SideEffects [Returns the current writing position.] SeeAlso [] ***********************************************************************/ void Ioa_WriteAigerEncodeStr( Vec_Str_t * vStr, unsigned x ) { unsigned char ch; while (x & ~0x7f) { ch = (x & 0x7f) | 0x80; // putc (ch, file); // pBuffer[Pos++] = ch; Vec_StrPush( vStr, ch ); x >>= 7; } ch = x; // putc (ch, file); // pBuffer[Pos++] = ch; Vec_StrPush( vStr, ch ); } /**Function************************************************************* Synopsis [Create the array of literals to be written.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Ioa_WriteAigerLiterals( Aig_Man_t * pMan ) { Vec_Int_t * vLits; Aig_Obj_t * pObj, * pDriver; int i; vLits = Vec_IntAlloc( Aig_ManCoNum(pMan) ); Aig_ManForEachLiSeq( pMan, pObj, i ) { pDriver = Aig_ObjFanin0(pObj); Vec_IntPush( vLits, Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); } Aig_ManForEachPoSeq( pMan, pObj, i ) { pDriver = Aig_ObjFanin0(pObj); Vec_IntPush( vLits, Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); } return vLits; } /**Function************************************************************* Synopsis [Creates the binary encoded array of literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Ioa_WriteEncodeLiterals( Vec_Int_t * vLits ) { Vec_Str_t * vBinary; int Pos = 0, Lit, LitPrev, Diff, i; vBinary = Vec_StrAlloc( 2 * Vec_IntSize(vLits) ); LitPrev = Vec_IntEntry( vLits, 0 ); Pos = Ioa_WriteAigerEncode( (unsigned char *)Vec_StrArray(vBinary), Pos, LitPrev ); Vec_IntForEachEntryStart( vLits, Lit, i, 1 ) { Diff = Lit - LitPrev; Diff = (Lit < LitPrev)? -Diff : Diff; Diff = (Diff << 1) | (int)(Lit < LitPrev); Pos = Ioa_WriteAigerEncode( (unsigned char *)Vec_StrArray(vBinary), Pos, Diff ); LitPrev = Lit; if ( Pos + 10 > vBinary->nCap ) Vec_StrGrow( vBinary, vBinary->nCap+1 ); } vBinary->nSize = Pos; /* // verify { extern Vec_Int_t * Ioa_WriteDecodeLiterals( char ** ppPos, int nEntries ); char * pPos = Vec_StrArray( vBinary ); Vec_Int_t * vTemp = Ioa_WriteDecodeLiterals( &pPos, Vec_IntSize(vLits) ); for ( i = 0; i < Vec_IntSize(vLits); i++ ) { int Entry1 = Vec_IntEntry(vLits,i); int Entry2 = Vec_IntEntry(vTemp,i); assert( Entry1 == Entry2 ); } Vec_IntFree( vTemp ); } */ return vBinary; } /**Function************************************************************* Synopsis [Writes the AIG in into the memory buffer.] Description [The resulting buffer constains the AIG in AIGER format. The returned size (pnSize) gives the number of bytes in the buffer. The resulting buffer should be deallocated by the user.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Ioa_WriteAigerIntoMemoryStr( Aig_Man_t * pMan ) { Vec_Str_t * vBuffer; Aig_Obj_t * pObj, * pDriver; int nNodes, i, uLit, uLit0, uLit1; // set the node numbers to be used in the output file nNodes = 0; Ioa_ObjSetAigerNum( Aig_ManConst1(pMan), nNodes++ ); Aig_ManForEachCi( pMan, pObj, i ) Ioa_ObjSetAigerNum( pObj, nNodes++ ); Aig_ManForEachNode( pMan, pObj, i ) Ioa_ObjSetAigerNum( pObj, nNodes++ ); // write the header "M I L O A" where M = I + L + A /* fprintf( pFile, "aig%s %u %u %u %u %u\n", fCompact? "2" : "", Aig_ManCiNum(pMan) + Aig_ManNodeNum(pMan), Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan), Aig_ManRegNum(pMan), Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan), Aig_ManNodeNum(pMan) ); */ vBuffer = Vec_StrAlloc( 3*Aig_ManObjNum(pMan) ); Vec_StrPrintStr( vBuffer, "aig " ); Vec_StrPrintNum( vBuffer, Aig_ManCiNum(pMan) + Aig_ManNodeNum(pMan) ); Vec_StrPrintStr( vBuffer, " " ); Vec_StrPrintNum( vBuffer, Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan) ); Vec_StrPrintStr( vBuffer, " " ); Vec_StrPrintNum( vBuffer, Aig_ManRegNum(pMan) ); Vec_StrPrintStr( vBuffer, " " ); Vec_StrPrintNum( vBuffer, Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) ); Vec_StrPrintStr( vBuffer, " " ); Vec_StrPrintNum( vBuffer, Aig_ManNodeNum(pMan) ); Vec_StrPrintStr( vBuffer, "\n" ); // write latch drivers Aig_ManForEachLiSeq( pMan, pObj, i ) { pDriver = Aig_ObjFanin0(pObj); uLit = Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ); // fprintf( pFile, "%u\n", uLit ); Vec_StrPrintNum( vBuffer, uLit ); Vec_StrPrintStr( vBuffer, "\n" ); } // write PO drivers Aig_ManForEachPoSeq( pMan, pObj, i ) { pDriver = Aig_ObjFanin0(pObj); uLit = Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ); // fprintf( pFile, "%u\n", uLit ); Vec_StrPrintNum( vBuffer, uLit ); Vec_StrPrintStr( vBuffer, "\n" ); } // write the nodes into the buffer Aig_ManForEachNode( pMan, pObj, i ) { uLit = Ioa_ObjMakeLit( Ioa_ObjAigerNum(pObj), 0 ); uLit0 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); uLit1 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); assert( uLit0 != uLit1 ); if ( uLit0 > uLit1 ) { int Temp = uLit0; uLit0 = uLit1; uLit1 = Temp; } // Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit - uLit1 ); // Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 ); Ioa_WriteAigerEncodeStr( vBuffer, uLit - uLit1 ); Ioa_WriteAigerEncodeStr( vBuffer, uLit1 - uLit0 ); } Vec_StrPrintStr( vBuffer, "c" ); return vBuffer; } /**Function************************************************************* Synopsis [Writes the AIG in into the memory buffer.] Description [The resulting buffer constains the AIG in AIGER format. The returned size (pnSize) gives the number of bytes in the buffer. The resulting buffer should be deallocated by the user.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Ioa_WriteAigerIntoMemory( Aig_Man_t * pMan, int * pnSize ) { char * pBuffer; Vec_Str_t * vBuffer; vBuffer = Ioa_WriteAigerIntoMemoryStr( pMan ); if ( pMan->pName ) { Vec_StrPrintStr( vBuffer, "n" ); Vec_StrPrintStr( vBuffer, pMan->pName ); Vec_StrPush( vBuffer, 0 ); } // prepare the return values *pnSize = Vec_StrSize( vBuffer ); pBuffer = Vec_StrReleaseArray( vBuffer ); Vec_StrFree( vBuffer ); return pBuffer; } /**Function************************************************************* Synopsis [This procedure is used to test the above procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ioa_WriteAigerBufferTest( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ) { FILE * pFile; char * pBuffer; int nSize; if ( Aig_ManCoNum(pMan) == 0 ) { printf( "AIG cannot be written because it has no POs.\n" ); return; } // start the output stream pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { fprintf( stdout, "Ioa_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName ); return; } // write the buffer pBuffer = Ioa_WriteAigerIntoMemory( pMan, &nSize ); fwrite( pBuffer, 1, nSize, pFile ); ABC_FREE( pBuffer ); // write the comment // fprintf( pFile, "c" ); // if ( pMan->pName ) // fprintf( pFile, "n%s%c", pMan->pName, '\0' ); fprintf( pFile, "\nThis file was produced by the IOA package in ABC on %s\n", Ioa_TimeStamp() ); fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); fclose( pFile ); } /**Function************************************************************* Synopsis [Writes the AIG in the binary AIGER format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ) { // Bar_Progress_t * pProgress; FILE * pFile; Aig_Obj_t * pObj, * pDriver; int i, nNodes, nBufferSize, Pos; unsigned char * pBuffer; unsigned uLit0, uLit1, uLit; if ( Aig_ManCoNum(pMan) == 0 ) { printf( "AIG cannot be written because it has no POs.\n" ); return; } // assert( Aig_ManIsStrash(pMan) ); // start the output stream pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { fprintf( stdout, "Ioa_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName ); return; } /* Aig_ManForEachLatch( pMan, pObj, i ) if ( !Aig_LatchIsInit0(pObj) ) { fprintf( stdout, "Ioa_WriteAiger(): Cannot write AIGER format with non-0 latch init values. Run \"zero\".\n" ); return; } */ // set the node numbers to be used in the output file nNodes = 0; Ioa_ObjSetAigerNum( Aig_ManConst1(pMan), nNodes++ ); Aig_ManForEachCi( pMan, pObj, i ) Ioa_ObjSetAigerNum( pObj, nNodes++ ); Aig_ManForEachNode( pMan, pObj, i ) Ioa_ObjSetAigerNum( pObj, nNodes++ ); // write the header "M I L O A" where M = I + L + A fprintf( pFile, "aig%s %u %u %u %u %u", fCompact? "2" : "", Aig_ManCiNum(pMan) + Aig_ManNodeNum(pMan), Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan), Aig_ManRegNum(pMan), Aig_ManConstrNum(pMan) ? 0 : Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan), Aig_ManNodeNum(pMan) ); // write the extended header "B C J F" if ( Aig_ManConstrNum(pMan) ) fprintf( pFile, " %u %u", Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) - Aig_ManConstrNum(pMan), Aig_ManConstrNum(pMan) ); fprintf( pFile, "\n" ); // if the driver node is a constant, we need to complement the literal below // because, in the AIGER format, literal 0/1 is represented as number 0/1 // while, in ABC, constant 1 node has number 0 and so literal 0/1 will be 1/0 Aig_ManInvertConstraints( pMan ); if ( !fCompact ) { // write latch drivers Aig_ManForEachLiSeq( pMan, pObj, i ) { pDriver = Aig_ObjFanin0(pObj); fprintf( pFile, "%u\n", Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); } // write PO drivers Aig_ManForEachPoSeq( pMan, pObj, i ) { pDriver = Aig_ObjFanin0(pObj); fprintf( pFile, "%u\n", Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); } } else { Vec_Int_t * vLits = Ioa_WriteAigerLiterals( pMan ); Vec_Str_t * vBinary = Ioa_WriteEncodeLiterals( vLits ); fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), pFile ); Vec_StrFree( vBinary ); Vec_IntFree( vLits ); } Aig_ManInvertConstraints( pMan ); // write the nodes into the buffer Pos = 0; nBufferSize = 6 * Aig_ManNodeNum(pMan) + 100; // skeptically assuming 3 chars per one AIG edge pBuffer = ABC_ALLOC( unsigned char, nBufferSize ); // pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(pMan) ); Aig_ManForEachNode( pMan, pObj, i ) { // Bar_ProgressUpdate( pProgress, i, NULL ); uLit = Ioa_ObjMakeLit( Ioa_ObjAigerNum(pObj), 0 ); uLit0 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); uLit1 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); assert( uLit0 != uLit1 ); if ( uLit0 > uLit1 ) { int Temp = uLit0; uLit0 = uLit1; uLit1 = Temp; } Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit - uLit1 ); Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 ); if ( Pos > nBufferSize - 10 ) { printf( "Ioa_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" ); fclose( pFile ); return; } } assert( Pos < nBufferSize ); // Bar_ProgressStop( pProgress ); // write the buffer fwrite( pBuffer, 1, Pos, pFile ); ABC_FREE( pBuffer ); /* // write the symbol table if ( fWriteSymbols ) { int bads; // write PIs Aig_ManForEachPiSeq( pMan, pObj, i ) fprintf( pFile, "i%d %s\n", i, Aig_ObjName(pObj) ); // write latches Aig_ManForEachLoSeq( pMan, pObj, i ) fprintf( pFile, "l%d %s\n", i, Aig_ObjName(Aig_ObjFanout0(pObj)) ); // write POs bads = Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) - Aig_ManConstrNum(pMan); Aig_ManForEachPoSeq( pMan, pObj, i ) if ( !Aig_ManConstrNum(pMan) ) fprintf( pFile, "o%d %s\n", i, Aig_ObjName(pObj) ); else if ( i < bads ) fprintf( pFile, "b%d %s\n", i, Aig_ObjName(pObj) ); else fprintf( pFile, "c%d %s\n", i - bads, Aig_ObjName(pObj) ); } */ // write the comment fprintf( pFile, "c" ); if ( pMan->pName ) fprintf( pFile, "n%s%c", pMan->pName, '\0' ); fprintf( pFile, "\nThis file was produced by the IOA package in ABC on %s\n", Ioa_TimeStamp() ); fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); fclose( pFile ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ioa/module.make000066400000000000000000000001451477524141600164230ustar00rootroot00000000000000SRC += src/aig/ioa/ioaReadAig.c \ src/aig/ioa/ioaWriteAig.c \ src/aig/ioa/ioaUtil.c abc-0.52/src/aig/ivy/000077500000000000000000000000001477524141600143365ustar00rootroot00000000000000abc-0.52/src/aig/ivy/attr.h000066400000000000000000000267771477524141600155040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [attr.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network attributes.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: attr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__ivy__attr_h #define ABC__aig__ivy__attr_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "misc/extra/extra.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Attr_ManStruct_t_ Attr_Man_t; struct Attr_ManStruct_t_ { // attribute info int nAttrSize; // the size of each attribute in bytes Extra_MmFixed_t * pManMem; // memory manager for attributes int nAttrs; // the number of attributes allocated void ** pAttrs; // the array of attributes int fUseInt; // uses integer attributes // attribute specific info void * pManAttr; // the manager for this attribute void (*pFuncFreeMan) (void *); // the procedure to call to free attribute-specific manager void (*pFuncFreeObj) (void *, void *); // the procedure to call to free attribute-specific data }; // at any time, an attribute of the given ID can be // - not available (p->nAttrs < Id) // - available but not allocated (p->nAttrs >= Id && p->pAttrs[Id] == NULL) // - available and allocated (p->nAttrs >= Id && p->pAttrs[Id] != NULL) //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates the attribute manager.] Description [The manager is simple if it does not need memory manager.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Attr_Man_t * Attr_ManAlloc( int nAttrSize, int fManMem ) { Attr_Man_t * p; p = ALLOC( Attr_Man_t, 1 ); memset( p, 0, sizeof(Attr_Man_t) ); p->nAttrSize = nAttrSize; if ( fManMem ) p->pManMem = Extra_MmFixedStart( nAttrSize ); return p; } /**Function************************************************************* Synopsis [Start the attribute manager for integers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Attr_Man_t * Attr_ManStartInt( int nAttrs ) { Attr_Man_t * p; p = Attr_ManAlloc( sizeof(int), 0 ); p->nAttrs = nAttrs; p->pAttrs = (void **)ALLOC( int, nAttrs ); memset( (int *)p->pAttrs, 0, sizeof(int) * nAttrs ); p->fUseInt = 1; return p; } /**Function************************************************************* Synopsis [Start the attribute manager for pointers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Attr_Man_t * Attr_ManStartPtr( int nAttrs ) { Attr_Man_t * p; p = Attr_ManAlloc( sizeof(void *), 0 ); p->nAttrs = nAttrs; p->pAttrs = ALLOC( void *, nAttrs ); memset( p->pAttrs, 0, sizeof(void *) * nAttrs ); return p; } /**Function************************************************************* Synopsis [Start the attribute manager for the fixed entry size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Attr_Man_t * Attr_ManStartPtrMem( int nAttrs, int nAttrSize ) { Attr_Man_t * p; int i; p = Attr_ManAlloc( nAttrSize, 1 ); p->nAttrs = nAttrs; p->pAttrs = ALLOC( void *, nAttrs ); for ( i = 0; i < p->nAttrs; i++ ) { p->pAttrs[i] = Extra_MmFixedEntryFetch( p->pManMem ); memset( p->pAttrs[i], 0, nAttrSize ); } return p; } /**Function************************************************************* Synopsis [Stop the attribute manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Attr_ManStop( Attr_Man_t * p ) { // free the attributes of objects if ( p->pFuncFreeObj ) { int i; if ( p->fUseInt ) { for ( i = 0; i < p->nAttrs; i++ ) if ( ((int *)p->pAttrs)[i] ) p->pFuncFreeObj( p->pManAttr, (void *)((int *)p->pAttrs)[i] ); } else { for ( i = 0; i < p->nAttrs; i++ ) if ( p->pAttrs[i] ) p->pFuncFreeObj( p->pManAttr, p->pAttrs[i] ); } } // free the attribute manager if ( p->pManAttr && p->pFuncFreeMan ) p->pFuncFreeMan( p->pManAttr ); // free the memory manager if ( p->pManMem ) Extra_MmFixedStop( p->pManMem); // free the attribute manager FREE( p->pAttrs ); free( p ); } /**Function************************************************************* Synopsis [Reads the attribute of the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Attr_ManReadAttrInt( Attr_Man_t * p, int Id ) { assert( p->fUseInt ); if ( Id >= p->nAttrs ) return 0; return ((int *)p->pAttrs)[Id]; } /**Function************************************************************* Synopsis [Reads the attribute of the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void * Attr_ManReadAttrPtr( Attr_Man_t * p, int Id ) { assert( !p->fUseInt ); if ( Id >= p->nAttrs ) return NULL; return p->pAttrs[Id]; } /**Function************************************************************* Synopsis [Writes the attribute of the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Attr_ManWriteAttrInt( Attr_Man_t * p, int Id, int Attr ) { assert( p->fUseInt ); ((int *)p->pAttrs)[Id] = Attr; } /**Function************************************************************* Synopsis [Writes the attribute of the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Attr_ManWriteAttrPtr( Attr_Man_t * p, int Id, void * pAttr ) { assert( !p->fUseInt ); assert( p->pManMem == NULL ); p->pAttrs[Id] = pAttr; } /**Function************************************************************* Synopsis [Returns or creates the pointer to the attribute of the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int * Attr_ManFetchSpotInt( Attr_Man_t * p, int Id ) { assert( p->fUseInt ); if ( Id >= p->nAttrs ) { // save the old size int i, nAttrsOld = p->nAttrs; // get the new size p->nAttrs = p->nAttrs? 2*p->nAttrs : 1024; p->pAttrs = realloc( p->pAttrs, sizeof(int) * p->nAttrs ); // fill in the empty spots for ( i = nAttrsOld; i < p->nAttrs; i++ ) ((int *)p->pAttrs)[Id] = 0; } return ((int *)p->pAttrs) + Id; } /**Function************************************************************* Synopsis [Returns or creates the pointer to the attribute of the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void ** Attr_ManFetchSpotPtr( Attr_Man_t * p, int Id ) { assert( !p->fUseInt ); if ( Id >= p->nAttrs ) { // save the old size int i, nAttrsOld = p->nAttrs; // get the new size p->nAttrs = p->nAttrs? 2*p->nAttrs : 1024; p->pAttrs = realloc( p->pAttrs, sizeof(void *) * p->nAttrs ); // fill in the empty spots for ( i = nAttrsOld; i < p->nAttrs; i++ ) p->pAttrs[Id] = NULL; } // if memory manager is available but entry is not created, create it if ( p->pManMem && p->pAttrs[Id] != NULL ) { p->pAttrs[Id] = Extra_MmFixedEntryFetch( p->pManMem ); memset( p->pAttrs[Id], 0, p->nAttrSize ); } return p->pAttrs + Id; } /**Function************************************************************* Synopsis [Returns or creates the attribute of the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Attr_ManFetchAttrInt( Attr_Man_t * p, int Id ) { return *Attr_ManFetchSpotInt( p, Id ); } /**Function************************************************************* Synopsis [Returns or creates the attribute of the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void * Attr_ManFetchAttrPtr( Attr_Man_t * p, int Id ) { return *Attr_ManFetchSpotPtr( p, Id ); } /**Function************************************************************* Synopsis [Sets the attribute of the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Attr_ManSetAttrInt( Attr_Man_t * p, int Id, int Attr ) { *Attr_ManFetchSpotInt( p, Id ) = Attr; } /**Function************************************************************* Synopsis [Sets the attribute of the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Attr_ManSetAttrPtr( Attr_Man_t * p, int Id, void * pAttr ) { assert( p->pManMem == NULL ); *Attr_ManFetchSpotPtr( p, Id ) = pAttr; } ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/aig/ivy/ivy.h000066400000000000000000001034341477524141600153230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivy.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivy.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__ivy__ivy_h #define ABC__aig__ivy__ivy_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include "misc/extra/extra.h" #include "misc/vec/vec.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Ivy_Man_t_ Ivy_Man_t; typedef struct Ivy_Obj_t_ Ivy_Obj_t; typedef int Ivy_Edge_t; typedef struct Ivy_FraigParams_t_ Ivy_FraigParams_t; // object types typedef enum { IVY_NONE, // 0: non-existent object IVY_PI, // 1: primary input (and constant 1 node) IVY_PO, // 2: primary output IVY_ASSERT, // 3: assertion IVY_LATCH, // 4: sequential element IVY_AND, // 5: AND node IVY_EXOR, // 6: EXOR node IVY_BUF, // 7: buffer (temporary) IVY_VOID // 8: unused object } Ivy_Type_t; // latch initial values typedef enum { IVY_INIT_NONE, // 0: not a latch IVY_INIT_0, // 1: zero IVY_INIT_1, // 2: one IVY_INIT_DC // 3: don't-care } Ivy_Init_t; // the AIG node struct Ivy_Obj_t_ // 24 bytes (32-bit) or 32 bytes (64-bit) // 10 words - 16 words { int Id; // integer ID int TravId; // traversal ID unsigned Type : 4; // object type unsigned fMarkA : 1; // multipurpose mask unsigned fMarkB : 1; // multipurpose mask unsigned fExFan : 1; // set to 1 if last fanout added is EXOR unsigned fPhase : 1; // value under 000...0 pattern unsigned fFailTfo : 1; // the TFO of the failed node unsigned Init : 2; // latch initial value unsigned Level : 21; // logic level int nRefs; // reference counter Ivy_Obj_t * pFanin0; // fanin Ivy_Obj_t * pFanin1; // fanin Ivy_Obj_t * pFanout; // fanout Ivy_Obj_t * pNextFan0; // next fanout of the first fanin Ivy_Obj_t * pNextFan1; // next fanout of the second fanin Ivy_Obj_t * pPrevFan0; // prev fanout of the first fanin Ivy_Obj_t * pPrevFan1; // prev fanout of the second fanin Ivy_Obj_t * pEquiv; // equivalent node }; // the AIG manager struct Ivy_Man_t_ { // AIG nodes Vec_Ptr_t * vPis; // the array of PIs Vec_Ptr_t * vPos; // the array of POs Vec_Ptr_t * vBufs; // the array of buffers Vec_Ptr_t * vObjs; // the array of objects Ivy_Obj_t * pConst1; // the constant 1 node Ivy_Obj_t Ghost; // the ghost node // AIG node counters int nObjs[IVY_VOID];// the number of objects by type int nCreated; // the number of created objects int nDeleted; // the number of deleted objects // stuctural hash table int * pTable; // structural hash table int nTableSize; // structural hash table size // various data members int fCatchExor; // set to 1 to detect EXORs int nTravIds; // the traversal ID int nLevelMax; // the maximum level Vec_Int_t * vRequired; // required times int fFanout; // fanout is allocated void * pData; // the temporary data void * pCopy; // the temporary data Ivy_Man_t * pHaig; // history AIG if present int nClassesSkip; // the number of skipped classes // memory management Vec_Ptr_t * vChunks; // allocated memory pieces Vec_Ptr_t * vPages; // memory pages used by nodes Ivy_Obj_t * pListFree; // the list of free nodes // timing statistics abctime time1; abctime time2; }; struct Ivy_FraigParams_t_ { int nSimWords; // the number of words in the simulation info double dSimSatur; // the ratio of refined classes when saturation is reached int fPatScores; // enables simulation pattern scoring int MaxScore; // max score after which resimulation is used double dActConeRatio; // the ratio of cone to be bumped double dActConeBumpMax; // the largest bump in activity int fProve; // prove the miter outputs int fVerbose; // verbose output int fDoSparse; // skip sparse functions int nBTLimitNode; // conflict limit at a node int nBTLimitMiter; // conflict limit at an output // int nBTLimitGlobal; // conflict limit global // int nInsLimitNode; // inspection limit at a node // int nInsLimitMiter; // inspection limit at an output // int nInsLimitGlobal; // inspection limit global }; #define IVY_CUT_LIMIT 256 #define IVY_CUT_INPUT 6 typedef struct Ivy_Cut_t_ Ivy_Cut_t; struct Ivy_Cut_t_ { int nLatches; short nSize; short nSizeMax; int pArray[IVY_CUT_INPUT]; unsigned uHash; }; typedef struct Ivy_Store_t_ Ivy_Store_t; struct Ivy_Store_t_ { int nCuts; int nCutsM; int nCutsMax; int fSatur; Ivy_Cut_t pCuts[IVY_CUT_LIMIT]; // storage for cuts }; #define IVY_LEAF_MASK 255 #define IVY_LEAF_BITS 8 //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define IVY_MIN(a,b) (((a) < (b))? (a) : (b)) #define IVY_MAX(a,b) (((a) > (b))? (a) : (b)) extern void Ivy_ManAddMemory( Ivy_Man_t * p ); static inline int Ivy_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } static inline int Ivy_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } static inline int Ivy_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } static inline void Ivy_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } static inline void Ivy_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } static inline Ivy_Obj_t * Ivy_Regular( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } static inline Ivy_Obj_t * Ivy_Not( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } static inline Ivy_Obj_t * Ivy_NotCond( Ivy_Obj_t * p, int c ) { return (Ivy_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } static inline int Ivy_IsComplement( Ivy_Obj_t * p ) { return (int)((ABC_PTRUINT_T)(p) & 01); } static inline Ivy_Obj_t * Ivy_ManConst0( Ivy_Man_t * p ) { return Ivy_Not(p->pConst1); } static inline Ivy_Obj_t * Ivy_ManConst1( Ivy_Man_t * p ) { return p->pConst1; } static inline Ivy_Obj_t * Ivy_ManGhost( Ivy_Man_t * p ) { return &p->Ghost; } static inline Ivy_Obj_t * Ivy_ManPi( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPis, i); } static inline Ivy_Obj_t * Ivy_ManPo( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPos, i); } static inline Ivy_Obj_t * Ivy_ManObj( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vObjs, i); } static inline Ivy_Edge_t Ivy_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } static inline int Ivy_EdgeId( Ivy_Edge_t Edge ) { return Edge >> 1; } static inline int Ivy_EdgeIsComplement( Ivy_Edge_t Edge ) { return Edge & 1; } static inline Ivy_Edge_t Ivy_EdgeRegular( Ivy_Edge_t Edge ) { return (Edge >> 1) << 1; } static inline Ivy_Edge_t Ivy_EdgeNot( Ivy_Edge_t Edge ) { return Edge ^ 1; } static inline Ivy_Edge_t Ivy_EdgeNotCond( Ivy_Edge_t Edge, int fCond ) { return Edge ^ fCond; } static inline Ivy_Edge_t Ivy_EdgeFromNode( Ivy_Obj_t * pNode ) { return Ivy_EdgeCreate( Ivy_Regular(pNode)->Id, Ivy_IsComplement(pNode) ); } static inline Ivy_Obj_t * Ivy_EdgeToNode( Ivy_Man_t * p, Ivy_Edge_t Edge ){ return Ivy_NotCond( Ivy_ManObj(p, Ivy_EdgeId(Edge)), Ivy_EdgeIsComplement(Edge) ); } static inline int Ivy_LeafCreate( int Id, int Lat ) { return (Id << IVY_LEAF_BITS) | Lat; } static inline int Ivy_LeafId( int Leaf ) { return Leaf >> IVY_LEAF_BITS; } static inline int Ivy_LeafLat( int Leaf ) { return Leaf & IVY_LEAF_MASK; } static inline int Ivy_ManPiNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PI]; } static inline int Ivy_ManPoNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PO]; } static inline int Ivy_ManAssertNum( Ivy_Man_t * p ) { return p->nObjs[IVY_ASSERT]; } static inline int Ivy_ManLatchNum( Ivy_Man_t * p ) { return p->nObjs[IVY_LATCH]; } static inline int Ivy_ManAndNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]; } static inline int Ivy_ManExorNum( Ivy_Man_t * p ) { return p->nObjs[IVY_EXOR]; } static inline int Ivy_ManBufNum( Ivy_Man_t * p ) { return p->nObjs[IVY_BUF]; } static inline int Ivy_ManObjNum( Ivy_Man_t * p ) { return p->nCreated - p->nDeleted; } static inline int Ivy_ManObjIdMax( Ivy_Man_t * p ) { return Vec_PtrSize(p->vObjs)-1; } static inline int Ivy_ManNodeNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR];} static inline int Ivy_ManHashObjNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR]+p->nObjs[IVY_LATCH]; } static inline int Ivy_ManGetCost( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+3*p->nObjs[IVY_EXOR]+8*p->nObjs[IVY_LATCH]; } static inline Ivy_Type_t Ivy_ObjType( Ivy_Obj_t * pObj ) { return (Ivy_Type_t)pObj->Type; } static inline Ivy_Init_t Ivy_ObjInit( Ivy_Obj_t * pObj ) { return (Ivy_Init_t)pObj->Init; } static inline int Ivy_ObjIsConst1( Ivy_Obj_t * pObj ) { return pObj->Id == 0; } static inline int Ivy_ObjIsGhost( Ivy_Obj_t * pObj ) { return pObj->Id < 0; } static inline int Ivy_ObjIsNone( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_NONE; } static inline int Ivy_ObjIsPi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI; } static inline int Ivy_ObjIsPo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO; } static inline int Ivy_ObjIsCi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_LATCH; } static inline int Ivy_ObjIsCo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_LATCH; } static inline int Ivy_ObjIsAssert( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_ASSERT; } static inline int Ivy_ObjIsLatch( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_LATCH; } static inline int Ivy_ObjIsAnd( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND; } static inline int Ivy_ObjIsExor( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_EXOR; } static inline int Ivy_ObjIsBuf( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_BUF; } static inline int Ivy_ObjIsNode( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR; } static inline int Ivy_ObjIsTerm( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT; } static inline int Ivy_ObjIsHash( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR || pObj->Type == IVY_LATCH; } static inline int Ivy_ObjIsOneFanin( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT || pObj->Type == IVY_BUF || pObj->Type == IVY_LATCH; } static inline int Ivy_ObjIsMarkA( Ivy_Obj_t * pObj ) { return pObj->fMarkA; } static inline void Ivy_ObjSetMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 1; } static inline void Ivy_ObjClearMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 0; } static inline void Ivy_ObjSetTravId( Ivy_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } static inline void Ivy_ObjSetTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } static inline void Ivy_ObjSetTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1; } static inline int Ivy_ObjIsTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds); } static inline int Ivy_ObjIsTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds - 1); } static inline int Ivy_ObjId( Ivy_Obj_t * pObj ) { return pObj->Id; } static inline int Ivy_ObjTravId( Ivy_Obj_t * pObj ) { return pObj->TravId; } static inline int Ivy_ObjPhase( Ivy_Obj_t * pObj ) { return pObj->fPhase; } static inline int Ivy_ObjExorFanout( Ivy_Obj_t * pObj ) { return pObj->fExFan; } static inline int Ivy_ObjRefs( Ivy_Obj_t * pObj ) { return pObj->nRefs; } static inline void Ivy_ObjRefsInc( Ivy_Obj_t * pObj ) { pObj->nRefs++; } static inline void Ivy_ObjRefsDec( Ivy_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } static inline int Ivy_ObjFaninId0( Ivy_Obj_t * pObj ) { return pObj->pFanin0? Ivy_ObjId(Ivy_Regular(pObj->pFanin0)) : 0; } static inline int Ivy_ObjFaninId1( Ivy_Obj_t * pObj ) { return pObj->pFanin1? Ivy_ObjId(Ivy_Regular(pObj->pFanin1)) : 0; } static inline int Ivy_ObjFaninC0( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin0); } static inline int Ivy_ObjFaninC1( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin1); } static inline Ivy_Obj_t * Ivy_ObjFanin0( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin0); } static inline Ivy_Obj_t * Ivy_ObjFanin1( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin1); } static inline Ivy_Obj_t * Ivy_ObjChild0( Ivy_Obj_t * pObj ) { return pObj->pFanin0; } static inline Ivy_Obj_t * Ivy_ObjChild1( Ivy_Obj_t * pObj ) { return pObj->pFanin1; } static inline Ivy_Obj_t * Ivy_ObjChild0Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin0(pObj)? Ivy_NotCond(Ivy_ObjFanin0(pObj)->pEquiv, Ivy_ObjFaninC0(pObj)) : NULL; } static inline Ivy_Obj_t * Ivy_ObjChild1Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin1(pObj)? Ivy_NotCond(Ivy_ObjFanin1(pObj)->pEquiv, Ivy_ObjFaninC1(pObj)) : NULL; } static inline Ivy_Obj_t * Ivy_ObjEquiv( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj)->pEquiv? Ivy_NotCond(Ivy_Regular(pObj)->pEquiv, Ivy_IsComplement(pObj)) : NULL; } static inline int Ivy_ObjLevel( Ivy_Obj_t * pObj ) { return pObj->Level; } static inline int Ivy_ObjLevelNew( Ivy_Obj_t * pObj ) { return 1 + Ivy_ObjIsExor(pObj) + IVY_MAX(Ivy_ObjFanin0(pObj)->Level, Ivy_ObjFanin1(pObj)->Level); } static inline int Ivy_ObjFaninPhase( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj)? !Ivy_Regular(pObj)->fPhase : pObj->fPhase; } static inline void Ivy_ObjClean( Ivy_Obj_t * pObj ) { int IdSaved = pObj->Id; memset( pObj, 0, sizeof(Ivy_Obj_t) ); pObj->Id = IdSaved; } static inline void Ivy_ObjOverwrite( Ivy_Obj_t * pBase, Ivy_Obj_t * pData ) { int IdSaved = pBase->Id; memcpy( pBase, pData, sizeof(Ivy_Obj_t) ); pBase->Id = IdSaved; } static inline int Ivy_ObjWhatFanin( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanin ) { if ( Ivy_ObjFanin0(pObj) == pFanin ) return 0; if ( Ivy_ObjFanin1(pObj) == pFanin ) return 1; assert(0); return -1; } static inline int Ivy_ObjFanoutC( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) { if ( Ivy_ObjFanin0(pFanout) == pObj ) return Ivy_ObjFaninC0(pObj); if ( Ivy_ObjFanin1(pFanout) == pObj ) return Ivy_ObjFaninC1(pObj); assert(0); return -1; } // create the ghost of the new node static inline Ivy_Obj_t * Ivy_ObjCreateGhost( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type, Ivy_Init_t Init ) { Ivy_Obj_t * pGhost, * pTemp; assert( Type != IVY_AND || !Ivy_ObjIsConst1(Ivy_Regular(p0)) ); assert( p1 == NULL || !Ivy_ObjIsConst1(Ivy_Regular(p1)) ); assert( Type == IVY_PI || Ivy_Regular(p0) != Ivy_Regular(p1) ); assert( Type != IVY_LATCH || !Ivy_IsComplement(p0) ); // assert( p1 == NULL || (!Ivy_ObjIsLatch(Ivy_Regular(p0)) || !Ivy_ObjIsLatch(Ivy_Regular(p1))) ); pGhost = Ivy_ManGhost(p); pGhost->Type = Type; pGhost->Init = Init; pGhost->pFanin0 = p0; pGhost->pFanin1 = p1; if ( p1 && Ivy_ObjFaninId0(pGhost) > Ivy_ObjFaninId1(pGhost) ) pTemp = pGhost->pFanin0, pGhost->pFanin0 = pGhost->pFanin1, pGhost->pFanin1 = pTemp; return pGhost; } // get the complemented initial state static Ivy_Init_t Ivy_InitNotCond( Ivy_Init_t Init, int fCompl ) { assert( Init != IVY_INIT_NONE ); if ( fCompl == 0 ) return Init; if ( Init == IVY_INIT_0 ) return IVY_INIT_1; if ( Init == IVY_INIT_1 ) return IVY_INIT_0; return IVY_INIT_DC; } // get the initial state after forward retiming over AND gate static Ivy_Init_t Ivy_InitAnd( Ivy_Init_t InitA, Ivy_Init_t InitB ) { assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE ); if ( InitA == IVY_INIT_0 || InitB == IVY_INIT_0 ) return IVY_INIT_0; if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC ) return IVY_INIT_DC; return IVY_INIT_1; } // get the initial state after forward retiming over EXOR gate static Ivy_Init_t Ivy_InitExor( Ivy_Init_t InitA, Ivy_Init_t InitB ) { assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE ); if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC ) return IVY_INIT_DC; if ( InitA == IVY_INIT_0 && InitB == IVY_INIT_1 ) return IVY_INIT_1; if ( InitA == IVY_INIT_1 && InitB == IVY_INIT_0 ) return IVY_INIT_1; return IVY_INIT_0; } // internal memory manager static inline Ivy_Obj_t * Ivy_ManFetchMemory( Ivy_Man_t * p ) { Ivy_Obj_t * pTemp; if ( p->pListFree == NULL ) Ivy_ManAddMemory( p ); pTemp = p->pListFree; p->pListFree = *((Ivy_Obj_t **)pTemp); memset( pTemp, 0, sizeof(Ivy_Obj_t) ); return pTemp; } static inline void Ivy_ManRecycleMemory( Ivy_Man_t * p, Ivy_Obj_t * pEntry ) { pEntry->Type = IVY_NONE; // distinquishes dead node from live node *((Ivy_Obj_t **)pEntry) = p->pListFree; p->pListFree = pEntry; } //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// // iterator over the primary inputs #define Ivy_ManForEachPi( p, pObj, i ) \ Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPis, pObj, i ) // iterator over the primary outputs #define Ivy_ManForEachPo( p, pObj, i ) \ Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPos, pObj, i ) // iterator over all objects, including those currently not used #define Ivy_ManForEachObj( p, pObj, i ) \ Vec_PtrForEachEntry( Ivy_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else // iterator over the combinational inputs #define Ivy_ManForEachCi( p, pObj, i ) \ Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCi(pObj) ) {} else // iterator over the combinational outputs #define Ivy_ManForEachCo( p, pObj, i ) \ Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCo(pObj) ) {} else // iterator over logic nodes (AND and EXOR gates) #define Ivy_ManForEachNode( p, pObj, i ) \ Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsNode(pObj) ) {} else // iterator over logic latches #define Ivy_ManForEachLatch( p, pObj, i ) \ Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsLatch(pObj) ) {} else // iterator over the nodes whose IDs are stored in the array #define Ivy_ManForEachNodeVec( p, vIds, pObj, i ) \ for ( i = 0; i < Vec_IntSize(vIds) && ((pObj) = Ivy_ManObj(p, Vec_IntEntry(vIds,i))); i++ ) // iterator over the fanouts of an object #define Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, i ) \ for ( i = 0, Ivy_ObjCollectFanouts(p, pObj, vArray); \ i < Vec_PtrSize(vArray) && ((pFanout) = (Ivy_Obj_t *)Vec_PtrEntry(vArray,i)); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== ivyBalance.c ========================================================*/ extern Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel ); extern Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel ); /*=== ivyCanon.c ========================================================*/ extern Ivy_Obj_t * Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); extern Ivy_Obj_t * Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); extern Ivy_Obj_t * Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ); /*=== ivyCheck.c ========================================================*/ extern int Ivy_ManCheck( Ivy_Man_t * p ); extern int Ivy_ManCheckFanoutNums( Ivy_Man_t * p ); extern int Ivy_ManCheckFanouts( Ivy_Man_t * p ); extern int Ivy_ManCheckChoices( Ivy_Man_t * p ); /*=== ivyCut.c ==========================================================*/ extern void Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize ); extern Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ); /*=== ivyDfs.c ==========================================================*/ extern Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p ); extern Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches ); extern void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ); extern Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p ); extern Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p ); extern int Ivy_ManIsAcyclic( Ivy_Man_t * p ); extern int Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig ); /*=== ivyDsd.c ==========================================================*/ extern int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree ); extern void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree ); extern unsigned Ivy_TruthDsdCompute( Vec_Int_t * vTree ); extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); extern Ivy_Obj_t * Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree ); /*=== ivyFanout.c ==========================================================*/ extern void Ivy_ManStartFanout( Ivy_Man_t * p ); extern void Ivy_ManStopFanout( Ivy_Man_t * p ); extern void Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ); extern void Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ); extern void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew ); extern void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray ); extern Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj ); extern int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj ); /*=== ivyFastMap.c =============================================================*/ extern void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose ); extern void Ivy_FastMapStop( Ivy_Man_t * pAig ); extern void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves ); extern void Ivy_FastMapReverseLevel( Ivy_Man_t * pAig ); /*=== ivyFraig.c ==========================================================*/ extern int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars ); extern Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); extern Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); extern void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams ); /*=== ivyHaig.c ==========================================================*/ extern void Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose ); extern void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew ); extern void Ivy_ManHaigStop( Ivy_Man_t * p ); extern void Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose ); extern void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj ); extern void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew ); extern void Ivy_ManHaigSimulate( Ivy_Man_t * p ); /*=== ivyMan.c ==========================================================*/ extern Ivy_Man_t * Ivy_ManStart(); extern Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p ); extern Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p ); extern Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping ); extern void Ivy_ManStop( Ivy_Man_t * p ); extern int Ivy_ManCleanup( Ivy_Man_t * p ); extern int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel ); extern void Ivy_ManPrintStats( Ivy_Man_t * p ); extern void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits ); /*=== ivyMem.c ==========================================================*/ extern void Ivy_ManStartMemory( Ivy_Man_t * p ); extern void Ivy_ManStopMemory( Ivy_Man_t * p ); /*=== ivyMulti.c ==========================================================*/ extern Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); extern Ivy_Obj_t * Ivy_Multi1( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); extern Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ); extern Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); extern int Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSol ); /*=== ivyObj.c ==========================================================*/ extern Ivy_Obj_t * Ivy_ObjCreatePi( Ivy_Man_t * p ); extern Ivy_Obj_t * Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver ); extern Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost ); extern void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 ); extern void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj ); extern void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew ); extern void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ); extern void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ); extern void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel ); extern void Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel ); /*=== ivyOper.c =========================================================*/ extern Ivy_Obj_t * Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type ); extern Ivy_Obj_t * Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); extern Ivy_Obj_t * Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); extern Ivy_Obj_t * Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); extern Ivy_Obj_t * Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 ); extern Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC ); extern Ivy_Obj_t * Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs ); extern Ivy_Obj_t * Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ); /*=== ivyResyn.c =========================================================*/ extern Ivy_Man_t * Ivy_ManResyn0( Ivy_Man_t * p, int fUpdateLevel, int fVerbose ); extern Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * p, int fUpdateLevel, int fVerbose ); extern Ivy_Man_t * Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose ); /*=== ivyRewrite.c =========================================================*/ extern int Ivy_ManSeqRewrite( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ); extern int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ); extern int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose ); /*=== ivySeq.c =========================================================*/ extern int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose ); /*=== ivyShow.c =========================================================*/ extern void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ); /*=== ivyTable.c ========================================================*/ extern Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj ); extern void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj ); extern void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj ); extern void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew ); extern int Ivy_TableCountEntries( Ivy_Man_t * p ); extern void Ivy_TableProfile( Ivy_Man_t * p ); /*=== ivyUtil.c =========================================================*/ extern void Ivy_ManIncrementTravId( Ivy_Man_t * p ); extern void Ivy_ManCleanTravId( Ivy_Man_t * p ); extern unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth ); extern void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ); extern Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p ); extern int Ivy_ManLevels( Ivy_Man_t * p ); extern void Ivy_ManResetLevels( Ivy_Man_t * p ); extern int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pObj ); extern void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ); extern void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew ); extern int Ivy_ObjIsMuxType( Ivy_Obj_t * pObj ); extern Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pObj, Ivy_Obj_t ** ppObjT, Ivy_Obj_t ** ppObjE ); extern Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj ); extern void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig ); extern void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig ); extern int Ivy_CutTruthPrint( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/aig/ivy/ivyBalance.c000066400000000000000000000342311477524141600165620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyBalance.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Algebraic AIG balancing.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel ); static Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level ); static int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ); static void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ); static void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs algebraic balancing of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel ) { Ivy_Man_t * pNew; Ivy_Obj_t * pObj, * pDriver; Vec_Vec_t * vStore; int i, NewNodeId; // clean the old manager Ivy_ManCleanTravId( p ); // create the new manager pNew = Ivy_ManStart(); // map the nodes Ivy_ManConst1(p)->TravId = Ivy_EdgeFromNode( Ivy_ManConst1(pNew) ); Ivy_ManForEachPi( p, pObj, i ) pObj->TravId = Ivy_EdgeFromNode( Ivy_ObjCreatePi(pNew) ); // if HAIG is defined, trasfer the pointers to the PIs/latches // if ( p->pHaig ) // Ivy_ManHaigTrasfer( p, pNew ); // balance the AIG vStore = Vec_VecAlloc( 50 ); Ivy_ManForEachPo( p, pObj, i ) { pDriver = Ivy_ObjReal( Ivy_ObjChild0(pObj) ); NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(pDriver), vStore, 0, fUpdateLevel ); NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(pDriver) ); Ivy_ObjCreatePo( pNew, Ivy_EdgeToNode(pNew, NewNodeId) ); } Vec_VecFree( vStore ); if ( (i = Ivy_ManCleanup( pNew )) ) { // printf( "Cleanup after balancing removed %d dangling nodes.\n", i ); } // check the resulting AIG if ( !Ivy_ManCheck(pNew) ) printf( "Ivy_ManBalance(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_NodeCompareLevelsDecrease( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 ) { int Diff = Ivy_Regular(*pp1)->Level - Ivy_Regular(*pp2)->Level; if ( Diff > 0 ) return -1; if ( Diff < 0 ) return 1; Diff = Ivy_Regular(*pp1)->Id - Ivy_Regular(*pp2)->Id; if ( Diff > 0 ) return -1; if ( Diff < 0 ) return 1; return 0; } /**Function************************************************************* Synopsis [Returns the ID of new node constructed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) { Ivy_Obj_t * pObjNew; Vec_Ptr_t * vSuper; int i, NewNodeId; assert( !Ivy_IsComplement(pObjOld) ); assert( !Ivy_ObjIsBuf(pObjOld) ); // return if the result is known if ( Ivy_ObjIsConst1(pObjOld) ) return pObjOld->TravId; if ( pObjOld->TravId ) return pObjOld->TravId; assert( Ivy_ObjIsNode(pObjOld) ); // get the implication supergate vSuper = Ivy_NodeBalanceCone( pObjOld, vStore, Level ); if ( vSuper->nSize == 0 ) { // it means that the supergate contains two nodes in the opposite polarity pObjOld->TravId = Ivy_EdgeFromNode( Ivy_ManConst0(pNew) ); return pObjOld->TravId; } if ( vSuper->nSize < 2 ) printf( "BUG!\n" ); // for each old node, derive the new well-balanced node for ( i = 0; i < vSuper->nSize; i++ ) { NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular((Ivy_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement((Ivy_Obj_t *)vSuper->pArray[i]) ); vSuper->pArray[i] = Ivy_EdgeToNode( pNew, NewNodeId ); } // build the supergate pObjNew = Ivy_NodeBalanceBuildSuper( pNew, vSuper, Ivy_ObjType(pObjOld), fUpdateLevel ); vSuper->nSize = 0; // make sure the balanced node is not assigned assert( pObjOld->TravId == 0 ); pObjOld->TravId = Ivy_EdgeFromNode( pObjNew ); // assert( pObjOld->Level >= Ivy_Regular(pObjNew)->Level ); return pObjOld->TravId; } /**Function************************************************************* Synopsis [Builds implication supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel ) { Ivy_Obj_t * pObj1, * pObj2; int LeftBound; assert( vSuper->nSize > 1 ); // sort the new nodes by level in the decreasing order Vec_PtrSort( vSuper, (int (*)(const void *, const void *))Ivy_NodeCompareLevelsDecrease ); // balance the nodes while ( vSuper->nSize > 1 ) { // find the left bound on the node to be paired LeftBound = (!fUpdateLevel)? 0 : Ivy_NodeBalanceFindLeft( vSuper ); // find the node that can be shared (if no such node, randomize choice) Ivy_NodeBalancePermute( p, vSuper, LeftBound, Type == IVY_EXOR ); // pull out the last two nodes pObj1 = (Ivy_Obj_t *)Vec_PtrPop(vSuper); pObj2 = (Ivy_Obj_t *)Vec_PtrPop(vSuper); Ivy_NodeBalancePushUniqueOrderByLevel( vSuper, Ivy_Oper(p, pObj1, pObj2, Type) ); } return (Ivy_Obj_t *)Vec_PtrEntry(vSuper, 0); } /**Function************************************************************* Synopsis [Collects the nodes of the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_NodeBalanceCone_rec( Ivy_Obj_t * pRoot, Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper ) { int RetValue1, RetValue2, i; // check if the node is visited if ( Ivy_Regular(pObj)->fMarkB ) { // check if the node occurs in the same polarity for ( i = 0; i < vSuper->nSize; i++ ) if ( vSuper->pArray[i] == pObj ) return 1; // check if the node is present in the opposite polarity for ( i = 0; i < vSuper->nSize; i++ ) if ( vSuper->pArray[i] == Ivy_Not(pObj) ) return -1; assert( 0 ); return 0; } // if the new node is complemented or a PI, another gate begins if ( pObj != pRoot && (Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Ivy_ObjType(pRoot) || Ivy_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) ) { Vec_PtrPush( vSuper, pObj ); Ivy_Regular(pObj)->fMarkB = 1; return 0; } assert( !Ivy_IsComplement(pObj) ); assert( Ivy_ObjIsNode(pObj) ); // go through the branches RetValue1 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild0(pObj) ), vSuper ); RetValue2 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild1(pObj) ), vSuper ); if ( RetValue1 == -1 || RetValue2 == -1 ) return -1; // return 1 if at least one branch has a duplicate return RetValue1 || RetValue2; } /**Function************************************************************* Synopsis [Collects the nodes of the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) { Vec_Ptr_t * vNodes; int RetValue, i; assert( !Ivy_IsComplement(pObj) ); // extend the storage if ( Vec_VecSize( vStore ) <= Level ) Vec_VecPush( vStore, Level, 0 ); // get the temporary array of nodes vNodes = Vec_VecEntry( vStore, Level ); Vec_PtrClear( vNodes ); // collect the nodes in the implication supergate RetValue = Ivy_NodeBalanceCone_rec( pObj, pObj, vNodes ); assert( vNodes->nSize > 1 ); // unmark the visited nodes Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, i ) Ivy_Regular(pObj)->fMarkB = 0; // if we found the node and its complement in the same implication supergate, // return empty set of nodes (meaning that we should use constant-0 node) if ( RetValue == -1 ) vNodes->nSize = 0; return vNodes; } /**Function************************************************************* Synopsis [Finds the left bound on the next candidate to be paired.] Description [The nodes in the array are in the decreasing order of levels. The last node in the array has the smallest level. By default it would be paired with the next node on the left. However, it may be possible to pair it with some other node on the left, in such a way that the new node is shared. This procedure finds the index of the left-most node, which can be paired with the last node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) { Ivy_Obj_t * pObjRight, * pObjLeft; int Current; // if two or less nodes, pair with the first if ( Vec_PtrSize(vSuper) < 3 ) return 0; // set the pointer to the one before the last Current = Vec_PtrSize(vSuper) - 2; pObjRight = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, Current ); // go through the nodes to the left of this one for ( Current--; Current >= 0; Current-- ) { // get the next node on the left pObjLeft = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, Current ); // if the level of this node is different, quit the loop if ( Ivy_Regular(pObjLeft)->Level != Ivy_Regular(pObjRight)->Level ) break; } Current++; // get the node, for which the equality holds pObjLeft = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, Current ); assert( Ivy_Regular(pObjLeft)->Level == Ivy_Regular(pObjRight)->Level ); return Current; } /**Function************************************************************* Synopsis [Moves closer to the end the node that is best for sharing.] Description [If there is no node with sharing, randomly chooses one of the legal nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) { Ivy_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; int RightBound, i; // get the right bound RightBound = Vec_PtrSize(vSuper) - 2; assert( LeftBound <= RightBound ); if ( LeftBound == RightBound ) return; // get the two last nodes pObj1 = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 ); pObj2 = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, RightBound ); if ( Ivy_Regular(pObj1) == p->pConst1 || Ivy_Regular(pObj2) == p->pConst1 ) return; // find the first node that can be shared for ( i = RightBound; i >= LeftBound; i-- ) { pObj3 = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, i ); if ( Ivy_Regular(pObj3) == p->pConst1 ) { Vec_PtrWriteEntry( vSuper, i, pObj2 ); Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); return; } pGhost = Ivy_ObjCreateGhost( p, pObj1, pObj3, fExor? IVY_EXOR : IVY_AND, IVY_INIT_NONE ); if ( Ivy_TableLookup( p, pGhost ) ) { if ( pObj3 == pObj2 ) return; Vec_PtrWriteEntry( vSuper, i, pObj2 ); Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); return; } } /* // we did not find the node to share, randomize choice { int Choice = rand() % (RightBound - LeftBound + 1); pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); if ( pObj3 == pObj2 ) return; Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); } */ } /**Function************************************************************* Synopsis [Inserts a new node in the order by levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj ) { Ivy_Obj_t * pObj1, * pObj2; int i; if ( Vec_PtrPushUnique(vStore, pObj) ) return; // find the p of the node for ( i = vStore->nSize-1; i > 0; i-- ) { pObj1 = (Ivy_Obj_t *)vStore->pArray[i ]; pObj2 = (Ivy_Obj_t *)vStore->pArray[i-1]; if ( Ivy_Regular(pObj1)->Level <= Ivy_Regular(pObj2)->Level ) break; vStore->pArray[i ] = pObj2; vStore->pArray[i-1] = pObj1; } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyCanon.c000066400000000000000000000115461477524141600162770ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyCanon.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Finding canonical form of objects.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyCanon.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static Ivy_Obj_t * Ivy_TableLookupPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1, int fCompl0, int fCompl1, Ivy_Type_t Type ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates the canonical form of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_CanonPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pGhost ) { Ivy_Obj_t * pResult, * pLat0, * pLat1; Ivy_Init_t Init, Init0, Init1; int fCompl0, fCompl1; Ivy_Type_t Type; assert( Ivy_ObjIsNode(pGhost) ); assert( Ivy_ObjIsAnd(pGhost) || (!Ivy_ObjFaninC0(pGhost) && !Ivy_ObjFaninC1(pGhost)) ); assert( Ivy_ObjFaninId0(pGhost) != 0 && Ivy_ObjFaninId1(pGhost) != 0 ); // consider the case when the pair is canonical if ( !Ivy_ObjIsLatch(Ivy_ObjFanin0(pGhost)) || !Ivy_ObjIsLatch(Ivy_ObjFanin1(pGhost)) ) { if ( (pResult = Ivy_TableLookup( p, pGhost )) ) return pResult; return Ivy_ObjCreate( p, pGhost ); } /// remember the latches pLat0 = Ivy_ObjFanin0(pGhost); pLat1 = Ivy_ObjFanin1(pGhost); // remember type and compls Type = Ivy_ObjType(pGhost); fCompl0 = Ivy_ObjFaninC0(pGhost); fCompl1 = Ivy_ObjFaninC1(pGhost); // call recursively pResult = Ivy_Oper( p, Ivy_NotCond(Ivy_ObjFanin0(pLat0), fCompl0), Ivy_NotCond(Ivy_ObjFanin0(pLat1), fCompl1), Type ); // build latch on top of this Init0 = Ivy_InitNotCond( Ivy_ObjInit(pLat0), fCompl0 ); Init1 = Ivy_InitNotCond( Ivy_ObjInit(pLat1), fCompl1 ); Init = (Type == IVY_AND)? Ivy_InitAnd(Init0, Init1) : Ivy_InitExor(Init0, Init1); return Ivy_Latch( p, pResult, Init ); } /**Function************************************************************* Synopsis [Creates the canonical form of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) { Ivy_Obj_t * pGhost, * pResult; pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_AND, IVY_INIT_NONE ); pResult = Ivy_CanonPair_rec( p, pGhost ); return pResult; } /**Function************************************************************* Synopsis [Creates the canonical form of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) { Ivy_Obj_t * pGhost, * pResult; int fCompl = Ivy_IsComplement(pObj0) ^ Ivy_IsComplement(pObj1); pObj0 = Ivy_Regular(pObj0); pObj1 = Ivy_Regular(pObj1); pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_EXOR, IVY_INIT_NONE ); pResult = Ivy_CanonPair_rec( p, pGhost ); return Ivy_NotCond( pResult, fCompl ); } /**Function************************************************************* Synopsis [Creates the canonical form of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ) { Ivy_Obj_t * pGhost, * pResult; int fCompl = Ivy_IsComplement(pObj); pObj = Ivy_Regular(pObj); pGhost = Ivy_ObjCreateGhost( p, pObj, NULL, IVY_LATCH, Ivy_InitNotCond(Init, fCompl) ); pResult = Ivy_TableLookup( p, pGhost ); if ( pResult == NULL ) pResult = Ivy_ObjCreate( p, pGhost ); return Ivy_NotCond( pResult, fCompl ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyCheck.c000066400000000000000000000224741477524141600162600ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyCheck.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [AIG checking procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks the consistency of the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManCheck( Ivy_Man_t * p ) { Ivy_Obj_t * pObj, * pObj2; int i; Ivy_ManForEachObj( p, pObj, i ) { // skip deleted nodes if ( Ivy_ObjId(pObj) != i ) { printf( "Ivy_ManCheck: Node with ID %d is listed as number %d in the array of objects.\n", pObj->Id, i ); return 0; } // consider the constant node and PIs if ( i == 0 || Ivy_ObjIsPi(pObj) ) { if ( Ivy_ObjFaninId0(pObj) || Ivy_ObjFaninId1(pObj) || Ivy_ObjLevel(pObj) ) { printf( "Ivy_ManCheck: The AIG has non-standard constant or PI node with ID \"%d\".\n", pObj->Id ); return 0; } continue; } if ( Ivy_ObjIsPo(pObj) ) { if ( Ivy_ObjFaninId1(pObj) ) { printf( "Ivy_ManCheck: The AIG has non-standard PO node with ID \"%d\".\n", pObj->Id ); return 0; } continue; } if ( Ivy_ObjIsBuf(pObj) ) { if ( Ivy_ObjFanin1(pObj) ) { printf( "Ivy_ManCheck: The buffer with ID \"%d\" contains second fanin.\n", pObj->Id ); return 0; } continue; } if ( Ivy_ObjIsLatch(pObj) ) { if ( Ivy_ObjFanin1(pObj) ) { printf( "Ivy_ManCheck: The latch with ID \"%d\" contains second fanin.\n", pObj->Id ); return 0; } if ( Ivy_ObjInit(pObj) == IVY_INIT_NONE ) { printf( "Ivy_ManCheck: The latch with ID \"%d\" does not have initial state.\n", pObj->Id ); return 0; } 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; } // consider the AND node if ( !Ivy_ObjFanin0(pObj) || !Ivy_ObjFanin1(pObj) ) { printf( "Ivy_ManCheck: The AIG has internal node \"%d\" with a NULL fanin.\n", pObj->Id ); return 0; } if ( Ivy_ObjFaninId0(pObj) >= Ivy_ObjFaninId1(pObj) ) { printf( "Ivy_ManCheck: The AIG has node \"%d\" with a wrong ordering of fanins.\n", pObj->Id ); return 0; } if ( Ivy_ObjLevel(pObj) != Ivy_ObjLevelNew(pObj) ) printf( "Ivy_ManCheck: Node with ID \"%d\" has level %d but should have level %d.\n", pObj->Id, Ivy_ObjLevel(pObj), Ivy_ObjLevelNew(pObj) ); pObj2 = Ivy_TableLookup( p, pObj ); if ( pObj2 != pObj ) printf( "Ivy_ManCheck: Node with ID \"%d\" is not in the structural hashing table.\n", pObj->Id ); if ( Ivy_ObjRefs(pObj) == 0 ) printf( "Ivy_ManCheck: Node with ID \"%d\" has no fanouts.\n", pObj->Id ); // check fanouts if ( p->fFanout && Ivy_ObjRefs(pObj) != Ivy_ObjFanoutNum(p, pObj) ) printf( "Ivy_ManCheck: Node with ID \"%d\" has mismatch between the number of fanouts and refs.\n", pObj->Id ); } // count the number of nodes in the table if ( Ivy_TableCountEntries(p) != Ivy_ManAndNum(p) + Ivy_ManExorNum(p) + Ivy_ManLatchNum(p) ) { printf( "Ivy_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); return 0; } // if ( !Ivy_ManCheckFanouts(p) ) // return 0; if ( !Ivy_ManIsAcyclic(p) ) return 0; return 1; } /**Function************************************************************* Synopsis [Verifies the fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManCheckFanoutNums( Ivy_Man_t * p ) { Ivy_Obj_t * pObj; int i, Counter = 0; Ivy_ManForEachObj( p, pObj, i ) if ( Ivy_ObjIsNode(pObj) ) Counter += (Ivy_ObjRefs(pObj) == 0); if ( Counter ) printf( "Sequential AIG has %d dangling nodes.\n", Counter ); return Counter; } /**Function************************************************************* Synopsis [Verifies the fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManCheckFanouts( Ivy_Man_t * p ) { Vec_Ptr_t * vFanouts; Ivy_Obj_t * pObj, * pFanout, * pFanin; int i, k, RetValue = 1; if ( !p->fFanout ) return 1; vFanouts = Vec_PtrAlloc( 100 ); // make sure every fanin is a fanout Ivy_ManForEachObj( p, pObj, i ) { pFanin = Ivy_ObjFanin0(pObj); if ( pFanin == NULL ) continue; Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k ) if ( pFanout == pObj ) break; if ( k == Vec_PtrSize(vFanouts) ) { printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id ); RetValue = 0; } pFanin = Ivy_ObjFanin1(pObj); if ( pFanin == NULL ) continue; Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k ) if ( pFanout == pObj ) break; if ( k == Vec_PtrSize(vFanouts) ) { printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id ); RetValue = 0; } // check that the previous fanout has the same fanin if ( pObj->pPrevFan0 ) { if ( Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) && Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) && Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) && Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) ) { printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan0->Id ); RetValue = 0; } } // check that the previous fanout has the same fanin if ( pObj->pPrevFan1 ) { if ( Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) && Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) && Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) && Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) ) { printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan1->Id ); RetValue = 0; } } } // make sure every fanout is a fanin Ivy_ManForEachObj( p, pObj, i ) { Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, k ) if ( Ivy_ObjFanin0(pFanout) != pObj && Ivy_ObjFanin1(pFanout) != pObj ) { printf( "Node %d is a fanout of node %d but the fanin is not there.\n", pFanout->Id, pObj->Id ); RetValue = 0; } } Vec_PtrFree( vFanouts ); return RetValue; } /**Function************************************************************* Synopsis [Checks that each choice node has exactly one node with fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManCheckChoices( Ivy_Man_t * p ) { Ivy_Obj_t * pObj, * pTemp; int i; Ivy_ManForEachObj( p->pHaig, pObj, i ) { if ( Ivy_ObjRefs(pObj) == 0 ) continue; // count the number of nodes in the loop assert( !Ivy_IsComplement(pObj->pEquiv) ); for ( pTemp = pObj->pEquiv; pTemp && pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) if ( Ivy_ObjRefs(pTemp) > 1 ) printf( "Node %d has member %d in its equiv class with %d fanouts.\n", pObj->Id, pTemp->Id, Ivy_ObjRefs(pTemp) ); } return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyCut.c000066400000000000000000000717641477524141600160040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyCut.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Computes reconvergence driven sequential cut.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyCut.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline int Ivy_NodeCutHashValue( int NodeId ) { return 1 << (NodeId % 31); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Evaluate the cost of removing the node from the set of leaves.] Description [Returns the number of new leaves that will be brought in. Returns large number if the node cannot be removed from the set of leaves.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ivy_NodeGetLeafCostOne( Ivy_Man_t * p, int Leaf, Vec_Int_t * vInside ) { Ivy_Obj_t * pNode; int nLatches, FaninLeaf, Cost; // make sure leaf is not a contant node assert( Leaf > 0 ); // get the node pNode = Ivy_ManObj( p, Ivy_LeafId(Leaf) ); // cannot expand over the PI node if ( Ivy_ObjIsPi(pNode) || Ivy_ObjIsConst1(pNode) ) return 999; // get the number of latches nLatches = Ivy_LeafLat(Leaf) + Ivy_ObjIsLatch(pNode); if ( nLatches > 15 ) return 999; // get the first fanin FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches ); Cost = FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1); // quit if this is the one fanin node if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) return Cost; assert( Ivy_ObjIsNode(pNode) ); // get the second fanin FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches ); Cost += FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1); return Cost; } /**Function************************************************************* Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] Description [This procedure looks at the current leaves and tries to change one leaf at a time in such a way that the cut grows as little as possible. In evaluating the fanins, this procedure looks only at their immediate predecessors (this is why it is called a one-level construction procedure).] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManSeqFindCut_int( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSizeLimit ) { Ivy_Obj_t * pNode; int CostBest, CostCur, Leaf, LeafBest, Next, nLatches, i; int LeavesBest[10]; int Counter; // add random selection of the best fanin!!! // find the best fanin CostBest = 99; LeafBest = -1; Counter = -1; //printf( "Evaluating fanins of the cut:\n" ); Vec_IntForEachEntry( vFront, Leaf, i ) { CostCur = Ivy_NodeGetLeafCostOne( p, Leaf, vInside ); //printf( " Fanin %s has cost %d.\n", Ivy_ObjName(pNode), CostCur ); if ( CostBest > CostCur ) { CostBest = CostCur; LeafBest = Leaf; LeavesBest[0] = Leaf; Counter = 1; } else if ( CostBest == CostCur ) LeavesBest[Counter++] = Leaf; if ( CostBest <= 1 ) // can be if ( CostBest <= 1 ) break; } if ( CostBest == 99 ) return 0; // return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit ); assert( CostBest < 3 ); if ( Vec_IntSize(vFront) - 1 + CostBest > nSizeLimit ) return 0; // return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit ); assert( Counter > 0 ); printf( "%d", Counter ); LeafBest = LeavesBest[rand() % Counter]; // remove the node from the array assert( LeafBest >= 0 ); Vec_IntRemove( vFront, LeafBest ); //printf( "Removing fanin %s.\n", Ivy_ObjName(pNode) ); // get the node and its latches pNode = Ivy_ManObj( p, Ivy_LeafId(LeafBest) ); nLatches = Ivy_LeafLat(LeafBest) + Ivy_ObjIsLatch(pNode); assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ); // add the left child to the fanins Next = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches ); if ( Next && Vec_IntFind(vInside, Next) == -1 ) { //printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) ); Vec_IntPush( vFront, Next ); Vec_IntPush( vInside, Next ); } // quit if this is the one fanin node if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) return 1; assert( Ivy_ObjIsNode(pNode) ); // add the right child to the fanins Next = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches ); if ( Next && Vec_IntFind(vInside, Next) == -1 ) { //printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) ); Vec_IntPush( vFront, Next ); Vec_IntPush( vInside, Next ); } assert( Vec_IntSize(vFront) <= nSizeLimit ); // keep doing this return 1; } /**Function************************************************************* Synopsis [Computes one sequential cut of the given size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize ) { assert( !Ivy_IsComplement(pRoot) ); assert( Ivy_ObjIsNode(pRoot) ); assert( Ivy_ObjFaninId0(pRoot) ); assert( Ivy_ObjFaninId1(pRoot) ); // start the cut Vec_IntClear( vFront ); Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) ); Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) ); // start the visited nodes Vec_IntClear( vInside ); Vec_IntPush( vInside, Ivy_LeafCreate(pRoot->Id, 0) ); Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) ); Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) ); // compute the cut while ( Ivy_ManSeqFindCut_int( p, vFront, vInside, nSize ) ); assert( Vec_IntSize(vFront) <= nSize ); } /**Function************************************************************* Synopsis [Computing Boolean cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManFindBoolCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume, Ivy_Obj_t * pPivot ) { int RetValue0, RetValue1; if ( pObj == pPivot ) { Vec_PtrPushUnique( vLeaves, pObj ); Vec_PtrPushUnique( vVolume, pObj ); return 1; } if ( pObj->fMarkA ) return 0; // assert( !Ivy_ObjIsCi(pObj) ); if ( Ivy_ObjIsCi(pObj) ) return 0; if ( Ivy_ObjIsBuf(pObj) ) { RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot ); if ( !RetValue0 ) return 0; Vec_PtrPushUnique( vVolume, pObj ); return 1; } assert( Ivy_ObjIsNode(pObj) ); RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot ); RetValue1 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin1(pObj), vLeaves, vVolume, pPivot ); if ( !RetValue0 && !RetValue1 ) return 0; // add new leaves if ( !RetValue0 ) { Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin0(pObj) ); Vec_PtrPushUnique( vVolume, Ivy_ObjFanin0(pObj) ); } if ( !RetValue1 ) { Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin1(pObj) ); Vec_PtrPushUnique( vVolume, Ivy_ObjFanin1(pObj) ); } Vec_PtrPushUnique( vVolume, pObj ); return 1; } /**Function************************************************************* Synopsis [Returns the cost of one node (how many new nodes are added.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManFindBoolCutCost( Ivy_Obj_t * pObj ) { int Cost; // make sure the node is in the construction zone assert( pObj->fMarkA == 1 ); // cannot expand over the PI node if ( Ivy_ObjIsCi(pObj) ) return 999; // always expand over the buffer if ( Ivy_ObjIsBuf(pObj) ) return !Ivy_ObjFanin0(pObj)->fMarkA; // get the cost of the cone Cost = (!Ivy_ObjFanin0(pObj)->fMarkA) + (!Ivy_ObjFanin1(pObj)->fMarkA); // return the number of nodes to be added to the leaves if this node is removed return Cost; } /**Function************************************************************* Synopsis [Computing Boolean cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManFindBoolCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVolume, Vec_Ptr_t * vLeaves ) { Ivy_Obj_t * pObj = NULL; // Suppress "might be used uninitialized" Ivy_Obj_t * pFaninC, * pFanin0, * pFanin1, * pPivot; int RetValue, LevelLimit, Lev, k; assert( !Ivy_IsComplement(pRoot) ); // clear the frontier and collect the nodes Vec_PtrClear( vFront ); Vec_PtrClear( vVolume ); if ( Ivy_ObjIsMuxType(pRoot) ) pFaninC = Ivy_ObjRecognizeMux( pRoot, &pFanin0, &pFanin1 ); else { pFaninC = NULL; pFanin0 = Ivy_ObjFanin0(pRoot); pFanin1 = Ivy_ObjFanin1(pRoot); } // start cone A pFanin0->fMarkA = 1; Vec_PtrPush( vFront, pFanin0 ); Vec_PtrPush( vVolume, pFanin0 ); // start cone B pFanin1->fMarkB = 1; Vec_PtrPush( vFront, pFanin1 ); Vec_PtrPush( vVolume, pFanin1 ); // iteratively expand until the common node (pPivot) is found or limit is reached assert( Ivy_ObjLevel(pRoot) == Ivy_ObjLevelNew(pRoot) ); pPivot = NULL; LevelLimit = IVY_MAX( Ivy_ObjLevel(pRoot) - 10, 1 ); for ( Lev = Ivy_ObjLevel(pRoot) - 1; Lev >= LevelLimit; Lev-- ) { while ( 1 ) { // find the next node to expand on this level Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, k ) if ( (int)pObj->Level == Lev ) break; if ( k == Vec_PtrSize(vFront) ) break; assert( (int)pObj->Level <= Lev ); assert( pObj->fMarkA ^ pObj->fMarkB ); // remove the old node Vec_PtrRemove( vFront, pObj ); // expand this node pFanin0 = Ivy_ObjFanin0(pObj); if ( !pFanin0->fMarkA && !pFanin0->fMarkB ) { Vec_PtrPush( vFront, pFanin0 ); Vec_PtrPush( vVolume, pFanin0 ); } // mark the new nodes if ( pObj->fMarkA ) pFanin0->fMarkA = 1; if ( pObj->fMarkB ) pFanin0->fMarkB = 1; if ( Ivy_ObjIsBuf(pObj) ) { if ( pFanin0->fMarkA && pFanin0->fMarkB ) { pPivot = pFanin0; break; } continue; } // expand this node pFanin1 = Ivy_ObjFanin1(pObj); if ( !pFanin1->fMarkA && !pFanin1->fMarkB ) { Vec_PtrPush( vFront, pFanin1 ); Vec_PtrPush( vVolume, pFanin1 ); } // mark the new nodes if ( pObj->fMarkA ) pFanin1->fMarkA = 1; if ( pObj->fMarkB ) pFanin1->fMarkB = 1; // consider if it is time to quit if ( pFanin0->fMarkA && pFanin0->fMarkB ) { pPivot = pFanin0; break; } if ( pFanin1->fMarkA && pFanin1->fMarkB ) { pPivot = pFanin1; break; } } if ( pPivot != NULL ) break; } if ( pPivot == NULL ) return 0; // if the MUX control is defined, it should not be if ( pFaninC && !pFaninC->fMarkA && !pFaninC->fMarkB ) Vec_PtrPush( vFront, pFaninC ); // clean the markings Vec_PtrForEachEntry( Ivy_Obj_t *, vVolume, pObj, k ) pObj->fMarkA = pObj->fMarkB = 0; // mark the nodes on the frontier (including the pivot) Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, k ) pObj->fMarkA = 1; // cut exists, collect all the nodes on the shortest path to the pivot Vec_PtrClear( vLeaves ); Vec_PtrClear( vVolume ); RetValue = Ivy_ManFindBoolCut_rec( p, pRoot, vLeaves, vVolume, pPivot ); assert( RetValue == 1 ); // unmark the nodes on the frontier (including the pivot) Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, k ) pObj->fMarkA = 0; // mark the nodes in the volume Vec_PtrForEachEntry( Ivy_Obj_t *, vVolume, pObj, k ) pObj->fMarkA = 1; // expand the cut without increasing its size while ( 1 ) { Vec_PtrForEachEntry( Ivy_Obj_t *, vLeaves, pObj, k ) if ( Ivy_ManFindBoolCutCost(pObj) < 2 ) break; if ( k == Vec_PtrSize(vLeaves) ) break; // the node can be expanded // remove the old node Vec_PtrRemove( vLeaves, pObj ); // expand this node pFanin0 = Ivy_ObjFanin0(pObj); if ( !pFanin0->fMarkA ) { pFanin0->fMarkA = 1; Vec_PtrPush( vVolume, pFanin0 ); Vec_PtrPush( vLeaves, pFanin0 ); } if ( Ivy_ObjIsBuf(pObj) ) continue; // expand this node pFanin1 = Ivy_ObjFanin1(pObj); if ( !pFanin1->fMarkA ) { pFanin1->fMarkA = 1; Vec_PtrPush( vVolume, pFanin1 ); Vec_PtrPush( vLeaves, pFanin1 ); } } // unmark the nodes in the volume Vec_PtrForEachEntry( Ivy_Obj_t *, vVolume, pObj, k ) pObj->fMarkA = 0; return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManTestCutsBool( Ivy_Man_t * p ) { Vec_Ptr_t * vFront, * vVolume, * vLeaves; Ivy_Obj_t * pObj;//, * pTemp; int i, RetValue;//, k; vFront = Vec_PtrAlloc( 100 ); vVolume = Vec_PtrAlloc( 100 ); vLeaves = Vec_PtrAlloc( 100 ); Ivy_ManForEachObj( p, pObj, i ) { if ( !Ivy_ObjIsNode(pObj) ) continue; if ( Ivy_ObjIsMuxType(pObj) ) { printf( "m" ); continue; } if ( Ivy_ObjIsExor(pObj) ) printf( "x" ); RetValue = Ivy_ManFindBoolCut( p, pObj, vFront, vVolume, vLeaves ); if ( RetValue == 0 ) printf( "- " ); else printf( "%d ", Vec_PtrSize(vLeaves) ); /* printf( "( " ); Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, k ) printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) ); printf( ")\n" ); */ } printf( "\n" ); Vec_PtrFree( vFront ); Vec_PtrFree( vVolume ); Vec_PtrFree( vLeaves ); } /**Function************************************************************* Synopsis [Find the hash value of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut ) { int i; // for ( i = 1; i < pCut->nSize; i++ ) // assert( pCut->pArray[i-1] < pCut->pArray[i] ); pCut->uHash = 0; for ( i = 0; i < pCut->nSize; i++ ) pCut->uHash |= (1 << (pCut->pArray[i] % 31)); return pCut->uHash; } /**Function************************************************************* Synopsis [Removes one node to the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Ivy_NodeCutShrink( Ivy_Cut_t * pCut, int iOld ) { int i, k; for ( i = k = 0; i < pCut->nSize; i++ ) if ( pCut->pArray[i] != iOld ) pCut->pArray[k++] = pCut->pArray[i]; assert( k == pCut->nSize - 1 ); pCut->nSize--; } /**Function************************************************************* Synopsis [Adds one node to the cut.] Description [Returns 1 if the cuts is still okay.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ivy_NodeCutExtend( Ivy_Cut_t * pCut, int iNew ) { int i; for ( i = 0; i < pCut->nSize; i++ ) if ( pCut->pArray[i] == iNew ) return 1; // check if there is room if ( pCut->nSize == pCut->nSizeMax ) return 0; // add the new one for ( i = pCut->nSize - 1; i >= 0; i-- ) if ( pCut->pArray[i] > iNew ) pCut->pArray[i+1] = pCut->pArray[i]; else { assert( pCut->pArray[i] < iNew ); break; } pCut->pArray[i+1] = iNew; pCut->nSize++; return 1; } /**Function************************************************************* Synopsis [Returns 1 if the cut can be constructed; 0 otherwise.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ivy_NodeCutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 ) { int i; if ( pCut->nSize < pCut->nSizeMax ) return 1; for ( i = 0; i < pCut->nSize; i++ ) if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 ) return 1; return 0; } /**Function************************************************************* Synopsis [Derives new cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ivy_NodeCutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) { unsigned uHash = 0; int i, k; assert( pCut->nSize > 0 ); assert( IdNew0 < IdNew1 ); for ( i = k = 0; i < pCut->nSize; i++ ) { if ( pCut->pArray[i] == IdOld ) continue; if ( IdNew0 <= pCut->pArray[i] ) { if ( IdNew0 < pCut->pArray[i] ) { pCutNew->pArray[ k++ ] = IdNew0; uHash |= Ivy_NodeCutHashValue( IdNew0 ); } IdNew0 = 0x7FFFFFFF; } if ( IdNew1 <= pCut->pArray[i] ) { if ( IdNew1 < pCut->pArray[i] ) { pCutNew->pArray[ k++ ] = IdNew1; uHash |= Ivy_NodeCutHashValue( IdNew1 ); } IdNew1 = 0x7FFFFFFF; } pCutNew->pArray[ k++ ] = pCut->pArray[i]; uHash |= Ivy_NodeCutHashValue( pCut->pArray[i] ); } if ( IdNew0 < 0x7FFFFFFF ) { pCutNew->pArray[ k++ ] = IdNew0; uHash |= Ivy_NodeCutHashValue( IdNew0 ); } if ( IdNew1 < 0x7FFFFFFF ) { pCutNew->pArray[ k++ ] = IdNew1; uHash |= Ivy_NodeCutHashValue( IdNew1 ); } pCutNew->nSize = k; pCutNew->uHash = uHash; assert( pCutNew->nSize <= pCut->nSizeMax ); // for ( i = 1; i < pCutNew->nSize; i++ ) // assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); return 1; } /**Function************************************************************* Synopsis [Check if the cut exists.] Description [Returns 1 if the cut exists.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_NodeCutFindOrAdd( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) { Ivy_Cut_t * pCut; int i, k; assert( pCutNew->uHash ); // try to find the cut for ( i = 0; i < pCutStore->nCuts; i++ ) { pCut = pCutStore->pCuts + i; if ( pCut->uHash == pCutNew->uHash && pCut->nSize == pCutNew->nSize ) { for ( k = 0; k < pCutNew->nSize; k++ ) if ( pCut->pArray[k] != pCutNew->pArray[k] ) break; if ( k == pCutNew->nSize ) return 1; } } assert( pCutStore->nCuts < pCutStore->nCutsMax ); // add the cut pCut = pCutStore->pCuts + pCutStore->nCuts++; *pCut = *pCutNew; return 0; } /**Function************************************************************* Synopsis [Returns 1 if pDom is contained in pCut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut ) { int i, k; for ( i = 0; i < pDom->nSize; i++ ) { for ( k = 0; k < pCut->nSize; k++ ) if ( pDom->pArray[i] == pCut->pArray[k] ) break; if ( k == pCut->nSize ) // node i in pDom is not contained in pCut return 0; } // every node in pDom is contained in pCut return 1; } /**Function************************************************************* Synopsis [Check if the cut exists.] Description [Returns 1 if the cut exists.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_NodeCutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) { Ivy_Cut_t * pCut; int i, k; assert( pCutNew->uHash ); // try to find the cut for ( i = 0; i < pCutStore->nCuts; i++ ) { pCut = pCutStore->pCuts + i; if ( pCut->nSize == 0 ) continue; if ( pCut->nSize == pCutNew->nSize ) { if ( pCut->uHash == pCutNew->uHash ) { for ( k = 0; k < pCutNew->nSize; k++ ) if ( pCut->pArray[k] != pCutNew->pArray[k] ) break; if ( k == pCutNew->nSize ) return 1; } continue; } if ( pCut->nSize < pCutNew->nSize ) { // skip the non-contained cuts if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash ) continue; // check containment seriously if ( Ivy_CutCheckDominance( pCut, pCutNew ) ) return 1; continue; } // check potential containment of other cut // skip the non-contained cuts if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash ) continue; // check containment seriously if ( Ivy_CutCheckDominance( pCutNew, pCut ) ) { // remove the current cut // --pCutStore->nCuts; // for ( k = i; k < pCutStore->nCuts; k++ ) // pCutStore->pCuts[k] = pCutStore->pCuts[k+1]; // i--; pCut->nSize = 0; } } assert( pCutStore->nCuts < pCutStore->nCutsMax ); // add the cut pCut = pCutStore->pCuts + pCutStore->nCuts++; *pCut = *pCutNew; return 0; } /**Function************************************************************* Synopsis [Print the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeCompactCuts( Ivy_Store_t * pCutStore ) { Ivy_Cut_t * pCut; int i, k; for ( i = k = 0; i < pCutStore->nCuts; i++ ) { pCut = pCutStore->pCuts + i; if ( pCut->nSize == 0 ) continue; pCutStore->pCuts[k++] = *pCut; } pCutStore->nCuts = k; } /**Function************************************************************* Synopsis [Print the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodePrintCut( Ivy_Cut_t * pCut ) { int i; assert( pCut->nSize > 0 ); printf( "%d : {", pCut->nSize ); for ( i = 0; i < pCut->nSize; i++ ) printf( " %d", pCut->pArray[i] ); printf( " }\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodePrintCuts( Ivy_Store_t * pCutStore ) { int i; printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] ); for ( i = 0; i < pCutStore->nCuts; i++ ) Ivy_NodePrintCut( pCutStore->pCuts + i ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Ivy_Obj_t * Ivy_ObjRealFanin( Ivy_Obj_t * pObj ) { if ( !Ivy_ObjIsBuf(pObj) ) return pObj; return Ivy_ObjRealFanin( Ivy_ObjFanin0(pObj) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ) { static Ivy_Store_t CutStore, * pCutStore = &CutStore; Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut; Ivy_Obj_t * pLeaf; int i, k, iLeaf0, iLeaf1; assert( nLeaves <= IVY_CUT_INPUT ); // start the structure pCutStore->nCuts = 0; pCutStore->nCutsMax = IVY_CUT_LIMIT; // start the trivial cut pCutNew->uHash = 0; pCutNew->nSize = 1; pCutNew->nSizeMax = nLeaves; pCutNew->pArray[0] = pObj->Id; Ivy_NodeCutHash( pCutNew ); // add the trivial cut Ivy_NodeCutFindOrAdd( pCutStore, pCutNew ); assert( pCutStore->nCuts == 1 ); // explore the cuts for ( i = 0; i < pCutStore->nCuts; i++ ) { // expand this cut pCut = pCutStore->pCuts + i; if ( pCut->nSize == 0 ) continue; for ( k = 0; k < pCut->nSize; k++ ) { pLeaf = Ivy_ManObj( p, pCut->pArray[k] ); if ( Ivy_ObjIsCi(pLeaf) ) continue; /* *pCutNew = *pCut; Ivy_NodeCutShrink( pCutNew, pLeaf->Id ); if ( !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId0(pLeaf) ) ) continue; if ( Ivy_ObjIsNode(pLeaf) && !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId1(pLeaf) ) ) continue; Ivy_NodeCutHash( pCutNew ); */ iLeaf0 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin0(pLeaf)) ); iLeaf1 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin1(pLeaf)) ); // if ( iLeaf0 == iLeaf1 ) // strange situation observed on Jan 18, 2007 // continue; if ( !Ivy_NodeCutPrescreen( pCut, iLeaf0, iLeaf1 ) ) continue; if ( iLeaf0 > iLeaf1 ) Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf1, iLeaf0 ); else Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 ); Ivy_NodeCutFindOrAddFilter( pCutStore, pCutNew ); if ( pCutStore->nCuts == IVY_CUT_LIMIT ) break; } if ( pCutStore->nCuts == IVY_CUT_LIMIT ) break; } Ivy_NodeCompactCuts( pCutStore ); // Ivy_NodePrintCuts( pCutStore ); return pCutStore; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManTestCutsAll( Ivy_Man_t * p ) { Ivy_Obj_t * pObj; int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver; abctime clk = Abc_Clock(); nNodeTotal = nNodeOver = 0; nCutsTotal = -Ivy_ManNodeNum(p); Ivy_ManForEachObj( p, pObj, i ) { if ( !Ivy_ObjIsNode(pObj) ) continue; nCutsCut = Ivy_NodeFindCutsAll( p, pObj, 5 )->nCuts; nCutsTotal += nCutsCut; nNodeOver += (nCutsCut == IVY_CUT_LIMIT); nNodeTotal++; } printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ", nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); ABC_PRT( "Time", Abc_Clock() - clk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyCutTrav.c000066400000000000000000000346461477524141600166370ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyCutTrav.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyCutTrav.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ); static void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ); static void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, int nLeaves, int nWords, Vec_Int_t * vStore ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes cuts for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Store_t * Ivy_NodeFindCutsTravAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront, Vec_Int_t * vStore, Vec_Vec_t * vBitCuts ) { static Ivy_Store_t CutStore, * pCutStore = &CutStore; Vec_Ptr_t * vCuts, * vCuts0, * vCuts1; unsigned * pBitCut; Ivy_Obj_t * pLeaf; Ivy_Cut_t * pCut; int i, k, nWords, nNodes; assert( nLeaves <= IVY_CUT_INPUT ); // find the given number of nodes in the TFI Ivy_NodeComputeVolume( pObj, nNodeLimit - 1, vNodes, vFront ); nNodes = Vec_PtrSize(vNodes); // assert( nNodes <= nNodeLimit ); // make sure vBitCuts has enough room Vec_VecExpand( vBitCuts, nNodes-1 ); Vec_VecClear( vBitCuts ); // prepare the memory manager Vec_IntClear( vStore ); Vec_IntGrow( vStore, 64000 ); // set elementary cuts for the leaves nWords = Extra_BitWordNum( nNodes ); Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pLeaf, i ) { assert( Ivy_ObjTravId(pLeaf) < nNodes ); // get the new bitcut pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); // set it as the cut of this leaf Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); } // compute the cuts for each node Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pLeaf, i ) { // skip the leaves vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pLeaf) ); if ( Vec_PtrSize(vCuts) > 0 ) continue; // add elementary cut pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); // set it as the cut of this leaf Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); // get the fanin cuts vCuts0 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin0(pLeaf) ) ); vCuts1 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin1(pLeaf) ) ); assert( Vec_PtrSize(vCuts0) > 0 ); assert( Vec_PtrSize(vCuts1) > 0 ); // merge the cuts Ivy_NodeFindCutsMerge( vCuts0, vCuts1, vCuts, nLeaves, nWords, vStore ); } // start the structure pCutStore->nCuts = 0; pCutStore->nCutsMax = IVY_CUT_LIMIT; // collect the cuts of the root node vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pObj) ); Vec_PtrForEachEntry( unsigned *, vCuts, pBitCut, i ) { pCut = pCutStore->pCuts + pCutStore->nCuts++; pCut->nSize = 0; pCut->nSizeMax = nLeaves; pCut->uHash = 0; for ( k = 0; k < nNodes; k++ ) if ( Extra_TruthHasBit(pBitCut, k) ) pCut->pArray[ pCut->nSize++ ] = Ivy_ObjId( (Ivy_Obj_t *)Vec_PtrEntry(vNodes, k) ); assert( pCut->nSize <= nLeaves ); if ( pCutStore->nCuts == pCutStore->nCutsMax ) break; } // clean the travIds Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pLeaf, i ) pLeaf->TravId = 0; return pCutStore; } /**Function************************************************************* Synopsis [Creates elementary bit-cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ) { unsigned * pBitCut; pBitCut = Vec_IntFetch( vStore, nWords ); memset( pBitCut, 0, (size_t)(4 * nWords) ); Extra_TruthSetBit( pBitCut, NodeId ); return pBitCut; } /**Function************************************************************* Synopsis [Compares the node by level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_CompareNodesByLevel( Ivy_Obj_t ** ppObj1, Ivy_Obj_t ** ppObj2 ) { Ivy_Obj_t * pObj1 = *ppObj1; Ivy_Obj_t * pObj2 = *ppObj2; if ( pObj1->Level < pObj2->Level ) return -1; if ( pObj1->Level > pObj2->Level ) return 1; return 0; } /**Function************************************************************* Synopsis [Mark all nodes up to the given depth.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeComputeVolumeTrav1_rec( Ivy_Obj_t * pObj, int Depth ) { if ( Ivy_ObjIsCi(pObj) || Depth == 0 ) return; Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin0(pObj), Depth - 1 ); Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin1(pObj), Depth - 1 ); pObj->fMarkA = 1; } /**Function************************************************************* Synopsis [Collect the marked nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeComputeVolumeTrav2_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vNodes ) { if ( !pObj->fMarkA ) return; Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin0(pObj), vNodes ); Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin1(pObj), vNodes ); Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) { Ivy_Obj_t * pTemp, * pFanin; int i, nNodes; // mark nodes up to the given depth Ivy_NodeComputeVolumeTrav1_rec( pObj, 6 ); // collect the marked nodes Vec_PtrClear( vFront ); Ivy_NodeComputeVolumeTrav2_rec( pObj, vFront ); // find the fanins that are not marked Vec_PtrClear( vNodes ); Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i ) { pFanin = Ivy_ObjFanin0(pTemp); if ( !pFanin->fMarkA ) { pFanin->fMarkA = 1; Vec_PtrPush( vNodes, pFanin ); } pFanin = Ivy_ObjFanin1(pTemp); if ( !pFanin->fMarkA ) { pFanin->fMarkA = 1; Vec_PtrPush( vNodes, pFanin ); } } // remember the number of nodes in the frontier nNodes = Vec_PtrSize( vNodes ); // add the remaining nodes Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i ) Vec_PtrPush( vNodes, pTemp ); // unmark the nodes Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pTemp, i ) { pTemp->fMarkA = 0; pTemp->TravId = i; } // collect the frontier nodes Vec_PtrClear( vFront ); Vec_PtrForEachEntryStop( Ivy_Obj_t *, vNodes, pTemp, i, nNodes ) Vec_PtrPush( vFront, pTemp ); // printf( "%d ", Vec_PtrSize(vNodes) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeComputeVolume2( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) { Ivy_Obj_t * pLeaf, * pPivot, * pFanin; int LevelMax, i; assert( Ivy_ObjIsNode(pObj) ); // clear arrays Vec_PtrClear( vNodes ); Vec_PtrClear( vFront ); // add the root pObj->fMarkA = 1; Vec_PtrPush( vNodes, pObj ); Vec_PtrPush( vFront, pObj ); // expand node with maximum level LevelMax = pObj->Level; do { // get the node to expand pPivot = NULL; Vec_PtrForEachEntryReverse( Ivy_Obj_t *, vFront, pLeaf, i ) { if ( (int)pLeaf->Level == LevelMax ) { pPivot = pLeaf; break; } } // decrease level if we did not find the node if ( pPivot == NULL ) { if ( --LevelMax == 0 ) break; continue; } // the node to expand is found // remove it from frontier Vec_PtrRemove( vFront, pPivot ); // add fanins pFanin = Ivy_ObjFanin0(pPivot); if ( !pFanin->fMarkA ) { pFanin->fMarkA = 1; Vec_PtrPush( vNodes, pFanin ); Vec_PtrPush( vFront, pFanin ); } pFanin = Ivy_ObjFanin1(pPivot); if ( pFanin && !pFanin->fMarkA ) { pFanin->fMarkA = 1; Vec_PtrPush( vNodes, pFanin ); Vec_PtrPush( vFront, pFanin ); } // quit if we collected enough nodes } while ( Vec_PtrSize(vNodes) < nNodeLimit ); // sort nodes by level 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 ); assert( pFanin->Level <= pPivot->Level ); // clean the marks and remember node numbers in the TravId Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pFanin, i ) { pFanin->fMarkA = 0; pFanin->TravId = i; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Extra_TruthOrWords( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nWords ) { int w; for ( w = nWords-1; w >= 0; w-- ) pOut[w] = pIn0[w] | pIn1[w]; } static inline int Extra_TruthIsImplyWords( unsigned * pIn1, unsigned * pIn2, int nWords ) { int w; for ( w = nWords-1; w >= 0; w-- ) if ( pIn1[w] & ~pIn2[w] ) return 0; return 1; } /**Function************************************************************* Synopsis [Merges two sets of bit-cuts at a node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, int nLeaves, int nWords, Vec_Int_t * vStore ) { unsigned * pBitCut, * pBitCut0, * pBitCut1, * pBitCutTest; int i, k, c, w, Counter; // iterate through the cut pairs Vec_PtrForEachEntry( unsigned *, vCuts0, pBitCut0, i ) Vec_PtrForEachEntry( unsigned *, vCuts1, pBitCut1, k ) { // skip infeasible cuts Counter = 0; for ( w = 0; w < nWords; w++ ) { Counter += Extra_WordCountOnes( pBitCut0[w] | pBitCut1[w] ); if ( Counter > nLeaves ) break; } if ( Counter > nLeaves ) continue; // the new cut is feasible - create it pBitCutTest = Vec_IntFetch( vStore, nWords ); Extra_TruthOrWords( pBitCutTest, pBitCut0, pBitCut1, nWords ); // filter contained cuts; try to find containing cut w = 0; Vec_PtrForEachEntry( unsigned *, vCuts, pBitCut, c ) { if ( Extra_TruthIsImplyWords( pBitCut, pBitCutTest, nWords ) ) break; if ( Extra_TruthIsImplyWords( pBitCutTest, pBitCut, nWords ) ) continue; Vec_PtrWriteEntry( vCuts, w++, pBitCut ); } if ( c != Vec_PtrSize(vCuts) ) continue; Vec_PtrShrink( vCuts, w ); // add the cut Vec_PtrPush( vCuts, pBitCutTest ); } } /**Function************************************************************* Synopsis [Compute the set of all cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManTestCutsTravAll( Ivy_Man_t * p ) { Ivy_Store_t * pStore; Ivy_Obj_t * pObj; Vec_Ptr_t * vNodes, * vFront; Vec_Int_t * vStore; Vec_Vec_t * vBitCuts; int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver; abctime clk = Abc_Clock(); vNodes = Vec_PtrAlloc( 100 ); vFront = Vec_PtrAlloc( 100 ); vStore = Vec_IntAlloc( 100 ); vBitCuts = Vec_VecAlloc( 100 ); nNodeTotal = nNodeOver = 0; nCutsTotal = -Ivy_ManNodeNum(p); Ivy_ManForEachObj( p, pObj, i ) { if ( !Ivy_ObjIsNode(pObj) ) continue; pStore = Ivy_NodeFindCutsTravAll( p, pObj, 4, 60, vNodes, vFront, vStore, vBitCuts ); nCutsCut = pStore->nCuts; nCutsTotal += nCutsCut; nNodeOver += (nCutsCut == IVY_CUT_LIMIT); nNodeTotal++; } printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ", nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); ABC_PRT( "Time", Abc_Clock() - clk ); Vec_PtrFree( vNodes ); Vec_PtrFree( vFront ); Vec_IntFree( vStore ); Vec_VecFree( vBitCuts ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyDfs.c000066400000000000000000000372551477524141600157620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyDfs.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [DFS collection procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collects nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManDfs_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Int_t * vNodes ) { if ( Ivy_ObjIsMarkA(pObj) ) return; Ivy_ObjSetMarkA(pObj); if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) { if ( p->pHaig == NULL && pObj->pEquiv ) Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes ); return; } //printf( "visiting node %d\n", pObj->Id ); /* if ( pObj->Id == 87 || pObj->Id == 90 ) { int y = 0; } */ assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) ); Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); if ( !Ivy_ObjIsBuf(pObj) ) Ivy_ManDfs_rec( p, Ivy_ObjFanin1(pObj), vNodes ); if ( p->pHaig == NULL && pObj->pEquiv ) Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes ); Vec_IntPush( vNodes, pObj->Id ); //printf( "adding node %d with fanins %d and %d and equiv %d (refs = %d)\n", // pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id, // pObj->pEquiv? Ivy_Regular(pObj->pEquiv)->Id: -1, Ivy_ObjRefs(pObj) ); } /**Function************************************************************* Synopsis [Collects AND/EXOR nodes in the DFS order from CIs to COs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p ) { Vec_Int_t * vNodes; Ivy_Obj_t * pObj; int i; assert( Ivy_ManLatchNum(p) == 0 ); // make sure the nodes are not marked Ivy_ManForEachObj( p, pObj, i ) assert( !pObj->fMarkA && !pObj->fMarkB ); // collect the nodes vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) ); Ivy_ManForEachPo( p, pObj, i ) Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); // unmark the collected nodes // Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) // Ivy_ObjClearMarkA(pObj); Ivy_ManForEachObj( p, pObj, i ) Ivy_ObjClearMarkA(pObj); // make sure network does not have dangling nodes assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) ); return vNodes; } /**Function************************************************************* Synopsis [Collects AND/EXOR nodes in the DFS order from CIs to COs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches ) { Vec_Int_t * vNodes, * vLatches; Ivy_Obj_t * pObj; int i; // assert( Ivy_ManLatchNum(p) > 0 ); // make sure the nodes are not marked Ivy_ManForEachObj( p, pObj, i ) assert( !pObj->fMarkA && !pObj->fMarkB ); // collect the latches vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) ); Ivy_ManForEachLatch( p, pObj, i ) Vec_IntPush( vLatches, pObj->Id ); // collect the nodes vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) ); Ivy_ManForEachPo( p, pObj, i ) Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); // unmark the collected nodes // Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) // Ivy_ObjClearMarkA(pObj); Ivy_ManForEachObj( p, pObj, i ) Ivy_ObjClearMarkA(pObj); // make sure network does not have dangling nodes // assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) ); // temporary!!! if ( pvLatches == NULL ) Vec_IntFree( vLatches ); else *pvLatches = vLatches; return vNodes; } /**Function************************************************************* Synopsis [Collects nodes in the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManCollectCone_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vCone ) { if ( pObj->fMarkA ) return; if ( Ivy_ObjIsBuf(pObj) ) { Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone ); Vec_PtrPush( vCone, pObj ); return; } assert( Ivy_ObjIsNode(pObj) ); Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone ); Ivy_ManCollectCone_rec( Ivy_ObjFanin1(pObj), vCone ); Vec_PtrPushUnique( vCone, pObj ); } /**Function************************************************************* Synopsis [Collects nodes in the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ) { Ivy_Obj_t * pTemp; int i; assert( !Ivy_IsComplement(pObj) ); assert( Ivy_ObjIsNode(pObj) ); // mark the nodes Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i ) Ivy_Regular(pTemp)->fMarkA = 1; assert( pObj->fMarkA == 0 ); // collect the cone Vec_PtrClear( vCone ); Ivy_ManCollectCone_rec( pObj, vCone ); // unmark the nodes Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i ) Ivy_Regular(pTemp)->fMarkA = 0; } /**Function************************************************************* Synopsis [Returns the nodes by level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p ) { Vec_Vec_t * vNodes; Ivy_Obj_t * pObj; int i; vNodes = Vec_VecAlloc( 100 ); Ivy_ManForEachObj( p, pObj, i ) { assert( !Ivy_ObjIsBuf(pObj) ); if ( Ivy_ObjIsNode(pObj) ) Vec_VecPush( vNodes, pObj->Level, pObj ); } return vNodes; } /**Function************************************************************* Synopsis [Computes required levels for each node.] Description [Assumes topological ordering of the nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p ) { Ivy_Obj_t * pObj; Vec_Int_t * vLevelsR; Vec_Vec_t * vNodes; int i, k, Level, LevelMax; assert( p->vRequired == NULL ); // start the required times vLevelsR = Vec_IntStart( Ivy_ManObjIdMax(p) + 1 ); // iterate through the nodes in the reverse order vNodes = Ivy_ManLevelize( p ); Vec_VecForEachEntryReverseReverse( Ivy_Obj_t *, vNodes, pObj, i, k ) { Level = Vec_IntEntry( vLevelsR, pObj->Id ) + 1 + Ivy_ObjIsExor(pObj); if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId0(pObj) ) < Level ) Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId0(pObj), Level ); if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId1(pObj) ) < Level ) Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId1(pObj), Level ); } Vec_VecFree( vNodes ); // convert it into the required times LevelMax = Ivy_ManLevels( p ); //printf( "max %5d\n",LevelMax ); Ivy_ManForEachObj( p, pObj, i ) { Level = Vec_IntEntry( vLevelsR, pObj->Id ); Vec_IntWriteEntry( vLevelsR, pObj->Id, LevelMax - Level ); //printf( "%5d : %5d %5d\n", pObj->Id, Level, LevelMax - Level ); } p->vRequired = vLevelsR; return vLevelsR; } /**Function************************************************************* Synopsis [Recursively detects combinational loops.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManIsAcyclic_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { // skip the node if it is already visited if ( Ivy_ObjIsTravIdPrevious(p, pObj) ) return 1; // check if the node is part of the combinational loop if ( Ivy_ObjIsTravIdCurrent(p, pObj) ) { fprintf( stdout, "Manager contains combinational loop!\n" ); fprintf( stdout, "Node \"%d\" is encountered twice on the following path:\n", Ivy_ObjId(pObj) ); fprintf( stdout, " %d", Ivy_ObjId(pObj) ); return 0; } // mark this node as a node on the current path Ivy_ObjSetTravIdCurrent( p, pObj ); // explore equivalent nodes if pObj is the main node if ( p->pHaig == NULL && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) { Ivy_Obj_t * pTemp; assert( !Ivy_IsComplement(pObj->pEquiv) ); for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) { // traverse the fanin's cone searching for the loop if ( !Ivy_ManIsAcyclic_rec(p, pTemp) ) { // return as soon as the loop is detected fprintf( stdout, " -> (%d", Ivy_ObjId(pObj) ); for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) fprintf( stdout, " %d", Ivy_ObjId(pTemp) ); fprintf( stdout, ")" ); return 0; } } } // quite if it is a CI node if ( Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) ) { // mark this node as a visited node Ivy_ObjSetTravIdPrevious( p, pObj ); return 1; } assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); // traverse the fanin's cone searching for the loop if ( !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj)) ) { // return as soon as the loop is detected fprintf( stdout, " -> %d", Ivy_ObjId(pObj) ); return 0; } // traverse the fanin's cone searching for the loop if ( Ivy_ObjIsNode(pObj) && !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin1(pObj)) ) { // return as soon as the loop is detected fprintf( stdout, " -> %d", Ivy_ObjId(pObj) ); return 0; } // mark this node as a visited node Ivy_ObjSetTravIdPrevious( p, pObj ); return 1; } /**Function************************************************************* Synopsis [Detects combinational loops.] Description [This procedure is based on the idea suggested by Donald Chai. As we traverse the network and visit the nodes, we need to distinquish three types of nodes: (1) those that are visited for the first time, (2) those that have been visited in this traversal but are currently not on the traversal path, (3) those that have been visited and are currently on the travesal path. When the node of type (3) is encountered, it means that there is a combinational loop. To mark the three types of nodes, two new values of the traversal IDs are used.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManIsAcyclic( Ivy_Man_t * p ) { Ivy_Obj_t * pObj; int fAcyclic, i; // set the traversal ID for this DFS ordering Ivy_ManIncrementTravId( p ); Ivy_ManIncrementTravId( p ); // pObj->TravId == pNet->nTravIds means "pObj is on the path" // pObj->TravId == pNet->nTravIds - 1 means "pObj is visited but is not on the path" // pObj->TravId < pNet->nTravIds - 1 means "pObj is not visited" // traverse the network to detect cycles fAcyclic = 1; Ivy_ManForEachCo( p, pObj, i ) { // traverse the output logic cone if ( (fAcyclic = Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj))) ) continue; // stop as soon as the first loop is detected fprintf( stdout, " (cone of %s \"%d\")\n", Ivy_ObjIsLatch(pObj)? "latch" : "PO", Ivy_ObjId(pObj) ); break; } return fAcyclic; } /**Function************************************************************* Synopsis [Sets the levels of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManSetLevels_rec( Ivy_Obj_t * pObj, int fHaig ) { // quit if the node is visited if ( Ivy_ObjIsMarkA(pObj) ) return pObj->Level; Ivy_ObjSetMarkA(pObj); // quit if this is a CI if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) return 0; assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) ); // get levels of the fanins Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig ); if ( !Ivy_ObjIsBuf(pObj) ) Ivy_ManSetLevels_rec( Ivy_ObjFanin1(pObj), fHaig ); // get level of the node if ( Ivy_ObjIsBuf(pObj) ) pObj->Level = 1 + Ivy_ObjFanin0(pObj)->Level; else if ( Ivy_ObjIsNode(pObj) ) pObj->Level = Ivy_ObjLevelNew( pObj ); else assert( 0 ); // get level of other choices if ( fHaig && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) { Ivy_Obj_t * pTemp; unsigned LevelMax = pObj->Level; for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) { Ivy_ManSetLevels_rec( pTemp, fHaig ); LevelMax = IVY_MAX( LevelMax, pTemp->Level ); } // get this level pObj->Level = LevelMax; for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) pTemp->Level = LevelMax; } return pObj->Level; } /**Function************************************************************* Synopsis [Sets the levels of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig ) { Ivy_Obj_t * pObj; int i, LevelMax; // check if CIs have choices if ( fHaig ) { Ivy_ManForEachCi( p, pObj, i ) if ( pObj->pEquiv ) printf( "CI %d has a choice, which will not be visualized.\n", pObj->Id ); } // clean the levels Ivy_ManForEachObj( p, pObj, i ) pObj->Level = 0; // compute the levels LevelMax = 0; Ivy_ManForEachCo( p, pObj, i ) { Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig ); LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level ); } // compute levels of nodes without fanout Ivy_ManForEachObj( p, pObj, i ) if ( (Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj)) && Ivy_ObjRefs(pObj) == 0 ) { Ivy_ManSetLevels_rec( pObj, fHaig ); LevelMax = IVY_MAX( LevelMax, (int)pObj->Level ); } // clean the marks Ivy_ManForEachObj( p, pObj, i ) Ivy_ObjClearMarkA(pObj); return LevelMax; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyDsd.c000066400000000000000000000633001477524141600157460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyDsd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Disjoint-support decomposition.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyDsd.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // decomposition types typedef enum { IVY_DEC_PI, // 0: var IVY_DEC_CONST1, // 1: CONST1 IVY_DEC_BUF, // 2: BUF IVY_DEC_AND, // 3: AND IVY_DEC_EXOR, // 4: EXOR IVY_DEC_MUX, // 5: MUX IVY_DEC_MAJ, // 6: MAJ IVY_DEC_PRIME // 7: undecomposable } Ivy_DecType_t; typedef struct Ivy_Dec_t_ Ivy_Dec_t; struct Ivy_Dec_t_ { unsigned Type : 4; // the node type (PI, CONST1, AND, EXOR, MUX, PRIME) unsigned fCompl : 1; // shows if node is complemented (root node only) unsigned nFans : 3; // the number of fanins unsigned Fan0 : 4; // fanin 0 unsigned Fan1 : 4; // fanin 1 unsigned Fan2 : 4; // fanin 2 unsigned Fan3 : 4; // fanin 3 unsigned Fan4 : 4; // fanin 4 unsigned Fan5 : 4; // fanin 5 }; static inline int Ivy_DecToInt( Ivy_Dec_t m ) { union { Ivy_Dec_t x; int y; } v; v.x = m; return v.y; } static inline Ivy_Dec_t Ivy_IntToDec( int m ) { union { Ivy_Dec_t x; int y; } v; v.y = m; return v.x; } static inline void Ivy_DecClear( Ivy_Dec_t * pNode ) { *pNode = Ivy_IntToDec(0); } //static inline int Ivy_DecToInt( Ivy_Dec_t Node ) { return *((int *)&Node); } //static inline Ivy_Dec_t Ivy_IntToDec( int Node ) { return *((Ivy_Dec_t *)&Node); } //static inline void Ivy_DecClear( Ivy_Dec_t * pNode ) { *((int *)pNode) = 0; } static unsigned s_Masks[6][2] = { { 0x55555555, 0xAAAAAAAA }, { 0x33333333, 0xCCCCCCCC }, { 0x0F0F0F0F, 0xF0F0F0F0 }, { 0x00FF00FF, 0xFF00FF00 }, { 0x0000FFFF, 0xFFFF0000 }, { 0x00000000, 0xFFFFFFFF } }; static inline int Ivy_TruthWordCountOnes( unsigned uWord ) { uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); return (uWord & 0x0000FFFF) + (uWord>>16); } static inline int Ivy_TruthCofactorIsConst( unsigned uTruth, int Var, int Cof, int Const ) { if ( Const == 0 ) return (uTruth & s_Masks[Var][Cof]) == 0; else return (uTruth & s_Masks[Var][Cof]) == s_Masks[Var][Cof]; } static inline int Ivy_TruthCofactorIsOne( unsigned uTruth, int Var ) { return (uTruth & s_Masks[Var][0]) == 0; } static inline unsigned Ivy_TruthCofactor( unsigned uTruth, int Var ) { unsigned uCofactor = uTruth & s_Masks[Var >> 1][(Var & 1) == 0]; int Shift = (1 << (Var >> 1)); if ( Var & 1 ) return uCofactor | (uCofactor << Shift); return uCofactor | (uCofactor >> Shift); } static inline unsigned Ivy_TruthCofactor2( unsigned uTruth, int Var0, int Var1 ) { return Ivy_TruthCofactor( Ivy_TruthCofactor(uTruth, Var0), Var1 ); } // returns 1 if the truth table depends on this var (var is regular interger var) static inline int Ivy_TruthDepends( unsigned uTruth, int Var ) { return Ivy_TruthCofactor(uTruth, Var << 1) != Ivy_TruthCofactor(uTruth, (Var << 1) | 1); } static inline void Ivy_DecSetVar( Ivy_Dec_t * pNode, int iNum, unsigned Var ) { assert( iNum >= 0 && iNum <= 5 ); switch( iNum ) { case 0: pNode->Fan0 = Var; break; case 1: pNode->Fan1 = Var; break; case 2: pNode->Fan2 = Var; break; case 3: pNode->Fan3 = Var; break; case 4: pNode->Fan4 = Var; break; case 5: pNode->Fan5 = Var; break; } } static inline unsigned Ivy_DecGetVar( Ivy_Dec_t * pNode, int iNum ) { assert( iNum >= 0 && iNum <= 5 ); switch( iNum ) { case 0: return pNode->Fan0; case 1: return pNode->Fan1; case 2: return pNode->Fan2; case 3: return pNode->Fan3; case 4: return pNode->Fan4; case 5: return pNode->Fan5; } return ~0; } static int Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree ); static int Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree ); //int nTruthDsd; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes DSD of truth table of 5 variables or less.] Description [Returns 1 if the function is a constant or is fully DSD decomposable using AND/EXOR/MUX gates.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree ) { Ivy_Dec_t Node; int i, RetValue; // set the PI variables Vec_IntClear( vTree ); for ( i = 0; i < 5; i++ ) Vec_IntPush( vTree, 0 ); // check if it is a constant if ( uTruth == 0 || ~uTruth == 0 ) { Ivy_DecClear( &Node ); Node.Type = IVY_DEC_CONST1; Node.fCompl = (uTruth == 0); Vec_IntPush( vTree, Ivy_DecToInt(Node) ); return 1; } // perform the decomposition RetValue = Ivy_TruthDecompose_rec( uTruth, vTree ); if ( RetValue == -1 ) return 0; // get the topmost node if ( (RetValue >> 1) < 5 ) { // add buffer Ivy_DecClear( &Node ); Node.Type = IVY_DEC_BUF; Node.fCompl = (RetValue & 1); Node.Fan0 = ((RetValue >> 1) << 1); Vec_IntPush( vTree, Ivy_DecToInt(Node) ); } else if ( RetValue & 1 ) { // check if the topmost node has to be complemented Node = Ivy_IntToDec( Vec_IntPop(vTree) ); assert( Node.fCompl == 0 ); Node.fCompl = (RetValue & 1); Vec_IntPush( vTree, Ivy_DecToInt(Node) ); } if ( uTruth != Ivy_TruthDsdCompute(vTree) ) printf( "Verification failed.\n" ); return 1; } /**Function************************************************************* Synopsis [Computes DSD of truth table.] Description [Returns the number of topmost decomposition node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree ) { Ivy_Dec_t Node; int Supp[5], Vars0[5], Vars1[5], Vars2[5], * pVars = NULL; int nSupp, Count0, Count1, Count2, nVars = 0, RetValue, fCompl = 0, i; unsigned uTruthCof, uCof0, uCof1; // get constant confactors Count0 = Count1 = Count2 = nSupp = 0; for ( i = 0; i < 5; i++ ) { if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 0) ) Vars0[Count0++] = (i << 1) | 0; else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 0) ) Vars0[Count0++] = (i << 1) | 1; else if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 1) ) Vars1[Count1++] = (i << 1) | 0; else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 1) ) Vars1[Count1++] = (i << 1) | 1; else { uCof0 = Ivy_TruthCofactor( uTruth, (i << 1) | 1 ); uCof1 = Ivy_TruthCofactor( uTruth, (i << 1) | 0 ); if ( uCof0 == ~uCof1 ) Vars2[Count2++] = (i << 1) | 0; else if ( uCof0 != uCof1 ) Supp[nSupp++] = i; } } assert( Count0 == 0 || Count1 == 0 ); assert( Count0 == 0 || Count2 == 0 ); assert( Count1 == 0 || Count2 == 0 ); // consider the case of a single variable if ( Count0 == 1 && nSupp == 0 ) return Vars0[0]; // consider more complex decompositions if ( Count0 == 0 && Count1 == 0 && Count2 == 0 ) return Ivy_TruthRecognizeMuxMaj( uTruth, Supp, nSupp, vTree ); // extract the nodes Ivy_DecClear( &Node ); if ( Count0 > 0 ) nVars = Count0, pVars = Vars0, Node.Type = IVY_DEC_AND, fCompl = 0; else if ( Count1 > 0 ) nVars = Count1, pVars = Vars1, Node.Type = IVY_DEC_AND, fCompl = 1, uTruth = ~uTruth; else if ( Count2 > 0 ) nVars = Count2, pVars = Vars2, Node.Type = IVY_DEC_EXOR, fCompl = 0; else assert( 0 ); Node.nFans = nVars+(nSupp>0); // compute cofactor uTruthCof = uTruth; for ( i = 0; i < nVars; i++ ) { uTruthCof = Ivy_TruthCofactor( uTruthCof, pVars[i] ); Ivy_DecSetVar( &Node, i, pVars[i] ); } if ( Node.Type == IVY_DEC_EXOR ) fCompl ^= ((Node.nFans & 1) == 0); if ( nSupp > 0 ) { assert( uTruthCof != 0 && ~uTruthCof != 0 ); // call recursively RetValue = Ivy_TruthDecompose_rec( uTruthCof, vTree ); // quit if non-decomposable if ( RetValue == -1 ) return -1; // remove the complement from the child if the node is EXOR if ( Node.Type == IVY_DEC_EXOR && (RetValue & 1) ) { fCompl ^= 1; RetValue ^= 1; } // set the new decomposition Ivy_DecSetVar( &Node, nVars, RetValue ); } else if ( Node.Type == IVY_DEC_EXOR ) fCompl ^= (uTruthCof == 0); Vec_IntPush( vTree, Ivy_DecToInt(Node) ); return ((Vec_IntSize(vTree)-1) << 1) | fCompl; } /**Function************************************************************* Synopsis [Returns a non-negative number if the truth table is a MUX.] Description [If the truth table is a MUX, returns the variable as follows: first, control variable; second, positive cofactor; third, negative cofactor.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree ) { Ivy_Dec_t Node; int i, k, RetValue0, RetValue1; unsigned uCof0, uCof1, Num; char Count[3]; assert( nSupp >= 3 ); // start the node Ivy_DecClear( &Node ); Node.Type = IVY_DEC_MUX; Node.nFans = 3; // try each of the variables for ( i = 0; i < nSupp; i++ ) { // get the cofactors with respect to these variables uCof0 = Ivy_TruthCofactor( uTruth, (pSupp[i] << 1) | 1 ); uCof1 = Ivy_TruthCofactor( uTruth, pSupp[i] << 1 ); // go through all other variables and make sure // each of them belongs to the support of one cofactor for ( k = 0; k < nSupp; k++ ) { if ( k == i ) continue; if ( Ivy_TruthDepends(uCof0, pSupp[k]) && Ivy_TruthDepends(uCof1, pSupp[k]) ) break; } if ( k < nSupp ) continue; // MUX decomposition exists RetValue0 = Ivy_TruthDecompose_rec( uCof0, vTree ); if ( RetValue0 == -1 ) break; RetValue1 = Ivy_TruthDecompose_rec( uCof1, vTree ); if ( RetValue1 == -1 ) break; // both of them exist; create the node Ivy_DecSetVar( &Node, 0, pSupp[i] << 1 ); Ivy_DecSetVar( &Node, 1, RetValue1 ); Ivy_DecSetVar( &Node, 2, RetValue0 ); Vec_IntPush( vTree, Ivy_DecToInt(Node) ); return ((Vec_IntSize(vTree)-1) << 1) | 0; } // check majority gate if ( nSupp > 3 ) return -1; if ( Ivy_TruthWordCountOnes(uTruth) != 16 ) return -1; // this is a majority gate; determine polarity Node.Type = IVY_DEC_MAJ; Count[0] = Count[1] = Count[2] = 0; for ( i = 0; i < 8; i++ ) { Num = 0; for ( k = 0; k < 3; k++ ) if ( i & (1 << k) ) Num |= (1 << pSupp[k]); assert( Num < 32 ); if ( (uTruth & (1 << Num)) == 0 ) continue; for ( k = 0; k < 3; k++ ) if ( i & (1 << k) ) Count[k]++; } assert( Count[0] == 1 || Count[0] == 3 ); assert( Count[1] == 1 || Count[1] == 3 ); assert( Count[2] == 1 || Count[2] == 3 ); Ivy_DecSetVar( &Node, 0, (pSupp[0] << 1)|(Count[0] == 1) ); Ivy_DecSetVar( &Node, 1, (pSupp[1] << 1)|(Count[1] == 1) ); Ivy_DecSetVar( &Node, 2, (pSupp[2] << 1)|(Count[2] == 1) ); Vec_IntPush( vTree, Ivy_DecToInt(Node) ); return ((Vec_IntSize(vTree)-1) << 1) | 0; } /**Function************************************************************* Synopsis [Computes truth table of decomposition tree for verification.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Ivy_TruthDsdCompute_rec( int iNode, Vec_Int_t * vTree ) { unsigned uTruthChild, uTruthTotal; int Var, i; // get the node Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); // compute the node function if ( Node.Type == IVY_DEC_CONST1 ) return s_Masks[5][ !Node.fCompl ]; if ( Node.Type == IVY_DEC_PI ) return s_Masks[iNode][ !Node.fCompl ]; if ( Node.Type == IVY_DEC_BUF ) { uTruthTotal = Ivy_TruthDsdCompute_rec( Node.Fan0 >> 1, vTree ); return Node.fCompl? ~uTruthTotal : uTruthTotal; } if ( Node.Type == IVY_DEC_AND ) { uTruthTotal = s_Masks[5][1]; for ( i = 0; i < (int)Node.nFans; i++ ) { Var = Ivy_DecGetVar( &Node, i ); uTruthChild = Ivy_TruthDsdCompute_rec( Var >> 1, vTree ); uTruthTotal = (Var & 1)? uTruthTotal & ~uTruthChild : uTruthTotal & uTruthChild; } return Node.fCompl? ~uTruthTotal : uTruthTotal; } if ( Node.Type == IVY_DEC_EXOR ) { uTruthTotal = 0; for ( i = 0; i < (int)Node.nFans; i++ ) { Var = Ivy_DecGetVar( &Node, i ); uTruthTotal ^= Ivy_TruthDsdCompute_rec( Var >> 1, vTree ); assert( (Var & 1) == 0 ); } return Node.fCompl? ~uTruthTotal : uTruthTotal; } assert( Node.fCompl == 0 ); if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) { unsigned uTruthChildC, uTruthChild1, uTruthChild0; int VarC, Var1, Var0; VarC = Ivy_DecGetVar( &Node, 0 ); Var1 = Ivy_DecGetVar( &Node, 1 ); Var0 = Ivy_DecGetVar( &Node, 2 ); uTruthChildC = Ivy_TruthDsdCompute_rec( VarC >> 1, vTree ); uTruthChild1 = Ivy_TruthDsdCompute_rec( Var1 >> 1, vTree ); uTruthChild0 = Ivy_TruthDsdCompute_rec( Var0 >> 1, vTree ); assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 ); uTruthChildC = (VarC & 1)? ~uTruthChildC : uTruthChildC; uTruthChild1 = (Var1 & 1)? ~uTruthChild1 : uTruthChild1; uTruthChild0 = (Var0 & 1)? ~uTruthChild0 : uTruthChild0; if ( Node.Type == IVY_DEC_MUX ) return (uTruthChildC & uTruthChild1) | (~uTruthChildC & uTruthChild0); else return (uTruthChildC & uTruthChild1) | (uTruthChildC & uTruthChild0) | (uTruthChild1 & uTruthChild0); } assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Computes truth table of decomposition tree for verification.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Ivy_TruthDsdCompute( Vec_Int_t * vTree ) { return Ivy_TruthDsdCompute_rec( Vec_IntSize(vTree)-1, vTree ); } /**Function************************************************************* Synopsis [Prints the decomposition tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_TruthDsdPrint_rec( FILE * pFile, int iNode, Vec_Int_t * vTree ) { int Var, i; // get the node Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); // compute the node function if ( Node.Type == IVY_DEC_CONST1 ) fprintf( pFile, "Const1%s", (Node.fCompl? "\'" : "") ); else if ( Node.Type == IVY_DEC_PI ) fprintf( pFile, "%c%s", 'a' + iNode, (Node.fCompl? "\'" : "") ); else if ( Node.Type == IVY_DEC_BUF ) { Ivy_TruthDsdPrint_rec( pFile, Node.Fan0 >> 1, vTree ); fprintf( pFile, "%s", (Node.fCompl? "\'" : "") ); } else if ( Node.Type == IVY_DEC_AND ) { fprintf( pFile, "AND(" ); for ( i = 0; i < (int)Node.nFans; i++ ) { Var = Ivy_DecGetVar( &Node, i ); Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree ); fprintf( pFile, "%s", (Var & 1)? "\'" : "" ); if ( i != (int)Node.nFans-1 ) fprintf( pFile, "," ); } fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") ); } else if ( Node.Type == IVY_DEC_EXOR ) { fprintf( pFile, "EXOR(" ); for ( i = 0; i < (int)Node.nFans; i++ ) { Var = Ivy_DecGetVar( &Node, i ); Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree ); if ( i != (int)Node.nFans-1 ) fprintf( pFile, "," ); assert( (Var & 1) == 0 ); } fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") ); } else if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) { int VarC, Var1, Var0; assert( Node.fCompl == 0 ); VarC = Ivy_DecGetVar( &Node, 0 ); Var1 = Ivy_DecGetVar( &Node, 1 ); Var0 = Ivy_DecGetVar( &Node, 2 ); fprintf( pFile, "%s", (Node.Type == IVY_DEC_MUX)? "MUX(" : "MAJ(" ); Ivy_TruthDsdPrint_rec( pFile, VarC >> 1, vTree ); fprintf( pFile, "%s", (VarC & 1)? "\'" : "" ); fprintf( pFile, "," ); Ivy_TruthDsdPrint_rec( pFile, Var1 >> 1, vTree ); fprintf( pFile, "%s", (Var1 & 1)? "\'" : "" ); fprintf( pFile, "," ); Ivy_TruthDsdPrint_rec( pFile, Var0 >> 1, vTree ); fprintf( pFile, "%s", (Var0 & 1)? "\'" : "" ); fprintf( pFile, ")" ); } else assert( 0 ); } /**Function************************************************************* Synopsis [Prints the decomposition tree.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree ) { fprintf( pFile, "F = " ); Ivy_TruthDsdPrint_rec( pFile, Vec_IntSize(vTree)-1, vTree ); fprintf( pFile, "\n" ); } /**Function************************************************************* Synopsis [Implement DSD in the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_ManDsdConstruct_rec( Ivy_Man_t * p, Vec_Int_t * vFront, int iNode, Vec_Int_t * vTree ) { Ivy_Obj_t * pResult, * pChild, * pNodes[16]; int Var, i; // get the node Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); // compute the node function if ( Node.Type == IVY_DEC_CONST1 ) return Ivy_NotCond( Ivy_ManConst1(p), Node.fCompl ); if ( Node.Type == IVY_DEC_PI ) { pResult = Ivy_ManObj( p, Vec_IntEntry(vFront, iNode) ); return Ivy_NotCond( pResult, Node.fCompl ); } if ( Node.Type == IVY_DEC_BUF ) { pResult = Ivy_ManDsdConstruct_rec( p, vFront, Node.Fan0 >> 1, vTree ); return Ivy_NotCond( pResult, Node.fCompl ); } if ( Node.Type == IVY_DEC_AND || Node.Type == IVY_DEC_EXOR ) { for ( i = 0; i < (int)Node.nFans; i++ ) { Var = Ivy_DecGetVar( &Node, i ); assert( Node.Type == IVY_DEC_AND || (Var & 1) == 0 ); pChild = Ivy_ManDsdConstruct_rec( p, vFront, Var >> 1, vTree ); pChild = Ivy_NotCond( pChild, (Var & 1) ); pNodes[i] = pChild; } // Ivy_MultiEval( pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR ); pResult = Ivy_Multi( p, pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR ); return Ivy_NotCond( pResult, Node.fCompl ); } assert( Node.fCompl == 0 ); if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) { int VarC, Var1, Var0; VarC = Ivy_DecGetVar( &Node, 0 ); Var1 = Ivy_DecGetVar( &Node, 1 ); Var0 = Ivy_DecGetVar( &Node, 2 ); pNodes[0] = Ivy_ManDsdConstruct_rec( p, vFront, VarC >> 1, vTree ); pNodes[1] = Ivy_ManDsdConstruct_rec( p, vFront, Var1 >> 1, vTree ); pNodes[2] = Ivy_ManDsdConstruct_rec( p, vFront, Var0 >> 1, vTree ); assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 ); pNodes[0] = Ivy_NotCond( pNodes[0], (VarC & 1) ); pNodes[1] = Ivy_NotCond( pNodes[1], (Var1 & 1) ); pNodes[2] = Ivy_NotCond( pNodes[2], (Var0 & 1) ); if ( Node.Type == IVY_DEC_MUX ) return Ivy_Mux( p, pNodes[0], pNodes[1], pNodes[2] ); else return Ivy_Maj( p, pNodes[0], pNodes[1], pNodes[2] ); } assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Implement DSD in the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree ) { int Entry, i; // implement latches on the frontier (TEMPORARY!!!) Vec_IntForEachEntry( vFront, Entry, i ) Vec_IntWriteEntry( vFront, i, Ivy_LeafId(Entry) ); // recursively construct the tree return Ivy_ManDsdConstruct_rec( p, vFront, Vec_IntSize(vTree)-1, vTree ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_TruthDsdComputePrint( unsigned uTruth ) { static Vec_Int_t * vTree = NULL; if ( vTree == NULL ) vTree = Vec_IntAlloc( 12 ); if ( Ivy_TruthDsd( uTruth, vTree ) ) Ivy_TruthDsdPrint( stdout, vTree ); else printf( "Undecomposable\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_TruthTestOne( unsigned uTruth ) { static int Counter = 0; static Vec_Int_t * vTree = NULL; // decompose if ( vTree == NULL ) vTree = Vec_IntAlloc( 12 ); if ( !Ivy_TruthDsd( uTruth, vTree ) ) { // printf( "Undecomposable\n" ); } else { // nTruthDsd++; printf( "%5d : ", Counter++ ); Extra_PrintBinary( stdout, &uTruth, 32 ); printf( " " ); Ivy_TruthDsdPrint( stdout, vTree ); if ( uTruth != Ivy_TruthDsdCompute(vTree) ) printf( "Verification failed.\n" ); } // Vec_IntFree( vTree ); } #if 0 /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_TruthTest() { FILE * pFile; char Buffer[100]; unsigned uTruth; int i; pFile = fopen( "npn4.txt", "r" ); for ( i = 0; i < 222; i++ ) // pFile = fopen( "npn5.txt", "r" ); // for ( i = 0; i < 616126; i++ ) { fscanf( pFile, "%s", Buffer ); Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 ); // Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 ); uTruth |= (uTruth << 16); // uTruth = ~uTruth; Ivy_TruthTestOne( uTruth ); } fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_TruthTest3() { FILE * pFile; char Buffer[100]; unsigned uTruth; int i; pFile = fopen( "npn3.txt", "r" ); for ( i = 0; i < 14; i++ ) { fscanf( pFile, "%s", Buffer ); Extra_ReadHexadecimal( &uTruth, Buffer+2, 3 ); uTruth = uTruth | (uTruth << 8) | (uTruth << 16) | (uTruth << 24); Ivy_TruthTestOne( uTruth ); } fclose( pFile ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_TruthTest5() { FILE * pFile; char Buffer[100]; unsigned uTruth; int i; // pFile = fopen( "npn4.txt", "r" ); // for ( i = 0; i < 222; i++ ) pFile = fopen( "npn5.txt", "r" ); for ( i = 0; i < 616126; i++ ) { fscanf( pFile, "%s", Buffer ); // Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 ); Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 ); // uTruth |= (uTruth << 16); // uTruth = ~uTruth; Ivy_TruthTestOne( uTruth ); } fclose( pFile ); } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyFanout.c000066400000000000000000000225651477524141600165000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyFanout.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Representation of the fanouts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyFanout.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // getting hold of the next fanout of the node static inline Ivy_Obj_t * Ivy_ObjNextFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) { assert( !Ivy_IsComplement(pObj) ); assert( !Ivy_IsComplement(pFanout) ); if ( pFanout == NULL ) return NULL; if ( Ivy_ObjFanin0(pFanout) == pObj ) return pFanout->pNextFan0; assert( Ivy_ObjFanin1(pFanout) == pObj ); return pFanout->pNextFan1; } // getting hold of the previous fanout of the node static inline Ivy_Obj_t * Ivy_ObjPrevFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) { assert( !Ivy_IsComplement(pObj) ); assert( !Ivy_IsComplement(pFanout) ); if ( pFanout == NULL ) return NULL; if ( Ivy_ObjFanin0(pFanout) == pObj ) return pFanout->pPrevFan0; assert( Ivy_ObjFanin1(pFanout) == pObj ); return pFanout->pPrevFan1; } // getting hold of the place where the next fanout will be attached static inline Ivy_Obj_t ** Ivy_ObjNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) { assert( !Ivy_IsComplement(pObj) ); assert( !Ivy_IsComplement(pFanout) ); if ( Ivy_ObjFanin0(pFanout) == pObj ) return &pFanout->pNextFan0; assert( Ivy_ObjFanin1(pFanout) == pObj ); return &pFanout->pNextFan1; } // getting hold of the place where the next fanout will be attached static inline Ivy_Obj_t ** Ivy_ObjPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) { assert( !Ivy_IsComplement(pObj) ); assert( !Ivy_IsComplement(pFanout) ); if ( Ivy_ObjFanin0(pFanout) == pObj ) return &pFanout->pPrevFan0; assert( Ivy_ObjFanin1(pFanout) == pObj ); return &pFanout->pPrevFan1; } // getting hold of the place where the next fanout will be attached static inline Ivy_Obj_t ** Ivy_ObjPrevNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) { Ivy_Obj_t * pTemp; assert( !Ivy_IsComplement(pObj) ); assert( !Ivy_IsComplement(pFanout) ); pTemp = Ivy_ObjPrevFanout(pObj, pFanout); if ( pTemp == NULL ) return &pObj->pFanout; if ( Ivy_ObjFanin0(pTemp) == pObj ) return &pTemp->pNextFan0; assert( Ivy_ObjFanin1(pTemp) == pObj ); return &pTemp->pNextFan1; } // getting hold of the place where the next fanout will be attached static inline Ivy_Obj_t ** Ivy_ObjNextPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) { Ivy_Obj_t * pTemp; assert( !Ivy_IsComplement(pObj) ); assert( !Ivy_IsComplement(pFanout) ); pTemp = Ivy_ObjNextFanout(pObj, pFanout); if ( pTemp == NULL ) return NULL; if ( Ivy_ObjFanin0(pTemp) == pObj ) return &pTemp->pPrevFan0; assert( Ivy_ObjFanin1(pTemp) == pObj ); return &pTemp->pPrevFan1; } // iterator through the fanouts of the node #define Ivy_ObjForEachFanoutInt( pObj, pFanout ) \ for ( pFanout = (pObj)->pFanout; pFanout; \ pFanout = Ivy_ObjNextFanout(pObj, pFanout) ) // safe iterator through the fanouts of the node #define Ivy_ObjForEachFanoutIntSafe( pObj, pFanout, pFanout2 ) \ for ( pFanout = (pObj)->pFanout, \ pFanout2 = Ivy_ObjNextFanout(pObj, pFanout); \ pFanout; \ pFanout = pFanout2, \ pFanout2 = Ivy_ObjNextFanout(pObj, pFanout) ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the fanout representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManStartFanout( Ivy_Man_t * p ) { Ivy_Obj_t * pObj; int i; assert( !p->fFanout ); p->fFanout = 1; Ivy_ManForEachObj( p, pObj, i ) { if ( Ivy_ObjFanin0(pObj) ) Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj ); if ( Ivy_ObjFanin1(pObj) ) Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj ); } } /**Function************************************************************* Synopsis [Stops the fanout representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManStopFanout( Ivy_Man_t * p ) { Ivy_Obj_t * pObj; int i; assert( p->fFanout ); p->fFanout = 0; Ivy_ManForEachObj( p, pObj, i ) pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; } /**Function************************************************************* Synopsis [Add the fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout ) { assert( p->fFanout ); if ( pFanin->pFanout ) { *Ivy_ObjNextFanoutPlace(pFanin, pFanout) = pFanin->pFanout; *Ivy_ObjPrevFanoutPlace(pFanin, pFanin->pFanout) = pFanout; } pFanin->pFanout = pFanout; } /**Function************************************************************* Synopsis [Removes the fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout ) { Ivy_Obj_t ** ppPlace1, ** ppPlace2, ** ppPlaceN; assert( pFanin->pFanout != NULL ); ppPlace1 = Ivy_ObjNextFanoutPlace(pFanin, pFanout); ppPlaceN = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanout); assert( *ppPlaceN == pFanout ); if ( ppPlaceN ) *ppPlaceN = *ppPlace1; ppPlace2 = Ivy_ObjPrevFanoutPlace(pFanin, pFanout); ppPlaceN = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanout); assert( ppPlaceN == NULL || *ppPlaceN == pFanout ); if ( ppPlaceN ) *ppPlaceN = *ppPlace2; *ppPlace1 = NULL; *ppPlace2 = NULL; } /**Function************************************************************* Synopsis [Replaces the fanout of pOld to be pFanoutNew.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew ) { Ivy_Obj_t ** ppPlace; ppPlace = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanoutOld); assert( *ppPlace == pFanoutOld ); if ( ppPlace ) *ppPlace = pFanoutNew; ppPlace = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanoutOld); assert( ppPlace == NULL || *ppPlace == pFanoutOld ); if ( ppPlace ) *ppPlace = pFanoutNew; // assuming that pFanoutNew already points to the next fanout } /**Function************************************************************* Synopsis [Starts iteration through the fanouts.] Description [Copies the currently available fanouts into the array.] SideEffects [Can be used while the fanouts are being removed.] SeeAlso [] ***********************************************************************/ void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray ) { Ivy_Obj_t * pFanout; assert( p->fFanout ); assert( !Ivy_IsComplement(pObj) ); Vec_PtrClear( vArray ); Ivy_ObjForEachFanoutInt( pObj, pFanout ) Vec_PtrPush( vArray, pFanout ); } /**Function************************************************************* Synopsis [Reads one fanout.] Description [Returns fanout if there is only one fanout.] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return pObj->pFanout; } /**Function************************************************************* Synopsis [Reads one fanout.] Description [Returns fanout if there is only one fanout.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { Ivy_Obj_t * pFanout; int Counter = 0; Ivy_ObjForEachFanoutInt( pObj, pFanout ) Counter++; return Counter; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyFastMap.c000066400000000000000000001367221477524141600166000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyFastMap.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Fast FPGA mapping.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyFastMap.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define IVY_INFINITY 10000 typedef struct Ivy_SuppMan_t_ Ivy_SuppMan_t; struct Ivy_SuppMan_t_ { int nLimit; // the limit on the number of inputs int nObjs; // the number of entries int nSize; // size of each entry in bytes char * pMem; // memory allocated Vec_Vec_t * vLuts; // the array of nodes used in the mapping }; typedef struct Ivy_Supp_t_ Ivy_Supp_t; struct Ivy_Supp_t_ { char nSize; // the number of support nodes char fMark; // multipurpose mask char fMark2; // multipurpose mask char fMark3; // multipurpose mask int nRefs; // the number of references short Delay; // the delay of the node short DelayR; // the reverse delay of the node int pArray[0]; // the support nodes }; static inline Ivy_Supp_t * Ivy_ObjSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) { return (Ivy_Supp_t *)(((Ivy_SuppMan_t*)pAig->pData)->pMem + pObj->Id * ((Ivy_SuppMan_t*)pAig->pData)->nSize); } static inline Ivy_Supp_t * Ivy_ObjSuppStart( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) { Ivy_Supp_t * pSupp; pSupp = Ivy_ObjSupp( pAig, pObj ); pSupp->fMark = 0; pSupp->Delay = 0; pSupp->nSize = 1; pSupp->pArray[0] = pObj->Id; return pSupp; } static void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, abctime Time, char * pStr ); static int Ivy_FastMapDelay( Ivy_Man_t * pAig ); static int Ivy_FastMapArea( Ivy_Man_t * pAig ); static void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ); static void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ); static int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit ); static void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter ); static void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit ); static int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); static int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); static int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); static void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ); static int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); static int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); extern abctime s_MappingTime; extern int s_MappingMem; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs fast K-LUT mapping of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose ) { Ivy_SuppMan_t * pMan; Ivy_Obj_t * pObj; int i, Delay, Area; abctime clk, clkTotal = Abc_Clock(); // start the memory for supports pMan = ABC_ALLOC( Ivy_SuppMan_t, 1 ); memset( pMan, 0, sizeof(Ivy_SuppMan_t) ); pMan->nLimit = nLimit; pMan->nObjs = Ivy_ManObjIdMax(pAig) + 1; pMan->nSize = sizeof(Ivy_Supp_t) + nLimit * sizeof(int); pMan->pMem = (char *)ABC_ALLOC( char, pMan->nObjs * pMan->nSize ); memset( pMan->pMem, 0, pMan->nObjs * pMan->nSize ); pMan->vLuts = Vec_VecAlloc( 100 ); pAig->pData = pMan; clk = Abc_Clock(); // set the PI mapping Ivy_ObjSuppStart( pAig, Ivy_ManConst1(pAig) ); Ivy_ManForEachPi( pAig, pObj, i ) Ivy_ObjSuppStart( pAig, pObj ); // iterate through all nodes in the topological order Ivy_ManForEachNode( pAig, pObj, i ) Ivy_FastMapNode( pAig, pObj, nLimit ); // find the best arrival time and area Delay = Ivy_FastMapDelay( pAig ); Area = Ivy_FastMapArea(pAig); if ( fVerbose ) Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Delay oriented mapping: " ); // 2-1-2 (doing 2-1-2-1-2 improves 0.5%) if ( fRecovery ) { clk = Abc_Clock(); Ivy_FastMapRequired( pAig, Delay, 0 ); // remap the nodes Ivy_FastMapRecover( pAig, nLimit ); Delay = Ivy_FastMapDelay( pAig ); Area = Ivy_FastMapArea(pAig); if ( fVerbose ) Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Area recovery 2 : " ); clk = Abc_Clock(); Ivy_FastMapRequired( pAig, Delay, 0 ); // iterate through all nodes in the topological order Ivy_ManForEachNode( pAig, pObj, i ) Ivy_FastMapNodeArea( pAig, pObj, nLimit ); Delay = Ivy_FastMapDelay( pAig ); Area = Ivy_FastMapArea(pAig); if ( fVerbose ) Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Area recovery 1 : " ); clk = Abc_Clock(); Ivy_FastMapRequired( pAig, Delay, 0 ); // remap the nodes Ivy_FastMapRecover( pAig, nLimit ); Delay = Ivy_FastMapDelay( pAig ); Area = Ivy_FastMapArea(pAig); if ( fVerbose ) Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Area recovery 2 : " ); } s_MappingTime = Abc_Clock() - clkTotal; s_MappingMem = pMan->nObjs * pMan->nSize; /* { Vec_Ptr_t * vNodes; vNodes = Vec_PtrAlloc( 100 ); Vec_VecForEachEntry( Ivy_Obj_t *, pMan->vLuts, pObj, i, k ) Vec_PtrPush( vNodes, pObj ); Ivy_ManShow( pAig, 0, vNodes ); Vec_PtrFree( vNodes ); } */ } /**Function************************************************************* Synopsis [Cleans memory used for decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapStop( Ivy_Man_t * pAig ) { Ivy_SuppMan_t * p = (Ivy_SuppMan_t *)pAig->pData; Vec_VecFree( p->vLuts ); ABC_FREE( p->pMem ); ABC_FREE( p ); pAig->pData = NULL; } /**Function************************************************************* Synopsis [Prints statistics.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, abctime Time, char * pStr ) { printf( "%s : Delay = %3d. Area = %6d. ", pStr, Delay, Area ); ABC_PRT( "Time", Time ); } /**Function************************************************************* Synopsis [Computes delay after LUT mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FastMapDelay( Ivy_Man_t * pAig ) { Ivy_Supp_t * pSupp; Ivy_Obj_t * pObj; int i, DelayMax = 0; Ivy_ManForEachPo( pAig, pObj, i ) { pObj = Ivy_ObjFanin0(pObj); if ( !Ivy_ObjIsNode(pObj) ) continue; pSupp = Ivy_ObjSupp( pAig, pObj ); if ( DelayMax < pSupp->Delay ) DelayMax = pSupp->Delay; } return DelayMax; } /**Function************************************************************* Synopsis [Computes area after mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FastMapArea_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Vec_t * vLuts ) { Ivy_Supp_t * pSupp; int i, Counter; pSupp = Ivy_ObjSupp( pAig, pObj ); // skip visited nodes and PIs if ( pSupp->fMark || pSupp->nSize == 1 ) return 0; pSupp->fMark = 1; // compute the area of this node Counter = 0; for ( i = 0; i < pSupp->nSize; i++ ) Counter += Ivy_FastMapArea_rec( pAig, Ivy_ManObj(pAig, pSupp->pArray[i]), vLuts ); // add the node to the array of LUTs Vec_VecPush( vLuts, pSupp->Delay, pObj ); return 1 + Counter; } /**Function************************************************************* Synopsis [Computes area after mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FastMapArea( Ivy_Man_t * pAig ) { Vec_Vec_t * vLuts; Ivy_Obj_t * pObj; int i, Counter = 0; // get the array to store the nodes vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts; Vec_VecClear( vLuts ); // explore starting from each node Ivy_ManForEachPo( pAig, pObj, i ) Counter += Ivy_FastMapArea_rec( pAig, Ivy_ObjFanin0(pObj), vLuts ); // clean the marks Ivy_ManForEachNode( pAig, pObj, i ) Ivy_ObjSupp( pAig, pObj )->fMark = 0; return Counter; } /**Function************************************************************* Synopsis [Performs fast mapping for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ivy_ObjIsNodeInt1( Ivy_Obj_t * pObj ) { return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) == 1; } /**Function************************************************************* Synopsis [Performs fast mapping for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ivy_ObjIsNodeInt2( Ivy_Obj_t * pObj ) { return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) <= 2; } /**Function************************************************************* Synopsis [Performs fast mapping for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Vec_IntRemoveDup( int * pArray, int nSize ) { int i, k; if ( nSize < 2 ) return nSize; for ( i = k = 1; i < nSize; i++ ) if ( pArray[i] != pArray[i-1] ) pArray[k++] = pArray[i]; return k; } /**Function************************************************************* Synopsis [Performs fast mapping for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapNodeArea2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) { static int Store[32], StoreSize; static char Supp0[16], Supp1[16]; static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0; static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1; Ivy_Obj_t * pFanin0, * pFanin1; Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; int RetValue, DelayOld; assert( nLimit <= 32 ); assert( Ivy_ObjIsNode(pObj) ); // get the fanins pFanin0 = Ivy_ObjFanin0(pObj); pFanin1 = Ivy_ObjFanin1(pObj); // get the supports pSupp0 = Ivy_ObjSupp( pAig, pFanin0 ); pSupp1 = Ivy_ObjSupp( pAig, pFanin1 ); pSupp = Ivy_ObjSupp( pAig, pObj ); assert( pSupp->fMark == 0 ); // get the old delay of the node DelayOld = Ivy_FastMapNodeDelay(pAig, pObj); assert( DelayOld <= pSupp->DelayR ); // copy the current cut memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize ); StoreSize = pSupp->nSize; // get the fanin support if ( Ivy_ObjRefs(pFanin0) > 1 && pSupp0->Delay < pSupp->DelayR ) { pSupp0 = pTemp0; pSupp0->nSize = 1; pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); } // get the fanin support if ( Ivy_ObjRefs(pFanin1) > 1 && pSupp1->Delay < pSupp->DelayR ) { pSupp1 = pTemp1; pSupp1->nSize = 1; pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); } // merge the cuts if ( pSupp0->nSize < pSupp1->nSize ) RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); else RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); if ( !RetValue ) { pSupp->nSize = 2; pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); } // check the resulting delay pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj); if ( pSupp->Delay > pSupp->DelayR ) { pSupp->nSize = StoreSize; memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize ); pSupp->Delay = DelayOld; } } /**Function************************************************************* Synopsis [Performs fast mapping for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) { static int Store[32], StoreSize; static char Supp0[16], Supp1[16]; static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0; static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1; Ivy_Obj_t * pFanin0, * pFanin1; Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; int RetValue, DelayOld, RefsOld; int AreaBef, AreaAft; assert( nLimit <= 32 ); assert( Ivy_ObjIsNode(pObj) ); // get the fanins pFanin0 = Ivy_ObjFanin0(pObj); pFanin1 = Ivy_ObjFanin1(pObj); // get the supports pSupp0 = Ivy_ObjSupp( pAig, pFanin0 ); pSupp1 = Ivy_ObjSupp( pAig, pFanin1 ); pSupp = Ivy_ObjSupp( pAig, pObj ); assert( pSupp->fMark == 0 ); // get the area if ( pSupp->nRefs == 0 ) AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); else AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); // if ( AreaBef == 1 ) // return; // deref the cut if the node is refed if ( pSupp->nRefs != 0 ) Ivy_FastMapNodeDeref( pAig, pObj ); // get the old delay of the node DelayOld = Ivy_FastMapNodeDelay(pAig, pObj); assert( DelayOld <= pSupp->DelayR ); // copy the current cut memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize ); StoreSize = pSupp->nSize; // get the fanin support if ( Ivy_ObjRefs(pFanin0) > 2 && pSupp0->Delay < pSupp->DelayR ) // if ( pSupp0->nRefs > 0 && pSupp0->Delay < pSupp->DelayR ) // this leads to 2% worse results { pSupp0 = pTemp0; pSupp0->nSize = 1; pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); } // get the fanin support if ( Ivy_ObjRefs(pFanin1) > 2 && pSupp1->Delay < pSupp->DelayR ) // if ( pSupp1->nRefs > 0 && pSupp1->Delay < pSupp->DelayR ) { pSupp1 = pTemp1; pSupp1->nSize = 1; pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); } // merge the cuts if ( pSupp0->nSize < pSupp1->nSize ) RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); else RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); if ( !RetValue ) { pSupp->nSize = 2; pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); } // check the resulting delay pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj); RefsOld = pSupp->nRefs; pSupp->nRefs = 0; AreaAft = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); pSupp->nRefs = RefsOld; if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) // if ( pSupp->Delay > pSupp->DelayR ) { pSupp->nSize = StoreSize; memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize ); pSupp->Delay = DelayOld; // printf( "-" ); } // else // printf( "+" ); if ( pSupp->nRefs != 0 ) Ivy_FastMapNodeRef( pAig, pObj ); } /**Function************************************************************* Synopsis [Performs fast mapping for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) { Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; int fFaninParam = 2; int RetValue; assert( Ivy_ObjIsNode(pObj) ); // get the supports pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) ); pSupp = Ivy_ObjSupp( pAig, pObj ); pSupp->fMark = 0; // get the delays if ( pSupp0->Delay == pSupp1->Delay ) pSupp->Delay = (pSupp0->Delay == 0) ? pSupp0->Delay + 1: pSupp0->Delay; else if ( pSupp0->Delay > pSupp1->Delay ) { pSupp->Delay = pSupp0->Delay; pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); } else // if ( pSupp0->Delay < pSupp1->Delay ) { pSupp->Delay = pSupp1->Delay; pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); } // merge the cuts if ( pSupp0->nSize < pSupp1->nSize ) RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); else RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); if ( !RetValue ) { pSupp->Delay++; if ( fFaninParam == 2 ) { pSupp->nSize = 2; pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); } else if ( fFaninParam == 3 ) { Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB; pFanin0 = Ivy_ObjFanin0(pObj); pFanin1 = Ivy_ObjFanin1(pObj); pSupp->nSize = 0; // process the first fanin if ( Ivy_ObjIsNodeInt1(pFanin0) ) { pFaninA = Ivy_ObjFanin0(pFanin0); pFaninB = Ivy_ObjFanin1(pFanin0); if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0); else { pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA); pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB); } } else pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0); // process the second fanin if ( Ivy_ObjIsNodeInt1(pFanin1) ) { pFaninA = Ivy_ObjFanin0(pFanin1); pFaninB = Ivy_ObjFanin1(pFanin1); if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1); else { pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA); pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB); } } else pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1); // sort the fanins Vec_IntSelectSort( pSupp->pArray, pSupp->nSize ); pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize ); assert( pSupp->pArray[0] < pSupp->pArray[1] ); } else if ( fFaninParam == 4 ) { Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB; pFanin0 = Ivy_ObjFanin0(pObj); pFanin1 = Ivy_ObjFanin1(pObj); pSupp->nSize = 0; // consider the case when exactly one of them is internal if ( Ivy_ObjIsNodeInt1(pFanin0) ^ Ivy_ObjIsNodeInt1(pFanin1) ) { pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) ); if ( Ivy_ObjIsNodeInt1(pFanin0) && pSupp0->nSize < nLimit ) { pSupp->Delay = IVY_MAX( pSupp0->Delay, pSupp1->Delay + 1 ); pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); pSupp1->pArray[0] = Ivy_ObjId(pFanin1); // merge the cuts RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); assert( RetValue ); assert( pSupp->nSize > 1 ); return; } if ( Ivy_ObjIsNodeInt1(pFanin1) && pSupp1->nSize < nLimit ) { pSupp->Delay = IVY_MAX( pSupp1->Delay, pSupp0->Delay + 1 ); pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); pSupp0->pArray[0] = Ivy_ObjId(pFanin0); // merge the cuts RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); assert( RetValue ); assert( pSupp->nSize > 1 ); return; } } // process the first fanin if ( Ivy_ObjIsNodeInt1(pFanin0) ) { pFaninA = Ivy_ObjFanin0(pFanin0); pFaninB = Ivy_ObjFanin1(pFanin0); if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0); else { pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA); pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB); } } else pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0); // process the second fanin if ( Ivy_ObjIsNodeInt1(pFanin1) ) { pFaninA = Ivy_ObjFanin0(pFanin1); pFaninB = Ivy_ObjFanin1(pFanin1); if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1); else { pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA); pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB); } } else pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1); // sort the fanins Vec_IntSelectSort( pSupp->pArray, pSupp->nSize ); pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize ); assert( pSupp->pArray[0] < pSupp->pArray[1] ); assert( pSupp->nSize > 1 ); } } assert( pSupp->Delay > 0 ); } /**Function************************************************************* Synopsis [Merges two supports] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit ) { int i, k, c; assert( pSupp0->nSize >= pSupp1->nSize ); // the case of the largest cut sizes if ( pSupp0->nSize == nLimit && pSupp1->nSize == nLimit ) { for ( i = 0; i < pSupp0->nSize; i++ ) if ( pSupp0->pArray[i] != pSupp1->pArray[i] ) return 0; for ( i = 0; i < pSupp0->nSize; i++ ) pSupp->pArray[i] = pSupp0->pArray[i]; pSupp->nSize = pSupp0->nSize; return 1; } // the case when one of the cuts is the largest if ( pSupp0->nSize == nLimit ) { for ( i = 0; i < pSupp1->nSize; i++ ) { for ( k = pSupp0->nSize - 1; k >= 0; k-- ) if ( pSupp0->pArray[k] == pSupp1->pArray[i] ) break; if ( k == -1 ) // did not find return 0; } for ( i = 0; i < pSupp0->nSize; i++ ) pSupp->pArray[i] = pSupp0->pArray[i]; pSupp->nSize = pSupp0->nSize; return 1; } // compare two cuts with different numbers i = k = 0; for ( c = 0; c < nLimit; c++ ) { if ( k == pSupp1->nSize ) { if ( i == pSupp0->nSize ) { pSupp->nSize = c; return 1; } pSupp->pArray[c] = pSupp0->pArray[i++]; continue; } if ( i == pSupp0->nSize ) { if ( k == pSupp1->nSize ) { pSupp->nSize = c; return 1; } pSupp->pArray[c] = pSupp1->pArray[k++]; continue; } if ( pSupp0->pArray[i] < pSupp1->pArray[k] ) { pSupp->pArray[c] = pSupp0->pArray[i++]; continue; } if ( pSupp0->pArray[i] > pSupp1->pArray[k] ) { pSupp->pArray[c] = pSupp1->pArray[k++]; continue; } pSupp->pArray[c] = pSupp0->pArray[i++]; k++; } if ( i < pSupp0->nSize || k < pSupp1->nSize ) return 0; pSupp->nSize = c; return 1; } /**Function************************************************************* Synopsis [Creates integer vector with the support of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves ) { Ivy_Supp_t * pSupp; pSupp = Ivy_ObjSupp( pAig, pObj ); vLeaves->nCap = 8; vLeaves->nSize = pSupp->nSize; vLeaves->pArray = pSupp->pArray; } /**Function************************************************************* Synopsis [Sets the required times of the intermediate nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapRequired_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Ivy_Obj_t * pRoot, int DelayR ) { Ivy_Supp_t * pSupp; pSupp = Ivy_ObjSupp( pAig, pObj ); if ( pObj != pRoot && (pSupp->nRefs > 0 || Ivy_ObjIsCi(pObj)) ) return; Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin0(pObj), pRoot, DelayR ); Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin1(pObj), pRoot, DelayR ); // assert( pObj == pRoot || pSupp->DelayR == IVY_INFINITY ); pSupp->DelayR = DelayR; } /**Function************************************************************* Synopsis [Computes the required times for each node.] Description [Sets reference counters for each node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter ) { Vec_Vec_t * vLuts; Vec_Ptr_t * vNodes; Ivy_Obj_t * pObj; Ivy_Supp_t * pSupp, * pSuppF; int i, k, c; // clean the required times Ivy_ManForEachPi( pAig, pObj, i ) { pSupp = Ivy_ObjSupp( pAig, pObj ); pSupp->DelayR = IVY_INFINITY; pSupp->nRefs = 0; } Ivy_ManForEachNode( pAig, pObj, i ) { pSupp = Ivy_ObjSupp( pAig, pObj ); pSupp->DelayR = IVY_INFINITY; pSupp->nRefs = 0; } // set the required times of the POs Ivy_ManForEachPo( pAig, pObj, i ) { pSupp = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); pSupp->DelayR = Delay; pSupp->nRefs++; } // get the levelized nodes used in the mapping vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts; // propagate the required times Vec_VecForEachLevelReverse( vLuts, vNodes, i ) Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, k ) { pSupp = Ivy_ObjSupp( pAig, pObj ); assert( pSupp->nRefs > 0 ); for ( c = 0; c < pSupp->nSize; c++ ) { pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) ); pSuppF->DelayR = IVY_MIN( pSuppF->DelayR, pSupp->DelayR - 1 ); pSuppF->nRefs++; } } /* // print out some of the required times Ivy_ManForEachPi( pAig, pObj, i ) { pSupp = Ivy_ObjSupp( pAig, pObj ); printf( "%d ", pSupp->DelayR ); } printf( "\n" ); */ if ( fSetInter ) { // set the required times of the intermediate nodes Vec_VecForEachLevelReverse( vLuts, vNodes, i ) Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, k ) { pSupp = Ivy_ObjSupp( pAig, pObj ); Ivy_FastMapRequired_rec( pAig, pObj, pObj, pSupp->DelayR ); } // make sure that all required times are assigned Ivy_ManForEachNode( pAig, pObj, i ) { pSupp = Ivy_ObjSupp( pAig, pObj ); assert( pSupp->DelayR < IVY_INFINITY ); } } } /**Function************************************************************* Synopsis [Performs area recovery for each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit ) { Vec_Ptr_t * vFront, * vFrontOld; Ivy_Obj_t * pObj; int i; vFront = Vec_PtrAlloc( nLimit ); vFrontOld = Vec_PtrAlloc( nLimit ); Ivy_ManCleanTravId( pAig ); // iterate through all nodes in the topological order Ivy_ManForEachNode( pAig, pObj, i ) Ivy_FastMapNodeRecover( pAig, pObj, nLimit, vFront, vFrontOld ); Vec_PtrFree( vFrontOld ); Vec_PtrFree( vFront ); } /**Function************************************************************* Synopsis [Computes the delay of the cut rooted at this node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) { Ivy_Supp_t * pSupp, * pSuppF; int c, Delay = 0; pSupp = Ivy_ObjSupp( pAig, pObj ); for ( c = 0; c < pSupp->nSize; c++ ) { pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) ); Delay = IVY_MAX( Delay, pSuppF->Delay ); } return 1 + Delay; } /**function************************************************************* synopsis [References the cut.] description [This procedure is similar to the procedure NodeReclaim.] sideeffects [] seealso [] ***********************************************************************/ int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) { Ivy_Supp_t * pSupp, * pSuppF; Ivy_Obj_t * pNodeChild; int aArea, i; // start the area of this cut aArea = 1; // go through the children pSupp = Ivy_ObjSupp( pAig, pObj ); assert( pSupp->nSize > 1 ); for ( i = 0; i < pSupp->nSize; i++ ) { pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]); pSuppF = Ivy_ObjSupp( pAig, pNodeChild ); assert( pSuppF->nRefs >= 0 ); if ( pSuppF->nRefs++ > 0 ) continue; if ( pSuppF->nSize == 1 ) continue; aArea += Ivy_FastMapNodeRef( pAig, pNodeChild ); } return aArea; } /**function************************************************************* synopsis [Dereferences the cut.] description [This procedure is similar to the procedure NodeRecusiveDeref.] sideeffects [] seealso [] ***********************************************************************/ int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) { Ivy_Supp_t * pSupp, * pSuppF; Ivy_Obj_t * pNodeChild; int aArea, i; // start the area of this cut aArea = 1; // go through the children pSupp = Ivy_ObjSupp( pAig, pObj ); assert( pSupp->nSize > 1 ); for ( i = 0; i < pSupp->nSize; i++ ) { pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]); pSuppF = Ivy_ObjSupp( pAig, pNodeChild ); assert( pSuppF->nRefs > 0 ); if ( --pSuppF->nRefs > 0 ) continue; if ( pSuppF->nSize == 1 ) continue; aArea += Ivy_FastMapNodeDeref( pAig, pNodeChild ); } return aArea; } /**function************************************************************* synopsis [Computes the exact area associated with the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) { Ivy_Supp_t * pSupp; int aResult, aResult2; if ( Ivy_ObjIsCi(pObj) ) return 0; assert( Ivy_ObjIsNode(pObj) ); pSupp = Ivy_ObjSupp( pAig, pObj ); assert( pSupp->nRefs > 0 ); aResult = Ivy_FastMapNodeDeref( pAig, pObj ); aResult2 = Ivy_FastMapNodeRef( pAig, pObj ); assert( aResult == aResult2 ); return aResult; } /**function************************************************************* synopsis [Computes the exact area associated with the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) { Ivy_Supp_t * pSupp; int aResult, aResult2; if ( Ivy_ObjIsCi(pObj) ) return 0; assert( Ivy_ObjIsNode(pObj) ); pSupp = Ivy_ObjSupp( pAig, pObj ); assert( pSupp->nRefs == 0 ); aResult2 = Ivy_FastMapNodeRef( pAig, pObj ); aResult = Ivy_FastMapNodeDeref( pAig, pObj ); assert( aResult == aResult2 ); return aResult; } /**Function************************************************************* Synopsis [Counts the number of nodes with no external fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FastMapCutCost( Ivy_Man_t * pAig, Vec_Ptr_t * vFront ) { Ivy_Supp_t * pSuppF; Ivy_Obj_t * pFanin; int i, Counter = 0; Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i ) { pSuppF = Ivy_ObjSupp( pAig, pFanin ); if ( pSuppF->nRefs == 0 ) Counter++; } return Counter; } /**Function************************************************************* Synopsis [Performs area recovery for each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapMark_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) { if ( Ivy_ObjIsTravIdCurrent(pAig, pObj) ) return; assert( Ivy_ObjIsNode(pObj) ); Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin0(pObj) ); Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin1(pObj) ); Ivy_ObjSetTravIdCurrent(pAig, pObj); } /**Function************************************************************* Synopsis [Returns 1 if the number of fanins will grow.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FastMapNodeWillGrow( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) { Ivy_Obj_t * pFanin0, * pFanin1; assert( Ivy_ObjIsNode(pObj) ); pFanin0 = Ivy_ObjFanin0(pObj); pFanin1 = Ivy_ObjFanin1(pObj); return !Ivy_ObjIsTravIdCurrent(pAig, pFanin0) && !Ivy_ObjIsTravIdCurrent(pAig, pFanin1); } /**Function************************************************************* Synopsis [Returns the increase in the number of fanins with no external refs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FastMapNodeFaninCost( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) { Ivy_Supp_t * pSuppF; Ivy_Obj_t * pFanin; int Counter = 0; assert( Ivy_ObjIsNode(pObj) ); // check if the node has external refs pSuppF = Ivy_ObjSupp( pAig, pObj ); if ( pSuppF->nRefs == 0 ) Counter--; // increment the number of fanins without external refs pFanin = Ivy_ObjFanin0(pObj); pSuppF = Ivy_ObjSupp( pAig, pFanin ); if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 ) Counter++; // increment the number of fanins without external refs pFanin = Ivy_ObjFanin1(pObj); pSuppF = Ivy_ObjSupp( pAig, pFanin ); if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Updates the frontier.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapNodeFaninUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront ) { Ivy_Obj_t * pFanin; assert( Ivy_ObjIsNode(pObj) ); Vec_PtrRemove( vFront, pObj ); pFanin = Ivy_ObjFanin0(pObj); if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) ) { Ivy_ObjSetTravIdCurrent(pAig, pFanin); Vec_PtrPush( vFront, pFanin ); } pFanin = Ivy_ObjFanin1(pObj); if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) ) { Ivy_ObjSetTravIdCurrent(pAig, pFanin); Vec_PtrPush( vFront, pFanin ); } } /**Function************************************************************* Synopsis [Compacts the number of external refs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FastMapNodeFaninCompact0( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) { Ivy_Obj_t * pFanin; int i; Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i ) { if ( Ivy_ObjIsCi(pFanin) ) continue; if ( Ivy_FastMapNodeWillGrow(pAig, pFanin) ) continue; if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 ) { Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); return 1; } } return 0; } /**Function************************************************************* Synopsis [Compacts the number of external refs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FastMapNodeFaninCompact1( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) { Ivy_Obj_t * pFanin; int i; Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i ) { if ( Ivy_ObjIsCi(pFanin) ) continue; if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) < 0 ) { Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); return 1; } } return 0; } /**Function************************************************************* Synopsis [Compacts the number of external refs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FastMapNodeFaninCompact2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) { Ivy_Obj_t * pFanin; int i; Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i ) { if ( Ivy_ObjIsCi(pFanin) ) continue; if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 ) { Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); return 1; } } return 0; } /**Function************************************************************* Synopsis [Compacts the number of external refs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FastMapNodeFaninCompact_int( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) { if ( Ivy_FastMapNodeFaninCompact0(pAig, pObj, nLimit, vFront) ) return 1; if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact1(pAig, pObj, nLimit, vFront) ) return 1; if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact2(pAig, pObj, nLimit, vFront) ) return 1; assert( Vec_PtrSize(vFront) <= nLimit ); return 0; } /**Function************************************************************* Synopsis [Compacts the number of external refs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapNodeFaninCompact( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) { while ( Ivy_FastMapNodeFaninCompact_int( pAig, pObj, nLimit, vFront ) ); } /**Function************************************************************* Synopsis [Prepares node mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapNodePrepare( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) { Ivy_Supp_t * pSupp; Ivy_Obj_t * pFanin; int i; pSupp = Ivy_ObjSupp( pAig, pObj ); // expand the cut downwards from the given place Vec_PtrClear( vFront ); Vec_PtrClear( vFrontOld ); Ivy_ManIncrementTravId( pAig ); for ( i = 0; i < pSupp->nSize; i++ ) { pFanin = Ivy_ManObj(pAig, pSupp->pArray[i]); Vec_PtrPush( vFront, pFanin ); Vec_PtrPush( vFrontOld, pFanin ); Ivy_ObjSetTravIdCurrent( pAig, pFanin ); } // mark the nodes in the cone Ivy_FastMapMark_rec( pAig, pObj ); } /**Function************************************************************* Synopsis [Updates the frontier.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapNodeUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront ) { Ivy_Supp_t * pSupp; Ivy_Obj_t * pFanin; int i; pSupp = Ivy_ObjSupp( pAig, pObj ); // deref node's cut Ivy_FastMapNodeDeref( pAig, pObj ); // update the node's cut pSupp->nSize = Vec_PtrSize(vFront); Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i ) pSupp->pArray[i] = pFanin->Id; // ref the new cut Ivy_FastMapNodeRef( pAig, pObj ); } /**Function************************************************************* Synopsis [Performs area recovery for each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapNodeRecover2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) { Ivy_Supp_t * pSupp; int CostBef, CostAft; int AreaBef, AreaAft; pSupp = Ivy_ObjSupp( pAig, pObj ); // if ( pSupp->nRefs == 0 ) // return; if ( pSupp->nRefs == 0 ) AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); else AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); // get the area if ( AreaBef == 1 ) return; if ( pSupp->nRefs == 0 ) { pSupp->nRefs = 1000000; Ivy_FastMapNodeRef( pAig, pObj ); } // the cut is non-trivial Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); // iteratively modify the cut CostBef = Ivy_FastMapCutCost( pAig, vFront ); Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); CostAft = Ivy_FastMapCutCost( pAig, vFront ); assert( CostBef >= CostAft ); // update the node Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); // get the new area AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); if ( AreaAft > AreaBef ) { Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); assert( AreaAft == AreaBef ); } if ( pSupp->nRefs == 1000000 ) { pSupp->nRefs = 0; Ivy_FastMapNodeDeref( pAig, pObj ); } } /**Function************************************************************* Synopsis [Performs area recovery for each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) { Ivy_Supp_t * pSupp; int CostBef, CostAft; int AreaBef, AreaAft; int DelayOld; pSupp = Ivy_ObjSupp( pAig, pObj ); DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); assert( pSupp->Delay <= pSupp->DelayR ); if ( pSupp->nRefs == 0 ) return; // get the area AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); // if ( AreaBef == 1 ) // return; // the cut is non-trivial Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); // iteratively modify the cut Ivy_FastMapNodeDeref( pAig, pObj ); CostBef = Ivy_FastMapCutCost( pAig, vFront ); Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); CostAft = Ivy_FastMapCutCost( pAig, vFront ); Ivy_FastMapNodeRef( pAig, pObj ); assert( CostBef >= CostAft ); // update the node Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); // get the new area AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) { Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); assert( AreaAft == AreaBef ); pSupp->Delay = DelayOld; } } /**Function************************************************************* Synopsis [Performs area recovery for each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FastMapNodeRecover4( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) { Ivy_Supp_t * pSupp; int CostBef, CostAft; int AreaBef, AreaAft; int DelayOld; pSupp = Ivy_ObjSupp( pAig, pObj ); DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); assert( pSupp->Delay <= pSupp->DelayR ); // if ( pSupp->nRefs == 0 ) // return; // AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); // get the area if ( pSupp->nRefs == 0 ) AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); else AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); if ( AreaBef == 1 ) return; if ( pSupp->nRefs == 0 ) { pSupp->nRefs = 1000000; Ivy_FastMapNodeRef( pAig, pObj ); } // the cut is non-trivial Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); // iteratively modify the cut CostBef = Ivy_FastMapCutCost( pAig, vFront ); Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); CostAft = Ivy_FastMapCutCost( pAig, vFront ); assert( CostBef >= CostAft ); // update the node Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); // get the new area AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) { Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); assert( AreaAft == AreaBef ); pSupp->Delay = DelayOld; } if ( pSupp->nRefs == 1000000 ) { pSupp->nRefs = 0; Ivy_FastMapNodeDeref( pAig, pObj ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyFraig.c000066400000000000000000003033211477524141600162640ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyFraig.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Functional reduction of AIGs] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyFraig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "sat/bsat/satSolver.h" #include "misc/extra/extra.h" #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Ivy_FraigMan_t_ Ivy_FraigMan_t; typedef struct Ivy_FraigSim_t_ Ivy_FraigSim_t; typedef struct Ivy_FraigList_t_ Ivy_FraigList_t; struct Ivy_FraigList_t_ { Ivy_Obj_t * pHead; Ivy_Obj_t * pTail; int nItems; }; struct Ivy_FraigSim_t_ { int Type; Ivy_FraigSim_t * pNext; Ivy_FraigSim_t * pFanin0; Ivy_FraigSim_t * pFanin1; unsigned pData[0]; }; struct Ivy_FraigMan_t_ { // general info Ivy_FraigParams_t * pParams; // various parameters // temporary backtrack limits because "ABC_INT64_T" cannot be defined in Ivy_FraigParams_t ... ABC_INT64_T nBTLimitGlobal; // global limit on the number of backtracks ABC_INT64_T nInsLimitGlobal;// global limit on the number of clause inspects // AIG manager Ivy_Man_t * pManAig; // the starting AIG manager Ivy_Man_t * pManFraig; // the final AIG manager // simulation information int nSimWords; // the number of words char * pSimWords; // the simulation info Ivy_FraigSim_t * pSimStart; // the list of simulation info for internal nodes // counter example storage int nPatWords; // the number of words in the counter example unsigned * pPatWords; // the counter example int * pPatScores; // the scores of each pattern // equivalence classes Ivy_FraigList_t lClasses; // equivalence classes Ivy_FraigList_t lCand; // candidatates int nPairs; // the number of pairs of nodes // equivalence checking sat_solver * pSat; // SAT solver int nSatVars; // the number of variables currently used Vec_Ptr_t * vPiVars; // the PIs of the cone used // other ProgressBar * pProgress; // statistics int nSimRounds; int nNodesMiter; int nClassesZero; int nClassesBeg; int nClassesEnd; int nPairsBeg; int nPairsEnd; int nSatCalls; int nSatCallsSat; int nSatCallsUnsat; int nSatProof; int nSatFails; int nSatFailsReal; // runtime abctime timeSim; abctime timeTrav; abctime timeSat; abctime timeSatUnsat; abctime timeSatSat; abctime timeSatFail; abctime timeRef; abctime timeTotal; abctime time1; abctime time2; }; typedef struct Prove_ParamsStruct_t_ Prove_Params_t; struct Prove_ParamsStruct_t_ { // general parameters int fUseFraiging; // enables fraiging int fUseRewriting; // enables rewriting int fUseBdds; // enables BDD construction when other methods fail int fVerbose; // prints verbose stats // iterations int nItersMax; // the number of iterations // mitering int nMiteringLimitStart; // starting mitering limit float nMiteringLimitMulti; // multiplicative coefficient to increase the limit in each iteration // rewriting int nRewritingLimitStart; // the number of rewriting iterations float nRewritingLimitMulti; // multiplicative coefficient to increase the limit in each iteration // fraiging int nFraigingLimitStart; // starting backtrack(conflict) limit float nFraigingLimitMulti; // multiplicative coefficient to increase the limit in each iteration // last-gasp BDD construction int nBddSizeLimit; // the number of BDD nodes when construction is aborted int fBddReorder; // enables dynamic BDD variable reordering // last-gasp mitering int nMiteringLimitLast; // final mitering limit // global SAT solver limits ABC_INT64_T nTotalBacktrackLimit; // global limit on the number of backtracks ABC_INT64_T nTotalInspectLimit; // global limit on the number of clause inspects // global resources applied ABC_INT64_T nTotalBacktracksMade; // the total number of backtracks made ABC_INT64_T nTotalInspectsMade; // the total number of inspects made }; static inline Ivy_FraigSim_t * Ivy_ObjSim( Ivy_Obj_t * pObj ) { return (Ivy_FraigSim_t *)pObj->pFanout; } static inline Ivy_Obj_t * Ivy_ObjClassNodeLast( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; } static inline Ivy_Obj_t * Ivy_ObjClassNodeRepr( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; } static inline Ivy_Obj_t * Ivy_ObjClassNodeNext( Ivy_Obj_t * pObj ) { return pObj->pNextFan1; } static inline Ivy_Obj_t * Ivy_ObjNodeHashNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; } static inline Ivy_Obj_t * Ivy_ObjEquivListNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; } static inline Ivy_Obj_t * Ivy_ObjEquivListPrev( Ivy_Obj_t * pObj ) { return pObj->pPrevFan1; } static inline Ivy_Obj_t * Ivy_ObjFraig( Ivy_Obj_t * pObj ) { return pObj->pEquiv; } static inline int Ivy_ObjSatNum( Ivy_Obj_t * pObj ) { return (int)(ABC_PTRUINT_T)pObj->pNextFan0; } static inline Vec_Ptr_t * Ivy_ObjFaninVec( Ivy_Obj_t * pObj ) { return (Vec_Ptr_t *)pObj->pNextFan1; } static inline void Ivy_ObjSetSim( Ivy_Obj_t * pObj, Ivy_FraigSim_t * pSim ) { pObj->pFanout = (Ivy_Obj_t *)pSim; } static inline void Ivy_ObjSetClassNodeLast( Ivy_Obj_t * pObj, Ivy_Obj_t * pLast ) { pObj->pNextFan0 = pLast; } static inline void Ivy_ObjSetClassNodeRepr( Ivy_Obj_t * pObj, Ivy_Obj_t * pRepr ) { pObj->pNextFan0 = pRepr; } static inline void Ivy_ObjSetClassNodeNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pNextFan1 = pNext; } static inline void Ivy_ObjSetNodeHashNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; } static inline void Ivy_ObjSetEquivListNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; } static inline void Ivy_ObjSetEquivListPrev( Ivy_Obj_t * pObj, Ivy_Obj_t * pPrev ) { pObj->pPrevFan1 = pPrev; } static inline void Ivy_ObjSetFraig( Ivy_Obj_t * pObj, Ivy_Obj_t * pNode ) { pObj->pEquiv = pNode; } static inline void Ivy_ObjSetSatNum( Ivy_Obj_t * pObj, int Num ) { pObj->pNextFan0 = (Ivy_Obj_t *)(ABC_PTRUINT_T)Num; } static inline void Ivy_ObjSetFaninVec( Ivy_Obj_t * pObj, Vec_Ptr_t * vFanins ) { pObj->pNextFan1 = (Ivy_Obj_t *)vFanins; } static inline unsigned Ivy_ObjRandomSim() { return (rand() << 24) ^ (rand() << 12) ^ rand(); } // iterate through equivalence classes #define Ivy_FraigForEachEquivClass( pList, pEnt ) \ for ( pEnt = pList; \ pEnt; \ pEnt = Ivy_ObjEquivListNext(pEnt) ) #define Ivy_FraigForEachEquivClassSafe( pList, pEnt, pEnt2 ) \ for ( pEnt = pList, \ pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL; \ pEnt; \ pEnt = pEnt2, \ pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL ) // iterate through nodes in one class #define Ivy_FraigForEachClassNode( pClass, pEnt ) \ for ( pEnt = pClass; \ pEnt; \ pEnt = Ivy_ObjClassNodeNext(pEnt) ) // iterate through nodes in the hash table #define Ivy_FraigForEachBinNode( pBin, pEnt ) \ for ( pEnt = pBin; \ pEnt; \ pEnt = Ivy_ObjNodeHashNext(pEnt) ) static Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); static Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); static Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, ABC_INT64_T nBTLimitGlobal, ABC_INT64_T nInsLimitGlobal, ABC_INT64_T * pnSatConfs, ABC_INT64_T * pnSatInspects ); static void Ivy_FraigPrint( Ivy_FraigMan_t * p ); static void Ivy_FraigStop( Ivy_FraigMan_t * p ); static void Ivy_FraigSimulate( Ivy_FraigMan_t * p ); static void Ivy_FraigSweep( Ivy_FraigMan_t * p ); static Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld ); static int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ); static int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ); static void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ); static int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ); static void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew ); static int Ivy_FraigMiterStatus( Ivy_Man_t * pMan ); static void Ivy_FraigMiterProve( Ivy_FraigMan_t * p ); static void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, abctime clk, int fVerbose ); static int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p ); static int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 ); static int Ivy_FraigCheckCone( Ivy_FraigMan_t * pGlo, Ivy_Man_t * p, Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2, int nConfLimit ); static ABC_INT64_T s_nBTLimitGlobal = 0; static ABC_INT64_T s_nInsLimitGlobal = 0; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Sets the default solving parameters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams ) { memset( pParams, 0, sizeof(Ivy_FraigParams_t) ); pParams->nSimWords = 32; // the number of words in the simulation info pParams->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached pParams->fPatScores = 0; // enables simulation pattern scoring pParams->MaxScore = 25; // max score after which resimulation is used pParams->fDoSparse = 1; // skips sparse functions // pParams->dActConeRatio = 0.05; // the ratio of cone to be bumped // pParams->dActConeBumpMax = 5.0; // the largest bump of activity pParams->dActConeRatio = 0.3; // the ratio of cone to be bumped pParams->dActConeBumpMax = 10.0; // the largest bump of activity pParams->nBTLimitNode = 100; // conflict limit at a node pParams->nBTLimitMiter = 500000; // conflict limit at an output // pParams->nBTLimitGlobal = 0; // conflict limit global // pParams->nInsLimitGlobal = 0; // inspection limit global } /**Function************************************************************* Synopsis [Performs combinational equivalence checking for the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars ) { Prove_Params_t * pParams = (Prove_Params_t *)pPars; Ivy_FraigParams_t Params, * pIvyParams = &Params; Ivy_Man_t * pManAig, * pManTemp; int RetValue, nIter; abctime clk;//, Counter; ABC_INT64_T nSatConfs = 0, nSatInspects = 0; // start the network and parameters pManAig = *ppManAig; Ivy_FraigParamsDefault( pIvyParams ); pIvyParams->fVerbose = pParams->fVerbose; pIvyParams->fProve = 1; if ( pParams->fVerbose ) { printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n", pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" ); printf( "Miter = %d (%3.1f). Rwr = %d (%3.1f). Fraig = %d (%3.1f). Last = %d.\n", pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti, pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti, pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti, pParams->nMiteringLimitLast ); } // if SAT only, solve without iteration if ( !pParams->fUseRewriting && !pParams->fUseFraiging ) { clk = Abc_Clock(); pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig); pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); RetValue = Ivy_FraigMiterStatus( pManAig ); Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); *ppManAig = pManAig; return RetValue; } if ( Ivy_ManNodeNum(pManAig) < 500 ) { // run the first mitering clk = Abc_Clock(); pIvyParams->nBTLimitMiter = pParams->nMiteringLimitStart / Ivy_ManPoNum(pManAig); pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); RetValue = Ivy_FraigMiterStatus( pManAig ); Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); if ( RetValue >= 0 ) { *ppManAig = pManAig; return RetValue; } } // check the current resource limits RetValue = -1; for ( nIter = 0; nIter < pParams->nItersMax; nIter++ ) { if ( pParams->fVerbose ) { printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1, (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) ); fflush( stdout ); } // try rewriting if ( pParams->fUseRewriting ) { // bug in Ivy_NodeFindCutsAll() when leaves are identical! /* clk = Abc_Clock(); Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter)); pManAig = Ivy_ManRwsat( pManAig, 0 ); RetValue = Ivy_FraigMiterStatus( pManAig ); Ivy_FraigMiterPrint( pManAig, "Rewriting ", clk, pParams->fVerbose ); */ } if ( RetValue >= 0 ) break; // catch the situation when ref pattern detects the bug RetValue = Ivy_FraigMiterStatus( pManAig ); if ( RetValue >= 0 ) break; // try fraiging followed by mitering if ( pParams->fUseFraiging ) { clk = Abc_Clock(); pIvyParams->nBTLimitNode = (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)); pIvyParams->nBTLimitMiter = 1 + (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)) / Ivy_ManPoNum(pManAig); pManAig = Ivy_FraigPerform_int( pManTemp = pManAig, pIvyParams, pParams->nTotalBacktrackLimit, pParams->nTotalInspectLimit, &nSatConfs, &nSatInspects ); Ivy_ManStop( pManTemp ); RetValue = Ivy_FraigMiterStatus( pManAig ); Ivy_FraigMiterPrint( pManAig, "Fraiging ", clk, pParams->fVerbose ); } if ( RetValue >= 0 ) break; // add to the number of backtracks and inspects pParams->nTotalBacktracksMade += nSatConfs; pParams->nTotalInspectsMade += nSatInspects; // check if global resource limit is reached if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) { printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); *ppManAig = pManAig; return -1; } } /* if ( RetValue < 0 ) { if ( pParams->fVerbose ) { printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast ); fflush( stdout ); } clk = Abc_Clock(); pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig); if ( pParams->nTotalBacktrackLimit ) s_nBTLimitGlobal = pParams->nTotalBacktrackLimit - pParams->nTotalBacktracksMade; if ( pParams->nTotalInspectLimit ) s_nInsLimitGlobal = pParams->nTotalInspectLimit - pParams->nTotalInspectsMade; pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); s_nBTLimitGlobal = 0; s_nInsLimitGlobal = 0; RetValue = Ivy_FraigMiterStatus( pManAig ); Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); // make sure that the sover never returns "undecided" when infinite resource limits are set if( RetValue == -1 && pParams->nTotalInspectLimit == 0 && pParams->nTotalBacktrackLimit == 0 ) { extern void Prove_ParamsPrint( Prove_Params_t * pParams ); Prove_ParamsPrint( pParams ); printf("ERROR: ABC has returned \"undecided\" in spite of no limits...\n"); exit(1); } } */ // assign the model if it was proved by rewriting (const 1 miter) if ( RetValue == 0 && pManAig->pData == NULL ) { pManAig->pData = ABC_ALLOC( int, Ivy_ManPiNum(pManAig) ); memset( pManAig->pData, 0, sizeof(int) * Ivy_ManPiNum(pManAig) ); } *ppManAig = pManAig; return RetValue; } /**Function************************************************************* Synopsis [Performs fraiging of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, ABC_INT64_T nBTLimitGlobal, ABC_INT64_T nInsLimitGlobal, ABC_INT64_T * pnSatConfs, ABC_INT64_T * pnSatInspects ) { Ivy_FraigMan_t * p; Ivy_Man_t * pManAigNew; abctime clk; if ( Ivy_ManNodeNum(pManAig) == 0 ) return Ivy_ManDup(pManAig); clk = Abc_Clock(); assert( Ivy_ManLatchNum(pManAig) == 0 ); p = Ivy_FraigStart( pManAig, pParams ); // set global limits p->nBTLimitGlobal = nBTLimitGlobal; p->nInsLimitGlobal = nInsLimitGlobal; Ivy_FraigSimulate( p ); Ivy_FraigSweep( p ); pManAigNew = p->pManFraig; p->timeTotal = Abc_Clock() - clk; if ( pnSatConfs ) *pnSatConfs = p->pSat? p->pSat->stats.conflicts : 0; if ( pnSatInspects ) *pnSatInspects = p->pSat? p->pSat->stats.inspects : 0; Ivy_FraigStop( p ); return pManAigNew; } /**Function************************************************************* Synopsis [Performs fraiging of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) { Ivy_FraigMan_t * p; Ivy_Man_t * pManAigNew; abctime clk; if ( Ivy_ManNodeNum(pManAig) == 0 ) return Ivy_ManDup(pManAig); clk = Abc_Clock(); assert( Ivy_ManLatchNum(pManAig) == 0 ); p = Ivy_FraigStart( pManAig, pParams ); Ivy_FraigSimulate( p ); Ivy_FraigSweep( p ); pManAigNew = p->pManFraig; p->timeTotal = Abc_Clock() - clk; Ivy_FraigStop( p ); return pManAigNew; } /**Function************************************************************* Synopsis [Applies brute-force SAT to the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) { Ivy_FraigMan_t * p; Ivy_Man_t * pManAigNew; Ivy_Obj_t * pObj; int i; abctime clk; clk = Abc_Clock(); assert( Ivy_ManLatchNum(pManAig) == 0 ); p = Ivy_FraigStartSimple( pManAig, pParams ); // set global limits p->nBTLimitGlobal = s_nBTLimitGlobal; p->nInsLimitGlobal = s_nInsLimitGlobal; // duplicate internal nodes Ivy_ManForEachNode( p->pManAig, pObj, i ) pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); // try to prove each output of the miter Ivy_FraigMiterProve( p ); // add the POs Ivy_ManForEachPo( p->pManAig, pObj, i ) Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) ); // clean the new manager Ivy_ManForEachObj( p->pManFraig, pObj, i ) { if ( Ivy_ObjFaninVec(pObj) ) Vec_PtrFree( Ivy_ObjFaninVec(pObj) ); pObj->pNextFan0 = pObj->pNextFan1 = NULL; } // remove dangling nodes Ivy_ManCleanup( p->pManFraig ); pManAigNew = p->pManFraig; p->timeTotal = Abc_Clock() - clk; //printf( "Final nodes = %6d. ", Ivy_ManNodeNum(pManAigNew) ); //ABC_PRT( "Time", p->timeTotal ); Ivy_FraigStop( p ); return pManAigNew; } /**Function************************************************************* Synopsis [Starts the fraiging manager without simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) { Ivy_FraigMan_t * p; // allocat the fraiging manager p = ABC_ALLOC( Ivy_FraigMan_t, 1 ); memset( p, 0, sizeof(Ivy_FraigMan_t) ); p->pParams = pParams; p->pManAig = pManAig; p->pManFraig = Ivy_ManStartFrom( pManAig ); p->vPiVars = Vec_PtrAlloc( 100 ); return p; } /**Function************************************************************* Synopsis [Starts the fraiging manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) { Ivy_FraigMan_t * p; Ivy_FraigSim_t * pSims; Ivy_Obj_t * pObj; int i, k, EntrySize; // clean the fanout representation Ivy_ManForEachObj( pManAig, pObj, i ) // pObj->pEquiv = pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; assert( !pObj->pEquiv && !pObj->pFanout ); // allocat the fraiging manager p = ABC_ALLOC( Ivy_FraigMan_t, 1 ); memset( p, 0, sizeof(Ivy_FraigMan_t) ); p->pParams = pParams; p->pManAig = pManAig; p->pManFraig = Ivy_ManStartFrom( pManAig ); // allocate simulation info p->nSimWords = pParams->nSimWords; // 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, (size_t)EntrySize ); k = 0; Ivy_ManForEachObj( pManAig, pObj, i ) { pSims = (Ivy_FraigSim_t *)(p->pSimWords + EntrySize * k++); pSims->pNext = NULL; if ( Ivy_ObjIsNode(pObj) ) { if ( p->pSimStart == NULL ) p->pSimStart = pSims; else ((Ivy_FraigSim_t *)(p->pSimWords + EntrySize * (k-2)))->pNext = pSims; pSims->pFanin0 = Ivy_ObjSim( Ivy_ObjFanin0(pObj) ); pSims->pFanin1 = Ivy_ObjSim( Ivy_ObjFanin1(pObj) ); pSims->Type = (Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) << 2) | (Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)) << 1) | pObj->fPhase; } else { pSims->pFanin0 = NULL; pSims->pFanin1 = NULL; pSims->Type = 0; } Ivy_ObjSetSim( pObj, pSims ); } assert( k == Ivy_ManObjNum(pManAig) ); // allocate storage for sim pattern p->nPatWords = Ivy_BitWordNum( Ivy_ManPiNum(pManAig) ); p->pPatWords = ABC_ALLOC( unsigned, p->nPatWords ); p->pPatScores = ABC_ALLOC( int, 32 * p->nSimWords ); p->vPiVars = Vec_PtrAlloc( 100 ); // set random number generator srand( 0xABCABC ); return p; } /**Function************************************************************* Synopsis [Stops the fraiging manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigStop( Ivy_FraigMan_t * p ) { if ( p->pParams->fVerbose ) Ivy_FraigPrint( p ); if ( p->vPiVars ) Vec_PtrFree( p->vPiVars ); if ( p->pSat ) sat_solver_delete( p->pSat ); ABC_FREE( p->pPatScores ); ABC_FREE( p->pPatWords ); ABC_FREE( p->pSimWords ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Prints stats for the fraiging manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigPrint( Ivy_FraigMan_t * p ) { double nMemory; nMemory = (double)Ivy_ManObjNum(p->pManAig)*p->nSimWords*sizeof(unsigned)/(1<<20); printf( "SimWords = %d. Rounds = %d. Mem = %0.2f MB. ", p->nSimWords, p->nSimRounds, nMemory ); printf( "Classes: Beg = %d. End = %d.\n", p->nClassesBeg, p->nClassesEnd ); // printf( "Limits: BTNode = %d. BTMiter = %d.\n", p->pParams->nBTLimitNode, p->pParams->nBTLimitMiter ); printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n", p->nSatProof, p->nSatCallsSat, p->nSatFails, p->nSatFailsReal, p->nClassesZero ); printf( "Final = %d. Miter = %d. Total = %d. Mux = %d. (Exor = %d.) SatVars = %d.\n", Ivy_ManNodeNum(p->pManFraig), p->nNodesMiter, Ivy_ManNodeNum(p->pManAig), 0, 0, p->nSatVars ); if ( p->pSat ) Sat_SolverPrintStats( stdout, p->pSat ); ABC_PRT( "AIG simulation ", p->timeSim ); ABC_PRT( "AIG traversal ", p->timeTrav ); ABC_PRT( "SAT solving ", p->timeSat ); ABC_PRT( " Unsat ", p->timeSatUnsat ); ABC_PRT( " Sat ", p->timeSatSat ); ABC_PRT( " Fail ", p->timeSatFail ); ABC_PRT( "Class refining ", p->timeRef ); ABC_PRT( "TOTAL RUNTIME ", p->timeTotal ); if ( p->time1 ) { ABC_PRT( "time1 ", p->time1 ); } } /**Function************************************************************* Synopsis [Assigns random patterns to the PI node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeAssignRandom( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) { Ivy_FraigSim_t * pSims; int i; assert( Ivy_ObjIsPi(pObj) ); pSims = Ivy_ObjSim(pObj); for ( i = 0; i < p->nSimWords; i++ ) pSims->pData[i] = Ivy_ObjRandomSim(); } /**Function************************************************************* Synopsis [Assigns constant patterns to the PI node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeAssignConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int fConst1 ) { Ivy_FraigSim_t * pSims; int i; assert( Ivy_ObjIsPi(pObj) ); pSims = Ivy_ObjSim(pObj); for ( i = 0; i < p->nSimWords; i++ ) pSims->pData[i] = fConst1? ~(unsigned)0 : 0; } /**Function************************************************************* Synopsis [Assings random simulation info for the PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigAssignRandom( Ivy_FraigMan_t * p ) { Ivy_Obj_t * pObj; int i; Ivy_ManForEachPi( p->pManAig, pObj, i ) Ivy_NodeAssignRandom( p, pObj ); } /**Function************************************************************* Synopsis [Assings distance-1 simulation info for the PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigAssignDist1( Ivy_FraigMan_t * p, unsigned * pPat ) { Ivy_Obj_t * pObj; int i, Limit; Ivy_ManForEachPi( p->pManAig, pObj, i ) { Ivy_NodeAssignConst( p, pObj, Ivy_InfoHasBit(pPat, i) ); // printf( "%d", Ivy_InfoHasBit(pPat, i) ); } // printf( "\n" ); Limit = IVY_MIN( Ivy_ManPiNum(p->pManAig), p->nSimWords * 32 - 1 ); for ( i = 0; i < Limit; i++ ) Ivy_InfoXorBit( Ivy_ObjSim( Ivy_ManPi(p->pManAig,i) )->pData, i+1 ); } /**Function************************************************************* Synopsis [Returns 1 if simulation info is composed of all zeros.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_NodeHasZeroSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) { Ivy_FraigSim_t * pSims; int i; pSims = Ivy_ObjSim(pObj); for ( i = 0; i < p->nSimWords; i++ ) if ( pSims->pData[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if simulation info is composed of all zeros.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeComplementSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) { Ivy_FraigSim_t * pSims; int i; pSims = Ivy_ObjSim(pObj); for ( i = 0; i < p->nSimWords; i++ ) pSims->pData[i] = ~pSims->pData[i]; } /**Function************************************************************* Synopsis [Returns 1 if simulation infos are equal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_NodeCompareSims( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) { Ivy_FraigSim_t * pSims0, * pSims1; int i; pSims0 = Ivy_ObjSim(pObj0); pSims1 = Ivy_ObjSim(pObj1); for ( i = 0; i < p->nSimWords; i++ ) if ( pSims0->pData[i] != pSims1->pData[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeSimulateSim( Ivy_FraigMan_t * p, Ivy_FraigSim_t * pSims ) { unsigned * pData, * pData0, * pData1; int i; pData = pSims->pData; pData0 = pSims->pFanin0->pData; pData1 = pSims->pFanin1->pData; switch( pSims->Type ) { case 0: for ( i = 0; i < p->nSimWords; i++ ) pData[i] = (pData0[i] & pData1[i]); break; case 1: for ( i = 0; i < p->nSimWords; i++ ) pData[i] = ~(pData0[i] & pData1[i]); break; case 2: for ( i = 0; i < p->nSimWords; i++ ) pData[i] = (pData0[i] & ~pData1[i]); break; case 3: for ( i = 0; i < p->nSimWords; i++ ) pData[i] = (~pData0[i] | pData1[i]); break; case 4: for ( i = 0; i < p->nSimWords; i++ ) pData[i] = (~pData0[i] & pData1[i]); break; case 5: for ( i = 0; i < p->nSimWords; i++ ) pData[i] = (pData0[i] | ~pData1[i]); break; case 6: for ( i = 0; i < p->nSimWords; i++ ) pData[i] = ~(pData0[i] | pData1[i]); break; case 7: for ( i = 0; i < p->nSimWords; i++ ) pData[i] = (pData0[i] | pData1[i]); break; } } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeSimulate( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) { Ivy_FraigSim_t * pSims, * pSims0, * pSims1; int fCompl, fCompl0, fCompl1, i; assert( !Ivy_IsComplement(pObj) ); // get hold of the simulation information pSims = Ivy_ObjSim(pObj); pSims0 = Ivy_ObjSim(Ivy_ObjFanin0(pObj)); pSims1 = Ivy_ObjSim(Ivy_ObjFanin1(pObj)); // get complemented attributes of the children using their random info fCompl = pObj->fPhase; fCompl0 = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)); fCompl1 = Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)); // simulate if ( fCompl0 && fCompl1 ) { if ( fCompl ) for ( i = 0; i < p->nSimWords; i++ ) pSims->pData[i] = (pSims0->pData[i] | pSims1->pData[i]); else for ( i = 0; i < p->nSimWords; i++ ) pSims->pData[i] = ~(pSims0->pData[i] | pSims1->pData[i]); } else if ( fCompl0 && !fCompl1 ) { if ( fCompl ) for ( i = 0; i < p->nSimWords; i++ ) pSims->pData[i] = (pSims0->pData[i] | ~pSims1->pData[i]); else for ( i = 0; i < p->nSimWords; i++ ) pSims->pData[i] = (~pSims0->pData[i] & pSims1->pData[i]); } else if ( !fCompl0 && fCompl1 ) { if ( fCompl ) for ( i = 0; i < p->nSimWords; i++ ) pSims->pData[i] = (~pSims0->pData[i] | pSims1->pData[i]); else for ( i = 0; i < p->nSimWords; i++ ) pSims->pData[i] = (pSims0->pData[i] & ~pSims1->pData[i]); } else // if ( !fCompl0 && !fCompl1 ) { if ( fCompl ) for ( i = 0; i < p->nSimWords; i++ ) pSims->pData[i] = ~(pSims0->pData[i] & pSims1->pData[i]); else for ( i = 0; i < p->nSimWords; i++ ) pSims->pData[i] = (pSims0->pData[i] & pSims1->pData[i]); } } /**Function************************************************************* Synopsis [Computes hash value using simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Ivy_NodeHash( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) { static int s_FPrimes[128] = { 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 }; Ivy_FraigSim_t * pSims; unsigned uHash; int i; assert( p->nSimWords <= 128 ); uHash = 0; pSims = Ivy_ObjSim(pObj); for ( i = 0; i < p->nSimWords; i++ ) uHash ^= pSims->pData[i] * s_FPrimes[i]; return uHash; } /**Function************************************************************* Synopsis [Simulates AIG manager.] Description [Assumes that the PI simulation info is attached.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigSimulateOne( Ivy_FraigMan_t * p ) { Ivy_Obj_t * pObj; int i; abctime clk; clk = Abc_Clock(); Ivy_ManForEachNode( p->pManAig, pObj, i ) { Ivy_NodeSimulate( p, pObj ); /* if ( Ivy_ObjFraig(pObj) == NULL ) printf( "%3d --- -- %d : ", pObj->Id, pObj->fPhase ); else printf( "%3d %3d %2d %d : ", pObj->Id, Ivy_Regular(Ivy_ObjFraig(pObj))->Id, Ivy_ObjSatNum(Ivy_Regular(Ivy_ObjFraig(pObj))), pObj->fPhase ); Extra_PrintBinary( stdout, Ivy_ObjSim(pObj), 30 ); printf( "\n" ); */ } p->timeSim += Abc_Clock() - clk; p->nSimRounds++; } /**Function************************************************************* Synopsis [Simulates AIG manager.] Description [Assumes that the PI simulation info is attached.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigSimulateOneSim( Ivy_FraigMan_t * p ) { Ivy_FraigSim_t * pSims; abctime clk; clk = Abc_Clock(); for ( pSims = p->pSimStart; pSims; pSims = pSims->pNext ) Ivy_NodeSimulateSim( p, pSims ); p->timeSim += Abc_Clock() - clk; p->nSimRounds++; } /**Function************************************************************* Synopsis [Adds one node to the equivalence class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeAddToClass( Ivy_Obj_t * pClass, Ivy_Obj_t * pObj ) { if ( Ivy_ObjClassNodeNext(pClass) == NULL ) Ivy_ObjSetClassNodeNext( pClass, pObj ); else Ivy_ObjSetClassNodeNext( Ivy_ObjClassNodeLast(pClass), pObj ); Ivy_ObjSetClassNodeLast( pClass, pObj ); Ivy_ObjSetClassNodeRepr( pObj, pClass ); Ivy_ObjSetClassNodeNext( pObj, NULL ); } /**Function************************************************************* Synopsis [Adds equivalence class to the list of classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigAddClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass ) { if ( pList->pHead == NULL ) { pList->pHead = pClass; pList->pTail = pClass; Ivy_ObjSetEquivListPrev( pClass, NULL ); Ivy_ObjSetEquivListNext( pClass, NULL ); } else { Ivy_ObjSetEquivListNext( pList->pTail, pClass ); Ivy_ObjSetEquivListPrev( pClass, pList->pTail ); Ivy_ObjSetEquivListNext( pClass, NULL ); pList->pTail = pClass; } pList->nItems++; } /**Function************************************************************* Synopsis [Updates the list of classes after base class has split.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigInsertClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pBase, Ivy_Obj_t * pClass ) { Ivy_ObjSetEquivListPrev( pClass, pBase ); Ivy_ObjSetEquivListNext( pClass, Ivy_ObjEquivListNext(pBase) ); if ( Ivy_ObjEquivListNext(pBase) ) Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pBase), pClass ); Ivy_ObjSetEquivListNext( pBase, pClass ); if ( pList->pTail == pBase ) pList->pTail = pClass; pList->nItems++; } /**Function************************************************************* Synopsis [Removes equivalence class from the list of classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigRemoveClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass ) { if ( pList->pHead == pClass ) pList->pHead = Ivy_ObjEquivListNext(pClass); if ( pList->pTail == pClass ) pList->pTail = Ivy_ObjEquivListPrev(pClass); if ( Ivy_ObjEquivListPrev(pClass) ) Ivy_ObjSetEquivListNext( Ivy_ObjEquivListPrev(pClass), Ivy_ObjEquivListNext(pClass) ); if ( Ivy_ObjEquivListNext(pClass) ) Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pClass), Ivy_ObjEquivListPrev(pClass) ); Ivy_ObjSetEquivListNext( pClass, NULL ); Ivy_ObjSetEquivListPrev( pClass, NULL ); pClass->fMarkA = 0; pList->nItems--; } /**Function************************************************************* Synopsis [Count the number of pairs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FraigCountPairsClasses( Ivy_FraigMan_t * p ) { Ivy_Obj_t * pClass, * pNode; int nPairs = 0, nNodes; return nPairs; Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass ) { nNodes = 0; Ivy_FraigForEachClassNode( pClass, pNode ) nNodes++; nPairs += nNodes * (nNodes - 1) / 2; } return nPairs; } /**Function************************************************************* Synopsis [Creates initial simulation classes.] Description [Assumes that simulation info is assigned.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigCreateClasses( Ivy_FraigMan_t * p ) { Ivy_Obj_t ** pTable; Ivy_Obj_t * pObj, * pConst1, * pBin, * pEntry; int i, nTableSize; unsigned Hash; pConst1 = Ivy_ManConst1(p->pManAig); // allocate the table nTableSize = Ivy_ManObjNum(p->pManAig) / 2 + 13; pTable = ABC_ALLOC( Ivy_Obj_t *, nTableSize ); memset( pTable, 0, sizeof(Ivy_Obj_t *) * nTableSize ); // collect nodes into the table Ivy_ManForEachObj( p->pManAig, pObj, i ) { if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) ) continue; Hash = Ivy_NodeHash( p, pObj ); if ( Hash == 0 && Ivy_NodeHasZeroSim( p, pObj ) ) { Ivy_NodeAddToClass( pConst1, pObj ); continue; } // add the node to the table pBin = pTable[Hash % nTableSize]; Ivy_FraigForEachBinNode( pBin, pEntry ) if ( Ivy_NodeCompareSims( p, pEntry, pObj ) ) { Ivy_NodeAddToClass( pEntry, pObj ); break; } // check if the entry was added if ( pEntry ) continue; Ivy_ObjSetNodeHashNext( pObj, pBin ); pTable[Hash % nTableSize] = pObj; } // collect non-trivial classes assert( p->lClasses.pHead == NULL ); Ivy_ManForEachObj( p->pManAig, pObj, i ) { if ( !Ivy_ObjIsConst1(pObj) && !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) ) continue; Ivy_ObjSetNodeHashNext( pObj, NULL ); if ( Ivy_ObjClassNodeRepr(pObj) == NULL ) { assert( Ivy_ObjClassNodeNext(pObj) == NULL ); continue; } // recognize the head of the class if ( Ivy_ObjClassNodeNext( Ivy_ObjClassNodeRepr(pObj) ) != NULL ) continue; // clean the class representative and add it to the list Ivy_ObjSetClassNodeRepr( pObj, NULL ); Ivy_FraigAddClass( &p->lClasses, pObj ); } // free the table ABC_FREE( pTable ); } /**Function************************************************************* Synopsis [Recursively refines the class after simulation.] Description [Returns 1 if the class has changed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FraigRefineClass_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass ) { Ivy_Obj_t * pClassNew, * pListOld, * pListNew, * pNode; int RetValue = 0; // check if there is refinement pListOld = pClass; Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClass), pClassNew ) { if ( !Ivy_NodeCompareSims(p, pClass, pClassNew) ) { if ( p->pParams->fPatScores ) Ivy_FraigAddToPatScores( p, pClass, pClassNew ); break; } pListOld = pClassNew; } if ( pClassNew == NULL ) return 0; // set representative of the new class Ivy_ObjSetClassNodeRepr( pClassNew, NULL ); // start the new list pListNew = pClassNew; // go through the remaining nodes and sort them into two groups: // (1) matches of the old node; (2) non-matches of the old node Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClassNew), pNode ) if ( Ivy_NodeCompareSims( p, pClass, pNode ) ) { Ivy_ObjSetClassNodeNext( pListOld, pNode ); pListOld = pNode; } else { Ivy_ObjSetClassNodeNext( pListNew, pNode ); Ivy_ObjSetClassNodeRepr( pNode, pClassNew ); pListNew = pNode; } // finish both lists Ivy_ObjSetClassNodeNext( pListNew, NULL ); Ivy_ObjSetClassNodeNext( pListOld, NULL ); // update the list of classes Ivy_FraigInsertClass( &p->lClasses, pClass, pClassNew ); // if the old class is trivial, remove it if ( Ivy_ObjClassNodeNext(pClass) == NULL ) Ivy_FraigRemoveClass( &p->lClasses, pClass ); // if the new class is trivial, remove it; otherwise, try to refine it if ( Ivy_ObjClassNodeNext(pClassNew) == NULL ) Ivy_FraigRemoveClass( &p->lClasses, pClassNew ); else RetValue = Ivy_FraigRefineClass_rec( p, pClassNew ); return RetValue + 1; } /**Function************************************************************* Synopsis [Creates the counter-example from the successful pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigCheckOutputSimsSavePattern( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) { Ivy_FraigSim_t * pSims; int i, k, BestPat, * pModel; // find the word of the pattern pSims = Ivy_ObjSim(pObj); for ( i = 0; i < p->nSimWords; i++ ) if ( pSims->pData[i] ) break; assert( i < p->nSimWords ); // find the bit of the pattern for ( k = 0; k < 32; k++ ) if ( pSims->pData[i] & (1 << k) ) break; assert( k < 32 ); // determine the best pattern BestPat = i * 32 + k; // fill in the counter-example data pModel = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); Ivy_ManForEachPi( p->pManAig, pObj, i ) { pModel[i] = Ivy_InfoHasBit(Ivy_ObjSim(pObj)->pData, BestPat); // printf( "%d", pModel[i] ); } // printf( "\n" ); // set the model assert( p->pManFraig->pData == NULL ); p->pManFraig->pData = pModel; return; } /**Function************************************************************* Synopsis [Returns 1 if the one of the output is already non-constant 0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FraigCheckOutputSims( Ivy_FraigMan_t * p ) { Ivy_Obj_t * pObj; int i; // make sure the reference simulation pattern does not detect the bug // 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 // complement simulation info // if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) ) // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) // Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) ); // check if ( !Ivy_NodeHasZeroSim( p, Ivy_ObjFanin0(pObj) ) ) { // create the counter-example from this pattern Ivy_FraigCheckOutputSimsSavePattern( p, Ivy_ObjFanin0(pObj) ); return 1; } // complement simulation info // if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) ) // Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) ); } return 0; } /**Function************************************************************* Synopsis [Refines the classes after simulation.] Description [Assumes that simulation info is assigned. Returns the number of classes refined.] SideEffects [Large equivalence class of constant 0 may cause problems.] SeeAlso [] ***********************************************************************/ int Ivy_FraigRefineClasses( Ivy_FraigMan_t * p ) { Ivy_Obj_t * pClass, * pClass2; int RetValue, Counter = 0; abctime clk; // check if some outputs already became non-constant // this is a special case when computation can be stopped!!! if ( p->pParams->fProve ) Ivy_FraigCheckOutputSims( p ); if ( p->pManFraig->pData ) return 0; // refine the classed clk = Abc_Clock(); Ivy_FraigForEachEquivClassSafe( p->lClasses.pHead, pClass, pClass2 ) { if ( pClass->fMarkA ) continue; RetValue = Ivy_FraigRefineClass_rec( p, pClass ); Counter += ( RetValue > 0 ); //if ( Ivy_ObjIsConst1(pClass) ) //printf( "%d ", RetValue ); //if ( Ivy_ObjIsConst1(pClass) ) // p->time1 += Abc_Clock() - clk; } p->timeRef += Abc_Clock() - clk; return Counter; } /**Function************************************************************* Synopsis [Print the class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigPrintClass( Ivy_Obj_t * pClass ) { Ivy_Obj_t * pObj; printf( "Class {" ); Ivy_FraigForEachClassNode( pClass, pObj ) printf( " %d(%d)%c", pObj->Id, pObj->Level, pObj->fPhase? '+' : '-' ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Count the number of elements in the class.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FraigCountClassNodes( Ivy_Obj_t * pClass ) { Ivy_Obj_t * pObj; int Counter = 0; Ivy_FraigForEachClassNode( pClass, pObj ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Prints simulation classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigPrintSimClasses( Ivy_FraigMan_t * p ) { Ivy_Obj_t * pClass; Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass ) { // Ivy_FraigPrintClass( pClass ); printf( "%d ", Ivy_FraigCountClassNodes( pClass ) ); } // printf( "\n" ); } /**Function************************************************************* Synopsis [Generated const 0 pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigSavePattern0( Ivy_FraigMan_t * p ) { memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); } /**Function************************************************************* Synopsis [[Generated const 1 pattern.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigSavePattern1( Ivy_FraigMan_t * p ) { memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords ); } /**Function************************************************************* Synopsis [Generates the counter-example satisfying the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p ) { int * pModel; Ivy_Obj_t * pObj; int i; pModel = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); Ivy_ManForEachPi( p->pManFraig, pObj, i ) // pModel[i] = ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ); pModel[i] = ( p->pSat->model[Ivy_ObjSatNum(pObj)] == l_True ); return pModel; } /**Function************************************************************* Synopsis [Copy pattern from the solver into the internal storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigSavePattern( Ivy_FraigMan_t * p ) { Ivy_Obj_t * pObj; int i; memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); Ivy_ManForEachPi( p->pManFraig, pObj, i ) // Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPiVars, pObj, i ) // if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ) if ( p->pSat->model[Ivy_ObjSatNum(pObj)] == l_True ) Ivy_InfoSetBit( p->pPatWords, i ); // Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 ); } /**Function************************************************************* Synopsis [Copy pattern from the solver into the internal storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigSavePattern2( Ivy_FraigMan_t * p ) { Ivy_Obj_t * pObj; int i; memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); // Ivy_ManForEachPi( p->pManFraig, pObj, i ) Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPiVars, pObj, i ) // if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ) if ( p->pSat->model[Ivy_ObjSatNum(pObj)] == l_True ) // Ivy_InfoSetBit( p->pPatWords, i ); Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 ); } /**Function************************************************************* Synopsis [Copy pattern from the solver into the internal storage.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigSavePattern3( Ivy_FraigMan_t * p ) { Ivy_Obj_t * pObj; int i; for ( i = 0; i < p->nPatWords; i++ ) p->pPatWords[i] = Ivy_ObjRandomSim(); Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPiVars, pObj, i ) // if ( Ivy_InfoHasBit( p->pPatWords, pObj->Id - 1 ) ^ (p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True) ) if ( Ivy_InfoHasBit( p->pPatWords, pObj->Id - 1 ) ^ sat_solver_var_value(p->pSat, Ivy_ObjSatNum(pObj)) ) Ivy_InfoXorBit( p->pPatWords, pObj->Id - 1 ); } /**Function************************************************************* Synopsis [Performs simulation of the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigSimulate( Ivy_FraigMan_t * p ) { int nChanges, nClasses; // start the classes Ivy_FraigAssignRandom( p ); Ivy_FraigSimulateOne( p ); Ivy_FraigCreateClasses( p ); //printf( "Starting classes = %5d. Pairs = %6d.\n", p->lClasses.nItems, Ivy_FraigCountPairsClasses(p) ); // refine classes by walking 0/1 patterns Ivy_FraigSavePattern0( p ); Ivy_FraigAssignDist1( p, p->pPatWords ); Ivy_FraigSimulateOne( p ); nChanges = Ivy_FraigRefineClasses( p ); if ( p->pManFraig->pData ) return; //printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); Ivy_FraigSavePattern1( p ); Ivy_FraigAssignDist1( p, p->pPatWords ); Ivy_FraigSimulateOne( p ); nChanges = Ivy_FraigRefineClasses( p ); if ( p->pManFraig->pData ) return; //printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); // refine classes by random simulation do { Ivy_FraigAssignRandom( p ); Ivy_FraigSimulateOne( p ); nClasses = p->lClasses.nItems; nChanges = Ivy_FraigRefineClasses( p ); if ( p->pManFraig->pData ) return; //printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); } while ( (double)nChanges / nClasses > p->pParams->dSimSatur ); // Ivy_FraigPrintSimClasses( p ); } /**Function************************************************************* Synopsis [Cleans pattern scores.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigCleanPatScores( Ivy_FraigMan_t * p ) { int i, nLimit = p->nSimWords * 32; for ( i = 0; i < nLimit; i++ ) p->pPatScores[i] = 0; } /**Function************************************************************* Synopsis [Adds to pattern scores.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew ) { Ivy_FraigSim_t * pSims0, * pSims1; unsigned uDiff; int i, w; // get hold of the simulation information pSims0 = Ivy_ObjSim(pClass); pSims1 = Ivy_ObjSim(pClassNew); // iterate through the differences and record the score for ( w = 0; w < p->nSimWords; w++ ) { uDiff = pSims0->pData[w] ^ pSims1->pData[w]; if ( uDiff == 0 ) continue; for ( i = 0; i < 32; i++ ) if ( uDiff & ( 1 << i ) ) p->pPatScores[w*32+i]++; } } /**Function************************************************************* Synopsis [Selects the best pattern.] Description [Returns 1 if such pattern is found.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FraigSelectBestPat( Ivy_FraigMan_t * p ) { Ivy_FraigSim_t * pSims; Ivy_Obj_t * pObj; int i, nLimit = p->nSimWords * 32, MaxScore = 0, BestPat = -1; for ( i = 1; i < nLimit; i++ ) { if ( MaxScore < p->pPatScores[i] ) { MaxScore = p->pPatScores[i]; BestPat = i; } } if ( MaxScore == 0 ) return 0; // if ( MaxScore > p->pParams->MaxScore ) // printf( "Max score is %3d. ", MaxScore ); // copy the best pattern into the selected pattern memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); Ivy_ManForEachPi( p->pManAig, pObj, i ) { pSims = Ivy_ObjSim(pObj); if ( Ivy_InfoHasBit(pSims->pData, BestPat) ) Ivy_InfoSetBit(p->pPatWords, i); } return MaxScore; } /**Function************************************************************* Synopsis [Resimulates fraiging manager after finding a counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigResimulate( Ivy_FraigMan_t * p ) { int nChanges; Ivy_FraigAssignDist1( p, p->pPatWords ); Ivy_FraigSimulateOne( p ); if ( p->pParams->fPatScores ) Ivy_FraigCleanPatScores( p ); nChanges = Ivy_FraigRefineClasses( p ); if ( p->pManFraig->pData ) return; if ( nChanges < 1 ) printf( "Error: A counter-example did not refine classes!\n" ); assert( nChanges >= 1 ); //printf( "Refined classes! = %5d. Changes = %4d.\n", p->lClasses.nItems, nChanges ); if ( !p->pParams->fPatScores ) return; // perform additional simulation using dist1 patterns derived from successful patterns while ( Ivy_FraigSelectBestPat(p) > p->pParams->MaxScore ) { Ivy_FraigAssignDist1( p, p->pPatWords ); Ivy_FraigSimulateOne( p ); Ivy_FraigCleanPatScores( p ); nChanges = Ivy_FraigRefineClasses( p ); if ( p->pManFraig->pData ) return; //printf( "Refined class!!! = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); if ( nChanges == 0 ) break; } } /**Function************************************************************* Synopsis [Prints the status of the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, abctime clk, int fVerbose ) { if ( !fVerbose ) return; printf( "Nodes = %7d. Levels = %4d. ", Ivy_ManNodeNum(pNtk), Ivy_ManLevels(pNtk) ); ABC_PRT( pString, Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Reports the status of the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FraigMiterStatus( Ivy_Man_t * pMan ) { Ivy_Obj_t * pObj, * pObjNew; int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0; if ( pMan->pData ) return 0; Ivy_ManForEachPo( pMan, pObj, i ) { pObjNew = Ivy_ObjChild0(pObj); // check if the output is constant 1 if ( pObjNew == pMan->pConst1 ) { CountNonConst0++; continue; } // check if the output is constant 0 if ( pObjNew == Ivy_Not(pMan->pConst1) ) { CountConst0++; continue; } /* // check if the output is a primary input if ( Ivy_ObjIsPi(Ivy_Regular(pObjNew)) ) { CountNonConst0++; continue; } */ // check if the output can be constant 0 if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) ) { CountNonConst0++; continue; } CountUndecided++; } /* if ( p->pParams->fVerbose ) { printf( "Miter has %d outputs. ", Ivy_ManPoNum(p->pManAig) ); printf( "Const0 = %d. ", CountConst0 ); printf( "NonConst0 = %d. ", CountNonConst0 ); printf( "Undecided = %d. ", CountUndecided ); printf( "\n" ); } */ if ( CountNonConst0 ) return 0; if ( CountUndecided ) return -1; return 1; } /**Function************************************************************* Synopsis [Tries to prove each output of the miter until encountering a sat output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigMiterProve( Ivy_FraigMan_t * p ) { Ivy_Obj_t * pObj, * pObjNew; int i, RetValue; abctime clk = Abc_Clock(); int fVerbose = 0; Ivy_ManForEachPo( p->pManAig, pObj, i ) { if ( i && fVerbose ) { ABC_PRT( "Time", Abc_Clock() -clk ); } pObjNew = Ivy_ObjChild0Equiv(pObj); // check if the output is constant 1 if ( pObjNew == p->pManFraig->pConst1 ) { if ( fVerbose ) printf( "Output %2d (out of %2d) is constant 1. ", i, Ivy_ManPoNum(p->pManAig) ); // assing constant 0 model p->pManFraig->pData = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) ); break; } // check if the output is constant 0 if ( pObjNew == Ivy_Not(p->pManFraig->pConst1) ) { if ( fVerbose ) printf( "Output %2d (out of %2d) is already constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); continue; } // check if the output can be constant 0 if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) ) { if ( fVerbose ) printf( "Output %2d (out of %2d) cannot be constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); // assing constant 0 model p->pManFraig->pData = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) ); break; } /* // check the representative of this node pRepr = Ivy_ObjClassNodeRepr(Ivy_ObjFanin0(pObj)); if ( Ivy_Regular(pRepr) != p->pManAig->pConst1 ) printf( "Representative is not constant 1.\n" ); else printf( "Representative is constant 1.\n" ); */ // try to prove the output constant 0 RetValue = Ivy_FraigNodeIsConst( p, Ivy_Regular(pObjNew) ); if ( RetValue == 1 ) // proved equivalent { if ( fVerbose ) printf( "Output %2d (out of %2d) was proved constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); // set the constant miter Ivy_ObjFanin0(pObj)->pEquiv = Ivy_NotCond( p->pManFraig->pConst1, !Ivy_ObjFaninC0(pObj) ); continue; } if ( RetValue == -1 ) // failed { if ( fVerbose ) printf( "Output %2d (out of %2d) has timed out at %d backtracks. ", i, Ivy_ManPoNum(p->pManAig), p->pParams->nBTLimitMiter ); continue; } // proved satisfiable if ( fVerbose ) printf( "Output %2d (out of %2d) was proved NOT a constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); // create the model p->pManFraig->pData = Ivy_FraigCreateModel(p); break; } if ( fVerbose ) { ABC_PRT( "Time", Abc_Clock() -clk ); } } /**Function************************************************************* Synopsis [Performs fraiging for the internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigSweep( Ivy_FraigMan_t * p ) { Ivy_Obj_t * pObj;//, * pTemp; int i, k = 0; p->nClassesZero = p->lClasses.pHead? (Ivy_ObjIsConst1(p->lClasses.pHead) ? Ivy_FraigCountClassNodes(p->lClasses.pHead) : 0) : 0; p->nClassesBeg = p->lClasses.nItems; // duplicate internal nodes p->pProgress = Extra_ProgressBarStart( stdout, Ivy_ManNodeNum(p->pManAig) ); Ivy_ManForEachNode( p->pManAig, pObj, i ) { Extra_ProgressBarUpdate( p->pProgress, k++, NULL ); // default to simple strashing if simulation detected a counter-example for a PO if ( p->pManFraig->pData ) pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); else pObj->pEquiv = Ivy_FraigAnd( p, pObj ); assert( pObj->pEquiv != NULL ); // pTemp = Ivy_Regular(pObj->pEquiv); // assert( Ivy_Regular(pObj->pEquiv)->Type ); } Extra_ProgressBarStop( p->pProgress ); p->nClassesEnd = p->lClasses.nItems; // try to prove the outputs of the miter p->nNodesMiter = Ivy_ManNodeNum(p->pManFraig); // Ivy_FraigMiterStatus( p->pManFraig ); if ( p->pParams->fProve && p->pManFraig->pData == NULL ) Ivy_FraigMiterProve( p ); // add the POs Ivy_ManForEachPo( p->pManAig, pObj, i ) Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) ); // clean the old manager Ivy_ManForEachObj( p->pManAig, pObj, i ) pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; // clean the new manager Ivy_ManForEachObj( p->pManFraig, pObj, i ) { if ( Ivy_ObjFaninVec(pObj) ) Vec_PtrFree( Ivy_ObjFaninVec(pObj) ); pObj->pNextFan0 = pObj->pNextFan1 = NULL; pObj->pEquiv = NULL; } // remove dangling nodes Ivy_ManCleanup( p->pManFraig ); // clean up the class marks Ivy_FraigForEachEquivClass( p->lClasses.pHead, pObj ) pObj->fMarkA = 0; } /**Function************************************************************* Synopsis [Performs fraiging for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld ) { Ivy_Obj_t * pObjNew, * pFanin0New, * pFanin1New, * pObjReprNew; int RetValue; // get the fraiged fanins pFanin0New = Ivy_ObjChild0Equiv(pObjOld); pFanin1New = Ivy_ObjChild1Equiv(pObjOld); // get the candidate fraig node pObjNew = Ivy_And( p->pManFraig, pFanin0New, pFanin1New ); // get representative of this class if ( Ivy_ObjClassNodeRepr(pObjOld) == NULL || // this is a unique node (!p->pParams->fDoSparse && Ivy_ObjClassNodeRepr(pObjOld) == p->pManAig->pConst1) ) // this is a sparse node { // assert( Ivy_Regular(pFanin0New) != Ivy_Regular(pFanin1New) ); // assert( pObjNew != Ivy_Regular(pFanin0New) ); // assert( pObjNew != Ivy_Regular(pFanin1New) ); return pObjNew; } // get the fraiged representative pObjReprNew = Ivy_ObjFraig(Ivy_ObjClassNodeRepr(pObjOld)); // if the fraiged nodes are the same return if ( Ivy_Regular(pObjNew) == Ivy_Regular(pObjReprNew) ) return pObjNew; assert( Ivy_Regular(pObjNew) != Ivy_ManConst1(p->pManFraig) ); // printf( "Node = %d. Repr = %d.\n", pObjOld->Id, Ivy_ObjClassNodeRepr(pObjOld)->Id ); // they are different (the counter-example is in p->pPatWords) RetValue = Ivy_FraigNodesAreEquiv( p, Ivy_Regular(pObjReprNew), Ivy_Regular(pObjNew) ); if ( RetValue == 1 ) // proved equivalent { // mark the class as proved if ( Ivy_ObjClassNodeNext(pObjOld) == NULL ) Ivy_ObjClassNodeRepr(pObjOld)->fMarkA = 1; return Ivy_NotCond( pObjReprNew, pObjOld->fPhase ^ Ivy_ObjClassNodeRepr(pObjOld)->fPhase ); } if ( RetValue == -1 ) // failed return pObjNew; // simulate the counter-example and return the new node Ivy_FraigResimulate( p ); return pObjNew; } /**Function************************************************************* Synopsis [Prints variable activity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigPrintActivity( Ivy_FraigMan_t * p ) { int i; for ( i = 0; i < p->nSatVars; i++ ) printf( "%d %d ", i, (int)p->pSat->activity[i] ); printf( "\n" ); } /**Function************************************************************* Synopsis [Runs equivalence test for the two nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) { int pLits[4], RetValue, RetValue1, nBTLimit; abctime clk; //, clk2 = Abc_Clock(); // make sure the nodes are not complemented assert( !Ivy_IsComplement(pNew) ); assert( !Ivy_IsComplement(pOld) ); assert( pNew != pOld ); // if at least one of the nodes is a failed node, perform adjustments: // if the backtrack limit is small, simply skip this node // if the backtrack limit is > 10, take the quare root of the limit nBTLimit = p->pParams->nBTLimitNode; if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) ) { p->nSatFails++; // fail immediately // return -1; if ( nBTLimit <= 10 ) return -1; nBTLimit = (int)pow(nBTLimit, 0.7); } p->nSatCalls++; // make sure the solver is allocated and has enough variables if ( p->pSat == NULL ) { p->pSat = sat_solver_new(); sat_solver_setnvars( p->pSat, 1000 ); p->pSat->factors = ABC_CALLOC( double, p->pSat->cap ); p->nSatVars = 1; // var 0 is reserved for const1 node - add the clause // pLits[0] = toLit( 0 ); // sat_solver_addclause( p->pSat, pLits, pLits + 1 ); } // if the nodes do not have SAT variables, allocate them Ivy_FraigNodeAddToSolver( p, pOld, pNew ); // prepare variable activity Ivy_FraigSetActivityFactors( p, pOld, pNew ); // solve under assumptions // A = 1; B = 0 OR A = 1; B = 1 clk = Abc_Clock(); pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 0 ); pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase ); //Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, p->nBTLimitGlobal, p->nInsLimitGlobal ); p->timeSat += Abc_Clock() - clk; if ( RetValue1 == l_False ) { p->timeSatUnsat += Abc_Clock() - clk; pLits[0] = lit_neg( pLits[0] ); pLits[1] = lit_neg( pLits[1] ); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( RetValue ); // continue solving the other implication p->nSatCallsUnsat++; } else if ( RetValue1 == l_True ) { p->timeSatSat += Abc_Clock() - clk; Ivy_FraigSavePattern( p ); p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatFail += Abc_Clock() - clk; /* if ( nBTLimit > 1000 ) { RetValue = Ivy_FraigCheckCone( p, p->pManFraig, pOld, pNew, nBTLimit ); if ( RetValue != -1 ) return RetValue; } */ // mark the node as the failed node if ( pOld != p->pManFraig->pConst1 ) pOld->fFailTfo = 1; pNew->fFailTfo = 1; p->nSatFailsReal++; return -1; } // if the old node was constant 0, we already know the answer if ( pOld == p->pManFraig->pConst1 ) { p->nSatProof++; return 1; } // solve under assumptions // A = 0; B = 1 OR A = 0; B = 0 clk = Abc_Clock(); pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 1 ); pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase ^ pNew->fPhase ); RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, p->nBTLimitGlobal, p->nInsLimitGlobal ); p->timeSat += Abc_Clock() - clk; if ( RetValue1 == l_False ) { p->timeSatUnsat += Abc_Clock() - clk; pLits[0] = lit_neg( pLits[0] ); pLits[1] = lit_neg( pLits[1] ); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( RetValue ); p->nSatCallsUnsat++; } else if ( RetValue1 == l_True ) { p->timeSatSat += Abc_Clock() - clk; Ivy_FraigSavePattern( p ); p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatFail += Abc_Clock() - clk; /* if ( nBTLimit > 1000 ) { RetValue = Ivy_FraigCheckCone( p, p->pManFraig, pOld, pNew, nBTLimit ); if ( RetValue != -1 ) return RetValue; } */ // mark the node as the failed node pOld->fFailTfo = 1; pNew->fFailTfo = 1; p->nSatFailsReal++; return -1; } /* // check BDD proof { int RetVal; ABC_PRT( "Sat", Abc_Clock() - clk2 ); clk2 = Abc_Clock(); RetVal = Ivy_FraigNodesAreEquivBdd( pOld, pNew ); // printf( "%d ", RetVal ); assert( RetVal ); ABC_PRT( "Bdd", Abc_Clock() - clk2 ); printf( "\n" ); } */ // return SAT proof p->nSatProof++; return 1; } /**Function************************************************************* Synopsis [Runs equivalence test for one node.] Description [Returns the fraiged node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pNew ) { int pLits[2], RetValue1; abctime clk; int RetValue; // make sure the nodes are not complemented assert( !Ivy_IsComplement(pNew) ); assert( pNew != p->pManFraig->pConst1 ); p->nSatCalls++; // make sure the solver is allocated and has enough variables if ( p->pSat == NULL ) { p->pSat = sat_solver_new(); sat_solver_setnvars( p->pSat, 1000 ); p->pSat->factors = ABC_CALLOC( double, p->pSat->cap ); p->nSatVars = 1; // var 0 is reserved for const1 node - add the clause // pLits[0] = toLit( 0 ); // sat_solver_addclause( p->pSat, pLits, pLits + 1 ); } // if the nodes do not have SAT variables, allocate them Ivy_FraigNodeAddToSolver( p, NULL, pNew ); // prepare variable activity Ivy_FraigSetActivityFactors( p, NULL, pNew ); // solve under assumptions clk = Abc_Clock(); pLits[0] = toLitCond( Ivy_ObjSatNum(pNew), pNew->fPhase ); RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 1, (ABC_INT64_T)p->pParams->nBTLimitMiter, (ABC_INT64_T)0, p->nBTLimitGlobal, p->nInsLimitGlobal ); p->timeSat += Abc_Clock() - clk; if ( RetValue1 == l_False ) { p->timeSatUnsat += Abc_Clock() - clk; pLits[0] = lit_neg( pLits[0] ); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 ); assert( RetValue ); // continue solving the other implication p->nSatCallsUnsat++; } else if ( RetValue1 == l_True ) { p->timeSatSat += Abc_Clock() - clk; if ( p->pPatWords ) Ivy_FraigSavePattern( p ); p->nSatCallsSat++; return 0; } else // if ( RetValue1 == l_Undef ) { p->timeSatFail += Abc_Clock() - clk; /* if ( p->pParams->nBTLimitMiter > 1000 ) { RetValue = Ivy_FraigCheckCone( p, p->pManFraig, p->pManFraig->pConst1, pNew, p->pParams->nBTLimitMiter ); if ( RetValue != -1 ) return RetValue; } */ // mark the node as the failed node pNew->fFailTfo = 1; p->nSatFailsReal++; return -1; } // return SAT proof p->nSatProof++; return 1; } /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigAddClausesMux( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode ) { Ivy_Obj_t * pNodeI, * pNodeT, * pNodeE; int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; assert( !Ivy_IsComplement( pNode ) ); assert( Ivy_ObjIsMuxType( pNode ) ); // get nodes (I = if, T = then, E = else) pNodeI = Ivy_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); // get the variable numbers VarF = Ivy_ObjSatNum(pNode); VarI = Ivy_ObjSatNum(pNodeI); VarT = Ivy_ObjSatNum(Ivy_Regular(pNodeT)); VarE = Ivy_ObjSatNum(Ivy_Regular(pNodeE)); // get the complementation flags fCompT = Ivy_IsComplement(pNodeT); fCompE = Ivy_IsComplement(pNodeE); // f = ITE(i, t, e) // i' + t' + f // i' + t + f' // i + e' + f // i + e + f' // create four clauses pLits[0] = toLitCond(VarI, 1); pLits[1] = toLitCond(VarT, 1^fCompT); pLits[2] = toLitCond(VarF, 0); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = toLitCond(VarI, 1); pLits[1] = toLitCond(VarT, 0^fCompT); pLits[2] = toLitCond(VarF, 1); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = toLitCond(VarI, 0); pLits[1] = toLitCond(VarE, 1^fCompE); pLits[2] = toLitCond(VarF, 0); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = toLitCond(VarI, 0); pLits[1] = toLitCond(VarE, 0^fCompE); pLits[2] = toLitCond(VarF, 1); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); // two additional clauses // t' & e' -> f' // t & e -> f // t + e + f' // t' + e' + f if ( VarT == VarE ) { // assert( fCompT == !fCompE ); return; } pLits[0] = toLitCond(VarT, 0^fCompT); pLits[1] = toLitCond(VarE, 0^fCompE); pLits[2] = toLitCond(VarF, 1); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); pLits[0] = toLitCond(VarT, 1^fCompT); pLits[1] = toLitCond(VarE, 1^fCompE); pLits[2] = toLitCond(VarF, 0); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); assert( RetValue ); } /**Function************************************************************* Synopsis [Addes clauses to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigAddClausesSuper( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode, Vec_Ptr_t * vSuper ) { Ivy_Obj_t * pFanin; int * pLits, nLits, RetValue, i; assert( !Ivy_IsComplement(pNode) ); assert( Ivy_ObjIsNode( pNode ) ); // create storage for literals nLits = Vec_PtrSize(vSuper) + 1; pLits = ABC_ALLOC( int, nLits ); // suppose AND-gate is A & B = C // add !A => !C or A + !C Vec_PtrForEachEntry( Ivy_Obj_t *, vSuper, pFanin, i ) { pLits[0] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), Ivy_IsComplement(pFanin)); pLits[1] = toLitCond(Ivy_ObjSatNum(pNode), 1); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); assert( RetValue ); } // add A & B => C or !A + !B + C Vec_PtrForEachEntry( Ivy_Obj_t *, vSuper, pFanin, i ) pLits[i] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), !Ivy_IsComplement(pFanin)); pLits[nLits-1] = toLitCond(Ivy_ObjSatNum(pNode), 0); RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); assert( RetValue ); ABC_FREE( pLits ); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigCollectSuper_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) { // if the new node is complemented or a PI, another gate begins if ( Ivy_IsComplement(pObj) || Ivy_ObjIsPi(pObj) || (!fFirst && Ivy_ObjRefs(pObj) > 1) || (fUseMuxes && Ivy_ObjIsMuxType(pObj)) ) { Vec_PtrPushUnique( vSuper, pObj ); return; } // go through the branches Ivy_FraigCollectSuper_rec( Ivy_ObjChild0(pObj), vSuper, 0, fUseMuxes ); Ivy_FraigCollectSuper_rec( Ivy_ObjChild1(pObj), vSuper, 0, fUseMuxes ); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Ivy_FraigCollectSuper( Ivy_Obj_t * pObj, int fUseMuxes ) { Vec_Ptr_t * vSuper; assert( !Ivy_IsComplement(pObj) ); assert( !Ivy_ObjIsPi(pObj) ); vSuper = Vec_PtrAlloc( 4 ); Ivy_FraigCollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); return vSuper; } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigObjAddToFrontier( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vFrontier ) { assert( !Ivy_IsComplement(pObj) ); if ( Ivy_ObjSatNum(pObj) ) return; assert( Ivy_ObjSatNum(pObj) == 0 ); assert( Ivy_ObjFaninVec(pObj) == NULL ); if ( Ivy_ObjIsConst1(pObj) ) return; //printf( "Assigning node %d number %d\n", pObj->Id, p->nSatVars ); Ivy_ObjSetSatNum( pObj, p->nSatVars++ ); if ( Ivy_ObjIsNode(pObj) ) Vec_PtrPush( vFrontier, pObj ); } /**Function************************************************************* Synopsis [Updates the solver clause database.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) { Vec_Ptr_t * vFrontier, * vFanins; Ivy_Obj_t * pNode, * pFanin; int i, k, fUseMuxes = 1; assert( pOld || pNew ); // quit if CNF is ready if ( (!pOld || Ivy_ObjFaninVec(pOld)) && (!pNew || Ivy_ObjFaninVec(pNew)) ) return; // start the frontier vFrontier = Vec_PtrAlloc( 100 ); if ( pOld ) Ivy_FraigObjAddToFrontier( p, pOld, vFrontier ); if ( pNew ) Ivy_FraigObjAddToFrontier( p, pNew, vFrontier ); // explore nodes in the frontier Vec_PtrForEachEntry( Ivy_Obj_t *, vFrontier, pNode, i ) { // create the supergate assert( Ivy_ObjSatNum(pNode) ); assert( Ivy_ObjFaninVec(pNode) == NULL ); if ( fUseMuxes && Ivy_ObjIsMuxType(pNode) ) { vFanins = Vec_PtrAlloc( 4 ); Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin0(pNode) ) ); Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin1(pNode) ) ); Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin0(pNode) ) ); Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin1(pNode) ) ); Vec_PtrForEachEntry( Ivy_Obj_t *, vFanins, pFanin, k ) Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier ); Ivy_FraigAddClausesMux( p, pNode ); } else { vFanins = Ivy_FraigCollectSuper( pNode, fUseMuxes ); Vec_PtrForEachEntry( Ivy_Obj_t *, vFanins, pFanin, k ) Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier ); Ivy_FraigAddClausesSuper( p, pNode, vFanins ); } assert( Vec_PtrSize(vFanins) > 1 ); Ivy_ObjSetFaninVec( pNode, vFanins ); } Vec_PtrFree( vFrontier ); sat_solver_simplify( p->pSat ); } /**Function************************************************************* Synopsis [Sets variable activities in the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FraigSetActivityFactors_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int LevelMin, int LevelMax ) { Vec_Ptr_t * vFanins; Ivy_Obj_t * pFanin; int i, Counter = 0; assert( !Ivy_IsComplement(pObj) ); assert( Ivy_ObjSatNum(pObj) ); // skip visited variables if ( Ivy_ObjIsTravIdCurrent(p->pManFraig, pObj) ) return 0; Ivy_ObjSetTravIdCurrent(p->pManFraig, pObj); // add the PI to the list if ( pObj->Level <= (unsigned)LevelMin || Ivy_ObjIsPi(pObj) ) return 0; // set the factor of this variable // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pParams->dActConeBumpMax / ThisBump p->pSat->factors[Ivy_ObjSatNum(pObj)] = p->pParams->dActConeBumpMax * (pObj->Level - LevelMin)/(LevelMax - LevelMin); veci_push(&p->pSat->act_vars, Ivy_ObjSatNum(pObj)); // explore the fanins vFanins = Ivy_ObjFaninVec( pObj ); Vec_PtrForEachEntry( Ivy_Obj_t *, vFanins, pFanin, i ) Counter += Ivy_FraigSetActivityFactors_rec( p, Ivy_Regular(pFanin), LevelMin, LevelMax ); return 1 + Counter; } /**Function************************************************************* Synopsis [Sets variable activities in the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) { int LevelMin, LevelMax; abctime clk; assert( pOld || pNew ); clk = Abc_Clock(); // reset the active variables veci_resize(&p->pSat->act_vars, 0); // prepare for traversal Ivy_ManIncrementTravId( p->pManFraig ); // determine the min and max level to visit assert( p->pParams->dActConeRatio > 0 && p->pParams->dActConeRatio < 1 ); LevelMax = IVY_MAX( (pNew ? pNew->Level : 0), (pOld ? pOld->Level : 0) ); LevelMin = (int)(LevelMax * (1.0 - p->pParams->dActConeRatio)); // traverse if ( pOld && !Ivy_ObjIsConst1(pOld) ) Ivy_FraigSetActivityFactors_rec( p, pOld, LevelMin, LevelMax ); if ( pNew && !Ivy_ObjIsConst1(pNew) ) Ivy_FraigSetActivityFactors_rec( p, pNew, LevelMin, LevelMax ); //Ivy_FraigPrintActivity( p ); p->timeTrav += Abc_Clock() - clk; return 1; } ABC_NAMESPACE_IMPL_END #ifdef ABC_USE_CUDD #include "bdd/cudd/cuddInt.h" #endif ABC_NAMESPACE_IMPL_START #ifdef ABC_USE_CUDD /**Function************************************************************* Synopsis [Checks equivalence using BDDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Ivy_FraigNodesAreEquivBdd_int( DdManager * dd, DdNode * bFunc, Vec_Ptr_t * vFront, int Level ) { DdNode ** pFuncs; DdNode * bFuncNew; Vec_Ptr_t * vTemp; Ivy_Obj_t * pObj, * pFanin; int i, NewSize; // create new frontier vTemp = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, i ) { if ( (int)pObj->Level != Level ) { pObj->fMarkB = 1; pObj->TravId = Vec_PtrSize(vTemp); Vec_PtrPush( vTemp, pObj ); continue; } pFanin = Ivy_ObjFanin0(pObj); if ( pFanin->fMarkB == 0 ) { pFanin->fMarkB = 1; pFanin->TravId = Vec_PtrSize(vTemp); Vec_PtrPush( vTemp, pFanin ); } pFanin = Ivy_ObjFanin1(pObj); if ( pFanin->fMarkB == 0 ) { pFanin->fMarkB = 1; pFanin->TravId = Vec_PtrSize(vTemp); Vec_PtrPush( vTemp, pFanin ); } } // collect the permutation NewSize = IVY_MAX(dd->size, Vec_PtrSize(vTemp)); pFuncs = ABC_ALLOC( DdNode *, NewSize ); Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, i ) { if ( (int)pObj->Level != Level ) pFuncs[i] = Cudd_bddIthVar( dd, pObj->TravId ); else pFuncs[i] = Cudd_bddAnd( dd, Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin0(pObj)->TravId), Ivy_ObjFaninC0(pObj) ), Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin1(pObj)->TravId), Ivy_ObjFaninC1(pObj) ) ); Cudd_Ref( pFuncs[i] ); } // add the remaining vars assert( NewSize == dd->size ); for ( i = Vec_PtrSize(vFront); i < dd->size; i++ ) { pFuncs[i] = Cudd_bddIthVar( dd, i ); Cudd_Ref( pFuncs[i] ); } // create new bFuncNew = Cudd_bddVectorCompose( dd, bFunc, pFuncs ); Cudd_Ref( bFuncNew ); // clean trav Id Vec_PtrForEachEntry( Ivy_Obj_t *, vTemp, pObj, i ) { pObj->fMarkB = 0; pObj->TravId = 0; } // deref for ( i = 0; i < dd->size; i++ ) Cudd_RecursiveDeref( dd, pFuncs[i] ); ABC_FREE( pFuncs ); ABC_FREE( vFront->pArray ); *vFront = *vTemp; vTemp->nCap = vTemp->nSize = 0; vTemp->pArray = NULL; Vec_PtrFree( vTemp ); Cudd_Deref( bFuncNew ); return bFuncNew; } /**Function************************************************************* Synopsis [Checks equivalence using BDDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 ) { static DdManager * dd = NULL; DdNode * bFunc, * bTemp; Vec_Ptr_t * vFront; Ivy_Obj_t * pObj; int i, RetValue, Iter, Level; // start the manager if ( dd == NULL ) dd = Cudd_Init( 50, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); // create front vFront = Vec_PtrAlloc( 100 ); Vec_PtrPush( vFront, pObj1 ); Vec_PtrPush( vFront, pObj2 ); // get the function bFunc = Cudd_bddXor( dd, Cudd_bddIthVar(dd,0), Cudd_bddIthVar(dd,1) ); Cudd_Ref( bFunc ); bFunc = Cudd_NotCond( bFunc, pObj1->fPhase != pObj2->fPhase ); // try running BDDs for ( Iter = 0; ; Iter++ ) { // find max level Level = 0; Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, i ) if ( Level < (int)pObj->Level ) Level = (int)pObj->Level; if ( Level == 0 ) break; bFunc = Ivy_FraigNodesAreEquivBdd_int( dd, bTemp = bFunc, vFront, Level ); Cudd_Ref( bFunc ); Cudd_RecursiveDeref( dd, bTemp ); if ( bFunc == Cudd_ReadLogicZero(dd) ) // proved {printf( "%d", Iter ); break;} if ( Cudd_DagSize(bFunc) > 1000 ) {printf( "b" ); break;} if ( dd->size > 120 ) {printf( "s" ); break;} if ( Iter > 50 ) {printf( "i" ); break;} } if ( bFunc == Cudd_ReadLogicZero(dd) ) // unsat RetValue = 1; else if ( Level == 0 ) // sat RetValue = 0; else RetValue = -1; // spaceout/timeout Cudd_RecursiveDeref( dd, bFunc ); Vec_PtrFree( vFront ); return RetValue; } #endif ABC_NAMESPACE_IMPL_END #include "aig/aig/aig.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [Computes truth table of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_FraigExtractCone_rec( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) { if ( pNode->fMarkB ) return; pNode->fMarkB = 1; if ( Ivy_ObjIsPi(pNode) ) { Vec_IntPush( vLeaves, pNode->Id ); return; } assert( Ivy_ObjIsAnd(pNode) ); Ivy_FraigExtractCone_rec( p, Ivy_ObjFanin0(pNode), vLeaves, vNodes ); Ivy_FraigExtractCone_rec( p, Ivy_ObjFanin1(pNode), vLeaves, vNodes ); Vec_IntPush( vNodes, pNode->Id ); } /**Function************************************************************* Synopsis [Checks equivalence using BDDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Ivy_FraigExtractCone( Ivy_Man_t * p, Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2, Vec_Int_t * vLeaves ) { Aig_Man_t * pMan; Aig_Obj_t * pMiter; Vec_Int_t * vNodes; Ivy_Obj_t * pObjIvy; int i; // collect nodes vNodes = Vec_IntAlloc( 100 ); Ivy_ManConst1(p)->fMarkB = 1; Ivy_FraigExtractCone_rec( p, pObj1, vLeaves, vNodes ); Ivy_FraigExtractCone_rec( p, pObj2, vLeaves, vNodes ); Ivy_ManConst1(p)->fMarkB = 0; // create new manager pMan = Aig_ManStart( 1000 ); Ivy_ManConst1(p)->pEquiv = (Ivy_Obj_t *)Aig_ManConst1(pMan); Ivy_ManForEachNodeVec( p, vLeaves, pObjIvy, i ) { pObjIvy->pEquiv = (Ivy_Obj_t *)Aig_ObjCreateCi( pMan ); pObjIvy->fMarkB = 0; } // duplicate internal nodes Ivy_ManForEachNodeVec( p, vNodes, pObjIvy, i ) { pObjIvy->pEquiv = (Ivy_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Ivy_ObjChild0Equiv(pObjIvy), (Aig_Obj_t *)Ivy_ObjChild1Equiv(pObjIvy) ); pObjIvy->fMarkB = 0; pMiter = (Aig_Obj_t *)pObjIvy->pEquiv; assert( pMiter->fPhase == pObjIvy->fPhase ); } // create the PO pMiter = Aig_Exor( pMan, (Aig_Obj_t *)pObj1->pEquiv, (Aig_Obj_t *)pObj2->pEquiv ); pMiter = Aig_NotCond( pMiter, Aig_Regular(pMiter)->fPhase ^ Aig_IsComplement(pMiter) ); /* printf( "Polarity = %d\n", pMiter->fPhase ); if ( Ivy_ObjIsConst1(pObj1) || Ivy_ObjIsConst1(pObj2) ) { pMiter = Aig_NotCond( pMiter, 1 ); printf( "***************\n" ); } */ pMiter = Aig_ObjCreateCo( pMan, pMiter ); //printf( "Polarity = %d\n", pMiter->fPhase ); Aig_ManCleanup( pMan ); Vec_IntFree( vNodes ); return pMan; } /**Function************************************************************* Synopsis [Checks equivalence using BDDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_FraigCheckCone( Ivy_FraigMan_t * pGlo, Ivy_Man_t * p, Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2, int nConfLimit ) { extern int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose ); Vec_Int_t * vLeaves; Aig_Man_t * pMan; Aig_Obj_t * pObj; int i, RetValue; vLeaves = Vec_IntAlloc( 100 ); pMan = Ivy_FraigExtractCone( p, pObj1, pObj2, vLeaves ); RetValue = Fra_FraigSat( pMan, nConfLimit, 0, 0, 0, 0, 0, 0, 0, 1 ); if ( RetValue == 0 ) { int Counter = 0; memset( pGlo->pPatWords, 0, sizeof(unsigned) * pGlo->nPatWords ); Aig_ManForEachCi( pMan, pObj, i ) if ( ((int *)pMan->pData)[i] ) { int iObjIvy = Vec_IntEntry( vLeaves, i ); assert( iObjIvy > 0 && iObjIvy <= Ivy_ManPiNum(p) ); Ivy_InfoSetBit( pGlo->pPatWords, iObjIvy-1 ); //printf( "%d ", iObjIvy ); Counter++; } assert( Counter > 0 ); } Vec_IntFree( vLeaves ); if ( RetValue == 1 ) printf( "UNSAT\n" ); else if ( RetValue == 0 ) printf( "SAT\n" ); else if ( RetValue == -1 ) printf( "UNDEC\n" ); // p->pModel = (int *)pMan->pData, pMan2->pData = NULL; Aig_ManStop( pMan ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyHaig.c000066400000000000000000000417741477524141600161170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyHaig.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [HAIG management procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyHaig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /* HAIGing rules in working AIG: - Each node in the working AIG has a pointer to the corresponding node in HAIG (this node is not necessarily the representative of the equivalence class of HAIG nodes) - This pointer is complemented if the AIG node and its corresponding HAIG node have different phase Choice node rules in HAIG: - Equivalent nodes are linked into a ring - Exactly one node in the ring has fanouts (this node is called the representative) - The pointer going from a node to the next node in the ring is complemented if the first node is complemented, compared to the representative node of the equivalence class - (consequence of the above) The representative node always has non-complemented pointer to the next node - New nodes are inserted into the ring immediately after the representative node */ // returns the representative node of the given HAIG node static inline Ivy_Obj_t * Ivy_HaigObjRepr( Ivy_Obj_t * pObj ) { Ivy_Obj_t * pTemp; assert( !Ivy_IsComplement(pObj) ); // if the node has no equivalent node or has fanout, it is representative if ( pObj->pEquiv == NULL || Ivy_ObjRefs(pObj) > 0 ) return pObj; // the node belongs to a class and is not a representative // complemented edge (pObj->pEquiv) tells if it is complemented w.r.t. the repr for ( pTemp = Ivy_Regular(pObj->pEquiv); pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) if ( Ivy_ObjRefs(pTemp) > 0 ) break; // return the representative node assert( Ivy_ObjRefs(pTemp) > 0 ); return Ivy_NotCond( pTemp, Ivy_IsComplement(pObj->pEquiv) ); } // counts the number of nodes in the equivalence class static inline int Ivy_HaigObjCountClass( Ivy_Obj_t * pObj ) { Ivy_Obj_t * pTemp; int Counter; assert( !Ivy_IsComplement(pObj) ); assert( Ivy_ObjRefs(pObj) > 0 ); if ( pObj->pEquiv == NULL ) return 1; assert( !Ivy_IsComplement(pObj->pEquiv) ); Counter = 1; for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) Counter++; return Counter; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts HAIG for the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose ) { Vec_Int_t * vLatches; Ivy_Obj_t * pObj; int i; assert( p->pHaig == NULL ); p->pHaig = Ivy_ManDup( p ); if ( fVerbose ) { printf( "Starting : " ); Ivy_ManPrintStats( p->pHaig ); } // collect latches of design D and set their values to be DC vLatches = Vec_IntAlloc( 100 ); Ivy_ManForEachLatch( p->pHaig, pObj, i ) { pObj->Init = IVY_INIT_DC; Vec_IntPush( vLatches, pObj->Id ); } p->pHaig->pData = vLatches; /* { int x; Ivy_ManShow( p, 0, NULL ); Ivy_ManShow( p->pHaig, 1, NULL ); x = 0; } */ } /**Function************************************************************* Synopsis [Transfers the HAIG to the newly created manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew ) { Ivy_Obj_t * pObj; int i; assert( p->pHaig != NULL ); Ivy_ManConst1(pNew)->pEquiv = Ivy_ManConst1(p)->pEquiv; Ivy_ManForEachPi( pNew, pObj, i ) pObj->pEquiv = Ivy_ManPi( p, i )->pEquiv; pNew->pHaig = p->pHaig; } /**Function************************************************************* Synopsis [Stops HAIG for the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManHaigStop( Ivy_Man_t * p ) { Ivy_Obj_t * pObj; int i; assert( p->pHaig != NULL ); Vec_IntFree( (Vec_Int_t *)p->pHaig->pData ); Ivy_ManStop( p->pHaig ); p->pHaig = NULL; // remove dangling pointers to the HAIG objects Ivy_ManForEachObj( p, pObj, i ) pObj->pEquiv = NULL; } /**Function************************************************************* Synopsis [Creates a new node in HAIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { Ivy_Obj_t * pEquiv0, * pEquiv1; assert( p->pHaig != NULL ); assert( !Ivy_IsComplement(pObj) ); if ( Ivy_ObjType(pObj) == IVY_BUF ) pObj->pEquiv = Ivy_ObjChild0Equiv(pObj); else if ( Ivy_ObjType(pObj) == IVY_LATCH ) { // pObj->pEquiv = Ivy_Latch( p->pHaig, Ivy_ObjChild0Equiv(pObj), pObj->Init ); pEquiv0 = Ivy_ObjChild0Equiv(pObj); pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) ); pObj->pEquiv = Ivy_Latch( p->pHaig, pEquiv0, (Ivy_Init_t)pObj->Init ); } else if ( Ivy_ObjType(pObj) == IVY_AND ) { // pObj->pEquiv = Ivy_And( p->pHaig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); pEquiv0 = Ivy_ObjChild0Equiv(pObj); pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) ); pEquiv1 = Ivy_ObjChild1Equiv(pObj); pEquiv1 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv1)), Ivy_IsComplement(pEquiv1) ); pObj->pEquiv = Ivy_And( p->pHaig, pEquiv0, pEquiv1 ); } else assert( 0 ); // make sure the node points to the representative // pObj->pEquiv = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObj->pEquiv)), Ivy_IsComplement(pObj->pEquiv) ); } /**Function************************************************************* Synopsis [Checks if the old node is in the TFI of the new node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ObjIsInTfi_rec( Ivy_Obj_t * pObjNew, Ivy_Obj_t * pObjOld, int Levels ) { if ( pObjNew == pObjOld ) return 1; if ( Levels == 0 || Ivy_ObjIsCi(pObjNew) || Ivy_ObjIsConst1(pObjNew) ) return 0; if ( Ivy_ObjIsInTfi_rec( Ivy_ObjFanin0(pObjNew), pObjOld, Levels - 1 ) ) return 1; if ( Ivy_ObjIsNode(pObjNew) && Ivy_ObjIsInTfi_rec( Ivy_ObjFanin1(pObjNew), pObjOld, Levels - 1 ) ) return 1; return 0; } /**Function************************************************************* Synopsis [Sets the pair of equivalent nodes in HAIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew ) { Ivy_Obj_t * pObjOldHaig, * pObjNewHaig; Ivy_Obj_t * pObjOldHaigR, * pObjNewHaigR; int fCompl; //printf( "\nCreating choice for %d and %d in AIG\n", pObjOld->Id, Ivy_Regular(pObjNew)->Id ); assert( p->pHaig != NULL ); assert( !Ivy_IsComplement(pObjOld) ); // get pointers to the representatives of pObjOld and pObjNew pObjOldHaig = pObjOld->pEquiv; pObjNewHaig = Ivy_NotCond( Ivy_Regular(pObjNew)->pEquiv, Ivy_IsComplement(pObjNew) ); // get the classes pObjOldHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjOldHaig)), Ivy_IsComplement(pObjOldHaig) ); pObjNewHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjNewHaig)), Ivy_IsComplement(pObjNewHaig) ); // get regular pointers pObjOldHaigR = Ivy_Regular(pObjOldHaig); pObjNewHaigR = Ivy_Regular(pObjNewHaig); // check if there is phase difference between them fCompl = (Ivy_IsComplement(pObjOldHaig) != Ivy_IsComplement(pObjNewHaig)); // if the class is the same, nothing to do if ( pObjOldHaigR == pObjNewHaigR ) return; // if the second node belongs to a class, do not merge classes (for the time being) if ( Ivy_ObjRefs(pObjOldHaigR) == 0 || pObjNewHaigR->pEquiv != NULL || Ivy_ObjRefs(pObjNewHaigR) > 0 ) //|| Ivy_ObjIsInTfi_rec(pObjNewHaigR, pObjOldHaigR, 10) ) { /* if ( pObjNewHaigR->pEquiv != NULL ) printf( "c" ); if ( Ivy_ObjRefs(pObjNewHaigR) > 0 ) printf( "f" ); printf( " " ); */ p->pHaig->nClassesSkip++; return; } // add this node to the class of pObjOldHaig assert( Ivy_ObjRefs(pObjOldHaigR) > 0 ); assert( !Ivy_IsComplement(pObjOldHaigR->pEquiv) ); if ( pObjOldHaigR->pEquiv == NULL ) pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ); else pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR->pEquiv, fCompl ); pObjOldHaigR->pEquiv = pObjNewHaigR; //printf( "Setting choice node %d -> %d.\n", pObjOldHaigR->Id, pObjNewHaigR->Id ); // update the class of the new node // Ivy_Regular(pObjNew)->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ^ Ivy_IsComplement(pObjNew) ); //printf( "Creating choice for %d and %d in HAIG\n", pObjOldHaigR->Id, pObjNewHaigR->Id ); // if ( pObjOldHaigR->Id == 13 ) // { // Ivy_ManShow( p, 0 ); // Ivy_ManShow( p->pHaig, 1 ); // } // if ( !Ivy_ManIsAcyclic( p->pHaig ) ) // printf( "HAIG contains a cycle\n" ); } /**Function************************************************************* Synopsis [Count the number of choices and choice nodes in HAIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManHaigCountChoices( Ivy_Man_t * p, int * pnChoices ) { Ivy_Obj_t * pObj; int nChoices, nChoiceNodes, Counter, i; assert( p->pHaig != NULL ); nChoices = nChoiceNodes = 0; Ivy_ManForEachObj( p->pHaig, pObj, i ) { if ( Ivy_ObjIsTerm(pObj) || i == 0 ) continue; if ( Ivy_ObjRefs(pObj) == 0 ) continue; Counter = Ivy_HaigObjCountClass( pObj ); nChoiceNodes += (int)(Counter > 1); nChoices += Counter - 1; // if ( Counter > 1 ) // printf( "Choice node %d %s\n", pObj->Id, Ivy_ObjIsLatch(pObj)? "(latch)": "" ); } *pnChoices = nChoices; return nChoiceNodes; } /**Function************************************************************* Synopsis [Prints statistics of the HAIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose ) { int nChoices, nChoiceNodes; assert( p->pHaig != NULL ); if ( fVerbose ) { printf( "Final : " ); Ivy_ManPrintStats( p ); printf( "HAIG : " ); Ivy_ManPrintStats( p->pHaig ); // print choice node stats nChoiceNodes = Ivy_ManHaigCountChoices( p, &nChoices ); printf( "Total choice nodes = %d. Total choices = %d. Skipped classes = %d.\n", nChoiceNodes, nChoices, p->pHaig->nClassesSkip ); } if ( Ivy_ManIsAcyclic( p->pHaig ) ) { if ( fVerbose ) printf( "HAIG is acyclic\n" ); } else printf( "HAIG contains a cycle\n" ); // if ( fVerbose ) // Ivy_ManHaigSimulate( p ); } /**Function************************************************************* Synopsis [Applies the simulation rules.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Ivy_Init_t Ivy_ManHaigSimulateAnd( Ivy_Init_t In0, Ivy_Init_t In1 ) { assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE ); if ( In0 == IVY_INIT_DC || In1 == IVY_INIT_DC ) return IVY_INIT_DC; if ( In0 == IVY_INIT_1 && In1 == IVY_INIT_1 ) return IVY_INIT_1; return IVY_INIT_0; } /**Function************************************************************* Synopsis [Applies the simulation rules.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Ivy_Init_t Ivy_ManHaigSimulateChoice( Ivy_Init_t In0, Ivy_Init_t In1 ) { assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE ); if ( (In0 == IVY_INIT_0 && In1 == IVY_INIT_1) || (In0 == IVY_INIT_1 && In1 == IVY_INIT_0) ) { printf( "Compatibility fails.\n" ); return IVY_INIT_0; } if ( In0 == IVY_INIT_DC && In1 == IVY_INIT_DC ) return IVY_INIT_DC; if ( In0 != IVY_INIT_DC ) return In0; return In1; } /**Function************************************************************* Synopsis [Simulate HAIG using modified 3-valued simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManHaigSimulate( Ivy_Man_t * p ) { Vec_Int_t * vNodes, * vLatches, * vLatchesD; Ivy_Obj_t * pObj, * pTemp; Ivy_Init_t In0, In1; int i, k, Counter; int fVerbose = 0; // check choices Ivy_ManCheckChoices( p ); // switch to HAIG assert( p->pHaig != NULL ); p = p->pHaig; if ( fVerbose ) Ivy_ManForEachPi( p, pObj, i ) printf( "Setting PI %d\n", pObj->Id ); // collect latches and nodes in the DFS order vNodes = Ivy_ManDfsSeq( p, &vLatches ); if ( fVerbose ) Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) printf( "Collected node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id ); // set the PI values Ivy_ManConst1(p)->Init = IVY_INIT_1; Ivy_ManForEachPi( p, pObj, i ) pObj->Init = IVY_INIT_0; // set the latch values Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) pObj->Init = IVY_INIT_DC; // set the latches of D to be determinate vLatchesD = (Vec_Int_t *)p->pData; Ivy_ManForEachNodeVec( p, vLatchesD, pObj, i ) pObj->Init = IVY_INIT_0; // perform several rounds of simulation for ( k = 0; k < 10; k++ ) { // count the number of non-determinate values Counter = 0; Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) Counter += ( pObj->Init == IVY_INIT_DC ); printf( "Iter %d : Non-determinate = %d\n", k, Counter ); // simulate the internal nodes Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) { if ( fVerbose ) printf( "Processing node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id ); In0 = Ivy_InitNotCond( (Ivy_Init_t)Ivy_ObjFanin0(pObj)->Init, Ivy_ObjFaninC0(pObj) ); In1 = Ivy_InitNotCond( (Ivy_Init_t)Ivy_ObjFanin1(pObj)->Init, Ivy_ObjFaninC1(pObj) ); pObj->Init = Ivy_ManHaigSimulateAnd( In0, In1 ); // simulate the equivalence class if the node is a representative if ( pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) { if ( fVerbose ) printf( "Processing choice node %d\n", pObj->Id ); In0 = (Ivy_Init_t)pObj->Init; assert( !Ivy_IsComplement(pObj->pEquiv) ); for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) { if ( fVerbose ) printf( "Processing secondary node %d\n", pTemp->Id ); In1 = Ivy_InitNotCond( (Ivy_Init_t)pTemp->Init, Ivy_IsComplement(pTemp->pEquiv) ); In0 = Ivy_ManHaigSimulateChoice( In0, In1 ); } pObj->Init = In0; } } // simulate the latches Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) { pObj->Level = Ivy_ObjFanin0(pObj)->Init; if ( fVerbose ) printf( "Using latch %d with fanin %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id ); } Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) pObj->Init = pObj->Level, pObj->Level = 0; } // free arrays Vec_IntFree( vNodes ); Vec_IntFree( vLatches ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyMan.c000066400000000000000000000425161477524141600157550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [AIG manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Man_t * Ivy_ManStart() { Ivy_Man_t * p; // start the manager p = ABC_ALLOC( Ivy_Man_t, 1 ); memset( p, 0, sizeof(Ivy_Man_t) ); // perform initializations p->Ghost.Id = -1; p->nTravIds = 1; p->fCatchExor = 1; // allocate arrays for nodes p->vPis = Vec_PtrAlloc( 100 ); p->vPos = Vec_PtrAlloc( 100 ); p->vBufs = Vec_PtrAlloc( 100 ); p->vObjs = Vec_PtrAlloc( 100 ); // prepare the internal memory manager Ivy_ManStartMemory( p ); // create the constant node p->pConst1 = Ivy_ManFetchMemory( p ); p->pConst1->fPhase = 1; Vec_PtrPush( p->vObjs, p->pConst1 ); p->nCreated = 1; // start the table p->nTableSize = 10007; p->pTable = ABC_ALLOC( int, p->nTableSize ); memset( p->pTable, 0, sizeof(int) * p->nTableSize ); return p; } /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p ) { Ivy_Man_t * pNew; Ivy_Obj_t * pObj; int i; // create the new manager pNew = Ivy_ManStart(); // create the PIs Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew); Ivy_ManForEachPi( p, pObj, i ) pObj->pEquiv = Ivy_ObjCreatePi(pNew); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p ) { Vec_Int_t * vNodes, * vLatches; Ivy_Man_t * pNew; Ivy_Obj_t * pObj; int i; // collect latches and nodes in the DFS order vNodes = Ivy_ManDfsSeq( p, &vLatches ); // create the new manager pNew = Ivy_ManStart(); // create the PIs Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew); Ivy_ManForEachPi( p, pObj, i ) pObj->pEquiv = Ivy_ObjCreatePi(pNew); // create the fake PIs for latches Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) pObj->pEquiv = Ivy_ObjCreatePi(pNew); // duplicate internal nodes Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) if ( Ivy_ObjIsBuf(pObj) ) pObj->pEquiv = Ivy_ObjChild0Equiv(pObj); else pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); // add the POs Ivy_ManForEachPo( p, pObj, i ) Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(pObj) ); // transform additional PI nodes into latches and connect them Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) { assert( !Ivy_ObjFaninC0(pObj) ); pObj->pEquiv->Type = IVY_LATCH; pObj->pEquiv->Init = pObj->Init; Ivy_ObjConnect( pNew, pObj->pEquiv, Ivy_ObjChild0Equiv(pObj), NULL ); } // shrink the arrays Vec_PtrShrink( pNew->vPis, Ivy_ManPiNum(p) ); // update the counters of different objects pNew->nObjs[IVY_PI] -= Ivy_ManLatchNum(p); pNew->nObjs[IVY_LATCH] += Ivy_ManLatchNum(p); // free arrays Vec_IntFree( vNodes ); Vec_IntFree( vLatches ); // make sure structural hashing did not change anything assert( Ivy_ManNodeNum(p) == Ivy_ManNodeNum(pNew) ); assert( Ivy_ManLatchNum(p) == Ivy_ManLatchNum(pNew) ); // check the resulting network if ( !Ivy_ManCheck(pNew) ) printf( "Ivy_ManMakeSeq(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Stops the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping ) { Vec_Ptr_t * vMapping; Ivy_Man_t * pNew; Ivy_Obj_t * pObj; int i, f, nPis, nPos, nIdMax; assert( Ivy_ManLatchNum(pMan) == 0 ); assert( nFrames > 0 ); // prepare the mapping nPis = Ivy_ManPiNum(pMan) - nLatches; nPos = Ivy_ManPoNum(pMan) - nLatches; nIdMax = Ivy_ManObjIdMax(pMan); // create the new manager pNew = Ivy_ManStart(); // set the starting values of latch inputs for ( i = 0; i < nLatches; i++ ) Ivy_ManPo(pMan, nPos+i)->pEquiv = fInit? Ivy_Not(Ivy_ManConst1(pNew)) : Ivy_ObjCreatePi(pNew); // add timeframes vMapping = Vec_PtrStart( nIdMax * nFrames + 1 ); for ( f = 0; f < nFrames; f++ ) { // create PIs Ivy_ManConst1(pMan)->pEquiv = Ivy_ManConst1(pNew); for ( i = 0; i < nPis; i++ ) Ivy_ManPi(pMan, i)->pEquiv = Ivy_ObjCreatePi(pNew); // transfer values to latch outputs for ( i = 0; i < nLatches; i++ ) Ivy_ManPi(pMan, nPis+i)->pEquiv = Ivy_ManPo(pMan, nPos+i)->pEquiv; // perform strashing Ivy_ManForEachNode( pMan, pObj, i ) pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); // create POs for ( i = 0; i < nPos; i++ ) Ivy_ManPo(pMan, i)->pEquiv = Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, i)) ); // set the results of latch inputs for ( i = 0; i < nLatches; i++ ) Ivy_ManPo(pMan, nPos+i)->pEquiv = Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, nPos+i)); // save the pointers in this frame Ivy_ManForEachObj( pMan, pObj, i ) Vec_PtrWriteEntry( vMapping, f * nIdMax + i, pObj->pEquiv ); } // connect latches if ( !fInit ) for ( i = 0; i < nLatches; i++ ) Ivy_ObjCreatePo( pNew, Ivy_ManPo(pMan, nPos+i)->pEquiv ); // remove dangling nodes Ivy_ManCleanup(pNew); *pvMapping = vMapping; // check the resulting network if ( !Ivy_ManCheck(pNew) ) printf( "Ivy_ManFrames(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Stops the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManStop( Ivy_Man_t * p ) { if ( p->time1 ) { ABC_PRT( "Update lev ", p->time1 ); } if ( p->time2 ) { ABC_PRT( "Update levR ", p->time2 ); } // Ivy_TableProfile( p ); // if ( p->vFanouts ) Ivy_ManStopFanout( p ); if ( p->vChunks ) Ivy_ManStopMemory( p ); if ( p->vRequired ) Vec_IntFree( p->vRequired ); if ( p->vPis ) Vec_PtrFree( p->vPis ); if ( p->vPos ) Vec_PtrFree( p->vPos ); if ( p->vBufs ) Vec_PtrFree( p->vBufs ); if ( p->vObjs ) Vec_PtrFree( p->vObjs ); ABC_FREE( p->pTable ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Removes nodes without fanout.] Description [Returns the number of dangling nodes removed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManCleanup( Ivy_Man_t * p ) { Ivy_Obj_t * pNode; int i, nNodesOld; nNodesOld = Ivy_ManNodeNum(p); Ivy_ManForEachObj( p, pNode, i ) if ( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) if ( Ivy_ObjRefs(pNode) == 0 ) Ivy_ObjDelete_rec( p, pNode, 1 ); //printf( "Cleanup removed %d nodes.\n", nNodesOld - Ivy_ManNodeNum(p) ); return nNodesOld - Ivy_ManNodeNum(p); } /**Function************************************************************* Synopsis [Marks nodes reachable from the given one.] Description [Returns the number of dangling nodes removed.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManCleanupSeq_rec( Ivy_Obj_t * pObj ) { if ( Ivy_ObjIsMarkA(pObj) ) return; Ivy_ObjSetMarkA(pObj); if ( pObj->pFanin0 != NULL ) Ivy_ManCleanupSeq_rec( Ivy_ObjFanin0(pObj) ); if ( pObj->pFanin1 != NULL ) Ivy_ManCleanupSeq_rec( Ivy_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Removes logic that does not feed into POs.] Description [Returns the number of dangling nodes removed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManCleanupSeq( Ivy_Man_t * p ) { Vec_Ptr_t * vNodes; Ivy_Obj_t * pObj; int i, RetValue; // mark the constant and PIs Ivy_ObjSetMarkA( Ivy_ManConst1(p) ); Ivy_ManForEachPi( p, pObj, i ) Ivy_ObjSetMarkA( pObj ); // mark nodes visited from POs Ivy_ManForEachPo( p, pObj, i ) Ivy_ManCleanupSeq_rec( pObj ); // collect unmarked nodes vNodes = Vec_PtrAlloc( 100 ); Ivy_ManForEachObj( p, pObj, i ) { if ( Ivy_ObjIsMarkA(pObj) ) Ivy_ObjClearMarkA(pObj); else Vec_PtrPush( vNodes, pObj ); } if ( Vec_PtrSize(vNodes) == 0 ) { Vec_PtrFree( vNodes ); //printf( "Sequential sweep cleaned out %d nodes.\n", 0 ); return 0; } // disconnect the marked objects Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, i ) Ivy_ObjDisconnect( p, pObj ); // remove the dangling objects Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, i ) { assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsLatch(pObj) || Ivy_ObjIsBuf(pObj) ); assert( Ivy_ObjRefs(pObj) == 0 ); // update node counters of the manager p->nObjs[pObj->Type]--; p->nDeleted++; // delete buffer from the array of buffers if ( p->fFanout && Ivy_ObjIsBuf(pObj) ) Vec_PtrRemove( p->vBufs, pObj ); // free the node Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); Ivy_ManRecycleMemory( p, pObj ); } // return the number of nodes freed RetValue = Vec_PtrSize(vNodes); Vec_PtrFree( vNodes ); //printf( "Sequential sweep cleaned out %d nodes.\n", RetValue ); return RetValue; } /**Function************************************************************* Synopsis [Checks if latches form self-loop.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManLatchIsSelfFeed_rec( Ivy_Obj_t * pLatch, Ivy_Obj_t * pLatchRoot ) { if ( !Ivy_ObjIsLatch(pLatch) && !Ivy_ObjIsBuf(pLatch) ) return 0; if ( pLatch == pLatchRoot ) return 1; return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatchRoot ); } /**Function************************************************************* Synopsis [Checks if latches form self-loop.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManLatchIsSelfFeed( Ivy_Obj_t * pLatch ) { if ( !Ivy_ObjIsLatch(pLatch) ) return 0; return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatch ); } /**Function************************************************************* Synopsis [Returns the number of dangling nodes removed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel ) { Ivy_Obj_t * pNode; int LimitFactor = 100; int NodeBeg = Ivy_ManNodeNum(p); int nSteps; for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ ) { pNode = (Ivy_Obj_t *)Vec_PtrEntryLast(p->vBufs); while ( Ivy_ObjIsBuf(pNode) ) pNode = Ivy_ObjReadFirstFanout( p, pNode ); // check if this buffer should remain if ( Ivy_ManLatchIsSelfFeed(pNode) ) { Vec_PtrPop(p->vBufs); continue; } //printf( "Propagating buffer %d with input %d and output %d\n", Ivy_ObjFaninId0(pNode), Ivy_ObjFaninId0(Ivy_ObjFanin0(pNode)), pNode->Id ); //printf( "Latch num %d\n", Ivy_ManLatchNum(p) ); Ivy_NodeFixBufferFanins( p, pNode, fUpdateLevel ); if ( nSteps > NodeBeg * LimitFactor ) { printf( "Structural hashing is not finished after %d forward latch moves.\n", NodeBeg * LimitFactor ); printf( "This circuit cannot be forward-retimed completely. Quitting.\n" ); break; } } // printf( "Number of steps = %d. Nodes beg = %d. Nodes end = %d.\n", nSteps, NodeBeg, Ivy_ManNodeNum(p) ); return nSteps; } /**Function************************************************************* Synopsis [Stops the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManPrintStats( Ivy_Man_t * p ) { printf( "PI/PO = %d/%d ", Ivy_ManPiNum(p), Ivy_ManPoNum(p) ); printf( "A = %7d. ", Ivy_ManAndNum(p) ); printf( "L = %5d. ", Ivy_ManLatchNum(p) ); // printf( "X = %d. ", Ivy_ManExorNum(p) ); // printf( "B = %3d. ", Ivy_ManBufNum(p) ); printf( "MaxID = %7d. ", Ivy_ManObjIdMax(p) ); // printf( "Cre = %d. ", p->nCreated ); // printf( "Del = %d. ", p->nDeleted ); printf( "Lev = %3d. ", Ivy_ManLatchNum(p)? -1 : Ivy_ManLevels(p) ); printf( "\n" ); fflush( stdout ); } /**Function************************************************************* Synopsis [Converts a combinational AIG manager into a sequential one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits ) { Ivy_Obj_t * pObj, * pLatch; Ivy_Init_t Init; int i; if ( nLatches == 0 ) return; assert( nLatches < Ivy_ManPiNum(p) && nLatches < Ivy_ManPoNum(p) ); assert( Ivy_ManPiNum(p) == Vec_PtrSize(p->vPis) ); assert( Ivy_ManPoNum(p) == Vec_PtrSize(p->vPos) ); assert( Vec_PtrSize( p->vBufs ) == 0 ); // create fanouts if ( p->fFanout == 0 ) Ivy_ManStartFanout( p ); // collect the POs to be converted into latches for ( i = 0; i < nLatches; i++ ) { // get the latch value Init = pInits? (Ivy_Init_t)pInits[i] : IVY_INIT_0; // create latch pObj = Ivy_ManPo( p, Ivy_ManPoNum(p) - nLatches + i ); pLatch = Ivy_Latch( p, Ivy_ObjChild0(pObj), Init ); Ivy_ObjDisconnect( p, pObj ); // recycle the old PO object Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); Ivy_ManRecycleMemory( p, pObj ); // convert the corresponding PI to a buffer and connect it to the latch pObj = Ivy_ManPi( p, Ivy_ManPiNum(p) - nLatches + i ); pObj->Type = IVY_BUF; Ivy_ObjConnect( p, pObj, pLatch, NULL ); // save the buffer Vec_PtrPush( p->vBufs, pObj ); } // shrink the arrays Vec_PtrShrink( p->vPis, Ivy_ManPiNum(p) - nLatches ); Vec_PtrShrink( p->vPos, Ivy_ManPoNum(p) - nLatches ); // update the counters of different objects p->nObjs[IVY_PI] -= nLatches; p->nObjs[IVY_PO] -= nLatches; p->nObjs[IVY_BUF] += nLatches; p->nDeleted -= 2 * nLatches; // remove dangling nodes Ivy_ManCleanup(p); Ivy_ManCleanupSeq(p); /* // check for dangling nodes Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsPo(pObj) && !Ivy_ObjIsConst1(pObj) ) { assert( Ivy_ObjRefs(pObj) > 0 ); assert( Ivy_ObjRefs(pObj) == Ivy_ObjFanoutNum(p, pObj) ); } */ // perform hashing by propagating the buffers Ivy_ManPropagateBuffers( p, 0 ); if ( Ivy_ManBufNum(p) ) printf( "The number of remaining buffers is %d.\n", Ivy_ManBufNum(p) ); // fix the levels Ivy_ManResetLevels( p ); // check the resulting network if ( !Ivy_ManCheck(p) ) printf( "Ivy_ManMakeSeq(): The check has failed.\n" ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyMem.c000066400000000000000000000071011477524141600157470ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyMem.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Memory management for the AIG nodes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // memory management #define IVY_PAGE_SIZE 12 // page size containing 2^IVY_PAGE_SIZE nodes #define IVY_PAGE_MASK 4095 // page bitmask (2^IVY_PAGE_SIZE)-1 //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the internal memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManStartMemory( Ivy_Man_t * p ) { p->vChunks = Vec_PtrAlloc( 128 ); p->vPages = Vec_PtrAlloc( 128 ); } /**Function************************************************************* Synopsis [Stops the internal memory manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManStopMemory( Ivy_Man_t * p ) { void * pMemory; int i; Vec_PtrForEachEntry( void *, p->vChunks, pMemory, i ) ABC_FREE( pMemory ); Vec_PtrFree( p->vChunks ); Vec_PtrFree( p->vPages ); p->pListFree = NULL; } /**Function************************************************************* Synopsis [Allocates additional memory for the nodes.] Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. Records the pointer to the AIG manager in the -1 entry.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManAddMemory( Ivy_Man_t * p ) { char * pMemory; int i, nBytes; int EntrySizeMax = 128; assert( sizeof(Ivy_Obj_t) <= EntrySizeMax ); assert( p->pListFree == NULL ); // assert( (Ivy_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); // allocate new memory page nBytes = sizeof(Ivy_Obj_t) * (1<vChunks, pMemory ); // align memory at the 32-byte boundary pMemory = pMemory + EntrySizeMax - (((int)(ABC_PTRUINT_T)pMemory) & (EntrySizeMax-1)); // remember the manager in the first entry Vec_PtrPush( p->vPages, pMemory ); // break the memory down into nodes p->pListFree = (Ivy_Obj_t *)pMemory; for ( i = 1; i <= IVY_PAGE_MASK; i++ ) { *((char **)pMemory) = pMemory + sizeof(Ivy_Obj_t); pMemory += sizeof(Ivy_Obj_t); } *((char **)pMemory) = NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyMulti.c000066400000000000000000000232241477524141600163270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyMulti.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Constructing multi-input AND/EXOR gates.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define IVY_EVAL_LIMIT 128 typedef struct Ivy_Eva_t_ Ivy_Eva_t; struct Ivy_Eva_t_ { Ivy_Obj_t * pArg; // the argument node unsigned Mask; // the mask of covered nodes int Weight; // the number of covered nodes }; static void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals ); static int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Constructs a balanced tree while taking sharing into account.] Description [Returns 1 if the implementation exists.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSols ) { static Ivy_Eva_t pEvals[IVY_EVAL_LIMIT]; Ivy_Eva_t * pEval, * pFan0, * pFan1; Ivy_Obj_t * pObj = NULL; // Suppress "might be used uninitialized" Ivy_Obj_t * pTemp; int nEvals, nEvalsOld, i, k, x, nLeaves; unsigned uMaskAll; // consider special cases nLeaves = Vec_PtrSize(vLeaves); assert( nLeaves > 2 ); if ( nLeaves > 32 || nLeaves + Vec_PtrSize(vCone) > IVY_EVAL_LIMIT ) return 0; // if ( nLeaves == 1 ) // return Vec_PtrEntry( vLeaves, 0 ); // if ( nLeaves == 2 ) // return Ivy_Oper( Vec_PtrEntry(vLeaves, 0), Vec_PtrEntry(vLeaves, 1), Type ); // set the leaf entries uMaskAll = ((1 << nLeaves) - 1); nEvals = 0; Vec_PtrForEachEntry( Ivy_Obj_t *, vLeaves, pObj, i ) { pEval = pEvals + nEvals; pEval->pArg = pObj; pEval->Mask = (1 << nEvals); pEval->Weight = 1; // mark the leaf Ivy_Regular(pObj)->TravId = nEvals; nEvals++; } // propagate masks through the cone Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pObj, i ) { pObj->TravId = nEvals + i; if ( Ivy_ObjIsBuf(pObj) ) pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask; else pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask | pEvals[Ivy_ObjFanin1(pObj)->TravId].Mask; } // set the internal entries Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pObj, i ) { if ( i == Vec_PtrSize(vCone) - 1 ) break; // skip buffers if ( Ivy_ObjIsBuf(pObj) ) continue; // skip nodes without external fanout if ( Ivy_ObjRefs(pObj) == 0 ) continue; assert( !Ivy_IsComplement(pObj) ); pEval = pEvals + nEvals; pEval->pArg = pObj; pEval->Mask = pEvals[pObj->TravId].Mask; pEval->Weight = Extra_WordCountOnes(pEval->Mask); // mark the node pObj->TravId = nEvals; nEvals++; } // find the available nodes nEvalsOld = nEvals; for ( i = 1; i < nEvals; i++ ) for ( k = 0; k < i; k++ ) { pFan0 = pEvals + i; pFan1 = pEvals + k; pTemp = Ivy_TableLookup(p, Ivy_ObjCreateGhost(p, pFan0->pArg, pFan1->pArg, Type, IVY_INIT_NONE)); // skip nodes in the cone if ( pTemp == NULL || pTemp->fMarkB ) continue; // skip the leaves for ( x = 0; x < nLeaves; x++ ) if ( pTemp == Ivy_Regular((Ivy_Obj_t *)vLeaves->pArray[x]) ) break; if ( x < nLeaves ) continue; pEval = pEvals + nEvals; pEval->pArg = pTemp; pEval->Mask = pFan0->Mask | pFan1->Mask; pEval->Weight = (pFan0->Mask & pFan1->Mask) ? Extra_WordCountOnes(pEval->Mask) : pFan0->Weight + pFan1->Weight; // save the argument pObj->TravId = nEvals; nEvals++; // quit if the number of entries exceeded the limit if ( nEvals == IVY_EVAL_LIMIT ) goto Outside; // quit if we found an acceptable implementation if ( pEval->Mask == uMaskAll ) goto Outside; } Outside: // Ivy_MultiPrint( pEvals, nLeaves, nEvals ); if ( !Ivy_MultiCover( p, pEvals, nLeaves, nEvals, nLimit, vSols ) ) return 0; assert( Vec_PtrSize( vSols ) > 0 ); return 1; } /**Function************************************************************* Synopsis [Computes how many uncovered ones this one covers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals ) { Ivy_Eva_t * pEval; int i, k; for ( i = nLeaves; i < nEvals; i++ ) { pEval = pEvals + i; printf( "%2d (id = %5d) : |", i-nLeaves, Ivy_ObjId(pEval->pArg) ); for ( k = 0; k < nLeaves; k++ ) { if ( pEval->Mask & (1 << k) ) printf( "+" ); else printf( " " ); } printf( "| Lev = %d.\n", Ivy_ObjLevel(pEval->pArg) ); } } /**Function************************************************************* Synopsis [Computes how many uncovered ones this one covers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ivy_MultiWeight( unsigned uMask, int nMaskOnes, unsigned uFound ) { assert( uMask & ~uFound ); if ( (uMask & uFound) == 0 ) return nMaskOnes; return Extra_WordCountOnes( uMask & ~uFound ); } /**Function************************************************************* Synopsis [Finds the cover.] Description [Returns 1 if the cover is found.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols ) { int fVerbose = 0; Ivy_Eva_t * pEval; Ivy_Eva_t * pEvalBest = NULL; // Suppress "might be used uninitialized" unsigned uMaskAll, uFound, uTemp; int i, k, BestK; int WeightBest = -1; // Suppress "might be used uninitialized" int WeightCur; int LevelBest = -1; // Suppress "might be used uninitialized" int LevelCur; uMaskAll = (nLeaves == 32)? (~(unsigned)0) : ((1 << nLeaves) - 1); uFound = 0; // solve the covering problem if ( fVerbose ) printf( "Solution: " ); Vec_PtrClear( vSols ); for ( i = 0; i < nLimit; i++ ) { BestK = -1; for ( k = nEvals - 1; k >= 0; k-- ) { pEval = pEvals + k; if ( (pEval->Mask & ~uFound) == 0 ) continue; if ( BestK == -1 ) { BestK = k; pEvalBest = pEval; WeightBest = Ivy_MultiWeight( pEvalBest->Mask, pEvalBest->Weight, uFound ); LevelBest = Ivy_ObjLevel( Ivy_Regular(pEvalBest->pArg) ); continue; } // compare BestK and the new one (k) WeightCur = Ivy_MultiWeight( pEval->Mask, pEval->Weight, uFound ); LevelCur = Ivy_ObjLevel( Ivy_Regular(pEval->pArg) ); if ( WeightBest < WeightCur || (WeightBest == WeightCur && LevelBest > LevelCur) ) { BestK = k; pEvalBest = pEval; WeightBest = WeightCur; LevelBest = LevelCur; } } assert( BestK != -1 ); // if the cost is only 1, take the leaf if ( WeightBest == 1 && BestK >= nLeaves ) { uTemp = (pEvalBest->Mask & ~uFound); for ( k = 0; k < nLeaves; k++ ) if ( uTemp & (1 << k) ) break; assert( k < nLeaves ); BestK = k; pEvalBest = pEvals + BestK; } if ( fVerbose ) { if ( BestK < nLeaves ) printf( "L(%d) ", BestK ); else printf( "%d ", BestK - nLeaves ); } // update the found set Vec_PtrPush( vSols, pEvalBest->pArg ); uFound |= pEvalBest->Mask; if ( uFound == uMaskAll ) break; } if ( uFound == uMaskAll ) { if ( fVerbose ) printf( " Found \n\n" ); return 1; } else { if ( fVerbose ) printf( " Not found \n\n" ); return 0; } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyMulti8.c000066400000000000000000000327051477524141600164230ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyMulti.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Constructing multi-input AND/EXOR gates.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Ivy_Eval_t_ Ivy_Eval_t; struct Ivy_Eval_t_ { unsigned Mask : 5; // the mask of covered nodes unsigned Weight : 3; // the number of covered nodes unsigned Cost : 4; // the number of overlapping nodes unsigned Level : 12; // the level of this node unsigned Fan0 : 4; // the first fanin unsigned Fan1 : 4; // the second fanin }; static Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); static void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs ); static int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode ); static Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Constructs the well-balanced tree of gates.] Description [Disregards levels and possible logic sharing.] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_Multi_rec( Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ) { Ivy_Obj_t * pObj1, * pObj2; if ( nObjs == 1 ) return ppObjs[0]; pObj1 = Ivy_Multi_rec( ppObjs, nObjs/2, Type ); pObj2 = Ivy_Multi_rec( ppObjs + nObjs/2, nObjs - nObjs/2, Type ); return Ivy_Oper( pObj1, pObj2, Type ); } /**Function************************************************************* Synopsis [Constructs a balanced tree while taking sharing into account.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_Multi( Ivy_Obj_t ** pArgsInit, int nArgs, Ivy_Type_t Type ) { static char NumBits[32] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5}; static Ivy_Eval_t pEvals[15+15*14/2]; static Ivy_Obj_t * pArgs[16]; Ivy_Eval_t * pEva, * pEvaBest; int nArgsNew, nEvals, i, k; Ivy_Obj_t * pTemp; // consider the case of one argument assert( nArgs > 0 ); if ( nArgs == 1 ) return pArgsInit[0]; // consider the case of two arguments if ( nArgs == 2 ) return Ivy_Oper( pArgsInit[0], pArgsInit[1], Type ); //Ivy_MultiEval( pArgsInit, nArgs, Type ); printf( "\n" ); // set the initial ones for ( i = 0; i < nArgs; i++ ) { pArgs[i] = pArgsInit[i]; pEva = pEvals + i; pEva->Mask = (1 << i); pEva->Weight = 1; pEva->Cost = 0; pEva->Level = Ivy_Regular(pArgs[i])->Level; pEva->Fan0 = 0; pEva->Fan1 = 0; } // find the available nodes pEvaBest = pEvals; nArgsNew = nArgs; for ( i = 1; i < nArgsNew; i++ ) for ( k = 0; k < i; k++ ) if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)) ) { pEva = pEvals + nArgsNew; pEva->Mask = pEvals[k].Mask | pEvals[i].Mask; pEva->Weight = NumBits[pEva->Mask]; pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask]; pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level); pEva->Fan0 = k; pEva->Fan1 = i; // assert( pEva->Level == (unsigned)Ivy_ObjLevel(pTemp) ); // compare if ( pEvaBest->Weight < pEva->Weight || pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost || pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level ) pEvaBest = pEva; // save the argument pArgs[nArgsNew++] = pTemp; if ( nArgsNew == 15 ) goto Outside; } Outside: // printf( "Best = %d.\n", pEvaBest - pEvals ); // the case of no common nodes if ( nArgsNew == nArgs ) { Ivy_MultiSort( pArgs, nArgs ); return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); } // the case of one common node if ( nArgsNew == nArgs + 1 ) { assert( pEvaBest - pEvals == nArgs ); k = 0; for ( i = 0; i < nArgs; i++ ) if ( i != (int)pEvaBest->Fan0 && i != (int)pEvaBest->Fan1 ) pArgs[k++] = pArgs[i]; pArgs[k++] = pArgs[nArgs]; assert( k == nArgs - 1 ); nArgs = k; Ivy_MultiSort( pArgs, nArgs ); return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); } // the case when there is a node that covers everything if ( (int)pEvaBest->Mask == ((1 << nArgs) - 1) ) return Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type ); // evaluate node pairs nEvals = nArgsNew; for ( i = 1; i < nArgsNew; i++ ) for ( k = 0; k < i; k++ ) { pEva = pEvals + nEvals; pEva->Mask = pEvals[k].Mask | pEvals[i].Mask; pEva->Weight = NumBits[pEva->Mask]; pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask]; pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level); pEva->Fan0 = k; pEva->Fan1 = i; // compare if ( pEvaBest->Weight < pEva->Weight || pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost || pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level ) pEvaBest = pEva; // save the argument nEvals++; } assert( pEvaBest - pEvals >= nArgsNew ); // printf( "Used (%d, %d).\n", pEvaBest->Fan0, pEvaBest->Fan1 ); // get the best implementation pTemp = Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type ); // collect those not covered by EvaBest k = 0; for ( i = 0; i < nArgs; i++ ) if ( (pEvaBest->Mask & (1 << i)) == 0 ) pArgs[k++] = pArgs[i]; pArgs[k++] = pTemp; assert( k == nArgs - (int)pEvaBest->Weight + 1 ); nArgs = k; Ivy_MultiSort( pArgs, nArgs ); return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); } /**Function************************************************************* Synopsis [Implements multi-input AND/EXOR operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) { Ivy_Obj_t * pNode0, * pNode1; if ( iNum < nArgs ) return pArgs[iNum]; pNode0 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan0, pArgs, nArgs, Type ); pNode1 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan1, pArgs, nArgs, Type ); return Ivy_Oper( pNode0, pNode1, Type ); } /**Function************************************************************* Synopsis [Selection-sorts the nodes in the decreasing over of level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs ) { Ivy_Obj_t * pTemp; int i, j, iBest; for ( i = 0; i < nArgs-1; i++ ) { iBest = i; for ( j = i+1; j < nArgs; j++ ) if ( Ivy_Regular(pArgs[j])->Level > Ivy_Regular(pArgs[iBest])->Level ) iBest = j; pTemp = pArgs[i]; pArgs[i] = pArgs[iBest]; pArgs[iBest] = pTemp; } } /**Function************************************************************* Synopsis [Inserts a new node in the order by levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode ) { Ivy_Obj_t * pNode1, * pNode2; int i; // try to find the node in the array for ( i = 0; i < nArgs; i++ ) if ( pArray[i] == pNode ) return nArgs; // put the node last pArray[nArgs++] = pNode; // find the place to put the new node for ( i = nArgs-1; i > 0; i-- ) { pNode1 = pArray[i ]; pNode2 = pArray[i-1]; if ( Ivy_Regular(pNode1)->Level <= Ivy_Regular(pNode2)->Level ) break; pArray[i ] = pNode2; pArray[i-1] = pNode1; } return nArgs; } /**Function************************************************************* Synopsis [Balances the array recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) { Ivy_Obj_t * pNodeNew; // consider the case of one argument assert( nArgs > 0 ); if ( nArgs == 1 ) return pArgs[0]; // consider the case of two arguments if ( nArgs == 2 ) return Ivy_Oper( pArgs[0], pArgs[1], Type ); // get the last two nodes pNodeNew = Ivy_Oper( pArgs[nArgs-1], pArgs[nArgs-2], Type ); // add the new node nArgs = Ivy_MultiPushUniqueOrderByLevel( pArgs, nArgs - 2, pNodeNew ); return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); } /**Function************************************************************* Synopsis [Implements multi-input AND/EXOR operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) { Ivy_Obj_t * pTemp; int i, k; int nArgsOld = nArgs; for ( i = 0; i < nArgs; i++ ) printf( "%d[%d] ", i, Ivy_Regular(pArgs[i])->Level ); for ( i = 1; i < nArgs; i++ ) for ( k = 0; k < i; k++ ) { pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)); if ( pTemp != NULL ) { printf( "%d[%d]=(%d,%d) ", nArgs, Ivy_Regular(pTemp)->Level, k, i ); pArgs[nArgs++] = pTemp; } } printf( " ((%d/%d)) ", nArgsOld, nArgs-nArgsOld ); return NULL; } /**Function************************************************************* Synopsis [Old code.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_Multi1( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) { Ivy_Obj_t * pArgsRef[5], * pTemp; int i, k, m, nArgsNew, Counter = 0; //Ivy_MultiEval( pArgs, nArgs, Type ); printf( "\n" ); assert( Type == IVY_AND || Type == IVY_EXOR ); assert( nArgs > 0 ); if ( nArgs == 1 ) return pArgs[0]; // find the nodes with more than one fanout nArgsNew = 0; for ( i = 0; i < nArgs; i++ ) if ( Ivy_ObjRefs( Ivy_Regular(pArgs[i]) ) > 0 ) pArgsRef[nArgsNew++] = pArgs[i]; // go through pairs if ( nArgsNew >= 2 ) for ( i = 0; i < nArgsNew; i++ ) for ( k = i + 1; k < nArgsNew; k++ ) if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) ) Counter++; // printf( "%d", Counter ); // go through pairs if ( nArgsNew >= 2 ) for ( i = 0; i < nArgsNew; i++ ) for ( k = i + 1; k < nArgsNew; k++ ) if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) ) { nArgsNew = 0; for ( m = 0; m < nArgs; m++ ) if ( pArgs[m] != pArgsRef[i] && pArgs[m] != pArgsRef[k] ) pArgs[nArgsNew++] = pArgs[m]; pArgs[nArgsNew++] = pTemp; assert( nArgsNew == nArgs - 1 ); return Ivy_Multi1( pArgs, nArgsNew, Type ); } return Ivy_Multi_rec( pArgs, nArgs, Type ); } /**Function************************************************************* Synopsis [Old code.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_Multi2( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) { assert( Type == IVY_AND || Type == IVY_EXOR ); assert( nArgs > 0 ); return Ivy_Multi_rec( pArgs, nArgs, Type ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyObj.c000066400000000000000000000370761477524141600157610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyObj.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Adding/removing objects.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_ObjCreatePi( Ivy_Man_t * p ) { return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, NULL, NULL, IVY_PI, IVY_INIT_NONE) ); } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver ) { return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pDriver, NULL, IVY_PO, IVY_INIT_NONE) ); } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost ) { Ivy_Obj_t * pObj; assert( !Ivy_IsComplement(pGhost) ); assert( Ivy_ObjIsGhost(pGhost) ); assert( Ivy_TableLookup(p, pGhost) == NULL ); // get memory for the new object pObj = Ivy_ManFetchMemory( p ); assert( Ivy_ObjIsNone(pObj) ); pObj->Id = Vec_PtrSize(p->vObjs); Vec_PtrPush( p->vObjs, pObj ); // add basic info (fanins, compls, type, init) pObj->Type = pGhost->Type; pObj->Init = pGhost->Init; // add connections Ivy_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); // compute level if ( Ivy_ObjIsNode(pObj) ) pObj->Level = Ivy_ObjLevelNew(pObj); else if ( Ivy_ObjIsLatch(pObj) ) pObj->Level = 0; else if ( Ivy_ObjIsOneFanin(pObj) ) pObj->Level = Ivy_ObjFanin0(pObj)->Level; else if ( !Ivy_ObjIsPi(pObj) ) assert( 0 ); // create phase if ( Ivy_ObjIsNode(pObj) ) pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) & Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)); else if ( Ivy_ObjIsOneFanin(pObj) ) pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)); // set the fail TFO flag if ( Ivy_ObjIsNode(pObj) ) pObj->fFailTfo = Ivy_ObjFanin0(pObj)->fFailTfo | Ivy_ObjFanin1(pObj)->fFailTfo; // mark the fanins in a special way if the node is EXOR if ( Ivy_ObjIsExor(pObj) ) { Ivy_ObjFanin0(pObj)->fExFan = 1; Ivy_ObjFanin1(pObj)->fExFan = 1; } // add PIs/POs to the arrays if ( Ivy_ObjIsPi(pObj) ) Vec_PtrPush( p->vPis, pObj ); else if ( Ivy_ObjIsPo(pObj) ) Vec_PtrPush( p->vPos, pObj ); // else if ( Ivy_ObjIsBuf(pObj) ) // Vec_PtrPush( p->vBufs, pObj ); if ( p->vRequired && Vec_IntSize(p->vRequired) <= pObj->Id ) Vec_IntFillExtra( p->vRequired, 2 * Vec_IntSize(p->vRequired), 1000000 ); // update node counters of the manager p->nObjs[Ivy_ObjType(pObj)]++; p->nCreated++; // printf( "Adding %sAIG node: ", p->pHaig==NULL? "H":" " ); // Ivy_ObjPrintVerbose( p, pObj, p->pHaig==NULL ); // printf( "\n" ); // if HAIG is defined, create a corresponding node if ( p->pHaig ) Ivy_ManHaigCreateObj( p, pObj ); return pObj; } /**Function************************************************************* Synopsis [Connect the object to the fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 ) { assert( !Ivy_IsComplement(pObj) ); assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || pFan1 != NULL ); // add the first fanin pObj->pFanin0 = pFan0; pObj->pFanin1 = pFan1; // increment references of the fanins and add their fanouts if ( Ivy_ObjFanin0(pObj) != NULL ) { Ivy_ObjRefsInc( Ivy_ObjFanin0(pObj) ); if ( p->fFanout ) Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj ); } if ( Ivy_ObjFanin1(pObj) != NULL ) { Ivy_ObjRefsInc( Ivy_ObjFanin1(pObj) ); if ( p->fFanout ) Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj ); } // add the node to the structural hash table Ivy_TableInsert( p, pObj ); } /**Function************************************************************* Synopsis [Connect the object to the fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || Ivy_ObjFanin1(pObj) != NULL ); // remove connections if ( pObj->pFanin0 != NULL ) { Ivy_ObjRefsDec(Ivy_ObjFanin0(pObj)); if ( p->fFanout ) Ivy_ObjDeleteFanout( p, Ivy_ObjFanin0(pObj), pObj ); } if ( pObj->pFanin1 != NULL ) { Ivy_ObjRefsDec(Ivy_ObjFanin1(pObj)); if ( p->fFanout ) Ivy_ObjDeleteFanout( p, Ivy_ObjFanin1(pObj), pObj ); } assert( pObj->pNextFan0 == NULL ); assert( pObj->pNextFan1 == NULL ); assert( pObj->pPrevFan0 == NULL ); assert( pObj->pPrevFan1 == NULL ); // remove the node from the structural hash table Ivy_TableDelete( p, pObj ); // add the first fanin pObj->pFanin0 = NULL; pObj->pFanin1 = NULL; } /**Function************************************************************* Synopsis [Replaces the first fanin of the node by the new fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew ) { Ivy_Obj_t * pFaninOld; assert( !Ivy_IsComplement(pObj) ); pFaninOld = Ivy_ObjFanin0(pObj); // decrement ref and remove fanout Ivy_ObjRefsDec( pFaninOld ); if ( p->fFanout ) Ivy_ObjDeleteFanout( p, pFaninOld, pObj ); // update the fanin pObj->pFanin0 = pFaninNew; // increment ref and add fanout Ivy_ObjRefsInc( Ivy_Regular(pFaninNew) ); if ( p->fFanout ) Ivy_ObjAddFanout( p, Ivy_Regular(pFaninNew), pObj ); // get rid of old fanin if ( !Ivy_ObjIsPi(pFaninOld) && !Ivy_ObjIsConst1(pFaninOld) && Ivy_ObjRefs(pFaninOld) == 0 ) Ivy_ObjDelete_rec( p, pFaninOld, 1 ); } /**Function************************************************************* Synopsis [Deletes the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) { assert( !Ivy_IsComplement(pObj) ); assert( Ivy_ObjRefs(pObj) == 0 || !fFreeTop ); // update node counters of the manager p->nObjs[pObj->Type]--; p->nDeleted++; // remove connections Ivy_ObjDisconnect( p, pObj ); // remove PIs/POs from the arrays if ( Ivy_ObjIsPi(pObj) ) Vec_PtrRemove( p->vPis, pObj ); else if ( Ivy_ObjIsPo(pObj) ) Vec_PtrRemove( p->vPos, pObj ); else if ( p->fFanout && Ivy_ObjIsBuf(pObj) ) Vec_PtrRemove( p->vBufs, pObj ); // clean and recycle the entry if ( fFreeTop ) { // free the node Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); Ivy_ManRecycleMemory( p, pObj ); } else { int nRefsOld = pObj->nRefs; Ivy_Obj_t * pFanout = pObj->pFanout; Ivy_ObjClean( pObj ); pObj->pFanout = pFanout; pObj->nRefs = nRefsOld; } } /**Function************************************************************* Synopsis [Deletes the MFFC of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) { Ivy_Obj_t * pFanin0, * pFanin1; assert( !Ivy_IsComplement(pObj) ); assert( !Ivy_ObjIsNone(pObj) ); if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsPi(pObj) ) return; pFanin0 = Ivy_ObjFanin0(pObj); pFanin1 = Ivy_ObjFanin1(pObj); Ivy_ObjDelete( p, pObj, fFreeTop ); if ( pFanin0 && !Ivy_ObjIsNone(pFanin0) && Ivy_ObjRefs(pFanin0) == 0 ) Ivy_ObjDelete_rec( p, pFanin0, 1 ); if ( pFanin1 && !Ivy_ObjIsNone(pFanin1) && Ivy_ObjRefs(pFanin1) == 0 ) Ivy_ObjDelete_rec( p, pFanin1, 1 ); } /**Function************************************************************* Synopsis [Replaces one object by another.] Description [Both objects are currently in the manager. The new object (pObjNew) should be used instead of the old object (pObjOld). If the new object is complemented or used, the buffer is added.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel ) { int nRefsOld;//, clk; // the object to be replaced cannot be complemented assert( !Ivy_IsComplement(pObjOld) ); // the object to be replaced cannot be a terminal assert( Ivy_ObjIsNone(pObjOld) || !Ivy_ObjIsPi(pObjOld) ); // the object to be used cannot be a PO or assert assert( !Ivy_ObjIsBuf(Ivy_Regular(pObjNew)) ); // the object cannot be the same assert( pObjOld != Ivy_Regular(pObjNew) ); //printf( "Replacing %d by %d.\n", Ivy_Regular(pObjOld)->Id, Ivy_Regular(pObjNew)->Id ); // if HAIG is defined, create the choice node if ( p->pHaig ) { // if ( pObjOld->Id == 31 ) // { // Ivy_ManShow( p, 0 ); // Ivy_ManShow( p->pHaig, 1 ); // } Ivy_ManHaigCreateChoice( p, pObjOld, pObjNew ); } // if the new object is complemented or already used, add the buffer if ( Ivy_IsComplement(pObjNew) || Ivy_ObjIsLatch(pObjNew) || Ivy_ObjRefs(pObjNew) > 0 || Ivy_ObjIsPi(pObjNew) || Ivy_ObjIsConst1(pObjNew) ) pObjNew = Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pObjNew, NULL, IVY_BUF, IVY_INIT_NONE) ); assert( !Ivy_IsComplement(pObjNew) ); if ( fUpdateLevel ) { //clk = Abc_Clock(); // if the new node's arrival time is different, recursively update arrival time of the fanouts if ( p->fFanout && !Ivy_ObjIsBuf(pObjNew) && pObjOld->Level != pObjNew->Level ) { assert( Ivy_ObjIsNode(pObjOld) ); pObjOld->Level = pObjNew->Level; Ivy_ObjUpdateLevel_rec( p, pObjOld ); } //p->time1 += Abc_Clock() - clk; // if the new node's required time has changed, recursively update required time of the fanins //clk = Abc_Clock(); if ( p->vRequired ) { int ReqNew = Vec_IntEntry(p->vRequired, pObjOld->Id); if ( ReqNew < Vec_IntEntry(p->vRequired, pObjNew->Id) ) { Vec_IntWriteEntry( p->vRequired, pObjNew->Id, ReqNew ); Ivy_ObjUpdateLevelR_rec( p, pObjNew, ReqNew ); } } //p->time2 += Abc_Clock() - clk; } // delete the old object if ( fDeleteOld ) Ivy_ObjDelete_rec( p, pObjOld, fFreeTop ); // make sure object is not pointing to itself assert( Ivy_ObjFanin0(pObjNew) == NULL || pObjOld != Ivy_ObjFanin0(pObjNew) ); assert( Ivy_ObjFanin1(pObjNew) == NULL || pObjOld != Ivy_ObjFanin1(pObjNew) ); // make sure the old node has no fanin fanout pointers if ( p->fFanout ) { assert( pObjOld->pFanout != NULL ); assert( pObjNew->pFanout == NULL ); pObjNew->pFanout = pObjOld->pFanout; } // transfer the old object assert( Ivy_ObjRefs(pObjNew) == 0 ); nRefsOld = pObjOld->nRefs; Ivy_ObjOverwrite( pObjOld, pObjNew ); pObjOld->nRefs = nRefsOld; // patch the fanout of the fanins if ( p->fFanout ) { Ivy_ObjPatchFanout( p, Ivy_ObjFanin0(pObjOld), pObjNew, pObjOld ); if ( Ivy_ObjFanin1(pObjOld) ) Ivy_ObjPatchFanout( p, Ivy_ObjFanin1(pObjOld), pObjNew, pObjOld ); } // update the hash table Ivy_TableUpdate( p, pObjNew, pObjOld->Id ); // recycle the object that was taken over by pObjOld Vec_PtrWriteEntry( p->vObjs, pObjNew->Id, NULL ); Ivy_ManRecycleMemory( p, pObjNew ); // if the new node is the buffer propagate it if ( p->fFanout && Ivy_ObjIsBuf(pObjOld) ) Vec_PtrPush( p->vBufs, pObjOld ); // Ivy_ManCheckFanouts( p ); // printf( "\n" ); /* if ( p->pHaig ) { int x; Ivy_ManShow( p, 0, NULL ); Ivy_ManShow( p->pHaig, 1, NULL ); x = 0; } */ // if ( Ivy_ManCheckFanoutNums(p) ) // { // int x = 0; // } } /**Function************************************************************* Synopsis [Fixes buffer fanins.] Description [This situation happens because NodeReplace is a lazy procedure, which does not propagate the change to the fanouts but instead records the change in the form of a buf/inv node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel ) { Ivy_Obj_t * pFanReal0, * pFanReal1, * pResult = NULL; if ( Ivy_ObjIsPo(pNode) ) { if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) ) return; pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) ); Ivy_ObjPatchFanin0( p, pNode, pFanReal0 ); // Ivy_ManCheckFanouts( p ); return; } if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) && !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) ) return; // get the real fanins pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) ); pFanReal1 = Ivy_ObjReal( Ivy_ObjChild1(pNode) ); // get the new node if ( Ivy_ObjIsNode(pNode) ) pResult = Ivy_Oper( p, pFanReal0, pFanReal1, Ivy_ObjType(pNode) ); else if ( Ivy_ObjIsLatch(pNode) ) pResult = Ivy_Latch( p, pFanReal0, Ivy_ObjInit(pNode) ); else assert( 0 ); //printf( "===== Replacing %d by %d.\n", pNode->Id, pResult->Id ); //Ivy_ObjPrintVerbose( p, pNode, 0 ); printf( "\n" ); //Ivy_ObjPrintVerbose( p, pResult, 0 ); printf( "\n" ); // perform the replacement Ivy_ObjReplace( p, pNode, pResult, 1, 0, fUpdateLevel ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyOper.c000066400000000000000000000224011477524141600161360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyOper.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [AIG operations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // procedure to detect an EXOR gate static inline int Ivy_ObjIsExorType( Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Obj_t ** ppFan0, Ivy_Obj_t ** ppFan1 ) { if ( !Ivy_IsComplement(p0) || !Ivy_IsComplement(p1) ) return 0; p0 = Ivy_Regular(p0); p1 = Ivy_Regular(p1); if ( !Ivy_ObjIsAnd(p0) || !Ivy_ObjIsAnd(p1) ) return 0; if ( Ivy_ObjFanin0(p0) != Ivy_ObjFanin0(p1) || Ivy_ObjFanin1(p0) != Ivy_ObjFanin1(p1) ) return 0; if ( Ivy_ObjFaninC0(p0) == Ivy_ObjFaninC0(p1) || Ivy_ObjFaninC1(p0) == Ivy_ObjFaninC1(p1) ) return 0; *ppFan0 = Ivy_ObjChild0(p0); *ppFan1 = Ivy_ObjChild1(p0); return 1; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Perform one operation.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type ) { if ( Type == IVY_AND ) return Ivy_And( p, p0, p1 ); if ( Type == IVY_EXOR ) return Ivy_Exor( p, p0, p1 ); assert( 0 ); return NULL; } /**Function************************************************************* Synopsis [Performs canonicization step.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) { // Ivy_Obj_t * pFan0, * pFan1; // check trivial cases if ( p0 == p1 ) return p0; if ( p0 == Ivy_Not(p1) ) return Ivy_Not(p->pConst1); if ( Ivy_Regular(p0) == p->pConst1 ) return p0 == p->pConst1 ? p1 : Ivy_Not(p->pConst1); if ( Ivy_Regular(p1) == p->pConst1 ) return p1 == p->pConst1 ? p0 : Ivy_Not(p->pConst1); // check if it can be an EXOR gate // if ( Ivy_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) // return Ivy_CanonExor( pFan0, pFan1 ); return Ivy_CanonAnd( p, p0, p1 ); } /**Function************************************************************* Synopsis [Performs canonicization step.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) { /* // check trivial cases if ( p0 == p1 ) return Ivy_Not(p->pConst1); if ( p0 == Ivy_Not(p1) ) return p->pConst1; if ( Ivy_Regular(p0) == p->pConst1 ) return Ivy_NotCond( p1, p0 == p->pConst1 ); if ( Ivy_Regular(p1) == p->pConst1 ) return Ivy_NotCond( p0, p1 == p->pConst1 ); // check the table return Ivy_CanonExor( p, p0, p1 ); */ return Ivy_Or( p, Ivy_And(p, p0, Ivy_Not(p1)), Ivy_And(p, Ivy_Not(p0), p1) ); } /**Function************************************************************* Synopsis [Implements Boolean OR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) { return Ivy_Not( Ivy_And( p, Ivy_Not(p0), Ivy_Not(p1) ) ); } /**Function************************************************************* Synopsis [Implements ITE operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 ) { Ivy_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; int Count0, Count1; // consider trivial cases if ( p0 == Ivy_Not(p1) ) return Ivy_Exor( p, pC, p0 ); // other cases can be added // implement the first MUX (F = C * x1 + C' * x0) pTempA1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC, p1, IVY_AND, IVY_INIT_NONE) ); pTempA2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), p0, IVY_AND, IVY_INIT_NONE) ); if ( pTempA1 && pTempA2 ) { pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempA1), Ivy_Not(pTempA2), IVY_AND, IVY_INIT_NONE) ); if ( pTemp ) return Ivy_Not(pTemp); } Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); // implement the second MUX (F' = C * x1' + C' * x0') pTempB1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC, Ivy_Not(p1), IVY_AND, IVY_INIT_NONE) ); pTempB2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), Ivy_Not(p0), IVY_AND, IVY_INIT_NONE) ); if ( pTempB1 && pTempB2 ) { pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempB1), Ivy_Not(pTempB2), IVY_AND, IVY_INIT_NONE) ); if ( pTemp ) return pTemp; } Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); // compare and decide which one to implement if ( Count0 >= Count1 ) { pTempA1 = pTempA1? pTempA1 : Ivy_And(p, pC, p1); pTempA2 = pTempA2? pTempA2 : Ivy_And(p, Ivy_Not(pC), p0); return Ivy_Or( p, pTempA1, pTempA2 ); } pTempB1 = pTempB1? pTempB1 : Ivy_And(p, pC, Ivy_Not(p1)); pTempB2 = pTempB2? pTempB2 : Ivy_And(p, Ivy_Not(pC), Ivy_Not(p0)); return Ivy_Not( Ivy_Or( p, pTempB1, pTempB2 ) ); // return Ivy_Or( Ivy_And(pC, p1), Ivy_And(Ivy_Not(pC), p0) ); } /**Function************************************************************* Synopsis [Implements ITE operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC ) { return Ivy_Or( p, Ivy_Or(p, Ivy_And(p, pA, pB), Ivy_And(p, pA, pC)), Ivy_And(p, pB, pC) ); } /**Function************************************************************* Synopsis [Constructs the well-balanced tree of gates.] Description [Disregards levels and possible logic sharing.] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ) { Ivy_Obj_t * pObj1, * pObj2; if ( nObjs == 1 ) return ppObjs[0]; pObj1 = Ivy_Multi_rec( p, ppObjs, nObjs/2, Type ); pObj2 = Ivy_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); return Ivy_Oper( p, pObj1, pObj2, Type ); } /**Function************************************************************* Synopsis [Old code.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) { assert( Type == IVY_AND || Type == IVY_EXOR ); assert( nArgs > 0 ); return Ivy_Multi_rec( p, pArgs, nArgs, Type ); } /**Function************************************************************* Synopsis [Implements the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs ) { int i; assert( vPairs->nSize > 0 ); assert( vPairs->nSize % 2 == 0 ); // go through the cubes of the node's SOP for ( i = 0; i < vPairs->nSize; i += 2 ) vPairs->pArray[i/2] = Ivy_Not( Ivy_Exor( p, (Ivy_Obj_t *)vPairs->pArray[i], (Ivy_Obj_t *)vPairs->pArray[i+1] ) ); vPairs->nSize = vPairs->nSize/2; return Ivy_Not( Ivy_Multi_rec( p, (Ivy_Obj_t **)vPairs->pArray, vPairs->nSize, IVY_AND ) ); } /**Function************************************************************* Synopsis [Performs canonicization step.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ) { return Ivy_CanonLatch( p, pObj, Init ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyResyn.c000066400000000000000000000137241477524141600163410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyResyn.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [AIG rewriting script.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyResyn.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs several passes of rewriting on the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Man_t * Ivy_ManResyn0( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose ) { abctime clk; Ivy_Man_t * pTemp; if ( fVerbose ) { printf( "Original:\n" ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); clk = Abc_Clock(); pMan = Ivy_ManBalance( pMan, fUpdateLevel ); if ( fVerbose ) { printf( "\n" ); } if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); // Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 ); clk = Abc_Clock(); Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 ); if ( fVerbose ) { printf( "\n" ); } if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); clk = Abc_Clock(); pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); Ivy_ManStop( pTemp ); if ( fVerbose ) { printf( "\n" ); } if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); return pMan; } /**Function************************************************************* Synopsis [Performs several passes of rewriting on the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose ) { abctime clk; Ivy_Man_t * pTemp; if ( fVerbose ) { printf( "Original:\n" ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); clk = Abc_Clock(); pMan = Ivy_ManBalance( pMan, fUpdateLevel ); if ( fVerbose ) { printf( "\n" ); } if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); // Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 ); clk = Abc_Clock(); Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 ); if ( fVerbose ) { printf( "\n" ); } if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); clk = Abc_Clock(); pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); Ivy_ManStop( pTemp ); if ( fVerbose ) { printf( "\n" ); } if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); // Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 ); clk = Abc_Clock(); Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 ); if ( fVerbose ) { printf( "\n" ); } if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); clk = Abc_Clock(); pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); Ivy_ManStop( pTemp ); if ( fVerbose ) { printf( "\n" ); } if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); // Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 ); clk = Abc_Clock(); Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 ); if ( fVerbose ) { printf( "\n" ); } if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); clk = Abc_Clock(); pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); Ivy_ManStop( pTemp ); if ( fVerbose ) { printf( "\n" ); } if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); return pMan; } /**Function************************************************************* Synopsis [Performs several passes of rewriting on the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Man_t * Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose ) { abctime clk; Ivy_Man_t * pTemp; if ( fVerbose ) { printf( "Original:\n" ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); clk = Abc_Clock(); Ivy_ManRewritePre( pMan, 0, 0, 0 ); if ( fVerbose ) { printf( "\n" ); } if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); clk = Abc_Clock(); pMan = Ivy_ManBalance( pTemp = pMan, 0 ); // pMan = Ivy_ManDup( pTemp = pMan ); Ivy_ManStop( pTemp ); if ( fVerbose ) { printf( "\n" ); } if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); /* clk = Abc_Clock(); Ivy_ManRewritePre( pMan, 0, 0, 0 ); if ( fVerbose ) { printf( "\n" ); } if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); clk = Abc_Clock(); pMan = Ivy_ManBalance( pTemp = pMan, 0 ); Ivy_ManStop( pTemp ); if ( fVerbose ) { printf( "\n" ); } if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } if ( fVerbose ) Ivy_ManPrintStats( pMan ); */ return pMan; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyRwr.c000066400000000000000000000526511477524141600160150ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyRwt.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Rewriting based on precomputation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyRwt.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" #include "bool/deco/deco.h" #include "opt/rwt/rwt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums ); static int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost ); static Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth ); static int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ); static void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs incremental rewriting of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose ) { Rwt_Man_t * pManRwt; Ivy_Obj_t * pNode; int i, nNodes, nGain; abctime clk, clkStart = Abc_Clock(); // start the rewriting manager pManRwt = Rwt_ManStart( 0 ); p->pData = pManRwt; if ( pManRwt == NULL ) return 0; // create fanouts if ( fUpdateLevel && p->fFanout == 0 ) Ivy_ManStartFanout( p ); // compute the reverse levels if level update is requested if ( fUpdateLevel ) Ivy_ManRequiredLevels( p ); // set the number of levels // p->nLevelMax = Ivy_ManLevels( p ); // resynthesize each node once nNodes = Ivy_ManObjIdMax(p); Ivy_ManForEachNode( p, pNode, i ) { // fix the fanin buffer problem Ivy_NodeFixBufferFanins( p, pNode, 1 ); if ( Ivy_ObjIsBuf(pNode) ) continue; // stop if all nodes have been tried once if ( i > nNodes ) break; // for each cut, try to resynthesize it nGain = Ivy_NodeRewrite( p, pManRwt, pNode, fUpdateLevel, fUseZeroCost ); if ( nGain > 0 || (nGain == 0 && fUseZeroCost) ) { Dec_Graph_t * pGraph = (Dec_Graph_t *)Rwt_ManReadDecs(pManRwt); int fCompl = Rwt_ManReadCompl(pManRwt); /* { Ivy_Obj_t * pObj; int i; printf( "USING: (" ); Vec_PtrForEachEntry( Ivy_Obj_t *, Rwt_ManReadLeaves(pManRwt), pObj, i ) printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pObj)) ); printf( ") Gain = %d.\n", nGain ); } if ( nGain > 0 ) { // print stats on the MFFC extern void Ivy_NodeMffcConeSuppPrint( Ivy_Obj_t * pNode ); printf( "Node %6d : Gain = %4d ", pNode->Id, nGain ); Ivy_NodeMffcConeSuppPrint( pNode ); } */ // complement the FF if needed clk = Abc_Clock(); if ( fCompl ) Dec_GraphComplement( pGraph ); Ivy_GraphUpdateNetwork( p, pNode, pGraph, fUpdateLevel, nGain ); if ( fCompl ) Dec_GraphComplement( pGraph ); Rwt_ManAddTimeUpdate( pManRwt, Abc_Clock() - clk ); } } Rwt_ManAddTimeTotal( pManRwt, Abc_Clock() - clkStart ); // print stats if ( fVerbose ) Rwt_ManPrintStats( pManRwt ); // delete the managers Rwt_ManStop( pManRwt ); p->pData = NULL; // fix the levels if ( fUpdateLevel ) Vec_IntFree( p->vRequired ), p->vRequired = NULL; else Ivy_ManResetLevels( p ); // check if ( (i = Ivy_ManCleanup(p)) ) printf( "Cleanup after rewriting removed %d dangling nodes.\n", i ); if ( !Ivy_ManCheck(p) ) printf( "Ivy_ManRewritePre(): The check has failed.\n" ); return 1; } /**Function************************************************************* Synopsis [Performs rewriting for one node.] Description [This procedure considers all the cuts computed for the node and tries to rewrite each of them using the "forest" of different AIG structures precomputed and stored in the RWR manager. Determines the best rewriting and computes the gain in the number of AIG nodes in the final network. In the end, p->vFanins contains information about the best cut that can be used for rewriting, while p->pGraph gives the decomposition dag (represented using decomposition graph data structure). Returns gain in the number of nodes or -1 if node cannot be rewritten.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost ) { int fVeryVerbose = 0; Dec_Graph_t * pGraph; Ivy_Store_t * pStore; Ivy_Cut_t * pCut; Ivy_Obj_t * pFanin; unsigned uPhase; unsigned uTruthBest = 0; // Suppress "might be used uninitialized" unsigned uTruth; char * pPerm; int Required, nNodesSaved; int nNodesSaveCur = -1; // Suppress "might be used uninitialized" int i, c, GainCur = -1, GainBest = -1; abctime clk, clk2; p->nNodesConsidered++; // get the required times Required = fUpdateLevel? Vec_IntEntry( pMan->vRequired, pNode->Id ) : 1000000; // get the node's cuts clk = Abc_Clock(); pStore = Ivy_NodeFindCutsAll( pMan, pNode, 5 ); p->timeCut += Abc_Clock() - clk; // go through the cuts clk = Abc_Clock(); for ( c = 1; c < pStore->nCuts; c++ ) { pCut = pStore->pCuts + c; // consider only 4-input cuts if ( pCut->nSize != 4 ) continue; // skip the cuts with buffers for ( i = 0; i < (int)pCut->nSize; i++ ) if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, pCut->pArray[i]) ) ) break; if ( i != pCut->nSize ) { p->nCutsBad++; continue; } p->nCutsGood++; // get the fanin permutation clk2 = Abc_Clock(); uTruth = 0xFFFF & Ivy_NodeGetTruth( pNode, pCut->pArray, pCut->nSize ); // truth table p->timeTruth += Abc_Clock() - clk2; pPerm = p->pPerms4[ (int) p->pPerms[uTruth] ]; uPhase = p->pPhases[uTruth]; // collect fanins with the corresponding permutation/phase Vec_PtrClear( p->vFaninsCur ); Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 ); for ( i = 0; i < (int)pCut->nSize; i++ ) { pFanin = Ivy_ManObj( pMan, pCut->pArray[(int)pPerm[i]] ); assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) ); pFanin = Ivy_NotCond(pFanin, ((uPhase & (1< 0) ); Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); } clk2 = Abc_Clock(); /* printf( "Considering: (" ); Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i ) printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pFanin)) ); printf( ")\n" ); */ // mark the fanin boundary Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i ) Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); // label MFFC with current ID Ivy_ManIncrementTravId( pMan ); nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode ); // unmark the fanin boundary Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i ) Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); p->timeMffc += Abc_Clock() - clk2; // evaluate the cut clk2 = Abc_Clock(); pGraph = Rwt_CutEvaluate( pMan, p, pNode, p->vFaninsCur, nNodesSaved, Required, &GainCur, uTruth ); p->timeEval += Abc_Clock() - clk2; // check if the cut is better than the current best one if ( pGraph != NULL && GainBest < GainCur ) { // save this form nNodesSaveCur = nNodesSaved; GainBest = GainCur; p->pGraph = pGraph; p->fCompl = ((uPhase & (1<<4)) > 0); uTruthBest = uTruth; // collect fanins in the Vec_PtrClear( p->vFanins ); Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i ) Vec_PtrPush( p->vFanins, pFanin ); } } p->timeRes += Abc_Clock() - clk; if ( GainBest == -1 ) return -1; // printf( "%d", nNodesSaveCur - GainBest ); /* if ( GainBest > 0 ) { if ( Rwt_CutIsintean( pNode, p->vFanins ) ) printf( "b" ); else { printf( "Node %d : ", pNode->Id ); Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFanins, pFanin, i ) printf( "%d ", Ivy_Regular(pFanin)->Id ); printf( "a" ); } } */ /* if ( GainBest > 0 ) if ( p->fCompl ) printf( "c" ); else printf( "." ); */ // copy the leaves Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFanins, pFanin, i ) Dec_GraphNode((Dec_Graph_t *)p->pGraph, i)->pFunc = pFanin; p->nScores[p->pMap[uTruthBest]]++; p->nNodesGained += GainBest; if ( fUseZeroCost || GainBest > 0 ) p->nNodesRewritten++; // report the progress if ( fVeryVerbose && GainBest > 0 ) { printf( "Node %6d : ", Ivy_ObjId(pNode) ); printf( "Fanins = %d. ", p->vFanins->nSize ); printf( "Save = %d. ", nNodesSaveCur ); printf( "Add = %d. ", nNodesSaveCur-GainBest ); printf( "GAIN = %d. ", GainBest ); printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum((Dec_Graph_t *)p->pGraph) : 0 ); printf( "Class = %d. ", p->pMap[uTruthBest] ); printf( "\n" ); } return GainBest; } /**Function************************************************************* Synopsis [Computes the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Ivy_NodeGetTruth_rec( Ivy_Obj_t * pObj, int * pNums, int nNums ) { static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; unsigned uTruth0, uTruth1; int i; for ( i = 0; i < nNums; i++ ) if ( pObj->Id == pNums[i] ) return uMasks[i]; assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); uTruth0 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin0(pObj), pNums, nNums ); if ( Ivy_ObjFaninC0(pObj) ) uTruth0 = ~uTruth0; if ( Ivy_ObjIsBuf(pObj) ) return uTruth0; uTruth1 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin1(pObj), pNums, nNums ); if ( Ivy_ObjFaninC1(pObj) ) uTruth1 = ~uTruth1; return uTruth0 & uTruth1; } /**Function************************************************************* Synopsis [Computes the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums ) { assert( nNums < 6 ); return Ivy_NodeGetTruth_rec( pObj, pNums, nNums ); } /**Function************************************************************* Synopsis [Evaluates the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth ) { Vec_Ptr_t * vSubgraphs; Dec_Graph_t * pGraphBest = NULL; // Suppress "might be used uninitialized" Dec_Graph_t * pGraphCur; Rwt_Node_t * pNode, * pFanin; int nNodesAdded, GainBest, i, k; // find the matching class of subgraphs vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); p->nSubgraphs += vSubgraphs->nSize; // determine the best subgraph GainBest = -1; Vec_PtrForEachEntry( Rwt_Node_t *, vSubgraphs, pNode, i ) { // get the current graph pGraphCur = (Dec_Graph_t *)pNode->pNext; // copy the leaves Vec_PtrForEachEntry( Rwt_Node_t *, vFaninsCur, pFanin, k ) Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; // detect how many unlabeled nodes will be reused nNodesAdded = Ivy_GraphToNetworkCount( pMan, pRoot, pGraphCur, nNodesSaved, LevelMax ); if ( nNodesAdded == -1 ) continue; assert( nNodesSaved >= nNodesAdded ); // count the gain at this node if ( GainBest < nNodesSaved - nNodesAdded ) { GainBest = nNodesSaved - nNodesAdded; pGraphBest = pGraphCur; } } if ( GainBest == -1 ) return NULL; *pGainBest = GainBest; return pGraphBest; } /**Function************************************************************* Synopsis [Counts the number of new nodes added when using this graph.] Description [AIG nodes for the fanins should be assigned to pNode->pFunc of the leaves of the graph before calling this procedure. Returns -1 if the number of nodes and levels exceeded the given limit or the number of levels exceeded the maximum allowed level.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ) { Dec_Node_t * pNode, * pNode0, * pNode1; Ivy_Obj_t * pAnd, * pAnd0, * pAnd1; int i, Counter, LevelNew, LevelOld; // check for constant function or a literal if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) return 0; // set the levels of the leaves Dec_GraphForEachLeaf( pGraph, pNode, i ) pNode->Level = Ivy_Regular((Ivy_Obj_t *)pNode->pFunc)->Level; // compute the AIG size after adding the internal nodes Counter = 0; Dec_GraphForEachNode( pGraph, pNode, i ) { // get the children of this node pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); // get the AIG nodes corresponding to the children pAnd0 = (Ivy_Obj_t *)pNode0->pFunc; pAnd1 = (Ivy_Obj_t *)pNode1->pFunc; if ( pAnd0 && pAnd1 ) { // if they are both present, find the resulting node pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl ); pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl ); pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) ); // return -1 if the node is the same as the original root if ( Ivy_Regular(pAnd) == pRoot ) return -1; } else pAnd = NULL; // count the number of added nodes if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) ) { if ( ++Counter > NodeMax ) return -1; } // count the number of new levels LevelNew = 1 + RWT_MAX( pNode0->Level, pNode1->Level ); if ( pAnd ) { if ( Ivy_Regular(pAnd) == p->pConst1 ) LevelNew = 0; else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd0) ) LevelNew = (int)Ivy_Regular(pAnd0)->Level; else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd1) ) LevelNew = (int)Ivy_Regular(pAnd1)->Level; LevelOld = (int)Ivy_Regular(pAnd)->Level; // assert( LevelNew == LevelOld ); } if ( LevelNew > LevelMax ) return -1; pNode->pFunc = pAnd; pNode->Level = LevelNew; } return Counter; } /**Function************************************************************* Synopsis [Transforms the decomposition graph into the AIG.] Description [AIG nodes for the fanins should be assigned to pNode->pFunc of the leaves of the graph before calling this procedure.] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_GraphToNetwork( Ivy_Man_t * p, Dec_Graph_t * pGraph ) { Ivy_Obj_t * pAnd0, * pAnd1; Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" int i; // check for constant function if ( Dec_GraphIsConst(pGraph) ) return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) ); // check for a literal if ( Dec_GraphIsVar(pGraph) ) return Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); // build the AIG nodes corresponding to the AND gates of the graph Dec_GraphForEachNode( pGraph, pNode, i ) { pAnd0 = Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); pAnd1 = Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 ); } // complement the result if necessary return Ivy_NotCond( (Ivy_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); } /**Function************************************************************* Synopsis [Replaces MFFC of the node by the new factored form.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ) { Ivy_Obj_t * pRootNew; int nNodesNew, nNodesOld, Required; Required = fUpdateLevel? Vec_IntEntry( p->vRequired, pRoot->Id ) : 1000000; nNodesOld = Ivy_ManNodeNum(p); // create the new structure of nodes pRootNew = Ivy_GraphToNetwork( p, pGraph ); assert( (int)Ivy_Regular(pRootNew)->Level <= Required ); // if ( Ivy_Regular(pRootNew)->Level == Required ) // printf( "Difference %d.\n", Ivy_Regular(pRootNew)->Level - Required ); // remove the old nodes // Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel ); /* if ( Ivy_IsComplement(pRootNew) ) printf( "c" ); else printf( "d" ); if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 ) printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) ); printf( " " ); */ Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 1 ); // compare the gains nNodesNew = Ivy_ManNodeNum(p); assert( nGain <= nNodesOld - nNodesNew ); // propagate the buffer Ivy_ManPropagateBuffers( p, 1 ); } /**Function************************************************************* Synopsis [Replaces MFFC of the node by the new factored form.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_GraphUpdateNetwork3( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ) { Ivy_Obj_t * pRootNew, * pFanin; int nNodesNew, nNodesOld, i, nRefsOld; nNodesOld = Ivy_ManNodeNum(p); //printf( "Before = %d. ", Ivy_ManNodeNum(p) ); // mark the cut Vec_PtrForEachEntry( Ivy_Obj_t *, ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); // deref the old cone nRefsOld = pRoot->nRefs; pRoot->nRefs = 0; Ivy_ObjDelete_rec( p, pRoot, 0 ); pRoot->nRefs = nRefsOld; // unmark the cut Vec_PtrForEachEntry( Ivy_Obj_t *, ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); //printf( "Deref = %d. ", Ivy_ManNodeNum(p) ); // create the new structure of nodes pRootNew = Ivy_GraphToNetwork( p, pGraph ); //printf( "Create = %d. ", Ivy_ManNodeNum(p) ); // remove the old nodes // Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel ); /* if ( Ivy_IsComplement(pRootNew) ) printf( "c" ); else printf( "d" ); if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 ) printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) ); printf( " " ); */ Ivy_ObjReplace( p, pRoot, pRootNew, 0, 0, 1 ); //printf( "Replace = %d. ", Ivy_ManNodeNum(p) ); // delete remaining dangling nodes Vec_PtrForEachEntry( Ivy_Obj_t *, ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) { pFanin = Ivy_Regular(pFanin); if ( !Ivy_ObjIsNone(pFanin) && Ivy_ObjRefs(pFanin) == 0 ) Ivy_ObjDelete_rec( p, pFanin, 1 ); } //printf( "Deref = %d. ", Ivy_ManNodeNum(p) ); //printf( "\n" ); // compare the gains nNodesNew = Ivy_ManNodeNum(p); assert( nGain <= nNodesOld - nNodesNew ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyRwrAlg.c000066400000000000000000000323101477524141600164270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyRwrAlg.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Algebraic AIG rewriting.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyRwrAlg.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ); static Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost ); static int Ivy_NodeCountMffc( Ivy_Obj_t * pNode ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Algebraic AIG rewriting.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ) { Vec_Int_t * vRequired; Vec_Ptr_t * vFront, * vLeaves, * vCone, * vSol; Ivy_Obj_t * pObj, * pResult; int i, RetValue, LevelR, nNodesOld; int CountUsed, CountUndo; vRequired = fUpdateLevel? Ivy_ManRequiredLevels( p ) : NULL; vFront = Vec_PtrAlloc( 100 ); vLeaves = Vec_PtrAlloc( 100 ); vCone = Vec_PtrAlloc( 100 ); vSol = Vec_PtrAlloc( 100 ); // go through the nodes in the topological order CountUsed = CountUndo = 0; nNodesOld = Ivy_ManObjIdNext(p); Ivy_ManForEachObj( p, pObj, i ) { assert( !Ivy_ObjIsBuf(pObj) ); if ( i >= nNodesOld ) break; // skip no-nodes and MUX roots if ( !Ivy_ObjIsNode(pObj) || Ivy_ObjIsExor(pObj) || Ivy_ObjIsMuxType(pObj) ) continue; // if ( pObj->Id > 297 ) // 296 --- 297 // break; if ( pObj->Id == 297 ) { int x = 0; } // get the largest algebraic cut RetValue = Ivy_ManFindAlgCut( pObj, vFront, vLeaves, vCone ); // the case of a trivial tree cut if ( RetValue == 1 ) continue; // the case of constant 0 cone if ( RetValue == -1 ) { Ivy_ObjReplace( pObj, Ivy_ManConst0(p), 1, 0, 1 ); continue; } assert( Vec_PtrSize(vLeaves) > 2 ); // get the required level for this node LevelR = vRequired? Vec_IntEntry(vRequired, pObj->Id) : 1000000; // create a new cone pResult = Ivy_NodeRewriteAlg( pObj, vFront, vLeaves, vCone, vSol, LevelR, fUseZeroCost ); if ( pResult == NULL || pResult == pObj ) continue; assert( Vec_PtrSize(vSol) == 1 || !Ivy_IsComplement(pResult) ); if ( Ivy_ObjLevel(Ivy_Regular(pResult)) > LevelR && Ivy_ObjRefs(Ivy_Regular(pResult)) == 0 ) Ivy_ObjDelete_rec(Ivy_Regular(pResult), 1), CountUndo++; else Ivy_ObjReplace( pObj, pResult, 1, 0, 1 ), CountUsed++; } printf( "Used = %d. Undo = %d.\n", CountUsed, CountUndo ); Vec_PtrFree( vFront ); Vec_PtrFree( vCone ); Vec_PtrFree( vSol ); if ( vRequired ) Vec_IntFree( vRequired ); if ( i = Ivy_ManCleanup(p) ) printf( "Cleanup after rewriting removed %d dangling nodes.\n", i ); if ( !Ivy_ManCheck(p) ) printf( "Ivy_ManRewriteAlg(): The check has failed.\n" ); return 1; } /**Function************************************************************* Synopsis [Analizes one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost ) { int fVerbose = 0; Ivy_Obj_t * pTemp; int k, Counter, nMffc, RetValue; if ( fVerbose ) { if ( Ivy_ObjIsExor(pObj) ) printf( "x " ); else printf( " " ); } /* printf( "%d ", Vec_PtrSize(vFront) ); printf( "( " ); Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, k ) printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) ); printf( ")\n" ); */ // collect nodes in the cone if ( Ivy_ObjIsExor(pObj) ) Ivy_ManCollectCone( pObj, vFront, vCone ); else Ivy_ManCollectCone( pObj, vLeaves, vCone ); // deref nodes in the cone Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pTemp, k ) { Ivy_ObjRefsDec( Ivy_ObjFanin0(pTemp) ); Ivy_ObjRefsDec( Ivy_ObjFanin1(pTemp) ); pTemp->fMarkB = 1; } // count the MFFC size Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, k ) Ivy_Regular(pTemp)->fMarkA = 1; nMffc = Ivy_NodeCountMffc( pObj ); Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, k ) Ivy_Regular(pTemp)->fMarkA = 0; if ( fVerbose ) { Counter = 0; Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pTemp, k ) Counter += (Ivy_ObjRefs(pTemp) > 0); printf( "%5d : Leaves = %2d. Cone = %2d. ConeRef = %2d. Mffc = %d. Lev = %d. LevR = %d.\n", pObj->Id, Vec_PtrSize(vFront), Vec_PtrSize(vCone), Counter-1, nMffc, Ivy_ObjLevel(pObj), LevelR ); } /* printf( "Leaves:" ); Vec_PtrForEachEntry( Ivy_Obj_t *, vLeaves, pTemp, k ) printf( " %d%s", Ivy_Regular(pTemp)->Id, Ivy_IsComplement(pTemp)? "\'" : "" ); printf( "\n" ); printf( "Cone:\n" ); Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pTemp, k ) printf( " %5d = %d%s %d%s\n", pTemp->Id, Ivy_ObjFaninId0(pTemp), Ivy_ObjFaninC0(pTemp)? "\'" : "", Ivy_ObjFaninId1(pTemp), Ivy_ObjFaninC1(pTemp)? "\'" : "" ); */ RetValue = Ivy_MultiPlus( vLeaves, vCone, Ivy_ObjType(pObj), nMffc + fUseZeroCost, vSols ); // ref nodes in the cone Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pTemp, k ) { Ivy_ObjRefsInc( Ivy_ObjFanin0(pTemp) ); Ivy_ObjRefsInc( Ivy_ObjFanin1(pTemp) ); pTemp->fMarkA = 0; pTemp->fMarkB = 0; } if ( !RetValue ) return NULL; if ( Vec_PtrSize( vSols ) == 1 ) return Vec_PtrEntry( vSols, 0 ); return Ivy_NodeBalanceBuildSuper( vSols, Ivy_ObjType(pObj), 1 ); } /**Function************************************************************* Synopsis [Comparison for node pointers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_NodeCountMffc_rec( Ivy_Obj_t * pNode ) { if ( Ivy_ObjRefs(pNode) > 0 || Ivy_ObjIsCi(pNode) || pNode->fMarkA ) return 0; assert( pNode->fMarkB ); pNode->fMarkA = 1; // printf( "%d ", pNode->Id ); if ( Ivy_ObjIsBuf(pNode) ) return Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ); return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) ); } /**Function************************************************************* Synopsis [Comparison for node pointers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_NodeCountMffc( Ivy_Obj_t * pNode ) { assert( pNode->fMarkB ); return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) ); } /**Function************************************************************* Synopsis [Comparison for node pointers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManFindAlgCutCompare( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 ) { if ( *pp1 < *pp2 ) return -1; if ( *pp1 > *pp2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Computing one algebraic cut.] Description [Returns 1 if the tree-leaves of this node where traversed and found to have no external references (and have not been collected). Returns 0 if the tree-leaves have external references and are collected.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManFindAlgCut_rec( Ivy_Obj_t * pObj, Ivy_Type_t Type, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ) { int RetValue0, RetValue1; Ivy_Obj_t * pObjR = Ivy_Regular(pObj); assert( !Ivy_ObjIsBuf(pObjR) ); assert( Type != IVY_EXOR || !Ivy_IsComplement(pObj) ); // make sure the node is not visited twice in different polarities if ( Ivy_IsComplement(pObj) ) { // if complemented, mark B if ( pObjR->fMarkA ) return -1; pObjR->fMarkB = 1; } else { // if non-complicated, mark A if ( pObjR->fMarkB ) return -1; pObjR->fMarkA = 1; } Vec_PtrPush( vCone, pObjR ); // if the node is the end of the tree, return if ( Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Type ) { if ( Ivy_ObjRefs(pObjR) == 1 ) return 1; assert( Ivy_ObjRefs(pObjR) > 1 ); Vec_PtrPush( vFront, pObj ); return 0; } // branch on the node assert( !Ivy_IsComplement(pObj) ); assert( Ivy_ObjIsNode(pObj) ); // what if buffer has more than one fanout??? RetValue0 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild0(pObj) ), Type, vFront, vCone ); RetValue1 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild1(pObj) ), Type, vFront, vCone ); if ( RetValue0 == -1 || RetValue1 == -1 ) return -1; // the case when both have no external references if ( RetValue0 && RetValue1 ) { if ( Ivy_ObjRefs(pObj) == 1 ) return 1; assert( Ivy_ObjRefs(pObj) > 1 ); Vec_PtrPush( vFront, pObj ); return 0; } // the case when one of them has external references if ( RetValue0 ) Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild0(pObj) ) ); if ( RetValue1 ) Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild1(pObj) ) ); return 0; } /**Function************************************************************* Synopsis [Computing one algebraic cut.] Description [Algebraic cut stops when we hit (a) CI, (b) complemented edge, (c) boundary of different gates. Returns 1 if this is a pure tree. Returns -1 if the contant 0 is detected. Return 0 if the array can be used.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ) { Ivy_Obj_t * pObj, * pPrev; int RetValue, i; assert( !Ivy_IsComplement(pRoot) ); assert( Ivy_ObjIsNode(pRoot) ); // clear the frontier and collect the nodes Vec_PtrClear( vCone ); Vec_PtrClear( vFront ); Vec_PtrClear( vLeaves ); RetValue = Ivy_ManFindAlgCut_rec( pRoot, Ivy_ObjType(pRoot), vFront, vCone ); // clean the marks Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pObj, i ) pObj->fMarkA = pObj->fMarkB = 0; // quit if the same node is found in both polarities if ( RetValue == -1 ) return -1; // return if the node is the root of a tree if ( RetValue == 1 ) return 1; // return if the cut is composed of two nodes if ( Vec_PtrSize(vFront) <= 2 ) return 1; // sort the entries in increasing order 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 ); Vec_PtrForEachEntryStart( Ivy_Obj_t *, vFront, pObj, i, 1 ) { // compare current entry and the previous entry if ( pObj == pPrev ) { if ( Ivy_ObjIsExor(pRoot) ) // A <+> A = 0 { // vLeaves are no longer structural support of pRoot!!! Vec_PtrPop(vLeaves); pPrev = Vec_PtrSize(vLeaves) == 0 ? NULL : Vec_PtrEntryLast(vLeaves); } continue; } if ( pObj == Ivy_Not(pPrev) ) { assert( Ivy_ObjIsAnd(pRoot) ); return -1; } pPrev = pObj; Vec_PtrPush( vLeaves, pObj ); } if ( Vec_PtrSize(vLeaves) == 0 ) return -1; if ( Vec_PtrSize(vLeaves) <= 2 ) return 1; return 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivySeq.c000066400000000000000000001076601477524141600157740ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivySeq.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivySeq.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" #include "bool/deco/deco.h" #include "opt/rwt/rwt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost ); static void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm ); static unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums ); static Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth ); static int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax ); static Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph ); static void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain ); static Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ); static inline int Ivy_CutHashValue( int NodeId ) { return 1 << (NodeId % 31); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //int nMoves; //int nMovesS; //int nClauses; //int timeInv; /**Function************************************************************* Synopsis [Performs incremental rewriting of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose ) { Rwt_Man_t * pManRwt; Ivy_Obj_t * pNode; int i, nNodes, nGain; abctime clk, clkStart = Abc_Clock(); // set the DC latch values Ivy_ManForEachLatch( p, pNode, i ) pNode->Init = IVY_INIT_DC; // start the rewriting manager pManRwt = Rwt_ManStart( 0 ); p->pData = pManRwt; if ( pManRwt == NULL ) return 0; // create fanouts if ( p->fFanout == 0 ) Ivy_ManStartFanout( p ); // resynthesize each node once nNodes = Ivy_ManObjIdMax(p); Ivy_ManForEachNode( p, pNode, i ) { assert( !Ivy_ObjIsBuf(pNode) ); assert( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) ); assert( !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) ); // fix the fanin buffer problem // Ivy_NodeFixBufferFanins( p, pNode ); // if ( Ivy_ObjIsBuf(pNode) ) // continue; // stop if all nodes have been tried once if ( i > nNodes ) break; // for each cut, try to resynthesize it nGain = Ivy_NodeRewriteSeq( p, pManRwt, pNode, fUseZeroCost ); if ( nGain > 0 || (nGain == 0 && fUseZeroCost) ) { Dec_Graph_t * pGraph = (Dec_Graph_t *)Rwt_ManReadDecs(pManRwt); int fCompl = Rwt_ManReadCompl(pManRwt); // complement the FF if needed clk = Abc_Clock(); if ( fCompl ) Dec_GraphComplement( pGraph ); Ivy_GraphUpdateNetworkSeq( p, pNode, pGraph, nGain ); if ( fCompl ) Dec_GraphComplement( pGraph ); Rwt_ManAddTimeUpdate( pManRwt, Abc_Clock() - clk ); } } Rwt_ManAddTimeTotal( pManRwt, Abc_Clock() - clkStart ); // print stats if ( fVerbose ) Rwt_ManPrintStats( pManRwt ); // delete the managers Rwt_ManStop( pManRwt ); p->pData = NULL; // fix the levels Ivy_ManResetLevels( p ); // if ( Ivy_ManCheckFanoutNums(p) ) // printf( "Ivy_ManRewritePre(): The check has failed.\n" ); // check if ( !Ivy_ManCheck(p) ) printf( "Ivy_ManRewritePre(): The check has failed.\n" ); return 1; } /**Function************************************************************* Synopsis [Performs rewriting for one node.] Description [This procedure considers all the cuts computed for the node and tries to rewrite each of them using the "forest" of different AIG structures precomputed and stored in the RWR manager. Determines the best rewriting and computes the gain in the number of AIG nodes in the final network. In the end, p->vFanins contains information about the best cut that can be used for rewriting, while p->pGraph gives the decomposition dag (represented using decomposition graph data structure). Returns gain in the number of nodes or -1 if node cannot be rewritten.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost ) { int fVeryVerbose = 0; Dec_Graph_t * pGraph; Ivy_Store_t * pStore; Ivy_Cut_t * pCut; Ivy_Obj_t * pFanin;//, * pFanout; Vec_Ptr_t * vFanout; unsigned uPhase; unsigned uTruthBest = 0; // Suppress "might be used uninitialized" unsigned uTruth;//, nNewClauses; char * pPerm; int nNodesSaved; int nNodesSaveCur = -1; // Suppress "might be used uninitialized" int i, c, GainCur = -1, GainBest = -1; abctime clk, clk2;//, clk3; p->nNodesConsidered++; // get the node's cuts clk = Abc_Clock(); pStore = Ivy_CutComputeForNode( pMan, pNode, 5 ); p->timeCut += Abc_Clock() - clk; // go through the cuts clk = Abc_Clock(); vFanout = Vec_PtrAlloc( 100 ); for ( c = 1; c < pStore->nCuts; c++ ) { pCut = pStore->pCuts + c; // consider only 4-input cuts if ( pCut->nSize != 4 ) continue; // skip the cuts with buffers for ( i = 0; i < (int)pCut->nSize; i++ ) if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, Ivy_LeafId(pCut->pArray[i])) ) ) break; if ( i != pCut->nSize ) { p->nCutsBad++; continue; } p->nCutsGood++; // get the fanin permutation clk2 = Abc_Clock(); uTruth = 0xFFFF & Ivy_CutGetTruth( pMan, pNode, pCut->pArray, pCut->nSize ); // truth table p->timeTruth += Abc_Clock() - clk2; pPerm = p->pPerms4[ (int)p->pPerms[uTruth] ]; uPhase = p->pPhases[uTruth]; // collect fanins with the corresponding permutation/phase Vec_PtrClear( p->vFaninsCur ); Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 ); for ( i = 0; i < (int)pCut->nSize; i++ ) { pFanin = Ivy_ManObj( pMan, Ivy_LeafId( pCut->pArray[(int)pPerm[i]] ) ); assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) || Ivy_ObjIsConst1(pFanin) ); pFanin = Ivy_NotCond(pFanin, ((uPhase & (1< 0) ); Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); } clk2 = Abc_Clock(); // mark the fanin boundary Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i ) Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); // label MFFC with current ID Ivy_ManIncrementTravId( pMan ); nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode ); // label fanouts with the current ID // Ivy_ObjForEachFanout( pMan, pNode, vFanout, pFanout, i ) // Ivy_ObjSetTravIdCurrent( pMan, pFanout ); // unmark the fanin boundary Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i ) Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); p->timeMffc += Abc_Clock() - clk2; // evaluate the cut clk2 = Abc_Clock(); pGraph = Rwt_CutEvaluateSeq( pMan, p, pNode, pCut, pPerm, p->vFaninsCur, nNodesSaved, &GainCur, uTruth ); p->timeEval += Abc_Clock() - clk2; // check if the cut is better than the current best one if ( pGraph != NULL && GainBest < GainCur ) { // save this form nNodesSaveCur = nNodesSaved; GainBest = GainCur; p->pGraph = pGraph; p->pCut = pCut; p->pPerm = pPerm; p->fCompl = ((uPhase & (1<<4)) > 0); uTruthBest = uTruth; // collect fanins in the Vec_PtrClear( p->vFanins ); Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i ) Vec_PtrPush( p->vFanins, pFanin ); } } Vec_PtrFree( vFanout ); p->timeRes += Abc_Clock() - clk; if ( GainBest == -1 ) return -1; /* { Ivy_Cut_t * pCut = p->pCut; printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) ); for ( i = 0; i < pCut->nSize; i++ ) printf( " %d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); printf( " }\n" ); } */ //clk3 = Abc_Clock(); //nNewClauses = Ivy_CutTruthPrint( pMan, p->pCut, uTruth ); //timeInv += Abc_Clock() - clk; // nClauses += nNewClauses; // nMoves++; // if ( nNewClauses > 0 ) // nMovesS++; // copy the leaves Ivy_GraphPrepare( (Dec_Graph_t *)p->pGraph, (Ivy_Cut_t *)p->pCut, p->vFanins, p->pPerm ); p->nScores[p->pMap[uTruthBest]]++; p->nNodesGained += GainBest; if ( fUseZeroCost || GainBest > 0 ) p->nNodesRewritten++; /* if ( GainBest > 0 ) { Ivy_Cut_t * pCut = p->pCut; printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) ); for ( i = 0; i < pCut->nSize; i++ ) printf( " %5d(%2d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); printf( " }\n" ); } */ // report the progress if ( fVeryVerbose && GainBest > 0 ) { printf( "Node %6d : ", Ivy_ObjId(pNode) ); printf( "Fanins = %d. ", p->vFanins->nSize ); printf( "Save = %d. ", nNodesSaveCur ); printf( "Add = %d. ", nNodesSaveCur-GainBest ); printf( "GAIN = %d. ", GainBest ); printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum((Dec_Graph_t *)p->pGraph) : 0 ); printf( "Class = %d. ", p->pMap[uTruthBest] ); printf( "\n" ); } return GainBest; } /**Function************************************************************* Synopsis [Evaluates the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth ) { Vec_Ptr_t * vSubgraphs; Dec_Graph_t * pGraphBest = NULL; // Suppress "might be used uninitialized" Dec_Graph_t * pGraphCur; Rwt_Node_t * pNode; int nNodesAdded, GainBest, i; // find the matching class of subgraphs vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); p->nSubgraphs += vSubgraphs->nSize; // determine the best subgraph GainBest = -1; Vec_PtrForEachEntry( Rwt_Node_t *, vSubgraphs, pNode, i ) { // get the current graph pGraphCur = (Dec_Graph_t *)pNode->pNext; // if ( pRoot->Id == 8648 ) // Dec_GraphPrint( stdout, pGraphCur, NULL, NULL ); // copy the leaves // Vec_PtrForEachEntry( Ivy_Obj_t *, vFaninsCur, pFanin, k ) // Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; Ivy_GraphPrepare( pGraphCur, pCut, vFaninsCur, pPerm ); // detect how many unlabeled nodes will be reused nNodesAdded = Ivy_GraphToNetworkSeqCountSeq( pMan, pRoot, pGraphCur, nNodesSaved ); if ( nNodesAdded == -1 ) continue; assert( nNodesSaved >= nNodesAdded ); // count the gain at this node if ( GainBest < nNodesSaved - nNodesAdded ) { GainBest = nNodesSaved - nNodesAdded; pGraphBest = pGraphCur; } } if ( GainBest == -1 ) return NULL; *pGainBest = GainBest; return pGraphBest; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm ) { Dec_Node_t * pNode, * pNode0, * pNode1; int i; assert( Dec_GraphLeaveNum(pGraph) == pCut->nSize ); assert( Vec_PtrSize(vFanins) == pCut->nSize ); // label the leaves with latch numbers Dec_GraphForEachLeaf( pGraph, pNode, i ) { pNode->pFunc = Vec_PtrEntry( vFanins, i ); pNode->nLat2 = Ivy_LeafLat( pCut->pArray[(int)pPerm[i]] ); } // propagate latches through the nodes Dec_GraphForEachNode( pGraph, pNode, i ) { // get the children of this node pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); // distribute the latches pNode->nLat2 = IVY_MIN( pNode0->nLat2, pNode1->nLat2 ); pNode->nLat0 = pNode0->nLat2 - pNode->nLat2; pNode->nLat1 = pNode1->nLat2 - pNode->nLat2; } } /**Function************************************************************* Synopsis [Counts the number of new nodes added when using this graph.] Description [AIG nodes for the fanins should be assigned to pNode->pFunc of the leaves of the graph before calling this procedure. Returns -1 if the number of nodes and levels exceeded the given limit or the number of levels exceeded the maximum allowed level.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax ) { Dec_Node_t * pNode, * pNode0, * pNode1; Ivy_Obj_t * pAnd, * pAnd0, * pAnd1; int i, k, Counter, fCompl; // check for constant function or a literal if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) return 0; // compute the AIG size after adding the internal nodes Counter = 0; Dec_GraphForEachNode( pGraph, pNode, i ) { // get the children of this node pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); // get the AIG nodes corresponding to the children pAnd0 = (Ivy_Obj_t *)pNode0->pFunc; pAnd1 = (Ivy_Obj_t *)pNode1->pFunc; // skip the latches for ( k = 0; pAnd0 && k < (int)pNode->nLat0; k++ ) { fCompl = Ivy_IsComplement(pAnd0); pAnd0 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd0), NULL, IVY_LATCH, IVY_INIT_DC) ); if ( pAnd0 ) pAnd0 = Ivy_NotCond( pAnd0, fCompl ); } for ( k = 0; pAnd1 && k < (int)pNode->nLat1; k++ ) { fCompl = Ivy_IsComplement(pAnd1); pAnd1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd1), NULL, IVY_LATCH, IVY_INIT_DC) ); if ( pAnd1 ) pAnd1 = Ivy_NotCond( pAnd1, fCompl ); } // get the new node if ( pAnd0 && pAnd1 ) { // if they are both present, find the resulting node pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl ); pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl ); assert( !Ivy_ObjIsLatch(Ivy_Regular(pAnd0)) || !Ivy_ObjIsLatch(Ivy_Regular(pAnd1)) ); if ( Ivy_Regular(pAnd0) == Ivy_Regular(pAnd1) || Ivy_ObjIsConst1(Ivy_Regular(pAnd0)) || Ivy_ObjIsConst1(Ivy_Regular(pAnd1)) ) pAnd = Ivy_And( p, pAnd0, pAnd1 ); else pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) ); // return -1 if the node is the same as the original root if ( Ivy_Regular(pAnd) == pRoot ) return -1; } else pAnd = NULL; // count the number of added nodes if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) ) { if ( ++Counter > NodeMax ) return -1; } pNode->pFunc = pAnd; } return Counter; } /**Function************************************************************* Synopsis [Transforms the decomposition graph into the AIG.] Description [AIG nodes for the fanins should be assigned to pNode->pFunc of the leaves of the graph before calling this procedure.] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph ) { Ivy_Obj_t * pAnd0, * pAnd1; Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" int i, k; // check for constant function if ( Dec_GraphIsConst(pGraph) ) return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) ); // check for a literal if ( Dec_GraphIsVar(pGraph) ) { // get the variable node pNode = Dec_GraphVar(pGraph); // add the remaining latches for ( k = 0; k < (int)pNode->nLat2; k++ ) pNode->pFunc = Ivy_Latch( p, (Ivy_Obj_t *)pNode->pFunc, IVY_INIT_DC ); return Ivy_NotCond( (Ivy_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); } // build the AIG nodes corresponding to the AND gates of the graph Dec_GraphForEachNode( pGraph, pNode, i ) { pAnd0 = Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); pAnd1 = Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); // add the latches for ( k = 0; k < (int)pNode->nLat0; k++ ) pAnd0 = Ivy_Latch( p, pAnd0, IVY_INIT_DC ); for ( k = 0; k < (int)pNode->nLat1; k++ ) pAnd1 = Ivy_Latch( p, pAnd1, IVY_INIT_DC ); // create the node pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 ); } // add the remaining latches for ( k = 0; k < (int)pNode->nLat2; k++ ) pNode->pFunc = Ivy_Latch( p, (Ivy_Obj_t *)pNode->pFunc, IVY_INIT_DC ); // complement the result if necessary return Ivy_NotCond( (Ivy_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); } /**Function************************************************************* Synopsis [Replaces MFFC of the node by the new factored form.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain ) { Ivy_Obj_t * pRootNew; int nNodesNew, nNodesOld; nNodesOld = Ivy_ManNodeNum(p); // create the new structure of nodes pRootNew = Ivy_GraphToNetworkSeq( p, pGraph ); Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 0 ); // compare the gains nNodesNew = Ivy_ManNodeNum(p); assert( nGain <= nNodesOld - nNodesNew ); // propagate the buffer Ivy_ManPropagateBuffers( p, 0 ); } /**Function************************************************************* Synopsis [Computes the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Ivy_CutGetTruth_rec( Ivy_Man_t * p, int Leaf, int * pNums, int nNums ) { static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; unsigned uTruth0, uTruth1; Ivy_Obj_t * pObj; int i; for ( i = 0; i < nNums; i++ ) if ( Leaf == pNums[i] ) return uMasks[i]; pObj = Ivy_ManObj( p, Ivy_LeafId(Leaf) ); if ( Ivy_ObjIsLatch(pObj) ) { assert( !Ivy_ObjFaninC0(pObj) ); Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) + 1 ); return Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); } assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) ); uTruth0 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); if ( Ivy_ObjFaninC0(pObj) ) uTruth0 = ~uTruth0; if ( Ivy_ObjIsBuf(pObj) ) return uTruth0; Leaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pObj), Ivy_LeafLat(Leaf) ); uTruth1 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); if ( Ivy_ObjFaninC1(pObj) ) uTruth1 = ~uTruth1; return uTruth0 & uTruth1; } /**Function************************************************************* Synopsis [Computes the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums ) { assert( Ivy_ObjIsNode(pObj) ); assert( nNums < 6 ); return Ivy_CutGetTruth_rec( p, Ivy_LeafCreate(pObj->Id, 0), pNums, nNums ); } /**Function************************************************************* Synopsis [Returns 1 if the cut can be constructed; 0 otherwise.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ivy_CutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 ) { int i; if ( pCut->nSize < pCut->nSizeMax ) return 1; for ( i = 0; i < pCut->nSize; i++ ) if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 ) return 1; return 0; } /**Function************************************************************* Synopsis [Derives new cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ivy_CutDeriveNew2( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) { unsigned uHash = 0; int i, k; assert( pCut->nSize > 0 ); assert( IdNew0 < IdNew1 ); for ( i = k = 0; i < pCut->nSize; i++ ) { if ( pCut->pArray[i] == IdOld ) continue; if ( IdNew0 >= 0 ) { if ( IdNew0 <= pCut->pArray[i] ) { if ( IdNew0 < pCut->pArray[i] ) { if ( k == pCut->nSizeMax ) return 0; pCutNew->pArray[ k++ ] = IdNew0; uHash |= Ivy_CutHashValue( IdNew0 ); } IdNew0 = -1; } } if ( IdNew1 >= 0 ) { if ( IdNew1 <= pCut->pArray[i] ) { if ( IdNew1 < pCut->pArray[i] ) { if ( k == pCut->nSizeMax ) return 0; pCutNew->pArray[ k++ ] = IdNew1; uHash |= Ivy_CutHashValue( IdNew1 ); } IdNew1 = -1; } } if ( k == pCut->nSizeMax ) return 0; pCutNew->pArray[ k++ ] = pCut->pArray[i]; uHash |= Ivy_CutHashValue( pCut->pArray[i] ); } if ( IdNew0 >= 0 ) { if ( k == pCut->nSizeMax ) return 0; pCutNew->pArray[ k++ ] = IdNew0; uHash |= Ivy_CutHashValue( IdNew0 ); } if ( IdNew1 >= 0 ) { if ( k == pCut->nSizeMax ) return 0; pCutNew->pArray[ k++ ] = IdNew1; uHash |= Ivy_CutHashValue( IdNew1 ); } pCutNew->nSize = k; pCutNew->uHash = uHash; assert( pCutNew->nSize <= pCut->nSizeMax ); for ( i = 1; i < pCutNew->nSize; i++ ) assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); return 1; } /**Function************************************************************* Synopsis [Derives new cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ivy_CutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) { unsigned uHash = 0; int i, k; assert( pCut->nSize > 0 ); assert( IdNew0 < IdNew1 ); for ( i = k = 0; i < pCut->nSize; i++ ) { if ( pCut->pArray[i] == IdOld ) continue; if ( IdNew0 <= pCut->pArray[i] ) { if ( IdNew0 < pCut->pArray[i] ) { pCutNew->pArray[ k++ ] = IdNew0; uHash |= Ivy_CutHashValue( IdNew0 ); } IdNew0 = 0x7FFFFFFF; } if ( IdNew1 <= pCut->pArray[i] ) { if ( IdNew1 < pCut->pArray[i] ) { pCutNew->pArray[ k++ ] = IdNew1; uHash |= Ivy_CutHashValue( IdNew1 ); } IdNew1 = 0x7FFFFFFF; } pCutNew->pArray[ k++ ] = pCut->pArray[i]; uHash |= Ivy_CutHashValue( pCut->pArray[i] ); } if ( IdNew0 < 0x7FFFFFFF ) { pCutNew->pArray[ k++ ] = IdNew0; uHash |= Ivy_CutHashValue( IdNew0 ); } if ( IdNew1 < 0x7FFFFFFF ) { pCutNew->pArray[ k++ ] = IdNew1; uHash |= Ivy_CutHashValue( IdNew1 ); } pCutNew->nSize = k; pCutNew->uHash = uHash; assert( pCutNew->nSize <= pCut->nSizeMax ); // for ( i = 1; i < pCutNew->nSize; i++ ) // assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); return 1; } /**Function************************************************************* Synopsis [Find the hash value of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut ) { int i; pCut->uHash = 0; for ( i = 0; i < pCut->nSize; i++ ) pCut->uHash |= (1 << (pCut->pArray[i] % 31)); return pCut->uHash; } /**Function************************************************************* Synopsis [Derives new cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ivy_CutDeriveNew3( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) { int i, k; assert( pCut->nSize > 0 ); assert( IdNew0 < IdNew1 ); for ( i = k = 0; i < pCut->nSize; i++ ) { if ( pCut->pArray[i] == IdOld ) continue; if ( IdNew0 <= pCut->pArray[i] ) { if ( IdNew0 < pCut->pArray[i] ) pCutNew->pArray[ k++ ] = IdNew0; IdNew0 = 0x7FFFFFFF; } if ( IdNew1 <= pCut->pArray[i] ) { if ( IdNew1 < pCut->pArray[i] ) pCutNew->pArray[ k++ ] = IdNew1; IdNew1 = 0x7FFFFFFF; } pCutNew->pArray[ k++ ] = pCut->pArray[i]; } if ( IdNew0 < 0x7FFFFFFF ) pCutNew->pArray[ k++ ] = IdNew0; if ( IdNew1 < 0x7FFFFFFF ) pCutNew->pArray[ k++ ] = IdNew1; pCutNew->nSize = k; assert( pCutNew->nSize <= pCut->nSizeMax ); Ivy_NodeCutHash( pCutNew ); return 1; } /**Function************************************************************* Synopsis [Returns 1 if pDom is contained in pCut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut ) { int i, k; for ( i = 0; i < pDom->nSize; i++ ) { assert( i==0 || pDom->pArray[i-1] < pDom->pArray[i] ); for ( k = 0; k < pCut->nSize; k++ ) if ( pDom->pArray[i] == pCut->pArray[k] ) break; if ( k == pCut->nSize ) // node i in pDom is not contained in pCut return 0; } // every node in pDom is contained in pCut return 1; } /**Function************************************************************* Synopsis [Check if the cut exists.] Description [Returns 1 if the cut exists.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_CutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) { Ivy_Cut_t * pCut; int i, k; assert( pCutNew->uHash ); // try to find the cut for ( i = 0; i < pCutStore->nCuts; i++ ) { pCut = pCutStore->pCuts + i; if ( pCut->nSize == 0 ) continue; if ( pCut->nSize == pCutNew->nSize ) { if ( pCut->uHash == pCutNew->uHash ) { for ( k = 0; k < pCutNew->nSize; k++ ) if ( pCut->pArray[k] != pCutNew->pArray[k] ) break; if ( k == pCutNew->nSize ) return 1; } continue; } if ( pCut->nSize < pCutNew->nSize ) { // skip the non-contained cuts if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash ) continue; // check containment seriously if ( Ivy_CutCheckDominance( pCut, pCutNew ) ) return 1; continue; } // check potential containment of other cut // skip the non-contained cuts if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash ) continue; // check containment seriously if ( Ivy_CutCheckDominance( pCutNew, pCut ) ) { // remove the current cut pCut->nSize = 0; } } assert( pCutStore->nCuts < pCutStore->nCutsMax ); // add the cut pCut = pCutStore->pCuts + pCutStore->nCuts++; *pCut = *pCutNew; return 0; } /**Function************************************************************* Synopsis [Compresses the cut representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_CutCompactAll( Ivy_Store_t * pCutStore ) { Ivy_Cut_t * pCut; int i, k; pCutStore->nCutsM = 0; for ( i = k = 0; i < pCutStore->nCuts; i++ ) { pCut = pCutStore->pCuts + i; if ( pCut->nSize == 0 ) continue; if ( pCut->nSize < pCut->nSizeMax ) pCutStore->nCutsM++; pCutStore->pCuts[k++] = *pCut; } pCutStore->nCuts = k; } /**Function************************************************************* Synopsis [Print the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_CutPrintForNode( Ivy_Cut_t * pCut ) { int i; assert( pCut->nSize > 0 ); printf( "%d : {", pCut->nSize ); for ( i = 0; i < pCut->nSize; i++ ) printf( " %d", pCut->pArray[i] ); printf( " }\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_CutPrintForNodes( Ivy_Store_t * pCutStore ) { int i; printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] ); for ( i = 0; i < pCutStore->nCuts; i++ ) Ivy_CutPrintForNode( pCutStore->pCuts + i ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Ivy_CutReadLeaf( Ivy_Obj_t * pFanin ) { int nLats, iLeaf; assert( !Ivy_IsComplement(pFanin) ); if ( !Ivy_ObjIsLatch(pFanin) ) return Ivy_LeafCreate( pFanin->Id, 0 ); iLeaf = Ivy_CutReadLeaf(Ivy_ObjFanin0(pFanin)); nLats = Ivy_LeafLat(iLeaf); assert( nLats < IVY_LEAF_MASK ); return 1 + iLeaf; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ) { static Ivy_Store_t CutStore, * pCutStore = &CutStore; Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut; Ivy_Obj_t * pLeaf; int i, k, Temp, nLats, iLeaf0, iLeaf1; assert( nLeaves <= IVY_CUT_INPUT ); // start the structure pCutStore->nCuts = 0; pCutStore->nCutsMax = IVY_CUT_LIMIT; // start the trivial cut pCutNew->uHash = 0; pCutNew->nSize = 1; pCutNew->nSizeMax = nLeaves; pCutNew->pArray[0] = Ivy_LeafCreate( pObj->Id, 0 ); pCutNew->uHash = Ivy_CutHashValue( pCutNew->pArray[0] ); // add the trivial cut pCutStore->pCuts[pCutStore->nCuts++] = *pCutNew; assert( pCutStore->nCuts == 1 ); // explore the cuts for ( i = 0; i < pCutStore->nCuts; i++ ) { // expand this cut pCut = pCutStore->pCuts + i; if ( pCut->nSize == 0 ) continue; for ( k = 0; k < pCut->nSize; k++ ) { pLeaf = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[k]) ); if ( Ivy_ObjIsCi(pLeaf) || Ivy_ObjIsConst1(pLeaf) ) continue; assert( Ivy_ObjIsNode(pLeaf) ); nLats = Ivy_LeafLat(pCut->pArray[k]); // get the fanins fanins iLeaf0 = Ivy_CutReadLeaf( Ivy_ObjFanin0(pLeaf) ); iLeaf1 = Ivy_CutReadLeaf( Ivy_ObjFanin1(pLeaf) ); assert( nLats + Ivy_LeafLat(iLeaf0) < IVY_LEAF_MASK && nLats + Ivy_LeafLat(iLeaf1) < IVY_LEAF_MASK ); iLeaf0 = nLats + iLeaf0; iLeaf1 = nLats + iLeaf1; if ( !Ivy_CutPrescreen( pCut, iLeaf0, iLeaf1 ) ) continue; // the given cut exist if ( iLeaf0 > iLeaf1 ) Temp = iLeaf0, iLeaf0 = iLeaf1, iLeaf1 = Temp; // create the new cut if ( !Ivy_CutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 ) ) continue; // add the cut Ivy_CutFindOrAddFilter( pCutStore, pCutNew ); if ( pCutStore->nCuts == IVY_CUT_LIMIT ) break; } if ( pCutStore->nCuts == IVY_CUT_LIMIT ) break; } if ( pCutStore->nCuts == IVY_CUT_LIMIT ) pCutStore->fSatur = 1; else pCutStore->fSatur = 0; // printf( "%d ", pCutStore->nCuts ); Ivy_CutCompactAll( pCutStore ); // printf( "%d \n", pCutStore->nCuts ); // Ivy_CutPrintForNodes( pCutStore ); return pCutStore; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs ) { Ivy_Store_t * pStore; Ivy_Obj_t * pObj; int i, nCutsTotal, nCutsTotalM, nNodeTotal, nNodeOver; abctime clk = Abc_Clock(); if ( nInputs > IVY_CUT_INPUT ) { printf( "Cannot compute cuts for more than %d inputs.\n", IVY_CUT_INPUT ); return; } nNodeTotal = nNodeOver = 0; nCutsTotal = nCutsTotalM = -Ivy_ManNodeNum(p); Ivy_ManForEachObj( p, pObj, i ) { if ( !Ivy_ObjIsNode(pObj) ) continue; pStore = Ivy_CutComputeForNode( p, pObj, nInputs ); nCutsTotal += pStore->nCuts; nCutsTotalM += pStore->nCutsM; nNodeOver += pStore->fSatur; nNodeTotal++; } printf( "All = %6d. Minus = %6d. Triv = %6d. Node = %6d. Satur = %6d. ", nCutsTotal, nCutsTotalM, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); ABC_PRT( "Time", Abc_Clock() - clk ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyShow.c000066400000000000000000000310221477524141600161500ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyShow.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Visualization of HAIG.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) { extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); static int Counter = 0; char FileNameDot[200]; FILE * pFile; // create the file name // Ivy_ShowGetFileName( pMan->pName, FileNameDot ); sprintf( FileNameDot, "temp%02d.dot", Counter++ ); // check that the file can be opened if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) { fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); return; } fclose( pFile ); // generate the file Ivy_WriteDotAig( pMan, FileNameDot, fHaig, vBold ); // visualize the file Abc_ShowFile( FileNameDot, 0 ); } /**Function************************************************************* Synopsis [Writes the graph structure of AIG for DOT.] Description [Useful for graph visualization using tools such as GraphViz: http://www.graphviz.org/] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ) { FILE * pFile; Ivy_Obj_t * pNode, * pTemp, * pPrev; int LevelMax, Level, i; if ( Ivy_ManNodeNum(pMan) > 200 ) { fprintf( stdout, "Cannot visualize AIG with more than 200 nodes.\n" ); return; } if ( (pFile = fopen( pFileName, "w" )) == NULL ) { fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); return; } // mark the nodes if ( vBold ) Vec_PtrForEachEntry( Ivy_Obj_t *, vBold, pNode, i ) pNode->fMarkB = 1; // compute levels LevelMax = 1 + Ivy_ManSetLevels( pMan, fHaig ); // write the DOT header fprintf( pFile, "# %s\n", "AIG structure generated by IVY package" ); fprintf( pFile, "\n" ); fprintf( pFile, "digraph AIG {\n" ); fprintf( pFile, "size = \"7.5,10\";\n" ); // fprintf( pFile, "ranksep = 0.5;\n" ); // fprintf( pFile, "nodesep = 0.5;\n" ); fprintf( pFile, "center = true;\n" ); // fprintf( pFile, "orientation = landscape;\n" ); // fprintf( pFile, "edge [fontsize = 10];\n" ); // fprintf( pFile, "edge [dir = none];\n" ); fprintf( pFile, "edge [dir = back];\n" ); fprintf( pFile, "\n" ); // labels on the left of the picture fprintf( pFile, "{\n" ); fprintf( pFile, " node [shape = plaintext];\n" ); fprintf( pFile, " edge [style = invis];\n" ); fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); // generate node names with labels for ( Level = LevelMax; Level >= 0; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); fprintf( pFile, " [label = " ); // label name fprintf( pFile, "\"" ); fprintf( pFile, "\"" ); fprintf( pFile, "];\n" ); } // genetate the sequence of visible/invisible nodes to mark levels fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); for ( Level = LevelMax; Level >= 0; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); // the connector if ( Level != 0 ) fprintf( pFile, " ->" ); else fprintf( pFile, ";" ); } fprintf( pFile, "\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate title box on top fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); fprintf( pFile, " LevelTitle1;\n" ); fprintf( pFile, " title1 [shape=plaintext,\n" ); fprintf( pFile, " fontsize=20,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); fprintf( pFile, "%s", "AIG structure visualized by ABC" ); fprintf( pFile, "\\n" ); fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate statistics box fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); fprintf( pFile, " LevelTitle2;\n" ); fprintf( pFile, " title2 [shape=plaintext,\n" ); fprintf( pFile, " fontsize=18,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Ivy_ManNodeNum(pMan), LevelMax ); fprintf( pFile, "\\n" ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate the COs fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMax ); // generate the CO nodes Ivy_ManForEachCo( pMan, pNode, i ) { if ( fHaig || pNode->pEquiv == NULL ) fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); else fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":""), Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"invtriangle") ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate nodes of each rank for ( Level = LevelMax - 1; Level > 0; Level-- ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", Level ); Ivy_ManForEachObj( pMan, pNode, i ) { if ( (int)pNode->Level != Level ) continue; if ( fHaig || pNode->pEquiv == NULL ) fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); else fprintf( pFile, " Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id, Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); fprintf( pFile, ", shape = ellipse" ); if ( vBold && pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); } // generate the CI nodes fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", 0 ); // generate constant node if ( Ivy_ObjRefs(Ivy_ManConst1(pMan)) > 0 ) { pNode = Ivy_ManConst1(pMan); // check if the costant node is present fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id ); fprintf( pFile, ", shape = ellipse" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } // generate the CI nodes Ivy_ManForEachCi( pMan, pNode, i ) { if ( fHaig || pNode->pEquiv == NULL ) fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":"") ); else fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":""), Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"triangle") ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate invisible edges from the square down fprintf( pFile, "title1 -> title2 [style = invis];\n" ); Ivy_ManForEachCo( pMan, pNode, i ) fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); // generate edges Ivy_ManForEachObj( pMan, pNode, i ) { if ( !Ivy_ObjIsNode(pNode) && !Ivy_ObjIsCo(pNode) && !Ivy_ObjIsBuf(pNode) ) continue; // generate the edge from this node to the next fprintf( pFile, "Node%d%s", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d%s", Ivy_ObjFaninId0(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin0(pNode))? "_out":"") ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", Ivy_ObjFaninC0(pNode)? "dotted" : "bold" ); // if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 ) // fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); if ( !Ivy_ObjIsNode(pNode) ) continue; // generate the edge from this node to the next fprintf( pFile, "Node%d", pNode->Id ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d%s", Ivy_ObjFaninId1(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin1(pNode))? "_out":"") ); fprintf( pFile, " [" ); fprintf( pFile, "style = %s", Ivy_ObjFaninC1(pNode)? "dotted" : "bold" ); // if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 ) // fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); fprintf( pFile, "]" ); fprintf( pFile, ";\n" ); // generate the edges between the equivalent nodes if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 ) { pPrev = pNode; for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) ) { fprintf( pFile, "Node%d", pPrev->Id ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", pTemp->Id ); fprintf( pFile, " [style = %s]", Ivy_IsComplement(pTemp->pEquiv)? "dotted" : "bold" ); fprintf( pFile, ";\n" ); pPrev = pTemp; } // connect the last node with the first fprintf( pFile, "Node%d", pPrev->Id ); fprintf( pFile, " -> " ); fprintf( pFile, "Node%d", pNode->Id ); fprintf( pFile, " [style = %s]", Ivy_IsComplement(pPrev->pEquiv)? "dotted" : "bold" ); fprintf( pFile, ";\n" ); } } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); fclose( pFile ); // unmark nodes if ( vBold ) Vec_PtrForEachEntry( Ivy_Obj_t *, vBold, pNode, i ) pNode->fMarkB = 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyTable.c000066400000000000000000000174741477524141600162760ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyTable.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Structural hashing table.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006. ] Revision [$Id: ivyTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // hashing the node static unsigned Ivy_Hash( Ivy_Obj_t * pObj, int TableSize ) { unsigned Key = Ivy_ObjIsExor(pObj) * 1699; Key ^= Ivy_ObjFaninId0(pObj) * 7937; Key ^= Ivy_ObjFaninId1(pObj) * 2971; Key ^= Ivy_ObjFaninC0(pObj) * 911; Key ^= Ivy_ObjFaninC1(pObj) * 353; Key ^= Ivy_ObjInit(pObj) * 911; return Key % TableSize; } // returns the place where this node is stored (or should be stored) static int * Ivy_TableFind( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { int i; assert( Ivy_ObjIsHash(pObj) ); for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) if ( p->pTable[i] == pObj->Id ) break; return p->pTable + i; } static void Ivy_TableResize( Ivy_Man_t * p ); static unsigned int Cudd_PrimeAig( unsigned int p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks if node with the given attributes is in the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { Ivy_Obj_t * pEntry; int i; assert( !Ivy_IsComplement(pObj) ); if ( !Ivy_ObjIsHash(pObj) ) return NULL; assert( Ivy_ObjIsLatch(pObj) || Ivy_ObjFaninId0(pObj) > 0 ); assert( Ivy_ObjFaninId1(pObj) == 0 || Ivy_ObjFaninId0(pObj) < Ivy_ObjFaninId1(pObj) ); if ( Ivy_ObjFanin0(pObj)->nRefs == 0 || (Ivy_ObjChild1(pObj) && Ivy_ObjFanin1(pObj)->nRefs == 0) ) return NULL; for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) { pEntry = Ivy_ManObj( p, p->pTable[i] ); if ( Ivy_ObjChild0(pEntry) == Ivy_ObjChild0(pObj) && Ivy_ObjChild1(pEntry) == Ivy_ObjChild1(pObj) && Ivy_ObjInit(pEntry) == Ivy_ObjInit(pObj) && Ivy_ObjType(pEntry) == Ivy_ObjType(pObj) ) return pEntry; } return NULL; } /**Function************************************************************* Synopsis [Adds the node to the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { int * pPlace; assert( !Ivy_IsComplement(pObj) ); if ( !Ivy_ObjIsHash(pObj) ) return; if ( (pObj->Id & 63) == 0 ) { if ( p->nTableSize < 2 * Ivy_ManHashObjNum(p) ) Ivy_TableResize( p ); } pPlace = Ivy_TableFind( p, pObj ); assert( *pPlace == 0 ); *pPlace = pObj->Id; } /**Function************************************************************* Synopsis [Deletes the node from the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { Ivy_Obj_t * pEntry; int i, * pPlace; assert( !Ivy_IsComplement(pObj) ); if ( !Ivy_ObjIsHash(pObj) ) return; pPlace = Ivy_TableFind( p, pObj ); assert( *pPlace == pObj->Id ); // node should be in the table *pPlace = 0; // rehash the adjacent entries i = pPlace - p->pTable; for ( i = (i+1) % p->nTableSize; p->pTable[i]; i = (i+1) % p->nTableSize ) { pEntry = Ivy_ManObj( p, p->pTable[i] ); p->pTable[i] = 0; Ivy_TableInsert( p, pEntry ); } } /**Function************************************************************* Synopsis [Updates the table to point to the new node.] Description [If the old node (pObj) is in the table, updates the table to point to an object with different ID (ObjIdNew). The table should not contain an object with ObjIdNew (this is currently not checked).] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew ) { int * pPlace; assert( !Ivy_IsComplement(pObj) ); if ( !Ivy_ObjIsHash(pObj) ) return; pPlace = Ivy_TableFind( p, pObj ); assert( *pPlace == pObj->Id ); // node should be in the table *pPlace = ObjIdNew; } /**Function************************************************************* Synopsis [Count the number of nodes in the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_TableCountEntries( Ivy_Man_t * p ) { int i, Counter = 0; for ( i = 0; i < p->nTableSize; i++ ) Counter += (p->pTable[i] != 0); return Counter; } /**Function************************************************************* Synopsis [Resizes the table.] Description [Typically this procedure should not be called.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_TableResize( Ivy_Man_t * p ) { int * pTableOld, * pPlace; int nTableSizeOld, Counter, nEntries, e; abctime clk; clk = Abc_Clock(); // save the old table pTableOld = p->pTable; nTableSizeOld = p->nTableSize; // get the new table p->nTableSize = Abc_PrimeCudd( 5 * Ivy_ManHashObjNum(p) ); p->pTable = ABC_ALLOC( int, p->nTableSize ); memset( p->pTable, 0, sizeof(int) * p->nTableSize ); // rehash the entries from the old table Counter = 0; for ( e = 0; e < nTableSizeOld; e++ ) { if ( pTableOld[e] == 0 ) continue; Counter++; // get the place where this entry goes in the table table pPlace = Ivy_TableFind( p, Ivy_ManObj(p, pTableOld[e]) ); assert( *pPlace == 0 ); // should not be in the table *pPlace = pTableOld[e]; } nEntries = Ivy_ManHashObjNum(p); // assert( Counter == nEntries ); // printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); // ABC_PRT( "Time", Abc_Clock() - clk ); // replace the table and the parameters ABC_FREE( pTableOld ); } /**Function******************************************************************** Synopsis [Profiles the hash table.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ void Ivy_TableProfile( Ivy_Man_t * p ) { int i, Counter = 0; for ( i = 0; i < p->nTableSize; i++ ) { if ( p->pTable[i] ) Counter++; else if ( Counter ) { printf( "%d ", Counter ); Counter = 0; } } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivyUtil.c000066400000000000000000000645241477524141600161620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivyUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [Various procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivyUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Increments the current traversal ID of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManIncrementTravId( Ivy_Man_t * p ) { if ( p->nTravIds >= (1<<30)-1 - 1000 ) Ivy_ManCleanTravId( p ); p->nTravIds++; } /**Function************************************************************* Synopsis [Sets the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManCleanTravId( Ivy_Man_t * p ) { Ivy_Obj_t * pObj; int i; p->nTravIds = 1; Ivy_ManForEachObj( p, pObj, i ) pObj->TravId = 0; } /**Function************************************************************* Synopsis [Computes truth table of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManCollectCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vNodes ) { if ( pNode->fMarkA ) return; pNode->fMarkA = 1; assert( Ivy_ObjIsAnd(pNode) || Ivy_ObjIsExor(pNode) ); Ivy_ManCollectCut_rec( p, Ivy_ObjFanin0(pNode), vNodes ); Ivy_ManCollectCut_rec( p, Ivy_ObjFanin1(pNode), vNodes ); Vec_IntPush( vNodes, pNode->Id ); } /**Function************************************************************* Synopsis [Computes truth table of the cut.] Description [Does not modify the array of leaves. Uses array vTruth to store temporary truth tables. The returned pointer should be used immediately.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) { int i, Leaf; // collect and mark the leaves Vec_IntClear( vNodes ); Vec_IntForEachEntry( vLeaves, Leaf, i ) { Vec_IntPush( vNodes, Leaf ); Ivy_ManObj(p, Leaf)->fMarkA = 1; } // collect and mark the nodes Ivy_ManCollectCut_rec( p, pRoot, vNodes ); // clean the nodes Vec_IntForEachEntry( vNodes, Leaf, i ) Ivy_ManObj(p, Leaf)->fMarkA = 0; } /**Function************************************************************* Synopsis [Returns the pointer to the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Ivy_ObjGetTruthStore( int ObjNum, Vec_Int_t * vTruth ) { return ((unsigned *)Vec_IntArray(vTruth)) + 8 * ObjNum; } /**Function************************************************************* Synopsis [Computes truth table of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManCutTruthOne( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vTruth, int nWords ) { unsigned * pTruth, * pTruth0, * pTruth1; int i; pTruth = Ivy_ObjGetTruthStore( pNode->TravId, vTruth ); pTruth0 = Ivy_ObjGetTruthStore( Ivy_ObjFanin0(pNode)->TravId, vTruth ); pTruth1 = Ivy_ObjGetTruthStore( Ivy_ObjFanin1(pNode)->TravId, vTruth ); if ( Ivy_ObjIsExor(pNode) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] ^ pTruth1[i]; else if ( !Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] & pTruth1[i]; else if ( !Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = pTruth0[i] & ~pTruth1[i]; else if ( Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = ~pTruth0[i] & pTruth1[i]; else // if ( Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) ) for ( i = 0; i < nWords; i++ ) pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; } /**Function************************************************************* Synopsis [Computes truth table of the cut.] Description [Does not modify the array of leaves. Uses array vTruth to store temporary truth tables. The returned pointer should be used immediately.] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth ) { static unsigned uTruths[8][8] = { // elementary truth tables { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } }; int i, Leaf; // collect the cut Ivy_ManCollectCut( p, pRoot, vLeaves, vNodes ); // set the node numbers Vec_IntForEachEntry( vNodes, Leaf, i ) Ivy_ManObj(p, Leaf)->TravId = i; // alloc enough memory Vec_IntClear( vTruth ); Vec_IntGrow( vTruth, 8 * Vec_IntSize(vNodes) ); // set the elementary truth tables Vec_IntForEachEntry( vLeaves, Leaf, i ) memcpy( Ivy_ObjGetTruthStore(i, vTruth), uTruths[i], 8 * sizeof(unsigned) ); // compute truths for other nodes Vec_IntForEachEntryStart( vNodes, Leaf, i, Vec_IntSize(vLeaves) ) Ivy_ManCutTruthOne( p, Ivy_ManObj(p, Leaf), vTruth, 8 ); return Ivy_ObjGetTruthStore( pRoot->TravId, vTruth ); } /**Function************************************************************* Synopsis [Collect the latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p ) { Vec_Int_t * vLatches; Ivy_Obj_t * pObj; int i; vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) ); Ivy_ManForEachLatch( p, pObj, i ) Vec_IntPush( vLatches, pObj->Id ); return vLatches; } /**Function************************************************************* Synopsis [Collect the latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManLevels( Ivy_Man_t * p ) { Ivy_Obj_t * pObj; int i, LevelMax = 0; Ivy_ManForEachPo( p, pObj, i ) LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level ); return LevelMax; } /**Function************************************************************* Synopsis [Collect the latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ManResetLevels_rec( Ivy_Obj_t * pObj ) { if ( pObj->Level || Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) ) return pObj->Level; if ( Ivy_ObjIsBuf(pObj) ) return pObj->Level = Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); assert( Ivy_ObjIsNode(pObj) ); Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); Ivy_ManResetLevels_rec( Ivy_ObjFanin1(pObj) ); return pObj->Level = Ivy_ObjLevelNew( pObj ); } /**Function************************************************************* Synopsis [Collect the latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManResetLevels( Ivy_Man_t * p ) { Ivy_Obj_t * pObj; int i; Ivy_ManForEachObj( p, pObj, i ) pObj->Level = 0; Ivy_ManForEachCo( p, pObj, i ) Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); } /**Function************************************************************* Synopsis [References/references the node and returns MFFC size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ObjRefDeref( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fReference, int fLabel ) { Ivy_Obj_t * pNode0, * pNode1; int Counter; // label visited nodes if ( fLabel ) Ivy_ObjSetTravIdCurrent( p, pNode ); // skip the CI if ( Ivy_ObjIsPi(pNode) ) return 0; assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsBuf(pNode) || Ivy_ObjIsLatch(pNode) ); // process the internal node pNode0 = Ivy_ObjFanin0(pNode); pNode1 = Ivy_ObjFanin1(pNode); Counter = Ivy_ObjIsNode(pNode); if ( fReference ) { if ( pNode0->nRefs++ == 0 ) Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel ); if ( pNode1 && pNode1->nRefs++ == 0 ) Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel ); } else { assert( pNode0->nRefs > 0 ); assert( pNode1 == NULL || pNode1->nRefs > 0 ); if ( --pNode0->nRefs == 0 ) Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel ); if ( pNode1 && --pNode1->nRefs == 0 ) Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel ); } return Counter; } /**Function************************************************************* Synopsis [Labels MFFC with the current label.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pNode ) { int nConeSize1, nConeSize2; assert( !Ivy_IsComplement( pNode ) ); assert( Ivy_ObjIsNode( pNode ) ); nConeSize1 = Ivy_ObjRefDeref( p, pNode, 0, 1 ); // dereference nConeSize2 = Ivy_ObjRefDeref( p, pNode, 1, 0 ); // reference assert( nConeSize1 == nConeSize2 ); assert( nConeSize1 > 0 ); return nConeSize1; } /**Function************************************************************* Synopsis [Recursively updates fanout levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { Ivy_Obj_t * pFanout; Vec_Ptr_t * vFanouts; int i, LevelNew; assert( p->fFanout ); assert( Ivy_ObjIsNode(pObj) ); vFanouts = Vec_PtrAlloc( 10 ); Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) { if ( Ivy_ObjIsCo(pFanout) ) { // assert( (int)Ivy_ObjFanin0(pFanout)->Level <= p->nLevelMax ); continue; } LevelNew = Ivy_ObjLevelNew( pFanout ); if ( (int)pFanout->Level == LevelNew ) continue; pFanout->Level = LevelNew; Ivy_ObjUpdateLevel_rec( p, pFanout ); } Vec_PtrFree( vFanouts ); } /**Function************************************************************* Synopsis [Compute the new required level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ObjLevelRNew( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { Ivy_Obj_t * pFanout; Vec_Ptr_t * vFanouts; int i, Required, LevelNew = 1000000; assert( p->fFanout && p->vRequired ); vFanouts = Vec_PtrAlloc( 10 ); Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) { Required = Vec_IntEntry(p->vRequired, pFanout->Id); LevelNew = IVY_MIN( LevelNew, Required ); } Vec_PtrFree( vFanouts ); return LevelNew - 1; } /**Function************************************************************* Synopsis [Recursively updates fanout levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew ) { Ivy_Obj_t * pFanin; if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) return; assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); // process the first fanin pFanin = Ivy_ObjFanin0(pObj); if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 ) { Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 ); Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 ); } if ( Ivy_ObjIsBuf(pObj) ) return; // process the second fanin pFanin = Ivy_ObjFanin1(pObj); if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 ) { Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 ); Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 ); } } /**Function************************************************************* Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_ObjIsMuxType( Ivy_Obj_t * pNode ) { Ivy_Obj_t * pNode0, * pNode1; // check that the node is regular assert( !Ivy_IsComplement(pNode) ); // if the node is not AND, this is not MUX if ( !Ivy_ObjIsAnd(pNode) ) return 0; // if the children are not complemented, this is not MUX if ( !Ivy_ObjFaninC0(pNode) || !Ivy_ObjFaninC1(pNode) ) return 0; // get children pNode0 = Ivy_ObjFanin0(pNode); pNode1 = Ivy_ObjFanin1(pNode); // if the children are not ANDs, this is not MUX if ( !Ivy_ObjIsAnd(pNode0) || !Ivy_ObjIsAnd(pNode1) ) return 0; // otherwise the node is MUX iff it has a pair of equal grandchildren return (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1))) || (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1))) || (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1))) || (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1))); } /**Function************************************************************* Synopsis [Recognizes what nodes are control and data inputs of a MUX.] Description [If the node is a MUX, returns the control variable C. Assigns nodes T and E to be the then and else variables of the MUX. Node C is never complemented. Nodes T and E can be complemented. This function also recognizes EXOR/NEXOR gates as MUXes.] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pNode, Ivy_Obj_t ** ppNodeT, Ivy_Obj_t ** ppNodeE ) { Ivy_Obj_t * pNode0, * pNode1; assert( !Ivy_IsComplement(pNode) ); assert( Ivy_ObjIsMuxType(pNode) ); // get children pNode0 = Ivy_ObjFanin0(pNode); pNode1 = Ivy_ObjFanin1(pNode); // find the control variable // if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p1) ) if ( Ivy_ObjFaninC0(pNode0) ) { // pNode2->p1 is positive phase of C *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); return Ivy_ObjChild0(pNode1);//pNode2->p1; } else { // pNode1->p1 is positive phase of C *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); return Ivy_ObjChild0(pNode0);//pNode1->p1; } } // else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) else if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p1) ) if ( Ivy_ObjFaninC0(pNode0) ) { // pNode2->p2 is positive phase of C *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); return Ivy_ObjChild1(pNode1);//pNode2->p2; } else { // pNode1->p1 is positive phase of C *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); return Ivy_ObjChild0(pNode0);//pNode1->p1; } } // else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p2) ) if ( Ivy_ObjFaninC1(pNode0) ) { // pNode2->p1 is positive phase of C *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); return Ivy_ObjChild0(pNode1);//pNode2->p1; } else { // pNode1->p2 is positive phase of C *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); return Ivy_ObjChild1(pNode0);//pNode1->p2; } } // else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p2) ) if ( Ivy_ObjFaninC1(pNode0) ) { // pNode2->p2 is positive phase of C *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); return Ivy_ObjChild1(pNode1);//pNode2->p2; } else { // pNode1->p2 is positive phase of C *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); return Ivy_ObjChild1(pNode0);//pNode1->p2; } } assert( 0 ); // this is not MUX return NULL; } /**Function************************************************************* Synopsis [Returns the real fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj ) { Ivy_Obj_t * pFanin; if ( pObj == NULL || !Ivy_ObjIsBuf( Ivy_Regular(pObj) ) ) return pObj; pFanin = Ivy_ObjReal( Ivy_ObjChild0(Ivy_Regular(pObj)) ); return Ivy_NotCond( pFanin, Ivy_IsComplement(pObj) ); } /**Function************************************************************* Synopsis [Prints node in HAIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig ) { Ivy_Obj_t * pTemp; int fShowFanouts = 0; assert( !Ivy_IsComplement(pObj) ); printf( "Node %5d : ", Ivy_ObjId(pObj) ); if ( Ivy_ObjIsConst1(pObj) ) printf( "constant 1" ); else if ( Ivy_ObjIsPi(pObj) ) printf( "PI" ); else if ( Ivy_ObjIsPo(pObj) ) printf( "PO" ); else if ( Ivy_ObjIsLatch(pObj) ) printf( "latch (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); else if ( Ivy_ObjIsBuf(pObj) ) printf( "buffer (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); else printf( "AND( %5d%s, %5d%s )", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " "), Ivy_ObjFanin1(pObj)->Id, (Ivy_ObjFaninC1(pObj)? "\'" : " ") ); printf( " (refs = %3d)", Ivy_ObjRefs(pObj) ); if ( fShowFanouts ) { Vec_Ptr_t * vFanouts; Ivy_Obj_t * pFanout; int i; vFanouts = Vec_PtrAlloc( 10 ); printf( "\nFanouts:\n" ); Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) { printf( " " ); printf( "Node %5d : ", Ivy_ObjId(pFanout) ); if ( Ivy_ObjIsPo(pFanout) ) printf( "PO" ); else if ( Ivy_ObjIsLatch(pFanout) ) printf( "latch (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") ); else if ( Ivy_ObjIsBuf(pFanout) ) printf( "buffer (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") ); else printf( "AND( %5d%s, %5d%s )", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " "), Ivy_ObjFanin1(pFanout)->Id, (Ivy_ObjFaninC1(pFanout)? "\'" : " ") ); printf( "\n" ); } Vec_PtrFree( vFanouts ); return; } if ( !fHaig ) { if ( pObj->pEquiv == NULL ) printf( " HAIG node not given" ); else printf( " HAIG node = %d%s", Ivy_Regular(pObj->pEquiv)->Id, (Ivy_IsComplement(pObj->pEquiv)? "\'" : " ") ); return; } if ( pObj->pEquiv == NULL ) return; // there are choices if ( Ivy_ObjRefs(pObj) > 0 ) { // print equivalence class printf( " { %5d ", pObj->Id ); assert( !Ivy_IsComplement(pObj->pEquiv) ); for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) printf( " %5d%s", pTemp->Id, (Ivy_IsComplement(pTemp->pEquiv)? "\'" : " ") ); printf( " }" ); return; } // this is a secondary node for ( pTemp = Ivy_Regular(pObj->pEquiv); Ivy_ObjRefs(pTemp) == 0; pTemp = Ivy_Regular(pTemp->pEquiv) ); assert( Ivy_ObjRefs(pTemp) > 0 ); printf( " class of %d", pTemp->Id ); } /**Function************************************************************* Synopsis [Prints node in HAIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig ) { Vec_Int_t * vNodes; Ivy_Obj_t * pObj; int i; printf( "PIs: " ); Ivy_ManForEachPi( p, pObj, i ) printf( " %d", pObj->Id ); printf( "\n" ); printf( "POs: " ); Ivy_ManForEachPo( p, pObj, i ) printf( " %d", pObj->Id ); printf( "\n" ); printf( "Latches: " ); Ivy_ManForEachLatch( p, pObj, i ) printf( " %d=%d%s", pObj->Id, Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); printf( "\n" ); vNodes = Ivy_ManDfsSeq( p, NULL ); Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) Ivy_ObjPrintVerbose( p, pObj, fHaig ), printf( "\n" ); printf( "\n" ); Vec_IntFree( vNodes ); } /**Function************************************************************* Synopsis [Performs incremental rewriting of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_CutTruthPrint2( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth ) { int i; printf( "Trying cut : {" ); for ( i = 0; i < pCut->nSize; i++ ) printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); printf( " } " ); Extra_PrintBinary( stdout, &uTruth, 16 ); printf( "\n" ); return 0; } /**Function************************************************************* Synopsis [Performs incremental rewriting of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ivy_CutTruthPrint( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth ) { Vec_Ptr_t * vArray; Ivy_Obj_t * pObj, * pFanout; int nLatches = 0; int nPresent = 0; int i, k; int fVerbose = 0; if ( fVerbose ) printf( "Trying cut : {" ); for ( i = 0; i < pCut->nSize; i++ ) { if ( fVerbose ) printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); nLatches += Ivy_LeafLat(pCut->pArray[i]); } if ( fVerbose ) printf( " } " ); if ( fVerbose ) printf( "Latches = %d. ", nLatches ); // check if there are latches on the fanout edges vArray = Vec_PtrAlloc( 100 ); for ( i = 0; i < pCut->nSize; i++ ) { pObj = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[i]) ); Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, k ) { if ( Ivy_ObjIsLatch(pFanout) ) { nPresent++; break; } } } Vec_PtrSize( vArray ); if ( fVerbose ) { printf( "Present = %d. ", nPresent ); if ( nLatches > nPresent ) printf( "Clauses = %d. ", 2*(nLatches - nPresent) ); printf( "\n" ); } return ( nLatches > nPresent ) ? 2*(nLatches - nPresent) : 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/ivy_.c000066400000000000000000000026501477524141600154530ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ivy_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [And-Inverter Graph package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - May 11, 2006.] Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ivy.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/ivy/module.make000066400000000000000000000011651477524141600164650ustar00rootroot00000000000000SRC += src/aig/ivy/ivyBalance.c \ src/aig/ivy/ivyCanon.c \ src/aig/ivy/ivyCheck.c \ src/aig/ivy/ivyCut.c \ src/aig/ivy/ivyCutTrav.c \ src/aig/ivy/ivyDfs.c \ src/aig/ivy/ivyDsd.c \ src/aig/ivy/ivyFanout.c \ src/aig/ivy/ivyFastMap.c \ src/aig/ivy/ivyFraig.c \ src/aig/ivy/ivyHaig.c \ src/aig/ivy/ivyMan.c \ src/aig/ivy/ivyMem.c \ src/aig/ivy/ivyMulti.c \ src/aig/ivy/ivyObj.c \ src/aig/ivy/ivyOper.c \ src/aig/ivy/ivyResyn.c \ src/aig/ivy/ivyRwr.c \ src/aig/ivy/ivySeq.c \ src/aig/ivy/ivyShow.c \ src/aig/ivy/ivyTable.c \ src/aig/ivy/ivyUtil.c abc-0.52/src/aig/miniaig/000077500000000000000000000000001477524141600151445ustar00rootroot00000000000000abc-0.52/src/aig/miniaig/abcOper.h000066400000000000000000000246761477524141600167070ustar00rootroot00000000000000/**CFile**************************************************************** FileName [acbTypes.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Hierarchical word-level netlist.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - July 21, 2015.] Revision [$Id: acbTypes.h,v 1.00 2014/11/29 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__base__acb__acb__types_h #define ABC__base__acb__acb__types_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// #ifndef _YOSYS_ ABC_NAMESPACE_HEADER_START #endif //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // network objects typedef enum { ABC_OPER_NONE = 0, // 00 unused ABC_OPER_PI, // 01 input ABC_OPER_PO, // 02 output ABC_OPER_CI, // 03 combinational input ABC_OPER_CO, // 04 combinational output ABC_OPER_FON, // 05 output placeholder ABC_OPER_BOX, // 06 box ABC_OPER_CONST_F, // 07 ABC_OPER_CONST_T, // 08 ABC_OPER_CONST_X, // 09 ABC_OPER_CONST_Z, // 10 ABC_OPER_BIT_BUF, // 11 ABC_OPER_BIT_INV, // 12 ABC_OPER_BIT_AND, // 13 ABC_OPER_BIT_NAND, // 14 ABC_OPER_BIT_OR, // 15 ABC_OPER_BIT_NOR, // 16 ABC_OPER_BIT_XOR, // 17 ABC_OPER_BIT_NXOR, // 18 ABC_OPER_BIT_SHARP, // 19 ABC_OPER_BIT_SHARPL, // 20 ABC_OPER_BIT_MUX, // 21 fanins are: {Ctrl, Data1, Data0} ABC_OPER_BIT_MAJ, // 22 ABC_OPER_ABC, // 23 ABC_OPER_BA, // 24 ABC_OPER_BO, // 25 ABC_OPER_BX, // 26 ABC_OPER_BN, // 27 ABC_OPER_BAO, // 28 ABC_OPER_BOA, // 29 ABC_OPER_RED_AND, // 30 ABC_OPER_RED_NAND, // 31 ABC_OPER_RED_OR, // 32 ABC_OPER_RED_NOR, // 33 ABC_OPER_RED_XOR, // 34 ABC_OPER_RED_NXOR, // 35 ABC_OPER_LOGIC_NOT, // 36 ABC_OPER_LOGIC_AND, // 37 ABC_OPER_LOGIC_NAND, // 38 ABC_OPER_LOGIC_OR, // 39 ABC_OPER_LOGIC_NOR, // 40 ABC_OPER_LOGIC_XOR, // 41 ABC_OPER_LOGIC_XNOR, // 42 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 ABC_OPER_SEL_PENC, // 47 ABC_OPER_SEL_DEC, // 48 ABC_OPER_SEL_EDEC, // 49 ABC_OPER_ARI_ADD, // 50 ABC_OPER_ARI_SUB, // 51 ABC_OPER_ARI_MUL, // 52 ABC_OPER_ARI_SMUL, // 53 ABC_OPER_ARI_DIV, // 54 ABC_OPER_ARI_MOD, // 55 ABC_OPER_ARI_REM, // 56 ABC_OPER_ARI_POW, // 57 ABC_OPER_ARI_MIN, // 58 ABC_OPER_ARI_SQRT, // 59 ABC_OPER_ARI_ABS, // 60 ABC_OPER_COMP_SLESS, // 61 ABC_OPER_COMP_LESS, // 62 ABC_OPER_COMP_LESSEQU, // 63 ABC_OPER_COMP_MOREEQU, // 64 ABC_OPER_COMP_MORE, // 65 ABC_OPER_COMP_EQU, // 66 ABC_OPER_COMP_NOTEQU, // 67 ABC_OPER_SHIFT_L, // 68 ABC_OPER_SHIFT_R, // 69 ABC_OPER_SHIFT_LA, // 70 ABC_OPER_SHIFT_RA, // 71 ABC_OPER_SHIFT_ROTL, // 72 ABC_OPER_SHIFT_ROTR, // 73 ABC_OPER_NODE, // 74 ABC_OPER_LUT, // 75 ABC_OPER_GATE, // 76 ABC_OPER_TABLE, // 77 ABC_OPER_TRI, // 78 ABC_OPER_RAM, // 79 ABC_OPER_RAMR, // 80 ABC_OPER_RAMW, // 81 ABC_OPER_RAMWC, // 82 ABC_OPER_RAML, // 83 ABC_OPER_RAMS, // 84 ABC_OPER_RAMBOX, // 85 ABC_OPER_LATCH, // 86 ABC_OPER_LATCHRS, // 87 ABC_OPER_DFF, // 88 ABC_OPER_DFFRSE, // 89 ABC_OPER_DFFLAST, // 90 ABC_OPER_SLICE, // 91 ABC_OPER_CONCAT, // 92 ABC_OPER_ZEROPAD, // 93 ABC_OPER_SIGNEXT, // 94 ABC_OPER_LOGIC_IMPL, // 95 ABC_OPER_ARI_SQUARE, // 96 ABC_OPER_CONST, // 97 ABC_OPER_ARI_ADDSUB, // 98 ABC_OPER_LAST // 99 } Acb_ObjType_t; // printing operator types static inline const char * Abc_OperName( int Type ) { if ( Type == ABC_OPER_NONE ) return NULL; if ( Type == ABC_OPER_PI ) return "pi"; if ( Type == ABC_OPER_PO ) return "po"; if ( Type == ABC_OPER_CI ) return "ci"; if ( Type == ABC_OPER_CO ) return "co"; if ( Type == ABC_OPER_FON ) return "fon"; if ( Type == ABC_OPER_BOX ) return "box"; if ( Type == ABC_OPER_BIT_BUF ) return "buf"; if ( Type == ABC_OPER_BIT_INV ) return "~"; if ( Type == ABC_OPER_BIT_MUX ) return "mux"; if ( Type == ABC_OPER_BIT_MAJ ) return "maj"; if ( Type == ABC_OPER_BIT_AND ) return "&"; if ( Type == ABC_OPER_BIT_OR ) return "|"; if ( Type == ABC_OPER_BIT_XOR ) return "^"; if ( Type == ABC_OPER_BIT_NAND ) return "~&"; if ( Type == ABC_OPER_BIT_NOR ) return "~|"; if ( Type == ABC_OPER_BIT_NXOR ) return "~^"; if ( Type == ABC_OPER_RED_AND ) return "&"; if ( Type == ABC_OPER_RED_OR ) return "|"; if ( Type == ABC_OPER_RED_XOR ) return "^"; if ( Type == ABC_OPER_RED_NAND ) return "~&"; if ( Type == ABC_OPER_RED_NOR ) return "~|"; if ( Type == ABC_OPER_RED_NXOR ) return "~^"; if ( Type == ABC_OPER_LOGIC_NOT ) return "!"; if ( Type == ABC_OPER_LOGIC_IMPL ) return "=>"; if ( Type == ABC_OPER_LOGIC_AND ) return "&&"; if ( Type == ABC_OPER_LOGIC_OR ) return "||"; if ( Type == ABC_OPER_LOGIC_XOR ) return "^^"; 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"; if ( Type == ABC_OPER_ARI_POW ) return "**"; if ( Type == ABC_OPER_ARI_MIN ) return "-"; if ( Type == ABC_OPER_ARI_SQRT ) return "sqrt"; if ( Type == ABC_OPER_ARI_SQUARE ) return "squar"; if ( Type == ABC_OPER_COMP_EQU ) return "=="; if ( Type == ABC_OPER_COMP_NOTEQU ) return "!="; if ( Type == ABC_OPER_COMP_LESS ) return "<"; if ( Type == ABC_OPER_COMP_MORE ) return ">"; if ( Type == ABC_OPER_COMP_LESSEQU ) return "<="; if ( Type == ABC_OPER_COMP_MOREEQU ) return ">="; if ( Type == ABC_OPER_SHIFT_L ) return "<<"; if ( Type == ABC_OPER_SHIFT_R ) return ">>"; if ( Type == ABC_OPER_SHIFT_LA ) return "<<<"; if ( Type == ABC_OPER_SHIFT_RA ) return ">>>"; 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 /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifndef _YOSYS_ ABC_NAMESPACE_HEADER_END #endif #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/aig/miniaig/miniaig.h000066400000000000000000000724271477524141600167460ustar00rootroot00000000000000/**CFile**************************************************************** FileName [miniaig.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Minimalistic AIG package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 29, 2012.] Revision [$Id: miniaig.h,v 1.00 2012/09/29 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef MINI_AIG__mini_aig_h #define MINI_AIG__mini_aig_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #ifndef _VERIFIC_DATABASE_H_ ABC_NAMESPACE_HEADER_START #endif //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// #define MINI_AIG_NULL (0x7FFFFFFF) #define MINI_AIG_START_SIZE (0x000000FF) //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Mini_Aig_t_ Mini_Aig_t; struct Mini_Aig_t_ { int nCap; int nSize; int nRegs; int * pArray; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // memory management #define MINI_AIG_ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) #define MINI_AIG_CALLOC(type, num) ((type *) calloc((num), sizeof(type))) #define MINI_AIG_FALLOC(type, num) ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num))) #define MINI_AIG_FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) #define MINI_AIG_REALLOC(type, obj, num) \ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ ((type *) malloc(sizeof(type) * (num)))) // internal procedures static void Mini_AigGrow( Mini_Aig_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pArray = MINI_AIG_REALLOC( int, p->pArray, nCapMin ); assert( p->pArray ); p->nCap = nCapMin; } static void Mini_AigPush( Mini_Aig_t * p, int Lit0, int Lit1 ) { if ( p->nSize + 2 > p->nCap ) { assert( p->nSize < MINI_AIG_NULL/4 ); if ( p->nCap < MINI_AIG_START_SIZE ) Mini_AigGrow( p, MINI_AIG_START_SIZE ); else Mini_AigGrow( p, 2 * p->nCap ); } p->pArray[p->nSize++] = Lit0; p->pArray[p->nSize++] = Lit1; } // accessing fanins static int Mini_AigNodeFanin0( Mini_Aig_t * p, int Id ) { assert( Id >= 0 && 2*Id < p->nSize ); 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] == 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; } static int Mini_AigLit2Var( int Lit ) { return Lit >> 1; } static int Mini_AigLitIsCompl( int Lit ) { return Lit & 1; } static int Mini_AigLitNot( int Lit ) { return Lit ^ 1; } static int Mini_AigLitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } static int Mini_AigLitRegular( int Lit ) { return Lit & ~01; } static int Mini_AigLitConst0() { return 0; } static int Mini_AigLitConst1() { return 1; } static int Mini_AigLitIsConst0( int Lit ) { return Lit == 0; } static int Mini_AigLitIsConst1( int Lit ) { return Lit == 1; } static int Mini_AigLitIsConst( int Lit ) { return Lit == 0 || Lit == 1; } static int Mini_AigNodeNum( Mini_Aig_t * p ) { return p->nSize/2; } static int Mini_AigNodeIsConst( Mini_Aig_t * p, int Id ) { assert( Id >= 0 ); return Id == 0; } static int Mini_AigNodeIsPi( Mini_Aig_t * p, int Id ) { assert( Id >= 0 ); return Id > 0 && Mini_AigNodeFanin0( p, Id ) == MINI_AIG_NULL; } static int Mini_AigNodeIsPo( Mini_Aig_t * p, int Id ) { assert( Id >= 0 ); return Id > 0 && Mini_AigNodeFanin0( p, Id ) != MINI_AIG_NULL && Mini_AigNodeFanin1( p, Id ) == MINI_AIG_NULL; } static int Mini_AigNodeIsAnd( Mini_Aig_t * p, int Id ) { assert( Id >= 0 ); return Id > 0 && Mini_AigNodeFanin0( p, Id ) != MINI_AIG_NULL && Mini_AigNodeFanin1( p, Id ) != MINI_AIG_NULL; } // working with sequential AIGs static int Mini_AigRegNum( Mini_Aig_t * p ) { return p->nRegs; } static void Mini_AigSetRegNum( Mini_Aig_t * p, int n ) { p->nRegs = n; } // iterators through objects #define Mini_AigForEachPi( p, i ) for (i = 1; i < Mini_AigNodeNum(p); i++) if ( !Mini_AigNodeIsPi(p, i) ) {} else #define Mini_AigForEachPo( p, i ) for (i = 1; i < Mini_AigNodeNum(p); i++) if ( !Mini_AigNodeIsPo(p, i) ) {} else #define Mini_AigForEachAnd( p, i ) for (i = 1; i < Mini_AigNodeNum(p); i++) if ( !Mini_AigNodeIsAnd(p, i) ) {} else // constructor/destructor static Mini_Aig_t * Mini_AigStart() { Mini_Aig_t * p; p = MINI_AIG_CALLOC( Mini_Aig_t, 1 ); p->nCap = MINI_AIG_START_SIZE; p->pArray = MINI_AIG_ALLOC( int, p->nCap ); 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 ); MINI_AIG_FREE( p ); } static int Mini_AigPiNum( Mini_Aig_t * p ) { int i, nPis = 0; Mini_AigForEachPi( p, i ) nPis++; return nPis; } static int Mini_AigPoNum( Mini_Aig_t * p ) { int i, nPos = 0; Mini_AigForEachPo( p, i ) nPos++; return nPos; } static int Mini_AigAndNum( Mini_Aig_t * p ) { int i, nNodes = 0; Mini_AigForEachAnd( p, i ) 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( "MiniAIG stats: PI = %d PO = %d FF = %d AND = %d\n", Mini_AigPiNum(p), Mini_AigPoNum(p), Mini_AigRegNum(p), Mini_AigAndNum(p) ); } // serialization static void Mini_AigDump( Mini_Aig_t * p, char * pFileName ) { FILE * pFile; int RetValue; pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open file for writing \"%s\".\n", pFileName ); return; } RetValue = (int)fwrite( &p->nSize, sizeof(int), 1, pFile ); RetValue = (int)fwrite( &p->nRegs, sizeof(int), 1, pFile ); RetValue = (int)fwrite( p->pArray, sizeof(int), p->nSize, pFile ); fclose( pFile ); } static Mini_Aig_t * Mini_AigLoad( char * pFileName ) { Mini_Aig_t * p; FILE * pFile; int RetValue, nSize; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open file for reading \"%s\".\n", pFileName ); return NULL; } RetValue = (int)fread( &nSize, sizeof(int), 1, pFile ); p = MINI_AIG_CALLOC( Mini_Aig_t, 1 ); p->nSize = p->nCap = nSize; p->pArray = MINI_AIG_ALLOC( int, p->nCap ); RetValue = (int)fread( &p->nRegs, sizeof(int), 1, pFile ); RetValue = (int)fread( p->pArray, sizeof(int), p->nSize, pFile ); fclose( pFile ); return p; } // creating nodes // (constant node is created when AIG manager is created) static int Mini_AigCreatePi( Mini_Aig_t * p ) { int Lit = p->nSize; Mini_AigPush( p, MINI_AIG_NULL, MINI_AIG_NULL ); return Lit; } static int Mini_AigCreatePo( Mini_Aig_t * p, int Lit0 ) { int Lit = p->nSize; assert( Lit0 >= 0 && Lit0 < Lit ); Mini_AigPush( p, Lit0, MINI_AIG_NULL ); return Lit; } // boolean operations 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 ); 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 ) { return Mini_AigLitNot( Mini_AigAnd( p, Mini_AigLitNot(Lit0), Mini_AigLitNot(Lit1) ) ); } static int Mini_AigMux( Mini_Aig_t * p, int LitC, int Lit1, int Lit0 ) { int Res0 = Mini_AigAnd( p, LitC, Lit1 ); int Res1 = Mini_AigAnd( p, Mini_AigLitNot(LitC), Lit0 ); return Mini_AigOr( p, Res0, Res1 ); } 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 ) { int status = 1; int i, iFaninLit0, iFaninLit1; Mini_AigForEachAnd( p, i ) { // get the fanin literals of this AND node iFaninLit0 = Mini_AigNodeFanin0( p, i ); iFaninLit1 = Mini_AigNodeFanin1( p, i ); // compare the fanin literals with the literal of the current node (2 * i) if ( iFaninLit0 >= 2 * i ) printf( "Fanin0 of AND node %d is not in a topological order.\n", i ), status = 0; if ( iFaninLit1 >= 2 * i ) printf( "Fanin0 of AND node %d is not in a topological order.\n", i ), status = 0; } Mini_AigForEachPo( p, i ) { // get the fanin literal of this PO node iFaninLit0 = Mini_AigNodeFanin0( p, i ); // compare the fanin literal with the literal of the current node (2 * i) if ( iFaninLit0 >= 2 * i ) printf( "Fanin0 of PO node %d is not in a topological order.\n", i ), status = 0; } return status; } // procedure to dump MiniAIG into a Verilog file static void Mini_AigDumpVerilog( char * pFileName, char * pModuleName, Mini_Aig_t * p ) { int i, k, iFaninLit0, iFaninLit1, Length = strlen(pModuleName), nPos = Mini_AigPoNum(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 ); MINI_AIG_FREE( pObjIsPi ); return; } // write interface //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 ) { fprintf( pFile, "%*sinput wire", Length+10, "" ); k = 0; Mini_AigForEachPi( p, i ) { if ( k++ % 12 == 0 ) fprintf( pFile, "\n%*s", Length+10, "" ); fprintf( pFile, "i%d, ", i ); pObjIsPi[i] = 1; } } fprintf( pFile, "\n%*soutput wire", Length+10, "" ); k = 0; Mini_AigForEachPo( p, i ) { if ( k++ % 12 == 0 ) fprintf( pFile, "\n%*s", Length+10, "" ); fprintf( pFile, "o%d%s", i, k==nPos ? "":", " ); } fprintf( pFile, "\n%*s);\n\n", Length+8, "" ); // write LUTs Mini_AigForEachAnd( p, i ) { iFaninLit0 = Mini_AigNodeFanin0( p, i ); iFaninLit1 = Mini_AigNodeFanin1( p, i ); fprintf( pFile, " assign n%d = ", i ); fprintf( pFile, "%s%c%d", (iFaninLit0 & 1) ? "~":"", pObjIsPi[iFaninLit0 >> 1] ? 'i':'n', iFaninLit0 >> 1 ); fprintf( pFile, " & " ); fprintf( pFile, "%s%c%d", (iFaninLit1 & 1) ? "~":"", pObjIsPi[iFaninLit1 >> 1] ? 'i':'n', iFaninLit1 >> 1 ); fprintf( pFile, ";\n" ); } // write assigns fprintf( pFile, "\n" ); Mini_AigForEachPo( p, i ) { iFaninLit0 = Mini_AigNodeFanin0( p, i ); fprintf( pFile, " assign o%d = ", i ); 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 ); 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 //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/aig/miniaig/minilut.h000066400000000000000000000267611477524141600170120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [minilut.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Minimalistic representation of LUT mapped network.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - September 29, 2012.] Revision [$Id: minilut.h,v 1.00 2012/09/29 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef MINI_LUT__mini_lut_h #define MINI_LUT__mini_lut_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// #define MINI_LUT_NULL (0x7FFFFFFF) #define MINI_LUT_NULL2 (0x7FFFFFFE) #define MINI_LUT_START_SIZE (0x000000FF) //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Mini_Lut_t_ Mini_Lut_t; struct Mini_Lut_t_ { int nCap; int nSize; int nRegs; int LutSize; int * pArray; unsigned * pTruths; }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // memory management #define MINI_LUT_ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) #define MINI_LUT_CALLOC(type, num) ((type *) calloc((num), sizeof(type))) #define MINI_LUT_FALLOC(type, num) ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num))) #define MINI_LUT_FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) #define MINI_LUT_REALLOC(type, obj, num) \ ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ ((type *) malloc(sizeof(type) * (num)))) // compute truth table size measured in unsigned's static int Mini_LutWordNum( int LutSize ) { return LutSize > 5 ? 1 << (LutSize-5) : 1; } // internal procedures static void Mini_LutGrow( Mini_Lut_t * p, int nCapMin ) { if ( p->nCap >= nCapMin ) return; p->pArray = MINI_LUT_REALLOC( int, p->pArray, nCapMin * p->LutSize ); p->pTruths = MINI_LUT_REALLOC( unsigned, p->pTruths, nCapMin * Mini_LutWordNum(p->LutSize) ); p->nCap = nCapMin; assert( p->pArray ); assert( p->pTruths ); } static void Mini_LutPush( Mini_Lut_t * p, int nVars, int * pVars, unsigned * pTruth ) { int i, nWords = Mini_LutWordNum(p->LutSize); if ( p->nSize == p->nCap ) { assert( p->LutSize*p->nSize < MINI_LUT_NULL/2 ); if ( p->nCap < MINI_LUT_START_SIZE ) Mini_LutGrow( p, MINI_LUT_START_SIZE ); 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++ ) p->pArray[p->LutSize * p->nSize + i] = MINI_LUT_NULL; for ( i = 0; i < nWords; i++ ) p->pTruths[nWords * p->nSize + i] = pTruth? pTruth[i] : 0; p->nSize++; } // accessing fanins static int Mini_LutNodeFanin( Mini_Lut_t * p, int Id, int k ) { assert( Id >= 0 && Id < p->nSize ); return p->pArray[p->LutSize*Id+k]; } static unsigned * Mini_LutNodeTruth( Mini_Lut_t * p, int Id ) { assert( Id >= 0 && Id < p->nSize ); return p->pTruths + Id * Mini_LutWordNum(p->LutSize); } // working with LUTs static int Mini_LutNodeConst0() { return 0; } static int Mini_LutNodeConst1() { return 1; } static int Mini_LutNodeNum( Mini_Lut_t * p ) { return p->nSize; } static int Mini_LutNodeIsConst( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id == 0 || Id == 1; } static int Mini_LutNodeIsPi( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id > 1 && Mini_LutNodeFanin( p, Id, 0 ) == MINI_LUT_NULL; } static int Mini_LutNodeIsPo( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id > 1 && Mini_LutNodeFanin( p, Id, 0 ) != MINI_LUT_NULL && Mini_LutNodeFanin( p, Id, 1 ) == MINI_LUT_NULL2; } static int Mini_LutNodeIsNode( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id > 1 && Mini_LutNodeFanin( p, Id, 0 ) != MINI_LUT_NULL && Mini_LutNodeFanin( p, Id, 1 ) != MINI_LUT_NULL2; } static int Mini_LutSize( Mini_Lut_t * p ) { return p->LutSize; } // working with sequential AIGs static int Mini_LutRegNum( Mini_Lut_t * p ) { return p->nRegs; } static void Mini_LutSetRegNum( Mini_Lut_t * p, int n ) { p->nRegs = n; } // iterators through objects #define Mini_LutForEachPi( p, i ) for (i = 2; i < Mini_LutNodeNum(p); i++) if ( !Mini_LutNodeIsPi(p, i) ) {} else #define Mini_LutForEachPo( p, i ) for (i = 2; i < Mini_LutNodeNum(p); i++) if ( !Mini_LutNodeIsPo(p, i) ) {} else #define Mini_LutForEachNode( p, i ) for (i = 2; i < Mini_LutNodeNum(p); i++) if ( !Mini_LutNodeIsNode(p, i) ) {} else // iterator through fanins #define Mini_LutForEachFanin( p, i, Fan, k ) for (k = 0; (k < p->LutSize) && (Fan = Mini_LutNodeFanin(p, i, k)) < MINI_LUT_NULL2; k++) // constructor/destructor static Mini_Lut_t * Mini_LutStart( int LutSize ) { Mini_Lut_t * p; int i; assert( LutSize >= 2 && LutSize <= 16 ); p = MINI_LUT_CALLOC( Mini_Lut_t, 1 ); p->LutSize = LutSize; p->nCap = MINI_LUT_START_SIZE; p->pArray = MINI_LUT_ALLOC( int, p->nCap * p->LutSize ); p->pTruths = MINI_LUT_ALLOC( unsigned, p->nCap * Mini_LutWordNum(p->LutSize) ); Mini_LutPush( p, 0, NULL, NULL ); // const0 Mini_LutPush( p, 0, NULL, NULL ); // const1 for ( i = 0; i < Mini_LutWordNum(p->LutSize); i++ ) p->pTruths[i] = 0; for ( i = 0; i < Mini_LutWordNum(p->LutSize); i++ ) p->pTruths[Mini_LutWordNum(p->LutSize) + i] = ~0; return p; } static void Mini_LutStop( Mini_Lut_t * p ) { MINI_LUT_FREE( p->pArray ); MINI_LUT_FREE( p->pTruths ); MINI_LUT_FREE( p ); } static void Mini_LutPrintStats( Mini_Lut_t * p ) { int i, nPis, nPos, nNodes; nPis = 0; Mini_LutForEachPi( p, i ) nPis++; nPos = 0; Mini_LutForEachPo( p, i ) nPos++; nNodes = 0; Mini_LutForEachNode( p, i ) 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 static void Mini_LutDump( Mini_Lut_t * p, char * pFileName ) { FILE * pFile; int RetValue; pFile = fopen( pFileName, "wb" ); if ( pFile == NULL ) { printf( "Cannot open file for writing \"%s\".\n", pFileName ); return; } RetValue = (int)fwrite( &p->nSize, sizeof(int), 1, pFile ); RetValue = (int)fwrite( &p->nRegs, sizeof(int), 1, pFile ); RetValue = (int)fwrite( &p->LutSize, sizeof(int), 1, pFile ); RetValue = (int)fwrite( p->pArray, sizeof(int), p->nSize * p->LutSize, pFile ); RetValue = (int)fwrite( p->pTruths, sizeof(int), p->nSize * Mini_LutWordNum(p->LutSize), pFile ); fclose( pFile ); } static Mini_Lut_t * Mini_LutLoad( char * pFileName ) { Mini_Lut_t * p; FILE * pFile; int RetValue, nSize; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open file for reading \"%s\".\n", pFileName ); return NULL; } RetValue = (int)fread( &nSize, sizeof(int), 1, pFile ); p = MINI_LUT_CALLOC( Mini_Lut_t, 1 ); p->nSize = p->nCap = nSize; RetValue = (int)fread( &p->nRegs, sizeof(int), 1, pFile ); RetValue = (int)fread( &p->LutSize, sizeof(int), 1, pFile ); p->pArray = MINI_LUT_ALLOC( int, p->nCap * p->LutSize ); p->pTruths = MINI_LUT_ALLOC( unsigned, p->nCap * Mini_LutWordNum(p->LutSize) ); RetValue = (int)fread( p->pArray, sizeof(int), p->nCap * p->LutSize, pFile ); RetValue = (int)fread( p->pTruths, sizeof(int), p->nCap * Mini_LutWordNum(p->LutSize), pFile ); fclose( pFile ); return p; } // creating nodes // (constant nodes are created when LUT manager is created) static int Mini_LutCreatePi( Mini_Lut_t * p ) { Mini_LutPush( p, 0, NULL, NULL ); return p->nSize - 1; } static int Mini_LutCreatePo( Mini_Lut_t * p, int Var0 ) { assert( Var0 >= 0 && Var0 < p->nSize ); Mini_LutPush( p, 1, &Var0, NULL ); // mark PO by setting its 2nd fanin to the special number p->pArray[p->LutSize*(p->nSize - 1)+1] = MINI_LUT_NULL2; return p->nSize - 1; } // create LUT static int Mini_LutCreateNode( Mini_Lut_t * p, int nVars, int * pVars, unsigned * pTruth ) { assert( nVars >= 0 && nVars <= p->LutSize ); Mini_LutPush( p, nVars, pVars, pTruth ); return p->nSize - 1; } // procedure to check the topological order during AIG construction static int Mini_LutCheck( Mini_Lut_t * p ) { int status = 1; int i, k, iFaninVar; Mini_LutForEachNode( p, i ) { for ( k = 0; k < p->LutSize; k++ ) { iFaninVar = Mini_LutNodeFanin( p, i, k ); if ( iFaninVar == MINI_LUT_NULL ) continue; if ( iFaninVar >= p->LutSize * i ) printf( "Fanin %d of LUT node %d is not in a topological order.\n", k, i ), status = 0; } } Mini_LutForEachPo( p, i ) { iFaninVar = Mini_LutNodeFanin( p, i, 0 ); if ( iFaninVar >= p->LutSize * i ) printf( "Fanin %d of PO node %d is not in a topological order.\n", k, i ), status = 0; } return status; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/aig/miniaig/module.make000066400000000000000000000000101477524141600172570ustar00rootroot00000000000000SRC += abc-0.52/src/aig/miniaig/ndr.h000066400000000000000000001375361477524141600161170ustar00rootroot00000000000000/**CFile**************************************************************** FileName [ndr.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Format for word-level design representation.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 22, 2014.] Revision [$Id: ndr.h,v 1.00 2014/09/12 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__base__ndr__ndr_h #define ABC__base__ndr__ndr_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "abcOper.h" #ifndef _YOSYS_ ABC_NAMESPACE_HEADER_START #endif #ifdef _WIN32 #define inline __inline #endif /* For the lack of a better name, this format is called New Data Representation (NDR). 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) */ //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// // record types typedef enum { NDR_NONE = 0, // 0: unused NDR_DESIGN, // 1: design (or library of modules) NDR_MODULE, // 2: one module NDR_OBJECT, // 3: object NDR_INPUT, // 4: input NDR_OUTPUT, // 5: output NDR_OPERTYPE, // 6: operator type (buffer, shifter, adder, etc) NDR_NAME, // 7: name NDR_RANGE, // 8: bit range NDR_FUNCTION, // 9: specified for some operators (PLAs, etc) NDR_TARGET, // 10: target NDR_UNKNOWN // 11: unknown } Ndr_RecordType_t; //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// // this is an internal procedure, which is not seen by the user typedef struct Ndr_Data_t_ Ndr_Data_t; struct Ndr_Data_t_ { int nSize; int nCap; unsigned char * pHead; unsigned int * pBody; }; static inline int Ndr_DataType( Ndr_Data_t * p, int i ) { assert( p->pHead[i] ); return (int)p->pHead[i]; } static inline int Ndr_DataSize( Ndr_Data_t * p, int i ) { return Ndr_DataType(p, i) > NDR_OBJECT ? 1 : p->pBody[i]; } static inline int Ndr_DataEntry( Ndr_Data_t * p, int i ) { return (int)p->pBody[i]; } static inline int * Ndr_DataEntryP( Ndr_Data_t * p, int i ) { return (int *)p->pBody + i; } static inline int Ndr_DataEnd( Ndr_Data_t * p, int i ) { return i + p->pBody[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 /// //////////////////////////////////////////////////////////////////////// // iterates over modules in the design #define Ndr_DesForEachMod( p, Mod ) \ for ( Mod = 1; Mod < Ndr_DataEntry(p, 0); Mod += Ndr_DataSize(p, Mod) ) if (Ndr_DataType(p, Mod) != NDR_MODULE) {} else // iterates over objects in a module #define Ndr_ModForEachObj( p, Mod, Obj ) \ for ( Obj = Mod + 1; Obj < Ndr_DataEnd(p, Mod); Obj += Ndr_DataSize(p, Obj) ) if (Ndr_DataType(p, Obj) != NDR_OBJECT) {} else // iterates over records in an object #define Ndr_ObjForEachEntry( p, Obj, Ent ) \ for ( Ent = Obj + 1; Ent < Ndr_DataEnd(p, Obj); Ent += Ndr_DataSize(p, Ent) ) // iterates over primary inputs of a module #define Ndr_ModForEachPi( p, Mod, Obj ) \ Ndr_ModForEachObj( p, Mod, Obj ) if ( !Ndr_ObjIsType(p, Obj, ABC_OPER_CI) ) {} else // iteraots over primary outputs of a module #define Ndr_ModForEachPo( p, Mod, Obj ) \ Ndr_ModForEachObj( p, Mod, Obj ) if ( !Ndr_ObjIsType(p, Obj, ABC_OPER_CO) ) {} else // iterates over internal nodes of a module #define Ndr_ModForEachNode( p, Mod, Obj ) \ Ndr_ModForEachObj( p, Mod, Obj ) if ( Ndr_ObjIsType(p, Obj, ABC_OPER_CI) || Ndr_ObjIsType(p, Obj, ABC_OPER_CO) ) {} else // iterates over target signals of a module #define Ndr_ModForEachTarget( p, Mod, Obj ) \ for ( Obj = Mod + 1; Obj < Ndr_DataEnd(p, Mod); Obj += Ndr_DataSize(p, Obj) ) if (Ndr_DataType(p, Obj) != NDR_TARGET) {} else //////////////////////////////////////////////////////////////////////// /// INTERNAL PROCEDURES /// //////////////////////////////////////////////////////////////////////// static inline void Ndr_DataResize( Ndr_Data_t * p, int Add ) { if ( p->nSize + Add <= p->nCap ) return; 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 ); } static inline void Ndr_DataPushRange( Ndr_Data_t * p, int RangeLeft, int RangeRight, int fSignedness ) { if ( fSignedness ) { Ndr_DataPush( p, NDR_RANGE, RangeLeft ); Ndr_DataPush( p, NDR_RANGE, RangeRight ); Ndr_DataPush( p, NDR_RANGE, fSignedness ); return; } if ( !RangeLeft && !RangeRight ) return; if ( RangeLeft == RangeRight ) Ndr_DataPush( p, NDR_RANGE, RangeLeft ); else { Ndr_DataPush( p, NDR_RANGE, RangeLeft ); Ndr_DataPush( p, NDR_RANGE, RangeRight ); } } static inline void Ndr_DataPushArray( Ndr_Data_t * p, int Type, int nArray, int * pArray ) { if ( !nArray ) return; assert( nArray > 0 ); Ndr_DataResize( p, 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 ObjType, int Type, char * pFunc ) { int nBuffInts; int * pBuff; if ( !pFunc ) return; if ( ObjType == ABC_OPER_LUT ) { //word Truth = (word)pFunc; //Ndr_DataPushArray( p, Type, 2, (int *)&Truth ); int nInts = (strlen(pFunc) + 1 + sizeof(int) - 1) / sizeof(int); Ndr_DataPushArray( p, Type, nInts, (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 ); } } //////////////////////////////////////////////////////////////////////// /// VERILOG WRITING /// //////////////////////////////////////////////////////////////////////// static inline int Ndr_ObjReadEntry( Ndr_Data_t * p, int Obj, int Type ) { int Ent; Ndr_ObjForEachEntry( p, Obj, Ent ) if ( Ndr_DataType(p, Ent) == Type ) return Ndr_DataEntry(p, Ent); return -1; } static inline int Ndr_ObjReadArray( Ndr_Data_t * p, int Obj, int Type, int ** ppStart ) { int Ent, Counter = 0; *ppStart = NULL; Ndr_ObjForEachEntry( p, Obj, Ent ) if ( Ndr_DataType(p, Ent) == Type ) { Counter++; if ( *ppStart == NULL ) *ppStart = (int *)p->pBody + Ent; } else if ( *ppStart ) return Counter; return Counter; } static inline int Ndr_ObjIsType( Ndr_Data_t * p, int Obj, int Type ) { int Ent; Ndr_ObjForEachEntry( p, Obj, Ent ) if ( Ndr_DataType(p, Ent) == NDR_OPERTYPE ) return (int)(Ndr_DataEntry(p, Ent) == Type); return -1; } static inline int Ndr_ObjReadBody( Ndr_Data_t * p, int Obj, int Type ) { int Ent; Ndr_ObjForEachEntry( p, Obj, Ent ) if ( Ndr_DataType(p, Ent) == Type ) return Ndr_DataEntry(p, Ent); return -1; } static inline int * Ndr_ObjReadBodyP( Ndr_Data_t * p, int Obj, int Type ) { int Ent; Ndr_ObjForEachEntry( p, Obj, Ent ) if ( Ndr_DataType(p, Ent) == Type ) return Ndr_DataEntryP(p, Ent); return NULL; } static inline void Ndr_ObjWriteRange( Ndr_Data_t * p, int Obj, FILE * pFile, int fSkipBin ) { int * pArray, nArray = Ndr_ObjReadArray( p, Obj, NDR_RANGE, &pArray ); if ( (nArray == 0 || nArray == 1) && fSkipBin ) return; if ( nArray == 3 && fSkipBin ) fprintf( pFile, "signed " ); else if ( nArray == 1 ) { if ( fSkipBin ) fprintf( pFile, "[%d:%d]", pArray[0], pArray[0] ); else fprintf( pFile, "[%d]", pArray[0] ); } else if ( nArray == 0 ) { if ( fSkipBin ) fprintf( pFile, "[%d:%d]", 0, 0 ); else fprintf( pFile, "[%d]", 0 ); } else fprintf( pFile, "[%d:%d]", pArray[0], pArray[1] ); } static inline char * Ndr_ObjReadOutName( Ndr_Data_t * p, int Obj, char ** pNames ) { return pNames[Ndr_ObjReadBody(p, Obj, NDR_OUTPUT)]; } static inline char * Ndr_ObjReadInName( Ndr_Data_t * p, int Obj, char ** pNames ) { return pNames[Ndr_ObjReadBody(p, Obj, NDR_INPUT)]; } static inline int Ndr_DataCiNum( Ndr_Data_t * p, int Mod ) { int Obj, Count = 0; Ndr_ModForEachPi( p, Mod, Obj ) Count++; return Count; } static inline int Ndr_DataCoNum( Ndr_Data_t * p, int Mod ) { int Obj, Count = 0; Ndr_ModForEachPo( p, Mod, Obj ) Count++; return Count; } static inline int Ndr_DataObjNum( Ndr_Data_t * p, int Mod ) { int Obj, Count = 0; Ndr_ModForEachObj( p, Mod, Obj ) Count++; return Count; } // 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, int fSimple ) { Ndr_Data_t * p = (Ndr_Data_t *)pDesign; 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)] ); Ndr_ModForEachPi( p, Mod, Obj ) fprintf( pFile, "%s, ", Ndr_ObjReadOutName(p, Obj, pNames) ); fprintf( pFile, "\n " ); Ndr_ModForEachPo( p, Mod, Obj ) fprintf( pFile, "%s%s", fFirst ? "":", ", Ndr_ObjReadInName(p, Obj, pNames) ), fFirst = 0; fprintf( pFile, "\n);\n\n" ); Ndr_ModForEachPi( p, Mod, Obj ) { fprintf( pFile, " input " ); Ndr_ObjWriteRange( p, Obj, pFile, 1 ); 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" ); Ndr_ModForEachNode( p, Mod, Obj ) { int i, Type = Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE); if ( Type >= 256 ) { fprintf( pFile, " %s ", pNames[Ndr_ObjReadEntry(p, Type-256, 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 ); for ( i = 0; i < nArray; i++ ) fprintf( pFile, "%s%s ", pNames[pArray[i]], i==nArray-1 ? "":"," ); 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 ) 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 if ( Type == ABC_OPER_SLICE ) fprintf( pFile, "%s", pNames[pArray[0]] ), Ndr_ObjWriteRange( p, Obj, pFile, 0 ), fprintf( pFile, ";\n" ); else if ( Type == ABC_OPER_CONCAT ) { fprintf( pFile, "{" ); for ( i = 0; i < nArray; i++ ) fprintf( pFile, "%s%s", pNames[pArray[i]], i==nArray-1 ? "":", " ); fprintf( pFile, "};\n" ); } else if ( nArray == 1 ) fprintf( pFile, "%s %s;\n", Abc_OperName(Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE)), pNames[pArray[0]] ); else if ( nArray == 2 ) fprintf( pFile, "%s %s %s;\n", pNames[pArray[0]], Abc_OperName(Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE)), pNames[pArray[1]] ); 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[2]], pNames[pArray[1]] ); else fprintf( pFile, ";\n", Abc_OperName(Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE)) ); } fprintf( pFile, "\nendmodule\n\n" ); } // 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, 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 ? pFileName : "stdout" ); return; } Ndr_DesForEachMod( p, Mod ) Ndr_WriteVerilogModule( pFile, p, Mod, pNames, fSimple ); if ( pFileName ) fclose( pFile ); } //////////////////////////////////////////////////////////////////////// /// EXTERNAL PROCEDURES /// //////////////////////////////////////////////////////////////////////// // 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 = NDR_ALLOC( Ndr_Data_t, 1 ); p->nSize = 0; p->nCap = 16; 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 ); assert( p->nSize == 2 ); assert( Name ); return p; } // creating a new module in an already started design // returns module ID to be used when adding objects to the module static inline int Ndr_AddModule( void * pDesign, int Name ) { Ndr_Data_t * p = (Ndr_Data_t *)pDesign; int Mod = p->nSize; Ndr_DataResize( p, 6 ); Ndr_DataPush( p, NDR_MODULE, 0 ); Ndr_DataPush( p, NDR_NAME, Name ); Ndr_DataAddTo( p, Mod, p->nSize - Mod ); Ndr_DataAddTo( p, 0, p->nSize - Mod ); assert( (int)p->pBody[0] == p->nSize ); return Mod + 256; } // adding a new object (input/output/flop/intenal node) to an already started module // this procedure takes the design, the module ID, and the parameters of the boject // (please note that all objects should be added to a given module before starting a new module) static inline void Ndr_AddObject( void * pDesign, int ModuleId, int ObjType, int InstName, int RangeLeft, int RangeRight, int fSignedness, int nInputs, int * pInputs, int nOutputs, int * pOutputs, char * pFunction ) { Ndr_Data_t * p = (Ndr_Data_t *)pDesign; int Mod = ModuleId - 256; int Obj = p->nSize; assert( ObjType != 0 ); Ndr_DataResize( p, 6 ); Ndr_DataPush( p, NDR_OBJECT, 0 ); Ndr_DataPush( p, NDR_OPERTYPE, ObjType ); Ndr_DataPushRange( p, RangeLeft, RangeRight, fSignedness ); if ( InstName ) Ndr_DataPush( p, NDR_NAME, InstName ); Ndr_DataPushArray( p, NDR_INPUT, nInputs, pInputs ); Ndr_DataPushArray( p, NDR_OUTPUT, nOutputs, pOutputs ); 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 ); assert( (int)p->pBody[0] == p->nSize ); } // deallocate the memory buffer static inline void Ndr_Delete( void * pDesign ) { Ndr_Data_t * p = (Ndr_Data_t *)pDesign; if ( !p ) return; free( p->pHead ); free( p->pBody ); free( p ); } //////////////////////////////////////////////////////////////////////// /// FILE READING AND WRITING /// //////////////////////////////////////////////////////////////////////// // file reading/writing static inline void * Ndr_Read( char * pFileName ) { Ndr_Data_t * p; int nFileSize, RetValue; FILE * pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for reading.\n", pFileName ); return NULL; } // 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 = NDR_ALLOC( Ndr_Data_t, 1 ); p->nSize = p->nCap = nFileSize / 5; 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] ); fclose( pFile ); //printf( "Read the design from file \"%s\".\n", pFileName ); return p; } 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 ? 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 ); //printf( "Dumped the design into file \"%s\".\n", pFileName ); } //////////////////////////////////////////////////////////////////////// /// TESTING PROCEDURE /// //////////////////////////////////////////////////////////////////////// // This testing procedure creates and writes into a Verilog file // the following design composed of one module // module add10 ( input [3:0] a, output [3:0] s ); // wire [3:0] const10 = 4'b1010; // assign s = a + const10; // endmodule static inline void Ndr_ModuleTest() { // name IDs int NameIdA = 2; int NameIdS = 3; int NameIdC = 4; // 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" }; // 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, &NameIdA, NULL ); // 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, 0 ); Ndr_Write( (char*)"add4.ndr", pDesign ); Ndr_Delete( pDesign ); } // This testing procedure creates and writes into a Verilog file // 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]; // wire [3:0] b0 = b[3:0]; // wire [7:4] a1 = a[7:4]; // wire [7:4] b1 = b[7:4]; // wire [4:0] r0 = a0 + b0; // wire [3:0] s0 = r0[3:0]; // wire rco = r0[4]; // wire [4:0] r1 = a1 + b1 + rco; // wire [3:0] s1 = r1[3:0]; // assign co = r1[4]; // assign s = {s1, s0}; // endmodule static inline void Ndr_ModuleTestAdder() { /* // map name IDs into char strings char * ppNames[20] = { NULL, "a", "b", "s", "co", // 1, 2, 3, 4 "a0", "a1", "b0", "b1", // 5, 6, 7, 8 "r0", "s0", "rco", // 9, 10, 11 "r1", "s1", "add8" // 12, 13, 14 }; */ // fanins int FaninA = 1; int FaninB = 2; int FaninS = 3; int FaninCO = 4; int FaninA0 = 5; int FaninA1 = 6; int FaninB0 = 7; int FaninB1 = 8; int FaninR0 = 9; int FaninS0 = 10; int FaninRCO = 11; int FaninR1 = 12; int FaninS1 = 13; int Fanins1[2] = { FaninA0, FaninB0 }; int Fanins2[3] = { FaninA1, FaninB1, FaninRCO }; int Fanins3[4] = { FaninS1, FaninS0 }; // create a new module void * pDesign = Ndr_Create( 14 ); int ModuleID = Ndr_AddModule( pDesign, 14 ); // add objects to the modele Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 7, 0, 0, 0, NULL, 1, &FaninA, NULL ); // no fanins Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 7, 0, 0, 0, NULL, 1, &FaninB, NULL ); // no fanins Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 3, 0, 0, 1, &FaninA, 1, &FaninA0, NULL ); // wire [3:0] a0 = a[3:0]; Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 3, 0, 0, 1, &FaninB, 1, &FaninB0, NULL ); // wire [3:0] b0 = a[3:0]; Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 7, 4, 0, 1, &FaninA, 1, &FaninA1, NULL ); // wire [7:4] a1 = a[7:4]; Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 7, 4, 0, 1, &FaninB, 1, &FaninB1, NULL ); // wire [7:4] b1 = b[7:4]; Ndr_AddObject( pDesign, ModuleID, ABC_OPER_ARI_ADD, 0, 4, 0, 0, 2, Fanins1, 1, &FaninR0, NULL ); // wire [4:0] r0 = a0 + b0; Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 3, 0, 0, 1, &FaninR0, 1, &FaninS0, NULL ); // wire [3:0] s0 = r0[3:0]; Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 4, 4, 0, 1, &FaninR0, 1, &FaninRCO, NULL ); // wire rco = r0[4]; Ndr_AddObject( pDesign, ModuleID, ABC_OPER_ARI_ADD, 0, 4, 0, 0, 3, Fanins2, 1, &FaninR1, NULL ); // wire [4:0] r1 = a1 + b1 + rco; Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 3, 0, 0, 1, &FaninR1, 1, &FaninS1, NULL ); // wire [3:0] s1 = r1[3:0]; Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 4, 4, 0, 1, &FaninR1, 1, &FaninCO, NULL ); // assign co = r1[4]; Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CONCAT, 0, 7, 0, 0, 2, Fanins3, 1, &FaninS, NULL ); // s = {s1, s0}; Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 7, 0, 0, 1, &FaninS, 0, NULL, NULL ); 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, 0 ); Ndr_Write( (char*)"add8.ndr", pDesign ); Ndr_Delete( pDesign ); } // This testing procedure creates and writes into a Verilog file // 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; // endmodule // module mux41w ( input [1:0] sel, input [15:0] d, output [3:0] out ); // wire [3:0] t0, t1; // wire [3:0] d0 = d[3:0]; // wire [3:0] d1 = d[7:4]; // wire [3:0] d2 = d[11:8]; // wire [3:0] d3 = d[15:12]; // wire sel0 = sel[0]; // wire sel1 = sel[1]; // mux21w i0 ( sel0, d1, d0, t0 ); // mux21w i1 ( sel0, d3, d2, t1 ); // mux21w i2 ( sel1, t1, t0, out ); // endmodule static inline void Ndr_ModuleTestHierarchy() { /* // map name IDs into char strings char * ppNames[20] = { NULL, "mux21w", "mux41w", // 1, 2 "sel", "d", "out", // 3, 4, 5 "d0", "d1", "d2", "d3", // 6, 7, 8, 9 "sel0", "sel1", // 10, 11, "t0", "t1", // 12, 13 "i0", "i1", "i2" // 14, 15, 16 }; */ // fanins int FaninSel = 3; int FaninSel0 = 10; int FaninSel1 = 11; int FaninD = 4; int FaninD0 = 6; int FaninD1 = 7; int FaninD2 = 8; int FaninD3 = 9; int FaninT0 = 12; int FaninT1 = 13; int FaninOut = 5; int Fanins1[3] = { FaninSel, FaninD1, FaninD0 }; int Fanins3[3][3] = { {FaninSel0, FaninD1, FaninD0 }, {FaninSel0, FaninD3, FaninD2 }, {FaninSel1, FaninT1, FaninT0 } }; // create a new module void * pDesign = Ndr_Create( 2 ); int Module21, Module41; Module21 = Ndr_AddModule( pDesign, 1 ); Ndr_AddObject( pDesign, Module21, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &FaninSel, NULL ); Ndr_AddObject( pDesign, Module21, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &FaninD1, NULL ); Ndr_AddObject( pDesign, Module21, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &FaninD0, NULL ); Ndr_AddObject( pDesign, Module21, ABC_OPER_BIT_MUX, 0, 3, 0, 0, 3, Fanins1, 1, &FaninOut, NULL ); Ndr_AddObject( pDesign, Module21, ABC_OPER_CO, 0, 3, 0, 0, 1, &FaninOut, 0, NULL, NULL ); Module41 = Ndr_AddModule( pDesign, 2 ); Ndr_AddObject( pDesign, Module41, ABC_OPER_CI, 0, 1, 0, 0, 0, NULL, 1, &FaninSel, NULL ); Ndr_AddObject( pDesign, Module41, ABC_OPER_CI, 0, 15,0, 0, 0, NULL, 1, &FaninD, NULL ); Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 3, 0, 0, 1, &FaninD, 1, &FaninD0, NULL ); Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 7, 4, 0, 1, &FaninD, 1, &FaninD1, NULL ); Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 11,8, 0, 1, &FaninD, 1, &FaninD2, NULL ); Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 15,12,0, 1, &FaninD, 1, &FaninD3, NULL ); Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 0, 0, 0, 1, &FaninSel, 1, &FaninSel0, NULL ); Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 1, 1, 0, 1, &FaninSel, 1, &FaninSel1, NULL ); Ndr_AddObject( pDesign, Module41, Module21, 14, 3, 0, 0, 3, Fanins3[0], 1, &FaninT0, NULL ); Ndr_AddObject( pDesign, Module41, Module21, 15, 3, 0, 0, 3, Fanins3[1], 1, &FaninT1, NULL ); Ndr_AddObject( pDesign, Module41, Module21, 16, 3, 0, 0, 3, Fanins3[2], 1, &FaninOut, NULL ); 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, 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 //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/aig/saig/000077500000000000000000000000001477524141600144525ustar00rootroot00000000000000abc-0.52/src/aig/saig/module.make000066400000000000000000000014541477524141600166020ustar00rootroot00000000000000SRC += src/aig/saig/saigCone.c \ src/aig/saig/saigConstr.c \ src/aig/saig/saigConstr2.c \ src/aig/saig/saigDual.c \ src/aig/saig/saigDup.c \ src/aig/saig/saigInd.c \ src/aig/saig/saigIoa.c \ src/aig/saig/saigIso.c \ src/aig/saig/saigIsoFast.c \ src/aig/saig/saigIsoSlow.c \ src/aig/saig/saigMiter.c \ src/aig/saig/saigOutDec.c \ src/aig/saig/saigPhase.c \ src/aig/saig/saigRetFwd.c \ src/aig/saig/saigRetMin.c \ src/aig/saig/saigRetStep.c \ src/aig/saig/saigScl.c \ src/aig/saig/saigSimFast.c \ src/aig/saig/saigSimMv.c \ src/aig/saig/saigSimSeq.c \ src/aig/saig/saigStrSim.c \ src/aig/saig/saigSwitch.c \ src/aig/saig/saigSynch.c \ src/aig/saig/saigTempor.c \ src/aig/saig/saigTrans.c \ src/aig/saig/saigWnd.c abc-0.52/src/aig/saig/saig.h000066400000000000000000000320571477524141600155550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saig.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saig.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__aig__saig__saig_h #define ABC__aig__saig__saig_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include "aig/aig/aig.h" ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Sec_MtrStatus_t_ Sec_MtrStatus_t; struct Sec_MtrStatus_t_ { int nInputs; // the total number of inputs int nNodes; // the total number of nodes int nOutputs; // the total number of outputs int nUnsat; // the number of UNSAT outputs int nSat; // the number of SAT outputs int nUndec; // the number of undecided outputs int iOut; // the satisfied output }; typedef struct Saig_ParBbr_t_ Saig_ParBbr_t; struct Saig_ParBbr_t_ { int TimeLimit; int nBddMax; int nIterMax; int fPartition; int fReorder; int fReorderImage; int fVerbose; int fSilent; int fSkipOutCheck;// skip output checking int iFrame; // explored up to this frame }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// static inline int Saig_ManPiNum( Aig_Man_t * p ) { return p->nTruePis; } static inline int Saig_ManPoNum( Aig_Man_t * p ) { return p->nTruePos; } static inline int Saig_ManCiNum( Aig_Man_t * p ) { return p->nTruePis + p->nRegs; } static inline int Saig_ManCoNum( Aig_Man_t * p ) { return p->nTruePos + p->nRegs; } static inline int Saig_ManRegNum( Aig_Man_t * p ) { return p->nRegs; } static inline int Saig_ManConstrNum( Aig_Man_t * p ) { return p->nConstrs; } static inline Aig_Obj_t * Saig_ManLo( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vCis, Saig_ManPiNum(p)+i); } static inline Aig_Obj_t * Saig_ManLi( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vCos, Saig_ManPoNum(p)+i); } static inline int Saig_ObjIsPi( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjIsCi(pObj) && Aig_ObjCioId(pObj) < Saig_ManPiNum(p); } static inline int Saig_ObjIsPo( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjIsCo(pObj) && Aig_ObjCioId(pObj) < Saig_ManPoNum(p); } static inline int Saig_ObjIsLo( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjIsCi(pObj) && Aig_ObjCioId(pObj) >= Saig_ManPiNum(p); } static inline int Saig_ObjIsLi( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjIsCo(pObj) && Aig_ObjCioId(pObj) >= Saig_ManPoNum(p); } static inline Aig_Obj_t * Saig_ObjLoToLi( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert(Saig_ObjIsLo(p, pObj)); return (Aig_Obj_t *)Vec_PtrEntry(p->vCos, Saig_ManPoNum(p)+Aig_ObjCioId(pObj)-Saig_ManPiNum(p)); } static inline Aig_Obj_t * Saig_ObjLiToLo( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert(Saig_ObjIsLi(p, pObj)); return (Aig_Obj_t *)Vec_PtrEntry(p->vCis, Saig_ManPiNum(p)+Aig_ObjCioId(pObj)-Saig_ManPoNum(p)); } static inline int Saig_ObjRegId( Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( Saig_ObjIsLo(p, pObj) ) return Aig_ObjCioId(pObj)-Saig_ManPiNum(p); if ( Saig_ObjIsLi(p, pObj) ) return Aig_ObjCioId(pObj)-Saig_ManPoNum(p); else assert(0); return -1; } // iterator over the primary inputs/outputs #define Saig_ManForEachPi( p, pObj, i ) \ Vec_PtrForEachEntryStop( Aig_Obj_t *, p->vCis, pObj, i, Saig_ManPiNum(p) ) #define Saig_ManForEachPo( p, pObj, i ) \ Vec_PtrForEachEntryStop( Aig_Obj_t *, p->vCos, pObj, i, Saig_ManPoNum(p) ) // iterator over the latch inputs/outputs #define Saig_ManForEachLo( p, pObj, i ) \ for ( i = 0; (i < Saig_ManRegNum(p)) && (((pObj) = (Aig_Obj_t *)Vec_PtrEntry(p->vCis, i+Saig_ManPiNum(p))), 1); i++ ) #define Saig_ManForEachLi( p, pObj, i ) \ for ( i = 0; (i < Saig_ManRegNum(p)) && (((pObj) = (Aig_Obj_t *)Vec_PtrEntry(p->vCos, i+Saig_ManPoNum(p))), 1); i++ ) // iterator over the latch input and outputs #define Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) \ for ( i = 0; (i < Saig_ManRegNum(p)) && (((pObjLi) = Saig_ManLi(p, i)), 1) \ && (((pObjLo)=Saig_ManLo(p, i)), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== saigCone.c ==========================================================*/ extern void Saig_ManPrintCones( Aig_Man_t * p ); /*=== saigConstr.c ==========================================================*/ extern Aig_Man_t * Saig_ManDupUnfoldConstrs( Aig_Man_t * pAig ); extern Aig_Man_t * Saig_ManDupFoldConstrs( Aig_Man_t * pAig, Vec_Int_t * vConstrs ); extern int Saig_ManDetectConstrTest( Aig_Man_t * p ); extern void Saig_ManDetectConstrFuncTest( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose ); /*=== saigConstr2.c ==========================================================*/ extern Aig_Man_t * Saig_ManDupFoldConstrsFunc( Aig_Man_t * pAig, int fCompl, int fVerbose, int fSeqCleanup ); extern Aig_Man_t * Saig_ManDupUnfoldConstrsFunc( Aig_Man_t * pAig, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose ); // -- jlong -- begin extern Aig_Man_t * Saig_ManDupFoldConstrsFunc2( Aig_Man_t * pAig, int fCompl, int fVerbose, int typeII_cnt ); extern Aig_Man_t * Saig_ManDupUnfoldConstrsFunc2( Aig_Man_t * pAig, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose , int * typeII_cnt); // --jlong -- end /*=== saigDual.c ==========================================================*/ extern Aig_Man_t * Saig_ManDupDual( Aig_Man_t * pAig, Vec_Int_t * vDcFlops, int nDualPis, int fDualFfs, int fMiterFfs, int fComplPo, int fCheckZero, int fCheckOne ); extern void Saig_ManBlockPo( Aig_Man_t * pAig, int nCycles ); /*=== saigDup.c ==========================================================*/ extern Aig_Man_t * Saig_ManDupOrpos( Aig_Man_t * p ); extern Aig_Man_t * Saig_ManCreateEquivMiter( Aig_Man_t * pAig, Vec_Int_t * vPairs, int fAddOuts ); extern Aig_Man_t * Saig_ManDupAbstraction( Aig_Man_t * pAig, Vec_Int_t * vFlops ); extern int Saig_ManVerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p ); extern Abc_Cex_t * Saig_ManExtendCex( Aig_Man_t * pAig, Abc_Cex_t * p ); extern int Saig_ManFindFailedPoCex( Aig_Man_t * pAig, Abc_Cex_t * p ); extern Aig_Man_t * Saig_ManDupWithPhase( Aig_Man_t * pAig, Vec_Int_t * vInit ); extern Aig_Man_t * Saig_ManDupCones( Aig_Man_t * pAig, int * pPos, int nPos ); /*=== saigHaig.c ==========================================================*/ extern Aig_Man_t * Saig_ManHaigRecord( Aig_Man_t * p, int nIters, int nSteps, int fRetimingOnly, int fAddBugs, int fUseCnf, int fVerbose ); /*=== saigInd.c ==========================================================*/ extern int Saig_ManInduction( Aig_Man_t * p, int nTimeOut, int nFramesMax, int nConfMax, int fUnique, int fUniqueAll, int fGetCex, int fVerbose, int fVeryVerbose ); /*=== saigIoa.c ==========================================================*/ extern void Saig_ManDumpBlif( Aig_Man_t * p, char * pFileName ); extern Aig_Man_t * Saig_ManReadBlif( char * pFileName ); /*=== saigIso.c ==========================================================*/ extern Vec_Int_t * Saig_ManFindIsoPerm( Aig_Man_t * pAig, int fVerbose ); extern Aig_Man_t * Saig_ManDupIsoCanonical( Aig_Man_t * pAig, int fVerbose ); extern Aig_Man_t * Saig_ManIsoReduce( Aig_Man_t * pAig, Vec_Ptr_t ** pvCosEquivs, int fVerbose ); /*=== saigIsoFast.c ==========================================================*/ extern Vec_Vec_t * Saig_IsoDetectFast( Aig_Man_t * pAig ); /*=== saigMiter.c ==========================================================*/ extern Sec_MtrStatus_t Sec_MiterStatus( Aig_Man_t * p ); extern Aig_Man_t * Saig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int Oper ); extern Aig_Man_t * Saig_ManCreateMiterComb( Aig_Man_t * p1, Aig_Man_t * p2, int Oper ); extern Aig_Man_t * Saig_ManDualRail( Aig_Man_t * p, int fMiter ); extern Aig_Man_t * Saig_ManCreateMiterTwo( Aig_Man_t * pOld, Aig_Man_t * pNew, int nFrames ); extern int Saig_ManDemiterSimple( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ); extern int Saig_ManDemiterSimpleDiff( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ); extern int Saig_ManDemiterDual( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ); extern int Ssw_SecSpecialMiter( Aig_Man_t * p0, Aig_Man_t * p1, int nFrames, int fVerbose ); extern int Saig_ManDemiterNew( Aig_Man_t * pMan ); /*=== saigOutdec.c ==========================================================*/ extern Aig_Man_t * Saig_ManDecPropertyOutput( Aig_Man_t * pAig, int nLits, int fVerbose ); /*=== saigPhase.c ==========================================================*/ extern Aig_Man_t * Saig_ManPhaseAbstract( Aig_Man_t * p, Vec_Int_t * vInits, int nFrames, int nPref, int fIgnore, int fPrint, int fVerbose ); /*=== saigRetFwd.c ==========================================================*/ extern void Saig_ManMarkAutonomous( Aig_Man_t * p ); extern Aig_Man_t * Saig_ManRetimeForward( Aig_Man_t * p, int nMaxIters, int fVerbose ); /*=== saigRetMin.c ==========================================================*/ extern Aig_Man_t * Saig_ManRetimeDupForward( Aig_Man_t * p, Vec_Ptr_t * vCut ); extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ); /*=== saigRetStep.c ==========================================================*/ extern int Saig_ManRetimeSteps( Aig_Man_t * p, int nSteps, int fForward, int fAddBugs ); /*=== saigScl.c ==========================================================*/ extern void Saig_ManReportUselessRegisters( Aig_Man_t * pAig ); /*=== saigSimMv.c ==========================================================*/ extern Vec_Ptr_t * Saig_MvManSimulate( Aig_Man_t * pAig, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose ); /*=== saigStrSim.c ==========================================================*/ extern Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter ); /*=== saigSwitch.c ==========================================================*/ extern Vec_Int_t * Saig_ManComputeSwitchProb2s( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); /*=== saigSynch.c ==========================================================*/ extern Aig_Man_t * Saig_ManDupInitZero( Aig_Man_t * p ); /*=== saigTrans.c ==========================================================*/ extern Aig_Man_t * Saig_ManTimeframeSimplify( Aig_Man_t * pAig, int nFrames, int nFramesMax, int fInit, int fVerbose ); /*=== saigWnd.c ==========================================================*/ extern Aig_Man_t * Saig_ManWindowExtract( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist ); extern Aig_Man_t * Saig_ManWindowInsert( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist, Aig_Man_t * pWnd ); extern Aig_Obj_t * Saig_ManFindPivot( Aig_Man_t * p ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/aig/saig/saigCone.c000066400000000000000000000127661477524141600163620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigCone.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Cone of influence computation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigCone.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Counts the support size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManSupport_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); if ( Aig_ObjIsConst1(pObj) ) return; if ( Aig_ObjIsCi(pObj) ) { if ( Saig_ObjIsLo(p,pObj) ) { pObj = Saig_ManLi( p, Aig_ObjCioId(pObj)-Saig_ManPiNum(p) ); Vec_PtrPush( vSupp, pObj ); } return; } assert( Aig_ObjIsNode(pObj) ); Saig_ManSupport_rec( p, Aig_ObjFanin0(pObj), vSupp ); Saig_ManSupport_rec( p, Aig_ObjFanin1(pObj), vSupp ); } /**Function************************************************************* Synopsis [Counts the support size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Saig_ManSupport( Aig_Man_t * p, Vec_Ptr_t * vNodes ) { Vec_Ptr_t * vSupp; Aig_Obj_t * pObj; int i; vSupp = Vec_PtrAlloc( 100 ); Aig_ManIncrementTravId( p ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { assert( Aig_ObjIsCo(pObj) ); Saig_ManSupport_rec( p, Aig_ObjFanin0(pObj), vSupp ); } return vSupp; } /**Function************************************************************* Synopsis [Prints information about cones of influence of the POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManPrintConeOne( Aig_Man_t * p, Aig_Obj_t * pObj ) { Vec_Ptr_t * vPrev, * vCur, * vTotal; int s, i, nCurNew, nCurPrev, nCurOld; assert( Saig_ObjIsPo(p, pObj) ); // start the array vPrev = Vec_PtrAlloc( 100 ); Vec_PtrPush( vPrev, pObj ); // get the current support vCur = Saig_ManSupport( p, vPrev ); Vec_PtrClear( vPrev ); printf( " PO %3d ", Aig_ObjCioId(pObj) ); // continue computing supports as long as there are now nodes vTotal = Vec_PtrAlloc( 100 ); for ( s = 0; ; s++ ) { // classify current into those new, prev, and older nCurNew = nCurPrev = nCurOld = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vCur, pObj, i ) { if ( Vec_PtrFind(vTotal, pObj) == -1 ) { Vec_PtrPush( vTotal, pObj ); nCurNew++; } else if ( Vec_PtrFind(vPrev, pObj) >= 0 ) nCurPrev++; else nCurOld++; } assert( nCurNew + nCurPrev + nCurOld == Vec_PtrSize(vCur) ); // print the result printf( "%d:%d %d=%d+%d+%d ", s, Vec_PtrSize(vTotal), Vec_PtrSize(vCur), nCurNew, nCurPrev, nCurOld ); if ( nCurNew == 0 ) break; // compute one more step Vec_PtrFree( vPrev ); vCur = Saig_ManSupport( p, vPrev = vCur ); } printf( "\n" ); Vec_PtrFree( vPrev ); Vec_PtrFree( vCur ); Vec_PtrFree( vTotal ); } /**Function************************************************************* Synopsis [Prints information about cones of influence of the POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManPrintCones( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; printf( "The format of this print-out: For each PO, x:a b=c+d+e, where \n" ); printf( "- x is the time-frame counting back from the PO\n" ); printf( "- a is the total number of registers in the COI of the PO so far\n" ); printf( "- b is the number of registers in the COI of the PO in this time-frame\n" ); printf( "- c is the number of registers in b that are new (appear for the first time)\n" ); printf( "- d is the number of registers in b in common with the previous time-frame\n" ); printf( "- e is the number of registers in b in common with other time-frames\n" ); Aig_ManSetCioIds( p ); Saig_ManForEachPo( p, pObj, i ) Saig_ManPrintConeOne( p, pObj ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigConstr.c000066400000000000000000000362611477524141600167420ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigConstr.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Structural constraint detection.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigConstr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" #include "bool/kit/kit.h" #include "aig/ioa/ioa.h" ABC_NAMESPACE_IMPL_START /* Property holds iff it is const 0. Constraint holds iff it is const 0. The following structure is used for folding constraints: - the output of OR gate is 0 as long as all constraints hold - as soon as one constraint fail, the property output becomes 0 forever because the flop becomes 1 and it stays 1 forever property output | |-----| | and | |-----| | | | / \ | /inv\ | ----- ____| |_________________________ | | | / \ ----------- | / \ | or | | / \ ----------- | / logic \ | | | | / cone \ | | | | /___________\ | | | | | | ------ | | | |flop| (init=0) | | | ------ | | | | | | | |______________| | | c1 c2 */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_DetectConstrCollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) { // if the new node is complemented or a PI, another gate begins if ( Aig_IsComplement(pObj) || !Aig_ObjIsNode(pObj) )//|| (Aig_ObjRefs(pObj) > 1) ) { Vec_PtrPushUnique( vSuper, Aig_Not(pObj) ); return; } // go through the branches Saig_DetectConstrCollectSuper_rec( Aig_ObjChild0(pObj), vSuper ); Saig_DetectConstrCollectSuper_rec( Aig_ObjChild1(pObj), vSuper ); } /**Function************************************************************* Synopsis [Collects the supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Saig_DetectConstrCollectSuper( Aig_Obj_t * pObj ) { Vec_Ptr_t * vSuper; assert( !Aig_IsComplement(pObj) ); assert( Aig_ObjIsAnd(pObj) ); vSuper = Vec_PtrAlloc( 4 ); Saig_DetectConstrCollectSuper_rec( Aig_ObjChild0(pObj), vSuper ); Saig_DetectConstrCollectSuper_rec( Aig_ObjChild1(pObj), vSuper ); return vSuper; } /**Function************************************************************* Synopsis [Returns NULL if not contained, or array with unique entries.] Description [Returns NULL if vSuper2 is not contained in vSuper. Otherwise returns the array of entries in vSuper that are not found in vSuper2.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Saig_ManDetectConstrCheckCont( Vec_Ptr_t * vSuper, Vec_Ptr_t * vSuper2 ) { Vec_Ptr_t * vUnique; Aig_Obj_t * pObj, * pObj2; int i; Vec_PtrForEachEntry( Aig_Obj_t *, vSuper2, pObj2, i ) if ( Vec_PtrFind( vSuper, pObj2 ) == -1 ) return 0; vUnique = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i ) if ( Vec_PtrFind( vSuper2, pObj ) == -1 ) Vec_PtrPush( vUnique, pObj ); return vUnique; } /**Function************************************************************* Synopsis [Detects constraints using structural methods.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManDetectConstr( Aig_Man_t * p, int iOut, Vec_Ptr_t ** pvOuts, Vec_Ptr_t ** pvCons ) { Vec_Ptr_t * vSuper, * vSuper2 = NULL, * vUnique; Aig_Obj_t * pObj, * pObj2, * pFlop; int i, nFlops, RetValue; assert( iOut >= 0 && iOut < Saig_ManPoNum(p) ); *pvOuts = NULL; *pvCons = NULL; pObj = Aig_ObjChild0( Aig_ManCo(p, iOut) ); if ( pObj == Aig_ManConst0(p) ) { vUnique = Vec_PtrStart( 1 ); Vec_PtrWriteEntry( vUnique, 0, Aig_ManConst1(p) ); *pvOuts = vUnique; *pvCons = Vec_PtrAlloc( 0 ); return -1; } if ( Aig_IsComplement(pObj) || !Aig_ObjIsNode(pObj) ) { printf( "The output is not an AND.\n" ); return 0; } vSuper = Saig_DetectConstrCollectSuper( pObj ); assert( Vec_PtrSize(vSuper) >= 2 ); nFlops = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i ) nFlops += Saig_ObjIsLo( p, Aig_Regular(pObj) ); if ( nFlops == 0 ) { printf( "There is no flop outputs.\n" ); Vec_PtrFree( vSuper ); return 0; } // try flops vUnique = NULL; Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i ) { pFlop = Aig_Regular( pObj ); if ( !Saig_ObjIsLo(p, pFlop) ) continue; pFlop = Saig_ObjLoToLi( p, pFlop ); pObj2 = Aig_ObjChild0( pFlop ); if ( !Aig_IsComplement(pObj2) || !Aig_ObjIsNode(Aig_Regular(pObj2)) ) continue; vSuper2 = Saig_DetectConstrCollectSuper( Aig_Regular(pObj2) ); // every node in vSuper2 should appear in vSuper vUnique = Saig_ManDetectConstrCheckCont( vSuper, vSuper2 ); if ( vUnique != NULL ) { /// assert( !Aig_IsComplement(pObj) ); // assert( Vec_PtrFind( vSuper2, pObj ) >= 0 ); if ( Aig_IsComplement(pObj) ) { printf( "Special flop input is complemented.\n" ); Vec_PtrFreeP( &vUnique ); Vec_PtrFree( vSuper2 ); break; } if ( Vec_PtrFind( vSuper2, pObj ) == -1 ) { printf( "Cannot find special flop about the inputs of OR gate.\n" ); Vec_PtrFreeP( &vUnique ); Vec_PtrFree( vSuper2 ); break; } // remove the flop output Vec_PtrRemove( vSuper2, pObj ); break; } Vec_PtrFree( vSuper2 ); } Vec_PtrFree( vSuper ); if ( vUnique == NULL ) { printf( "There is no structural constraints.\n" ); return 0; } // vUnique contains unique entries // vSuper2 contains the supergate printf( "Output %d : Structural analysis found %d original properties and %d constraints.\n", iOut, Vec_PtrSize(vUnique), Vec_PtrSize(vSuper2) ); // remember the number of constraints RetValue = Vec_PtrSize(vSuper2); // make the AND of properties // Vec_PtrFree( vUnique ); // Vec_PtrFree( vSuper2 ); *pvOuts = vUnique; *pvCons = vSuper2; return RetValue; } /**Function************************************************************* Synopsis [Procedure used for sorting nodes by ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManDupCompare( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ) { int Diff = Aig_ObjToLit(*pp1) - Aig_ObjToLit(*pp2); if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; return 0; } /**Function************************************************************* Synopsis [Duplicates the AIG while unfolding constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDupUnfoldConstrs( Aig_Man_t * pAig ) { Vec_Ptr_t * vOutsAll, * vConsAll; Vec_Ptr_t * vOuts, * vCons, * vCons0; Aig_Man_t * pAigNew; Aig_Obj_t * pMiter, * pObj; int i, k, RetValue; // detect constraints for each output vOutsAll = Vec_PtrAlloc( Saig_ManPoNum(pAig) ); vConsAll = Vec_PtrAlloc( Saig_ManPoNum(pAig) ); Saig_ManForEachPo( pAig, pObj, i ) { RetValue = Saig_ManDetectConstr( pAig, i, &vOuts, &vCons ); if ( RetValue == 0 ) { Vec_PtrFreeP( &vOuts ); Vec_PtrFreeP( &vCons ); Vec_VecFree( (Vec_Vec_t *)vOutsAll ); Vec_VecFree( (Vec_Vec_t *)vConsAll ); return Aig_ManDupDfs( pAig ); } 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 ); } // check if constraints are compatible vCons0 = (Vec_Ptr_t *)Vec_PtrEntry( vConsAll, 0 ); Vec_PtrForEachEntry( Vec_Ptr_t *, vConsAll, vCons, i ) if ( Vec_PtrSize(vCons) ) vCons0 = vCons; Vec_PtrForEachEntry( Vec_Ptr_t *, vConsAll, vCons, i ) { // Constant 0 outputs are always compatible (vOuts stores the negation) vOuts = (Vec_Ptr_t *)Vec_PtrEntry( vOutsAll, i ); if ( Vec_PtrSize(vOuts) == 1 && (Aig_Obj_t *)Vec_PtrEntry( vOuts, 0 ) == Aig_ManConst1(pAig) ) continue; if ( !Vec_PtrEqual(vCons0, vCons) ) break; } if ( i < Vec_PtrSize(vConsAll) ) { printf( "Collected constraints are not compatible.\n" ); Vec_VecFree( (Vec_Vec_t *)vOutsAll ); Vec_VecFree( (Vec_Vec_t *)vConsAll ); return Aig_ManDupDfs( pAig ); } // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); pAigNew->pName = Abc_UtilStrsav( pAig->pName ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create variables for PIs Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( pAigNew ); // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // transform each output Vec_PtrForEachEntry( Vec_Ptr_t *, vOutsAll, vOuts, i ) { // AND the outputs pMiter = Aig_ManConst1( pAigNew ); Vec_PtrForEachEntry( Aig_Obj_t *, vOuts, pObj, k ) pMiter = Aig_And( pAigNew, pMiter, Aig_Not(Aig_ObjRealCopy(pObj)) ); Aig_ObjCreateCo( pAigNew, pMiter ); } // add constraints pAigNew->nConstrs = Vec_PtrSize(vCons0); Vec_PtrForEachEntry( Aig_Obj_t *, vCons0, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_ObjRealCopy(pObj) ); // transfer to register outputs Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); // Vec_PtrFreeP( &vOuts ); // Vec_PtrFreeP( &vCons ); Vec_VecFree( (Vec_Vec_t *)vOutsAll ); Vec_VecFree( (Vec_Vec_t *)vConsAll ); Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) ); Aig_ManCleanup( pAigNew ); Aig_ManSeqCleanup( pAigNew ); return pAigNew; } /**Function************************************************************* Synopsis [Duplicates the AIG while folding in the constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDupFoldConstrs( Aig_Man_t * pAig, Vec_Int_t * vConstrs ) { Aig_Man_t * pAigNew; Aig_Obj_t * pMiter, * pFlopOut, * pFlopIn, * pObj; int Entry, i; assert( Saig_ManRegNum(pAig) > 0 ); // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); pAigNew->pName = Abc_UtilStrsav( pAig->pName ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create variables for PIs Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( pAigNew ); // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // OR the constraint outputs pMiter = Aig_ManConst0( pAigNew ); Vec_IntForEachEntry( vConstrs, Entry, i ) { assert( Entry > 0 && Entry < Saig_ManPoNum(pAig) ); pObj = Aig_ManCo( pAig, Entry ); pMiter = Aig_Or( pAigNew, pMiter, Aig_ObjChild0Copy(pObj) ); } // create additional flop pFlopOut = Aig_ObjCreateCi( pAigNew ); pFlopIn = Aig_Or( pAigNew, pMiter, pFlopOut ); // create primary output Saig_ManForEachPo( pAig, pObj, i ) { pMiter = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_Not(pFlopIn) ); Aig_ObjCreateCo( pAigNew, pMiter ); } // transfer to register outputs Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); // create additional flop Aig_ObjCreateCo( pAigNew, pFlopIn ); Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig)+1 ); Aig_ManCleanup( pAigNew ); Aig_ManSeqCleanup( pAigNew ); return pAigNew; } /**Function************************************************************* Synopsis [Tests the above two procedures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManFoldConstrTest( Aig_Man_t * pAig ) { Aig_Man_t * pAig1, * pAig2; Vec_Int_t * vConstrs; // unfold constraints pAig1 = Saig_ManDupUnfoldConstrs( pAig ); // create the constraint list vConstrs = Vec_IntStartNatural( Saig_ManPoNum(pAig1) ); Vec_IntRemove( vConstrs, 0 ); // fold constraints back pAig2 = Saig_ManDupFoldConstrs( pAig1, vConstrs ); Vec_IntFree( vConstrs ); // compare the two AIGs Ioa_WriteAiger( pAig2, "test.aig", 0, 0 ); Aig_ManStop( pAig1 ); Aig_ManStop( pAig2 ); } /**Function************************************************************* Synopsis [Experiment with the above procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManDetectConstrTest( Aig_Man_t * p ) { Vec_Ptr_t * vOuts, * vCons; int RetValue = Saig_ManDetectConstr( p, 0, &vOuts, &vCons ); Vec_PtrFreeP( &vOuts ); Vec_PtrFreeP( &vCons ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigConstr2.c000066400000000000000000001060171477524141600170210ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigConstr2.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Functional constraint detection.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigConstr2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" #include "bool/kit/kit.h" #include "misc/bar/bar.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline Aig_Obj_t * Aig_ObjFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return pObjMap[nFs*pObj->Id + i]; } static inline void Aig_ObjSetFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { pObjMap[nFs*pObj->Id + i] = pNode; } static inline Aig_Obj_t * Aig_ObjChild0Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin0(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } static inline Aig_Obj_t * Aig_ObjChild1Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin1(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the probability of POs being 1 under rand seq sim.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_ManProfileConstraints( Aig_Man_t * p, int nWords, int nFrames, int fVerbose ) { Vec_Ptr_t * vInfo; Vec_Int_t * vProbs, * vProbs2; Aig_Obj_t * pObj, * pObjLi; unsigned * pInfo, * pInfo0, * pInfo1, * pInfoMask, * pInfoMask2; int i, w, f, RetValue = 1; abctime clk = Abc_Clock(); if ( fVerbose ) printf( "Simulating %d nodes and %d flops for %d frames with %d words... ", Aig_ManNodeNum(p), Aig_ManRegNum(p), nFrames, nWords ); Aig_ManRandom( 1 ); vInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p)+2, nWords ); Vec_PtrCleanSimInfo( vInfo, 0, nWords ); vProbs = Vec_IntStart( Saig_ManPoNum(p) ); vProbs2 = Vec_IntStart( Saig_ManPoNum(p) ); // start the constant pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(Aig_ManConst1(p)) ); for ( w = 0; w < nWords; w++ ) pInfo[w] = ~0; // start the flop inputs Saig_ManForEachLi( p, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); for ( w = 0; w < nWords; w++ ) pInfo[w] = 0; } // get the info mask pInfoMask = (unsigned *)Vec_PtrEntry( vInfo, Aig_ManObjNumMax(p) ); // PO failed pInfoMask2 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ManObjNumMax(p)+1 ); // constr failed for ( f = 0; f < nFrames; f++ ) { // assign primary inputs Saig_ManForEachPi( p, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); for ( w = 0; w < nWords; w++ ) pInfo[w] = Aig_ManRandom( 0 ); } // move the flop values Saig_ManForEachLiLo( p, pObjLi, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObjLi) ); for ( w = 0; w < nWords; w++ ) pInfo[w] = pInfo0[w]; } // simulate the nodes Aig_ManForEachNode( p, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjFaninId0(pObj) ); pInfo1 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjFaninId1(pObj) ); if ( Aig_ObjFaninC0(pObj) ) { if ( Aig_ObjFaninC1(pObj) ) for ( w = 0; w < nWords; w++ ) pInfo[w] = ~(pInfo0[w] | pInfo1[w]); else for ( w = 0; w < nWords; w++ ) pInfo[w] = ~pInfo0[w] & pInfo1[w]; } else { if ( Aig_ObjFaninC1(pObj) ) for ( w = 0; w < nWords; w++ ) pInfo[w] = pInfo0[w] & ~pInfo1[w]; else for ( w = 0; w < nWords; w++ ) pInfo[w] = pInfo0[w] & pInfo1[w]; } } // clean the mask for ( w = 0; w < nWords; w++ ) pInfoMask[w] = pInfoMask2[w] = 0; // simulate the primary outputs Aig_ManForEachCo( p, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjFaninId0(pObj) ); if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) || i >= Saig_ManPoNum(p) ) { if ( Aig_ObjFaninC0(pObj) ) { for ( w = 0; w < nWords; w++ ) pInfo[w] = ~pInfo0[w]; } else { for ( w = 0; w < nWords; w++ ) pInfo[w] = pInfo0[w]; } } else { if ( Aig_ObjFaninC0(pObj) ) { for ( w = 0; w < nWords; w++ ) pInfo[w] |= ~pInfo0[w]; } else { for ( w = 0; w < nWords; w++ ) pInfo[w] |= pInfo0[w]; } } // collect patterns when one of the outputs fails if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) ) { for ( w = 0; w < nWords; w++ ) pInfoMask[w] |= pInfo[w]; } else if ( i < Saig_ManPoNum(p) ) { for ( w = 0; w < nWords; w++ ) pInfoMask2[w] |= pInfo[w]; } } // compare the PO values (mask=1 => out=0) or UNSAT(mask=1 & out=1) Saig_ManForEachPo( p, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); for ( w = 0; w < nWords; w++ ) Vec_IntAddToEntry( vProbs, i, Aig_WordCountOnes(pInfo[w]) ); if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) ) { // chek the output for ( w = 0; w < nWords; w++ ) if ( pInfo[w] & ~pInfoMask2[w] ) break; if ( w == nWords ) continue; printf( "Primary output %d fails on some input patterns.\n", i ); } else { // collect patterns that block the POs for ( w = 0; w < nWords; w++ ) Vec_IntAddToEntry( vProbs2, i, Aig_WordCountOnes(pInfo[w] & pInfoMask[w]) ); } } } if ( fVerbose ) Abc_PrintTime( 1, "T", Abc_Clock() - clk ); // print the state if ( fVerbose ) { Saig_ManForEachPo( p, pObj, i ) { if ( i < Saig_ManPoNum(p) - Saig_ManConstrNum(p) ) printf( "Primary output : " ); else printf( "Constraint %3d : ", i-(Saig_ManPoNum(p) - Saig_ManConstrNum(p)) ); printf( "ProbOne = %f ", (float)Vec_IntEntry(vProbs, i)/(32*nWords*nFrames) ); printf( "ProbOneC = %f ", (float)Vec_IntEntry(vProbs2, i)/(32*nWords*nFrames) ); printf( "AllZeroValue = %d ", Aig_ObjPhase(pObj) ); printf( "\n" ); } } // print the states Vec_PtrFree( vInfo ); Vec_IntFree( vProbs ); Vec_IntFree( vProbs2 ); return RetValue; } /**Function************************************************************* Synopsis [Creates COI of the property output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManCreateIndMiter( Aig_Man_t * pAig, Vec_Vec_t * vCands ) { int nFrames = 2; Vec_Ptr_t * vNodes; Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; Aig_Obj_t ** pObjMap; int i, f, k; // create mapping for the frames nodes pObjMap = ABC_CALLOC( Aig_Obj_t *, nFrames * Aig_ManObjNumMax(pAig) ); // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); pFrames->pName = Abc_UtilStrsav( pAig->pName ); pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); // map constant nodes for ( f = 0; f < nFrames; f++ ) Aig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); // create PI nodes for the frames for ( f = 0; f < nFrames; f++ ) Aig_ManForEachPiSeq( pAig, pObj, i ) Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, Aig_ObjCreateCi(pFrames) ); // set initial state for the latches Aig_ManForEachLoSeq( pAig, pObj, i ) Aig_ObjSetFrames( pObjMap, nFrames, pObj, 0, Aig_ObjCreateCi(pFrames) ); // add timeframes for ( f = 0; f < nFrames; f++ ) { // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) { pObjNew = Aig_And( pFrames, Aig_ObjChild0Frames(pObjMap,nFrames,pObj,f), Aig_ObjChild1Frames(pObjMap,nFrames,pObj,f) ); Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); } // set the latch inputs and copy them into the latch outputs of the next frame Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i ) { pObjNew = Aig_ObjChild0Frames(pObjMap,nFrames,pObjLi,f); if ( f < nFrames - 1 ) Aig_ObjSetFrames( pObjMap, nFrames, pObjLo, f+1, pObjNew ); } } // go through the candidates Vec_VecForEachLevel( vCands, vNodes, i ) { Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) { Aig_Obj_t * pObjR = Aig_Regular(pObj); Aig_Obj_t * pNode0 = pObjMap[nFrames*Aig_ObjId(pObjR)+0]; Aig_Obj_t * pNode1 = pObjMap[nFrames*Aig_ObjId(pObjR)+1]; Aig_Obj_t * pFan0 = Aig_NotCond( pNode0, Aig_IsComplement(pObj) ); Aig_Obj_t * pFan1 = Aig_NotCond( pNode1, !Aig_IsComplement(pObj) ); Aig_Obj_t * pMiter = Aig_And( pFrames, pFan0, pFan1 ); Aig_ObjCreateCo( pFrames, pMiter ); } } Aig_ManCleanup( pFrames ); ABC_FREE( pObjMap ); //Aig_ManShow( pAig, 0, NULL ); //Aig_ManShow( pFrames, 0, NULL ); return pFrames; } /**Function************************************************************* Synopsis [Performs inductive check for one of the constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManFilterUsingIndOne_new( Aig_Man_t * p, Aig_Man_t * pFrame, sat_solver * pSat, Cnf_Dat_t * pCnf, int nConfs, int nProps, int Counter ) { Aig_Obj_t * pObj; int Lit, status; pObj = Aig_ManCo( pFrame, Counter ); Lit = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ); status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfs, 0, 0, 0 ); if ( status == l_False ) return 1; if ( status == l_Undef ) { // printf( "Solver returned undecided.\n" ); return 0; } assert( status == l_True ); return 0; } /**Function************************************************************* Synopsis [Detects constraints functionally.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManFilterUsingInd( Aig_Man_t * p, Vec_Vec_t * vCands, int nConfs, int nProps, int fVerbose ) { Vec_Ptr_t * vNodes; Aig_Man_t * pFrames; sat_solver * pSat; Cnf_Dat_t * pCnf; Aig_Obj_t * pObj; int i, k, k2, Counter; /* Vec_VecForEachLevel( vCands, vNodes, i ) Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) printf( "%d ", Aig_ObjId(Aig_Regular(pObj)) ); printf( "\n" ); */ // create timeframes // pFrames = Saig_ManUnrollInd( p ); pFrames = Saig_ManCreateIndMiter( p, vCands ); assert( Aig_ManCoNum(pFrames) == Vec_VecSizeSize(vCands) ); // start the SAT solver pCnf = Cnf_DeriveSimple( pFrames, Aig_ManCoNum(pFrames) ); pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); // check candidates if ( fVerbose ) printf( "Filtered cands: " ); Counter = 0; Vec_VecForEachLevel( vCands, vNodes, i ) { k2 = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) { if ( Saig_ManFilterUsingIndOne_new( p, pFrames, pSat, pCnf, nConfs, nProps, Counter++ ) ) // if ( Saig_ManFilterUsingIndOne_old( p, pSat, pCnf, nConfs, pObj ) ) { Vec_PtrWriteEntry( vNodes, k2++, pObj ); if ( fVerbose ) printf( "%d:%s%d ", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); } } Vec_PtrShrink( vNodes, k2 ); } if ( fVerbose ) printf( "\n" ); // clean up Cnf_DataFree( pCnf ); sat_solver_delete( pSat ); if ( fVerbose ) Aig_ManPrintStats( pFrames ); Aig_ManStop( pFrames ); } /**Function************************************************************* Synopsis [Creates COI of the property output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManUnrollCOI_( Aig_Man_t * p, int nFrames ) { Aig_Man_t * pFrames; Aig_Obj_t ** pObjMap; int i; //Aig_Man_t * Aig_ManFrames( Aig_Man_t * pAig, int nFrames, int fInit, int fOuts, int fRegs, int fEnlarge, Aig_Obj_t *** ppObjMap ) pFrames = Aig_ManFrames( p, nFrames, 0, 1, 1, 0, &pObjMap ); for ( i = 0; i < nFrames * Aig_ManObjNumMax(p); i++ ) if ( pObjMap[i] && Aig_ObjIsNone( Aig_Regular(pObjMap[i]) ) ) pObjMap[i] = NULL; assert( p->pObjCopies == NULL ); p->pObjCopies = pObjMap; return pFrames; } /**Function************************************************************* Synopsis [Creates COI of the property output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManUnrollCOI( Aig_Man_t * pAig, int nFrames ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; Aig_Obj_t ** pObjMap; int i, f; // create mapping for the frames nodes pObjMap = ABC_CALLOC( Aig_Obj_t *, nFrames * Aig_ManObjNumMax(pAig) ); // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); pFrames->pName = Abc_UtilStrsav( pAig->pName ); pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); // map constant nodes for ( f = 0; f < nFrames; f++ ) Aig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); // create PI nodes for the frames for ( f = 0; f < nFrames; f++ ) Aig_ManForEachPiSeq( pAig, pObj, i ) Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, Aig_ObjCreateCi(pFrames) ); // set initial state for the latches Aig_ManForEachLoSeq( pAig, pObj, i ) Aig_ObjSetFrames( pObjMap, nFrames, pObj, 0, Aig_ObjCreateCi(pFrames) ); // add timeframes for ( f = 0; f < nFrames; f++ ) { Aig_ManForEachNode( pAig, pObj, i ) { pObjNew = Aig_And( pFrames, Aig_ObjChild0Frames(pObjMap,nFrames,pObj,f), Aig_ObjChild1Frames(pObjMap,nFrames,pObj,f) ); Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); } // set the latch inputs and copy them into the latch outputs of the next frame Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i ) { pObjNew = Aig_ObjChild0Frames(pObjMap,nFrames,pObjLi,f); if ( f < nFrames - 1 ) Aig_ObjSetFrames( pObjMap, nFrames, pObjLo, f+1, pObjNew ); } } // create the only output for ( f = nFrames-1; f < nFrames; f++ ) { Aig_ManForEachPoSeq( pAig, pObj, i ) { pObjNew = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Frames(pObjMap,nFrames,pObj,f) ); Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); } } // created lots of dangling nodes - no sweeping! //Aig_ManCleanup( pFrames ); assert( pAig->pObjCopies == NULL ); pAig->pObjCopies = pObjMap; return pFrames; } /**Function************************************************************* Synopsis [Collects and saves values of the SAT variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_CollectSatValues( sat_solver * pSat, Cnf_Dat_t * pCnf, Vec_Ptr_t * vInfo, int * piPat ) { Aig_Obj_t * pObj; unsigned * pInfo; int i; Aig_ManForEachObj( pCnf->pMan, pObj, i ) { if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) continue; assert( pCnf->pVarNums[i] > 0 ); pInfo = (unsigned *)Vec_PtrEntry( vInfo, i ); if ( Abc_InfoHasBit(pInfo, *piPat) != sat_solver_var_value(pSat, pCnf->pVarNums[i]) ) Abc_InfoXorBit(pInfo, *piPat); } } /**Function************************************************************* Synopsis [Runs the SAT test for the node in one polarity.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_DetectTryPolarity( sat_solver * pSat, int nConfs, int nProps, Cnf_Dat_t * pCnf, Aig_Obj_t * pObj, int iPol, Vec_Ptr_t * vInfo, int * piPat, int fVerbose ) { Aig_Obj_t * pOut = Aig_ManCo( pCnf->pMan, 0 ); int status, Lits[2]; // ABC_INT64_T nOldConfs = pSat->stats.conflicts; // ABC_INT64_T nOldImps = pSat->stats.propagations; Lits[0] = toLitCond( pCnf->pVarNums[Aig_ObjId(pOut)], 0 ); Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !iPol ); status = sat_solver_solve( pSat, Lits, Lits + 2, (ABC_INT64_T)nConfs, (ABC_INT64_T)nProps, 0, 0 ); if ( status == l_False ) { // printf( "u%d(%d) ", (int)(pSat->stats.conflicts-nOldConfs), (int)(pSat->stats.propagations-nOldImps) ); return 1; } if ( status == l_Undef ) { // printf( "Solver returned undecided.\n" ); return 0; } // printf( "s%d(%d) ", (int)(pSat->stats.conflicts-nOldConfs), (int)(pSat->stats.propagations-nOldImps) ); assert( status == l_True ); Saig_CollectSatValues( pSat, pCnf, vInfo, piPat ); (*piPat)++; if ( *piPat == Vec_PtrReadWordsSimInfo(vInfo) * 32 ) { if ( fVerbose ) printf( "Warning: Reached the limit on the number of patterns.\n" ); *piPat = 0; } return 0; } /**Function************************************************************* Synopsis [Returns the number of variables implied by the output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Ssw_ManFindDirectImplications( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fVerbose ) { Vec_Vec_t * vCands = NULL; Vec_Ptr_t * vNodes; Cnf_Dat_t * pCnf; sat_solver * pSat; Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pRepr, * pReprR; int i, f, k, value; vCands = Vec_VecAlloc( nFrames ); // perform unrolling pFrames = Saig_ManUnrollCOI( p, nFrames ); assert( Aig_ManCoNum(pFrames) == 1 ); // start the SAT solver pCnf = Cnf_DeriveSimple( pFrames, 0 ); pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); if ( pSat != NULL ) { Aig_ManIncrementTravId( p ); for ( f = 0; f < nFrames; f++ ) { Aig_ManForEachObj( p, pObj, i ) { if ( !Aig_ObjIsCand(pObj) ) continue; if ( Aig_ObjIsTravIdCurrent(p, pObj) ) continue; // get the node from timeframes pRepr = p->pObjCopies[nFrames*i + nFrames-1-f]; pReprR = Aig_Regular(pRepr); if ( pCnf->pVarNums[Aig_ObjId(pReprR)] < 0 ) continue; // value = pSat->assigns[ pCnf->pVarNums[Aig_ObjId(pReprR)] ]; value = sat_solver_get_var_value( pSat, pCnf->pVarNums[Aig_ObjId(pReprR)] ); if ( value == l_Undef ) continue; // label this node as taken Aig_ObjSetTravIdCurrent(p, pObj); if ( Saig_ObjIsLo(p, pObj) ) Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin0(Saig_ObjLoToLi(p, pObj)) ); // remember the node Vec_VecPush( vCands, f, Aig_NotCond( pObj, (value == l_True) ^ Aig_IsComplement(pRepr) ) ); // printf( "%s%d ", (value == l_False)? "":"!", i ); } } // printf( "\n" ); sat_solver_delete( pSat ); } Aig_ManStop( pFrames ); Cnf_DataFree( pCnf ); if ( fVerbose ) { printf( "Found %3d candidates.\n", Vec_VecSizeSize(vCands) ); Vec_VecForEachLevel( vCands, vNodes, k ) { printf( "Level %d. Cands =%d ", k, Vec_PtrSize(vNodes) ); // Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) // printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); printf( "\n" ); } } ABC_FREE( p->pObjCopies ); Saig_ManFilterUsingInd( p, vCands, nConfs, nProps, fVerbose ); if ( Vec_VecSizeSize(vCands) ) printf( "Found %3d constraints after filtering.\n", Vec_VecSizeSize(vCands) ); if ( fVerbose ) { Vec_VecForEachLevel( vCands, vNodes, k ) { printf( "Level %d. Constr =%d ", k, Vec_PtrSize(vNodes) ); // Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) // printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); printf( "\n" ); } } return vCands; } /**Function************************************************************* Synopsis [Detects constraints functionally.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Saig_ManDetectConstrFunc( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fVerbose ) { int iPat = 0, nWordsAlloc = 16; Bar_Progress_t * pProgress = NULL; Vec_Vec_t * vCands = NULL; Vec_Ptr_t * vInfo, * vNodes; Aig_Obj_t * pObj, * pRepr, * pObjNew; Aig_Man_t * pFrames; sat_solver * pSat; Cnf_Dat_t * pCnf; unsigned * pInfo; int i, j, k, Lit, status, nCands = 0; assert( Saig_ManPoNum(p) == 1 ); if ( Saig_ManPoNum(p) != 1 ) { printf( "The number of outputs is different from 1.\n" ); return NULL; } //printf( "Implications = %d.\n", Ssw_ManCountImplications(p, nFrames) ); // perform unrolling pFrames = Saig_ManUnrollCOI( p, nFrames ); assert( Aig_ManCoNum(pFrames) == 1 ); if ( fVerbose ) { printf( "Detecting constraints with %d frames, %d conflicts, and %d propagations.\n", nFrames, nConfs, nProps ); printf( "Frames: " ); Aig_ManPrintStats( pFrames ); } // Aig_ManShow( pFrames, 0, NULL ); // start the SAT solver pCnf = Cnf_DeriveSimple( pFrames, Aig_ManCoNum(pFrames) ); pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); //printf( "Implications = %d.\n", pSat->qhead ); // solve the original problem Lit = toLitCond( pCnf->pVarNums[Aig_ObjId(Aig_ManCo(pFrames,0))], 0 ); status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfs, 0, 0, 0 ); if ( status == l_False ) { printf( "The problem is trivially UNSAT (inductive with k=%d).\n", nFrames-1 ); Cnf_DataFree( pCnf ); sat_solver_delete( pSat ); Aig_ManStop( pFrames ); return NULL; } if ( status == l_Undef ) { printf( "Solver could not solve the original problem.\n" ); Cnf_DataFree( pCnf ); sat_solver_delete( pSat ); Aig_ManStop( pFrames ); return NULL; } assert( status == l_True ); // create simulation info vInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(pFrames), nWordsAlloc ); Vec_PtrCleanSimInfo( vInfo, 0, nWordsAlloc ); Saig_CollectSatValues( pSat, pCnf, vInfo, &iPat ); Aig_ManForEachObj( pFrames, pObj, i ) { pInfo = (unsigned *)Vec_PtrEntry( vInfo, i ); if ( pInfo[0] & 1 ) memset( (char*)pInfo, 0xff, 4*nWordsAlloc ); } // Aig_ManShow( pFrames, 0, NULL ); // Aig_ManShow( p, 0, NULL ); // consider the nodes for ci=>!Out and label when it holds pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(pFrames) ); Aig_ManCleanMarkAB( pFrames ); Aig_ManForEachObj( pFrames, pObj, i ) { if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) continue; Bar_ProgressUpdate( pProgress, i, NULL ); // check if the node is available in both polarities pInfo = (unsigned *)Vec_PtrEntry( vInfo, i ); for ( k = 0; k < nWordsAlloc; k++ ) if ( pInfo[k] != ~0 ) break; if ( k == nWordsAlloc ) { if ( Saig_DetectTryPolarity(pSat, nConfs, nProps, pCnf, pObj, 0, vInfo, &iPat, fVerbose) ) // !pObj is a constr { pObj->fMarkA = 1, nCands++; // printf( "!%d ", Aig_ObjId(pObj) ); } continue; } for ( k = 0; k < nWordsAlloc; k++ ) if ( pInfo[k] != 0 ) break; if ( k == nWordsAlloc ) { if ( Saig_DetectTryPolarity(pSat, nConfs, nProps, pCnf, pObj, 1, vInfo, &iPat, fVerbose) ) // pObj is a constr { pObj->fMarkB = 1, nCands++; // printf( "%d ", Aig_ObjId(pObj) ); } continue; } } Bar_ProgressStop( pProgress ); if ( nCands ) { // printf( "\n" ); if ( fVerbose ) printf( "Found %3d classes of candidates.\n", nCands ); vCands = Vec_VecAlloc( nFrames ); for ( k = 0; k < nFrames; k++ ) { Aig_ManForEachObj( p, pObj, i ) { if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) continue; pRepr = p->pObjCopies[nFrames*i + nFrames-1-k]; // pRepr = p->pObjCopies[nFrames*i + k]; if ( pRepr == NULL ) continue; if ( Aig_Regular(pRepr)->fMarkA ) // !pObj is a constr { pObjNew = Aig_NotCond(pObj, !Aig_IsComplement(pRepr)); for ( j = 0; j < k; j++ ) if ( Vec_PtrFind( Vec_VecEntry(vCands, j), pObjNew ) >= 0 ) break; if ( j == k ) Vec_VecPush( vCands, k, pObjNew ); // printf( "%d->!%d ", Aig_ObjId(Aig_Regular(pRepr)), Aig_ObjId(pObj) ); } else if ( Aig_Regular(pRepr)->fMarkB ) // pObj is a constr { pObjNew = Aig_NotCond(pObj, Aig_IsComplement(pRepr)); for ( j = 0; j < k; j++ ) if ( Vec_PtrFind( Vec_VecEntry(vCands, j), pObjNew ) >= 0 ) break; if ( j == k ) Vec_VecPush( vCands, k, pObjNew ); // printf( "%d->%d ", Aig_ObjId(Aig_Regular(pRepr)), Aig_ObjId(pObj) ); } } } // printf( "\n" ); if ( fVerbose ) { printf( "Found %3d candidates.\n", Vec_VecSizeSize(vCands) ); Vec_VecForEachLevel( vCands, vNodes, k ) { printf( "Level %d. Cands =%d ", k, Vec_PtrSize(vNodes) ); // Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) // printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); printf( "\n" ); } } ABC_FREE( p->pObjCopies ); Saig_ManFilterUsingInd( p, vCands, nConfs, nProps, fVerbose ); if ( Vec_VecSizeSize(vCands) ) printf( "Found %3d constraints after filtering.\n", Vec_VecSizeSize(vCands) ); if ( fVerbose ) { Vec_VecForEachLevel( vCands, vNodes, k ) { printf( "Level %d. Constr =%d ", k, Vec_PtrSize(vNodes) ); // Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) // printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); printf( "\n" ); } } } Vec_PtrFree( vInfo ); Cnf_DataFree( pCnf ); sat_solver_delete( pSat ); Aig_ManCleanMarkAB( pFrames ); Aig_ManStop( pFrames ); return vCands; } /**Function************************************************************* Synopsis [Experimental procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManDetectConstrFuncTest( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose ) { Vec_Vec_t * vCands; if ( fOldAlgo ) vCands = Saig_ManDetectConstrFunc( p, nFrames, nConfs, nProps, fVerbose ); else vCands = Ssw_ManFindDirectImplications( p, nFrames, nConfs, nProps, fVerbose ); Vec_VecFreeP( &vCands ); } /**Function************************************************************* Synopsis [Duplicates the AIG while unfolding constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDupUnfoldConstrsFunc( Aig_Man_t * pAig, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose ) { Aig_Man_t * pNew; Vec_Vec_t * vCands; Vec_Ptr_t * vNodes, * vNewFlops; Aig_Obj_t * pObj; int i, j, k, nNewFlops; if ( fOldAlgo ) vCands = Saig_ManDetectConstrFunc( pAig, nFrames, nConfs, nProps, fVerbose ); else vCands = Ssw_ManFindDirectImplications( pAig, nFrames, nConfs, nProps, fVerbose ); if ( vCands == NULL || Vec_VecSizeSize(vCands) == 0 ) { Vec_VecFreeP( &vCands ); return Aig_ManDupDfs( pAig ); } // create new manager pNew = Aig_ManDupWithoutPos( pAig ); pNew->nConstrs = pAig->nConstrs + Vec_VecSizeSize(vCands); // add normal POs Saig_ManForEachPo( pAig, pObj, i ) Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); // create constraint outputs vNewFlops = Vec_PtrAlloc( 100 ); Vec_VecForEachLevel( vCands, vNodes, i ) { Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) { Vec_PtrPush( vNewFlops, Aig_ObjRealCopy(pObj) ); for ( j = 0; j < i; j++ ) Vec_PtrPush( vNewFlops, Aig_ObjCreateCi(pNew) ); Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrPop(vNewFlops) ); } } // add latch outputs Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); // add new latch outputs nNewFlops = 0; Vec_VecForEachLevel( vCands, vNodes, i ) { Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) { for ( j = 0; j < i; j++ ) Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vNewFlops, nNewFlops++) ); } } assert( nNewFlops == Vec_PtrSize(vNewFlops) ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) + nNewFlops ); Vec_VecFreeP( &vCands ); Vec_PtrFree( vNewFlops ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG while unfolding constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDupFoldConstrsFunc( Aig_Man_t * pAig, int fCompl, int fVerbose, int fSeqCleanup ) { Aig_Man_t * pAigNew; Aig_Obj_t * pMiter, * pFlopOut, * pFlopIn, * pObj; int i; if ( Aig_ManConstrNum(pAig) == 0 ) return Aig_ManDupDfs( pAig ); assert( Aig_ManConstrNum(pAig) < Saig_ManPoNum(pAig) ); // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); pAigNew->pName = Abc_UtilStrsav( pAig->pName ); pAigNew->pSpec = Abc_UtilStrsav( pAig->pSpec ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create variables for PIs Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( pAigNew ); // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // OR the constraint outputs pMiter = Aig_ManConst0( pAigNew ); Saig_ManForEachPo( pAig, pObj, i ) { if ( i < Saig_ManPoNum(pAig)-Aig_ManConstrNum(pAig) ) continue; pMiter = Aig_Or( pAigNew, pMiter, Aig_NotCond( Aig_ObjChild0Copy(pObj), fCompl ) ); } // create additional flop if ( Saig_ManRegNum(pAig) > 0 ) { pFlopOut = Aig_ObjCreateCi( pAigNew ); pFlopIn = Aig_Or( pAigNew, pMiter, pFlopOut ); } else pFlopIn = pMiter; // create primary output Saig_ManForEachPo( pAig, pObj, i ) { if ( i >= Saig_ManPoNum(pAig)-Aig_ManConstrNum(pAig) ) continue; pMiter = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_Not(pFlopIn) ); Aig_ObjCreateCo( pAigNew, pMiter ); } // transfer to register outputs Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); // create additional flop if ( Saig_ManRegNum(pAig) > 0 ) { Aig_ObjCreateCo( pAigNew, pFlopIn ); Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig)+1 ); } // perform cleanup Aig_ManCleanup( pAigNew ); if ( fSeqCleanup ) Aig_ManSeqCleanup( pAigNew ); return pAigNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// #include "saigUnfold2.c" ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigDual.c000066400000000000000000000205461477524141600163560ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigDual.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Various duplication procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigDual.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline void Saig_ObjSetDual( Vec_Ptr_t * vCopies, int Id, int fPos, Aig_Obj_t * pItem ) { Vec_PtrWriteEntry( vCopies, 2*Id+fPos, pItem ); } static inline Aig_Obj_t * Saig_ObjDual( Vec_Ptr_t * vCopies, int Id, int fPos ) { return (Aig_Obj_t *)Vec_PtrEntry( vCopies, 2*Id+fPos ); } static inline void Saig_ObjDualFanin( Aig_Man_t * pAigNew, Vec_Ptr_t * vCopies, Aig_Obj_t * pObj, int iFanin, Aig_Obj_t ** ppRes0, Aig_Obj_t ** ppRes1 ) { Aig_Obj_t * pTemp0, * pTemp1, * pCare; int fCompl; assert( iFanin == 0 || iFanin == 1 ); if ( iFanin == 0 ) { pTemp0 = Saig_ObjDual( vCopies, Aig_ObjFaninId0(pObj), 0 ); pTemp1 = Saig_ObjDual( vCopies, Aig_ObjFaninId0(pObj), 1 ); fCompl = Aig_ObjFaninC0( pObj ); } else { pTemp0 = Saig_ObjDual( vCopies, Aig_ObjFaninId1(pObj), 0 ); pTemp1 = Saig_ObjDual( vCopies, Aig_ObjFaninId1(pObj), 1 ); fCompl = Aig_ObjFaninC1( pObj ); } if ( fCompl ) { pCare = Aig_Or( pAigNew, pTemp0, pTemp1 ); *ppRes0 = Aig_And( pAigNew, pTemp1, pCare ); *ppRes1 = Aig_And( pAigNew, pTemp0, pCare ); } else { *ppRes0 = pTemp0; *ppRes1 = pTemp1; } } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Transforms sequential AIG into dual-rail miter.] Description [Transforms sequential AIG into a miter encoding ternary problem formulated as follows "none of the POs has a ternary value". Interprets the first nDualPis as having ternary value. Sets flops to have ternary intial value when fDualFfs is set to 1.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDupDual( Aig_Man_t * pAig, Vec_Int_t * vDcFlops, int nDualPis, int fDualFfs, int fMiterFfs, int fComplPo, int fCheckZero, int fCheckOne ) { Vec_Ptr_t * vCopies; Aig_Man_t * pAigNew; Aig_Obj_t * pObj, * pTemp0, * pTemp1, * pTemp2, * pTemp3, * pCare, * pMiter; int i; assert( Saig_ManPoNum(pAig) > 0 ); assert( nDualPis >= 0 && nDualPis <= Saig_ManPiNum(pAig) ); assert( vDcFlops == NULL || Vec_IntSize(vDcFlops) == Aig_ManRegNum(pAig) ); vCopies = Vec_PtrStart( 2*Aig_ManObjNum(pAig) ); // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); pAigNew->pName = Abc_UtilStrsav( pAig->pName ); // map the constant node Saig_ObjSetDual( vCopies, 0, 0, Aig_ManConst0(pAigNew) ); Saig_ObjSetDual( vCopies, 0, 1, Aig_ManConst1(pAigNew) ); // create variables for PIs Aig_ManForEachCi( pAig, pObj, i ) { if ( i < nDualPis ) { pTemp0 = Aig_ObjCreateCi( pAigNew ); pTemp1 = Aig_ObjCreateCi( pAigNew ); } else if ( i < Saig_ManPiNum(pAig) ) { pTemp1 = Aig_ObjCreateCi( pAigNew ); pTemp0 = Aig_Not( pTemp1 ); } else { pTemp0 = Aig_ObjCreateCi( pAigNew ); pTemp1 = Aig_ObjCreateCi( pAigNew ); if ( vDcFlops ) pTemp0 = Aig_NotCond( pTemp0, !Vec_IntEntry(vDcFlops, i-Saig_ManPiNum(pAig)) ); else pTemp0 = Aig_NotCond( pTemp0, !fDualFfs ); } Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 0, Aig_And(pAigNew, pTemp0, Aig_Not(pTemp1)) ); Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 1, Aig_And(pAigNew, pTemp1, Aig_Not(pTemp0)) ); } // create internal nodes Aig_ManForEachNode( pAig, pObj, i ) { Saig_ObjDualFanin( pAigNew, vCopies, pObj, 0, &pTemp0, &pTemp1 ); Saig_ObjDualFanin( pAigNew, vCopies, pObj, 1, &pTemp2, &pTemp3 ); Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 0, Aig_Or (pAigNew, pTemp0, pTemp2) ); Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 1, Aig_And(pAigNew, pTemp1, pTemp3) ); } // create miter and flops pMiter = Aig_ManConst0(pAigNew); if ( fMiterFfs ) { Saig_ManForEachLi( pAig, pObj, i ) { Saig_ObjDualFanin( pAigNew, vCopies, pObj, 0, &pTemp0, &pTemp1 ); if ( fCheckZero ) { pCare = Aig_And( pAigNew, pTemp0, Aig_Not(pTemp1) ); pMiter = Aig_Or( pAigNew, pMiter, pCare ); } else if ( fCheckOne ) { pCare = Aig_And( pAigNew, Aig_Not(pTemp0), pTemp1 ); pMiter = Aig_Or( pAigNew, pMiter, pCare ); } else // check X { pCare = Aig_And( pAigNew, Aig_Not(pTemp0), Aig_Not(pTemp1) ); pMiter = Aig_Or( pAigNew, pMiter, pCare ); } } } else { Saig_ManForEachPo( pAig, pObj, i ) { Saig_ObjDualFanin( pAigNew, vCopies, pObj, 0, &pTemp0, &pTemp1 ); if ( fCheckZero ) { pCare = Aig_And( pAigNew, pTemp0, Aig_Not(pTemp1) ); pMiter = Aig_Or( pAigNew, pMiter, pCare ); } else if ( fCheckOne ) { pCare = Aig_And( pAigNew, Aig_Not(pTemp0), pTemp1 ); pMiter = Aig_Or( pAigNew, pMiter, pCare ); } else // check X { pCare = Aig_And( pAigNew, Aig_Not(pTemp0), Aig_Not(pTemp1) ); pMiter = Aig_Or( pAigNew, pMiter, pCare ); } } } // create PO pMiter = Aig_NotCond( pMiter, fComplPo ); Aig_ObjCreateCo( pAigNew, pMiter ); // create flops Saig_ManForEachLi( pAig, pObj, i ) { Saig_ObjDualFanin( pAigNew, vCopies, pObj, 0, &pTemp0, &pTemp1 ); if ( vDcFlops ) pTemp0 = Aig_NotCond( pTemp0, !Vec_IntEntry(vDcFlops, i) ); else pTemp0 = Aig_NotCond( pTemp0, !fDualFfs ); Aig_ObjCreateCo( pAigNew, pTemp0 ); Aig_ObjCreateCo( pAigNew, pTemp1 ); } // set the flops Aig_ManSetRegNum( pAigNew, 2 * Aig_ManRegNum(pAig) ); Aig_ManCleanup( pAigNew ); Vec_PtrFree( vCopies ); return pAigNew; } /**Function************************************************************* Synopsis [Transforms sequential AIG to block the PO for N cycles.] Description [This procedure should be applied to a safety property miter to make the propetry 'true' (const 0) during the first N cycles.] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManBlockPo( Aig_Man_t * pAig, int nCycles ) { Aig_Obj_t * pObj, * pCond, * pPrev, * pTemp; int i; assert( nCycles > 0 ); // add N flops (assuming 1-hot encoding of cycles) pPrev = Aig_ManConst1(pAig); pCond = Aig_ManConst1(pAig); for ( i = 0; i < nCycles; i++ ) { Aig_ObjCreateCo( pAig, pPrev ); pPrev = Aig_ObjCreateCi( pAig ); pCond = Aig_And( pAig, pCond, pPrev ); } // update the POs Saig_ManForEachPo( pAig, pObj, i ) { pTemp = Aig_And( pAig, Aig_ObjChild0(pObj), pCond ); Aig_ObjPatchFanin0( pAig, pObj, pTemp ); } // set the flops Aig_ManSetRegNum( pAig, Aig_ManRegNum(pAig) + nCycles ); Aig_ManCleanup( pAig ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigDup.c000066400000000000000000000475151477524141600162260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigDup.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Various duplication procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigDup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Duplicates while ORing the POs of sequential circuit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDupOrpos( Aig_Man_t * pAig ) { Aig_Man_t * pAigNew; Aig_Obj_t * pObj, * pMiter; int i; if ( pAig->nConstrs > 0 ) { printf( "The AIG manager should have no constraints.\n" ); return NULL; } // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); pAigNew->pName = Abc_UtilStrsav( pAig->pName ); pAigNew->nConstrs = pAig->nConstrs; // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create variables for PIs Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( pAigNew ); // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create PO of the circuit pMiter = Aig_ManConst0( pAigNew ); Saig_ManForEachPo( pAig, pObj, i ) pMiter = Aig_Or( pAigNew, pMiter, Aig_ObjChild0Copy(pObj) ); Aig_ObjCreateCo( pAigNew, pMiter ); // transfer to register outputs Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); Aig_ManCleanup( pAigNew ); Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) ); return pAigNew; } /**Function************************************************************* Synopsis [Duplicates while ORing the POs of sequential circuit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManCreateEquivMiter( Aig_Man_t * pAig, Vec_Int_t * vPairs, int fAddOuts ) { Aig_Man_t * pAigNew; Aig_Obj_t * pObj, * pObj2, * pMiter; int i; if ( pAig->nConstrs > 0 ) { printf( "The AIG manager should have no constraints.\n" ); return NULL; } // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); pAigNew->pName = Abc_UtilStrsav( pAig->pName ); pAigNew->nConstrs = pAig->nConstrs; // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create variables for PIs Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( pAigNew ); // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create POs assert( Vec_IntSize(vPairs) % 2 == 0 ); Aig_ManForEachObjVec( vPairs, pAig, pObj, i ) { pObj2 = Aig_ManObj( pAig, Vec_IntEntry(vPairs, ++i) ); pMiter = Aig_Exor( pAigNew, (Aig_Obj_t *)pObj->pData, (Aig_Obj_t *)pObj2->pData ); pMiter = Aig_NotCond( pMiter, pObj->fPhase ^ pObj2->fPhase ); Aig_ObjCreateCo( pAigNew, pMiter ); } // transfer to register outputs if ( fAddOuts ) Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); Aig_ManCleanup( pAigNew ); if ( fAddOuts ) Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) ); return pAigNew; } /**Function************************************************************* Synopsis [Trims the model by removing PIs without fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManTrimPis( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i, fAllPisHaveNoRefs; // check the refs of PIs fAllPisHaveNoRefs = 1; Saig_ManForEachPi( p, pObj, i ) if ( pObj->nRefs ) fAllPisHaveNoRefs = 0; // start the new manager pNew = Aig_ManStart( Aig_ManObjNum(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->nConstrs = p->nConstrs; // start mapping of the CI numbers pNew->vCiNumsOrig = Vec_IntAlloc( Aig_ManCiNum(p) ); // map const and primary inputs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) if ( fAllPisHaveNoRefs || pObj->nRefs || Saig_ObjIsLo(p, pObj) ) { pObj->pData = Aig_ObjCreateCi( pNew ); Vec_IntPush( pNew->vCiNumsOrig, Vec_IntEntry(p->vCiNumsOrig, i) ); } Aig_ManForEachNode( p, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); Aig_ManForEachCo( p, pObj, i ) pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG manager recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Saig_ManAbstractionDfs_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj ) { if ( pObj->pData ) return (Aig_Obj_t *)pObj->pData; Saig_ManAbstractionDfs_rec( pNew, Aig_ObjFanin0(pObj) ); Saig_ManAbstractionDfs_rec( pNew, Aig_ObjFanin1(pObj) ); return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) )); } /**Function************************************************************* Synopsis [Performs abstraction of the AIG to preserve the included flops.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDupAbstraction( Aig_Man_t * p, Vec_Int_t * vFlops ) { Aig_Man_t * pNew;//, * pTemp; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, Entry; Aig_ManCleanData( p ); // start the new manager pNew = Aig_ManStart( 5000 ); pNew->pName = Abc_UtilStrsav( p->pName ); // map the constant node Aig_ManConst1(p)->pData = Aig_ManConst1( pNew ); // label included flops Vec_IntForEachEntry( vFlops, Entry, i ) { pObjLi = Saig_ManLi( p, Entry ); assert( pObjLi->fMarkA == 0 ); pObjLi->fMarkA = 1; pObjLo = Saig_ManLo( p, Entry ); assert( pObjLo->fMarkA == 0 ); pObjLo->fMarkA = 1; } // create variables for PIs assert( p->vCiNumsOrig == NULL ); pNew->vCiNumsOrig = Vec_IntAlloc( Aig_ManCiNum(p) ); Aig_ManForEachCi( p, pObj, i ) if ( !pObj->fMarkA ) { pObj->pData = Aig_ObjCreateCi( pNew ); Vec_IntPush( pNew->vCiNumsOrig, i ); } // create variables for LOs Aig_ManForEachCi( p, pObj, i ) if ( pObj->fMarkA ) { pObj->fMarkA = 0; pObj->pData = Aig_ObjCreateCi( pNew ); Vec_IntPush( pNew->vCiNumsOrig, i ); } // add internal nodes // Aig_ManForEachNode( p, pObj, i ) // pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create POs Saig_ManForEachPo( p, pObj, i ) { Saig_ManAbstractionDfs_rec( pNew, Aig_ObjFanin0(pObj) ); Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } // create LIs Aig_ManForEachCo( p, pObj, i ) if ( pObj->fMarkA ) { pObj->fMarkA = 0; Saig_ManAbstractionDfs_rec( pNew, Aig_ObjFanin0(pObj) ); Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } Aig_ManSetRegNum( pNew, Vec_IntSize(vFlops) ); Aig_ManSeqCleanup( pNew ); // remove PIs without fanout // pNew = Saig_ManTrimPis( pTemp = pNew ); // Aig_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [Resimulates the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManVerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p ) { Aig_Obj_t * pObj, * pObjRi, * pObjRo; int RetValue, i, k, iBit = 0; Aig_ManCleanMarkB(pAig); Aig_ManConst1(pAig)->fMarkB = 1; Saig_ManForEachLo( pAig, pObj, i ) pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); for ( i = 0; i <= p->iFrame; i++ ) { Saig_ManForEachPi( pAig, pObj, k ) pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); Aig_ManForEachNode( pAig, pObj, k ) pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); Aig_ManForEachCo( pAig, pObj, k ) pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); if ( i == p->iFrame ) break; Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) pObjRo->fMarkB = pObjRi->fMarkB; } assert( iBit == p->nBits ); RetValue = Aig_ManCo(pAig, p->iPo)->fMarkB; Aig_ManCleanMarkB(pAig); return RetValue; } /**Function************************************************************* Synopsis [Resimulates the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManVerifyCexNoClear( Aig_Man_t * pAig, Abc_Cex_t * p ) { Aig_Obj_t * pObj, * pObjRi, * pObjRo; int RetValue, i, k, iBit = 0; Aig_ManCleanMarkB(pAig); Aig_ManConst1(pAig)->fMarkB = 1; Saig_ManForEachLo( pAig, pObj, i ) pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); for ( i = 0; i <= p->iFrame; i++ ) { Saig_ManForEachPi( pAig, pObj, k ) pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); Aig_ManForEachNode( pAig, pObj, k ) pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); Aig_ManForEachCo( pAig, pObj, k ) pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); if ( i == p->iFrame ) break; Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) pObjRo->fMarkB = pObjRi->fMarkB; } assert( iBit == p->nBits ); RetValue = Aig_ManCo(pAig, p->iPo)->fMarkB; //Aig_ManCleanMarkB(pAig); return RetValue; } Vec_Int_t * Saig_ManReturnFailingState( Aig_Man_t * pAig, Abc_Cex_t * p, int fNextOne ) { Aig_Obj_t * pObj; Vec_Int_t * vState; int i, RetValue = Saig_ManVerifyCexNoClear( pAig, p ); if ( RetValue == 0 ) { Aig_ManCleanMarkB(pAig); printf( "CEX does fail the given sequential miter.\n" ); return NULL; } vState = Vec_IntAlloc( Aig_ManRegNum(pAig) ); if ( fNextOne ) { Saig_ManForEachLi( pAig, pObj, i ) Vec_IntPush( vState, pObj->fMarkB ); } else { Saig_ManForEachLo( pAig, pObj, i ) Vec_IntPush( vState, pObj->fMarkB ); } Aig_ManCleanMarkB(pAig); return vState; } /**Function************************************************************* Synopsis [Resimulates the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Saig_ManExtendCex( Aig_Man_t * pAig, Abc_Cex_t * p ) { Abc_Cex_t * pNew; Aig_Obj_t * pObj, * pObjRi, * pObjRo; int RetValue, i, k, iBit = 0; // create new counter-example pNew = Abc_CexAlloc( 0, Aig_ManCiNum(pAig), p->iFrame + 1 ); pNew->iPo = p->iPo; pNew->iFrame = p->iFrame; // simulate the AIG Aig_ManCleanMarkB(pAig); Aig_ManConst1(pAig)->fMarkB = 1; Saig_ManForEachLo( pAig, pObj, i ) pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); for ( i = 0; i <= p->iFrame; i++ ) { Saig_ManForEachPi( pAig, pObj, k ) pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); ///////// write PI+LO values //////////// Aig_ManForEachCi( pAig, pObj, k ) if ( pObj->fMarkB ) Abc_InfoSetBit(pNew->pData, Aig_ManCiNum(pAig)*i + k); ///////////////////////////////////////// Aig_ManForEachNode( pAig, pObj, k ) pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); Aig_ManForEachCo( pAig, pObj, k ) pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); if ( i == p->iFrame ) break; Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) pObjRo->fMarkB = pObjRi->fMarkB; } assert( iBit == p->nBits ); RetValue = Aig_ManCo(pAig, p->iPo)->fMarkB; Aig_ManCleanMarkB(pAig); if ( RetValue == 0 ) printf( "Saig_ManExtendCex(): The counter-example is invalid!!!\n" ); return pNew; } /**Function************************************************************* Synopsis [Resimulates the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManFindFailedPoCex( Aig_Man_t * pAig, Abc_Cex_t * p ) { Aig_Obj_t * pObj, * pObjRi, * pObjRo; int RetValue, i, k, iBit = 0; Aig_ManCleanMarkB(pAig); Aig_ManConst1(pAig)->fMarkB = 1; Saig_ManForEachLo( pAig, pObj, i ) pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); for ( i = 0; i <= p->iFrame; i++ ) { Saig_ManForEachPi( pAig, pObj, k ) pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); Aig_ManForEachNode( pAig, pObj, k ) pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); Aig_ManForEachCo( pAig, pObj, k ) pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); if ( i == p->iFrame ) break; Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) pObjRo->fMarkB = pObjRi->fMarkB; } assert( iBit == p->nBits ); // remember the number of failed output RetValue = -1; Saig_ManForEachPo( pAig, pObj, i ) if ( pObj->fMarkB ) { RetValue = i; break; } Aig_ManCleanMarkB(pAig); return RetValue; } /**Function************************************************************* Synopsis [Duplicates while ORing the POs of sequential circuit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDupWithPhase( Aig_Man_t * pAig, Vec_Int_t * vInit ) { Aig_Man_t * pAigNew; Aig_Obj_t * pObj; int i; assert( Aig_ManRegNum(pAig) <= Vec_IntSize(vInit) ); // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); pAigNew->pName = Abc_UtilStrsav( pAig->pName ); pAigNew->nConstrs = pAig->nConstrs; // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create variables for PIs Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( pAigNew ); // update the flop variables Saig_ManForEachLo( pAig, pObj, i ) pObj->pData = Aig_NotCond( (Aig_Obj_t *)pObj->pData, Vec_IntEntry(vInit, i) ); // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // transfer to register outputs Saig_ManForEachPo( pAig, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); // update the flop variables Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_NotCond(Aig_ObjChild0Copy(pObj), Vec_IntEntry(vInit, i)) ); // finalize Aig_ManCleanup( pAigNew ); Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) ); return pAigNew; } /**Function************************************************************* Synopsis [Copy an AIG structure related to the selected POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManDupCones_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vRoots ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); if ( Aig_ObjIsNode(pObj) ) { Saig_ManDupCones_rec( p, Aig_ObjFanin0(pObj), vLeaves, vNodes, vRoots ); Saig_ManDupCones_rec( p, Aig_ObjFanin1(pObj), vLeaves, vNodes, vRoots ); Vec_PtrPush( vNodes, pObj ); } else if ( Aig_ObjIsCo(pObj) ) Saig_ManDupCones_rec( p, Aig_ObjFanin0(pObj), vLeaves, vNodes, vRoots ); else if ( Saig_ObjIsLo(p, pObj) ) Vec_PtrPush( vRoots, Saig_ObjLoToLi(p, pObj) ); else if ( Saig_ObjIsPi(p, pObj) ) Vec_PtrPush( vLeaves, pObj ); else assert( 0 ); } Aig_Man_t * Saig_ManDupCones( Aig_Man_t * pAig, int * pPos, int nPos ) { Aig_Man_t * pAigNew; Vec_Ptr_t * vLeaves, * vNodes, * vRoots; Aig_Obj_t * pObj; int i; // collect initial POs vLeaves = Vec_PtrAlloc( 100 ); vNodes = Vec_PtrAlloc( 100 ); vRoots = Vec_PtrAlloc( 100 ); for ( i = 0; i < nPos; i++ ) Vec_PtrPush( vRoots, Aig_ManCo(pAig, pPos[i]) ); // mark internal nodes Aig_ManIncrementTravId( pAig ); Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i ) Saig_ManDupCones_rec( pAig, pObj, vLeaves, vNodes, vRoots ); // start the new manager pAigNew = Aig_ManStart( Vec_PtrSize(vNodes) ); pAigNew->pName = Abc_UtilStrsav( pAig->pName ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create PIs Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) pObj->pData = Aig_ObjCreateCi( pAigNew ); // create LOs Vec_PtrForEachEntryStart( Aig_Obj_t *, vRoots, pObj, i, nPos ) Saig_ObjLiToLo(pAig, pObj)->pData = Aig_ObjCreateCi( pAigNew ); // create internal nodes Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create COs Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); // finalize Aig_ManSetRegNum( pAigNew, Vec_PtrSize(vRoots)-nPos ); Vec_PtrFree( vLeaves ); Vec_PtrFree( vNodes ); Vec_PtrFree( vRoots ); return pAigNew; } #ifndef ABC_USE_CUDD int Aig_ManVerifyUsingBdds( Aig_Man_t * pInit, Saig_ParBbr_t * pPars ) { return 0; } void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p ) {} #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigGlaCba.c000066400000000000000000000655221477524141600166050ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigGlaCba.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Gate level abstraction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigGlaCba.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "sat/bsat/satSolver.h" #include "sat/cnf/cnf.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Aig_Gla1Man_t_ Aig_Gla1Man_t; struct Aig_Gla1Man_t_ { // user data Aig_Man_t * pAig; int nConfLimit; int nFramesMax; int fVerbose; // unrolling int nFrames; Vec_Int_t * vObj2Vec; // maps obj ID into its vec ID Vec_Int_t * vVec2Var; // maps vec ID into its sat Var (nFrames per vec ID) Vec_Int_t * vVar2Inf; // maps sat Var into its frame and obj ID // abstraction Vec_Int_t * vAssigned; // collects objects whose SAT variables have been created Vec_Int_t * vIncluded; // maps obj ID into its status (0=unused; 1=included in abstraction) // components Vec_Int_t * vPis; // primary inputs Vec_Int_t * vPPis; // pseudo primary inputs Vec_Int_t * vFlops; // flops Vec_Int_t * vNodes; // nodes // CNF computation Vec_Ptr_t * vLeaves; Vec_Ptr_t * vVolume; Vec_Int_t * vCover; Vec_Ptr_t * vObj2Cnf; Vec_Int_t * vLits; // SAT solver sat_solver * pSat; // statistics clock_t timeSat; clock_t timeRef; clock_t timeTotal; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Adds constant to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_Gla1AddConst( sat_solver * pSat, int iVar, int fCompl ) { lit Lit = toLitCond( iVar, fCompl ); if ( !sat_solver_addclause( pSat, &Lit, &Lit + 1 ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Adds buffer to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_Gla1AddBuffer( sat_solver * pSat, int iVar0, int iVar1, int fCompl ) { lit Lits[2]; Lits[0] = toLitCond( iVar0, 0 ); Lits[1] = toLitCond( iVar1, !fCompl ); if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) return 0; Lits[0] = toLitCond( iVar0, 1 ); Lits[1] = toLitCond( iVar1, fCompl ); if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Adds buffer to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_Gla1AddNode( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 ) { lit Lits[3]; Lits[0] = toLitCond( iVar, 1 ); Lits[1] = toLitCond( iVar0, fCompl0 ); if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) return 0; Lits[0] = toLitCond( iVar, 1 ); Lits[1] = toLitCond( iVar1, fCompl1 ); if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) return 0; Lits[0] = toLitCond( iVar, 0 ); Lits[1] = toLitCond( iVar0, !fCompl0 ); Lits[2] = toLitCond( iVar1, !fCompl1 ); if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Derives abstraction components (PIs, PPIs, flops, nodes).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_Gla1CollectAbstr( Aig_Gla1Man_t * p ) { Aig_Obj_t * pObj; int i, Entry; /* // make sure every neighbor of included objects is assigned a variable Vec_IntForEachEntry( p->vIncluded, Entry, i ) { if ( Entry == 0 ) continue; assert( Entry == 1 ); pObj = Aig_ManObj( p->pAig, i ); if ( Vec_IntFind( p->vAssigned, Aig_ObjId(pObj) ) == -1 ) printf( "Aig_Gla1CollectAbstr(): Object not found\n" ); if ( Aig_ObjIsNode(pObj) ) { if ( Vec_IntFind( p->vAssigned, Aig_ObjFaninId0(pObj) ) == -1 ) printf( "Aig_Gla1CollectAbstr(): Node's fanin is not found\n" ); if ( Vec_IntFind( p->vAssigned, Aig_ObjFaninId1(pObj) ) == -1 ) printf( "Aig_Gla1CollectAbstr(): Node's fanin is not found\n" ); } else if ( Saig_ObjIsLo(p->pAig, pObj) ) { Aig_Obj_t * pObjLi; pObjLi = Saig_ObjLoToLi(p->pAig, pObj); if ( Vec_IntFind( p->vAssigned, Aig_ObjFaninId0(pObjLi) ) == -1 ) printf( "Aig_Gla1CollectAbstr(): Flop's fanin is not found\n" ); } else assert( Aig_ObjIsConst1(pObj) ); } */ Vec_IntClear( p->vPis ); Vec_IntClear( p->vPPis ); Vec_IntClear( p->vFlops ); Vec_IntClear( p->vNodes ); Vec_IntForEachEntryReverse( p->vAssigned, Entry, i ) { pObj = Aig_ManObj( p->pAig, Entry ); if ( Saig_ObjIsPi(p->pAig, pObj) ) Vec_IntPush( p->vPis, Aig_ObjId(pObj) ); else if ( !Vec_IntEntry(p->vIncluded, Aig_ObjId(pObj)) ) Vec_IntPush( p->vPPis, Aig_ObjId(pObj) ); else if ( Aig_ObjIsNode(pObj) ) Vec_IntPush( p->vNodes, Aig_ObjId(pObj) ); else if ( Saig_ObjIsLo(p->pAig, pObj) ) Vec_IntPush( p->vFlops, Aig_ObjId(pObj) ); else assert( Aig_ObjIsConst1(pObj) ); } } /**Function************************************************************* Synopsis [Duplicates the AIG manager recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_Gla1DeriveAbs_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj ) { if ( pObj->pData ) return; assert( Aig_ObjIsNode(pObj) ); Aig_Gla1DeriveAbs_rec( pNew, Aig_ObjFanin0(pObj) ); Aig_Gla1DeriveAbs_rec( pNew, Aig_ObjFanin1(pObj) ); pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } /**Function************************************************************* Synopsis [Derives abstraction.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_Gla1DeriveAbs( Aig_Gla1Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i, RetValue; assert( Saig_ManPoNum(p->pAig) == 1 ); // start the new manager pNew = Aig_ManStart( 5000 ); pNew->pName = Abc_UtilStrsav( p->pAig->pName ); // create constant Aig_ManCleanData( p->pAig ); Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew); // create PIs Aig_ManForEachObjVec( p->vPis, p->pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi(pNew); // create additional PIs Aig_ManForEachObjVec( p->vPPis, p->pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi(pNew); // create ROs Aig_ManForEachObjVec( p->vFlops, p->pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi(pNew); // create internal nodes Aig_ManForEachObjVec( p->vNodes, p->pAig, pObj, i ) // pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); Aig_Gla1DeriveAbs_rec( pNew, pObj ); // create PO Saig_ManForEachPo( p->pAig, pObj, i ) pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); // create RIs Aig_ManForEachObjVec( p->vFlops, p->pAig, pObj, i ) { assert( Saig_ObjIsLo(p->pAig, pObj) ); pObj = Saig_ObjLoToLi( p->pAig, pObj ); pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } Aig_ManSetRegNum( pNew, Vec_IntSize(p->vFlops) ); // clean up RetValue = Aig_ManCleanup( pNew ); if ( RetValue > 0 ) printf( "Aig_Gla1DeriveAbs(): Internal error! Object count mismatch.\n" ); assert( RetValue == 0 ); return pNew; } /**Function************************************************************* Synopsis [Finds existing SAT variable or creates a new one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_Gla1FetchVecId( Aig_Gla1Man_t * p, Aig_Obj_t * pObj ) { int i, iVecId; iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) ); if ( iVecId == 0 ) { iVecId = Vec_IntSize( p->vVec2Var ) / p->nFrames; for ( i = 0; i < p->nFrames; i++ ) Vec_IntPush( p->vVec2Var, 0 ); Vec_IntWriteEntry( p->vObj2Vec, Aig_ObjId(pObj), iVecId ); Vec_IntPushOrderReverse( p->vAssigned, Aig_ObjId(pObj) ); } return iVecId; } /**Function************************************************************* Synopsis [Finds existing SAT variable or creates a new one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_Gla1FetchVar( Aig_Gla1Man_t * p, Aig_Obj_t * pObj, int k ) { int iVecId, iSatVar; assert( k < p->nFrames ); iVecId = Aig_Gla1FetchVecId( p, pObj ); iSatVar = Vec_IntEntry( p->vVec2Var, iVecId * p->nFrames + k ); if ( iSatVar == 0 ) { iSatVar = Vec_IntSize( p->vVar2Inf ) / 2; Vec_IntPush( p->vVar2Inf, Aig_ObjId(pObj) ); Vec_IntPush( p->vVar2Inf, k ); Vec_IntWriteEntry( p->vVec2Var, iVecId * p->nFrames + k, iSatVar ); sat_solver_setnvars( p->pSat, iSatVar + 1 ); } return iSatVar; } /**Function************************************************************* Synopsis [Adds CNF for the given object in the given frame.] Description [Returns 0, if the solver becames UNSAT.] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_Gla1ObjAddToSolver( Aig_Gla1Man_t * p, Aig_Obj_t * pObj, int k ) { if ( k == p->nFrames ) { int i, j, nVecIds = Vec_IntSize( p->vVec2Var ) / p->nFrames; Vec_Int_t * vVec2VarNew = Vec_IntAlloc( 4 * nVecIds * p->nFrames ); for ( i = 0; i < nVecIds; i++ ) { for ( j = 0; j < p->nFrames; j++ ) Vec_IntPush( vVec2VarNew, Vec_IntEntry( p->vVec2Var, i * p->nFrames + j ) ); for ( j = 0; j < p->nFrames; j++ ) Vec_IntPush( vVec2VarNew, i ? 0 : -1 ); } Vec_IntFree( p->vVec2Var ); p->vVec2Var = vVec2VarNew; p->nFrames *= 2; } assert( k < p->nFrames ); assert( Vec_IntEntry(p->vIncluded, Aig_ObjId(pObj)) ); if ( Aig_ObjIsConst1(pObj) ) return Aig_Gla1AddConst( p->pSat, Aig_Gla1FetchVar(p, pObj, k), 0 ); if ( Saig_ObjIsLo(p->pAig, pObj) ) { Aig_Obj_t * pObjLi = Saig_ObjLoToLi(p->pAig, pObj); if ( k == 0 ) { Aig_Gla1FetchVecId( p, Aig_ObjFanin0(pObjLi) ); return Aig_Gla1AddConst( p->pSat, Aig_Gla1FetchVar(p, pObj, k), 1 ); } return Aig_Gla1AddBuffer( p->pSat, Aig_Gla1FetchVar(p, pObj, k), Aig_Gla1FetchVar(p, Aig_ObjFanin0(pObjLi), k-1), Aig_ObjFaninC0(pObjLi) ); } else { Vec_Int_t * vClauses; int i, Entry; assert( Aig_ObjIsNode(pObj) ); if ( p->vObj2Cnf == NULL ) return Aig_Gla1AddNode( p->pSat, Aig_Gla1FetchVar(p, pObj, k), Aig_Gla1FetchVar(p, Aig_ObjFanin0(pObj), k), Aig_Gla1FetchVar(p, Aig_ObjFanin1(pObj), k), Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) ); // derive clauses assert( pObj->fMarkA ); vClauses = (Vec_Int_t *)Vec_PtrEntry( p->vObj2Cnf, Aig_ObjId(pObj) ); if ( vClauses == NULL ) { Vec_PtrWriteEntry( p->vObj2Cnf, Aig_ObjId(pObj), (vClauses = Vec_IntAlloc(16)) ); Cnf_ComputeClauses( p->pAig, pObj, p->vLeaves, p->vVolume, NULL, p->vCover, vClauses ); } // derive variables Cnf_CollectLeaves( pObj, p->vLeaves, 0 ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vLeaves, pObj, i ) Aig_Gla1FetchVar( p, pObj, k ); // translate clauses assert( Vec_IntSize(vClauses) >= 2 ); assert( Vec_IntEntry(vClauses, 0) == 0 ); Vec_IntForEachEntry( vClauses, Entry, i ) { if ( Entry == 0 ) { Vec_IntClear( p->vLits ); continue; } Vec_IntPush( p->vLits, (Entry & 1) ^ (2 * Aig_Gla1FetchVar(p, Aig_ManObj(p->pAig, Entry >> 1), k)) ); if ( i == Vec_IntSize(vClauses) - 1 || Vec_IntEntry(vClauses, i+1) == 0 ) { if ( !sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntArray(p->vLits)+Vec_IntSize(p->vLits) ) ) return 0; } } return 1; } } /**Function************************************************************* Synopsis [Returns the array of neighbors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_Gla1CollectAssigned( Aig_Gla1Man_t * p, Vec_Int_t * vGateClasses ) { Aig_Obj_t * pObj; int i, Entry; Vec_IntForEachEntryReverse( vGateClasses, Entry, i ) { if ( Entry == 0 ) continue; assert( Entry == 1 ); pObj = Aig_ManObj( p->pAig, i ); Aig_Gla1FetchVecId( p, pObj ); if ( Aig_ObjIsNode(pObj) ) { Aig_Gla1FetchVecId( p, Aig_ObjFanin0(pObj) ); Aig_Gla1FetchVecId( p, Aig_ObjFanin1(pObj) ); } else if ( Saig_ObjIsLo(p->pAig, pObj) ) Aig_Gla1FetchVecId( p, Aig_ObjFanin0(Saig_ObjLoToLi(p->pAig, pObj)) ); else assert( Aig_ObjIsConst1(pObj) ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Gla1Man_t * Aig_Gla1ManStart( Aig_Man_t * pAig, Vec_Int_t * vGateClassesOld, int fNaiveCnf ) { Aig_Gla1Man_t * p; int i; p = ABC_CALLOC( Aig_Gla1Man_t, 1 ); p->pAig = pAig; p->nFrames = 32; // unrolling p->vObj2Vec = Vec_IntStart( Aig_ManObjNumMax(pAig) ); p->vVec2Var = Vec_IntAlloc( 1 << 20 ); p->vVar2Inf = Vec_IntAlloc( 1 << 20 ); // skip first vector ID for ( i = 0; i < p->nFrames; i++ ) Vec_IntPush( p->vVec2Var, -1 ); // skip first SAT variable Vec_IntPush( p->vVar2Inf, -1 ); Vec_IntPush( p->vVar2Inf, -1 ); // abstraction p->vAssigned = Vec_IntAlloc( 1000 ); if ( vGateClassesOld ) { p->vIncluded = Vec_IntDup( vGateClassesOld ); Aig_Gla1CollectAssigned( p, vGateClassesOld ); assert( fNaiveCnf ); } else p->vIncluded = Vec_IntStart( Aig_ManObjNumMax(pAig) ); // components p->vPis = Vec_IntAlloc( 1000 ); p->vPPis = Vec_IntAlloc( 1000 ); p->vFlops = Vec_IntAlloc( 1000 ); p->vNodes = Vec_IntAlloc( 1000 ); // CNF computation if ( !fNaiveCnf ) { p->vLeaves = Vec_PtrAlloc( 100 ); p->vVolume = Vec_PtrAlloc( 100 ); p->vCover = Vec_IntAlloc( 1 << 16 ); p->vObj2Cnf = Vec_PtrStart( Aig_ManObjNumMax(pAig) ); p->vLits = Vec_IntAlloc( 100 ); Cnf_DeriveFastMark( pAig ); } // start the SAT solver p->pSat = sat_solver_new(); sat_solver_setnvars( p->pSat, 256 ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_Gla1ManStop( Aig_Gla1Man_t * p ) { Vec_IntFreeP( &p->vObj2Vec ); Vec_IntFreeP( &p->vVec2Var ); Vec_IntFreeP( &p->vVar2Inf ); Vec_IntFreeP( &p->vAssigned ); Vec_IntFreeP( &p->vIncluded ); Vec_IntFreeP( &p->vPis ); Vec_IntFreeP( &p->vPPis ); Vec_IntFreeP( &p->vFlops ); Vec_IntFreeP( &p->vNodes ); if ( p->vObj2Cnf ) { Vec_PtrFreeP( &p->vLeaves ); Vec_PtrFreeP( &p->vVolume ); Vec_IntFreeP( &p->vCover ); Vec_VecFreeP( (Vec_Vec_t **)&p->vObj2Cnf ); Vec_IntFreeP( &p->vLits ); Aig_ManCleanMarkA( p->pAig ); } if ( p->pSat ) sat_solver_delete( p->pSat ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Aig_Gla1DeriveCex( Aig_Gla1Man_t * p, int iFrame ) { Abc_Cex_t * pCex; Aig_Obj_t * pObj; int i, f, iVecId, iSatId; pCex = Abc_CexAlloc( Vec_IntSize(p->vFlops), Vec_IntSize(p->vPis) + Vec_IntSize(p->vPPis), iFrame+1 ); pCex->iFrame = iFrame; Aig_ManForEachObjVec( p->vPis, p->pAig, pObj, i ) { iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) ); assert( iVecId > 0 ); for ( f = 0; f <= iFrame; f++ ) { iSatId = Vec_IntEntry( p->vVec2Var, iVecId * p->nFrames + f ); if ( iSatId == 0 ) continue; assert( iSatId > 0 ); if ( sat_solver_var_value(p->pSat, iSatId) ) Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + i ); } } Aig_ManForEachObjVec( p->vPPis, p->pAig, pObj, i ) { iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) ); assert( iVecId > 0 ); for ( f = 0; f <= iFrame; f++ ) { iSatId = Vec_IntEntry( p->vVec2Var, iVecId * p->nFrames + f ); if ( iSatId == 0 ) continue; assert( iSatId > 0 ); if ( sat_solver_var_value(p->pSat, iSatId) ) Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + Vec_IntSize(p->vPis) + i ); } } return pCex; } /**Function************************************************************* Synopsis [Prints current abstraction statistics.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_Gla1PrintAbstr( Aig_Gla1Man_t * p, int f, int r, int v, int c ) { if ( r == 0 ) printf( "== %3d ==", f ); else printf( " " ); printf( " %4d PI =%6d PPI =%6d FF =%6d Node =%6d Var =%7d Conf =%6d\n", r, Vec_IntSize(p->vPis), Vec_IntSize(p->vPPis), Vec_IntSize(p->vFlops), Vec_IntSize(p->vNodes), v, c ); } /**Function************************************************************* Synopsis [Prints current abstraction statistics.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_Gla1ExtendIncluded( Aig_Gla1Man_t * p ) { Aig_Obj_t * pObj; int i, k; Aig_ManForEachNode( p->pAig, pObj, i ) { if ( !Vec_IntEntry( p->vIncluded, i ) ) continue; Cnf_ComputeClauses( p->pAig, pObj, p->vLeaves, p->vVolume, NULL, p->vCover, p->vNodes ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vVolume, pObj, k ) { assert( Aig_ObjId(pObj) <= i ); Vec_IntWriteEntry( p->vIncluded, Aig_ObjId(pObj), 1 ); } } } /**Function************************************************************* Synopsis [Performs gate-level localization abstraction.] Description [Returns array of objects included in the abstraction. This array may contain only const1, flop outputs, and internal nodes, that is, objects that should have clauses added to the SAT solver.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Aig_Gla1ManPerform( Aig_Man_t * pAig, Vec_Int_t * vGateClassesOld, int nStart, int nFramesMax, int nConfLimit, int TimeLimit, int fNaiveCnf, int fVerbose, int * piFrame ) { Vec_Int_t * vResult = NULL; Aig_Gla1Man_t * p; Aig_Man_t * pAbs; Aig_Obj_t * pObj; Abc_Cex_t * pCex; Vec_Int_t * vPPiRefine; int f, g, r, i, iSatVar, Lit, Entry, RetValue; int nConfBef, nConfAft; clock_t clk, clkTotal = clock(); clock_t nTimeToStop = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + clock(): 0; assert( Saig_ManPoNum(pAig) == 1 ); if ( nFramesMax == 0 ) nFramesMax = ABC_INFINITY; if ( fVerbose ) { if ( TimeLimit ) printf( "Abstracting from frame %d to frame %d with timeout %d sec.\n", nStart, nFramesMax, TimeLimit ); else printf( "Abstracting from frame %d to frame %d with no timeout.\n", nStart, nFramesMax ); } // start the solver p = Aig_Gla1ManStart( pAig, vGateClassesOld, fNaiveCnf ); p->nFramesMax = nFramesMax; p->nConfLimit = nConfLimit; p->fVerbose = fVerbose; // include constant node Vec_IntWriteEntry( p->vIncluded, 0, 1 ); Aig_Gla1FetchVecId( p, Aig_ManConst1(pAig) ); // set runtime limit if ( TimeLimit ) sat_solver_set_runtime_limit( p->pSat, nTimeToStop ); // iterate over the timeframes for ( f = 0; f < nFramesMax; f++ ) { // initialize abstraction in this timeframe Aig_ManForEachObjVec( p->vAssigned, pAig, pObj, i ) if ( Vec_IntEntry(p->vIncluded, Aig_ObjId(pObj)) ) if ( !Aig_Gla1ObjAddToSolver( p, pObj, f ) ) printf( "Error! SAT solver became UNSAT.\n" ); // skip checking if we are not supposed to if ( f < nStart ) continue; // create output literal to represent property failure pObj = Aig_ManCo( pAig, 0 ); iSatVar = Aig_Gla1FetchVar( p, Aig_ObjFanin0(pObj), f ); Lit = toLitCond( iSatVar, Aig_ObjFaninC0(pObj) ); // try solving the abstraction Aig_Gla1CollectAbstr( p ); for ( r = 0; r < ABC_INFINITY; r++ ) { // try to find a counter-example clk = clock(); nConfBef = p->pSat->stats.conflicts; RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); nConfAft = p->pSat->stats.conflicts; p->timeSat += clock() - clk; if ( RetValue != l_True ) { if ( fVerbose ) { if ( r == 0 ) printf( "== %3d ==", f ); else printf( " " ); if ( TimeLimit && clock() > nTimeToStop ) printf( " SAT solver timed out after %d seconds.\n", TimeLimit ); else if ( RetValue != l_False ) printf( " SAT solver returned UNDECIDED after %5d conflicts.\n", nConfAft - nConfBef ); else { printf( " SAT solver returned UNSAT after %5d conflicts. ", nConfAft - nConfBef ); Abc_PrintTime( 1, "Total time", clock() - clkTotal ); } } break; } clk = clock(); // derive abstraction pAbs = Aig_Gla1DeriveAbs( p ); // derive counter-example pCex = Aig_Gla1DeriveCex( p, f ); // verify the counter-example RetValue = Saig_ManVerifyCex( pAbs, pCex ); if ( RetValue == 0 ) printf( "Error! CEX is invalid.\n" ); // perform refinement vPPiRefine = Saig_ManCbaFilterInputs( pAbs, Vec_IntSize(p->vPis), pCex, 0 ); Vec_IntForEachEntry( vPPiRefine, Entry, i ) { pObj = Aig_ManObj( pAig, Vec_IntEntry(p->vPPis, Entry) ); assert( Aig_ObjIsNode(pObj) || Saig_ObjIsLo(p->pAig, pObj) ); assert( Vec_IntEntry( p->vIncluded, Aig_ObjId(pObj) ) == 0 ); Vec_IntWriteEntry( p->vIncluded, Aig_ObjId(pObj), 1 ); for ( g = 0; g <= f; g++ ) if ( !Aig_Gla1ObjAddToSolver( p, pObj, g ) ) printf( "Error! SAT solver became UNSAT.\n" ); } if ( Vec_IntSize(vPPiRefine) == 0 ) { Vec_IntFreeP( &p->vIncluded ); Vec_IntFree( vPPiRefine ); Aig_ManStop( pAbs ); Abc_CexFree( pCex ); break; } Vec_IntFree( vPPiRefine ); Aig_ManStop( pAbs ); Abc_CexFree( pCex ); p->timeRef += clock() - clk; // prepare abstraction Aig_Gla1CollectAbstr( p ); if ( fVerbose ) Aig_Gla1PrintAbstr( p, f, r, p->pSat->size, nConfAft - nConfBef ); } if ( RetValue != l_False ) break; } p->timeTotal = clock() - clkTotal; if ( f == nFramesMax ) printf( "Finished %d frames without exceeding conflict limit (%d).\n", f, nConfLimit ); else if ( p->vIncluded == NULL ) printf( "The problem is SAT in frame %d. The CEX is currently not produced.\n", f ); else printf( "Ran out of conflict limit (%d) at frame %d.\n", nConfLimit, f ); *piFrame = f; // print stats if ( fVerbose ) { ABC_PRTP( "Sat ", p->timeSat, p->timeTotal ); ABC_PRTP( "Ref ", p->timeRef, p->timeTotal ); ABC_PRTP( "Total ", p->timeTotal, p->timeTotal ); } // prepare return value if ( !fNaiveCnf && p->vIncluded ) Aig_Gla1ExtendIncluded( p ); vResult = p->vIncluded; p->vIncluded = NULL; Aig_Gla1ManStop( p ); return vResult; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigGlaPba.c000066400000000000000000000443051477524141600166160ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigGlaPba.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Gate level abstraction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigGlaPba.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "sat/bsat/satSolver.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Aig_Gla2Man_t_ Aig_Gla2Man_t; struct Aig_Gla2Man_t_ { // user data Aig_Man_t * pAig; int nStart; int nFramesMax; int fVerbose; // unrolling Vec_Int_t * vObj2Vec; // maps obj ID into its vec ID Vec_Int_t * vVec2Var; // maps vec ID into its sat Var (nFrames per vec ID) Vec_Int_t * vVar2Inf; // maps sat Var into its frame and obj ID // clause mapping Vec_Int_t * vCla2Obj; // maps clause into its root object Vec_Int_t * vCla2Fra; // maps clause into its frame Vec_Int_t * vVec2Use; // maps vec ID into its used frames (nFrames per vec ID) // SAT solver sat_solver * pSat; // statistics clock_t timePre; clock_t timeSat; clock_t timeTotal; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Adds constant to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_Gla2AddConst( sat_solver * pSat, int iVar, int fCompl ) { lit Lit = toLitCond( iVar, fCompl ); if ( !sat_solver_addclause( pSat, &Lit, &Lit + 1 ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Adds buffer to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_Gla2AddBuffer( sat_solver * pSat, int iVar0, int iVar1, int fCompl ) { lit Lits[2]; Lits[0] = toLitCond( iVar0, 0 ); Lits[1] = toLitCond( iVar1, !fCompl ); if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) return 0; Lits[0] = toLitCond( iVar0, 1 ); Lits[1] = toLitCond( iVar1, fCompl ); if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Adds buffer to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_Gla2AddNode( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 ) { lit Lits[3]; Lits[0] = toLitCond( iVar, 1 ); Lits[1] = toLitCond( iVar0, fCompl0 ); if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) return 0; Lits[0] = toLitCond( iVar, 1 ); Lits[1] = toLitCond( iVar1, fCompl1 ); if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) return 0; Lits[0] = toLitCond( iVar, 0 ); Lits[1] = toLitCond( iVar0, !fCompl0 ); Lits[2] = toLitCond( iVar1, !fCompl1 ); if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Finds existing SAT variable or creates a new one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_Gla2FetchVar( Aig_Gla2Man_t * p, Aig_Obj_t * pObj, int k ) { int i, iVecId, iSatVar; assert( k < p->nFramesMax ); iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) ); if ( iVecId == 0 ) { iVecId = Vec_IntSize( p->vVec2Var ) / p->nFramesMax; for ( i = 0; i < p->nFramesMax; i++ ) Vec_IntPush( p->vVec2Var, 0 ); Vec_IntWriteEntry( p->vObj2Vec, Aig_ObjId(pObj), iVecId ); } iSatVar = Vec_IntEntry( p->vVec2Var, iVecId * p->nFramesMax + k ); if ( iSatVar == 0 ) { iSatVar = Vec_IntSize( p->vVar2Inf ) / 2; Vec_IntPush( p->vVar2Inf, Aig_ObjId(pObj) ); Vec_IntPush( p->vVar2Inf, k ); Vec_IntWriteEntry( p->vVec2Var, iVecId * p->nFramesMax + k, iSatVar ); } return iSatVar; } /**Function************************************************************* Synopsis [Assigns variables to the AIG nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_Gla2AssignVars_rec( Aig_Gla2Man_t * p, Aig_Obj_t * pObj, int f ) { int nVars = Vec_IntSize(p->vVar2Inf); Aig_Gla2FetchVar( p, pObj, f ); if ( nVars == Vec_IntSize(p->vVar2Inf) ) return; if ( Aig_ObjIsConst1(pObj) ) return; if ( Saig_ObjIsPo( p->pAig, pObj ) ) { Aig_Gla2AssignVars_rec( p, Aig_ObjFanin0(pObj), f ); return; } if ( Aig_ObjIsCi( pObj ) ) { if ( Saig_ObjIsLo(p->pAig, pObj) && f > 0 ) Aig_Gla2AssignVars_rec( p, Aig_ObjFanin0( Saig_ObjLoToLi(p->pAig, pObj) ), f-1 ); return; } assert( Aig_ObjIsNode(pObj) ); Aig_Gla2AssignVars_rec( p, Aig_ObjFanin0(pObj), f ); Aig_Gla2AssignVars_rec( p, Aig_ObjFanin1(pObj), f ); } /**Function************************************************************* Synopsis [Creates SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_Gla2CreateSatSolver( Aig_Gla2Man_t * p ) { Vec_Int_t * vPoLits; Aig_Obj_t * pObj; int i, f, ObjId, nVars, RetValue = 1; // assign variables for ( f = p->nFramesMax - 1; f >= 0; f-- ) // for ( f = 0; f < p->nFramesMax; f++ ) Aig_Gla2AssignVars_rec( p, Aig_ManCo(p->pAig, 0), f ); // create SAT solver p->pSat = sat_solver_new(); sat_solver_store_alloc( p->pSat ); sat_solver_setnvars( p->pSat, Vec_IntSize(p->vVar2Inf)/2 ); // add clauses nVars = Vec_IntSize( p->vVar2Inf ); Vec_IntForEachEntryDouble( p->vVar2Inf, ObjId, f, i ) { if ( ObjId == -1 ) continue; pObj = Aig_ManObj( p->pAig, ObjId ); if ( Aig_ObjIsNode(pObj) ) { RetValue &= Aig_Gla2AddNode( p->pSat, Aig_Gla2FetchVar(p, pObj, f), Aig_Gla2FetchVar(p, Aig_ObjFanin0(pObj), f), Aig_Gla2FetchVar(p, Aig_ObjFanin1(pObj), f), Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Fra, f ); Vec_IntPush( p->vCla2Fra, f ); Vec_IntPush( p->vCla2Fra, f ); } else if ( Saig_ObjIsLo(p->pAig, pObj) ) { if ( f == 0 ) { RetValue &= Aig_Gla2AddConst( p->pSat, Aig_Gla2FetchVar(p, pObj, f), 1 ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Fra, f ); } else { Aig_Obj_t * pObjLi = Saig_ObjLoToLi(p->pAig, pObj); RetValue &= Aig_Gla2AddBuffer( p->pSat, Aig_Gla2FetchVar(p, pObj, f), Aig_Gla2FetchVar(p, Aig_ObjFanin0(pObjLi), f-1), Aig_ObjFaninC0(pObjLi) ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Fra, f ); Vec_IntPush( p->vCla2Fra, f ); } } else if ( Saig_ObjIsPo(p->pAig, pObj) ) { RetValue &= Aig_Gla2AddBuffer( p->pSat, Aig_Gla2FetchVar(p, pObj, f), Aig_Gla2FetchVar(p, Aig_ObjFanin0(pObj), f), Aig_ObjFaninC0(pObj) ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Fra, f ); Vec_IntPush( p->vCla2Fra, f ); } else if ( Aig_ObjIsConst1(pObj) ) { RetValue &= Aig_Gla2AddConst( p->pSat, Aig_Gla2FetchVar(p, pObj, f), 0 ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Fra, f ); } else assert( Saig_ObjIsPi(p->pAig, pObj) ); } // add output clause vPoLits = Vec_IntAlloc( p->nFramesMax ); for ( f = p->nStart; f < p->nFramesMax; f++ ) Vec_IntPush( vPoLits, 2 * Aig_Gla2FetchVar(p, Aig_ManCo(p->pAig, 0), f) ); RetValue &= sat_solver_addclause( p->pSat, Vec_IntArray(vPoLits), Vec_IntArray(vPoLits) + Vec_IntSize(vPoLits) ); Vec_IntFree( vPoLits ); Vec_IntPush( p->vCla2Obj, 0 ); Vec_IntPush( p->vCla2Fra, 0 ); assert( Vec_IntSize(p->vCla2Fra) == Vec_IntSize(p->vCla2Obj) ); assert( nVars == Vec_IntSize(p->vVar2Inf) ); assert( ((Sto_Man_t *)p->pSat->pStore)->nClauses == Vec_IntSize(p->vCla2Obj) ); // Sto_ManDumpClauses( ((Sto_Man_t *)p->pSat->pStore), "temp_sto.cnf" ); sat_solver_store_mark_roots( p->pSat ); if ( p->fVerbose ) printf( "The resulting SAT problem contains %d variables and %d clauses.\n", p->pSat->size, p->pSat->stats.clauses ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Gla2Man_t * Aig_Gla2ManStart( Aig_Man_t * pAig, int nStart, int nFramesMax, int fVerbose ) { Aig_Gla2Man_t * p; int i; p = ABC_CALLOC( Aig_Gla2Man_t, 1 ); p->pAig = pAig; p->vObj2Vec = Vec_IntStart( Aig_ManObjNumMax(pAig) ); p->vVec2Var = Vec_IntAlloc( 1 << 20 ); p->vVar2Inf = Vec_IntAlloc( 1 << 20 ); p->vCla2Obj = Vec_IntAlloc( 1 << 20 ); p->vCla2Fra = Vec_IntAlloc( 1 << 20 ); // skip first vector ID p->nStart = nStart; p->nFramesMax = nFramesMax; p->fVerbose = fVerbose; for ( i = 0; i < p->nFramesMax; i++ ) Vec_IntPush( p->vVec2Var, -1 ); // skip first SAT variable Vec_IntPush( p->vVar2Inf, -1 ); Vec_IntPush( p->vVar2Inf, -1 ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_Gla2ManStop( Aig_Gla2Man_t * p ) { Vec_IntFreeP( &p->vObj2Vec ); Vec_IntFreeP( &p->vVec2Var ); Vec_IntFreeP( &p->vVar2Inf ); Vec_IntFreeP( &p->vCla2Obj ); Vec_IntFreeP( &p->vCla2Fra ); Vec_IntFreeP( &p->vVec2Use ); if ( p->pSat ) sat_solver_delete( p->pSat ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Finds the set of clauses involved in the UNSAT core.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_AbsSolverUnsatCore( sat_solver * pSat, int nConfMax, int fVerbose, int * piRetValue ) { Vec_Int_t * vCore; void * pSatCnf; Intp_Man_t * pManProof; int RetValue; clock_t clk = clock(); if ( piRetValue ) *piRetValue = -1; // solve the problem RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue == l_Undef ) { printf( "Conflict limit is reached.\n" ); return NULL; } if ( RetValue == l_True ) { printf( "The BMC problem is SAT.\n" ); if ( piRetValue ) *piRetValue = 0; return NULL; } if ( fVerbose ) { printf( "SAT solver returned UNSAT after %7d conflicts. ", (int)pSat->stats.conflicts ); Abc_PrintTime( 1, "Time", clock() - clk ); } assert( RetValue == l_False ); pSatCnf = sat_solver_store_release( pSat ); // derive the UNSAT core clk = clock(); pManProof = Intp_ManAlloc(); vCore = (Vec_Int_t *)Intp_ManUnsatCore( pManProof, (Sto_Man_t *)pSatCnf, 0, 0 ); Intp_ManFree( pManProof ); if ( fVerbose ) { printf( "SAT core contains %8d clauses (out of %8d). ", Vec_IntSize(vCore), sat_solver_nclauses(pSat) ); Abc_PrintTime( 1, "Time", clock() - clk ); } Sto_ManFree( (Sto_Man_t *)pSatCnf ); return vCore; } /**Function************************************************************* Synopsis [Collects abstracted objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Aig_Gla2ManCollect( Aig_Gla2Man_t * p, Vec_Int_t * vCore ) { Vec_Int_t * vResult; Aig_Obj_t * pObj; int i, ClaId, iVecId; // p->vVec2Use = Vec_IntStart( Vec_IntSize(p->vVec2Var) ); vResult = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); Vec_IntWriteEntry( vResult, 0, 1 ); // add const1 Vec_IntForEachEntry( vCore, ClaId, i ) { pObj = Aig_ManObj( p->pAig, Vec_IntEntry(p->vCla2Obj, ClaId) ); if ( Saig_ObjIsPi(p->pAig, pObj) || Saig_ObjIsPo(p->pAig, pObj) || Aig_ObjIsConst1(pObj) ) continue; assert( Saig_ObjIsLo(p->pAig, pObj) || Aig_ObjIsNode(pObj) ); Vec_IntWriteEntry( vResult, Aig_ObjId(pObj), 1 ); /* // add flop inputs with multiple fanouts if ( Saig_ObjIsLo(p->pAig, pObj) ) { Aig_Obj_t * pObjLi = Saig_ObjLoToLi(p->pAig, pObj); if ( !Saig_ObjIsPi(p->pAig, Aig_ObjFanin0(pObjLi)) ) // if ( Aig_ObjRefs( Aig_ObjFanin0(pObjLi) ) > 1 ) Vec_IntWriteEntry( vResult, Aig_ObjFaninId0(pObjLi), 1 ); } else { if ( !Saig_ObjIsPi(p->pAig, Aig_ObjFanin0(pObj)) ) Vec_IntWriteEntry( vResult, Aig_ObjFaninId0(pObj), 1 ); if ( !Saig_ObjIsPi(p->pAig, Aig_ObjFanin1(pObj)) ) Vec_IntWriteEntry( vResult, Aig_ObjFaninId1(pObj), 1 ); } */ if ( p->vVec2Use ) { iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) ); Vec_IntWriteEntry( p->vVec2Use, iVecId * p->nFramesMax + Vec_IntEntry(p->vCla2Fra, ClaId), 1 ); } } // printf( "Number of entries %d\n", Vec_IntCountPositive(vResult) ); // count the number of objects in each frame if ( p->vVec2Use ) { Vec_Int_t * vCounts = Vec_IntStart( p->nFramesMax ); int v, f, Entry, nVecIds = Vec_IntSize(p->vVec2Use) / p->nFramesMax; for ( f = 0; f < p->nFramesMax; f++ ) for ( v = 0; v < nVecIds; v++ ) if ( Vec_IntEntry( p->vVec2Use, v * p->nFramesMax + f ) ) Vec_IntAddToEntry( vCounts, f, 1 ); Vec_IntForEachEntry( vCounts, Entry, f ) printf( "%d ", Entry ); printf( "\n" ); Vec_IntFree( vCounts ); } return vResult; } /**Function************************************************************* Synopsis [Performs gate-level localization abstraction.] Description [Returns array of objects included in the abstraction. This array may contain only const1, flop outputs, and internal nodes, that is, objects that should have clauses added to the SAT solver.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Aig_Gla2ManPerform( Aig_Man_t * pAig, int nStart, int nFramesMax, int nConfLimit, int TimeLimit, int fSkipRand, int fVerbose ) { Aig_Gla2Man_t * p; Vec_Int_t * vCore, * vResult; clock_t nTimeToStop = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + clock(): 0; clock_t clk, clk2 = clock(); assert( Saig_ManPoNum(pAig) == 1 ); if ( fVerbose ) { if ( TimeLimit ) printf( "Abstracting from frame %d to frame %d with timeout %d sec.\n", nStart, nFramesMax, TimeLimit ); else printf( "Abstracting from frame %d to frame %d with no timeout.\n", nStart, nFramesMax ); } // start the solver clk = clock(); p = Aig_Gla2ManStart( pAig, nStart, nFramesMax, fVerbose ); if ( !Aig_Gla2CreateSatSolver( p ) ) { printf( "Error! SAT solver became UNSAT.\n" ); Aig_Gla2ManStop( p ); return NULL; } sat_solver_set_random( p->pSat, fSkipRand ); p->timePre += clock() - clk; // set runtime limit if ( TimeLimit ) sat_solver_set_runtime_limit( p->pSat, nTimeToStop ); // compute UNSAT core clk = clock(); vCore = Saig_AbsSolverUnsatCore( p->pSat, nConfLimit, fVerbose, NULL ); if ( vCore == NULL ) { Aig_Gla2ManStop( p ); return NULL; } p->timeSat += clock() - clk; p->timeTotal += clock() - clk2; // print stats if ( fVerbose ) { ABC_PRTP( "Pre ", p->timePre, p->timeTotal ); ABC_PRTP( "Sat ", p->timeSat, p->timeTotal ); ABC_PRTP( "Total ", p->timeTotal, p->timeTotal ); } // prepare return value vResult = Aig_Gla2ManCollect( p, vCore ); Vec_IntFree( vCore ); Aig_Gla2ManStop( p ); return vResult; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigGlaPba2.c000066400000000000000000000416001477524141600166730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigGlaPba.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Gate level abstraction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigGlaPba.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "sat/bsat/satSolver2.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Aig_Gla3Man_t_ Aig_Gla3Man_t; struct Aig_Gla3Man_t_ { // user data Aig_Man_t * pAig; int nStart; int nFramesMax; int fVerbose; // unrolling Vec_Int_t * vObj2Vec; // maps obj ID into its vec ID Vec_Int_t * vVec2Var; // maps vec ID into its sat Var (nFrames per vec ID) Vec_Int_t * vVar2Inf; // maps sat Var into its frame and obj ID // clause mapping Vec_Int_t * vCla2Obj; // maps clause into its root object Vec_Int_t * vCla2Fra; // maps clause into its frame Vec_Int_t * vVec2Use; // maps vec ID into its used frames (nFrames per vec ID) // SAT solver sat_solver2 * pSat; // statistics clock_t timePre; clock_t timeSat; clock_t timeTotal; }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #define ABC_CPS 1000 /**Function************************************************************* Synopsis [Adds constant to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_Gla3AddConst( sat_solver2 * pSat, int iVar, int fCompl ) { lit Lit = toLitCond( iVar, fCompl ); if ( !sat_solver2_addclause( pSat, &Lit, &Lit + 1, 0 ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Adds buffer to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_Gla3AddBuffer( sat_solver2 * pSat, int iVar0, int iVar1, int fCompl ) { lit Lits[2]; Lits[0] = toLitCond( iVar0, 0 ); Lits[1] = toLitCond( iVar1, !fCompl ); if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) ) return 0; Lits[0] = toLitCond( iVar0, 1 ); Lits[1] = toLitCond( iVar1, fCompl ); if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Adds buffer to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Aig_Gla3AddNode( sat_solver2 * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 ) { lit Lits[3]; Lits[0] = toLitCond( iVar, 1 ); Lits[1] = toLitCond( iVar0, fCompl0 ); if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) ) return 0; Lits[0] = toLitCond( iVar, 1 ); Lits[1] = toLitCond( iVar1, fCompl1 ); if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) ) return 0; Lits[0] = toLitCond( iVar, 0 ); Lits[1] = toLitCond( iVar0, !fCompl0 ); Lits[2] = toLitCond( iVar1, !fCompl1 ); if ( !sat_solver2_addclause( pSat, Lits, Lits + 3, 0 ) ) return 0; return 1; } /**Function************************************************************* Synopsis [Finds existing SAT variable or creates a new one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_Gla3FetchVar( Aig_Gla3Man_t * p, Aig_Obj_t * pObj, int k ) { int i, iVecId, iSatVar; assert( k < p->nFramesMax ); iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) ); if ( iVecId == 0 ) { iVecId = Vec_IntSize( p->vVec2Var ) / p->nFramesMax; for ( i = 0; i < p->nFramesMax; i++ ) Vec_IntPush( p->vVec2Var, 0 ); Vec_IntWriteEntry( p->vObj2Vec, Aig_ObjId(pObj), iVecId ); } iSatVar = Vec_IntEntry( p->vVec2Var, iVecId * p->nFramesMax + k ); if ( iSatVar == 0 ) { iSatVar = Vec_IntSize( p->vVar2Inf ) / 2; Vec_IntPush( p->vVar2Inf, Aig_ObjId(pObj) ); Vec_IntPush( p->vVar2Inf, k ); Vec_IntWriteEntry( p->vVec2Var, iVecId * p->nFramesMax + k, iSatVar ); } return iSatVar; } /**Function************************************************************* Synopsis [Assigns variables to the AIG nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_Gla3AssignVars_rec( Aig_Gla3Man_t * p, Aig_Obj_t * pObj, int f ) { int nVars = Vec_IntSize(p->vVar2Inf); Aig_Gla3FetchVar( p, pObj, f ); if ( nVars == Vec_IntSize(p->vVar2Inf) ) return; if ( Aig_ObjIsConst1(pObj) ) return; if ( Saig_ObjIsPo( p->pAig, pObj ) ) { Aig_Gla3AssignVars_rec( p, Aig_ObjFanin0(pObj), f ); return; } if ( Aig_ObjIsCi( pObj ) ) { if ( Saig_ObjIsLo(p->pAig, pObj) && f > 0 ) Aig_Gla3AssignVars_rec( p, Aig_ObjFanin0( Saig_ObjLoToLi(p->pAig, pObj) ), f-1 ); return; } assert( Aig_ObjIsNode(pObj) ); Aig_Gla3AssignVars_rec( p, Aig_ObjFanin0(pObj), f ); Aig_Gla3AssignVars_rec( p, Aig_ObjFanin1(pObj), f ); } /**Function************************************************************* Synopsis [Creates SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_Gla3CreateSatSolver( Aig_Gla3Man_t * p ) { Vec_Int_t * vPoLits; Aig_Obj_t * pObj; int i, f, ObjId, nVars, RetValue = 1; // assign variables for ( f = p->nFramesMax - 1; f >= 0; f-- ) Aig_Gla3AssignVars_rec( p, Aig_ManCo(p->pAig, 0), f ); // create SAT solver p->pSat = sat_solver2_new(); sat_solver2_setnvars( p->pSat, Vec_IntSize(p->vVar2Inf)/2 ); // add clauses nVars = Vec_IntSize( p->vVar2Inf ); Vec_IntForEachEntryDouble( p->vVar2Inf, ObjId, f, i ) { if ( ObjId == -1 ) continue; pObj = Aig_ManObj( p->pAig, ObjId ); if ( Aig_ObjIsNode(pObj) ) { Aig_Gla3AddNode( p->pSat, Aig_Gla3FetchVar(p, pObj, f), Aig_Gla3FetchVar(p, Aig_ObjFanin0(pObj), f), Aig_Gla3FetchVar(p, Aig_ObjFanin1(pObj), f), Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Fra, f ); Vec_IntPush( p->vCla2Fra, f ); Vec_IntPush( p->vCla2Fra, f ); } else if ( Saig_ObjIsLo(p->pAig, pObj) ) { if ( f == 0 ) { Aig_Gla3AddConst( p->pSat, Aig_Gla3FetchVar(p, pObj, f), 1 ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Fra, f ); } else { Aig_Obj_t * pObjLi = Saig_ObjLoToLi(p->pAig, pObj); Aig_Gla3AddBuffer( p->pSat, Aig_Gla3FetchVar(p, pObj, f), Aig_Gla3FetchVar(p, Aig_ObjFanin0(pObjLi), f-1), Aig_ObjFaninC0(pObjLi) ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Fra, f ); Vec_IntPush( p->vCla2Fra, f ); } } else if ( Saig_ObjIsPo(p->pAig, pObj) ) { Aig_Gla3AddBuffer( p->pSat, Aig_Gla3FetchVar(p, pObj, f), Aig_Gla3FetchVar(p, Aig_ObjFanin0(pObj), f), Aig_ObjFaninC0(pObj) ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Fra, f ); Vec_IntPush( p->vCla2Fra, f ); } else if ( Aig_ObjIsConst1(pObj) ) { Aig_Gla3AddConst( p->pSat, Aig_Gla3FetchVar(p, pObj, f), 0 ); Vec_IntPush( p->vCla2Obj, ObjId ); Vec_IntPush( p->vCla2Fra, f ); } else assert( Saig_ObjIsPi(p->pAig, pObj) ); } // add output clause vPoLits = Vec_IntAlloc( p->nFramesMax ); for ( f = p->nStart; f < p->nFramesMax; f++ ) Vec_IntPush( vPoLits, 2 * Aig_Gla3FetchVar(p, Aig_ManCo(p->pAig, 0), f) ); sat_solver2_addclause( p->pSat, Vec_IntArray(vPoLits), Vec_IntArray(vPoLits) + Vec_IntSize(vPoLits), 0 ); Vec_IntFree( vPoLits ); Vec_IntPush( p->vCla2Obj, 0 ); Vec_IntPush( p->vCla2Fra, 0 ); assert( Vec_IntSize(p->vCla2Fra) == Vec_IntSize(p->vCla2Obj) ); assert( nVars == Vec_IntSize(p->vVar2Inf) ); assert( Vec_IntSize(p->vCla2Obj) == (int)p->pSat->stats.clauses+1 ); if ( p->fVerbose ) printf( "The resulting SAT problem contains %d variables and %d clauses.\n", p->pSat->size, p->pSat->stats.clauses ); return RetValue; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Gla3Man_t * Aig_Gla3ManStart( Aig_Man_t * pAig, int nStart, int nFramesMax, int fVerbose ) { Aig_Gla3Man_t * p; int i; p = ABC_CALLOC( Aig_Gla3Man_t, 1 ); p->pAig = pAig; p->vObj2Vec = Vec_IntStart( Aig_ManObjNumMax(pAig) ); p->vVec2Var = Vec_IntAlloc( 1 << 20 ); p->vVar2Inf = Vec_IntAlloc( 1 << 20 ); p->vCla2Obj = Vec_IntAlloc( 1 << 20 ); Vec_IntPush( p->vCla2Obj, -1 ); p->vCla2Fra = Vec_IntAlloc( 1 << 20 ); Vec_IntPush( p->vCla2Fra, -1 ); // skip first vector ID p->nStart = nStart; p->nFramesMax = nFramesMax; p->fVerbose = fVerbose; for ( i = 0; i < p->nFramesMax; i++ ) Vec_IntPush( p->vVec2Var, -1 ); // skip first SAT variable Vec_IntPush( p->vVar2Inf, -1 ); Vec_IntPush( p->vVar2Inf, -1 ); return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_Gla3ManStop( Aig_Gla3Man_t * p ) { Vec_IntFreeP( &p->vObj2Vec ); Vec_IntFreeP( &p->vVec2Var ); Vec_IntFreeP( &p->vVar2Inf ); Vec_IntFreeP( &p->vCla2Obj ); Vec_IntFreeP( &p->vCla2Fra ); Vec_IntFreeP( &p->vVec2Use ); if ( p->pSat ) sat_solver2_delete( p->pSat ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Finds the set of clauses involved in the UNSAT core.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Aig_Gla3ManUnsatCore( sat_solver2 * pSat, int nConfMax, int fVerbose, int * piRetValue ) { Vec_Int_t * vCore; int RetValue; clock_t clk = clock(); if ( piRetValue ) *piRetValue = -1; // solve the problem RetValue = sat_solver2_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue == l_Undef ) { printf( "Conflict limit is reached.\n" ); return NULL; } if ( RetValue == l_True ) { printf( "The BMC problem is SAT.\n" ); if ( piRetValue ) *piRetValue = 0; return NULL; } if ( fVerbose ) { printf( "SAT solver returned UNSAT after %7d conflicts. ", (int)pSat->stats.conflicts ); Abc_PrintTime( 1, "Time", clock() - clk ); } assert( RetValue == l_False ); // derive the UNSAT core clk = clock(); vCore = (Vec_Int_t *)Sat_ProofCore( pSat ); if ( fVerbose ) { printf( "SAT core contains %8d clauses (out of %8d). ", Vec_IntSize(vCore), sat_solver2_nclauses(pSat) ); Abc_PrintTime( 1, "Time", clock() - clk ); } return vCore; } /**Function************************************************************* Synopsis [Collects abstracted objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Aig_Gla3ManCollect( Aig_Gla3Man_t * p, Vec_Int_t * vCore ) { Vec_Int_t * vResult; Aig_Obj_t * pObj; int i, ClaId, iVecId; // p->vVec2Use = Vec_IntStart( Vec_IntSize(p->vVec2Var) ); vResult = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); Vec_IntWriteEntry( vResult, 0, 1 ); // add const1 Vec_IntForEachEntry( vCore, ClaId, i ) { pObj = Aig_ManObj( p->pAig, Vec_IntEntry(p->vCla2Obj, ClaId) ); if ( Saig_ObjIsPi(p->pAig, pObj) || Saig_ObjIsPo(p->pAig, pObj) || Aig_ObjIsConst1(pObj) ) continue; assert( Saig_ObjIsLo(p->pAig, pObj) || Aig_ObjIsNode(pObj) ); Vec_IntWriteEntry( vResult, Aig_ObjId(pObj), 1 ); if ( p->vVec2Use ) { iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) ); Vec_IntWriteEntry( p->vVec2Use, iVecId * p->nFramesMax + Vec_IntEntry(p->vCla2Fra, ClaId), 1 ); } } // count the number of objects in each frame if ( p->vVec2Use ) { Vec_Int_t * vCounts = Vec_IntStart( p->nFramesMax ); int v, f, Entry, nVecIds = Vec_IntSize(p->vVec2Use) / p->nFramesMax; for ( f = 0; f < p->nFramesMax; f++ ) for ( v = 0; v < nVecIds; v++ ) if ( Vec_IntEntry( p->vVec2Use, v * p->nFramesMax + f ) ) Vec_IntAddToEntry( vCounts, f, 1 ); Vec_IntForEachEntry( vCounts, Entry, f ) printf( "%d ", Entry ); printf( "\n" ); Vec_IntFree( vCounts ); } return vResult; } /**Function************************************************************* Synopsis [Performs gate-level localization abstraction.] Description [Returns array of objects included in the abstraction. This array may contain only const1, flop outputs, and internal nodes, that is, objects that should have clauses added to the SAT solver.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Aig_Gla3ManPerform( Aig_Man_t * pAig, int nStart, int nFramesMax, int nConfLimit, int TimeLimit, int fSkipRand, int fVerbose ) { Aig_Gla3Man_t * p; Vec_Int_t * vCore, * vResult; clock_t clk, clk2 = clock(); assert( Saig_ManPoNum(pAig) == 1 ); if ( fVerbose ) { if ( TimeLimit ) printf( "Abstracting from frame %d to frame %d with timeout %d sec.\n", nStart, nFramesMax, TimeLimit ); else printf( "Abstracting from frame %d to frame %d with no timeout.\n", nStart, nFramesMax ); } // start the solver clk = clock(); p = Aig_Gla3ManStart( pAig, nStart, nFramesMax, fVerbose ); if ( !Aig_Gla3CreateSatSolver( p ) ) { printf( "Error! SAT solver became UNSAT.\n" ); Aig_Gla3ManStop( p ); return NULL; } p->pSat->fNotUseRandom = fSkipRand; p->timePre += clock() - clk; // set runtime limit if ( TimeLimit ) sat_solver2_set_runtime_limit( p->pSat, TimeLimit * CLOCKS_PER_SEC + clock() ); // compute UNSAT core clk = clock(); vCore = Aig_Gla3ManUnsatCore( p->pSat, nConfLimit, fVerbose, NULL ); if ( vCore == NULL ) { Aig_Gla3ManStop( p ); return NULL; } p->timeSat += clock() - clk; p->timeTotal += clock() - clk2; // print stats if ( fVerbose ) { ABC_PRTP( "Pre ", p->timePre, p->timeTotal ); ABC_PRTP( "Sat ", p->timeSat, p->timeTotal ); ABC_PRTP( "Total ", p->timeTotal, p->timeTotal ); } // prepare return value vResult = Aig_Gla3ManCollect( p, vCore ); Vec_IntFree( vCore ); Aig_Gla3ManStop( p ); return vResult; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigInd.c000066400000000000000000000344161477524141600162040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigLoc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [K-step induction for one property only.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigLoc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns 1 if two state are equal.] Description [Array vState contains indexes of CNF variables for each flop in the first N time frames (0 < i < k, i < N, k < N).] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManStatesAreEqual( sat_solver * pSat, Vec_Int_t * vState, int nRegs, int i, int k ) { int * pStateI = (int *)Vec_IntArray(vState) + nRegs * i; int * pStateK = (int *)Vec_IntArray(vState) + nRegs * k; int v; assert( i && k && i < k ); assert( nRegs * k <= Vec_IntSize(vState) ); // check if the states are available for ( v = 0; v < nRegs; v++ ) if ( pStateI[v] >= 0 && pStateK[v] == -1 ) return 0; /* printf( "\nchecking uniqueness\n" ); printf( "%3d : ", i ); for ( v = 0; v < nRegs; v++ ) printf( "%d", sat_solver_var_value(pSat, pStateI[v]) ); printf( "\n" ); printf( "%3d : ", k ); for ( v = 0; v < nRegs; v++ ) printf( "%d", sat_solver_var_value(pSat, pStateK[v]) ); printf( "\n" ); */ for ( v = 0; v < nRegs; v++ ) if ( pStateI[v] >= 0 ) { if ( sat_solver_var_value(pSat, pStateI[v]) != sat_solver_var_value(pSat, pStateK[v]) ) return 0; } return 1; } /**Function************************************************************* Synopsis [Add uniqueness constraint.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManAddUniqueness( sat_solver * pSat, Vec_Int_t * vState, int nRegs, int i, int k, int * pnSatVarNum, int * pnClauses, int fVerbose ) { int * pStateI = (int *)Vec_IntArray(vState) + nRegs * i; int * pStateK = (int *)Vec_IntArray(vState) + nRegs * k; int v, iVars, nSatVarsOld, RetValue, * pClause; assert( i && k && i < k ); assert( nRegs * k <= Vec_IntSize(vState) ); // check if the states are available for ( v = 0; v < nRegs; v++ ) if ( pStateI[v] >= 0 && pStateK[v] == -1 ) { if ( fVerbose ) printf( "Cannot constrain an incomplete state.\n" ); return 0; } // add XORs nSatVarsOld = *pnSatVarNum; for ( v = 0; v < nRegs; v++ ) if ( pStateI[v] >= 0 ) { *pnClauses += 4; RetValue = Cnf_DataAddXorClause( pSat, pStateI[v], pStateK[v], (*pnSatVarNum)++ ); if ( RetValue == 0 ) { if ( fVerbose ) printf( "SAT solver became UNSAT after adding a uniqueness constraint.\n" ); return 1; } } // add OR clause (*pnClauses)++; iVars = 0; pClause = ABC_ALLOC( int, nRegs ); for ( v = nSatVarsOld; v < *pnSatVarNum; v++ ) pClause[iVars++] = toLitCond( v, 0 ); assert( iVars <= nRegs ); RetValue = sat_solver_addclause( pSat, pClause, pClause + iVars ); ABC_FREE( pClause ); if ( RetValue == 0 ) { if ( fVerbose ) printf( "SAT solver became UNSAT after adding a uniqueness constraint.\n" ); return 1; } return 0; } /**Function************************************************************* Synopsis [Performs induction by unrolling timeframes backward.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManInduction( Aig_Man_t * p, int nTimeOut, int nFramesMax, int nConfMax, int fUnique, int fUniqueAll, int fGetCex, int fVerbose, int fVeryVerbose ) { sat_solver * pSat; Aig_Man_t * pAigPart = NULL; Cnf_Dat_t * pCnfPart = NULL; Vec_Int_t * vTopVarNums, * vState, * vTopVarIds = NULL; Vec_Ptr_t * vTop, * vBot; Aig_Obj_t * pObjPi, * pObjPiCopy, * pObjPo; int i, k, f, Lits[2], status = -1, RetValue, nSatVarNum, nConfPrev; int nOldSize, iReg, iLast, fAdded, nConstrs = 0, nClauses = 0; abctime clk, nTimeToStop = nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock() : 0; assert( fUnique == 0 || fUniqueAll == 0 ); assert( Saig_ManPoNum(p) == 1 ); Aig_ManSetCioIds( p ); // start the top by including the PO vBot = Vec_PtrAlloc( 100 ); vTop = Vec_PtrAlloc( 100 ); vState = Vec_IntAlloc( 1000 ); Vec_PtrPush( vTop, Aig_ManCo(p, 0) ); // start the array of CNF variables vTopVarNums = Vec_IntAlloc( 100 ); // start the solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, 1000 ); // set runtime limit if ( nTimeToStop ) sat_solver_set_runtime_limit( pSat, nTimeToStop ); // iterate backward unrolling RetValue = -1; nSatVarNum = 0; if ( fVerbose ) printf( "Induction parameters: FramesMax = %5d. ConflictMax = %6d.\n", nFramesMax, nConfMax ); for ( f = 0; ; f++ ) { if ( f > 0 ) { Aig_ManStop( pAigPart ); Cnf_DataFree( pCnfPart ); } clk = Abc_Clock(); // get the bottom Aig_SupportNodes( p, (Aig_Obj_t **)Vec_PtrArray(vTop), Vec_PtrSize(vTop), vBot ); // derive AIG for the part between top and bottom pAigPart = Aig_ManDupSimpleDfsPart( p, vBot, vTop ); // convert it into CNF pCnfPart = Cnf_Derive( pAigPart, Aig_ManCoNum(pAigPart) ); Cnf_DataLift( pCnfPart, nSatVarNum ); nSatVarNum += pCnfPart->nVars; nClauses += pCnfPart->nClauses; // remember top frame var IDs if ( fGetCex && vTopVarIds == NULL ) { vTopVarIds = Vec_IntStartFull( Aig_ManCiNum(p) ); Aig_ManForEachCi( p, pObjPi, i ) { if ( pObjPi->pData == NULL ) continue; pObjPiCopy = (Aig_Obj_t *)pObjPi->pData; assert( Aig_ObjIsCi(pObjPiCopy) ); if ( Saig_ObjIsPi(p, pObjPi) ) Vec_IntWriteEntry( vTopVarIds, Aig_ObjCioId(pObjPi) + Saig_ManRegNum(p), pCnfPart->pVarNums[Aig_ObjId(pObjPiCopy)] ); else if ( Saig_ObjIsLo(p, pObjPi) ) Vec_IntWriteEntry( vTopVarIds, Aig_ObjCioId(pObjPi) - Saig_ManPiNum(p), pCnfPart->pVarNums[Aig_ObjId(pObjPiCopy)] ); else assert( 0 ); } } // stitch variables of top and bot assert( Aig_ManCoNum(pAigPart)-1 == Vec_IntSize(vTopVarNums) ); Aig_ManForEachCo( pAigPart, pObjPo, i ) { if ( i == 0 ) { // do not perform inductive strengthening // if ( f > 0 ) // continue; // add topmost literal Lits[0] = toLitCond( pCnfPart->pVarNums[pObjPo->Id], f>0 ); if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) ) assert( 0 ); nClauses++; continue; } Lits[0] = toLitCond( Vec_IntEntry(vTopVarNums, i-1), 0 ); Lits[1] = toLitCond( pCnfPart->pVarNums[pObjPo->Id], 1 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); Lits[0] = toLitCond( Vec_IntEntry(vTopVarNums, i-1), 1 ); Lits[1] = toLitCond( pCnfPart->pVarNums[pObjPo->Id], 0 ); if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) assert( 0 ); nClauses += 2; } // add CNF to the SAT solver for ( i = 0; i < pCnfPart->nClauses; i++ ) if ( !sat_solver_addclause( pSat, pCnfPart->pClauses[i], pCnfPart->pClauses[i+1] ) ) break; if ( i < pCnfPart->nClauses ) { // printf( "SAT solver became UNSAT after adding clauses.\n" ); RetValue = 1; break; } // create new set of POs to derive new top Vec_PtrClear( vTop ); Vec_PtrPush( vTop, Aig_ManCo(p, 0) ); Vec_IntClear( vTopVarNums ); nOldSize = Vec_IntSize(vState); Vec_IntFillExtra( vState, nOldSize + Aig_ManRegNum(p), -1 ); Vec_PtrForEachEntry( Aig_Obj_t *, vBot, pObjPi, i ) { assert( Aig_ObjIsCi(pObjPi) ); if ( Saig_ObjIsLo(p, pObjPi) ) { pObjPiCopy = (Aig_Obj_t *)pObjPi->pData; assert( pObjPiCopy != NULL ); Vec_PtrPush( vTop, Saig_ObjLoToLi(p, pObjPi) ); Vec_IntPush( vTopVarNums, pCnfPart->pVarNums[pObjPiCopy->Id] ); iReg = pObjPi->CioId - Saig_ManPiNum(p); assert( iReg >= 0 && iReg < Aig_ManRegNum(p) ); Vec_IntWriteEntry( vState, nOldSize+iReg, pCnfPart->pVarNums[pObjPiCopy->Id] ); } } assert( Vec_IntSize(vState)%Aig_ManRegNum(p) == 0 ); iLast = Vec_IntSize(vState)/Aig_ManRegNum(p); if ( fUniqueAll ) { for ( i = 1; i < iLast-1; i++ ) { nConstrs++; if ( fVeryVerbose ) printf( "Adding constaint for state %2d and state %2d.\n", i, iLast-1 ); if ( Saig_ManAddUniqueness( pSat, vState, Aig_ManRegNum(p), i, iLast-1, &nSatVarNum, &nClauses, fVerbose ) ) break; } if ( i < iLast-1 ) { RetValue = 1; break; } } nextrun: fAdded = 0; // run the SAT solver nConfPrev = pSat->stats.conflicts; status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfMax, 0, 0, 0 ); if ( fVerbose ) { printf( "Frame %4d : PI =%5d. PO =%5d. AIG =%5d. Var =%7d. Clau =%7d. Conf =%7d. ", f, Aig_ManCiNum(pAigPart), Aig_ManCoNum(pAigPart), Aig_ManNodeNum(pAigPart), nSatVarNum, nClauses, (int)pSat->stats.conflicts-nConfPrev ); ABC_PRT( "Time", Abc_Clock() - clk ); } if ( status == l_Undef ) break; if ( status == l_False ) { RetValue = 1; break; } assert( status == l_True ); // the problem is SAT - add more clauses if ( fVeryVerbose ) { Vec_IntForEachEntry( vState, iReg, i ) { if ( i && (i % Aig_ManRegNum(p)) == 0 ) printf( "\n" ); if ( (i % Aig_ManRegNum(p)) == 0 ) printf( " State %3d : ", i/Aig_ManRegNum(p) ); printf( "%c", (iReg >= 0) ? ('0' + sat_solver_var_value(pSat, iReg)) : 'x' ); } printf( "\n" ); } if ( nFramesMax && f == nFramesMax - 1 ) { // derive counter-example assert( status == l_True ); if ( fGetCex ) { int VarNum, iBit = 0; Abc_Cex_t * pCex = Abc_CexAlloc( Aig_ManRegNum(p)-1, Saig_ManPiNum(p), 1 ); pCex->iFrame = 0; pCex->iPo = 0; Vec_IntForEachEntryStart( vTopVarIds, VarNum, i, 1 ) { if ( VarNum >= 0 && sat_solver_var_value( pSat, VarNum ) ) Abc_InfoSetBit( pCex->pData, iBit ); iBit++; } assert( iBit == pCex->nBits ); Abc_CexFree( p->pSeqModel ); p->pSeqModel = pCex; } break; } if ( fUnique ) { for ( i = 1; i < iLast; i++ ) { for ( k = i+1; k < iLast; k++ ) { if ( !Saig_ManStatesAreEqual( pSat, vState, Aig_ManRegNum(p), i, k ) ) continue; nConstrs++; fAdded = 1; if ( fVeryVerbose ) printf( "Adding constaint for state %2d and state %2d.\n", i, k ); if ( Saig_ManAddUniqueness( pSat, vState, Aig_ManRegNum(p), i, k, &nSatVarNum, &nClauses, fVerbose ) ) break; } if ( k < iLast ) break; } if ( i < iLast ) { RetValue = 1; break; } } if ( fAdded ) goto nextrun; } if ( fVerbose ) { if ( nTimeToStop && Abc_Clock() >= nTimeToStop ) printf( "Timeout (%d sec) was reached during iteration %d.\n", nTimeOut, f+1 ); 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 iterations and added %d uniqueness constraints.\n", f+1, nConstrs ); else printf( "Completed %d iterations.\n", f+1 ); } // cleanup sat_solver_delete( pSat ); Aig_ManStop( pAigPart ); Cnf_DataFree( pCnfPart ); Vec_IntFree( vTopVarNums ); Vec_PtrFree( vTop ); Vec_PtrFree( vBot ); Vec_IntFree( vState ); Vec_IntFreeP( &vTopVarIds ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigIoa.c000066400000000000000000000330641477524141600162000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigIoa.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Input/output for sequential AIGs using BLIF files.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigIoa.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Saig_ObjName( Aig_Man_t * p, Aig_Obj_t * pObj ) { static char Buffer[1000]; if ( Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(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", (unsigned char)Abc_Base10Log(Saig_ManPiNum(p)), Aig_ObjCioId(pObj) ); else if ( Saig_ObjIsPo(p, 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", (unsigned char)Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjCioId(pObj) - Saig_ManPiNum(p) ); else if ( Saig_ObjIsLi(p, pObj) ) sprintf( Buffer, "li%0*d", (unsigned char)Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjCioId(pObj) - Saig_ManPoNum(p) ); else assert( 0 ); return Buffer; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManDumpBlif( Aig_Man_t * p, char * pFileName ) { FILE * pFile; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i; if ( Aig_ManCoNum(p) == 0 ) { printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" ); return; } Aig_ManSetCioIds( p ); // write input file pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { printf( "Saig_ManDumpBlif(): Cannot open file for writing.\n" ); return; } fprintf( pFile, "# BLIF file written by procedure Saig_ManDumpBlif()\n" ); fprintf( pFile, "# If unedited, this file can be read by Saig_ManReadBlif()\n" ); fprintf( pFile, "# AIG stats: pi=%d po=%d reg=%d and=%d obj=%d maxid=%d\n", Saig_ManPiNum(p), Saig_ManPoNum(p), Saig_ManRegNum(p), Aig_ManNodeNum(p), Aig_ManObjNum(p), Aig_ManObjNumMax(p) ); fprintf( pFile, ".model %s\n", p->pName ); // write primary inputs fprintf( pFile, ".inputs" ); Aig_ManForEachPiSeq( p, pObj, i ) fprintf( pFile, " %s", Saig_ObjName(p, pObj) ); fprintf( pFile, "\n" ); // write primary outputs fprintf( pFile, ".outputs" ); Aig_ManForEachPoSeq( p, pObj, i ) fprintf( pFile, " %s", Saig_ObjName(p, pObj) ); fprintf( pFile, "\n" ); // write registers if ( Aig_ManRegNum(p) ) { Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) { fprintf( pFile, ".latch" ); fprintf( pFile, " %s", Saig_ObjName(p, pObjLi) ); fprintf( pFile, " %s", Saig_ObjName(p, pObjLo) ); fprintf( pFile, " 0\n" ); } } // check if constant is used if ( Aig_ObjRefs(Aig_ManConst1(p)) ) fprintf( pFile, ".names %s\n 1\n", Saig_ObjName(p, Aig_ManConst1(p)) ); // write the nodes in the DFS order Aig_ManForEachNode( p, pObj, i ) { fprintf( pFile, ".names" ); fprintf( pFile, " %s", Saig_ObjName(p, Aig_ObjFanin0(pObj)) ); fprintf( pFile, " %s", Saig_ObjName(p, Aig_ObjFanin1(pObj)) ); fprintf( pFile, " %s", Saig_ObjName(p, pObj) ); fprintf( pFile, "\n%d%d 1\n", !Aig_ObjFaninC0(pObj), !Aig_ObjFaninC1(pObj) ); } // write the POs Aig_ManForEachCo( p, pObj, i ) { fprintf( pFile, ".names" ); fprintf( pFile, " %s", Saig_ObjName(p, Aig_ObjFanin0(pObj)) ); fprintf( pFile, " %s", Saig_ObjName(p, pObj) ); fprintf( pFile, "\n%d 1\n", !Aig_ObjFaninC0(pObj) ); } fprintf( pFile, ".end\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [Reads one token from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Saig_ManReadToken( FILE * pFile ) { static char Buffer[1000]; if ( fscanf( pFile, "%s", Buffer ) == 1 ) return Buffer; return NULL; } /**Function************************************************************* Synopsis [Returns the corresponding number.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManReadNumber( Aig_Man_t * p, char * pToken ) { if ( pToken[0] == 'n' ) return atoi( pToken + 1 ); if ( pToken[0] == 'p' ) return atoi( pToken + 2 ); if ( pToken[0] == 'l' ) return atoi( pToken + 2 ); assert( 0 ); return -1; } /**Function************************************************************* Synopsis [Returns the corresponding node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Saig_ManReadNode( Aig_Man_t * p, int * pNum2Id, char * pToken ) { int Num; if ( pToken[0] == 'n' ) { Num = atoi( pToken + 1 ); return Aig_ManObj( p, pNum2Id[Num] ); } if ( pToken[0] == 'p' ) { pToken++; if ( pToken[0] == 'i' ) { Num = atoi( pToken + 1 ); return Aig_ManCi( p, Num ); } if ( pToken[0] == 'o' ) return NULL; assert( 0 ); return NULL; } if ( pToken[0] == 'l' ) { pToken++; if ( pToken[0] == 'o' ) { Num = atoi( pToken + 1 ); return Saig_ManLo( p, Num ); } if ( pToken[0] == 'i' ) return NULL; assert( 0 ); return NULL; } assert( 0 ); return NULL; } /**Function************************************************************* Synopsis [Reads BLIF previously dumped by Saig_ManDumpBlif().] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManReadBlif( char * pFileName ) { FILE * pFile; Aig_Man_t * p; Aig_Obj_t * pFanin0, * pFanin1, * pNode; char * pToken; int i, nPis, nPos, nRegs, Number; int * pNum2Id = NULL; // mapping of node numbers in the file into AIG node IDs // open the file pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { printf( "Saig_ManReadBlif(): Cannot open file for reading.\n" ); return NULL; } // skip through the comments for ( i = 0; (pToken = Saig_ManReadToken( pFile )) && pToken[0] != '.'; i++ ); if ( pToken == NULL ) { printf( "Saig_ManReadBlif(): Error 1.\n" ); return NULL; } // get he model pToken = Saig_ManReadToken( pFile ); if ( pToken == NULL ) { printf( "Saig_ManReadBlif(): Error 2.\n" ); return NULL; } // start the package p = Aig_ManStart( 10000 ); p->pName = Abc_UtilStrsav( pToken ); p->pSpec = Abc_UtilStrsav( pFileName ); // count PIs pToken = Saig_ManReadToken( pFile ); if ( pToken == NULL || strcmp( pToken, ".inputs" ) ) { printf( "Saig_ManReadBlif(): Error 3.\n" ); Aig_ManStop(p); return NULL; } for ( nPis = 0; (pToken = Saig_ManReadToken( pFile )) && pToken[0] != '.'; nPis++ ); // count POs if ( pToken == NULL || strcmp( pToken, ".outputs" ) ) { printf( "Saig_ManReadBlif(): Error 4.\n" ); Aig_ManStop(p); return NULL; } for ( nPos = 0; (pToken = Saig_ManReadToken( pFile )) && pToken[0] != '.'; nPos++ ); // count latches if ( pToken == NULL ) { printf( "Saig_ManReadBlif(): Error 5.\n" ); Aig_ManStop(p); return NULL; } for ( nRegs = 0; strcmp( pToken, ".latch" ) == 0; nRegs++ ) { pToken = Saig_ManReadToken( pFile ); if ( pToken == NULL ) { printf( "Saig_ManReadBlif(): Error 6.\n" ); Aig_ManStop(p); return NULL; } pToken = Saig_ManReadToken( pFile ); if ( pToken == NULL ) { printf( "Saig_ManReadBlif(): Error 7.\n" ); Aig_ManStop(p); return NULL; } pToken = Saig_ManReadToken( pFile ); if ( pToken == NULL ) { printf( "Saig_ManReadBlif(): Error 8.\n" ); Aig_ManStop(p); return NULL; } pToken = Saig_ManReadToken( pFile ); if ( pToken == NULL ) { printf( "Saig_ManReadBlif(): Error 9.\n" ); Aig_ManStop(p); return NULL; } } // create PIs and LOs for ( i = 0; i < nPis + nRegs; i++ ) Aig_ObjCreateCi( p ); Aig_ManSetRegNum( p, nRegs ); // create nodes for ( i = 0; strcmp( pToken, ".names" ) == 0; i++ ) { // first token pToken = Saig_ManReadToken( pFile ); if ( i == 0 && pToken[0] == 'n' ) { // constant node // read 1 pToken = Saig_ManReadToken( pFile ); if ( pToken == NULL || strcmp( pToken, "1" ) ) { printf( "Saig_ManReadBlif(): Error 10.\n" ); Aig_ManStop(p); return NULL; } // read next pToken = Saig_ManReadToken( pFile ); if ( pToken == NULL ) { printf( "Saig_ManReadBlif(): Error 11.\n" ); Aig_ManStop(p); return NULL; } continue; } pFanin0 = Saig_ManReadNode( p, pNum2Id, pToken ); // second token pToken = Saig_ManReadToken( pFile ); if ( (pToken[0] == 'p' && pToken[1] == 'o') || (pToken[0] == 'l' && pToken[1] == 'i') ) { // buffer // read complemented attribute pToken = Saig_ManReadToken( pFile ); if ( pToken == NULL ) { printf( "Saig_ManReadBlif(): Error 12.\n" ); Aig_ManStop(p); return NULL; } if ( pToken[0] == '0' ) pFanin0 = Aig_Not(pFanin0); // read 1 pToken = Saig_ManReadToken( pFile ); if ( pToken == NULL || strcmp( pToken, "1" ) ) { printf( "Saig_ManReadBlif(): Error 13.\n" ); Aig_ManStop(p); return NULL; } Aig_ObjCreateCo( p, pFanin0 ); // read next pToken = Saig_ManReadToken( pFile ); if ( pToken == NULL ) { printf( "Saig_ManReadBlif(): Error 14.\n" ); Aig_ManStop(p); return NULL; } continue; } // third token // regular node pFanin1 = Saig_ManReadNode( p, pNum2Id, pToken ); pToken = Saig_ManReadToken( pFile ); Number = Saig_ManReadNumber( p, pToken ); // allocate mapping if ( pNum2Id == NULL ) { // extern double pow( double x, double y ); int Size = (int)pow(10.0, (double)(strlen(pToken) - 1)); pNum2Id = ABC_CALLOC( int, Size ); } // other tokens // get the complemented attributes pToken = Saig_ManReadToken( pFile ); if ( pToken == NULL ) { printf( "Saig_ManReadBlif(): Error 15.\n" ); Aig_ManStop(p); return NULL; } if ( pToken[0] == '0' ) pFanin0 = Aig_Not(pFanin0); if ( pToken[1] == '0' ) pFanin1 = Aig_Not(pFanin1); // read 1 pToken = Saig_ManReadToken( pFile ); if ( pToken == NULL || strcmp( pToken, "1" ) ) { printf( "Saig_ManReadBlif(): Error 16.\n" ); Aig_ManStop(p); return NULL; } // read next pToken = Saig_ManReadToken( pFile ); if ( pToken == NULL ) { printf( "Saig_ManReadBlif(): Error 17.\n" ); Aig_ManStop(p); return NULL; } // create new node pNode = Aig_And( p, pFanin0, pFanin1 ); if ( Aig_IsComplement(pNode) ) { printf( "Saig_ManReadBlif(): Error 18.\n" ); Aig_ManStop(p); return NULL; } // set mapping pNum2Id[ Number ] = pNode->Id; } if ( pToken == NULL || strcmp( pToken, ".end" ) ) { printf( "Saig_ManReadBlif(): Error 19.\n" ); Aig_ManStop(p); return NULL; } if ( nPos + nRegs != Aig_ManCoNum(p) ) { printf( "Saig_ManReadBlif(): Error 20.\n" ); Aig_ManStop(p); return NULL; } // add non-node objects to the mapping Aig_ManForEachCi( p, pNode, i ) pNum2Id[pNode->Id] = pNode->Id; // ABC_FREE( pNum2Id ); p->pData = pNum2Id; // check the new manager Aig_ManSetRegNum( p, nRegs ); if ( !Aig_ManCheck(p) ) printf( "Saig_ManReadBlif(): Check has failed.\n" ); return p; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigIso.c000066400000000000000000000457501477524141600162270ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigIso.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Sequential cleanup.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigIso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig/ioa/ioa.h" #include "saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Find the canonical permutation of the COs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_ManFindIsoPermCos( Aig_Man_t * pAig, Vec_Int_t * vPermCis ) { extern int Iso_ObjCompareByData( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ); Vec_Int_t * vPermCos; Aig_Obj_t * pObj, * pFanin; int i, Entry, Diff; assert( Vec_IntSize(vPermCis) == Aig_ManCiNum(pAig) ); vPermCos = Vec_IntAlloc( Aig_ManCoNum(pAig) ); if ( Saig_ManPoNum(pAig) == 1 ) Vec_IntPush( vPermCos, 0 ); else { Vec_Ptr_t * vRoots = Vec_PtrAlloc( Saig_ManPoNum(pAig) ); Saig_ManForEachPo( pAig, pObj, i ) { pFanin = Aig_ObjFanin0(pObj); assert( Aig_ObjIsConst1(pFanin) || pFanin->iData > 0 ); pObj->iData = Abc_Var2Lit( pFanin->iData, Aig_ObjFaninC0(pObj) ); Vec_PtrPush( vRoots, pObj ); } 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 ); } // add flop outputs Diff = Saig_ManPoNum(pAig) - Saig_ManPiNum(pAig); Vec_IntForEachEntryStart( vPermCis, Entry, i, Saig_ManPiNum(pAig) ) Vec_IntPush( vPermCos, Entry + Diff ); return vPermCos; } /**Function************************************************************* Synopsis [Performs canonical duplication of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManDupIsoCanonical_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj_t * pObj ) { if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return; Aig_ObjSetTravIdCurrent(pAig, pObj); assert( Aig_ObjIsNode(pObj) ); if ( !Aig_ObjIsNode(Aig_ObjFanin0(pObj)) || !Aig_ObjIsNode(Aig_ObjFanin1(pObj)) ) { Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) ); Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin1(pObj) ); } else { assert( Aig_ObjFanin0(pObj)->iData != Aig_ObjFanin1(pObj)->iData ); if ( Aig_ObjFanin0(pObj)->iData < Aig_ObjFanin1(pObj)->iData ) { Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) ); Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin1(pObj) ); } else { Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin1(pObj) ); Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) ); } } pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } /**Function************************************************************* Synopsis [Performs canonical duplication of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDupIsoCanonical( Aig_Man_t * pAig, int fVerbose ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; Vec_Int_t * vPerm, * vPermCo; int i, Entry; // derive permutations vPerm = Saig_ManFindIsoPerm( pAig, fVerbose ); vPermCo = Saig_ManFindIsoPermCos( pAig, vPerm ); // create the new manager pNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); pNew->pName = Abc_UtilStrsav( pAig->pName ); Aig_ManIncrementTravId( pAig ); // create constant pObj = Aig_ManConst1(pAig); pObj->pData = Aig_ManConst1(pNew); Aig_ObjSetTravIdCurrent( pAig, pObj ); // create PIs Vec_IntForEachEntry( vPerm, Entry, i ) { pObj = Aig_ManCi(pAig, Entry); pObj->pData = Aig_ObjCreateCi(pNew); Aig_ObjSetTravIdCurrent( pAig, pObj ); } // traverse from the POs Vec_IntForEachEntry( vPermCo, Entry, i ) { pObj = Aig_ManCo(pAig, Entry); Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) ); } // create POs Vec_IntForEachEntry( vPermCo, Entry, i ) { pObj = Aig_ManCo(pAig, Entry); Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) ); Vec_IntFreeP( &vPerm ); Vec_IntFreeP( &vPermCo ); return pNew; } /**Function************************************************************* Synopsis [Checks structural equivalence of AIG1 and AIG2.] Description [Returns 1 if AIG1 and AIG2 are structurally equivalent under this mapping.] SideEffects [] SeeAlso [] ***********************************************************************/ int Iso_ManCheckMapping( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vMap2to1, int fVerbose ) { Aig_Obj_t * pObj, * pFanin0, * pFanin1; int i; assert( Aig_ManCiNum(pAig1) == Aig_ManCiNum(pAig2) ); assert( Aig_ManCoNum(pAig1) == Aig_ManCoNum(pAig2) ); assert( Aig_ManRegNum(pAig1) == Aig_ManRegNum(pAig2) ); assert( Aig_ManNodeNum(pAig1) == Aig_ManNodeNum(pAig2) ); Aig_ManCleanData( pAig1 ); // map const and PI nodes Aig_ManConst1(pAig2)->pData = Aig_ManConst1(pAig1); Aig_ManForEachCi( pAig2, pObj, i ) pObj->pData = Aig_ManCi( pAig1, Vec_IntEntry(vMap2to1, i) ); // try internal nodes Aig_ManForEachNode( pAig2, pObj, i ) { pFanin0 = Aig_ObjChild0Copy( pObj ); pFanin1 = Aig_ObjChild1Copy( pObj ); pObj->pData = Aig_TableLookupTwo( pAig1, pFanin0, pFanin1 ); if ( pObj->pData == NULL ) { if ( fVerbose ) printf( "Structural equivalence failed at node %d.\n", i ); return 0; } } // make sure the first PO points to the same node if ( Aig_ManCoNum(pAig1)-Aig_ManRegNum(pAig1) == 1 && Aig_ObjChild0Copy(Aig_ManCo(pAig2, 0)) != Aig_ObjChild0(Aig_ManCo(pAig1, 0)) ) { if ( fVerbose ) printf( "Structural equivalence failed at primary output 0.\n" ); return 0; } return 1; } //static int s_Counter; /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Iso_ManNegEdgeNum( Aig_Man_t * pAig ) { Aig_Obj_t * pObj; int i, Counter = 0; if ( pAig->nComplEdges > 0 ) return pAig->nComplEdges; Aig_ManForEachObj( pAig, pObj, i ) if ( Aig_ObjIsNode(pObj) ) { Counter += Aig_ObjFaninC0(pObj); Counter += Aig_ObjFaninC1(pObj); } else if ( Aig_ObjIsCo(pObj) ) Counter += Aig_ObjFaninC0(pObj); return (pAig->nComplEdges = Counter); } /**Function************************************************************* Synopsis [Finds mapping of CIs of AIG2 into those of AIG1.] Description [Returns the mapping of CIs of the two AIGs, or NULL if there is no mapping.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Iso_ManFindMapping( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vPerm1_, Vec_Int_t * vPerm2_, int fVerbose ) { Vec_Int_t * vPerm1, * vPerm2, * vInvPerm2; int i, Entry; if ( Aig_ManCiNum(pAig1) != Aig_ManCiNum(pAig2) ) return NULL; if ( Aig_ManCoNum(pAig1) != Aig_ManCoNum(pAig2) ) return NULL; if ( Aig_ManRegNum(pAig1) != Aig_ManRegNum(pAig2) ) return NULL; if ( Aig_ManNodeNum(pAig1) != Aig_ManNodeNum(pAig2) ) return NULL; if ( Aig_ManLevelNum(pAig1) != Aig_ManLevelNum(pAig2) ) return NULL; // if ( Iso_ManNegEdgeNum(pAig1) != Iso_ManNegEdgeNum(pAig2) ) // return NULL; // s_Counter++; if ( fVerbose ) printf( "AIG1:\n" ); vPerm1 = vPerm1_ ? vPerm1_ : Saig_ManFindIsoPerm( pAig1, fVerbose ); if ( fVerbose ) printf( "AIG1:\n" ); vPerm2 = vPerm2_ ? vPerm2_ : Saig_ManFindIsoPerm( pAig2, fVerbose ); if ( vPerm1_ ) assert( Vec_IntSize(vPerm1_) == Aig_ManCiNum(pAig1) ); if ( vPerm2_ ) assert( Vec_IntSize(vPerm2_) == Aig_ManCiNum(pAig2) ); // find canonical permutation // vPerm1/vPerm2 give canonical order of CIs of AIG1/AIG2 vInvPerm2 = Vec_IntInvert( vPerm2, -1 ); Vec_IntForEachEntry( vInvPerm2, Entry, i ) { assert( Entry >= 0 && Entry < Aig_ManCiNum(pAig1) ); Vec_IntWriteEntry( vInvPerm2, i, Vec_IntEntry(vPerm1, Entry) ); } if ( vPerm1_ == NULL ) Vec_IntFree( vPerm1 ); if ( vPerm2_ == NULL ) Vec_IntFree( vPerm2 ); // check if they are indeed equivalent if ( !Iso_ManCheckMapping( pAig1, pAig2, vInvPerm2, fVerbose ) ) Vec_IntFreeP( &vInvPerm2 ); return vInvPerm2; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Iso_ManFilterPos_old( Aig_Man_t * pAig, int fVerbose ) { int fVeryVerbose = 0; Vec_Ptr_t * vParts, * vPerms, * vAigs; Vec_Int_t * vPos, * vMap; Aig_Man_t * pPart, * pTemp; int i, k, nPos; // derive AIG for each PO nPos = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig); vParts = Vec_PtrAlloc( nPos ); vPerms = Vec_PtrAlloc( nPos ); for ( i = 0; i < nPos; i++ ) { pPart = Saig_ManDupCones( pAig, &i, 1 ); vMap = Saig_ManFindIsoPerm( pPart, fVeryVerbose ); Vec_PtrPush( vParts, pPart ); Vec_PtrPush( vPerms, vMap ); } // s_Counter = 0; // check AIGs for each PO vAigs = Vec_PtrAlloc( 1000 ); vPos = Vec_IntAlloc( 1000 ); Vec_PtrForEachEntry( Aig_Man_t *, vParts, pPart, i ) { if ( fVeryVerbose ) { printf( "AIG %4d : ", i ); Aig_ManPrintStats( pPart ); } Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, k ) { if ( fVeryVerbose ) printf( "Comparing AIG %4d and AIG %4d. ", Vec_IntEntry(vPos,k), i ); vMap = Iso_ManFindMapping( pTemp, pPart, (Vec_Int_t *)Vec_PtrEntry(vPerms, Vec_IntEntry(vPos,k)), (Vec_Int_t *)Vec_PtrEntry(vPerms, i), fVeryVerbose ); if ( vMap != NULL ) { if ( fVeryVerbose ) printf( "Found match\n" ); // if ( fVerbose ) // printf( "Found match for AIG %4d and AIG %4d.\n", Vec_IntEntry(vPos,k), i ); Vec_IntFree( vMap ); break; } if ( fVeryVerbose ) printf( "No match.\n" ); } if ( k == Vec_PtrSize(vAigs) ) { Vec_PtrPush( vAigs, pPart ); Vec_IntPush( vPos, i ); } } // delete AIGs Vec_PtrForEachEntry( Aig_Man_t *, vParts, pPart, i ) Aig_ManStop( pPart ); Vec_PtrFree( vParts ); Vec_PtrForEachEntry( Vec_Int_t *, vPerms, vMap, i ) Vec_IntFree( vMap ); Vec_PtrFree( vPerms ); // derive the resulting AIG pPart = Saig_ManDupCones( pAig, Vec_IntArray(vPos), Vec_IntSize(vPos) ); Vec_PtrFree( vAigs ); Vec_IntFree( vPos ); // printf( "The number of all checks %d. Complex checks %d.\n", nPos*(nPos-1)/2, s_Counter ); return pPart; } /**Function************************************************************* Synopsis [Takes multi-output sequential AIG.] Description [Returns candidate equivalence classes of POs.] SideEffects [] SeeAlso [] ***********************************************************************/ int Iso_StoCompareVecStr( Vec_Str_t ** p1, Vec_Str_t ** p2 ) { return Vec_StrCompareVec( *p1, *p2 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Iso_ManFilterPos( Aig_Man_t * pAig, Vec_Ptr_t ** pvPosEquivs, int fVerbose ) { // int fVeryVerbose = 0; Aig_Man_t * pPart, * pTemp; Vec_Ptr_t * vBuffers, * vClasses; Vec_Int_t * vLevel, * vRemain; Vec_Str_t * vStr, * vPrev; int i, nPos; abctime clk = Abc_Clock(); abctime clkDup = 0, clkAig = 0, clkIso = 0, clk2; *pvPosEquivs = NULL; // derive AIG for each PO nPos = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig); vBuffers = Vec_PtrAlloc( nPos ); for ( i = 0; i < nPos; i++ ) { if ( i % 100 == 0 ) printf( "%6d finished...\r", i ); clk2 = Abc_Clock(); pPart = Saig_ManDupCones( pAig, &i, 1 ); clkDup += Abc_Clock() - clk2; clk2 = Abc_Clock(); pTemp = Saig_ManDupIsoCanonical( pPart, 0 ); clkIso += Abc_Clock() - clk2; clk2 = Abc_Clock(); vStr = Ioa_WriteAigerIntoMemoryStr( pTemp ); clkAig += Abc_Clock() - clk2; Vec_PtrPush( vBuffers, vStr ); Aig_ManStop( pTemp ); Aig_ManStop( pPart ); // remember the output number in nCap (attention: hack!) vStr->nCap = i; } // s_Counter = 0; if ( fVerbose ) { Abc_PrintTime( 1, "Duplicate time", clkDup ); Abc_PrintTime( 1, "Isomorph time", clkIso ); Abc_PrintTime( 1, "AIGER time", clkAig ); } // sort the infos clk = Abc_Clock(); Vec_PtrSort( vBuffers, (int (*)(const void *, const void *))Iso_StoCompareVecStr ); // create classes clk = Abc_Clock(); vClasses = Vec_PtrAlloc( Saig_ManPoNum(pAig) ); // start the first class Vec_PtrPush( vClasses, (vLevel = Vec_IntAlloc(4)) ); vPrev = (Vec_Str_t *)Vec_PtrEntry( vBuffers, 0 ); Vec_IntPush( vLevel, vPrev->nCap ); // consider other classes Vec_PtrForEachEntryStart( Vec_Str_t *, vBuffers, vStr, i, 1 ) { if ( Vec_StrCompareVec(vPrev, vStr) ) Vec_PtrPush( vClasses, Vec_IntAlloc(4) ); vLevel = (Vec_Int_t *)Vec_PtrEntryLast( vClasses ); Vec_IntPush( vLevel, vStr->nCap ); vPrev = vStr; } Vec_VecFree( (Vec_Vec_t *)vBuffers ); if ( fVerbose ) Abc_PrintTime( 1, "Sorting time", Abc_Clock() - clk ); // Abc_PrintTime( 1, "Traversal time", time_Trav ); // report the results // Vec_VecPrintInt( (Vec_Vec_t *)vClasses ); // printf( "Divided %d outputs into %d cand equiv classes.\n", Saig_ManPoNum(pAig), Vec_PtrSize(vClasses) ); /* if ( fVerbose ) { Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i ) if ( Vec_IntSize(vLevel) > 1 ) printf( "%d ", Vec_IntSize(vLevel) ); else nUnique++; printf( " Unique = %d\n", nUnique ); } */ // canonicize order Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i ) Vec_IntSort( vLevel, 0 ); Vec_VecSortByFirstInt( (Vec_Vec_t *)vClasses, 0 ); // collect the first ones vRemain = Vec_IntAlloc( 100 ); Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i ) Vec_IntPush( vRemain, Vec_IntEntry(vLevel, 0) ); // derive the resulting AIG pPart = Saig_ManDupCones( pAig, Vec_IntArray(vRemain), Vec_IntSize(vRemain) ); Vec_IntFree( vRemain ); // return (Vec_Vec_t *)vClasses; // Vec_VecFree( (Vec_Vec_t *)vClasses ); *pvPosEquivs = vClasses; return pPart; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Iso_ManTest( Aig_Man_t * pAig, int fVerbose ) { Vec_Int_t * vPerm; abctime clk = Abc_Clock(); vPerm = Saig_ManFindIsoPerm( pAig, fVerbose ); Vec_IntFree( vPerm ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManIsoReduce( Aig_Man_t * pAig, Vec_Ptr_t ** pvPosEquivs, int fVerbose ) { Aig_Man_t * pPart; abctime clk = Abc_Clock(); pPart = Iso_ManFilterPos( pAig, pvPosEquivs, fVerbose ); printf( "Reduced %d outputs to %d outputs. ", Saig_ManPoNum(pAig), Saig_ManPoNum(pPart) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); if ( fVerbose && *pvPosEquivs && Saig_ManPoNum(pAig) != Vec_PtrSize(*pvPosEquivs) ) { printf( "Nontrivial classes:\n" ); Vec_VecPrintInt( (Vec_Vec_t *)*pvPosEquivs, 1 ); } // Aig_ManStopP( &pPart ); return pPart; } ABC_NAMESPACE_IMPL_END #include "base/abc/abc.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Iso_ManTest888( Aig_Man_t * pAig1, int fVerbose ) { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); Abc_Ntk_t * pNtk; Aig_Man_t * pAig2; Vec_Int_t * vMap; pNtk = Abc_NtkFromAigPhase( pAig1 ); Abc_NtkPermute( pNtk, 1, 0, 1, NULL, NULL, NULL ); pAig2 = Abc_NtkToDar( pNtk, 0, 1 ); Abc_NtkDelete( pNtk ); vMap = Iso_ManFindMapping( pAig1, pAig2, NULL, NULL, fVerbose ); Aig_ManStop( pAig2 ); if ( vMap != NULL ) { printf( "Mapping of AIGs is found.\n" ); if ( fVerbose ) Vec_IntPrint( vMap ); } else printf( "Mapping of AIGs is NOT found.\n" ); Vec_IntFreeP( &vMap ); return NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigIsoFast.c000066400000000000000000000247571477524141600170510ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigIsoFast.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Graph isomorphism package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigIsoFast.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define AIG_ISO_NUM 16 typedef struct Iso_Dat_t_ Iso_Dat_t; struct Iso_Dat_t_ { unsigned nFiNeg : 3; unsigned nFoNeg : 2; unsigned nFoPos : 2; unsigned Fi0Lev : 3; unsigned Fi1Lev : 3; unsigned Level : 3; unsigned fVisit : 16; }; typedef struct Iso_Dat2_t_ Iso_Dat2_t; struct Iso_Dat2_t_ { unsigned Data : 16; }; typedef struct Iso_Sto_t_ Iso_Sto_t; struct Iso_Sto_t_ { Aig_Man_t * pAig; // user's AIG manager int nObjs; // number of objects Iso_Dat_t * pData; // data for each object Vec_Int_t * vVisited; // visited nodes Vec_Ptr_t * vRoots; // root nodes Vec_Int_t * vPlaces; // places in the counter lists int * pCounters; // counters }; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Iso_Sto_t * Iso_StoStart( Aig_Man_t * pAig ) { Iso_Sto_t * p; p = ABC_CALLOC( Iso_Sto_t, 1 ); p->pAig = pAig; p->nObjs = Aig_ManObjNumMax( pAig ); p->pData = ABC_CALLOC( Iso_Dat_t, p->nObjs ); p->vVisited = Vec_IntStart( 1000 ); p->vPlaces = Vec_IntStart( 1000 ); p->vRoots = Vec_PtrStart( 1000 ); p->pCounters = ABC_CALLOC( int, (1 << AIG_ISO_NUM) ); return p; } void Iso_StoStop( Iso_Sto_t * p ) { Vec_IntFree( p->vPlaces ); Vec_IntFree( p->vVisited ); Vec_PtrFree( p->vRoots ); ABC_FREE( p->pCounters ); ABC_FREE( p->pData ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Collect statistics about one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Iso_StoCollectInfo_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fCompl, Vec_Int_t * vVisited, Iso_Dat_t * pData, Vec_Ptr_t * vRoots ) { Iso_Dat_t * pThis = pData + Aig_ObjId(pObj); assert( Aig_ObjIsCi(pObj) || Aig_ObjIsNode(pObj) ); if ( pThis->fVisit ) { if ( fCompl ) pThis->nFoNeg++; else pThis->nFoPos++; return; } assert( *((int *)pThis) == 0 ); pThis->fVisit = 1; if ( fCompl ) pThis->nFoNeg++; else pThis->nFoPos++; pThis->Level = pObj->Level; pThis->nFiNeg = Aig_ObjFaninC0(pObj) + Aig_ObjFaninC1(pObj); if ( Aig_ObjIsNode(pObj) ) { if ( Aig_ObjFaninC0(pObj) < Aig_ObjFaninC1(pObj) || (Aig_ObjFaninC0(pObj) == Aig_ObjFaninC1(pObj) && Aig_ObjFanin0(pObj)->Level < Aig_ObjFanin1(pObj)->Level) ) { pThis->Fi0Lev = pObj->Level - Aig_ObjFanin0(pObj)->Level; pThis->Fi1Lev = pObj->Level - Aig_ObjFanin1(pObj)->Level; } else { pThis->Fi0Lev = pObj->Level - Aig_ObjFanin1(pObj)->Level; pThis->Fi1Lev = pObj->Level - Aig_ObjFanin0(pObj)->Level; } Iso_StoCollectInfo_rec( p, Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj), vVisited, pData, vRoots ); Iso_StoCollectInfo_rec( p, Aig_ObjFanin1(pObj), Aig_ObjFaninC1(pObj), vVisited, pData, vRoots ); } else if ( Saig_ObjIsLo(p, pObj) ) { pThis->Fi0Lev = 1; pThis->Fi1Lev = 0; Vec_PtrPush( vRoots, Saig_ObjLoToLi(p, pObj) ); } else if ( Saig_ObjIsPi(p, pObj) ) { pThis->Fi0Lev = 0; pThis->Fi1Lev = 0; } else assert( 0 ); assert( pThis->nFoNeg + pThis->nFoPos ); Vec_IntPush( vVisited, Aig_ObjId(pObj) ); } //static abctime time_Trav = 0; /**Function************************************************************* Synopsis [Collect statistics about one output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Iso_StoCollectInfo( Iso_Sto_t * p, Aig_Obj_t * pPo ) { int fVerboseShow = 0; Vec_Int_t * vInfo; Iso_Dat2_t * pData2 = (Iso_Dat2_t *)p->pData; Aig_Man_t * pAig = p->pAig; Aig_Obj_t * pObj; int i, Value, Entry, * pPerm; // abctime clk = Abc_Clock(); assert( Aig_ObjIsCo(pPo) ); // collect initial POs Vec_IntClear( p->vVisited ); Vec_PtrClear( p->vRoots ); Vec_PtrPush( p->vRoots, pPo ); // mark internal nodes Vec_PtrForEachEntry( Aig_Obj_t *, p->vRoots, pObj, i ) if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) Iso_StoCollectInfo_rec( pAig, Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj), p->vVisited, p->pData, p->vRoots ); // time_Trav += Abc_Clock() - clk; // count how many times each data entry appears Vec_IntClear( p->vPlaces ); Vec_IntForEachEntry( p->vVisited, Entry, i ) { Value = pData2[Entry].Data; // assert( Value > 0 ); if ( p->pCounters[Value]++ == 0 ) Vec_IntPush( p->vPlaces, Value ); // pData2[Entry].Data = 0; *((int *)(p->pData + Entry)) = 0; } // collect non-trivial counters Vec_IntClear( p->vVisited ); Vec_IntForEachEntry( p->vPlaces, Entry, i ) { assert( p->pCounters[Entry] ); Vec_IntPush( p->vVisited, p->pCounters[Entry] ); p->pCounters[Entry] = 0; } // printf( "%d ", Vec_IntSize(p->vVisited) ); // sort the costs in the increasing order pPerm = Abc_MergeSortCost( Vec_IntArray(p->vVisited), Vec_IntSize(p->vVisited) ); assert( Vec_IntEntry(p->vVisited, pPerm[0]) <= Vec_IntEntry(p->vVisited, pPerm[Vec_IntSize(p->vVisited)-1]) ); // create information vInfo = Vec_IntAlloc( Vec_IntSize(p->vVisited) ); for ( i = Vec_IntSize(p->vVisited)-1; i >= 0; i-- ) { Entry = Vec_IntEntry( p->vVisited, pPerm[i] ); Entry = (Entry << AIG_ISO_NUM) | Vec_IntEntry( p->vPlaces, pPerm[i] ); Vec_IntPush( vInfo, Entry ); } ABC_FREE( pPerm ); // show the final result if ( fVerboseShow ) Vec_IntForEachEntry( vInfo, Entry, i ) { Iso_Dat2_t Data = { (unsigned)Entry & 0xFFFF }; Iso_Dat_t * pData = (Iso_Dat_t *)&Data; printf( "%6d : ", i ); printf( "Freq =%6d ", Entry >> 16 ); printf( "FiNeg =%3d ", pData->nFiNeg ); printf( "FoNeg =%3d ", pData->nFoNeg ); printf( "FoPos =%3d ", pData->nFoPos ); printf( "Fi0L =%3d ", pData->Fi0Lev ); printf( "Fi1L =%3d ", pData->Fi1Lev ); printf( "Lev =%3d ", pData->Level ); printf( "\n" ); } return vInfo; } /**Function************************************************************* Synopsis [Takes multi-output sequential AIG.] Description [Returns candidate equivalence classes of POs.] SideEffects [] SeeAlso [] ***********************************************************************/ int Iso_StoCompareVecInt( Vec_Int_t ** p1, Vec_Int_t ** p2 ) { return Vec_IntCompareVec( *p1, *p2 ); } /**Function************************************************************* Synopsis [Takes multi-output sequential AIG.] Description [Returns candidate equivalence classes of POs.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Saig_IsoDetectFast( Aig_Man_t * pAig ) { Iso_Sto_t * pMan; Aig_Obj_t * pObj; Vec_Ptr_t * vClasses, * vInfos; Vec_Int_t * vInfo, * vPrev, * vLevel; int i, Number, nUnique = 0; abctime clk = Abc_Clock(); // collect infos and remember their number pMan = Iso_StoStart( pAig ); vInfos = Vec_PtrAlloc( Saig_ManPoNum(pAig) ); Saig_ManForEachPo( pAig, pObj, i ) { vInfo = Iso_StoCollectInfo(pMan, pObj); Vec_IntPush( vInfo, i ); Vec_PtrPush( vInfos, vInfo ); } Iso_StoStop( pMan ); Abc_PrintTime( 1, "Info computation time", Abc_Clock() - clk ); // sort the infos clk = Abc_Clock(); Vec_PtrSort( vInfos, (int (*)(const void *, const void *))Iso_StoCompareVecInt ); // create classes clk = Abc_Clock(); vClasses = Vec_PtrAlloc( Saig_ManPoNum(pAig) ); // start the first class Vec_PtrPush( vClasses, (vLevel = Vec_IntAlloc(4)) ); vPrev = (Vec_Int_t *)Vec_PtrEntry( vInfos, 0 ); Vec_IntPush( vLevel, Vec_IntPop(vPrev) ); // consider other classes Vec_PtrForEachEntryStart( Vec_Int_t *, vInfos, vInfo, i, 1 ) { Number = Vec_IntPop( vInfo ); if ( Vec_IntCompareVec(vPrev, vInfo) ) Vec_PtrPush( vClasses, Vec_IntAlloc(4) ); vLevel = (Vec_Int_t *)Vec_PtrEntryLast( vClasses ); Vec_IntPush( vLevel, Number ); vPrev = vInfo; } Vec_VecFree( (Vec_Vec_t *)vInfos ); Abc_PrintTime( 1, "Sorting time", Abc_Clock() - clk ); // Abc_PrintTime( 1, "Traversal time", time_Trav ); // report the results // Vec_VecPrintInt( (Vec_Vec_t *)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 ) printf( "%d ", Vec_IntSize(vLevel) ); else nUnique++; printf( " Unique = %d\n", nUnique ); // return (Vec_Vec_t *)vClasses; Vec_VecFree( (Vec_Vec_t *)vClasses ); return NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigIsoSlow.c000066400000000000000000001454451477524141600170760ustar00rootroot00000000000000/**CFile**************************************************************** FileName [aigIso.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Graph isomorphism package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigIso.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" ABC_NAMESPACE_IMPL_START /* #define ISO_MASK 0x3FF static int s_1kPrimes[ISO_MASK+1] = { 901403,984877,908741,966307,924437,965639,918787,931067,982621,917669,981473,936407,990487,926077,922897,970861, 942317,961747,979717,978947,940157,987821,981221,917713,983083,992231,928253,961187,991817,927643,923129,934291, 998071,967567,961087,988661,910031,930481,904489,974167,941351,959911,963811,921463,900161,934489,905629,930653, 901819,909457,939871,924083,915113,937969,928457,946291,973787,912869,994093,959279,905803,995219,949903,911011, 986707,995053,930583,955511,928307,930889,968729,911507,949043,939359,961679,918041,937681,909091,963913,923539, 929587,953347,917573,913037,995387,976483,986239,946949,922489,917887,957553,931529,929813,949567,941683,905161, 928819,932417,900089,935903,926587,914467,967361,944833,945881,941741,915949,903407,904157,971863,993893,963607, 918943,912463,980957,962963,968089,904513,963763,907363,904097,904093,991343,918347,986983,986659,935819,903569, 929171,913933,999749,923123,961531,935861,915053,994853,943511,969923,927191,968333,949391,950959,968311,991409, 911681,987101,904027,975259,907399,946223,907259,900409,957221,901063,974657,912337,979001,970147,982301,968213, 923959,964219,935443,950161,989251,936127,985679,958159,930077,971899,944857,956083,914293,941981,909481,909047, 960527,958183,970687,914827,949051,928159,933551,964423,914041,915869,929953,901367,914219,975551,912391,917809, 991499,904781,949153,959887,961957,970943,947741,941263,984541,951437,984301,947423,905761,964913,971357,927709, 916441,941933,956993,988243,921197,905453,922081,950813,946331,998561,929023,937421,956231,907651,977897,905491, 960173,931837,955217,911951,990643,971021,949439,988453,996781,951497,906011,944309,911293,917123,983803,928097, 977747,928703,949957,919189,925513,923953,904997,986351,930689,902009,912007,906757,955793,926803,906809,962743, 911917,909329,949021,974651,959083,945367,905137,948377,931757,945409,920279,915007,960121,920609,946163,946391, 928903,932951,944329,901529,959809,918469,978643,911159,982573,965411,962233,911269,953273,974437,907589,992269, 929399,980431,905693,968267,970481,911089,950557,913799,920407,974489,909863,918529,975277,929323,971549,969181, 972787,964267,939971,943763,940483,971501,921637,945341,955211,920701,978349,969041,929861,904103,908539,995369, 995567,917471,908879,993821,947783,954599,978463,914519,942869,947263,988343,914657,956987,903641,943343,991063, 985403,926327,982829,958439,942017,960353,944987,934793,948971,999331,990767,915199,912211,946459,997019,965059, 924907,983233,943273,945359,919613,933883,928927,942763,994087,996211,918971,924871,938491,957139,918839,914629, 974329,900577,952823,941641,900461,946997,983123,935149,923693,908419,995651,912871,987067,920201,913921,929209, 962509,974599,972001,920273,922099,951781,958549,909971,975133,937207,929941,961397,980677,923579,980081,942199, 940319,942979,912349,942691,986989,947711,972343,932663,937877,940369,919571,927187,981439,932353,952313,915947, 915851,974041,989381,921029,997013,999199,914801,918751,997327,992843,982133,932051,964861,903979,937463,916781, 944389,986719,958369,961451,917767,954367,949853,934939,958807,975797,949699,957097,980773,969989,934907,909281, 904679,909833,991741,946769,908381,932447,957889,981697,905701,919033,999023,993541,912953,911719,934603,925019, 989341,912269,917789,981049,959149,989909,960521,952183,922627,936253,910957,972047,945037,940399,928313,928471, 962459,959947,927541,917333,926899,911837,985631,955127,922729,911171,900511,926251,918209,943477,955277,959773, 971039,917353,955313,930301,990799,957731,917519,938507,988111,911657,999721,968917,934537,903073,921703,966227, 904661,998213,954307,931309,909331,933643,910099,958627,914533,902903,950149,972721,915157,969037,988219,944137, 976411,952873,964787,970927,968963,920741,975187,966817,982909,975281,931907,959267,980711,924617,975691,962309, 976307,932209,989921,907969,947927,932207,945397,948929,904903,938563,961691,977671,963173,927149,951061,966547, 937661,983597,948139,948041,982759,941093,993703,910097,902347,990307,978217,996763,904919,924641,902299,929549, 977323,975071,932917,996293,925579,925843,915487,917443,999541,943043,919109,959879,912173,986339,939193,939599, 927077,977183,966521,959471,991943,985951,942187,932557,904297,972337,931751,964097,942341,966221,929113,960131, 906427,970133,996511,925637,971651,983443,981703,933613,939749,929029,958043,961511,957241,901079,950479,975493, 985799,909401,945601,911077,978359,948151,950333,968879,978727,961151,957823,950393,960293,915683,971513,915659, 943841,902477,916837,911161,958487,963691,949607,935707,987607,901613,972557,938947,931949,919021,982217,914737, 913753,971279,981683,915631,907807,970421,983173,916099,984587,912049,981391,947747,966233,932101,991733,969757, 904283,996601,979807,974419,964693,931537,917251,967961,910093,989321,988129,997307,963427,999221,962447,991171, 993137,914339,964973,908617,968567,920497,980719,949649,912239,907367,995623,906779,914327,918131,983113,962993, 977849,914941,932681,905713,932579,923977,965507,916469,984119,931981,998423,984407,993841,901273,910799,939847, 997153,971429,994927,912631,931657,968377,927833,920149,978041,947449,993233,927743,939737,975017,961861,984539, 938857,977437,950921,963659,923917,932983,922331,982393,983579,935537,914357,973051,904531,962077,990281,989231, 910643,948281,961141,911839,947413,923653,982801,903883,931943,930617,928679,962119,969977,926921,999773,954181, 963019,973411,918139,959719,918823,941471,931883,925273,918173,949453,946993,945457,959561,968857,935603,978283, 978269,947389,931267,902599,961189,947621,920039,964049,947603,913259,997811,943843,978277,972119,929431,918257, 991663,954043,910883,948797,929197,985057,990023,960961,967139,923227,923371,963499,961601,971591,976501,989959, 908731,951331,989887,925307,909299,949159,913447,969797,959449,976957,906617,901213,922667,953731,960199,960049, 985447,942061,955613,965443,947417,988271,945887,976369,919823,971353,962537,929963,920473,974177,903649,955777, 963877,973537,929627,994013,940801,985709,995341,936319,904681,945817,996617,953191,952859,934889,949513,965407, 988357,946801,970391,953521,905413,976187,968419,940669,908591,976439,915731,945473,948517,939181,935183,978067, 907663,967511,968111,981599,913907,933761,994933,980557,952073,906557,935621,914351,967903,949129,957917,971821, 925937,926179,955729,966871,960737,968521,949997,956999,961273,962683,990377,908851,932231,929749,932149,966971, 922079,978149,938453,958313,995381,906259,969503,922321,918947,972443,916411,935021,944429,928643,952199,918157, 917783,998497,944777,917771,936731,999953,975157,908471,989557,914189,933787,933157,938953,922931,986569,964363, 906473,963419,941467,946079,973561,957431,952429,965267,978473,924109,979529,991901,988583,918259,961991,978037, 938033,949967,986071,986333,974143,986131,963163,940553,950933,936587,923407,950357,926741,959099,914891,976231, 949387,949441,943213,915353,983153,975739,934243,969359,926557,969863,961097,934463,957547,916501,904901,928231, 903673,974359,932219,916933,996019,934399,955813,938089,907693,918223,969421,940903,940703,913027,959323,940993, 937823,906691,930841,923701,933259,911959,915601,960251,985399,914359,930827,950251,975379,903037,905783,971237 }; */ /* #define ISO_MASK 0x7F static int s_1kPrimes[ISO_MASK+1] = { 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 }; */ /* #define ISO_MASK 0x7 static int s_1kPrimes[ISO_MASK+1] = { 12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741 }; */ #define ISO_MASK 0x3FF static unsigned int s_1kPrimes[ISO_MASK+1] = //#define ISO_MASK 0xFF //static int s_1kPrimes[0x3FF+1] = { 0x38c19891,0xde37b0ed,0xdebcd025,0xe19b7bbe,0x7e7ebd0e,0xaeed03a1,0x811230dc,0x10bfece0, 0xb3b23fb1,0x74176098,0xc34ec7c5,0x6bef8939,0xc40be5e3,0x2ab51a09,0xafc17cea,0x0dccc7a2, 0xdf7db34d,0x1009c96f,0x93fd7494,0x54385b33,0x6f36eed8,0xa1953f82,0xfbd1144a,0xde533a46, 0x23aa1cad,0x9a18943c,0xb65000d8,0x867e9974,0xe7880035,0xf9931ad4,0xcfca1e45,0x6b5aec96, 0xe9c1a119,0xfa4968c5,0x94cf93da,0xe8c9eac4,0x95884242,0x1bba52c7,0x9232c321,0x9cec8658, 0x984b6ad9,0x18a6eed3,0x950353e2,0x6222f6eb,0xdfbedd47,0xef0f9023,0xac932a26,0x590eaf55, 0x97d0a034,0xdc36cd2e,0x22736b37,0xdc9066b0,0x2eb2f98b,0x5d9c7baf,0x85747c9e,0x8aca1055, 0x50d66b74,0x2f01ae9e,0xa1a80123,0x3e1ce2dc,0xebedbc57,0x4e68bc34,0x855ee0cf,0x17275120, 0x2ae7f2df,0xf71039eb,0x7c283eec,0x70cd1137,0x7cf651f3,0xa87bfa7a,0x14d87f02,0xe82e197d, 0x8d8a5ebe,0x1e6a15dc,0x197d49db,0x5bab9c89,0x4b55dea7,0x55dede49,0x9a6a8080,0xe5e51035, 0xe148d658,0x8a17eb3b,0xe22e4b38,0xe5be2a9a,0xbe938cbb,0x3b981069,0x7f9c0c8e,0xf756df10, 0x8fa783f7,0x252062ce,0x3dc46b4b,0xf70f6432,0x3f378276,0x44b137a1,0x2bf74b77,0x04892ed6, 0xfd318de1,0xd58c235e,0x94c6d25b,0x7aa5f218,0x35c9e921,0x5732fbbb,0x06026481,0xf584a44f, 0x946e1b5f,0x8463d5b2,0x4ebca7b2,0x54887b15,0x08d1e804,0x5b22067d,0x794580f6,0xb351ea43, 0xbce555b9,0x19ae2194,0xd32f1396,0x6fc1a7f1,0x1fd8a867,0x3a89fdb0,0xea49c61c,0x25f8a879, 0xde1e6437,0x7c74afca,0x8ba63e50,0xb1572074,0xe4655092,0xdb6f8b1c,0xc2955f3c,0x327f85ba, 0x60a17021,0x95bd261d,0xdea94f28,0x04528b65,0xbe0109cc,0x26dd5688,0x6ab2729d,0xc4f029ce, 0xacf7a0be,0x4c912f55,0x34c06e65,0x4fbb938e,0x1533fb5f,0x03da06bd,0x48262889,0xc2523d7d, 0x28a71d57,0x89f9713a,0xf574c551,0x7a99deb5,0x52834d91,0x5a6f4484,0xc67ba946,0x13ae698f, 0x3e390f34,0x34fc9593,0x894c7932,0x6cf414a3,0xdb7928ab,0x13a3b8a3,0x4b381c1d,0xa10b54cb, 0x55359d9d,0x35a3422a,0x58d1b551,0x0fd4de20,0x199eb3f4,0x167e09e2,0x3ee6a956,0x5371a7fa, 0xd424efda,0x74f521c5,0xcb899ff6,0x4a42e4f4,0x747917b6,0x4b08df0b,0x090c7a39,0x11e909e4, 0x258e2e32,0xd9fad92d,0x48fe5f69,0x0545cde6,0x55937b37,0x9b4ae4e4,0x1332b40e,0xc3792351, 0xaff982ef,0x4dba132a,0x38b81ef1,0x28e641bf,0x227208c1,0xec4bbe37,0xc4e1821c,0x512c9d09, 0xdaef1257,0xb63e7784,0x043e04d7,0x9c2cea47,0x45a0e59a,0x281315ca,0x849f0aac,0xa4071ed3, 0x0ef707b3,0xfe8dac02,0x12173864,0x471f6d46,0x24a53c0a,0x35ab9265,0xbbf77406,0xa2144e79, 0xb39a884a,0x0baf5b6d,0xcccee3dd,0x12c77584,0x2907325b,0xfd1adcd2,0xd16ee972,0x345ad6c1, 0x315ebe66,0xc7ad2b8d,0x99e82c8d,0xe52da8c8,0xba50f1d3,0x66689cd8,0x2e8e9138,0x43e15e74, 0xf1ced14d,0x188ec52a,0xe0ef3cbb,0xa958aedc,0x4107a1bc,0x5a9e7a3e,0x3bde939f,0xb5b28d5a, 0x596fe848,0xe85ad00c,0x0b6b3aae,0x44503086,0x25b5695c,0xc0c31dcd,0x5ee617f0,0x74d40c3a, 0xd2cb2b9f,0x1e19f5fa,0x81e24faf,0xa01ed68f,0xcee172fc,0x7fdf2e4d,0x002f4774,0x664f82dd, 0xc569c39a,0xa2d4dcbe,0xaadea306,0xa4c947bf,0xa413e4e3,0x81fb5486,0x8a404970,0x752c980c, 0x98d1d881,0x5c932c1e,0xeee65dfb,0x37592cdd,0x0fd4e65b,0xad1d383f,0x62a1452f,0x8872f68d, 0xb58c919b,0x345c8ee3,0xb583a6d6,0x43d72cb3,0x77aaa0aa,0xeb508242,0xf2db64f8,0x86294328, 0x82211731,0x1239a9d5,0x673ba5de,0xaf4af007,0x44203b19,0x2399d955,0xa175cd12,0x595928a7, 0x6918928b,0xde3126bb,0x6c99835c,0x63ba1fa2,0xdebbdff0,0x3d02e541,0xd6f7aac6,0xe80b4cd0, 0xd0fa29f1,0x804cac5e,0x2c226798,0x462f624c,0xad05b377,0x22924fcd,0xfbea205c,0x1b47586d, 0x214d04ab,0xe093e487,0x10607ada,0x42b261cc,0x1a85e0f6,0xb851bfc3,0x77d5591c,0xda13f344, 0xc39c4c00,0xe60d75fc,0x7edae36a,0x3e4ac3ec,0x8bc38db4,0xe848dce9,0xb2407d4d,0x0d79c61e, 0x1e6c293a,0x7bc30986,0xdf18cb8f,0x23003172,0x6948e3fa,0x9b7e4f09,0x14b3b339,0x9c8078c2, 0x9a47c29f,0x85bb45ec,0x9ca35a93,0xd7db5227,0x1d9b0a10,0xb7fbbfe9,0x05b72426,0x6f30b2fa, 0x9fb44078,0xedffd3f8,0x1b02b7bc,0x43e3cfd3,0x0d44293e,0x25c8d552,0xedd3f85d,0x6f921c8c, 0x953cca0c,0x9c975b70,0xc6bd0b53,0x4f204f3e,0xa3cc69cc,0xceec390b,0x34905626,0x82ad5d41, 0xe46589a5,0x7989841d,0x045d7d9f,0xe49b7b2f,0x46baf101,0x996f92de,0x427566c8,0x918a1ee1, 0xf4baa589,0x6bdff7c7,0x3c6936ea,0xe85bfb70,0x5d96ea26,0x6d5a8991,0x7f0a528d,0x852f0634, 0x2ec04501,0x5ca15c35,0xd8695e7a,0x456876c7,0x52e97b83,0x34b4c5ed,0x54d73fbb,0x44a6be01, 0xf8019155,0x33d55a31,0x3fe51c99,0xe1cb94fd,0x8c39cd60,0xd585efba,0x2765579b,0xb8f7ed12, 0xbb04b2cd,0xd8859981,0xd966988d,0xa68bfeda,0x73110705,0x38d6aec0,0x613bc275,0xc7283c2d, 0xe051d0b1,0x32b8c2ee,0x0e73fb9e,0x7ab05c25,0x6ff652b9,0x45aeabc6,0x6be1a891,0x5b43531b, 0xcd711248,0x2b777d40,0x46956d16,0x474355a8,0xe872d6c6,0xe4158d96,0xabe03036,0x5b4fd9a4, 0xeceba1db,0xaac9713f,0xe953153b,0xf44a9229,0x460cba72,0xfd13fdf6,0x8bbf82ae,0xaf55778f, 0xa447a5b2,0x98b647b3,0x5f351c57,0x69d0bb71,0xf14d2706,0x78b1a3af,0x7206c73f,0x3f5cd4a6, 0x5c0e4515,0xdb46a663,0x10c3a9b0,0x8eda7748,0x52bb44c9,0x3df62689,0xc83e2732,0xf36c99af, 0x7ec7a94c,0x5c823718,0x6586e58e,0x4b726e75,0xcfe03a05,0x34eb2f4b,0xf4eec9cf,0xb38d6d73, 0x71fafa9e,0x0371a29a,0xc405f83b,0x889f49c2,0xd1443000,0x469665bf,0x609ed65d,0x67c8f9ba, 0x9d2f6055,0xb91b8eb1,0x96c809fe,0x2d6ab0f5,0xc16d4f04,0x590171ab,0x73d67526,0xf724e44c, 0x6aef02b7,0x6489a325,0x4458401e,0x22d94ad7,0x05e5be57,0x5634fad8,0x951fcf70,0x4baad7f0, 0x40c1090d,0xedc28abd,0x343cc6e4,0x4ff7c030,0x0734a641,0x2635a90e,0x2e000c84,0x4b617a70, 0x872e9c9e,0x3dceeb42,0xd0fcc398,0x9cc9b9c8,0x2de02f0c,0xaf0e2614,0xa60253aa,0xe0517492, 0xa7bde4b4,0x3bb66d7d,0x7f215e82,0xf259de66,0xe17380fe,0xdbc718b4,0x66abcc29,0xf0826e1f, 0x08f60995,0xce81b933,0xa832c0e9,0x37aed7d4,0x8a75c261,0x916627b4,0xd486a04b,0x64fd0fde, 0x1261328a,0xe037772f,0xb5b71117,0x55d04bd8,0x8f6c1c7b,0xb9f5fcdd,0x5918f756,0x25c90099, 0x2e8787db,0x58e14e38,0x0d397852,0x32c8e33b,0x5ae2b795,0x3a7b3ff7,0x5eebf893,0x1aeee816, 0xc2ef31d0,0x1d86e615,0x183f1de3,0xb89d46c4,0x525ebbf6,0xfe0198ca,0x4986cc4a,0x2a75701e, 0x382158b1,0x192ee88f,0x3e512912,0xcd571c3d,0xdf694fe8,0xec8ead1d,0x83719ac3,0x3f654079, 0xf6a623c5,0x33e1fc6e,0xe7f7c426,0x5bff0f6c,0x698a9bb1,0xec2a29ba,0x75358b45,0x40c6ffef, 0x6605bb55,0x53a8c97a,0x7bba1569,0x499bc51b,0x5849c89a,0xe6ddb267,0x8659c719,0x14a05548, 0xeec648a9,0x618af87a,0x62214521,0x7f36e610,0x152efeeb,0xc2b0f0ed,0x1d657588,0xa5fcec4b, 0xf872f109,0x46903038,0x04b57b97,0xe5d51b14,0x06c264ec,0x68aa8d14,0xa4e1bed8,0xdae169c2, 0xeb90debd,0xe8c11a7a,0xcafce013,0x63820cee,0x948c23e5,0xc1d42ea3,0x8256c951,0x9b587773, 0x2fa8380c,0x30255e09,0x1a809cdc,0xe1446068,0x2714621d,0xb3347d64,0x1f4cbf3d,0xd068bc26, 0x2c422740,0x06c4a3ad,0x5dc9d63c,0x4724bf48,0x28e34add,0x27d5221d,0xe349c7e2,0x6119e0a5, 0x4ae7d29f,0x53a7912d,0xfc5db779,0x7d28d357,0xfd80036d,0x06bcc597,0x36d70a8a,0x37738cb7, 0xf11e6272,0xfdd5d153,0x5dc666dc,0x6b5a415d,0x1073b415,0x36f30d9a,0x807daf7b,0x387f6823, 0x8970fe00,0xee560be5,0xea8c0bad,0xfac2b422,0xc845861d,0xa181a2ee,0x29c4dffd,0x4d441bb2, 0x7a64cf93,0x0c33e6ac,0x0a35d034,0x1067d26d,0x8c7da0cc,0x2d6e2d5a,0x9932c25a,0x5fca4e2c, 0x2c82fd71,0x41730b70,0x244bdbb9,0x96514307,0xc6a32a6b,0xc4c256a7,0x38517fd8,0x541aa859, 0x0752afe3,0x741e22f9,0xa2565483,0x7588b0b9,0xdd404e42,0x4d86c49d,0x6fa93fc1,0x163bd200, 0x745d0d31,0x8d3dd20e,0xebdc64db,0x9315c149,0x39db3299,0xb0c22004,0xa4c0295b,0x8b3573eb, 0xd92a40a3,0x73d6c379,0x67673309,0xdaff1d7f,0x42fcfeb8,0xd57c11a4,0x402066ef,0x9d1134e0, 0x9f417081,0x10f49e00,0x7e7ee855,0x314e6d25,0x602bdbe6,0xa4be4045,0xac511dc4,0x33d6bda8, 0x2f2bc412,0x4b9c0b6c,0x98aaab06,0x7f0a5801,0xfbf1f16d,0x058f54ae,0x4fd97724,0x348cb50b, 0xef6f659f,0x0cd8b184,0x1d71a666,0xae3c87dd,0x7bd56793,0xe0f8f6a8,0x90429c55,0x8a3cc4d0, 0x49957b70,0x3baf3912,0x755efebb,0xa5eca17f,0x486065a1,0x1dffcefb,0xd914b3a0,0x1ced93c1, 0xa4262dcd,0xc12a4adc,0x08f6de4e,0x4c204faf,0xca1815de,0xa4af836f,0x91d5e44d,0xd2a7caa4, 0x68a9a3fe,0x844f8dac,0x3fc36c67,0x8be23937,0x69879d94,0x5d0dbecb,0x1f0f59a4,0x94721142, 0xfca6064a,0x6d28aa48,0x804cd04e,0x4a3906de,0x8e352509,0x302326d9,0xed4937ed,0x4a570e63, 0xcaa57efb,0x64bd4878,0x3419334a,0x712e5f6b,0x9fa9d687,0x06f8645f,0x620ca96f,0xdc5d6cce, 0x392f3257,0x52140f06,0xc4b3bda4,0xe8c7eba7,0x066bd754,0xc5941f26,0xe6dfd573,0x328dd14d, 0xb1cb4ba7,0x1d37a9b8,0x96a195a5,0x970e535a,0x290351b8,0x570000f6,0xe14ae341,0x35ede6a6, 0x9a02f032,0xaf2ebb58,0x146be492,0x670b3e4b,0x72fa6cfd,0xa243af97,0xbbd5fc21,0xcb8852a2, 0x5d5b4a42,0xeefff0ac,0xa59ad1b6,0x3ec55544,0x48d64f69,0x9065d3d0,0xdd09485b,0xdd63bd09, 0x605e811d,0xc4b4ed7d,0xb0b58558,0x0644400b,0x12222346,0x086f146a,0xad6dee36,0x5488d1a3, 0x0c93bc0c,0x18555d92,0x9f4427bf,0xa590a66a,0x3a630fda,0xf1681c2e,0x948a16fb,0x16fe3338, 0xc9832357,0xd1e8e6b5,0xd9cfe034,0x05b22f26,0x27233c6e,0x355890e1,0xfbe6eaf3,0x0dcd8e8f, 0x00b5df46,0xd97730ac,0xc6dfd8ff,0x0cb1840a,0x41e9d249,0xbb471b4e,0x480b8f63,0x1ffe8871, 0x17b11821,0x1709e440,0xcefb3668,0xa4954ddd,0xf03ef8b5,0x6b3e633c,0xe5813096,0x3697c9a6, 0x7800f52f,0x73a7aa39,0x59ac23b7,0xb4663166,0x9ca9d6f8,0x2d441072,0x38cef3d3,0x39a3faf6, 0x89299fb9,0xd558295f,0xcf79c633,0x232dd96e,0xadb2955b,0xe962cbb9,0xab7c0061,0x1027c329, 0xb4b43e07,0x25240a7a,0x98ea4825,0xdbf2edbd,0x8be15d26,0x879f3cd9,0xa4138089,0xa32dcb06, 0x602af961,0x4b13f451,0x1c87d0d5,0xc3bb141b,0x9ebf55a1,0xef030a9a,0x8d199b93,0xdabcbb56, 0xf412f80f,0x302e90ad,0xc4d9878b,0xc392f650,0x4fd3a614,0x0a96ddc4,0xcd1878c7,0x9ddd3ae1, 0xdaf46458,0xba7c8656,0xf667948f,0xc37e3c23,0x04a577c6,0xbe615f1e,0xcc97406c,0xd497f16f, 0x79586586,0xd2057d14,0x1bb92028,0xab888e5e,0x26bef100,0xf46b3671,0xf21f1acc,0x67f288c8, 0x39c722df,0x61d21eaf,0x9c5853a0,0x63b693c7,0x1ea53c0a,0x95bc0a85,0xa7372f2d,0x3ef6a6b3, 0x82c9c4ac,0x4dea10ee,0xdfcb543d,0xd412f427,0x53e27f2c,0x875d8422,0x5367a7d8,0x41acf3fa, 0xbce47234,0x8056fb9a,0x4e9a4c48,0xe4a45945,0x2cfee3ae,0xb4554b10,0x5e37a915,0x591b1963, 0x4fa255c1,0xe01c897b,0x504e6208,0x7c7368eb,0x13808fd7,0x02ac0816,0x30305d2c,0x6c4bbdb7, 0xa48a9599,0x57466059,0x4c6ebfc7,0x8587ccdf,0x6ff0abf0,0x5b6b63fe,0x31d9ec64,0x63458abd, 0x21245905,0xccdb28fc,0xac828acb,0xe5e82bea,0xa7d76141,0xa699038e,0xcaba7e06,0x2710253f, 0x2ff9c94d,0x26e48a2c,0xd713ec5e,0x869f2ed4,0x25bcd712,0xcb3e918f,0x615c3a5a,0x9fb43903, 0x37900eb9,0x4f682db0,0x35a80dc6,0x4eb27c65,0x502735ab,0xb163b4c8,0x604649a8,0xb23a6cd3, 0x9f715091,0x2e6fbb51,0x2ec9144b,0x272cbe65,0x90a0a453,0x420e1503,0x2d00d338,0x4aa96675, 0xd025b61c,0xab02d9d7,0x2afe2a37,0xf8129b9b,0x4db04c54,0x654a5c06,0x3213ff51,0x4e09d0b1, 0x333369a3,0xae27310a,0x91d076d0,0xa96ebcd0,0xefde54f4,0x021c309a,0xd506f53d,0xa5635251, 0x2f23916e,0x1fe86bb1,0xcbc62160,0x2147c8cc,0xdeb3e47c,0x028e3987,0x8061de42,0x39be931b, 0x2b7e54c5,0xe64d2f96,0x4069522d,0x4aa66857,0x83b62634,0x4ba72095,0x9aade2a9,0xf1223cd9, 0x91cbddf0,0xec5d237f,0x593f3280,0x0b924439,0x446f4063,0xc66f8d8c,0x8b7128ba,0xb597f451, 0xc8925236,0x1720f235,0x7cd2e9a0,0x4c130339,0x8a665a52,0x5bef2733,0xba35d9bc,0x6d26644c, 0x385cdce1,0x509e4280,0x12aa9ed7,0xf5314d21,0xbe249d4a,0xf32e9753,0x91821cf9,0x01d63491, 0x49afa237,0x80e0bc27,0x844d796b,0xeff5ccb7,0x46303091,0x743484b4,0x77de1ab7,0x5ab00bea, 0x6316cd81,0x8ded07f4,0x3845a3a5,0x206625c4,0x8c123c6f,0xc80a971e,0xd4d4fa3f,0x5eba911d, 0xee168406,0x61cdcbad,0x981a44cd,0x718d030f,0xf653e92e,0xd5b77859,0x11e9e5d9,0xf6fe6ff3, 0x5239f010,0xe289b21b,0x0b52832b,0xca700c62,0xee7a5e15,0x8543ce2c,0x94a703cc,0x0b844d34, 0xf70638e5,0xfa286206,0xf8778906,0x1419e883,0xdb0fc46b,0xbeb74261,0xc6957b62,0x8352d2a8, 0x460586ce,0x90b28336,0xc9107ea8,0x3590403b,0x259a4279,0x6a1a7bbe,0x0f3b76e1,0x4872a716, 0xa5bfff13,0x8b30be72,0xe5a68957,0x17dbbc52,0x33a40187,0x7074220c,0xd8221b92,0x40ec7448, 0x7dbbcdfc,0xd5a9bb83,0xb4c0d25c,0xa0040390,0x6fb429dc,0xb8cede12,0x87d193bd,0x55c6e004 }; //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define ISO_NUM_INTS 3 typedef struct Iso_Obj_t_ Iso_Obj_t; struct Iso_Obj_t_ { // hashing entries (related to the parameter ISO_NUM_INTS!) unsigned Level : 30; unsigned nFinNeg : 2; unsigned FaninSig; unsigned FanoutSig; // other data int iNext; // hash table entry int iClass; // next one in class int Id; // unique ID }; typedef struct Iso_Man_t_ Iso_Man_t; struct Iso_Man_t_ { Aig_Man_t * pAig; // user's AIG manager Iso_Obj_t * pObjs; // isomorphism objects int nObjIds; // counter of object IDs int nClasses; // total number of classes int nEntries; // total number of entries int nSingles; // total number of singletons int nObjs; // total objects int nBins; // hash table size int * pBins; // hash table Vec_Ptr_t * vSingles; // singletons Vec_Ptr_t * vClasses; // other classes Vec_Ptr_t * vTemp1; // other classes Vec_Ptr_t * vTemp2; // other classes abctime timeHash; abctime timeFout; abctime timeSort; abctime timeOther; abctime timeTotal; }; static inline Iso_Obj_t * Iso_ManObj( Iso_Man_t * p, int i ) { assert( i >= 0 && i < p->nObjs ); return i ? p->pObjs + i : NULL; } static inline int Iso_ObjId( Iso_Man_t * p, Iso_Obj_t * pObj ) { assert( pObj > p->pObjs && pObj < p->pObjs + p->nObjs ); return pObj - p->pObjs; } static inline Aig_Obj_t * Iso_AigObj( Iso_Man_t * p, Iso_Obj_t * q ) { return Aig_ManObj( p->pAig, Iso_ObjId(p, q) ); } #define Iso_ManForEachObj( p, pObj, i ) \ for ( i = 1; (i < p->nObjs) && ((pObj) = Iso_ManObj(p, i)); i++ ) if ( pIso->Level == -1 ) {} else //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //extern void Iso_ReadPrimes( char * pFileName ); //Iso_ReadPrimes( "primes.txt" ); /**Function************************************************************* Synopsis [Read primes from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Iso_ReadPrimes( char * pFileName ) { FILE * pFile; int Nums[10000]; int i, j, Temp, nSize = 0; // read the numbers pFile = fopen( pFileName, "rb" ); while ( fscanf( pFile, "%d", Nums + nSize++ ) == 1 ); fclose( pFile ); assert( nSize >= (1<<10) ); // randomly permute srand( 111 ); for ( i = 0; i < nSize; i++ ) { j = rand() % nSize; Temp = Nums[i]; Nums[i] = Nums[j]; Nums[j] = Temp; } // write out for ( i = 0; i < 64; i++ ) { printf( " " ); for ( j = 0; j < 16; j++ ) printf( "%d,", Nums[i*16+j] ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Read primes from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Iso_FindNumbers() { unsigned Nums[1024]; unsigned char * pNums = (unsigned char *)Nums; int i, j; srand( 111 ); for ( i = 0; i < 1024 * 4; i++ ) pNums[i] = (unsigned char)rand(); // write out for ( i = 0; i < 128; i++ ) { printf( " " ); for ( j = 0; j < 8; j++ ) printf( "0x%08x,", Nums[i*8+j] ); printf( "\n" ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Iso_ManObjCount_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int * pnNodes, int * pnEdges ) { if ( Aig_ObjIsCi(pObj) ) return; if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); Iso_ManObjCount_rec( p, Aig_ObjFanin0(pObj), pnNodes, pnEdges ); Iso_ManObjCount_rec( p, Aig_ObjFanin1(pObj), pnNodes, pnEdges ); (*pnEdges) += Aig_ObjFaninC0(pObj) + Aig_ObjFaninC1(pObj); (*pnNodes)++; } void Iso_ManObjCount( Aig_Man_t * p, Aig_Obj_t * pObj, int * pnNodes, int * pnEdges ) { assert( Aig_ObjIsNode(pObj) ); *pnNodes = *pnEdges = 0; Aig_ManIncrementTravId( p ); Iso_ManObjCount_rec( p, pObj, pnNodes, pnEdges ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Iso_Man_t * Iso_ManStart( Aig_Man_t * pAig ) { Iso_Man_t * p; p = ABC_CALLOC( Iso_Man_t, 1 ); p->pAig = pAig; p->nObjs = Aig_ManObjNumMax( pAig ); p->pObjs = ABC_CALLOC( Iso_Obj_t, p->nObjs ); p->nBins = Abc_PrimeCudd( p->nObjs ); p->pBins = ABC_CALLOC( int, p->nBins ); p->vSingles = Vec_PtrAlloc( 1000 ); p->vClasses = Vec_PtrAlloc( 1000 ); p->vTemp1 = Vec_PtrAlloc( 1000 ); p->vTemp2 = Vec_PtrAlloc( 1000 ); p->nObjIds = 1; return p; } void Iso_ManStop( Iso_Man_t * p, int fVerbose ) { if ( fVerbose ) { p->timeOther = p->timeTotal - p->timeHash - p->timeFout; ABC_PRTP( "Building ", p->timeFout, p->timeTotal ); ABC_PRTP( "Hashing ", p->timeHash-p->timeSort, p->timeTotal ); ABC_PRTP( "Sorting ", p->timeSort, p->timeTotal ); ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); } Vec_PtrFree( p->vTemp1 ); Vec_PtrFree( p->vTemp2 ); Vec_PtrFree( p->vClasses ); Vec_PtrFree( p->vSingles ); ABC_FREE( p->pBins ); ABC_FREE( p->pObjs ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Compares two objects by their signature.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Iso_ObjCompare( Iso_Obj_t ** pp1, Iso_Obj_t ** pp2 ) { return -memcmp( *pp1, *pp2, sizeof(int) * ISO_NUM_INTS ); } /**Function************************************************************* Synopsis [Compares two objects by their ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Iso_ObjCompareByData( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ) { Aig_Obj_t * pIso1 = *pp1; Aig_Obj_t * pIso2 = *pp2; assert( Aig_ObjIsCi(pIso1) || Aig_ObjIsCo(pIso1) ); assert( Aig_ObjIsCi(pIso2) || Aig_ObjIsCo(pIso2) ); return pIso1->iData - pIso2->iData; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Iso_ObjHash( Iso_Obj_t * pIso, int nBins ) { static unsigned BigPrimes[8] = {12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741}; unsigned * pArray = (unsigned *)pIso; unsigned i, Value = 0; assert( ISO_NUM_INTS < 8 ); for ( i = 0; i < ISO_NUM_INTS; i++ ) Value ^= BigPrimes[i] * pArray[i]; return Value % nBins; } static inline int Iso_ObjHashAdd( Iso_Man_t * p, Iso_Obj_t * pIso ) { Iso_Obj_t * pThis; int * pPlace = p->pBins + Iso_ObjHash( pIso, p->nBins ); p->nEntries++; for ( pThis = Iso_ManObj(p, *pPlace); pThis; pPlace = &pThis->iNext, pThis = Iso_ManObj(p, *pPlace) ) if ( Iso_ObjCompare( &pThis, &pIso ) == 0 ) // equal signatures { if ( pThis->iClass == 0 ) { p->nClasses++; p->nSingles--; } // add to the list pIso->iClass = pThis->iClass; pThis->iClass = Iso_ObjId( p, pIso ); return 1; } // create new list *pPlace = Iso_ObjId( p, pIso ); p->nSingles++; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Iso_ManCollectClasses( Iso_Man_t * p ) { Iso_Obj_t * pIso; int i; abctime clk = Abc_Clock(); Vec_PtrClear( p->vSingles ); Vec_PtrClear( p->vClasses ); for ( i = 0; i < p->nBins; i++ ) { for ( pIso = Iso_ManObj(p, p->pBins[i]); pIso; pIso = Iso_ManObj(p, pIso->iNext) ) { assert( pIso->Id == 0 ); if ( pIso->iClass ) Vec_PtrPush( p->vClasses, pIso ); else Vec_PtrPush( p->vSingles, pIso ); } } clk = Abc_Clock(); 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 ); // assign IDs to singletons Vec_PtrForEachEntry( Iso_Obj_t *, p->vSingles, pIso, i ) if ( pIso->Id == 0 ) pIso->Id = p->nObjIds++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Iso_Man_t * Iso_ManCreate( Aig_Man_t * pAig ) { int fUseXor = 0; Iso_Man_t * p; Iso_Obj_t * pIso, * pIsoF; Aig_Obj_t * pObj, * pObjLi; int i; p = Iso_ManStart( pAig ); // create TFI signatures Aig_ManForEachObj( pAig, pObj, i ) { if ( Aig_ObjIsCo(pObj) ) continue; pIso = p->pObjs + i; pIso->Level = pObj->Level; // pIso->nFinNeg = Aig_ObjFaninC0(pObj) + Aig_ObjFaninC1(pObj); assert( pIso->FaninSig == 0 ); assert( pIso->FanoutSig == 0 ); if ( fUseXor ) { if ( Aig_ObjIsNode(pObj) ) { pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); pIso->FaninSig ^= pIsoF->FaninSig; pIso->FaninSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK]; pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); pIso->FaninSig ^= pIsoF->FaninSig; pIso->FaninSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC1(pObj)) & ISO_MASK]; } } else { if ( Aig_ObjIsNode(pObj) ) { pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); pIso->FaninSig += pIsoF->FaninSig; pIso->FaninSig += pIso->Level * s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK]; pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); pIso->FaninSig += pIsoF->FaninSig; pIso->FaninSig += pIso->Level * s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC1(pObj)) & ISO_MASK]; } } } // create TFO signatures Aig_ManForEachObjReverse( pAig, pObj, i ) { if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) continue; pIso = p->pObjs + i; if ( fUseXor ) { if ( Aig_ObjIsNode(pObj) ) { pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); pIsoF->FanoutSig ^= pIso->FanoutSig; pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK]; pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); pIsoF->FanoutSig ^= pIso->FanoutSig; pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC1(pObj)) & ISO_MASK]; } else if ( Aig_ObjIsCo(pObj) ) { pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); pIsoF->FanoutSig ^= pIso->FanoutSig; pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK]; } } else { if ( Aig_ObjIsNode(pObj) ) { pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); pIsoF->FanoutSig += pIso->FanoutSig; pIsoF->FanoutSig += pIso->Level * s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK]; pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); pIsoF->FanoutSig += pIso->FanoutSig; pIsoF->FanoutSig += pIso->Level * s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC1(pObj)) & ISO_MASK]; } else if ( Aig_ObjIsCo(pObj) ) { pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); pIsoF->FanoutSig += pIso->FanoutSig; pIsoF->FanoutSig += pIso->Level * s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK]; } } } // consider flops Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObj, i ) { if ( Aig_ObjFaninId0(pObjLi) == 0 ) // ignore constant! continue; pIso = Iso_ManObj( p, Aig_ObjId(pObj) ); pIsoF = Iso_ManObj( p, Aig_ObjFaninId0(pObjLi) ); assert( pIso->FaninSig == 0 ); pIso->FaninSig = pIsoF->FaninSig; // assert( pIsoF->FanoutSig == 0 ); pIsoF->FanoutSig += pIso->FanoutSig; } /* Aig_ManForEachObj( pAig, pObj, i ) { pIso = p->pObjs + i; Aig_ObjPrint( pAig, pObj ); printf( "Lev = %4d. Pos = %4d. FaninSig = %10d. FanoutSig = %10d.\n", pIso->Level, pIso->nFinNeg, pIso->FaninSig, pIso->FanoutSig ); } */ // add to the hash table Aig_ManForEachObj( pAig, pObj, i ) { if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) continue; pIso = p->pObjs + i; Iso_ObjHashAdd( p, pIso ); } // derive classes for the first time Iso_ManCollectClasses( p ); return p; } /**Function************************************************************* Synopsis [Creates adjacency lists.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Iso_ManAssignAdjacency( Iso_Man_t * p ) { int fUseXor = 0; Iso_Obj_t * pIso, * pIsoF; Aig_Obj_t * pObj, * pObjLi; int i; // create TFI signatures Aig_ManForEachObj( p->pAig, pObj, i ) { pIso = p->pObjs + i; pIso->FaninSig = 0; pIso->FanoutSig = 0; if ( Aig_ObjIsCo(pObj) ) continue; if ( fUseXor ) { if ( Aig_ObjIsNode(pObj) ) { pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); pIso->FaninSig ^= pIsoF->FaninSig; if ( pIsoF->Id ) pIso->FaninSig ^= s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK]; pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); pIso->FaninSig ^= pIsoF->FaninSig; if ( pIsoF->Id ) pIso->FaninSig ^= s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC1(pObj)) & ISO_MASK]; } } else { if ( Aig_ObjIsNode(pObj) ) { pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); pIso->FaninSig += pIsoF->FaninSig; if ( pIsoF->Id ) pIso->FaninSig += pIsoF->Id * s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK]; pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); pIso->FaninSig += pIsoF->FaninSig; if ( pIsoF->Id ) pIso->FaninSig += pIsoF->Id * s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC1(pObj)) & ISO_MASK]; } } } // create TFO signatures Aig_ManForEachObjReverse( p->pAig, pObj, i ) { if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) continue; pIso = p->pObjs + i; assert( !Aig_ObjIsCo(pObj) || pIso->Id == 0 ); if ( fUseXor ) { if ( Aig_ObjIsNode(pObj) ) { pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); pIsoF->FanoutSig ^= pIso->FanoutSig; if ( pIso->Id ) pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK]; pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); pIsoF->FanoutSig ^= pIso->FanoutSig; if ( pIso->Id ) pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC1(pObj)) & ISO_MASK]; } else if ( Aig_ObjIsCo(pObj) ) { pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); pIsoF->FanoutSig ^= pIso->FanoutSig; if ( pIso->Id ) pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK]; } } else { if ( Aig_ObjIsNode(pObj) ) { pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); pIsoF->FanoutSig += pIso->FanoutSig; if ( pIso->Id ) pIsoF->FanoutSig += pIso->Id * s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK]; pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); pIsoF->FanoutSig += pIso->FanoutSig; if ( pIso->Id ) pIsoF->FanoutSig += pIso->Id * s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC1(pObj)) & ISO_MASK]; } else if ( Aig_ObjIsCo(pObj) ) { pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); pIsoF->FanoutSig += pIso->FanoutSig; if ( pIso->Id ) pIsoF->FanoutSig += pIso->Id * s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK]; } } } // consider flops Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObj, i ) { if ( Aig_ObjFaninId0(pObjLi) == 0 ) // ignore constant! continue; pIso = Iso_ManObj( p, Aig_ObjId(pObj) ); pIsoF = Iso_ManObj( p, Aig_ObjFaninId0(pObjLi) ); assert( pIso->FaninSig == 0 ); // assert( pIsoF->FanoutSig == 0 ); if ( fUseXor ) { pIso->FaninSig = pIsoF->FaninSig; if ( pIsoF->Id ) pIso->FaninSig ^= s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC0(pObjLi)) & ISO_MASK]; pIsoF->FanoutSig += pIso->FanoutSig; if ( pIso->Id ) pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObjLi)) & ISO_MASK]; } else { pIso->FaninSig = pIsoF->FaninSig; if ( pIsoF->Id ) pIso->FaninSig += pIsoF->Id * s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC0(pObjLi)) & ISO_MASK]; pIsoF->FanoutSig += pIso->FanoutSig; if ( pIso->Id ) pIsoF->FanoutSig += pIso->Id * s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObjLi)) & ISO_MASK]; } } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Iso_ManPrintClasseSizes( Iso_Man_t * p ) { Iso_Obj_t * pIso, * pTemp; int i, Counter; Vec_PtrForEachEntry( Iso_Obj_t *, p->vClasses, pIso, i ) { Counter = 0; for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) ) Counter++; printf( "%d ", Counter ); } printf( "\n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Iso_ManPrintClasses( Iso_Man_t * p, int fVerbose, int fVeryVerbose ) { int fOnlyCis = 0; Iso_Obj_t * pIso, * pTemp; int i; // count unique objects if ( fVerbose ) printf( "Total objects =%7d. Entries =%7d. Classes =%7d. Singles =%7d.\n", p->nObjs, p->nEntries, p->nClasses, p->nSingles ); if ( !fVeryVerbose ) return; printf( "Non-trivial classes:\n" ); Vec_PtrForEachEntry( Iso_Obj_t *, p->vClasses, pIso, i ) { if ( fOnlyCis && pIso->Level > 0 ) continue; printf( "%5d : {", i ); for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) ) { if ( fOnlyCis ) printf( " %d", Aig_ObjCioId( Iso_AigObj(p, pTemp) ) ); else { Aig_Obj_t * pObj = Iso_AigObj(p, pTemp); if ( Aig_ObjIsNode(pObj) ) printf( " %d{%s%d(%d),%s%d(%d)}", Iso_ObjId(p, pTemp), Aig_ObjFaninC0(pObj)? "-": "+", Aig_ObjFaninId0(pObj), Aig_ObjLevel(Aig_ObjFanin0(pObj)), Aig_ObjFaninC1(pObj)? "-": "+", Aig_ObjFaninId1(pObj), Aig_ObjLevel(Aig_ObjFanin1(pObj)) ); else printf( " %d", Iso_ObjId(p, pTemp) ); } printf( "(%d)", pTemp->Level ); } printf( " }\n" ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Iso_ManRehashClassNodes( Iso_Man_t * p ) { Iso_Obj_t * pIso, * pTemp; int i; // collect nodes Vec_PtrClear( p->vTemp1 ); Vec_PtrClear( p->vTemp2 ); Vec_PtrForEachEntry( Iso_Obj_t *, p->vClasses, pIso, i ) { for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) ) if ( pTemp->Id == 0 ) Vec_PtrPush( p->vTemp1, pTemp ); else Vec_PtrPush( p->vTemp2, pTemp ); } // clean and add nodes p->nClasses = 0; // total number of classes p->nEntries = 0; // total number of entries p->nSingles = 0; // total number of singletons memset( p->pBins, 0, sizeof(int) * p->nBins ); Vec_PtrForEachEntry( Iso_Obj_t *, p->vTemp1, pTemp, i ) { assert( pTemp->Id == 0 ); pTemp->iClass = pTemp->iNext = 0; Iso_ObjHashAdd( p, pTemp ); } Vec_PtrForEachEntry( Iso_Obj_t *, p->vTemp2, pTemp, i ) { assert( pTemp->Id != 0 ); pTemp->iClass = pTemp->iNext = 0; } // collect new classes Iso_ManCollectClasses( p ); } /**Function************************************************************* Synopsis [Find nodes with the min number of edges.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Iso_Obj_t * Iso_ManFindBestObj( Iso_Man_t * p, Iso_Obj_t * pIso ) { Iso_Obj_t * pTemp, * pBest = NULL; int nNodesBest = -1, nNodes; int nEdgesBest = -1, nEdges; assert( pIso->Id == 0 ); if ( pIso->Level == 0 ) return pIso; for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) ) { assert( pTemp->Id == 0 ); Iso_ManObjCount( p->pAig, Iso_AigObj(p, pTemp), &nNodes, &nEdges ); // printf( "%d,%d ", nNodes, nEdges ); if ( nNodesBest < nNodes || (nNodesBest == nNodes && nEdgesBest < nEdges) ) { nNodesBest = nNodes; nEdgesBest = nEdges; pBest = pTemp; } } // printf( "\n" ); return pBest; } /**Function************************************************************* Synopsis [Find nodes with the min number of edges.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Iso_ManBreakTies( Iso_Man_t * p, int fVerbose ) { int fUseOneBest = 0; Iso_Obj_t * pIso, * pTemp; int i, LevelStart = 0; pIso = (Iso_Obj_t *)Vec_PtrEntry( p->vClasses, 0 ); LevelStart = pIso->Level; if ( fVerbose ) printf( "Best level %d\n", LevelStart ); Vec_PtrForEachEntry( Iso_Obj_t *, p->vClasses, pIso, i ) { if ( (int)pIso->Level < LevelStart ) break; if ( !fUseOneBest ) { for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) ) { assert( pTemp->Id == 0 ); pTemp->Id = p->nObjIds++; } continue; } if ( pIso->Level == 0 )//&& pIso->nFoutPos + pIso->nFoutNeg == 0 ) { for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) ) pTemp->Id = p->nObjIds++; continue; } pIso = Iso_ManFindBestObj( p, pIso ); pIso->Id = p->nObjIds++; } } /**Function************************************************************* Synopsis [Finalizes unification of combinational outputs.] Description [Assigns IDs to the unclassified CIs in the order of obj IDs.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Iso_ManFinalize( Iso_Man_t * p ) { Vec_Int_t * vRes; Aig_Obj_t * pObj; int i; assert( p->nClasses == 0 ); assert( Vec_PtrSize(p->vClasses) == 0 ); // set canonical numbers Aig_ManForEachObj( p->pAig, pObj, i ) { if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) { pObj->iData = -1; continue; } pObj->iData = Iso_ManObj(p, Aig_ObjId(pObj))->Id; assert( pObj->iData > 0 ); } Aig_ManConst1(p->pAig)->iData = 0; // assign unique IDs to the CIs Vec_PtrClear( p->vTemp1 ); Vec_PtrClear( p->vTemp2 ); Aig_ManForEachCi( p->pAig, pObj, i ) { assert( pObj->iData > 0 ); if ( Aig_ObjCioId(pObj) >= Aig_ManCiNum(p->pAig) - Aig_ManRegNum(p->pAig) ) // flop Vec_PtrPush( p->vTemp2, pObj ); else // PI Vec_PtrPush( p->vTemp1, pObj ); } // sort CIs by their IDs 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 ) Vec_IntPush( vRes, Aig_ObjCioId(pObj) ); Vec_PtrForEachEntry( Aig_Obj_t *, p->vTemp2, pObj, i ) Vec_IntPush( vRes, Aig_ObjCioId(pObj) ); return vRes; } /**Function************************************************************* Synopsis [Find nodes with the min number of edges.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Iso_ManDumpOneClass( Iso_Man_t * p ) { Vec_Ptr_t * vNodes = Vec_PtrAlloc( 100 ); Iso_Obj_t * pIso, * pTemp; Aig_Man_t * pNew = NULL; assert( p->nClasses > 0 ); pIso = (Iso_Obj_t *)Vec_PtrEntry( p->vClasses, 0 ); assert( pIso->Id == 0 ); for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) ) { assert( pTemp->Id == 0 ); Vec_PtrPush( vNodes, Iso_AigObj(p, pTemp) ); } pNew = Aig_ManDupNodes( p->pAig, vNodes ); Vec_PtrFree( vNodes ); Aig_ManShow( pNew, 0, NULL ); Aig_ManStopP( &pNew ); } /**Function************************************************************* Synopsis [Finds canonical permutation of CIs and assigns unique IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_ManFindIsoPerm( Aig_Man_t * pAig, int fVerbose ) { int fVeryVerbose = 0; Vec_Int_t * vRes; Iso_Man_t * p; abctime clk = Abc_Clock(), clk2 = Abc_Clock(); p = Iso_ManCreate( pAig ); p->timeFout += Abc_Clock() - clk; Iso_ManPrintClasses( p, fVerbose, fVeryVerbose ); while ( p->nClasses ) { // assign adjacency to classes clk = Abc_Clock(); Iso_ManAssignAdjacency( p ); p->timeFout += Abc_Clock() - clk; // rehash the class nodes clk = Abc_Clock(); Iso_ManRehashClassNodes( p ); p->timeHash += Abc_Clock() - clk; Iso_ManPrintClasses( p, fVerbose, fVeryVerbose ); // force refinement while ( p->nSingles == 0 && p->nClasses ) { // Iso_ManPrintClasseSizes( p ); // assign IDs to the topmost level of classes Iso_ManBreakTies( p, fVerbose ); // assign adjacency to classes clk = Abc_Clock(); Iso_ManAssignAdjacency( p ); p->timeFout += Abc_Clock() - clk; // rehash the class nodes clk = Abc_Clock(); Iso_ManRehashClassNodes( p ); p->timeHash += Abc_Clock() - clk; Iso_ManPrintClasses( p, fVerbose, fVeryVerbose ); } } p->timeTotal = Abc_Clock() - clk2; // printf( "IDs assigned = %d. Objects = %d.\n", p->nObjIds, 1+Aig_ManCiNum(p->pAig)+Aig_ManNodeNum(p->pAig) ); assert( p->nObjIds == 1+Aig_ManCiNum(p->pAig)+Aig_ManNodeNum(p->pAig) ); // if ( p->nClasses ) // Iso_ManDumpOneClass( p ); vRes = Iso_ManFinalize( p ); Iso_ManStop( p, fVerbose ); return vRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigMiter.c000066400000000000000000001222361477524141600165500ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigMiter.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Computes sequential miter of two sequential AIGs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigMiter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "proof/fra/fra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks the status of the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Sec_MtrStatus_t Sec_MiterStatus( Aig_Man_t * p ) { Sec_MtrStatus_t Status; Aig_Obj_t * pObj, * pChild; int i; memset( &Status, 0, sizeof(Sec_MtrStatus_t) ); Status.iOut = -1; Status.nInputs = Saig_ManPiNum( p ); Status.nNodes = Aig_ManNodeNum( p ); Status.nOutputs = Saig_ManPoNum(p); Saig_ManForEachPo( p, pObj, i ) { pChild = Aig_ObjChild0(pObj); // check if the output is constant 0 if ( pChild == Aig_ManConst0(p) ) Status.nUnsat++; // check if the output is constant 1 else if ( pChild == Aig_ManConst1(p) ) { Status.nSat++; if ( Status.iOut == -1 ) Status.iOut = i; } // check if the output is a primary input else if ( Saig_ObjIsPi(p, Aig_Regular(pChild)) ) { Status.nSat++; if ( Status.iOut == -1 ) Status.iOut = i; } // check if the output is 1 for the 0000 pattern else if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) ) { Status.nSat++; if ( Status.iOut == -1 ) Status.iOut = i; } else Status.nUndec++; } return Status; } /**Function************************************************************* Synopsis [Creates sequential miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManCreateMiter( Aig_Man_t * p0, Aig_Man_t * p1, int Oper ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; assert( Saig_ManRegNum(p0) > 0 || Saig_ManRegNum(p1) > 0 ); assert( Saig_ManPiNum(p0) == Saig_ManPiNum(p1) ); assert( Saig_ManPoNum(p0) == Saig_ManPoNum(p1) ); pNew = Aig_ManStart( Aig_ManObjNumMax(p0) + Aig_ManObjNumMax(p1) ); pNew->pName = Abc_UtilStrsav( "miter" ); Aig_ManCleanData( p0 ); Aig_ManCleanData( p1 ); // map constant nodes Aig_ManConst1(p0)->pData = Aig_ManConst1(pNew); Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew); // map primary inputs Saig_ManForEachPi( p0, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); Saig_ManForEachPi( p1, pObj, i ) pObj->pData = Aig_ManCi( pNew, i ); // map register outputs Saig_ManForEachLo( p0, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); Saig_ManForEachLo( p1, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); // map internal nodes Aig_ManForEachNode( p0, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); Aig_ManForEachNode( p1, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create primary outputs Saig_ManForEachPo( p0, pObj, i ) { if ( Oper == 0 ) // XOR pObj = Aig_Exor( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild0Copy(Aig_ManCo(p1,i)) ); else if ( Oper == 1 ) // implication is PO(p0) -> PO(p1) ... complement is PO(p0) & !PO(p1) pObj = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_Not(Aig_ObjChild0Copy(Aig_ManCo(p1,i))) ); else assert( 0 ); Aig_ObjCreateCo( pNew, pObj ); } // create register inputs Saig_ManForEachLi( p0, pObj, i ) pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); Saig_ManForEachLi( p1, pObj, i ) pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); // cleanup Aig_ManSetRegNum( pNew, Saig_ManRegNum(p0) + Saig_ManRegNum(p1) ); // Aig_ManCleanup( pNew ); return pNew; } /**Function************************************************************* Synopsis [Creates combinational miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManCreateMiterComb( Aig_Man_t * p0, Aig_Man_t * p1, int Oper ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; assert( Aig_ManCiNum(p0) == Aig_ManCiNum(p1) ); assert( Aig_ManCoNum(p0) == Aig_ManCoNum(p1) ); pNew = Aig_ManStart( Aig_ManObjNumMax(p0) + Aig_ManObjNumMax(p1) ); pNew->pName = Abc_UtilStrsav( "miter" ); // map constant nodes Aig_ManConst1(p0)->pData = Aig_ManConst1(pNew); Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew); // map primary inputs and register outputs Aig_ManForEachCi( p0, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); Aig_ManForEachCi( p1, pObj, i ) pObj->pData = Aig_ManCi( pNew, i ); // map internal nodes Aig_ManForEachNode( p0, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); Aig_ManForEachNode( p1, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create primary outputs Aig_ManForEachCo( p0, pObj, i ) { if ( Oper == 0 ) // XOR pObj = Aig_Exor( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild0Copy(Aig_ManCo(p1,i)) ); else if ( Oper == 1 ) // implication is PO(p0) -> PO(p1) ... complement is PO(p0) & !PO(p1) pObj = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_Not(Aig_ObjChild0Copy(Aig_ManCo(p1,i))) ); else assert( 0 ); Aig_ObjCreateCo( pNew, pObj ); } // cleanup Aig_ManSetRegNum( pNew, 0 ); Aig_ManCleanup( pNew ); return pNew; } /**Function************************************************************* Synopsis [Derives dual-rail AIG.] Description [Orders nodes as follows: PIs, ANDs, POs.] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_AndDualRail( Aig_Man_t * pNew, Aig_Obj_t * pObj, Aig_Obj_t ** ppData, Aig_Obj_t ** ppNext ) { Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj); Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj); Aig_Obj_t * p0Data = Aig_ObjFaninC0(pObj)? pFanin0->pNext : (Aig_Obj_t *)pFanin0->pData; Aig_Obj_t * p0Next = Aig_ObjFaninC0(pObj)? (Aig_Obj_t *)pFanin0->pData : pFanin0->pNext; Aig_Obj_t * p1Data = Aig_ObjFaninC1(pObj)? pFanin1->pNext : (Aig_Obj_t *)pFanin1->pData; Aig_Obj_t * p1Next = Aig_ObjFaninC1(pObj)? (Aig_Obj_t *)pFanin1->pData : pFanin1->pNext; *ppData = Aig_Or( pNew, Aig_And(pNew, p0Data, Aig_Not(p0Next)), Aig_And(pNew, p1Data, Aig_Not(p1Next)) ); *ppNext = Aig_And( pNew, Aig_And(pNew, Aig_Not(p0Data), p0Next), Aig_And(pNew, Aig_Not(p1Data), p1Next) ); } /**Function************************************************************* Synopsis [Derives dual-rail AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDualRail( Aig_Man_t * p, int fMiter ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pMiter; int i; Aig_ManCleanData( p ); Aig_ManCleanNext( p ); // create the new manager pNew = Aig_ManStart( 4*Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // create the PIs Aig_ManConst1(p)->pData = Aig_ManConst0(pNew); Aig_ManConst1(p)->pNext = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) { pObj->pData = Aig_ObjCreateCi( pNew ); pObj->pNext = Aig_ObjCreateCi( pNew ); } // duplicate internal nodes Aig_ManForEachNode( p, pObj, i ) Saig_AndDualRail( pNew, pObj, (Aig_Obj_t **)&pObj->pData, &pObj->pNext ); // add the POs if ( fMiter ) { pMiter = Aig_ManConst1(pNew); Saig_ManForEachLo( p, pObj, i ) { pMiter = Aig_And( pNew, pMiter, Aig_Or(pNew, (Aig_Obj_t *)pObj->pData, pObj->pNext) ); } Aig_ObjCreateCo( pNew, pMiter ); Saig_ManForEachLi( p, pObj, i ) { if ( !Aig_ObjFaninC0(pObj) ) { Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); Aig_ObjCreateCo( pNew, Aig_ObjFanin0(pObj)->pNext ); } else { Aig_ObjCreateCo( pNew, Aig_ObjFanin0(pObj)->pNext ); Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); } } } else { Aig_ManForEachCo( p, pObj, i ) { if ( !Aig_ObjFaninC0(pObj) ) { Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); Aig_ObjCreateCo( pNew, Aig_ObjFanin0(pObj)->pNext ); } else { Aig_ObjCreateCo( pNew, Aig_ObjFanin0(pObj)->pNext ); Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); } } } Aig_ManSetRegNum( pNew, 2*Aig_ManRegNum(p) ); Aig_ManCleanData( p ); Aig_ManCleanNext( p ); Aig_ManCleanup( pNew ); // check the resulting network if ( !Aig_ManCheck(pNew) ) printf( "Aig_ManDupSimple(): The check has failed.\n" ); return pNew; } /**Function************************************************************* Synopsis [Create combinational timeframes by unrolling sequential circuits.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManUnrollTwo( Aig_Man_t * pBot, Aig_Man_t * pTop, int nFrames ) { Aig_Man_t * p, * pAig; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, f; // assert( nFrames > 1 ); assert( Saig_ManPiNum(pBot) == Saig_ManPiNum(pTop) ); assert( Saig_ManPoNum(pBot) == Saig_ManPoNum(pTop) ); assert( Saig_ManRegNum(pBot) == Saig_ManRegNum(pTop) ); assert( Saig_ManRegNum(pBot) > 0 || Saig_ManRegNum(pTop) > 0 ); // start timeframes p = Aig_ManStart( nFrames * Abc_MaxInt(Aig_ManObjNumMax(pBot), Aig_ManObjNumMax(pTop)) ); p->pName = Abc_UtilStrsav( "frames" ); // create variables for register outputs pAig = pBot; Saig_ManForEachLo( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( p ); // add timeframes for ( f = 0; f < nFrames; f++ ) { // create PI nodes for this frame Aig_ManConst1(pAig)->pData = Aig_ManConst1( p ); Saig_ManForEachPi( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( p ); // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); if ( f == nFrames - 1 ) { // create POs for this frame Aig_ManForEachCo( pAig, pObj, i ) Aig_ObjCreateCo( p, Aig_ObjChild0Copy(pObj) ); break; } // create POs for this frame Saig_ManForEachPo( pAig, pObj, i ) Aig_ObjCreateCo( p, Aig_ObjChild0Copy(pObj) ); // save register inputs Saig_ManForEachLi( pAig, pObj, i ) pObj->pData = Aig_ObjChild0Copy(pObj); // transfer to register outputs Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) pObjLo->pData = pObjLi->pData; if ( f == 0 ) { // transfer from pOld to pNew Saig_ManForEachLo( pAig, pObj, i ) Saig_ManLo(pTop, i)->pData = pObj->pData; pAig = pTop; } } Aig_ManCleanup( p ); return p; } /**Function************************************************************* Synopsis [Duplicates the AIG while creating POs from the set.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupNodesAll( Aig_Man_t * p, Vec_Ptr_t * vSet ) { Aig_Man_t * pNew, * pCopy; Aig_Obj_t * pObj; int i; pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Aig_ManForEachCi( p, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); Aig_ManForEachNode( p, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // Saig_ManForEachPo( p, pObj, i ) // pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); Vec_PtrForEachEntry( Aig_Obj_t *, vSet, pObj, i ) Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj)) ); Saig_ManForEachLi( p, pObj, i ) pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); Aig_ManSetRegNum( pNew, Saig_ManRegNum(p) ); // cleanup and return a copy Aig_ManSeqCleanup( pNew ); pCopy = Aig_ManDupSimpleDfs( pNew ); Aig_ManStop( pNew ); return pCopy; } /**Function************************************************************* Synopsis [Duplicates the AIG while creating POs from the set.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManDupNodesHalf( Aig_Man_t * p, Vec_Ptr_t * vSet, int iPart ) { Aig_Man_t * pNew, * pCopy; Aig_Obj_t * pObj; int i; Aig_ManCleanData( p ); pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Saig_ManForEachPi( p, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); if ( iPart == 0 ) { Saig_ManForEachLo( p, pObj, i ) if ( i < Saig_ManRegNum(p)/2 ) pObj->pData = Aig_ObjCreateCi( pNew ); } else { Saig_ManForEachLo( p, pObj, i ) if ( i >= Saig_ManRegNum(p)/2 ) pObj->pData = Aig_ObjCreateCi( pNew ); } Aig_ManForEachNode( p, pObj, i ) if ( Aig_ObjFanin0(pObj)->pData && Aig_ObjFanin1(pObj)->pData ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // Saig_ManForEachPo( p, pObj, i ) // pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); Vec_PtrForEachEntry( Aig_Obj_t *, vSet, pObj, i ) { assert( Aig_Regular(pObj)->pData != NULL ); Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj)) ); } if ( iPart == 0 ) { Saig_ManForEachLi( p, pObj, i ) if ( i < Saig_ManRegNum(p)/2 ) pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } else { Saig_ManForEachLi( p, pObj, i ) if ( i >= Saig_ManRegNum(p)/2 ) pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } Aig_ManSetRegNum( pNew, Saig_ManRegNum(p)/2 ); // cleanup and return a copy // Aig_ManSeqCleanup( pNew ); Aig_ManCleanup( pNew ); pCopy = Aig_ManDupSimpleDfs( pNew ); Aig_ManStop( pNew ); return pCopy; } /**Function************************************************************* Synopsis [Duplicates the AIG to have constant-0 initial state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManDemiterSimple( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ) { Vec_Ptr_t * vSet0, * vSet1; Aig_Obj_t * pObj, * pFanin, * pObj0, * pObj1; int i, Counter = 0; assert( Saig_ManRegNum(p) % 2 == 0 ); vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) ); vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) ); Saig_ManForEachPo( p, pObj, i ) { pFanin = Aig_ObjFanin0(pObj); if ( Aig_ObjIsConst1( pFanin ) ) { if ( !Aig_ObjFaninC0(pObj) ) printf( "The output number %d of the miter is constant 1.\n", i ); Counter++; continue; } if ( !Aig_ObjIsNode(pFanin) || !Aig_ObjRecognizeExor( pFanin, &pObj0, &pObj1 ) ) { printf( "The miter cannot be demitered.\n" ); Vec_PtrFree( vSet0 ); Vec_PtrFree( vSet1 ); return 0; } if ( Aig_ObjFaninC0(pObj) ) pObj0 = Aig_Not(pObj0); // printf( "%d %d ", Aig_Regular(pObj0)->Id, Aig_Regular(pObj1)->Id ); if ( Aig_Regular(pObj0)->Id < Aig_Regular(pObj1)->Id ) { Vec_PtrPush( vSet0, pObj0 ); Vec_PtrPush( vSet1, pObj1 ); } else { Vec_PtrPush( vSet0, pObj1 ); Vec_PtrPush( vSet1, pObj0 ); } } // printf( "Miter has %d constant outputs.\n", Counter ); // printf( "\n" ); if ( ppAig0 ) { *ppAig0 = Aig_ManDupNodesHalf( p, vSet0, 0 ); ABC_FREE( (*ppAig0)->pName ); (*ppAig0)->pName = Abc_UtilStrsav( "part0" ); } if ( ppAig1 ) { *ppAig1 = Aig_ManDupNodesHalf( p, vSet1, 1 ); ABC_FREE( (*ppAig1)->pName ); (*ppAig1)->pName = Abc_UtilStrsav( "part1" ); } Vec_PtrFree( vSet0 ); Vec_PtrFree( vSet1 ); return 1; } /**Function************************************************************* Synopsis [Returns 1 if PO can be demitered.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManDemiterMarkPos( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManCleanMarkAB( p ); Saig_ManForEachLo( p, pObj, i ) if ( i < Saig_ManRegNum(p)/2 ) pObj->fMarkA = 1; else pObj->fMarkB = 1; Aig_ManForEachNode( p, pObj, i ) { pObj->fMarkA = Aig_ObjFanin0(pObj)->fMarkA | Aig_ObjFanin1(pObj)->fMarkA; pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB | Aig_ObjFanin1(pObj)->fMarkB; } } /**Function************************************************************* Synopsis [Returns 1 if PO can be demitered.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManDemiterCheckPo( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t ** ppPo0, Aig_Obj_t ** ppPo1 ) { Aig_Obj_t * pFanin, * pObj0, * pObj1, * pObjR0, * pObjR1; assert( Saig_ObjIsPo(p, pObj) ); pFanin = Aig_ObjFanin0( pObj ); if ( Aig_ObjIsConst1(pFanin) ) { if ( !Aig_ObjFaninC0(pObj) ) return 0; *ppPo0 = Aig_ManConst0(p); *ppPo1 = Aig_ManConst0(p); return 1; } if ( !Aig_ObjIsNode(pFanin) ) return 0; if ( !Aig_ObjRecognizeExor( pFanin, &pObj0, &pObj1 ) ) return 0; if ( Aig_ObjFaninC0(pObj) ) pObj0 = Aig_Not(pObj0); // make sure they can reach only one pObjR0 = Aig_Regular(pObj0); pObjR1 = Aig_Regular(pObj1); if ( (pObjR0->fMarkA && pObjR0->fMarkB) || (pObjR1->fMarkA && pObjR1->fMarkB) || (pObjR0->fMarkA && pObjR1->fMarkA) || (pObjR0->fMarkB && pObjR1->fMarkB) ) return 0; if ( pObjR1->fMarkA && !pObjR0->fMarkA ) { *ppPo0 = pObj1; *ppPo1 = pObj0; } else if ( pObjR0->fMarkA && !pObjR1->fMarkA ) { *ppPo0 = pObj0; *ppPo1 = pObj1; } else { /* printf( "%d", pObjR0->fMarkA ); printf( "%d", pObjR0->fMarkB ); printf( ":" ); printf( "%d", pObjR1->fMarkA ); printf( "%d", pObjR1->fMarkB ); printf( " " ); */ if ( Aig_Regular(pObj0)->Id < Aig_Regular(pObj1)->Id ) { *ppPo0 = pObj0; *ppPo1 = pObj1; } else { *ppPo0 = pObj1; *ppPo1 = pObj0; } } return 1; } /**Function************************************************************* Synopsis [Returns 1 if AIG can be demitered.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManDemiterSimpleDiff( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ) { Vec_Ptr_t * vSet0, * vSet1; Aig_Obj_t * pObj, * pObj0, * pObj1; int i; if ( Aig_ManRegNum(p) == 0 || (Aig_ManRegNum(p) & 1) ) return 0; Saig_ManDemiterMarkPos( p ); vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) ); vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) ); Saig_ManForEachPo( p, pObj, i ) { if ( !Saig_ManDemiterCheckPo( p, pObj, &pObj0, &pObj1 ) ) { Vec_PtrFree( vSet0 ); Vec_PtrFree( vSet1 ); Aig_ManCleanMarkAB( p ); return 0; } Vec_PtrPush( vSet0, pObj0 ); Vec_PtrPush( vSet1, pObj1 ); } // create new AIG *ppAig0 = Aig_ManDupNodesHalf( p, vSet0, 0 ); ABC_FREE( (*ppAig0)->pName ); (*ppAig0)->pName = Abc_UtilStrsav( "part0" ); // create new AIGs *ppAig1 = Aig_ManDupNodesHalf( p, vSet1, 1 ); ABC_FREE( (*ppAig1)->pName ); (*ppAig1)->pName = Abc_UtilStrsav( "part1" ); // cleanup Vec_PtrFree( vSet0 ); Vec_PtrFree( vSet1 ); Aig_ManCleanMarkAB( p ); return 1; } /**Function************************************************************* Synopsis [Returns 1 if AIG can be demitered.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManDemiterDual( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ) { Aig_Man_t * pTemp; Aig_Obj_t * pObj; int i, k; if ( p->pFanData ) Aig_ManFanoutStop( p ); k = 0; pTemp = Aig_ManDupSimple( p ); Saig_ManForEachPo( pTemp, pObj, i ) { if ( i & 1 ) Aig_ObjDeletePo( pTemp, pObj ); else Vec_PtrWriteEntry( pTemp->vCos, k++, pObj ); } Saig_ManForEachLi( pTemp, pObj, i ) Vec_PtrWriteEntry( pTemp->vCos, k++, pObj ); Vec_PtrShrink( pTemp->vCos, k ); pTemp->nTruePos = k - Saig_ManRegNum(pTemp); Aig_ManSeqCleanup( pTemp ); *ppAig0 = Aig_ManDupSimple( pTemp ); Aig_ManStop( pTemp ); k = 0; pTemp = Aig_ManDupSimple( p ); Saig_ManForEachPo( pTemp, pObj, i ) { if ( i & 1 ) Vec_PtrWriteEntry( pTemp->vCos, k++, pObj ); else Aig_ObjDeletePo( pTemp, pObj ); } Saig_ManForEachLi( pTemp, pObj, i ) Vec_PtrWriteEntry( pTemp->vCos, k++, pObj ); Vec_PtrShrink( pTemp->vCos, k ); pTemp->nTruePos = k - Saig_ManRegNum(pTemp); Aig_ManSeqCleanup( pTemp ); *ppAig1 = Aig_ManDupSimple( pTemp ); Aig_ManStop( pTemp ); return 1; } /**Function************************************************************* Synopsis [Duplicates the AIG to have constant-0 initial state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManDemiterSimpleDiff_old( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ) { Vec_Ptr_t * vSet0, * vSet1; Aig_Obj_t * pObj, * pFanin, * pObj0, * pObj1; int i, Counter = 0; // assert( Saig_ManRegNum(p) % 2 == 0 ); vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) ); vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) ); Saig_ManForEachPo( p, pObj, i ) { pFanin = Aig_ObjFanin0(pObj); if ( Aig_ObjIsConst1( pFanin ) ) { if ( !Aig_ObjFaninC0(pObj) ) printf( "The output number %d of the miter is constant 1.\n", i ); Counter++; continue; } if ( !Aig_ObjIsNode(pFanin) || !Aig_ObjRecognizeExor( pFanin, &pObj0, &pObj1 ) ) { /* printf( "The miter cannot be demitered.\n" ); Vec_PtrFree( vSet0 ); Vec_PtrFree( vSet1 ); return 0; */ printf( "The output number %d cannot be demitered.\n", i ); continue; } if ( Aig_ObjFaninC0(pObj) ) pObj0 = Aig_Not(pObj0); // printf( "%d %d ", Aig_Regular(pObj0)->Id, Aig_Regular(pObj1)->Id ); if ( Aig_Regular(pObj0)->Id < Aig_Regular(pObj1)->Id ) { Vec_PtrPush( vSet0, pObj0 ); Vec_PtrPush( vSet1, pObj1 ); } else { Vec_PtrPush( vSet0, pObj1 ); Vec_PtrPush( vSet1, pObj0 ); } } // printf( "Miter has %d constant outputs.\n", Counter ); // printf( "\n" ); if ( ppAig0 ) { *ppAig0 = Aig_ManDupNodesAll( p, vSet0 ); ABC_FREE( (*ppAig0)->pName ); (*ppAig0)->pName = Abc_UtilStrsav( "part0" ); } if ( ppAig1 ) { *ppAig1 = Aig_ManDupNodesAll( p, vSet1 ); ABC_FREE( (*ppAig1)->pName ); (*ppAig1)->pName = Abc_UtilStrsav( "part1" ); } Vec_PtrFree( vSet0 ); Vec_PtrFree( vSet1 ); return 1; } /**Function************************************************************* Synopsis [Labels logic reachable from the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManDemiterLabel_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int Value ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); if ( Value ) pObj->fMarkB = 1; else pObj->fMarkA = 1; if ( Saig_ObjIsPi(p, pObj) ) return; if ( Saig_ObjIsLo(p, pObj) ) { Saig_ManDemiterLabel_rec( p, Aig_ObjFanin0( Saig_ObjLoToLi(p, pObj) ), Value ); return; } assert( Aig_ObjIsNode(pObj) ); Saig_ManDemiterLabel_rec( p, Aig_ObjFanin0(pObj), Value ); Saig_ManDemiterLabel_rec( p, Aig_ObjFanin1(pObj), Value ); } /**Function************************************************************* Synopsis [Returns the first labeled register encountered during traversal.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Saig_ManGetLabeledRegister_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pResult; if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return NULL; Aig_ObjSetTravIdCurrent(p, pObj); if ( Saig_ObjIsPi(p, pObj) ) return NULL; if ( Saig_ObjIsLo(p, pObj) ) { if ( pObj->fMarkA || pObj->fMarkB ) return pObj; return Saig_ManGetLabeledRegister_rec( p, Aig_ObjFanin0( Saig_ObjLoToLi(p, pObj) ) ); } assert( Aig_ObjIsNode(pObj) ); pResult = Saig_ManGetLabeledRegister_rec( p, Aig_ObjFanin0(pObj) ); if ( pResult ) return pResult; return Saig_ManGetLabeledRegister_rec( p, Aig_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Duplicates the AIG to have constant-0 initial state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManDemiter( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ) { Vec_Ptr_t * vPairs, * vSet0, * vSet1; Aig_Obj_t * pObj, * pObj0, * pObj1, * pFlop0, * pFlop1; int i, Counter; assert( Saig_ManRegNum(p) > 0 ); Aig_ManSetCioIds( p ); // check if demitering is possible vPairs = Vec_PtrAlloc( 2 * Saig_ManPoNum(p) ); Saig_ManForEachPo( p, pObj, i ) { if ( !Aig_ObjRecognizeExor( Aig_ObjFanin0(pObj), &pObj0, &pObj1 ) ) { Vec_PtrFree( vPairs ); return 0; } Vec_PtrPush( vPairs, pObj0 ); Vec_PtrPush( vPairs, pObj1 ); } // start array of outputs vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) ); vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) ); // get the first pair of outputs pObj0 = (Aig_Obj_t *)Vec_PtrEntry( vPairs, 0 ); pObj1 = (Aig_Obj_t *)Vec_PtrEntry( vPairs, 1 ); // label registers reachable from the outputs Aig_ManIncrementTravId( p ); Saig_ManDemiterLabel_rec( p, Aig_Regular(pObj0), 0 ); Vec_PtrPush( vSet0, pObj0 ); Aig_ManIncrementTravId( p ); Saig_ManDemiterLabel_rec( p, Aig_Regular(pObj1), 1 ); Vec_PtrPush( vSet1, pObj1 ); // find where each output belongs for ( i = 2; i < Vec_PtrSize(vPairs); i += 2 ) { pObj0 = (Aig_Obj_t *)Vec_PtrEntry( vPairs, i ); pObj1 = (Aig_Obj_t *)Vec_PtrEntry( vPairs, i+1 ); Aig_ManIncrementTravId( p ); pFlop0 = Saig_ManGetLabeledRegister_rec( p, Aig_Regular(pObj0) ); Aig_ManIncrementTravId( p ); pFlop1 = Saig_ManGetLabeledRegister_rec( p, Aig_Regular(pObj1) ); if ( (pFlop0->fMarkA && pFlop0->fMarkB) || (pFlop1->fMarkA && pFlop1->fMarkB) || (pFlop0->fMarkA && pFlop1->fMarkA) || (pFlop0->fMarkB && pFlop1->fMarkB) ) printf( "Output pair %4d: Difficult case...\n", i/2 ); if ( pFlop0->fMarkB ) { Saig_ManDemiterLabel_rec( p, pObj0, 1 ); Vec_PtrPush( vSet0, pObj0 ); } else // if ( pFlop0->fMarkA ) or none { Saig_ManDemiterLabel_rec( p, pObj0, 0 ); Vec_PtrPush( vSet1, pObj0 ); } if ( pFlop1->fMarkB ) { Saig_ManDemiterLabel_rec( p, pObj1, 1 ); Vec_PtrPush( vSet0, pObj1 ); } else // if ( pFlop1->fMarkA ) or none { Saig_ManDemiterLabel_rec( p, pObj1, 0 ); Vec_PtrPush( vSet1, pObj1 ); } } // check if there are any flops in common Counter = 0; Saig_ManForEachLo( p, pObj, i ) if ( pObj->fMarkA && pObj->fMarkB ) Counter++; if ( Counter > 0 ) printf( "The miters contains %d flops reachable from both AIGs.\n", Counter ); // produce two miters if ( ppAig0 ) { assert( 0 ); *ppAig0 = Aig_ManDupNodesHalf( p, vSet0, 0 ); // not ready ABC_FREE( (*ppAig0)->pName ); (*ppAig0)->pName = Abc_UtilStrsav( "part0" ); } if ( ppAig1 ) { assert( 0 ); *ppAig1 = Aig_ManDupNodesHalf( p, vSet1, 1 ); // not ready ABC_FREE( (*ppAig1)->pName ); (*ppAig1)->pName = Abc_UtilStrsav( "part1" ); } Vec_PtrFree( vSet0 ); Vec_PtrFree( vSet1 ); Vec_PtrFree( vPairs ); return 1; } /**Function************************************************************* Synopsis [Create specialized miter by unrolling two circuits.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManCreateMiterTwo( Aig_Man_t * pOld, Aig_Man_t * pNew, int nFrames ) { Aig_Man_t * pFrames0, * pFrames1, * pMiter; // assert( Aig_ManNodeNum(pOld) <= Aig_ManNodeNum(pNew) ); pFrames0 = Saig_ManUnrollTwo( pOld, pOld, nFrames ); pFrames1 = Saig_ManUnrollTwo( pNew, pOld, nFrames ); pMiter = Saig_ManCreateMiterComb( pFrames0, pFrames1, 0 ); Aig_ManStop( pFrames0 ); Aig_ManStop( pFrames1 ); return pMiter; } /**Function************************************************************* Synopsis [Resimulates counter-example and returns the failed output number.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SecCexResimulate( Aig_Man_t * p, int * pModel, int * pnOutputs ) { Aig_Obj_t * pObj; int i, RetValue = -1; *pnOutputs = 0; Aig_ManConst1(p)->fMarkA = 1; Aig_ManForEachCi( p, pObj, i ) pObj->fMarkA = pModel[i]; Aig_ManForEachNode( p, pObj, i ) pObj->fMarkA = ( Aig_ObjFanin0(pObj)->fMarkA ^ Aig_ObjFaninC0(pObj) ) & ( Aig_ObjFanin1(pObj)->fMarkA ^ Aig_ObjFaninC1(pObj) ); Aig_ManForEachCo( p, pObj, i ) pObj->fMarkA = Aig_ObjFanin0(pObj)->fMarkA ^ Aig_ObjFaninC0(pObj); Aig_ManForEachCo( p, pObj, i ) if ( pObj->fMarkA ) { if ( RetValue == -1 ) RetValue = i; (*pnOutputs)++; } Aig_ManCleanMarkA(p); return RetValue; } /**Function************************************************************* Synopsis [Reduces SEC to CEC for the special case of seq synthesis.] Description [The first circuit (pPart0) should be circuit before synthesis. The second circuit (pPart1) should be circuit after synthesis.] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SecSpecial( Aig_Man_t * pPart0, Aig_Man_t * pPart1, int nFrames, int fVerbose ) { // extern int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose ); int iOut, nOuts; Aig_Man_t * pMiterCec; int RetValue; abctime clkTotal = Abc_Clock(); if ( fVerbose ) { Aig_ManPrintStats( pPart0 ); Aig_ManPrintStats( pPart1 ); } // Aig_ManDumpBlif( pPart0, "file0.blif", NULL, NULL ); // Aig_ManDumpBlif( pPart1, "file1.blif", NULL, NULL ); // assert( Aig_ManNodeNum(pPart0) <= Aig_ManNodeNum(pPart1) ); /* if ( Aig_ManNodeNum(pPart0) >= Aig_ManNodeNum(pPart1) ) { printf( "Warning: The design after synthesis is smaller!\n" ); printf( "This warning may indicate that the order of designs is changed.\n" ); printf( "The solver expects the original design as first argument and\n" ); printf( "the modified design as the second argument in \"absec\".\n" ); } */ // create two-level miter pMiterCec = Saig_ManCreateMiterTwo( pPart0, pPart1, nFrames ); if ( fVerbose ) { Aig_ManPrintStats( pMiterCec ); // Aig_ManDumpBlif( pMiterCec, "miter01.blif", NULL, NULL ); // printf( "The new miter is written into file \"%s\".\n", "miter01.blif" ); } // run CEC on this miter RetValue = Fra_FraigCec( &pMiterCec, 100000, fVerbose ); // transfer model if given // if ( pNtk2 == NULL ) // pNtk1->pModel = pMiterCec->pData, pMiterCec->pData = NULL; // report the miter if ( RetValue == 1 ) { printf( "Networks are equivalent. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } else if ( RetValue == 0 ) { printf( "Networks are NOT EQUIVALENT. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); if ( pMiterCec->pData == NULL ) printf( "Counter-example is not available.\n" ); else { iOut = Ssw_SecCexResimulate( pMiterCec, (int *)pMiterCec->pData, &nOuts ); if ( iOut == -1 ) printf( "Counter-example verification has failed.\n" ); else { if ( iOut < Saig_ManPoNum(pPart0) * nFrames ) printf( "Primary output %d has failed in frame %d.\n", iOut%Saig_ManPoNum(pPart0), iOut/Saig_ManPoNum(pPart0) ); else printf( "Flop input %d has failed in the last frame.\n", iOut - Saig_ManPoNum(pPart0) * nFrames ); printf( "The counter-example detected %d incorrect POs or flop inputs.\n", nOuts ); } } } else { printf( "Networks are UNDECIDED. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } fflush( stdout ); Aig_ManStop( pMiterCec ); return RetValue; } /**Function************************************************************* Synopsis [Reduces SEC to CEC for the special case of seq synthesis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_SecSpecialMiter( Aig_Man_t * p0, Aig_Man_t * p1, int nFrames, int fVerbose ) { Aig_Man_t * pPart0, * pPart1; int RetValue; if ( fVerbose ) printf( "Performing sequential verification using combinational A/B miter.\n" ); // consider the case when a miter is given if ( p1 == NULL ) { if ( fVerbose ) { Aig_ManPrintStats( p0 ); } // demiter the miter if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) ) { printf( "Demitering has failed.\n" ); return -1; } if ( Aig_ManRegNum(pPart0) != Aig_ManRegNum(pPart1) ) { Aig_ManStop( pPart0 ); Aig_ManStop( pPart1 ); printf( "After demitering AIGs have different number of flops. Quitting.\n" ); return -1; } } else { pPart0 = Aig_ManDupSimple( p0 ); pPart1 = Aig_ManDupSimple( p1 ); } if ( fVerbose ) { // Aig_ManPrintStats( pPart0 ); // Aig_ManPrintStats( pPart1 ); if ( p1 == NULL ) { // Aig_ManDumpBlif( pPart0, "part0.blif", NULL, NULL ); // Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL ); // printf( "The result of demitering is written into files \"%s\" and \"%s\".\n", "part0.blif", "part1.blif" ); } } assert( Aig_ManRegNum(pPart0) > 0 ); assert( Aig_ManRegNum(pPart1) > 0 ); assert( Saig_ManPiNum(pPart0) == Saig_ManPiNum(pPart1) ); assert( Saig_ManPoNum(pPart0) == Saig_ManPoNum(pPart1) ); assert( Aig_ManRegNum(pPart0) == Aig_ManRegNum(pPart1) ); RetValue = Ssw_SecSpecial( pPart0, pPart1, nFrames, fVerbose ); if ( RetValue != 1 && Aig_ManNodeNum(pPart0) >= Aig_ManNodeNum(pPart1) ) RetValue = Ssw_SecSpecial( pPart1, pPart0, nFrames, fVerbose ); Aig_ManStop( pPart0 ); Aig_ManStop( pPart1 ); return RetValue; } /**Function************************************************************* Synopsis [Performs demitering of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManDemiterNew( Aig_Man_t * pMan ) { Vec_Ptr_t * vSuper, * vSupp0, * vSupp1; Aig_Obj_t * pObj, * pTemp, * pFan0, * pFan1; int i, k; vSuper = Vec_PtrAlloc( 100 ); Saig_ManForEachPo( pMan, pObj, i ) { if ( pMan->nConstrs && i >= Saig_ManPoNum(pMan) - pMan->nConstrs ) break; printf( "Output %3d : ", i ); if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) { if ( !Aig_ObjFaninC0(pObj) ) printf( "Const1\n" ); else printf( "Const0\n" ); continue; } if ( !Aig_ObjIsNode(Aig_ObjFanin0(pObj)) ) { printf( "Terminal\n" ); continue; } // check AND if ( !Aig_ObjFaninC0(pObj) ) { printf( "AND " ); if ( Aig_ObjRecognizeExor(Aig_ObjFanin0(pObj), &pFan0, &pFan1) ) printf( " Yes" ); else printf( " No" ); printf( "\n" ); continue; } // check OR Aig_ObjCollectSuper( Aig_ObjFanin0(pObj), vSuper ); printf( "OR with %d inputs ", Vec_PtrSize(vSuper) ); if ( Vec_PtrSize(vSuper) == 2 ) { if ( Aig_ObjRecognizeExor(Aig_ObjFanin0(pObj), &pFan0, &pFan1) ) { printf( " Yes" ); printf( "\n" ); vSupp0 = Aig_Support( pMan, Aig_Regular(pFan0) ); Vec_PtrForEachEntry( Aig_Obj_t *, vSupp0, pTemp, k ) if ( Saig_ObjIsLo(pMan, pTemp) ) printf( " %d", Aig_ObjCioId(pTemp) ); printf( "\n" ); Vec_PtrFree( vSupp0 ); vSupp1 = Aig_Support( pMan, Aig_Regular(pFan1) ); Vec_PtrForEachEntry( Aig_Obj_t *, vSupp1, pTemp, k ) if ( Saig_ObjIsLo(pMan, pTemp) ) printf( " %d", Aig_ObjCioId(pTemp) ); printf( "\n" ); Vec_PtrFree( vSupp1 ); } else printf( " No" ); printf( "\n" ); continue; } /* Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pTemp, k ) if ( Aig_ObjRecognizeExor(Aig_Regular(pTemp), &pFan0, &pFan1) ) { printf( " Yes" ); if ( Aig_IsComplement(pTemp) ) pFan0 = Aig_Not(pFan0); } else printf( " No" ); */ printf( "\n" ); } Vec_PtrFree( vSuper ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigOutDec.c000066400000000000000000000161271477524141600166540ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigOutDec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Output cone decomposition.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigOutDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs decomposition of the property output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Saig_ManFindPrimes( Aig_Man_t * pAig, int nLits, int fVerbose ) { Cnf_Dat_t * pCnf; sat_solver * pSat; Aig_Obj_t * pObj0, * pObj1, * pRoot, * pMiter; Vec_Ptr_t * vPrimes, * vNodes; Vec_Int_t * vCube, * vMarks; int i0, i1, m, RetValue, Lits[10]; int fCompl0, fCompl1, nNodes1, nNodes2; assert( nLits == 1 || nLits == 2 ); assert( nLits < 10 ); // create SAT solver pCnf = Cnf_DeriveSimple( pAig, Aig_ManCoNum(pAig) ); pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); // collect nodes in the property output cone pMiter = Aig_ManCo( pAig, 0 ); pRoot = Aig_ObjFanin0( pMiter ); vNodes = Aig_ManDfsNodes( pAig, &pRoot, 1 ); // sort nodes by level and remove the last few // try single nodes vPrimes = Vec_PtrAlloc( 100 ); // create assumptions vMarks = Vec_IntStart( Vec_PtrSize(vNodes) ); Lits[0] = toLitCond( pCnf->pVarNums[Aig_ObjId(pMiter)], 1 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj0, i0 ) if ( pObj0 != pRoot ) { // create assumptions Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj0)], pObj0->fPhase ); // solve the problem RetValue = sat_solver_solve( pSat, Lits, Lits+2, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue == l_False ) { vCube = Vec_IntAlloc( 1 ); Vec_IntPush( vCube, toLitCond(Aig_ObjId(pObj0), pObj0->fPhase) ); Vec_PtrPush( vPrimes, vCube ); if ( fVerbose ) printf( "Adding prime %d%c\n", Aig_ObjId(pObj0), pObj0->fPhase?'-':'+' ); Vec_IntWriteEntry( vMarks, i0, 1 ); } } nNodes1 = Vec_PtrSize(vPrimes); if ( nLits > 1 ) { // try adding second literal Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj0, i0 ) if ( pObj0 != pRoot ) Vec_PtrForEachEntryStart( Aig_Obj_t *, vNodes, pObj1, i1, i0+1 ) if ( pObj1 != pRoot ) { if ( Vec_IntEntry(vMarks,i0) || Vec_IntEntry(vMarks,i1) ) continue; for ( m = 0; m < 3; m++ ) { fCompl0 = m & 1; fCompl1 = (m >> 1) & 1; // create assumptions Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj0)], fCompl0 ^ pObj0->fPhase ); Lits[2] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj1)], fCompl1 ^ pObj1->fPhase ); // solve the problem RetValue = sat_solver_solve( pSat, Lits, Lits+3, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue == l_False ) { vCube = Vec_IntAlloc( 2 ); Vec_IntPush( vCube, toLitCond(Aig_ObjId(pObj0), fCompl0 ^ pObj0->fPhase) ); Vec_IntPush( vCube, toLitCond(Aig_ObjId(pObj1), fCompl1 ^ pObj1->fPhase) ); Vec_PtrPush( vPrimes, vCube ); if ( fVerbose ) printf( "Adding prime %d%c %d%c\n", Aig_ObjId(pObj0), (fCompl0 ^ pObj0->fPhase)?'-':'+', Aig_ObjId(pObj1), (fCompl1 ^ pObj1->fPhase)?'-':'+' ); break; } } } } nNodes2 = Vec_PtrSize(vPrimes) - nNodes1; printf( "Property cone size = %6d 1-lit primes = %5d 2-lit primes = %5d\n", Vec_PtrSize(vNodes), nNodes1, nNodes2 ); // clean up sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); Vec_PtrFree( vNodes ); Vec_IntFree( vMarks ); return vPrimes; } /**Function************************************************************* Synopsis [Performs decomposition of the property output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDecPropertyOutput( Aig_Man_t * pAig, int nLits, int fVerbose ) { Aig_Man_t * pAigNew = NULL; Aig_Obj_t * pObj, * pMiter; Vec_Ptr_t * vPrimes; Vec_Int_t * vCube; int i, k, Lit; // compute primes of the comb output function vPrimes = Saig_ManFindPrimes( pAig, nLits, fVerbose ); // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); pAigNew->pName = Abc_UtilStrsav( pAig->pName ); pAigNew->nConstrs = pAig->nConstrs; // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create variables for PIs Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( pAigNew ); // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create original POs of the circuit Saig_ManForEachPo( pAig, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); // create prime POs of the circuit if ( vPrimes ) Vec_PtrForEachEntry( Vec_Int_t *, vPrimes, vCube, k ) { pMiter = Aig_ManConst1( pAigNew ); Vec_IntForEachEntry( vCube, Lit, i ) { pObj = Aig_NotCond( Aig_ObjCopy(Aig_ManObj(pAig, Abc_Lit2Var(Lit))), Abc_LitIsCompl(Lit) ); pMiter = Aig_And( pAigNew, pMiter, pObj ); } Aig_ObjCreateCo( pAigNew, pMiter ); } // transfer to register outputs Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); Aig_ManCleanup( pAigNew ); Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) ); Vec_VecFreeP( (Vec_Vec_t **)&vPrimes ); return pAigNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigPhase.c000066400000000000000000001077461477524141600165410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigPhase.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Automated phase abstraction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigPhase.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" ABC_NAMESPACE_IMPL_START /* The algorithm is described in the paper: Per Bjesse and Jim Kukula, "Automatic Phase Abstraction for Formal Verification", ICCAD 2005 http://www.iccad.com/data2/iccad/iccad_05acceptedpapers.nsf/9cfb1ebaaf59043587256a6a00031f78/1701ecf34b149e958725702f00708828?OpenDocument */ // the maximum number of cycles of termiry simulation #define TSIM_MAX_ROUNDS 10000 #define TSIM_ONE_SERIES 3000 #define SAIG_XVS0 1 #define SAIG_XVS1 2 #define SAIG_XVSX 3 static inline int Saig_XsimConvertValue( int v ) { return v == 0? SAIG_XVS0 : (v == 1? SAIG_XVS1 : (v == 2? SAIG_XVSX : -1)); } static inline void Saig_ObjSetXsim( Aig_Obj_t * pObj, int Value ) { pObj->nCuts = Value; } static inline int Saig_ObjGetXsim( Aig_Obj_t * pObj ) { return pObj->nCuts; } static inline int Saig_XsimInv( int Value ) { if ( Value == SAIG_XVS0 ) return SAIG_XVS1; if ( Value == SAIG_XVS1 ) return SAIG_XVS0; assert( Value == SAIG_XVSX ); return SAIG_XVSX; } static inline int Saig_XsimAnd( int Value0, int Value1 ) { if ( Value0 == SAIG_XVS0 || Value1 == SAIG_XVS0 ) return SAIG_XVS0; if ( Value0 == SAIG_XVSX || Value1 == SAIG_XVSX ) return SAIG_XVSX; assert( Value0 == SAIG_XVS1 && Value1 == SAIG_XVS1 ); return SAIG_XVS1; } static inline int Saig_XsimRand2() { return (Aig_ManRandom(0) & 1) ? SAIG_XVS1 : SAIG_XVS0; } static inline int Saig_XsimRand3() { int RetValue; do { RetValue = Aig_ManRandom(0) & 3; } while ( RetValue == 0 ); return RetValue; } static inline int Saig_ObjGetXsimFanin0( Aig_Obj_t * pObj ) { int RetValue; RetValue = Saig_ObjGetXsim(Aig_ObjFanin0(pObj)); return Aig_ObjFaninC0(pObj)? Saig_XsimInv(RetValue) : RetValue; } static inline int Saig_ObjGetXsimFanin1( Aig_Obj_t * pObj ) { int RetValue; RetValue = Saig_ObjGetXsim(Aig_ObjFanin1(pObj)); return Aig_ObjFaninC1(pObj)? Saig_XsimInv(RetValue) : RetValue; } static inline void Saig_XsimPrint( FILE * pFile, int Value ) { if ( Value == SAIG_XVS0 ) { fprintf( pFile, "0" ); return; } if ( Value == SAIG_XVS1 ) { fprintf( pFile, "1" ); return; } assert( Value == SAIG_XVSX ); fprintf( pFile, "x" ); } // simulation manager typedef struct Saig_Tsim_t_ Saig_Tsim_t; struct Saig_Tsim_t_ { Aig_Man_t * pAig; // the original AIG manager int nWords; // the number of words in the states // ternary state representation Vec_Ptr_t * vStates; // the collection of ternary states Aig_MmFixed_t * pMem; // memory for ternary states int nPrefix; // prefix of the ternary state space int nCycle; // cycle of the ternary state space int nNonXRegs; // the number of candidate registers Vec_Int_t * vNonXRegs; // the candidate registers // hash table for terminary states unsigned ** pBins; int nBins; }; static inline unsigned * Saig_TsiNext( unsigned * pState, int nWords ) { return *((unsigned **)(pState + nWords)); } static inline void Saig_TsiSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; } //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Saig_Tsim_t * Saig_TsiStart( Aig_Man_t * pAig ) { Saig_Tsim_t * p; p = (Saig_Tsim_t *)ABC_ALLOC( char, sizeof(Saig_Tsim_t) ); memset( p, 0, sizeof(Saig_Tsim_t) ); p->pAig = pAig; p->nWords = Abc_BitWordNum( 2*Aig_ManRegNum(pAig) ); p->vStates = Vec_PtrAlloc( 1000 ); p->pMem = Aig_MmFixedStart( sizeof(unsigned) * p->nWords + sizeof(unsigned *), 10000 ); p->nBins = Abc_PrimeCudd(TSIM_MAX_ROUNDS/2); p->pBins = ABC_ALLOC( unsigned *, p->nBins ); memset( p->pBins, 0, sizeof(unsigned *) * p->nBins ); return p; } /**Function************************************************************* Synopsis [Deallocates simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_TsiStop( Saig_Tsim_t * p ) { if ( p->vNonXRegs ) Vec_IntFree( p->vNonXRegs ); Aig_MmFixedStop( p->pMem, 0 ); Vec_PtrFree( p->vStates ); ABC_FREE( p->pBins ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Computes hash value of the node using its simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_TsiStateHash( unsigned * pState, int nWords, int nTableSize ) { static int s_FPrimes[128] = { 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 }; unsigned uHash; int i; uHash = 0; for ( i = 0; i < nWords; i++ ) uHash ^= pState[i] * s_FPrimes[i & 0x7F]; return uHash % nTableSize; } /**Function************************************************************* Synopsis [Count non-X-valued registers in the simulation data.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_TsiCountNonXValuedRegisters( Saig_Tsim_t * p, int nPref ) { unsigned * pState; int nRegs = p->pAig->nRegs; int Value, i, k; assert( p->vNonXRegs == NULL ); p->vNonXRegs = Vec_IntAlloc( 10 ); for ( i = 0; i < nRegs; i++ ) { Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, k, nPref ) { Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); assert( Value != 0 ); if ( Value == SAIG_XVSX ) break; } if ( k == Vec_PtrSize(p->vStates) ) Vec_IntPush( p->vNonXRegs, i ); } return Vec_IntSize(p->vNonXRegs); } /**Function************************************************************* Synopsis [Computes flops that are stuck-at constant.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_TsiComputeTransient( Saig_Tsim_t * p, int nPref ) { Vec_Int_t * vCounters; unsigned * pState; int ValueThis = -1, ValuePrev = -1, StepPrev = -1; int i, k, nRegs = p->pAig->nRegs; vCounters = Vec_IntStart( nPref ); for ( i = 0; i < nRegs; i++ ) { Vec_PtrForEachEntry( unsigned *, p->vStates, pState, k ) { ValueThis = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); //printf( "%s", (ValueThis == 1)? "0" : ((ValueThis == 2)? "1" : "x") ); assert( ValueThis != 0 ); if ( ValuePrev != ValueThis ) { ValuePrev = ValueThis; StepPrev = k; } } //printf( "\n" ); if ( ValueThis == SAIG_XVSX ) continue; if ( StepPrev >= nPref ) continue; Vec_IntAddToEntry( vCounters, StepPrev, 1 ); } Vec_IntForEachEntry( vCounters, ValueThis, i ) { if ( ValueThis == 0 ) continue; // printf( "%3d : %3d\n", i, ValueThis ); } return vCounters; } /**Function************************************************************* Synopsis [Count non-X-valued registers in the simulation data.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_TsiPrintTraces( Saig_Tsim_t * p, int nWords, int nPrefix, int nLoop ) { unsigned * pState; int nRegs = p->pAig->nRegs; int Value, i, k, Counter = 0; printf( "Ternary traces for each flop:\n" ); printf( " : " ); for ( i = 0; i < Vec_PtrSize(p->vStates) - nLoop - 1; i++ ) printf( "%d", i%10 ); printf( " " ); for ( i = 0; i < nLoop; i++ ) printf( "%d", i%10 ); printf( "\n" ); for ( i = 0; i < nRegs; i++ ) { /* Vec_PtrForEachEntry( unsigned *, p->vStates, pState, k ) { Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); if ( Value == SAIG_XVSX ) break; } if ( k == Vec_PtrSize(p->vStates) ) Counter++; else continue; */ // print trace // printf( "%5d : %5d %5d ", Counter, i, Saig_ManLo(p->pAig, i)->Id ); printf( "%5d : ", Counter++ ); Vec_PtrForEachEntryStop( unsigned *, p->vStates, pState, k, Vec_PtrSize(p->vStates)-1 ) { Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); if ( Value == SAIG_XVS0 ) printf( "0" ); else if ( Value == SAIG_XVS1 ) printf( "1" ); else if ( Value == SAIG_XVSX ) printf( "x" ); else assert( 0 ); if ( k == nPrefix - 1 ) printf( " " ); } printf( "\n" ); } } /**Function************************************************************* Synopsis [Returns the number of the state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_TsiComputePrefix( Saig_Tsim_t * p, unsigned * pState, int nWords ) { unsigned * pEntry, * pPrev; int Hash, i; Hash = Saig_TsiStateHash( pState, nWords, p->nBins ); for ( pEntry = p->pBins[Hash]; pEntry; pEntry = Saig_TsiNext(pEntry, nWords) ) if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) ) { Vec_PtrForEachEntry( unsigned *, p->vStates, pPrev, i ) { if ( pPrev == pEntry ) return i; } assert( 0 ); return -1; } return -1; } /**Function************************************************************* Synopsis [Checks if the value exists in the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_TsiStateLookup( Saig_Tsim_t * p, unsigned * pState, int nWords ) { unsigned * pEntry; int Hash; Hash = Saig_TsiStateHash( pState, nWords, p->nBins ); for ( pEntry = p->pBins[Hash]; pEntry; pEntry = Saig_TsiNext(pEntry, nWords) ) if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) ) return 1; return 0; } /**Function************************************************************* Synopsis [Inserts value into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_TsiStateInsert( Saig_Tsim_t * p, unsigned * pState, int nWords ) { int Hash = Saig_TsiStateHash( pState, nWords, p->nBins ); assert( !Saig_TsiStateLookup( p, pState, nWords ) ); Saig_TsiSetNext( pState, nWords, p->pBins[Hash] ); p->pBins[Hash] = pState; } /**Function************************************************************* Synopsis [Inserts value into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Saig_TsiStateNew( Saig_Tsim_t * p ) { unsigned * pState; pState = (unsigned *)Aig_MmFixedEntryFetch( p->pMem ); memset( pState, 0, sizeof(unsigned) * p->nWords ); Vec_PtrPush( p->vStates, pState ); return pState; } /**Function************************************************************* Synopsis [Inserts value into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_TsiStatePrint( Saig_Tsim_t * p, unsigned * pState ) { int i, Value, nZeros = 0, nOnes = 0, nDcs = 0; for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) { Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); if ( Value == SAIG_XVS0 ) printf( "0" ), nZeros++; else if ( Value == SAIG_XVS1 ) printf( "1" ), nOnes++; else if ( Value == SAIG_XVSX ) printf( "x" ), nDcs++; else assert( 0 ); } printf( " (0=%5d, 1=%5d, x=%5d)\n", nZeros, nOnes, nDcs ); } /**Function************************************************************* Synopsis [Count constant values in the state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_TsiStateCount( Saig_Tsim_t * p, unsigned * pState ) { Aig_Obj_t * pObjLi, * pObjLo; int i, Value, nCounter = 0; Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i ) { Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); nCounter += (Value == SAIG_XVS0 || Value == SAIG_XVS1); } return nCounter; } /**Function************************************************************* Synopsis [Count constant values in the state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_TsiStateOrAll( Saig_Tsim_t * pTsi, unsigned * pState ) { unsigned * pPrev; int i, k; Vec_PtrForEachEntry( unsigned *, pTsi->vStates, pPrev, i ) { for ( k = 0; k < pTsi->nWords; k++ ) pState[k] |= pPrev[k]; } } /**Function************************************************************* Synopsis [Cycles the circuit to create a new initial state.] Description [Simulates the circuit with random input for the given number of timeframes to get a better initial state.] SideEffects [] SeeAlso [] ***********************************************************************/ Saig_Tsim_t * Saig_ManReachableTernary( Aig_Man_t * p, Vec_Int_t * vInits, int fVerbose ) { Saig_Tsim_t * pTsi; Aig_Obj_t * pObj, * pObjLi, * pObjLo; unsigned * pState; int i, f, Value, nCounter; // allocate the simulation manager pTsi = Saig_TsiStart( p ); // initialize the values Saig_ObjSetXsim( Aig_ManConst1(p), SAIG_XVS1 ); Saig_ManForEachPi( p, pObj, i ) Saig_ObjSetXsim( pObj, SAIG_XVSX ); if ( vInits ) { Saig_ManForEachLo( p, pObj, i ) Saig_ObjSetXsim( pObj, Saig_XsimConvertValue(Vec_IntEntry(vInits, i)) ); } else { Saig_ManForEachLo( p, pObj, i ) Saig_ObjSetXsim( pObj, SAIG_XVS0 ); } // simulate for the given number of timeframes for ( f = 0; f < TSIM_MAX_ROUNDS; f++ ) { // collect this state pState = Saig_TsiStateNew( pTsi ); Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) { Value = Saig_ObjGetXsim(pObjLo); if ( Value & 1 ) Abc_InfoSetBit( pState, 2 * i ); if ( Value & 2 ) Abc_InfoSetBit( pState, 2 * i + 1 ); } // printf( "%d ", Saig_TsiStateCount(pTsi, pState) ); // Saig_TsiStatePrint( pTsi, pState ); // check if this state exists if ( Saig_TsiStateLookup( pTsi, pState, pTsi->nWords ) ) { if ( fVerbose ) printf( "Ternary simulation converged after %d iterations.\n", f ); return pTsi; } // insert this state Saig_TsiStateInsert( pTsi, pState, pTsi->nWords ); // simulate internal nodes Aig_ManForEachNode( p, pObj, i ) Saig_ObjSetXsim( pObj, Saig_XsimAnd(Saig_ObjGetXsimFanin0(pObj), Saig_ObjGetXsimFanin1(pObj)) ); // transfer the latch values Saig_ManForEachLi( p, pObj, i ) Saig_ObjSetXsim( pObj, Saig_ObjGetXsimFanin0(pObj) ); nCounter = 0; Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) { if ( f < TSIM_ONE_SERIES ) Saig_ObjSetXsim( pObjLo, Saig_ObjGetXsim(pObjLi) ); else { if ( Saig_ObjGetXsim(pObjLi) != Saig_ObjGetXsim(pObjLo) ) Saig_ObjSetXsim( pObjLo, SAIG_XVSX ); } nCounter += (Saig_ObjGetXsim(pObjLo) == SAIG_XVS0); } } printf( "Saig_ManReachableTernary(): Did not reach a fixed point after %d iterations (not a bug).\n", TSIM_MAX_ROUNDS ); Saig_TsiStop( pTsi ); return NULL; } /**Function************************************************************* Synopsis [Analize initial value of the selected register.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManAnalizeControl( Aig_Man_t * p, int Reg ) { Aig_Obj_t * pObj, * pReg, * pCtrl, * pAnd; int i; pReg = Saig_ManLo( p, Reg ); pCtrl = Saig_ManLo( p, Saig_ManRegNum(p)-1 ); assert( pReg->Id < pCtrl->Id ); // find a node pointing to both pAnd = NULL; Aig_ManForEachNode( p, pObj, i ) { if ( Aig_ObjFanin0(pObj) == pReg && Aig_ObjFanin1(pObj) == pCtrl ) { pAnd = pObj; break; } } if ( pAnd == NULL ) { printf( "Register is not found.\n" ); return; } printf( "Clock-like register: \n" ); Aig_ObjPrint( p, pReg ); printf( "\n" ); printf( "Control register: \n" ); Aig_ObjPrint( p, pCtrl ); printf( "\n" ); printf( "Their fanout: \n" ); Aig_ObjPrint( p, pAnd ); printf( "\n" ); // find the fanouts of pAnd printf( "Fanouts of the fanout: \n" ); Aig_ManForEachObj( p, pObj, i ) if ( Aig_ObjFanin0(pObj) == pAnd || Aig_ObjFanin1(pObj) == pAnd ) { Aig_ObjPrint( p, pObj ); printf( "\n" ); } printf( "\n" ); } /**Function************************************************************* Synopsis [Finds the registers to phase-abstract.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManFindRegisters( Saig_Tsim_t * pTsi, int nFrames, int fIgnore, int fVerbose ) { int Values[257] = {0}; unsigned * pState; int r, i, k, Reg, Value; int nTests = pTsi->nPrefix + 2 * pTsi->nCycle; assert( nFrames <= 256 ); r = 0; Vec_IntForEachEntry( pTsi->vNonXRegs, Reg, i ) { for ( k = 0; k < nTests; k++ ) { if ( k < pTsi->nPrefix + pTsi->nCycle ) pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, k ); else pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, k - pTsi->nCycle ); Value = (Abc_InfoHasBit( pState, 2 * Reg + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * Reg ); assert( Value == SAIG_XVS0 || Value == SAIG_XVS1 ); if ( k < nFrames || (fIgnore && k == nFrames) ) Values[k % nFrames] = Value; else if ( Values[k % nFrames] != Value ) break; } if ( k < nTests ) continue; // skip stuck at if ( fIgnore ) { for ( k = 1; k < nFrames; k++ ) if ( Values[k] != Values[0] ) break; if ( k == nFrames ) continue; } // report useful register Vec_IntWriteEntry( pTsi->vNonXRegs, r++, Reg ); if ( fVerbose ) { printf( "Register %5d has generator: [", Reg ); for ( k = 0; k < nFrames; k++ ) Saig_XsimPrint( stdout, Values[k] ); printf( "]\n" ); if ( fVerbose ) Saig_ManAnalizeControl( pTsi->pAig, Reg ); } } Vec_IntShrink( pTsi->vNonXRegs, r ); if ( fVerbose ) printf( "Found %3d useful registers.\n", Vec_IntSize(pTsi->vNonXRegs) ); return Vec_IntSize(pTsi->vNonXRegs); } /**Function************************************************************* Synopsis [Mapping of AIG nodes into frames nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Aig_Obj_t * Saig_ObjFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return pObjMap[nFs*pObj->Id + i]; } static inline void Saig_ObjSetFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { pObjMap[nFs*pObj->Id + i] = pNode; } static inline Aig_Obj_t * Saig_ObjChild0Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin0(pObj)? Aig_NotCond(Saig_ObjFrames(pObjMap,nFs,Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } static inline Aig_Obj_t * Saig_ObjChild1Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin1(pObj)? Aig_NotCond(Saig_ObjFrames(pObjMap,nFs,Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } /**Function************************************************************* Synopsis [Performs phase abstraction by unrolling the circuit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManPerformAbstraction( Saig_Tsim_t * pTsi, int nFrames, int fVerbose ) { Aig_Man_t * pFrames, * pAig = pTsi->pAig; Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; Aig_Obj_t ** pObjMap; unsigned * pState; int i, f, Reg, Value; assert( Vec_IntSize(pTsi->vNonXRegs) > 0 ); // create mapping for the frames nodes pObjMap = ABC_ALLOC( Aig_Obj_t *, nFrames * Aig_ManObjNumMax(pAig) ); memset( pObjMap, 0, sizeof(Aig_Obj_t *) * nFrames * Aig_ManObjNumMax(pAig) ); // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); pFrames->pName = Abc_UtilStrsav( pAig->pName ); pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); // map constant nodes for ( f = 0; f < nFrames; f++ ) Saig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); // create PI nodes for the frames for ( f = 0; f < nFrames; f++ ) Aig_ManForEachPiSeq( pAig, pObj, i ) Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, Aig_ObjCreateCi(pFrames) ); // create the latches Aig_ManForEachLoSeq( pAig, pObj, i ) Saig_ObjSetFrames( pObjMap, nFrames, pObj, 0, Aig_ObjCreateCi(pFrames) ); // add timeframes for ( f = 0; f < nFrames; f++ ) { // replace abstracted registers by constants Vec_IntForEachEntry( pTsi->vNonXRegs, Reg, i ) { pObj = Saig_ManLo( pAig, Reg ); pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, f ); Value = (Abc_InfoHasBit( pState, 2 * Reg + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * Reg ); assert( Value == SAIG_XVS0 || Value == SAIG_XVS1 ); pObjNew = (Value == SAIG_XVS1)? Aig_ManConst1(pFrames) : Aig_ManConst0(pFrames); Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); } // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) { pObjNew = Aig_And( pFrames, Saig_ObjChild0Frames(pObjMap,nFrames,pObj,f), Saig_ObjChild1Frames(pObjMap,nFrames,pObj,f) ); Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); } // set the latch inputs and copy them into the latch outputs of the next frame Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i ) { pObjNew = Saig_ObjChild0Frames(pObjMap,nFrames,pObjLi,f); if ( f < nFrames - 1 ) Saig_ObjSetFrames( pObjMap, nFrames, pObjLo, f+1, pObjNew ); } } for ( f = 0; f < nFrames; f++ ) { Aig_ManForEachPoSeq( pAig, pObj, i ) { pObjNew = Aig_ObjCreateCo( pFrames, Saig_ObjChild0Frames(pObjMap,nFrames,pObj,f) ); Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); } } pFrames->nRegs = pAig->nRegs; pFrames->nTruePis = Aig_ManCiNum(pFrames) - Aig_ManRegNum(pFrames); pFrames->nTruePos = Aig_ManCoNum(pFrames) - Aig_ManRegNum(pFrames); Aig_ManForEachLiSeq( pAig, pObj, i ) { pObjNew = Aig_ObjCreateCo( pFrames, Saig_ObjChild0Frames(pObjMap,nFrames,pObj,nFrames-1) ); Saig_ObjSetFrames( pObjMap, nFrames, pObj, nFrames-1, pObjNew ); } //Aig_ManPrintStats( pFrames ); Aig_ManSeqCleanup( pFrames ); //Aig_ManPrintStats( pFrames ); // Aig_ManCiCleanup( pFrames ); //Aig_ManPrintStats( pFrames ); ABC_FREE( pObjMap ); return pFrames; } /**Function************************************************************* Synopsis [Performs automated phase abstraction.] Description [Takes the AIG manager and the array of initial states.] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManPhaseFrameNum( Aig_Man_t * p, Vec_Int_t * vInits ) { Saig_Tsim_t * pTsi; int nFrames, nPrefix; assert( Saig_ManRegNum(p) ); assert( Saig_ManPiNum(p) ); assert( Saig_ManPoNum(p) ); // perform terminary simulation pTsi = Saig_ManReachableTernary( p, vInits, 0 ); if ( pTsi == NULL ) return 1; // derive information nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords ); nFrames = Vec_PtrSize(pTsi->vStates) - 1 - nPrefix; Saig_TsiStop( pTsi ); // potentially, may need to reduce nFrames if nPrefix is less than nFrames return nFrames; } /**Function************************************************************* Synopsis [Performs automated phase abstraction.] Description [Takes the AIG manager and the array of initial states.] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManPhasePrefixLength( Aig_Man_t * p, int fVerbose, int fVeryVerbose, Vec_Int_t ** pvTrans ) { Saig_Tsim_t * pTsi; int nFrames, nPrefix, nNonXRegs; assert( Saig_ManRegNum(p) ); assert( Saig_ManPiNum(p) ); assert( Saig_ManPoNum(p) ); // perform terminary simulation pTsi = Saig_ManReachableTernary( p, NULL, 0 ); if ( pTsi == NULL ) return 0; // derive information nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords ); nFrames = Vec_PtrSize(pTsi->vStates) - 1 - nPrefix; nNonXRegs = Saig_TsiCountNonXValuedRegisters( pTsi, nPrefix ); if ( pvTrans ) *pvTrans = Saig_TsiComputeTransient( pTsi, nPrefix ); // print statistics if ( fVerbose ) printf( "Lead = %5d. Loop = %5d. Total flops = %5d. Binary flops = %5d.\n", nPrefix, nFrames, p->nRegs, nNonXRegs ); if ( fVeryVerbose ) Saig_TsiPrintTraces( pTsi, pTsi->nWords, nPrefix, nFrames ); Saig_TsiStop( pTsi ); // potentially, may need to reduce nFrames if nPrefix is less than nFrames return nPrefix; } /**Function************************************************************* Synopsis [Performs automated phase abstraction.] Description [Takes the AIG manager and the array of initial states.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManPhaseAbstract( Aig_Man_t * p, Vec_Int_t * vInits, int nFrames, int nPref, int fIgnore, int fPrint, int fVerbose ) { Aig_Man_t * pNew = NULL; Saig_Tsim_t * pTsi; assert( Saig_ManRegNum(p) ); assert( Saig_ManPiNum(p) ); assert( Saig_ManPoNum(p) ); // perform terminary simulation pTsi = Saig_ManReachableTernary( p, vInits, fVerbose ); if ( pTsi == NULL ) return NULL; // derive information pTsi->nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords ); pTsi->nCycle = Vec_PtrSize(pTsi->vStates) - 1 - pTsi->nPrefix; pTsi->nNonXRegs = Saig_TsiCountNonXValuedRegisters(pTsi, Abc_MinInt(pTsi->nPrefix,nPref)); // print statistics if ( fVerbose ) { printf( "Lead = %5d. Loop = %5d. Total flops = %5d. Binary flops = %5d.\n", pTsi->nPrefix, pTsi->nCycle, p->nRegs, pTsi->nNonXRegs ); if ( pTsi->nNonXRegs < 100 && Vec_PtrSize(pTsi->vStates) < 80 ) Saig_TsiPrintTraces( pTsi, pTsi->nWords, pTsi->nPrefix, pTsi->nCycle ); } if ( fPrint ) printf( "Print-out finished. Phase assignment is not performed.\n" ); else if ( nFrames < 2 ) printf( "The number of frames is less than 2. Phase assignment is not performed.\n" ); else if ( nFrames > 256 ) printf( "The number of frames is more than 256. Phase assignment is not performed.\n" ); else if ( pTsi->nCycle == 1 ) printf( "The cycle of ternary states is trivial. Phase abstraction cannot be done.\n" ); else if ( pTsi->nCycle % nFrames != 0 ) printf( "The cycle (%d) is not modulo the number of frames (%d). Phase abstraction cannot be done.\n", pTsi->nCycle, nFrames ); else if ( pTsi->nNonXRegs == 0 ) printf( "All registers have X-valued states. Phase abstraction cannot be done.\n" ); else if ( !Saig_ManFindRegisters( pTsi, nFrames, fIgnore, fVerbose ) ) printf( "There is no registers to abstract with %d frames.\n", nFrames ); else pNew = Saig_ManPerformAbstraction( pTsi, nFrames, fVerbose ); Saig_TsiStop( pTsi ); return pNew; } /**Function************************************************************* Synopsis [Performs automated phase abstraction.] Description [Takes the AIG manager and the array of initial states.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManPhaseAbstractAuto( Aig_Man_t * p, int fVerbose ) { Aig_Man_t * pNew = NULL; Saig_Tsim_t * pTsi; int fPrint = 0; int nFrames; assert( Saig_ManRegNum(p) ); assert( Saig_ManPiNum(p) ); assert( Saig_ManPoNum(p) ); // perform terminary simulation pTsi = Saig_ManReachableTernary( p, NULL, fVerbose ); if ( pTsi == NULL ) return NULL; // derive information pTsi->nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords ); pTsi->nCycle = Vec_PtrSize(pTsi->vStates) - 1 - pTsi->nPrefix; pTsi->nNonXRegs = Saig_TsiCountNonXValuedRegisters(pTsi, 0); // print statistics if ( fVerbose ) { printf( "Lead = %5d. Loop = %5d. Total flops = %5d. Binary flops = %5d.\n", pTsi->nPrefix, pTsi->nCycle, p->nRegs, pTsi->nNonXRegs ); if ( pTsi->nNonXRegs < 100 && Vec_PtrSize(pTsi->vStates) < 80 ) Saig_TsiPrintTraces( pTsi, pTsi->nWords, pTsi->nPrefix, pTsi->nCycle ); } nFrames = pTsi->nCycle; if ( fPrint ) { printf( "Print-out finished. Phase assignment is not performed.\n" ); } else if ( nFrames < 2 ) { // printf( "The number of frames is less than 2. Phase assignment is not performed.\n" ); } else if ( nFrames > 256 ) { // printf( "The number of frames is more than 256. Phase assignment is not performed.\n" ); } else if ( pTsi->nCycle == 1 ) { // printf( "The cycle of ternary states is trivial. Phase abstraction cannot be done.\n" ); } else if ( pTsi->nCycle % nFrames != 0 ) { // printf( "The cycle (%d) is not modulo the number of frames (%d). Phase abstraction cannot be done.\n", pTsi->nCycle, nFrames ); } else if ( pTsi->nNonXRegs == 0 ) { // printf( "All registers have X-valued states. Phase abstraction cannot be done.\n" ); } else if ( !Saig_ManFindRegisters( pTsi, nFrames, 0, fVerbose ) ) { // printf( "There is no registers to abstract with %d frames.\n", nFrames ); } else pNew = Saig_ManPerformAbstraction( pTsi, nFrames, fVerbose ); Saig_TsiStop( pTsi ); if ( pNew == NULL ) pNew = Aig_ManDupSimple( p ); if ( Aig_ManCiNum(pNew) == Aig_ManRegNum(pNew) ) { Aig_ManStop( pNew); pNew = Aig_ManDupSimple( p ); } return pNew; } /**Function************************************************************* Synopsis [Derives CEX for the original AIG from CEX of the unrolled AIG.] Description [The number of PIs of the given CEX should divide by the number of PIs of the original AIG without a remainder.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Saig_PhaseTranslateCex( Aig_Man_t * p, Abc_Cex_t * pCex ) { Abc_Cex_t * pNew; int i, k, iFrame, nFrames; // make sure the PI count of the AIG is a multiple of the PI count of the CEX // if this is not true, the CEX is not derived as the result of unrolling of pAig // or the unrolled CEX went through transformations that change the PI count if ( pCex->nPis % Saig_ManPiNum(p) != 0 ) { printf( "The PI count in the AIG and in the CEX do not match.\n" ); return NULL; } // get the number of unrolled frames nFrames = pCex->nPis / Saig_ManPiNum(p); // get the frame where it fails iFrame = pCex->iFrame * nFrames + pCex->iPo / Saig_ManPoNum(p); // start a new CEX (assigns: p->nRegs, p->nPis, p->nBits) pNew = Abc_CexAlloc( Saig_ManRegNum(p), Saig_ManPiNum(p), iFrame+1 ); assert( pNew->nBits == pNew->nPis * (iFrame + 1) + pNew->nRegs ); // now assign the failed frame and the failed PO (p->iFrame and p->iPo) pNew->iFrame = iFrame; pNew->iPo = pCex->iPo % Saig_ManPoNum(p); // copy the bit data for ( i = pCex->nRegs, k = pNew->nRegs; k < pNew->nBits; k++, i++ ) if ( Abc_InfoHasBit( pCex->pData, i ) ) Abc_InfoSetBit( pNew->pData, k ); assert( i <= pCex->nBits ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigRefSat.c000066400000000000000000001023531477524141600166520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigRefSat.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [SAT based refinement of a counter-example.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigRefSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // local manager typedef struct Saig_RefMan_t_ Saig_RefMan_t; struct Saig_RefMan_t_ { // user data Aig_Man_t * pAig; // user's AIG Abc_Cex_t * pCex; // user's CEX int nInputs; // the number of first inputs to skip int fVerbose; // verbose flag // unrolling Aig_Man_t * pFrames; // unrolled timeframes Vec_Int_t * vMapPiF2A; // mapping of frame PIs into real PIs }; // performs ternary simulation extern int Saig_ManSimDataInit( Aig_Man_t * p, Abc_Cex_t * pCex, Vec_Ptr_t * vSimInfo, Vec_Int_t * vRes ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Maps array of frame PI IDs into array of original PI IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_RefManReason2Inputs( Saig_RefMan_t * p, Vec_Int_t * vReasons ) { Vec_Int_t * vOriginal, * vVisited; int i, Entry; vOriginal = Vec_IntAlloc( Saig_ManPiNum(p->pAig) ); vVisited = Vec_IntStart( Saig_ManPiNum(p->pAig) ); Vec_IntForEachEntry( vReasons, Entry, i ) { int iInput = Vec_IntEntry( p->vMapPiF2A, 2*Entry ); assert( iInput >= 0 && iInput < Aig_ManCiNum(p->pAig) ); if ( Vec_IntEntry(vVisited, iInput) == 0 ) Vec_IntPush( vOriginal, iInput ); Vec_IntAddToEntry( vVisited, iInput, 1 ); } Vec_IntFree( vVisited ); return vOriginal; } /**Function************************************************************* Synopsis [Creates the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Saig_RefManReason2Cex( Saig_RefMan_t * p, Vec_Int_t * vReasons ) { Abc_Cex_t * pCare; int i, Entry, iInput, iFrame; pCare = Abc_CexDup( p->pCex, p->pCex->nRegs ); memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) ); Vec_IntForEachEntry( vReasons, Entry, i ) { assert( Entry >= 0 && Entry < Aig_ManCiNum(p->pFrames) ); iInput = Vec_IntEntry( p->vMapPiF2A, 2*Entry ); iFrame = Vec_IntEntry( p->vMapPiF2A, 2*Entry+1 ); Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput ); } return pCare; } /**Function************************************************************* Synopsis [Returns reasons for the property to fail.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_RefManFindReason_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vPrios, Vec_Int_t * vReasons ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); if ( Aig_ObjIsCi(pObj) ) { Vec_IntPush( vReasons, Aig_ObjCioId(pObj) ); return; } assert( Aig_ObjIsNode(pObj) ); if ( pObj->fPhase ) { Saig_RefManFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons ); Saig_RefManFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons ); } else { int fPhase0 = Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase; int fPhase1 = Aig_ObjFaninC1(pObj) ^ Aig_ObjFanin1(pObj)->fPhase; assert( !fPhase0 || !fPhase1 ); if ( !fPhase0 && fPhase1 ) Saig_RefManFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons ); else if ( fPhase0 && !fPhase1 ) Saig_RefManFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons ); else { int iPrio0 = Vec_IntEntry( vPrios, Aig_ObjFaninId0(pObj) ); int iPrio1 = Vec_IntEntry( vPrios, Aig_ObjFaninId1(pObj) ); if ( iPrio0 <= iPrio1 ) Saig_RefManFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons ); else Saig_RefManFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons ); } } } /**Function************************************************************* Synopsis [Returns reasons for the property to fail.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_RefManFindReason( Saig_RefMan_t * p ) { Aig_Obj_t * pObj; Vec_Int_t * vPrios, * vPi2Prio, * vReasons; int i, CountPrios; vPi2Prio = Vec_IntStartFull( Saig_ManPiNum(p->pAig) ); vPrios = Vec_IntStartFull( Aig_ManObjNumMax(p->pFrames) ); // set PI values according to CEX CountPrios = 0; Aig_ManConst1(p->pFrames)->fPhase = 1; Aig_ManForEachCi( p->pFrames, pObj, i ) { int iInput = Vec_IntEntry( p->vMapPiF2A, 2*i ); int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 ); pObj->fPhase = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); // assign priority if ( Vec_IntEntry(vPi2Prio, iInput) == ~0 ) Vec_IntWriteEntry( vPi2Prio, iInput, CountPrios++ ); // Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), Vec_IntEntry(vPi2Prio, iInput) ); Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), i ); } // printf( "Priority numbers = %d.\n", CountPrios ); Vec_IntFree( vPi2Prio ); // traverse and set the priority Aig_ManForEachNode( p->pFrames, pObj, i ) { int fPhase0 = Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase; int fPhase1 = Aig_ObjFaninC1(pObj) ^ Aig_ObjFanin1(pObj)->fPhase; int iPrio0 = Vec_IntEntry( vPrios, Aig_ObjFaninId0(pObj) ); int iPrio1 = Vec_IntEntry( vPrios, Aig_ObjFaninId1(pObj) ); pObj->fPhase = fPhase0 && fPhase1; if ( fPhase0 && fPhase1 ) // both are one Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), Abc_MaxInt(iPrio0, iPrio1) ); else if ( !fPhase0 && fPhase1 ) Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), iPrio0 ); else if ( fPhase0 && !fPhase1 ) Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), iPrio1 ); else // both are zero Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), Abc_MinInt(iPrio0, iPrio1) ); } // check the property output pObj = Aig_ManCo( p->pFrames, 0 ); assert( (int)Aig_ObjFanin0(pObj)->fPhase == Aig_ObjFaninC0(pObj) ); // select the reason vReasons = Vec_IntAlloc( 100 ); Aig_ManIncrementTravId( p->pFrames ); if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) Saig_RefManFindReason_rec( p->pFrames, Aig_ObjFanin0(pObj), vPrios, vReasons ); Vec_IntFree( vPrios ); return vReasons; } /**Function************************************************************* Synopsis [Collect nodes in the unrolled timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManUnrollCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vObjs, Vec_Int_t * vRoots ) { if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) return; Aig_ObjSetTravIdCurrent(pAig, pObj); if ( Aig_ObjIsCo(pObj) ) Saig_ManUnrollCollect_rec( pAig, Aig_ObjFanin0(pObj), vObjs, vRoots ); else if ( Aig_ObjIsNode(pObj) ) { Saig_ManUnrollCollect_rec( pAig, Aig_ObjFanin0(pObj), vObjs, vRoots ); Saig_ManUnrollCollect_rec( pAig, Aig_ObjFanin1(pObj), vObjs, vRoots ); } if ( vRoots && Saig_ObjIsLo( pAig, pObj ) ) Vec_IntPush( vRoots, Aig_ObjId( Saig_ObjLoToLi(pAig, pObj) ) ); Vec_IntPush( vObjs, Aig_ObjId(pObj) ); } /**Function************************************************************* Synopsis [Derive unrolled timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManUnrollWithCex( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, Vec_Int_t ** pvMapPiF2A ) { Aig_Man_t * pFrames; // unrolled timeframes Vec_Vec_t * vFrameCos; // the list of COs per frame Vec_Vec_t * vFrameObjs; // the list of objects per frame Vec_Int_t * vRoots, * vObjs; Aig_Obj_t * pObj; int i, f; // sanity checks assert( Saig_ManPiNum(pAig) == pCex->nPis ); assert( Saig_ManRegNum(pAig) == pCex->nRegs ); assert( pCex->iPo >= 0 && pCex->iPo < Saig_ManPoNum(pAig) ); // map PIs of the unrolled frames into PIs of the original design *pvMapPiF2A = Vec_IntAlloc( 1000 ); // collect COs and Objs visited in each frame vFrameCos = Vec_VecStart( pCex->iFrame+1 ); vFrameObjs = Vec_VecStart( pCex->iFrame+1 ); // initialized the topmost frame pObj = Aig_ManCo( pAig, pCex->iPo ); Vec_VecPushInt( vFrameCos, pCex->iFrame, Aig_ObjId(pObj) ); for ( f = pCex->iFrame; f >= 0; f-- ) { // collect nodes starting from the roots Aig_ManIncrementTravId( pAig ); vRoots = Vec_VecEntryInt( vFrameCos, f ); Aig_ManForEachObjVec( vRoots, pAig, pObj, i ) Saig_ManUnrollCollect_rec( pAig, pObj, Vec_VecEntryInt(vFrameObjs, f), (Vec_Int_t *)(f ? Vec_VecEntry(vFrameCos, f-1) : NULL) ); } // derive unrolled timeframes pFrames = Aig_ManStart( 10000 ); pFrames->pName = Abc_UtilStrsav( pAig->pName ); pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); // initialize the flops Saig_ManForEachLo( pAig, pObj, i ) pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Abc_InfoHasBit(pCex->pData, i) ); // iterate through the frames for ( f = 0; f <= pCex->iFrame; f++ ) { // construct vObjs = Vec_VecEntryInt( vFrameObjs, f ); Aig_ManForEachObjVec( vObjs, pAig, pObj, i ) { if ( Aig_ObjIsNode(pObj) ) pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); else if ( Aig_ObjIsCo(pObj) ) pObj->pData = Aig_ObjChild0Copy(pObj); else if ( Aig_ObjIsConst1(pObj) ) pObj->pData = Aig_ManConst1(pFrames); else if ( Saig_ObjIsPi(pAig, pObj) ) { if ( Aig_ObjCioId(pObj) < nInputs ) { int iBit = pCex->nRegs + f * pCex->nPis + Aig_ObjCioId(pObj); pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Abc_InfoHasBit(pCex->pData, iBit) ); } else { pObj->pData = Aig_ObjCreateCi( pFrames ); Vec_IntPush( *pvMapPiF2A, Aig_ObjCioId(pObj) ); Vec_IntPush( *pvMapPiF2A, f ); } } } if ( f == pCex->iFrame ) break; // transfer vRoots = Vec_VecEntryInt( vFrameCos, f ); Aig_ManForEachObjVec( vRoots, pAig, pObj, i ) Saig_ObjLiToLo( pAig, pObj )->pData = pObj->pData; } // create output pObj = Aig_ManCo( pAig, pCex->iPo ); Aig_ObjCreateCo( pFrames, Aig_Not((Aig_Obj_t *)pObj->pData) ); Aig_ManSetRegNum( pFrames, 0 ); // cleanup Vec_VecFree( vFrameCos ); Vec_VecFree( vFrameObjs ); // finallize Aig_ManCleanup( pFrames ); // return return pFrames; } /**Function************************************************************* Synopsis [Creates refinement manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Saig_RefMan_t * Saig_RefManStart( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, int fVerbose ) { Saig_RefMan_t * p; p = ABC_CALLOC( Saig_RefMan_t, 1 ); p->pAig = pAig; p->pCex = pCex; p->nInputs = nInputs; p->fVerbose = fVerbose; p->pFrames = Saig_ManUnrollWithCex( pAig, pCex, nInputs, &p->vMapPiF2A ); return p; } /**Function************************************************************* Synopsis [Destroys refinement manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_RefManStop( Saig_RefMan_t * p ) { Aig_ManStopP( &p->pFrames ); Vec_IntFreeP( &p->vMapPiF2A ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Sets phase bits in the timeframe AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_RefManSetPhases( Saig_RefMan_t * p, Abc_Cex_t * pCare, int fValue1 ) { Aig_Obj_t * pObj; int i, iFrame, iInput; Aig_ManConst1( p->pFrames )->fPhase = 1; Aig_ManForEachCi( p->pFrames, pObj, i ) { iInput = Vec_IntEntry( p->vMapPiF2A, 2*i ); iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 ); pObj->fPhase = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); // update value if it is a don't-care if ( pCare && !Abc_InfoHasBit( pCare->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ) ) pObj->fPhase = fValue1; } Aig_ManForEachNode( p->pFrames, pObj, i ) pObj->fPhase = ( Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj) ) & ( Aig_ObjFanin1(pObj)->fPhase ^ Aig_ObjFaninC1(pObj) ); Aig_ManForEachCo( p->pFrames, pObj, i ) pObj->fPhase = ( Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj) ); pObj = Aig_ManCo( p->pFrames, 0 ); return pObj->fPhase; } /**Function************************************************************* Synopsis [Tries to remove literals from abstraction.] Description [The literals are sorted more desirable first.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Saig_RefManOrderLiterals( Saig_RefMan_t * p, Vec_Int_t * vVar2PiId, Vec_Int_t * vAssumps ) { Vec_Vec_t * vLits; Vec_Int_t * vVar2New; int i, Entry, iInput, iFrame; // collect literals vLits = Vec_VecAlloc( 100 ); vVar2New = Vec_IntStartFull( Saig_ManPiNum(p->pAig) ); Vec_IntForEachEntry( vAssumps, Entry, i ) { int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(Entry) ); assert( iPiNum >= 0 && iPiNum < Aig_ManCiNum(p->pFrames) ); iInput = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum ); iFrame = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum+1 ); // Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput ); if ( Vec_IntEntry( vVar2New, iInput ) == ~0 ) Vec_IntWriteEntry( vVar2New, iInput, Vec_VecSize(vLits) ); Vec_VecPushInt( vLits, Vec_IntEntry( vVar2New, iInput ), Entry ); } Vec_IntFree( vVar2New ); return vLits; } /**Function************************************************************* Synopsis [Generate the care set using SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Saig_RefManCreateCex( Saig_RefMan_t * p, Vec_Int_t * vVar2PiId, Vec_Int_t * vAssumps ) { Abc_Cex_t * pCare; int i, Entry, iInput, iFrame; // create counter-example pCare = Abc_CexDup( p->pCex, p->pCex->nRegs ); memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) ); Vec_IntForEachEntry( vAssumps, Entry, i ) { int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(Entry) ); assert( iPiNum >= 0 && iPiNum < Aig_ManCiNum(p->pFrames) ); iInput = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum ); iFrame = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum+1 ); Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput ); } return pCare; } /**Function************************************************************* Synopsis [Generate the care set using SAT solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Saig_RefManRunSat( Saig_RefMan_t * p, int fNewOrder ) { int nConfLimit = 1000000; Abc_Cex_t * pCare; Cnf_Dat_t * pCnf; sat_solver * pSat; Aig_Obj_t * pObj; Vec_Vec_t * vLits = NULL; Vec_Int_t * vAssumps, * vVar2PiId; int i, k, Entry, RetValue;//, f = 0, Counter = 0; int nCoreLits, * pCoreLits; clock_t clk = clock(); // create CNF assert( Aig_ManRegNum(p->pFrames) == 0 ); // pCnf = Cnf_Derive( p->pFrames, 0 ); // too slow pCnf = Cnf_DeriveSimple( p->pFrames, 0 ); RetValue = Saig_RefManSetPhases( p, NULL, 0 ); if ( RetValue ) { printf( "Constructed frames are incorrect.\n" ); Cnf_DataFree( pCnf ); return NULL; } Cnf_DataTranformPolarity( pCnf, 0 ); // create SAT solver pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); if ( pSat == NULL ) { Cnf_DataFree( pCnf ); return NULL; } //Abc_PrintTime( 1, "Preparing", clock() - clk ); // look for a true counter-example if ( p->nInputs > 0 ) { RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); if ( RetValue == l_False ) { printf( "The problem is trivially UNSAT. The CEX is real.\n" ); // create counter-example pCare = Abc_CexDup( p->pCex, p->pCex->nRegs ); memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) ); return pCare; } // the problem is SAT - it is expected } // create assumptions vVar2PiId = Vec_IntStartFull( pCnf->nVars ); vAssumps = Vec_IntAlloc( Aig_ManCiNum(p->pFrames) ); Aig_ManForEachCi( p->pFrames, pObj, i ) { // RetValue = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); // Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !RetValue ) ); Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 ) ); Vec_IntWriteEntry( vVar2PiId, pCnf->pVarNums[Aig_ObjId(pObj)], i ); } // reverse the order of assumptions // if ( fNewOrder ) // Vec_IntReverseOrder( vAssumps ); if ( fNewOrder ) { // create literals vLits = Saig_RefManOrderLiterals( p, vVar2PiId, vAssumps ); // sort literals Vec_VecSort( vLits, 1 ); // save literals Vec_IntClear( vAssumps ); Vec_VecForEachEntryInt( vLits, Entry, i, k ) Vec_IntPush( vAssumps, Entry ); for ( i = 0; i < Vec_VecSize(vLits); i++ ) printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) ); printf( "\n" ); if ( p->fVerbose ) printf( "Total PIs = %d. Essential PIs = %d.\n", Saig_ManPiNum(p->pAig) - p->nInputs, Vec_VecSize(vLits) ); } // solve clk = clock(); RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); //Abc_PrintTime( 1, "Solving", clock() - clk ); if ( RetValue != l_False ) { if ( RetValue == l_True ) printf( "Internal Error!!! The resulting problem is SAT.\n" ); else printf( "Internal Error!!! SAT solver timed out.\n" ); Cnf_DataFree( pCnf ); sat_solver_delete( pSat ); Vec_IntFree( vAssumps ); Vec_IntFree( vVar2PiId ); return NULL; } assert( RetValue == l_False ); // UNSAT // get relevant SAT literals nCoreLits = sat_solver_final( pSat, &pCoreLits ); assert( nCoreLits > 0 ); if ( p->fVerbose ) printf( "AnalizeFinal selected %d assumptions (out of %d). Conflicts = %d.\n", nCoreLits, Vec_IntSize(vAssumps), (int)pSat->stats.conflicts ); // save literals Vec_IntClear( vAssumps ); for ( i = 0; i < nCoreLits; i++ ) Vec_IntPush( vAssumps, pCoreLits[i] ); // create literals vLits = Saig_RefManOrderLiterals( p, vVar2PiId, vAssumps ); // sort literals // Vec_VecSort( vLits, 0 ); // save literals Vec_IntClear( vAssumps ); Vec_VecForEachEntryInt( vLits, Entry, i, k ) Vec_IntPush( vAssumps, Entry ); // for ( i = 0; i < Vec_VecSize(vLits); i++ ) // printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) ); // printf( "\n" ); if ( p->fVerbose ) printf( "Total PIs = %d. Essential PIs = %d.\n", Saig_ManPiNum(p->pAig) - p->nInputs, Vec_VecSize(vLits) ); /* // try assumptions in different order RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", Vec_IntSize(vAssumps), (RetValue == l_False ? "UNSAT" : "SAT"), (int)pSat->stats.conflicts ); // create different sets of assumptions Counter = Vec_VecSize(vLits); for ( f = 0; f < Vec_VecSize(vLits); f++ ) { Vec_IntClear( vAssumps ); Vec_VecForEachEntryInt( vLits, Entry, i, k ) if ( i != f ) Vec_IntPush( vAssumps, Entry ); // try the new assumptions RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", Vec_IntSize(vAssumps), RetValue == l_False ? "UNSAT" : "SAT", (int)pSat->stats.conflicts ); if ( RetValue != l_False ) continue; // UNSAT - remove literals Vec_IntClear( Vec_VecEntryInt(vLits, f) ); Counter--; } for ( i = 0; i < Vec_VecSize(vLits); i++ ) printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) ); printf( "\n" ); if ( p->fVerbose ) printf( "Total PIs = %d. Essential PIs = %d.\n", Saig_ManPiNum(p->pAig) - p->nInputs, Counter ); // save literals Vec_IntClear( vAssumps ); Vec_VecForEachEntryInt( vLits, Entry, i, k ) Vec_IntPush( vAssumps, Entry ); */ // create counter-example pCare = Saig_RefManCreateCex( p, vVar2PiId, vAssumps ); // cleanup Cnf_DataFree( pCnf ); sat_solver_delete( pSat ); Vec_IntFree( vAssumps ); Vec_IntFree( vVar2PiId ); Vec_VecFreeP( &vLits ); // verify counter-example RetValue = Saig_RefManSetPhases( p, pCare, 0 ); if ( RetValue ) printf( "Reduced CEX verification has failed.\n" ); RetValue = Saig_RefManSetPhases( p, pCare, 1 ); if ( RetValue ) printf( "Reduced CEX verification has failed.\n" ); return pCare; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_RefManRefineWithSat( Saig_RefMan_t * p, Vec_Int_t * vAigPis ) { int nConfLimit = 1000000; Cnf_Dat_t * pCnf; sat_solver * pSat; Aig_Obj_t * pObj; Vec_Vec_t * vLits; Vec_Int_t * vReasons, * vAssumps, * vVisited, * vVar2PiId; int i, k, f, Entry, RetValue, Counter; // create CNF and SAT solver pCnf = Cnf_DeriveSimple( p->pFrames, 0 ); pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); if ( pSat == NULL ) { Cnf_DataFree( pCnf ); return NULL; } // mark used AIG inputs vVisited = Vec_IntStart( Saig_ManPiNum(p->pAig) ); Vec_IntForEachEntry( vAigPis, Entry, i ) { assert( Entry >= 0 && Entry < Aig_ManCiNum(p->pAig) ); Vec_IntWriteEntry( vVisited, Entry, 1 ); } // create assumptions vVar2PiId = Vec_IntStartFull( pCnf->nVars ); vAssumps = Vec_IntAlloc( Aig_ManCiNum(p->pFrames) ); Aig_ManForEachCi( p->pFrames, pObj, i ) { int iInput = Vec_IntEntry( p->vMapPiF2A, 2*i ); int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 ); if ( Vec_IntEntry(vVisited, iInput) == 0 ) continue; RetValue = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !RetValue ) ); // Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 ) ); Vec_IntWriteEntry( vVar2PiId, pCnf->pVarNums[Aig_ObjId(pObj)], i ); } Vec_IntFree( vVisited ); // try assumptions in different order RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", Vec_IntSize(vAssumps), (RetValue == l_False ? "UNSAT" : "SAT"), (int)pSat->stats.conflicts ); /* // AnalizeFinal does not work because it implications propagate directly // and SAT solver does not kick in (the number of conflicts in 0). // count the number of lits in the unsat core { int nCoreLits, * pCoreLits; nCoreLits = sat_solver_final( pSat, &pCoreLits ); assert( nCoreLits > 0 ); // count the number of flops vVisited = Vec_IntStart( Saig_ManPiNum(p->pAig) ); for ( i = 0; i < nCoreLits; i++ ) { int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(pCoreLits[i]) ); int iInput = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum ); int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum+1 ); Vec_IntWriteEntry( vVisited, iInput, 1 ); } // count the number of entries Counter = 0; Vec_IntForEachEntry( vVisited, Entry, i ) Counter += Entry; Vec_IntFree( vVisited ); // if ( p->fVerbose ) printf( "AnalizeFinal: Assumptions %d (out of %d). Essential PIs = %d. Conflicts = %d.\n", nCoreLits, Vec_IntSize(vAssumps), Counter, (int)pSat->stats.conflicts ); } */ // derive literals vLits = Saig_RefManOrderLiterals( p, vVar2PiId, vAssumps ); for ( i = 0; i < Vec_VecSize(vLits); i++ ) printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) ); printf( "\n" ); // create different sets of assumptions Counter = Vec_VecSize(vLits); for ( f = 0; f < Vec_VecSize(vLits); f++ ) { Vec_IntClear( vAssumps ); Vec_VecForEachEntryInt( vLits, Entry, i, k ) if ( i != f ) Vec_IntPush( vAssumps, Entry ); // try the new assumptions RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", Vec_IntSize(vAssumps), RetValue == l_False ? "UNSAT" : "SAT", (int)pSat->stats.conflicts ); if ( RetValue != l_False ) continue; // UNSAT - remove literals Vec_IntClear( Vec_VecEntryInt(vLits, f) ); Counter--; } for ( i = 0; i < Vec_VecSize(vLits); i++ ) printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) ); printf( "\n" ); // create assumptions Vec_IntClear( vAssumps ); Vec_VecForEachEntryInt( vLits, Entry, i, k ) Vec_IntPush( vAssumps, Entry ); // try assumptions in different order RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", Vec_IntSize(vAssumps), (RetValue == l_False ? "UNSAT" : "SAT"), (int)pSat->stats.conflicts ); // if ( p->fVerbose ) // printf( "Total PIs = %d. Essential PIs = %d.\n", // Saig_ManPiNum(p->pAig) - p->nInputs, Counter ); // transform assumptions into reasons vReasons = Vec_IntAlloc( 100 ); Vec_IntForEachEntry( vAssumps, Entry, i ) { int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(Entry) ); assert( iPiNum >= 0 && iPiNum < Aig_ManCiNum(p->pFrames) ); Vec_IntPush( vReasons, iPiNum ); } // cleanup Cnf_DataFree( pCnf ); sat_solver_delete( pSat ); Vec_IntFree( vAssumps ); Vec_IntFree( vVar2PiId ); Vec_VecFreeP( &vLits ); return vReasons; } /**Function************************************************************* Synopsis [SAT-based refinement of the counter-example.] Description [The first parameter (nInputs) indicates how many first primary inputs to skip without considering as care candidates.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Saig_ManFindCexCareBits( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, int fNewOrder, int fVerbose ) { Saig_RefMan_t * p; Vec_Int_t * vReasons; Abc_Cex_t * pCare; clock_t clk = clock(); clk = clock(); p = Saig_RefManStart( pAig, pCex, nInputs, fVerbose ); vReasons = Saig_RefManFindReason( p ); if ( fVerbose ) Aig_ManPrintStats( p->pFrames ); // if ( fVerbose ) { Vec_Int_t * vRes = Saig_RefManReason2Inputs( p, vReasons ); printf( "Frame PIs = %4d (essential = %4d) AIG PIs = %4d (essential = %4d) ", Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) ); ABC_PRT( "Time", clock() - clk ); Vec_IntFree( vRes ); /* //////////////////////////////////// Vec_IntFree( vReasons ); vReasons = Saig_RefManRefineWithSat( p, vRes ); //////////////////////////////////// Vec_IntFree( vRes ); vRes = Saig_RefManReason2Inputs( p, vReasons ); printf( "Frame PIs = %4d (essential = %4d) AIG PIs = %4d (essential = %4d) ", Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) ); Vec_IntFree( vRes ); ABC_PRT( "Time", clock() - clk ); */ } pCare = Saig_RefManReason2Cex( p, vReasons ); Vec_IntFree( vReasons ); Saig_RefManStop( p ); if ( fVerbose ) Abc_CexPrintStats( pCex ); if ( fVerbose ) Abc_CexPrintStats( pCare ); return pCare; } /**Function************************************************************* Synopsis [Returns the array of PIs for flops that should not be absracted.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_ManExtendCounterExampleTest3( Aig_Man_t * pAig, int iFirstFlopPi, Abc_Cex_t * pCex, int fVerbose ) { Saig_RefMan_t * p; Vec_Int_t * vRes, * vReasons; clock_t clk; if ( Saig_ManPiNum(pAig) != pCex->nPis ) { printf( "Saig_ManExtendCounterExampleTest3(): The PI count of AIG (%d) does not match that of cex (%d).\n", Aig_ManCiNum(pAig), pCex->nPis ); return NULL; } clk = clock(); p = Saig_RefManStart( pAig, pCex, iFirstFlopPi, fVerbose ); vReasons = Saig_RefManFindReason( p ); vRes = Saig_RefManReason2Inputs( p, vReasons ); // if ( fVerbose ) { printf( "Frame PIs = %4d (essential = %4d) AIG PIs = %4d (essential = %4d) ", Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) ); ABC_PRT( "Time", clock() - clk ); } /* //////////////////////////////////// Vec_IntFree( vReasons ); vReasons = Saig_RefManRefineWithSat( p, vRes ); //////////////////////////////////// // derive new result Vec_IntFree( vRes ); vRes = Saig_RefManReason2Inputs( p, vReasons ); // if ( fVerbose ) { printf( "Frame PIs = %4d (essential = %4d) AIG PIs = %4d (essential = %4d) ", Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) ); ABC_PRT( "Time", clock() - clk ); } */ Vec_IntFree( vReasons ); Saig_RefManStop( p ); return vRes; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigRetFwd.c000066400000000000000000000172431477524141600166640ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigRetFwd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Most-forward retiming.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigRetFwd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static inline Aig_Obj_t * Aig_ObjFanoutStatic( Aig_Obj_t * pObj, int i ) { return ((Aig_Obj_t **)pObj->pData)[i]; } static inline void Aig_ObjSetFanoutStatic( Aig_Obj_t * pObj, Aig_Obj_t * pFan ) { ((Aig_Obj_t **)pObj->pData)[pObj->nRefs++] = pFan; } #define Aig_ObjForEachFanoutStatic( pObj, pFan, i ) \ for ( i = 0; (i < (int)(pObj)->nRefs) && ((pFan) = Aig_ObjFanoutStatic(pObj, i)); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocate static fanout for all nodes in the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t ** Aig_ManStaticFanoutStart( Aig_Man_t * p ) { Aig_Obj_t ** ppFanouts, * pObj; int i, nFanouts, nFanoutsAlloc; // allocate fanouts nFanoutsAlloc = 2 * Aig_ManObjNumMax(p) - Aig_ManCiNum(p) - Aig_ManCoNum(p); ppFanouts = ABC_ALLOC( Aig_Obj_t *, nFanoutsAlloc ); // mark up storage nFanouts = 0; Aig_ManForEachObj( p, pObj, i ) { pObj->pData = ppFanouts + nFanouts; nFanouts += pObj->nRefs; pObj->nRefs = 0; } assert( nFanouts < nFanoutsAlloc ); // add fanouts Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjChild0(pObj) ) Aig_ObjSetFanoutStatic( Aig_ObjFanin0(pObj), pObj ); if ( Aig_ObjChild1(pObj) ) Aig_ObjSetFanoutStatic( Aig_ObjFanin1(pObj), pObj ); } return ppFanouts; } /**Function************************************************************* Synopsis [Marks the objects reachable from the given object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManMarkAutonomous_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pFanout; int i; if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); Aig_ObjForEachFanoutStatic( pObj, pFanout, i ) Aig_ManMarkAutonomous_rec( p, pFanout ); } /**Function************************************************************* Synopsis [Marks with current trav ID nodes reachable from Const1 and PIs.] Description [Returns the number of unreachable registers.] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManMarkAutonomous( Aig_Man_t * p ) { Aig_Obj_t ** ppFanouts; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i; // temporarily connect register outputs to register inputs Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) { pObjLo->pFanin0 = pObjLi; pObjLi->nRefs = 1; } // mark nodes reachable from Const1 and PIs Aig_ManIncrementTravId( p ); ppFanouts = Aig_ManStaticFanoutStart( p ); Aig_ManMarkAutonomous_rec( p, Aig_ManConst1(p) ); Saig_ManForEachPi( p, pObj, i ) Aig_ManMarkAutonomous_rec( p, pObj ); ABC_FREE( ppFanouts ); // disconnect LIs/LOs and label unreachable registers Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) { assert( pObjLo->pFanin0 && pObjLi->nRefs == 1 ); pObjLo->pFanin0 = NULL; pObjLi->nRefs = 0; } } /**Function************************************************************* Synopsis [Derives the cut for forward retiming.] Description [Assumes topological ordering of the nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManRetimeForwardOne( Aig_Man_t * p, int * pnRegFixed, int * pnRegMoves ) { Aig_Man_t * pNew; Vec_Ptr_t * vCut; Aig_Obj_t * pObj, * pFanin; int i; // mark the retimable nodes Saig_ManMarkAutonomous( p ); // mark the retimable registers with the fresh trav ID Aig_ManIncrementTravId( p ); *pnRegFixed = 0; Saig_ManForEachLo( p, pObj, i ) if ( Aig_ObjIsTravIdPrevious(p, pObj) ) Aig_ObjSetTravIdCurrent(p, pObj); else (*pnRegFixed)++; // mark all the nodes that can be retimed forward *pnRegMoves = 0; Aig_ManForEachNode( p, pObj, i ) if ( Aig_ObjIsTravIdCurrent(p, Aig_ObjFanin0(pObj)) && Aig_ObjIsTravIdCurrent(p, Aig_ObjFanin1(pObj)) ) { Aig_ObjSetTravIdCurrent(p, pObj); (*pnRegMoves)++; } // mark the remaining registers Saig_ManForEachLo( p, pObj, i ) Aig_ObjSetTravIdCurrent(p, pObj); // find the cut (all such marked objects that fanout into unmarked nodes) vCut = Vec_PtrAlloc( 1000 ); Aig_ManIncrementTravId( p ); Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjIsTravIdPrevious(p, pObj) ) continue; pFanin = Aig_ObjFanin0(pObj); if ( pFanin && Aig_ObjIsTravIdPrevious(p, pFanin) ) { Vec_PtrPush( vCut, pFanin ); Aig_ObjSetTravIdCurrent( p, pFanin ); } pFanin = Aig_ObjFanin1(pObj); if ( pFanin && Aig_ObjIsTravIdPrevious(p, pFanin) ) { Vec_PtrPush( vCut, pFanin ); Aig_ObjSetTravIdCurrent( p, pFanin ); } } // finally derive the new manager pNew = Saig_ManRetimeDupForward( p, vCut ); Vec_PtrFree( vCut ); return pNew; } /**Function************************************************************* Synopsis [Derives the cut for forward retiming.] Description [Assumes topological ordering of the nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManRetimeForward( Aig_Man_t * p, int nMaxIters, int fVerbose ) { Aig_Man_t * pNew, * pTemp; int i, nRegFixed, nRegMoves = 1; abctime clk; pNew = p; for ( i = 0; i < nMaxIters && nRegMoves > 0; i++ ) { clk = Abc_Clock(); pNew = Saig_ManRetimeForwardOne( pTemp = pNew, &nRegFixed, &nRegMoves ); if ( fVerbose ) { printf( "%2d : And = %6d. Reg = %5d. Unret = %5d. Move = %6d. ", i + 1, Aig_ManNodeNum(pTemp), Aig_ManRegNum(pTemp), nRegFixed, nRegMoves ); ABC_PRT( "Time", Abc_Clock() - clk ); } if ( pTemp != p ) Aig_ManStop( pTemp ); } clk = Abc_Clock(); pNew = Aig_ManReduceLaches( pNew, fVerbose ); if ( fVerbose ) { ABC_PRT( "Register sharing time", Abc_Clock() - clk ); } return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigRetMin.c000066400000000000000000000536221477524141600166700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigRetMin.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Min-area retiming for the AIG.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigRetMin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "opt/nwk/nwk.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Derives the initial state after backward retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_ManRetimeInitState( Aig_Man_t * p ) { int nConfLimit = 1000000; Vec_Int_t * vCiIds, * vInit = NULL; Cnf_Dat_t * pCnf; sat_solver * pSat; Aig_Obj_t * pObj; int i, RetValue, * pModel; // solve the SAT problem pCnf = Cnf_DeriveSimpleForRetiming( p ); pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); if ( pSat == NULL ) { Cnf_DataFree( pCnf ); return NULL; } RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); assert( RetValue != l_Undef ); // create counter-example if ( RetValue == l_True ) { // accumulate SAT variables of the CIs vCiIds = Vec_IntAlloc( Aig_ManCiNum(p) ); Aig_ManForEachCi( p, pObj, i ) Vec_IntPush( vCiIds, pCnf->pVarNums[pObj->Id] ); // create the model pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); vInit = Vec_IntAllocArray( pModel, Aig_ManCiNum(p) ); Vec_IntFree( vCiIds ); } sat_solver_delete( pSat ); Cnf_DataFree( pCnf ); return vInit; } /**Function************************************************************* Synopsis [Uses UNSAT core to find the part of AIG to be excluded.] Description [Returns the number of the PO that appears in the UNSAT core.] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManRetimeUnsatCore( Aig_Man_t * p, int fVerbose ) { int fVeryVerbose = 0; int nConfLimit = 1000000; void * pSatCnf = NULL; Intp_Man_t * pManProof; Vec_Int_t * vCore = NULL; Cnf_Dat_t * pCnf; sat_solver * pSat; Aig_Obj_t * pObj; int * pClause1, * pClause2, * pLit, * pVars; int i, RetValue, iBadPo, iClause, nVars, nPos; // create the SAT solver pCnf = Cnf_DeriveSimpleForRetiming( p ); pSat = sat_solver_new(); sat_solver_store_alloc( pSat ); sat_solver_setnvars( pSat, pCnf->nVars ); for ( i = 0; i < pCnf->nClauses; i++ ) { if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) { Cnf_DataFree( pCnf ); sat_solver_delete( pSat ); return -1; } } sat_solver_store_mark_roots( pSat ); // solve the problem RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); assert( RetValue != l_Undef ); assert( RetValue == l_False ); pSatCnf = sat_solver_store_release( pSat ); sat_solver_delete( pSat ); // derive the UNSAT core pManProof = Intp_ManAlloc(); vCore = (Vec_Int_t *)Intp_ManUnsatCore( pManProof, (Sto_Man_t *)pSatCnf, 0, fVeryVerbose ); Intp_ManFree( pManProof ); Sto_ManFree( (Sto_Man_t *)pSatCnf ); // derive the set of variables on which the core depends // collect the variable numbers nVars = 0; pVars = ABC_ALLOC( int, pCnf->nVars ); memset( pVars, 0, sizeof(int) * pCnf->nVars ); Vec_IntForEachEntry( vCore, iClause, i ) { pClause1 = pCnf->pClauses[iClause]; pClause2 = pCnf->pClauses[iClause+1]; for ( pLit = pClause1; pLit < pClause2; pLit++ ) { if ( pVars[ (*pLit) >> 1 ] == 0 ) nVars++; pVars[ (*pLit) >> 1 ] = 1; if ( fVeryVerbose ) printf( "%s%d ", ((*pLit) & 1)? "-" : "+", (*pLit) >> 1 ); } if ( fVeryVerbose ) printf( "\n" ); } // collect the nodes if ( fVeryVerbose ) { Aig_ManForEachObj( p, pObj, i ) if ( pCnf->pVarNums[pObj->Id] >= 0 && pVars[ pCnf->pVarNums[pObj->Id] ] == 1 ) { Aig_ObjPrint( p, pObj ); printf( "\n" ); } } // pick the first PO in the list nPos = 0; iBadPo = -1; Aig_ManForEachCo( p, pObj, i ) if ( pCnf->pVarNums[pObj->Id] >= 0 && pVars[ pCnf->pVarNums[pObj->Id] ] == 1 ) { if ( iBadPo == -1 ) iBadPo = i; nPos++; } if ( fVerbose ) printf( "UNSAT core: %d clauses, %d variables, %d POs. ", Vec_IntSize(vCore), nVars, nPos ); ABC_FREE( pVars ); Vec_IntFree( vCore ); Cnf_DataFree( pCnf ); return iBadPo; } /**Function************************************************************* Synopsis [Marks the TFI cone with the current traversal ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManMarkCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( pObj == NULL ) return; if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) return; Aig_ObjSetTravIdCurrent( p, pObj ); Saig_ManMarkCone_rec( p, Aig_ObjFanin0(pObj) ); Saig_ManMarkCone_rec( p, Aig_ObjFanin1(pObj) ); } /**Function************************************************************* Synopsis [Counts the number of nodes to get registers after retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManRetimeCountCut( Aig_Man_t * p, Vec_Ptr_t * vCut ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj, * pFanin; int i, RetValue; // mark the cones Aig_ManIncrementTravId( p ); Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) Saig_ManMarkCone_rec( p, pObj ); // collect the new cut vNodes = Vec_PtrAlloc( 1000 ); Aig_ManForEachObj( p, pObj, i ) { if ( Aig_ObjIsTravIdCurrent(p, pObj) ) continue; pFanin = Aig_ObjFanin0( pObj ); if ( pFanin && !pFanin->fMarkA && Aig_ObjIsTravIdCurrent(p, pFanin) ) { Vec_PtrPush( vNodes, pFanin ); pFanin->fMarkA = 1; } pFanin = Aig_ObjFanin1( pObj ); if ( pFanin && !pFanin->fMarkA && Aig_ObjIsTravIdCurrent(p, pFanin) ) { Vec_PtrPush( vNodes, pFanin ); pFanin->fMarkA = 1; } } Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) pObj->fMarkA = 0; RetValue = Vec_PtrSize( vNodes ); Vec_PtrFree( vNodes ); return RetValue; } /**Function************************************************************* Synopsis [Duplicates the AIG recursively.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManRetimeDup_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj ) { if ( pObj->pData ) return; assert( Aig_ObjIsNode(pObj) ); Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) ); Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin1(pObj) ); pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } /**Function************************************************************* Synopsis [Duplicates the AIG while retiming the registers to the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManRetimeDupForward( Aig_Man_t * p, Vec_Ptr_t * vCut ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i; // mark the cones under the cut // assert( Vec_PtrSize(vCut) == Saig_ManRetimeCountCut(p, vCut) ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nRegs = Vec_PtrSize(vCut); pNew->nTruePis = p->nTruePis; pNew->nTruePos = p->nTruePos; // create the true PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Saig_ManForEachPi( p, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); // create the registers Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) pObj->pData = Aig_NotCond( Aig_ObjCreateCi(pNew), pObj->fPhase ); // duplicate logic above the cut Aig_ManForEachCo( p, pObj, i ) Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) ); // create the true POs Saig_ManForEachPo( p, pObj, i ) Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); // remember value in LI Saig_ManForEachLi( p, pObj, i ) pObj->pData = Aig_ObjChild0Copy(pObj); // transfer values from the LIs to the LOs Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) pObjLo->pData = pObjLi->pData; // erase the data values on the internal nodes of the cut Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) if ( Aig_ObjIsNode(pObj) ) pObj->pData = NULL; // duplicate logic below the cut Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) { Saig_ManRetimeDup_rec( pNew, pObj ); Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)pObj->pData, pObj->fPhase) ); } Aig_ManCleanup( pNew ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG while retiming the registers to the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManRetimeDupBackward( Aig_Man_t * p, Vec_Ptr_t * vCut, Vec_Int_t * vInit ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i; // mark the cones under the cut // assert( Vec_PtrSize(vCut) == Saig_ManRetimeCountCut(p, vCut) ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); pNew->nRegs = Vec_PtrSize(vCut); pNew->nTruePis = p->nTruePis; pNew->nTruePos = p->nTruePos; // create the true PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Saig_ManForEachPi( p, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); // create the registers Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) pObj->pData = Aig_NotCond( Aig_ObjCreateCi(pNew), vInit?Vec_IntEntry(vInit,i):0 ); // duplicate logic above the cut and remember values Saig_ManForEachLi( p, pObj, i ) { Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) ); pObj->pData = Aig_ObjChild0Copy(pObj); } // transfer values from the LIs to the LOs Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) pObjLo->pData = pObjLi->pData; // erase the data values on the internal nodes of the cut Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) if ( Aig_ObjIsNode(pObj) ) pObj->pData = NULL; // replicate the data on the constant node and the PIs pObj = Aig_ManConst1(p); pObj->pData = Aig_ManConst1(pNew); Saig_ManForEachPi( p, pObj, i ) pObj->pData = Aig_ManCi( pNew, i ); // duplicate logic below the cut Saig_ManForEachPo( p, pObj, i ) { Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) ); Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) { Saig_ManRetimeDup_rec( pNew, pObj ); Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)pObj->pData, vInit?Vec_IntEntry(vInit,i):0) ); } Aig_ManCleanup( pNew ); return pNew; } /**Function************************************************************* Synopsis [Derives AIG for the initial state computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManRetimeDupInitState( Aig_Man_t * p, Vec_Ptr_t * vCut ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; // mark the cones under the cut // assert( Vec_PtrSize(vCut) == Saig_ManRetimeCountCut(p, vCut) ); // create the new manager pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); // create the true PIs Aig_ManCleanData( p ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); // create the registers Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) pObj->pData = Aig_ObjCreateCi(pNew); // duplicate logic above the cut and create POs Saig_ManForEachLi( p, pObj, i ) { Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) ); Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } return pNew; } /**Function************************************************************* Synopsis [Returns the array of bad registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Saig_ManGetRegistersToExclude( Aig_Man_t * p ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj, * pFanin; int i, Diffs; assert( Saig_ManRegNum(p) > 0 ); Saig_ManForEachLi( p, pObj, i ) { pFanin = Aig_ObjFanin0(pObj); if ( !Aig_ObjFaninC0(pObj) ) pFanin->fMarkA = 1; else pFanin->fMarkB = 1; } Diffs = 0; Saig_ManForEachLi( p, pObj, i ) { pFanin = Aig_ObjFanin0(pObj); Diffs += pFanin->fMarkA && pFanin->fMarkB; } vNodes = Vec_PtrAlloc( 100 ); if ( Diffs > 0 ) { Saig_ManForEachLi( p, pObj, i ) { pFanin = Aig_ObjFanin0(pObj); if ( pFanin->fMarkA && pFanin->fMarkB ) Vec_PtrPush( vNodes, pObj ); } assert( Vec_PtrSize(vNodes) == Diffs ); } Saig_ManForEachLi( p, pObj, i ) { pFanin = Aig_ObjFanin0(pObj); pFanin->fMarkA = pFanin->fMarkB = 0; } return vNodes; } /**Function************************************************************* Synopsis [Hides the registers that cannot be backward retimed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManHideBadRegs( Aig_Man_t * p, Vec_Ptr_t * vBadRegs ) { Vec_Ptr_t * vPisNew, * vPosNew; Aig_Obj_t * pObjLi, * pObjLo; int nTruePi, nTruePo, nBadRegs, i; if ( Vec_PtrSize(vBadRegs) == 0 ) return 0; // attached LOs to LIs Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) pObjLi->pData = pObjLo; // reorder them by putting bad registers first vPisNew = Vec_PtrDup( p->vCis ); vPosNew = Vec_PtrDup( p->vCos ); nTruePi = Aig_ManCiNum(p) - Aig_ManRegNum(p); nTruePo = Aig_ManCoNum(p) - Aig_ManRegNum(p); assert( nTruePi == p->nTruePis ); assert( nTruePo == p->nTruePos ); Vec_PtrForEachEntry( Aig_Obj_t *, vBadRegs, pObjLi, i ) { Vec_PtrWriteEntry( vPisNew, nTruePi++, pObjLi->pData ); Vec_PtrWriteEntry( vPosNew, nTruePo++, pObjLi ); pObjLi->fMarkA = 1; } Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) { if ( pObjLi->fMarkA ) { pObjLi->fMarkA = 0; continue; } Vec_PtrWriteEntry( vPisNew, nTruePi++, pObjLo ); Vec_PtrWriteEntry( vPosNew, nTruePo++, pObjLi ); } // check the sizes assert( nTruePi == Aig_ManCiNum(p) ); assert( nTruePo == Aig_ManCoNum(p) ); // transfer the arrays Vec_PtrFree( p->vCis ); p->vCis = vPisNew; Vec_PtrFree( p->vCos ); p->vCos = vPosNew; // update the PIs nBadRegs = Vec_PtrSize(vBadRegs); p->nRegs -= nBadRegs; p->nTruePis += nBadRegs; p->nTruePos += nBadRegs; return nBadRegs; } /**Function************************************************************* Synopsis [Exposes bad registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManExposeBadRegs( Aig_Man_t * p, int nBadRegs ) { p->nRegs += nBadRegs; p->nTruePis -= nBadRegs; p->nTruePos -= nBadRegs; } /**Function************************************************************* Synopsis [Performs min-area retiming backward with initial state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManRetimeMinAreaBackward( Aig_Man_t * pNew, int fVerbose ) { Aig_Man_t * pInit, * pFinal; Vec_Ptr_t * vBadRegs, * vCut; Vec_Int_t * vInit; int iBadReg; // transform the AIG to have no bad registers vBadRegs = Saig_ManGetRegistersToExclude( pNew ); if ( fVerbose && Vec_PtrSize(vBadRegs) ) printf( "Excluding %d registers that cannot be backward retimed.\n", Vec_PtrSize(vBadRegs) ); while ( 1 ) { Saig_ManHideBadRegs( pNew, vBadRegs ); Vec_PtrFree( vBadRegs ); // compute cut vCut = Nwk_ManDeriveRetimingCut( pNew, 0, fVerbose ); if ( Vec_PtrSize(vCut) >= Aig_ManRegNum(pNew) ) { Vec_PtrFree( vCut ); return NULL; } // derive the initial state pInit = Saig_ManRetimeDupInitState( pNew, vCut ); vInit = Saig_ManRetimeInitState( pInit ); if ( vInit != NULL ) { pFinal = Saig_ManRetimeDupBackward( pNew, vCut, vInit ); Vec_IntFree( vInit ); Vec_PtrFree( vCut ); Aig_ManStop( pInit ); return pFinal; } Vec_PtrFree( vCut ); // there is no initial state - find the offending output iBadReg = Saig_ManRetimeUnsatCore( pInit, fVerbose ); Aig_ManStop( pInit ); if ( fVerbose ) printf( "Excluding register %d.\n", iBadReg ); // prepare to remove this output vBadRegs = Vec_PtrAlloc( 1 ); Vec_PtrPush( vBadRegs, Aig_ManCo( pNew, Saig_ManPoNum(pNew) + iBadReg ) ); } return NULL; } /**Function************************************************************* Synopsis [Performs min-area retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ) { Vec_Ptr_t * vCut; Aig_Man_t * pNew, * pTemp, * pCopy; int i, fChanges; pNew = Aig_ManDupSimple( p ); // perform several iterations of forward retiming fChanges = 0; if ( !fBackwardOnly ) for ( i = 0; i < nMaxIters; i++ ) { if ( Saig_ManRegNum(pNew) == 0 ) break; vCut = Nwk_ManDeriveRetimingCut( pNew, 1, fVerbose ); if ( Vec_PtrSize(vCut) >= Aig_ManRegNum(pNew) ) { if ( fVerbose && !fChanges ) printf( "Forward retiming cannot reduce registers.\n" ); Vec_PtrFree( vCut ); break; } pNew = Saig_ManRetimeDupForward( pTemp = pNew, vCut ); Aig_ManStop( pTemp ); Vec_PtrFree( vCut ); if ( fVerbose ) Aig_ManReportImprovement( p, pNew ); fChanges = 1; } // perform several iterations of backward retiming fChanges = 0; if ( !fForwardOnly && !fInitial ) for ( i = 0; i < nMaxIters; i++ ) { if ( Saig_ManRegNum(pNew) == 0 ) break; vCut = Nwk_ManDeriveRetimingCut( pNew, 0, fVerbose ); if ( Vec_PtrSize(vCut) >= Aig_ManRegNum(pNew) ) { if ( fVerbose && !fChanges ) printf( "Backward retiming cannot reduce registers.\n" ); Vec_PtrFree( vCut ); break; } pNew = Saig_ManRetimeDupBackward( pTemp = pNew, vCut, NULL ); Aig_ManStop( pTemp ); Vec_PtrFree( vCut ); if ( fVerbose ) Aig_ManReportImprovement( p, pNew ); fChanges = 1; } else if ( !fForwardOnly && fInitial ) for ( i = 0; i < nMaxIters; i++ ) { if ( Saig_ManRegNum(pNew) == 0 ) break; pCopy = Aig_ManDupSimple( pNew ); pTemp = Saig_ManRetimeMinAreaBackward( pCopy, fVerbose ); Aig_ManStop( pCopy ); if ( pTemp == NULL ) { if ( fVerbose && !fChanges ) printf( "Backward retiming cannot reduce registers.\n" ); break; } Saig_ManExposeBadRegs( pTemp, Saig_ManPoNum(pTemp) - Saig_ManPoNum(pNew) ); Aig_ManStop( pNew ); pNew = pTemp; if ( fVerbose ) Aig_ManReportImprovement( p, pNew ); fChanges = 1; } if ( !fForwardOnly && !fInitial && fChanges ) printf( "Assuming const-0 init-state after backward retiming. Result will not verify.\n" ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigRetStep.c000066400000000000000000000163461477524141600170620ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigRetStep.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Implementation of retiming steps.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigRetStep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs one retiming step forward.] Description [Returns the pointer to the register output after retiming.] SideEffects [Remember to run Aig_ManSetCioIds() in advance.] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Saig_ManRetimeNodeFwd( Aig_Man_t * p, Aig_Obj_t * pObj, int fMakeBug ) { Aig_Obj_t * pFanin0, * pFanin1; Aig_Obj_t * pInput0, * pInput1; Aig_Obj_t * pObjNew, * pObjLi, * pObjLo; int fCompl; assert( Saig_ManRegNum(p) > 0 ); assert( Aig_ObjIsNode(pObj) ); // get the fanins pFanin0 = Aig_ObjFanin0(pObj); pFanin1 = Aig_ObjFanin1(pObj); // skip of they are not primary inputs if ( !Aig_ObjIsCi(pFanin0) || !Aig_ObjIsCi(pFanin1) ) return NULL; // skip of they are not register outputs if ( !Saig_ObjIsLo(p, pFanin0) || !Saig_ObjIsLo(p, pFanin1) ) return NULL; assert( Aig_ObjCioId(pFanin0) > 0 ); assert( Aig_ObjCioId(pFanin1) > 0 ); // skip latch guns if ( !Aig_ObjIsTravIdCurrent(p, pFanin0) && !Aig_ObjIsTravIdCurrent(p, pFanin1) ) return NULL; // get the inputs of these registers pInput0 = Saig_ManLi( p, Aig_ObjCioId(pFanin0) - Saig_ManPiNum(p) ); pInput1 = Saig_ManLi( p, Aig_ObjCioId(pFanin1) - Saig_ManPiNum(p) ); pInput0 = Aig_ObjChild0( pInput0 ); pInput1 = Aig_ObjChild0( pInput1 ); pInput0 = Aig_NotCond( pInput0, Aig_ObjFaninC0(pObj) ); pInput1 = Aig_NotCond( pInput1, Aig_ObjFaninC1(pObj) ); // get the condition when the register should be complemetned fCompl = Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj); if ( fMakeBug ) { printf( "Introducing bug during retiming.\n" ); pInput1 = Aig_Not( pInput1 ); } // create new node pObjNew = Aig_And( p, pInput0, pInput1 ); // create new register input pObjLi = Aig_ObjCreateCo( p, Aig_NotCond(pObjNew, fCompl) ); pObjLi->CioId = Aig_ManCoNum(p) - 1; // create new register output pObjLo = Aig_ObjCreateCi( p ); pObjLo->CioId = Aig_ManCiNum(p) - 1; p->nRegs++; // make sure the register is retimable. Aig_ObjSetTravIdCurrent(p, pObjLo); //printf( "Reg = %4d. Reg = %4d. Compl = %d. Phase = %d.\n", // pFanin0->PioNum, pFanin1->PioNum, Aig_IsComplement(pObjNew), fCompl ); // return register output return Aig_NotCond( pObjLo, fCompl ); } /**Function************************************************************* Synopsis [Performs one retiming step backward.] Description [Returns the pointer to node after retiming.] SideEffects [Remember to run Aig_ManSetCioIds() in advance.] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Saig_ManRetimeNodeBwd( Aig_Man_t * p, Aig_Obj_t * pObjLo ) { Aig_Obj_t * pFanin0, * pFanin1; Aig_Obj_t * pLo0New, * pLo1New; Aig_Obj_t * pLi0New, * pLi1New; Aig_Obj_t * pObj, * pObjNew, * pObjLi; int fCompl0, fCompl1; assert( Saig_ManRegNum(p) > 0 ); assert( Aig_ObjCioId(pObjLo) > 0 ); assert( Saig_ObjIsLo(p, pObjLo) ); // get the corresponding latch input pObjLi = Saig_ManLi( p, Aig_ObjCioId(pObjLo) - Saig_ManPiNum(p) ); // get the node pObj = Aig_ObjFanin0(pObjLi); if ( !Aig_ObjIsNode(pObj) ) return NULL; // get the fanins pFanin0 = Aig_ObjFanin0(pObj); pFanin1 = Aig_ObjFanin1(pObj); // get the complemented attributes of the fanins fCompl0 = Aig_ObjFaninC0(pObj) ^ Aig_ObjFaninC0(pObjLi); fCompl1 = Aig_ObjFaninC1(pObj) ^ Aig_ObjFaninC0(pObjLi); // create latch inputs pLi0New = Aig_ObjCreateCo( p, Aig_NotCond(pFanin0, fCompl0) ); pLi0New->CioId = Aig_ManCoNum(p) - 1; pLi1New = Aig_ObjCreateCo( p, Aig_NotCond(pFanin1, fCompl1) ); pLi1New->CioId = Aig_ManCoNum(p) - 1; // create latch outputs pLo0New = Aig_ObjCreateCi(p); pLo0New->CioId = Aig_ManCiNum(p) - 1; pLo1New = Aig_ObjCreateCi(p); pLo1New->CioId = Aig_ManCiNum(p) - 1; pLo0New = Aig_NotCond( pLo0New, fCompl0 ); pLo1New = Aig_NotCond( pLo1New, fCompl1 ); p->nRegs += 2; // create node pObjNew = Aig_And( p, pLo0New, pLo1New ); // assert( pObjNew->fPhase == 0 ); return pObjNew; } /**Function************************************************************* Synopsis [Performs the given number of retiming steps.] Description [Returns the pointer to node after retiming.] SideEffects [Remember to run Aig_ManSetCioIds() in advance.] SeeAlso [] ***********************************************************************/ int Saig_ManRetimeSteps( Aig_Man_t * p, int nSteps, int fForward, int fAddBugs ) { Aig_Obj_t * pObj, * pObjNew; int RetValue, s, i; Aig_ManSetCioIds( p ); Aig_ManFanoutStart( p ); p->fCreatePios = 1; if ( fForward ) { Saig_ManMarkAutonomous( p ); for ( s = 0; s < nSteps; s++ ) { Aig_ManForEachNode( p, pObj, i ) { pObjNew = Saig_ManRetimeNodeFwd( p, pObj, fAddBugs && (s == 10) ); // pObjNew = Saig_ManRetimeNodeFwd( p, pObj, 0 ); if ( pObjNew == NULL ) continue; Aig_ObjReplace( p, pObj, pObjNew, 0 ); break; } if ( i == Vec_PtrSize(p->vObjs) ) break; } } else { for ( s = 0; s < nSteps; s++ ) { Saig_ManForEachLo( p, pObj, i ) { pObjNew = Saig_ManRetimeNodeBwd( p, pObj ); if ( pObjNew == NULL ) continue; Aig_ObjReplace( p, pObj, pObjNew, 0 ); break; } if ( i == Vec_PtrSize(p->vObjs) ) break; } } p->fCreatePios = 0; Aig_ManFanoutStop( p ); RetValue = Aig_ManCleanup( p ); assert( RetValue == 0 ); Aig_ManSetRegNum( p, p->nRegs ); return s; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigScl.c000066400000000000000000000064211477524141600162060ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigScl.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Sequential cleanup.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigScl.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Report registers useless for SEC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManReportUselessRegisters( Aig_Man_t * pAig ) { Aig_Obj_t * pObj, * pDriver; int i, Counter1, Counter2; // set PIO numbers Aig_ManSetCioIds( pAig ); // check how many POs are driven by a register whose ref count is 1 Counter1 = 0; Saig_ManForEachPo( pAig, pObj, i ) { pDriver = Aig_ObjFanin0(pObj); if ( Saig_ObjIsLo(pAig, pDriver) && Aig_ObjRefs(pDriver) == 1 ) Counter1++; } // check how many PIs have ref count 1 and drive a register Counter2 = 0; Saig_ManForEachLi( pAig, pObj, i ) { pDriver = Aig_ObjFanin0(pObj); if ( Saig_ObjIsPi(pAig, pDriver) && Aig_ObjRefs(pDriver) == 1 ) Counter2++; } if ( Counter1 ) printf( "Network has %d (out of %d) registers driving POs.\n", Counter1, Saig_ManRegNum(pAig) ); if ( Counter2 ) printf( "Network has %d (out of %d) registers driven by PIs.\n", Counter2, Saig_ManRegNum(pAig) ); } /**Function************************************************************* Synopsis [Report the number of pairs of complemented registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_ManReportComplements( Aig_Man_t * p ) { Aig_Obj_t * pObj, * pFanin; int i, Counter = 0; assert( Aig_ManRegNum(p) > 0 ); Aig_ManForEachObj( p, pObj, i ) assert( !pObj->fMarkA ); Aig_ManForEachLiSeq( p, pObj, i ) { pFanin = Aig_ObjFanin0(pObj); if ( pFanin->fMarkA ) Counter++; else pFanin->fMarkA = 1; } // count fanins that have both attributes Aig_ManForEachLiSeq( p, pObj, i ) { pFanin = Aig_ObjFanin0(pObj); pFanin->fMarkA = 0; } return Counter; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigSimFast.c000066400000000000000000000371501477524141600170360ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigSimFast.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Fast sequential AIG simulator.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigSimFast.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // the AIG manager typedef struct Faig_Man_t_ Faig_Man_t; struct Faig_Man_t_ { // parameters int nPis; int nPos; int nCis; int nCos; int nFfs; int nNos; // offsets int nPis1; int nCis1; int nCisNos1; int nCisNosPos1; int nObjs; // allocated data int nWords; int pObjs[0]; }; static inline int Faig_CheckIdPi( Faig_Man_t * p, int i ) { return i >= 1 && i < p->nPis1; } static inline int Faig_CheckIdLo( Faig_Man_t * p, int i ) { return i >= p->nPis1 && i < p->nCis1; } static inline int Faig_CheckIdNo( Faig_Man_t * p, int i ) { return i >= p->nCis1 && i < p->nCisNos1; } static inline int Faig_CheckIdPo( Faig_Man_t * p, int i ) { return i >= p->nCisNos1 && i < p->nCisNosPos1; } static inline int Faig_CheckIdLi( Faig_Man_t * p, int i ) { return i >= p->nCisNosPos1 && i < p->nObjs; } static inline int Faig_CheckIdCo( Faig_Man_t * p, int i ) { return i >= p->nCisNos1 && i < p->nObjs; } static inline int Faig_CheckIdObj( Faig_Man_t * p, int i ) { return i >= 0 && i < p->nObjs; } static inline int Faig_ObjIdToNumPi( Faig_Man_t * p, int i ) { assert( Faig_CheckIdPi(p,i) ); return i - 1; } static inline int Faig_ObjIdToNumLo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLo(p,i) ); return i - p->nPis1; } static inline int Faig_ObjIdToNumNo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdNo(p,i) ); return i - p->nCis1; } static inline int Faig_ObjIdToNumPo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdPo(p,i) ); return i - p->nCisNos1; } static inline int Faig_ObjIdToNumLi( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLi(p,i) ); return i - p->nCisNosPos1; } static inline int Faig_ObjIdToNumCo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdCo(p,i) ); return i - p->nCisNos1; } static inline int Faig_ObjLoToLi( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLo(p,i) ); return p->nObjs - (p->nCis1 - i); } static inline int Faig_ObjLiToLo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLi(p,i) ); return p->nCis1 - (p->nObjs - i); } static inline int Faig_NodeChild0( Faig_Man_t * p, int n ) { return p->pObjs[n<<1]; } static inline int Faig_NodeChild1( Faig_Man_t * p, int n ) { return p->pObjs[(n<<1)+1]; } static inline int Faig_CoChild0( Faig_Man_t * p, int n ) { return p->pObjs[(p->nNos<<1)+n]; } static inline int Faig_ObjFaninC( int iFan ) { return iFan & 1; } static inline int Faig_ObjFanin( int iFan ) { return iFan >> 1; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks if the manager is correct.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Faig_ManIsCorrect( Aig_Man_t * pAig ) { return Aig_ManObjNumMax(pAig) == 1 + Aig_ManCiNum(pAig) + Aig_ManNodeNum(pAig) + Aig_ManCoNum(pAig); } /**Function************************************************************* Synopsis [Creates fast simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Faig_Man_t * Faig_ManAlloc( Aig_Man_t * pAig ) { Faig_Man_t * p; int nWords; // assert( Faig_ManIsCorrect(pAig) ); nWords = 2 * Aig_ManNodeNum(pAig) + Aig_ManCoNum(pAig); p = (Faig_Man_t *)ABC_ALLOC( char, sizeof(Faig_Man_t) + sizeof(int) * nWords ); //printf( "Allocating %7.2f MB.\n", 1.0 * (sizeof(Faig_Man_t) + sizeof(int) * nWords)/(1<<20) ); memset( p, 0, sizeof(Faig_Man_t) ); p->nPis = Aig_ManCiNum(pAig) - Aig_ManRegNum(pAig); p->nPos = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig); p->nCis = Aig_ManCiNum(pAig); p->nCos = Aig_ManCoNum(pAig); p->nFfs = Aig_ManRegNum(pAig); p->nNos = Aig_ManNodeNum(pAig); // offsets p->nPis1 = p->nPis + 1; p->nCis1 = p->nCis + 1; p->nCisNos1 = p->nCis + p->nNos + 1; p->nCisNosPos1 = p->nCis + p->nNos + p->nPos + 1; p->nObjs = p->nCis + p->nNos + p->nCos + 1; p->nWords = nWords; return p; } /**Function************************************************************* Synopsis [Creates fast simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Faig_Man_t * Faig_ManCreate( Aig_Man_t * pAig ) { Faig_Man_t * p; Aig_Obj_t * pObj; int i, iWord = 0; p = Faig_ManAlloc( pAig ); Aig_ManForEachNode( pAig, pObj, i ) { p->pObjs[iWord++] = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj); p->pObjs[iWord++] = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj); } Aig_ManForEachCo( pAig, pObj, i ) p->pObjs[iWord++] = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj); assert( iWord == p->nWords ); return p; } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Faig_SimulateNode( Faig_Man_t * p, int Id, unsigned * pSimInfo ) { int n = Faig_ObjIdToNumNo( p, Id ); int iFan0 = Faig_NodeChild0( p, n ); int iFan1 = Faig_NodeChild1( p, n ); if ( Faig_ObjFaninC(iFan0) && Faig_ObjFaninC(iFan1) ) return ~(pSimInfo[Faig_ObjFanin(iFan0)] | pSimInfo[Faig_ObjFanin(iFan1)]); if ( Faig_ObjFaninC(iFan0) && !Faig_ObjFaninC(iFan1) ) return (~pSimInfo[Faig_ObjFanin(iFan0)] & pSimInfo[Faig_ObjFanin(iFan1)]); if ( !Faig_ObjFaninC(iFan0) && Faig_ObjFaninC(iFan1) ) return (pSimInfo[Faig_ObjFanin(iFan0)] & ~pSimInfo[Faig_ObjFanin(iFan1)]); // if ( !Faig_ObjFaninC(iFan0) && !Faig_ObjFaninC(iFan1) ) return (pSimInfo[Faig_ObjFanin(iFan0)] & pSimInfo[Faig_ObjFanin(iFan1)]); } /**Function************************************************************* Synopsis [Simulates one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Faig_SimulateCo( Faig_Man_t * p, int Id, unsigned * pSimInfo ) { int n = Faig_ObjIdToNumCo( p, Id ); int iFan0 = Faig_CoChild0( p, n ); if ( Faig_ObjFaninC(iFan0) ) return ~pSimInfo[Faig_ObjFanin(iFan0)]; // if ( !Faig_ObjFaninC(iFan0) ) return pSimInfo[Faig_ObjFanin(iFan0)]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Faig_SimulateRandomShift( unsigned uOld ) { return (uOld << 16) | ((uOld ^ Aig_ManRandom(0)) & 0xffff); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned Faig_SimulateTransferShift( unsigned uOld, unsigned uNew ) { return (uOld << 16) | (uNew & 0xffff); } /**Function************************************************************* Synopsis [Simulates the timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int * Faig_ManSimulateFrames( Faig_Man_t * p, int nFrames, int nPref, int fTrans ) { int * pNumOnes = ABC_CALLOC( int, p->nObjs ); unsigned * pSimInfo = ABC_ALLOC( unsigned, p->nObjs ); int f, i; //printf( "Allocating %7.2f MB.\n", 1.0 * 4 * p->nObjs/(1<<20) ); //printf( "Allocating %7.2f MB.\n", 1.0 * 4 * p->nObjs/(1<<20) ); // set constant 1 pSimInfo[0] = ~0; for ( f = 0; f < nFrames; f++ ) { if ( fTrans ) { for ( i = 1; i < p->nPis1; i++ ) pSimInfo[i] = f? Faig_SimulateRandomShift( pSimInfo[i] ) : Aig_ManRandom( 0 ); for ( ; i < p->nCis1; i++ ) pSimInfo[i] = f? Faig_SimulateTransferShift( pSimInfo[i], pSimInfo[Faig_ObjLoToLi(p,i)] ) : 0; } else { for ( i = 1; i < p->nPis1; i++ ) pSimInfo[i] = Aig_ManRandom( 0 ); for ( ; i < p->nCis1; i++ ) pSimInfo[i] = f? pSimInfo[Faig_ObjLoToLi(p,i)] : 0; } for ( ; i < p->nCisNos1; i++ ) pSimInfo[i] = Faig_SimulateNode( p, i, pSimInfo ); for ( ; i < p->nObjs; i++ ) pSimInfo[i] = Faig_SimulateCo( p, i, pSimInfo ); if ( f < nPref ) continue; if ( fTrans ) { for ( i = 0; i < p->nObjs; i++ ) pNumOnes[i] += Aig_WordCountOnes( (pSimInfo[i] ^ (pSimInfo[i] >> 16)) & 0xffff ); } else { for ( i = 0; i < p->nObjs; i++ ) pNumOnes[i] += Aig_WordCountOnes( pSimInfo[i] ); } } ABC_FREE( pSimInfo ); return pNumOnes; } /**Function************************************************************* Synopsis [Computes switching activity of one node.] Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] SideEffects [] SeeAlso [] ***********************************************************************/ float Faig_ManComputeSwitching( int nOnes, int nSimWords ) { int nTotal = 32 * nSimWords; return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal; } /**Function************************************************************* Synopsis [Computes switching activity of one node.] Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] SideEffects [] SeeAlso [] ***********************************************************************/ float Faig_ManComputeProbOne( int nOnes, int nSimWords ) { int nTotal = 32 * nSimWords; return (float)nOnes / nTotal; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Faig_ManComputeSwitchProbs4( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ) { int fTrans = 1; Faig_Man_t * pAig; Vec_Int_t * vSwitching; int * pProbs; float * pSwitching; int nFramesReal; abctime clk;//, clkTotal = Abc_Clock(); if ( fProbOne ) fTrans = 0; vSwitching = Vec_IntStart( Aig_ManObjNumMax(p) ); pSwitching = (float *)vSwitching->pArray; clk = Abc_Clock(); pAig = Faig_ManCreate( p ); //ABC_PRT( "\nCreation ", Abc_Clock() - clk ); Aig_ManRandom( 1 ); // get the number of frames to simulate // if the parameter "seqsimframes" is defined, use it // otherwise, use the given number of frames "nFrames" nFramesReal = nFrames; if ( Abc_FrameReadFlag("seqsimframes") ) nFramesReal = atoi( Abc_FrameReadFlag("seqsimframes") ); if ( nFramesReal <= nPref ) { printf( "The total number of frames (%d) should exceed prefix (%d).\n", nFramesReal, nPref ); printf( "Setting the total number of frames to be %d.\n", nFrames ); nFramesReal = nFrames; } //printf( "Simulating %d frames.\n", nFramesReal ); clk = Abc_Clock(); pProbs = Faig_ManSimulateFrames( pAig, nFramesReal, nPref, fTrans ); //ABC_PRT( "Simulation", Abc_Clock() - clk ); clk = Abc_Clock(); if ( fTrans ) { Aig_Obj_t * pObj; int i, Counter = 0; pObj = Aig_ManConst1(p); pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 ); Aig_ManForEachCi( p, pObj, i ) pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 ); Aig_ManForEachNode( p, pObj, i ) pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 ); Aig_ManForEachCo( p, pObj, i ) pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 ); assert( Counter == pAig->nObjs ); } else if ( fProbOne ) { Aig_Obj_t * pObj; int i, Counter = 0; pObj = Aig_ManConst1(p); pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref ); Aig_ManForEachCi( p, pObj, i ) pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref ); Aig_ManForEachNode( p, pObj, i ) pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref ); Aig_ManForEachCo( p, pObj, i ) pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref ); assert( Counter == pAig->nObjs ); } else { Aig_Obj_t * pObj; int i, Counter = 0; pObj = Aig_ManConst1(p); pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref ); Aig_ManForEachCi( p, pObj, i ) pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref ); Aig_ManForEachNode( p, pObj, i ) pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref ); Aig_ManForEachCo( p, pObj, i ) pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref ); assert( Counter == pAig->nObjs ); } ABC_FREE( pProbs ); ABC_FREE( pAig ); //ABC_PRT( "Switch ", Abc_Clock() - clk ); //ABC_PRT( "TOTAL ", Abc_Clock() - clkTotal ); return vSwitching; } /**Function************************************************************* Synopsis [Computes probability of switching (or of being 1).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_ManComputeSwitchProb3s( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ) { // return Faig_ManComputeSwitchProbs( p, nFrames, nPref, fProbOne ); return NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigSimMv.c000066400000000000000000000741431477524141600165260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigSimMv.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Multi-valued simulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigSimMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define SAIG_DIFF_VALUES 8 #define SAIG_UNDEF_VALUE 0x1ffffffe //536870910 // old AIG typedef struct Saig_MvObj_t_ Saig_MvObj_t; struct Saig_MvObj_t_ { int iFan0; int iFan1; unsigned Type : 3; unsigned Value : 29; }; // new AIG typedef struct Saig_MvAnd_t_ Saig_MvAnd_t; struct Saig_MvAnd_t_ { int iFan0; int iFan1; int iNext; }; // simulation manager typedef struct Saig_MvMan_t_ Saig_MvMan_t; struct Saig_MvMan_t_ { // user data Aig_Man_t * pAig; // original AIG // parameters int nStatesMax; // maximum number of states int nLevelsMax; // maximum number of levels int nValuesMax; // maximum number of values int nFlops; // number of flops // compacted AIG Saig_MvObj_t * pAigOld; // AIG objects Vec_Ptr_t * vFlops; // collected flops Vec_Int_t * vXFlops; // flops that had at least one X-value Vec_Ptr_t * vTired; // collected flops unsigned * pTStates; // hash table for states int nTStatesSize; // hash table size Aig_MmFixed_t * pMemStates; // memory for states Vec_Ptr_t * vStates; // reached states int * pRegsUndef; // count the number of undef values int ** pRegsValues; // write the first different values int * nRegsValues; // count the number of different values int nRUndefs; // the number of undef registers int nRValues[SAIG_DIFF_VALUES+1]; // the number of registers with given values // internal AIG Saig_MvAnd_t * pAigNew; // AIG nodes int nObjsAlloc; // the number of objects allocated int nObjs; // the number of objects int nPis; // the number of primary inputs int * pTNodes; // hash table int nTNodesSize; // hash table size unsigned char * pLevels; // levels of AIG nodes }; static inline int Saig_MvObjFaninC0( Saig_MvObj_t * pObj ) { return pObj->iFan0 & 1; } static inline int Saig_MvObjFaninC1( Saig_MvObj_t * pObj ) { return pObj->iFan1 & 1; } static inline int Saig_MvObjFanin0( Saig_MvObj_t * pObj ) { return pObj->iFan0 >> 1; } static inline int Saig_MvObjFanin1( Saig_MvObj_t * pObj ) { return pObj->iFan1 >> 1; } static inline int Saig_MvConst0() { return 1; } static inline int Saig_MvConst1() { return 0; } static inline int Saig_MvConst( int c ) { return !c; } static inline int Saig_MvUndef() { return SAIG_UNDEF_VALUE; } static inline int Saig_MvIsConst0( int iNode ) { return iNode == 1; } static inline int Saig_MvIsConst1( int iNode ) { return iNode == 0; } static inline int Saig_MvIsConst( int iNode ) { return iNode < 2; } static inline int Saig_MvIsUndef( int iNode ) { return iNode == SAIG_UNDEF_VALUE; } static inline int Saig_MvRegular( int iNode ) { return (iNode & ~01); } static inline int Saig_MvNot( int iNode ) { return (iNode ^ 01); } static inline int Saig_MvNotCond( int iNode, int c ) { return (iNode ^ (c)); } static inline int Saig_MvIsComplement( int iNode ) { return (int)(iNode & 01); } static inline int Saig_MvLit2Var( int iNode ) { return (iNode >> 1); } static inline int Saig_MvVar2Lit( int iVar ) { return (iVar << 1); } static inline int Saig_MvLev( Saig_MvMan_t * p, int iNode ) { return p->pLevels[iNode >> 1]; } // iterator over compacted objects #define Saig_MvManForEachObj( pAig, pEntry ) \ for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates reduced manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Saig_MvObj_t * Saig_ManCreateReducedAig( Aig_Man_t * p, Vec_Ptr_t ** pvFlops ) { Saig_MvObj_t * pAig, * pEntry; Aig_Obj_t * pObj; int i; *pvFlops = Vec_PtrAlloc( Aig_ManRegNum(p) ); pAig = ABC_CALLOC( Saig_MvObj_t, Aig_ManObjNumMax(p)+1 ); Aig_ManForEachObj( p, pObj, i ) { pEntry = pAig + i; pEntry->Type = pObj->Type; if ( Aig_ObjIsCi(pObj) || i == 0 ) { if ( Saig_ObjIsLo(p, pObj) ) { pEntry->iFan0 = (Saig_ObjLoToLi(p, pObj)->Id << 1); pEntry->iFan1 = -1; Vec_PtrPush( *pvFlops, pEntry ); } continue; } pEntry->iFan0 = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj); if ( Aig_ObjIsCo(pObj) ) continue; assert( Aig_ObjIsNode(pObj) ); pEntry->iFan1 = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj); } pEntry = pAig + Aig_ManObjNumMax(p); pEntry->Type = AIG_OBJ_VOID; return pAig; } /**Function************************************************************* Synopsis [Creates a new node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Saig_MvCreateObj( Saig_MvMan_t * p, int iFan0, int iFan1 ) { Saig_MvAnd_t * pNode; if ( p->nObjs == p->nObjsAlloc ) { p->pAigNew = ABC_REALLOC( Saig_MvAnd_t, p->pAigNew, 2*p->nObjsAlloc ); p->pLevels = ABC_REALLOC( unsigned char, p->pLevels, 2*p->nObjsAlloc ); p->nObjsAlloc *= 2; } pNode = p->pAigNew + p->nObjs; pNode->iFan0 = iFan0; pNode->iFan1 = iFan1; pNode->iNext = 0; if ( iFan0 || iFan1 ) p->pLevels[p->nObjs] = 1 + Abc_MaxInt( Saig_MvLev(p, iFan0), Saig_MvLev(p, iFan1) ); else p->pLevels[p->nObjs] = 0, p->nPis++; return p->nObjs++; } /**Function************************************************************* Synopsis [Creates multi-valued simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Saig_MvMan_t * Saig_MvManStart( Aig_Man_t * pAig, int nFramesSatur ) { Saig_MvMan_t * p; int i; assert( Aig_ManRegNum(pAig) > 0 ); p = (Saig_MvMan_t *)ABC_ALLOC( Saig_MvMan_t, 1 ); memset( p, 0, sizeof(Saig_MvMan_t) ); // set parameters p->pAig = pAig; p->nStatesMax = 2 * nFramesSatur + 100; p->nLevelsMax = 4; p->nValuesMax = SAIG_DIFF_VALUES; p->nFlops = Aig_ManRegNum(pAig); // compacted AIG p->pAigOld = Saig_ManCreateReducedAig( pAig, &p->vFlops ); p->nTStatesSize = Abc_PrimeCudd( p->nStatesMax ); p->pTStates = ABC_CALLOC( unsigned, p->nTStatesSize ); p->pMemStates = Aig_MmFixedStart( sizeof(int) * (p->nFlops+1), p->nStatesMax ); p->vStates = Vec_PtrAlloc( p->nStatesMax ); Vec_PtrPush( p->vStates, NULL ); p->pRegsUndef = ABC_CALLOC( int, p->nFlops ); p->pRegsValues = ABC_ALLOC( int *, p->nFlops ); p->pRegsValues[0] = ABC_ALLOC( int, p->nValuesMax * p->nFlops ); for ( i = 1; i < p->nFlops; i++ ) p->pRegsValues[i] = p->pRegsValues[i-1] + p->nValuesMax; p->nRegsValues = ABC_CALLOC( int, p->nFlops ); p->vTired = Vec_PtrAlloc( 100 ); // internal AIG p->nObjsAlloc = 1000000; p->pAigNew = ABC_ALLOC( Saig_MvAnd_t, p->nObjsAlloc ); p->nTNodesSize = Abc_PrimeCudd( p->nObjsAlloc / 3 ); p->pTNodes = ABC_CALLOC( int, p->nTNodesSize ); p->pLevels = ABC_ALLOC( unsigned char, p->nObjsAlloc ); Saig_MvCreateObj( p, 0, 0 ); return p; } /**Function************************************************************* Synopsis [Destroys multi-valued simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_MvManStop( Saig_MvMan_t * p ) { Aig_MmFixedStop( p->pMemStates, 0 ); Vec_PtrFree( p->vStates ); Vec_IntFreeP( &p->vXFlops ); Vec_PtrFree( p->vFlops ); Vec_PtrFree( p->vTired ); ABC_FREE( p->pRegsValues[0] ); ABC_FREE( p->pRegsValues ); ABC_FREE( p->nRegsValues ); ABC_FREE( p->pRegsUndef ); ABC_FREE( p->pAigOld ); ABC_FREE( p->pTStates ); ABC_FREE( p->pAigNew ); ABC_FREE( p->pTNodes ); ABC_FREE( p->pLevels ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Hashing the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Saig_MvHash( int iFan0, int iFan1, int TableSize ) { unsigned Key = 0; assert( iFan0 < iFan1 ); Key ^= Saig_MvLit2Var(iFan0) * 7937; Key ^= Saig_MvLit2Var(iFan1) * 2971; Key ^= Saig_MvIsComplement(iFan0) * 911; Key ^= Saig_MvIsComplement(iFan1) * 353; return (int)(Key % TableSize); } /**Function************************************************************* Synopsis [Returns the place where this node is stored (or should be stored).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int * Saig_MvTableFind( Saig_MvMan_t * p, int iFan0, int iFan1 ) { Saig_MvAnd_t * pEntry; int * pPlace = p->pTNodes + Saig_MvHash( iFan0, iFan1, p->nTNodesSize ); for ( pEntry = (*pPlace)? p->pAigNew + *pPlace : NULL; pEntry; pPlace = &pEntry->iNext, pEntry = (*pPlace)? p->pAigNew + *pPlace : NULL ) if ( pEntry->iFan0 == iFan0 && pEntry->iFan1 == iFan1 ) break; return pPlace; } /**Function************************************************************* Synopsis [Performs an AND-operation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Saig_MvAnd( Saig_MvMan_t * p, int iFan0, int iFan1, int fFirst ) { if ( iFan0 == iFan1 ) return iFan0; if ( iFan0 == Saig_MvNot(iFan1) ) return Saig_MvConst0(); if ( Saig_MvIsConst(iFan0) ) return Saig_MvIsConst1(iFan0) ? iFan1 : Saig_MvConst0(); if ( Saig_MvIsConst(iFan1) ) return Saig_MvIsConst1(iFan1) ? iFan0 : Saig_MvConst0(); if ( Saig_MvIsUndef(iFan0) || Saig_MvIsUndef(iFan1) ) return Saig_MvUndef(); // if ( Saig_MvLev(p, iFan0) >= p->nLevelsMax || Saig_MvLev(p, iFan1) >= p->nLevelsMax ) // return Saig_MvUndef(); // go undef after the first frame if ( !fFirst ) return Saig_MvUndef(); if ( iFan0 > iFan1 ) { int Temp = iFan0; iFan0 = iFan1; iFan1 = Temp; } { int * pPlace; pPlace = Saig_MvTableFind( p, iFan0, iFan1 ); if ( *pPlace == 0 ) { if ( pPlace >= (int*)p->pAigNew && pPlace < (int*)(p->pAigNew + p->nObjsAlloc) ) { int iPlace = pPlace - (int*)p->pAigNew; int iNode = Saig_MvCreateObj( p, iFan0, iFan1 ); ((int*)p->pAigNew)[iPlace] = iNode; return Saig_MvVar2Lit( iNode ); } else *pPlace = Saig_MvCreateObj( p, iFan0, iFan1 ); } return Saig_MvVar2Lit( *pPlace ); } } /**Function************************************************************* Synopsis [Propagates one edge.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Saig_MvSimulateValue0( Saig_MvObj_t * pAig, Saig_MvObj_t * pObj ) { Saig_MvObj_t * pObj0 = pAig + Saig_MvObjFanin0(pObj); if ( Saig_MvIsUndef( pObj0->Value ) ) return Saig_MvUndef(); return Saig_MvNotCond( pObj0->Value, Saig_MvObjFaninC0(pObj) ); } static inline int Saig_MvSimulateValue1( Saig_MvObj_t * pAig, Saig_MvObj_t * pObj ) { Saig_MvObj_t * pObj1 = pAig + Saig_MvObjFanin1(pObj); if ( Saig_MvIsUndef( pObj1->Value ) ) return Saig_MvUndef(); return Saig_MvNotCond( pObj1->Value, Saig_MvObjFaninC1(pObj) ); } /**Function************************************************************* Synopsis [Prints MV state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_MvPrintState( int Iter, Saig_MvMan_t * p ) { Saig_MvObj_t * pEntry; int i; printf( "%3d : ", Iter ); Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i ) { if ( pEntry->Value == SAIG_UNDEF_VALUE ) printf( " *" ); else printf( "%5d", pEntry->Value ); } printf( "\n" ); } /**Function************************************************************* Synopsis [Performs one iteration of simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_MvSimulateFrame( Saig_MvMan_t * p, int fFirst, int fVerbose ) { Saig_MvObj_t * pEntry; int i; Saig_MvManForEachObj( p->pAigOld, pEntry ) { if ( pEntry->Type == AIG_OBJ_AND ) { pEntry->Value = Saig_MvAnd( p, Saig_MvSimulateValue0(p->pAigOld, pEntry), Saig_MvSimulateValue1(p->pAigOld, pEntry), fFirst ); } else if ( pEntry->Type == AIG_OBJ_CO ) pEntry->Value = Saig_MvSimulateValue0(p->pAigOld, pEntry); else if ( pEntry->Type == AIG_OBJ_CI ) { if ( pEntry->iFan1 == 0 ) // true PI { if ( fFirst ) pEntry->Value = Saig_MvVar2Lit( Saig_MvCreateObj( p, 0, 0 ) ); else pEntry->Value = SAIG_UNDEF_VALUE; } // else if ( fFirst ) // register output // pEntry->Value = Saig_MvConst0(); // else // pEntry->Value = Saig_MvSimulateValue0(p->pAigOld, pEntry); } else if ( pEntry->Type == AIG_OBJ_CONST1 ) pEntry->Value = Saig_MvConst1(); else if ( pEntry->Type != AIG_OBJ_NONE ) assert( 0 ); } // transfer to registers Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i ) pEntry->Value = Saig_MvSimulateValue0( p->pAigOld, pEntry ); } /**Function************************************************************* Synopsis [Computes hash value of the node using its simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_MvSimHash( unsigned * pState, int nFlops, int TableSize ) { static int s_SPrimes[16] = { 1610612741, 805306457, 402653189, 201326611, 100663319, 50331653, 25165843, 12582917, 6291469, 3145739, 1572869, 786433, 393241, 196613, 98317, 49157 }; unsigned uHash = 0; int i; for ( i = 0; i < nFlops; i++ ) uHash ^= pState[i] * s_SPrimes[i & 0xF]; return (int)(uHash % TableSize); } /**Function************************************************************* Synopsis [Returns the place where this state is stored (or should be stored).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline unsigned * Saig_MvSimTableFind( Saig_MvMan_t * p, unsigned * pState ) { unsigned * pEntry; unsigned * pPlace = p->pTStates + Saig_MvSimHash( pState+1, p->nFlops, p->nTStatesSize ); for ( pEntry = (*pPlace)? (unsigned *)Vec_PtrEntry(p->vStates, *pPlace) : NULL; pEntry; pPlace = pEntry, pEntry = (*pPlace)? (unsigned *)Vec_PtrEntry(p->vStates, *pPlace) : NULL ) if ( memcmp( pEntry+1, pState+1, sizeof(int)*p->nFlops ) == 0 ) break; return pPlace; } /**Function************************************************************* Synopsis [Saves current state.] Description [Returns -1 if there is no fixed point.] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_MvSaveState( Saig_MvMan_t * p ) { Saig_MvObj_t * pEntry; unsigned * pState, * pPlace; int i; pState = (unsigned *)Aig_MmFixedEntryFetch( p->pMemStates ); pState[0] = 0; Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i ) pState[i+1] = pEntry->Value; pPlace = Saig_MvSimTableFind( p, pState ); if ( *pPlace ) return *pPlace; *pPlace = Vec_PtrSize( p->vStates ); Vec_PtrPush( p->vStates, pState ); return -1; } /**Function************************************************************* Synopsis [Performs multi-valued simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_MvManPostProcess( Saig_MvMan_t * p, int iState ) { Saig_MvObj_t * pEntry; unsigned * pState; int i, k, j, nTotal = 0, iFlop; Vec_Int_t * vUniques = Vec_IntAlloc( 100 ); Vec_Int_t * vCounter = Vec_IntAlloc( 100 ); // count registers that never became undef Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i ) if ( p->pRegsUndef[i] == 0 ) nTotal++; printf( "The number of registers that never became undef = %d. (Total = %d.)\n", nTotal, p->nFlops ); Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i ) { if ( p->pRegsUndef[i] ) continue; Vec_IntForEachEntry( vUniques, iFlop, k ) { Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, j, 1 ) if ( pState[iFlop+1] != pState[i+1] ) break; if ( j == Vec_PtrSize(p->vStates) ) { Vec_IntAddToEntry( vCounter, k, 1 ); break; } } if ( k == Vec_IntSize(vUniques) ) { Vec_IntPush( vUniques, i ); Vec_IntPush( vCounter, 1 ); } } Vec_IntForEachEntry( vUniques, iFlop, i ) { printf( "FLOP %5d : (%3d) ", iFlop, Vec_IntEntry(vCounter,i) ); /* for ( k = 0; k < p->nRegsValues[iFlop]; k++ ) if ( p->pRegsValues[iFlop][k] == SAIG_UNDEF_VALUE ) printf( "* " ); else printf( "%d ", p->pRegsValues[iFlop][k] ); printf( "\n" ); */ Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, k, 1 ) { if ( k == iState+1 ) printf( " # " ); if ( pState[iFlop+1] == SAIG_UNDEF_VALUE ) printf( "*" ); else printf( "%d", pState[iFlop+1] ); } printf( "\n" ); // if ( ++Counter == 10 ) // break; } Vec_IntFree( vUniques ); Vec_IntFree( vCounter ); } /**Function************************************************************* Synopsis [Performs multi-valued simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_MvManFindXFlops( Saig_MvMan_t * p ) { Vec_Int_t * vXFlops; unsigned * pState; int i, k; vXFlops = Vec_IntStart( p->nFlops ); Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, i, 1 ) { for ( k = 0; k < p->nFlops; k++ ) if ( Saig_MvIsUndef(pState[k+1]) ) Vec_IntWriteEntry( vXFlops, k, 1 ); } return vXFlops; } /**Function************************************************************* Synopsis [Checks if the flop is an oscilator.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_MvManCheckOscilator( Saig_MvMan_t * p, int iFlop ) { Vec_Int_t * vValues; unsigned * pState; int k, Per, Entry; // collect values of this flop vValues = Vec_IntAlloc( 100 ); Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, k, 1 ) { Vec_IntPush( vValues, pState[iFlop+1] ); //printf( "%d ", pState[iFlop+1] ); } //printf( "\n" ); assert( Saig_MvIsConst0( Vec_IntEntry(vValues,0) ) ); // look for constants for ( Per = 0; Per < Vec_IntSize(vValues)/2; Per++ ) { // find the first non-const0 Vec_IntForEachEntryStart( vValues, Entry, Per, Per ) if ( !Saig_MvIsConst0(Entry) ) break; if ( Per == Vec_IntSize(vValues) ) break; // find the first const0 Vec_IntForEachEntryStart( vValues, Entry, Per, Per ) if ( Saig_MvIsConst0(Entry) ) break; if ( Per == Vec_IntSize(vValues) ) break; // try to determine period assert( Saig_MvIsConst0( Vec_IntEntry(vValues,Per) ) ); for ( k = Per; k < Vec_IntSize(vValues); k++ ) if ( Vec_IntEntry(vValues, k-Per) != Vec_IntEntry(vValues, k) ) break; if ( k < Vec_IntSize(vValues) ) continue; Vec_IntFree( vValues ); //printf( "Period = %d\n", Per ); return Per; } Vec_IntFree( vValues ); return 0; } /**Function************************************************************* Synopsis [Returns const0 and binary flops.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_MvManFindConstBinaryFlops( Saig_MvMan_t * p, Vec_Int_t ** pvBinary ) { unsigned * pState; Vec_Int_t * vBinary, * vConst0; int i, k, fConst0; // detect constant flops vConst0 = Vec_IntAlloc( p->nFlops ); vBinary = Vec_IntAlloc( p->nFlops ); for ( k = 0; k < p->nFlops; k++ ) { // check if this flop is constant 0 in all states fConst0 = 1; Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, i, 1 ) { if ( !Saig_MvIsConst0(pState[k+1]) ) fConst0 = 0; if ( Saig_MvIsUndef(pState[k+1]) ) break; } if ( i < Vec_PtrSize(p->vStates) ) continue; // the flop is binary-valued if ( fConst0 ) Vec_IntPush( vConst0, k ); else Vec_IntPush( vBinary, k ); } *pvBinary = vBinary; return vConst0; } /**Function************************************************************* Synopsis [Find oscilators.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_MvManFindOscilators( Saig_MvMan_t * p, Vec_Int_t ** pvConst0 ) { Vec_Int_t * vBinary, * vOscils; int Entry, i; // detect constant flops *pvConst0 = Saig_MvManFindConstBinaryFlops( p, &vBinary ); // check binary flops vOscils = Vec_IntAlloc( 100 ); Vec_IntForEachEntry( vBinary, Entry, i ) if ( Saig_MvManCheckOscilator( p, Entry ) ) Vec_IntPush( vOscils, Entry ); Vec_IntFree( vBinary ); return vOscils; } /**Function************************************************************* Synopsis [Find constants and oscilators.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_MvManCreateNextSkip( Saig_MvMan_t * p ) { Vec_Int_t * vConst0, * vOscils, * vXFlops; int i, Entry; vOscils = Saig_MvManFindOscilators( p, &vConst0 ); //printf( "Found %d constants and %d oscilators.\n", Vec_IntSize(vConst0), Vec_IntSize(vOscils) ); vXFlops = Vec_IntAlloc( p->nFlops ); Vec_IntFill( vXFlops, p->nFlops, 1 ); Vec_IntForEachEntry( vConst0, Entry, i ) Vec_IntWriteEntry( vXFlops, Entry, 0 ); Vec_IntForEachEntry( vOscils, Entry, i ) Vec_IntWriteEntry( vXFlops, Entry, 0 ); Vec_IntFree( vOscils ); Vec_IntFree( vConst0 ); return vXFlops; } /**Function************************************************************* Synopsis [Finds equivalent flops.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Saig_MvManDeriveMap( Saig_MvMan_t * p, int fVerbose ) { Vec_Int_t * vConst0, * vBinValued; Vec_Ptr_t * vMap = NULL; Aig_Obj_t * pObj; unsigned * pState; int i, k, j, FlopK, FlopJ; int Counter1 = 0, Counter2 = 0; // prepare CI map vMap = Vec_PtrAlloc( Aig_ManCiNum(p->pAig) ); Aig_ManForEachCi( p->pAig, pObj, i ) Vec_PtrPush( vMap, pObj ); // detect constant flops vConst0 = Saig_MvManFindConstBinaryFlops( p, &vBinValued ); // set constants Vec_IntForEachEntry( vConst0, FlopK, k ) { Vec_PtrWriteEntry( vMap, Saig_ManPiNum(p->pAig) + FlopK, Aig_ManConst0(p->pAig) ); Counter1++; } Vec_IntFree( vConst0 ); // detect equivalent (non-ternary flops) Vec_IntForEachEntry( vBinValued, FlopK, k ) if ( FlopK >= 0 ) Vec_IntForEachEntryStart( vBinValued, FlopJ, j, k+1 ) if ( FlopJ >= 0 ) { // check if they are equal Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, i, 1 ) if ( pState[FlopK+1] != pState[FlopJ+1] ) break; if ( i < Vec_PtrSize(p->vStates) ) continue; // set the equivalence Vec_PtrWriteEntry( vMap, Saig_ManPiNum(p->pAig) + FlopJ, Saig_ManLo(p->pAig, FlopK) ); Vec_IntWriteEntry( vBinValued, j, -1 ); Counter2++; } if ( fVerbose ) printf( "Detected %d const0 flops and %d pairs of equiv binary flops.\n", Counter1, Counter2 ); Vec_IntFree( vBinValued ); if ( Counter1 == 0 && Counter2 == 0 ) Vec_PtrFreeP( &vMap ); return vMap; } /**Function************************************************************* Synopsis [Performs multi-valued simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Saig_MvManSimulate( Aig_Man_t * pAig, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose ) { Vec_Ptr_t * vMap; Saig_MvMan_t * p; Saig_MvObj_t * pEntry; int f, i, iState; abctime clk = Abc_Clock(); assert( nFramesSymb >= 1 && nFramesSymb <= nFramesSatur ); // start manager p = Saig_MvManStart( pAig, nFramesSatur ); if ( fVerbose ) ABC_PRT( "Constructing the problem", Abc_Clock() - clk ); // initialize registers Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i ) pEntry->Value = Saig_MvConst0(); Saig_MvSaveState( p ); if ( fVeryVerbose ) Saig_MvPrintState( 0, p ); // simulate until convergence clk = Abc_Clock(); for ( f = 0; ; f++ ) { if ( f == nFramesSatur ) { if ( fVerbose ) 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( "Aggressively saturating simulation after %d frames\n", f ); Vec_IntFree( p->vXFlops ); p->vXFlops = Saig_MvManCreateNextSkip( p ); } // retire some flops if ( p->vXFlops ) { Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i ) if ( Vec_IntEntry( p->vXFlops, i ) ) pEntry->Value = SAIG_UNDEF_VALUE; } // simulate timeframe Saig_MvSimulateFrame( p, (int)(f < nFramesSymb), fVerbose ); // save and print state iState = Saig_MvSaveState( p ); if ( fVeryVerbose ) Saig_MvPrintState( f+1, p ); if ( iState >= 0 ) { if ( fVerbose ) printf( "Converged after %d frames with lasso in state %d. Cycle = %d.\n", f+1, iState-1, f+2-iState ); // printf( "Total number of PIs = %d. AND nodes = %d.\n", p->nPis, p->nObjs - p->nPis ); break; } } // printf( "Coverged after %d frames.\n", f ); if ( fVerbose ) ABC_PRT( "Multi-valued simulation", Abc_Clock() - clk ); // implement equivalences // Saig_MvManPostProcess( p, iState-1 ); vMap = Saig_MvManDeriveMap( p, fVerbose ); Saig_MvManStop( p ); // return Aig_ManDupSimple( pAig ); return vMap; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigSimSeq.c000066400000000000000000000404641477524141600166730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigSimSeq.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Fast sequential AIG simulator.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigSimSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "proof/ssw/ssw.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // combinational simulation manager typedef struct Raig_Man_t_ Raig_Man_t; struct Raig_Man_t_ { // parameters Aig_Man_t * pAig; // the AIG to be used for simulation int nWords; // the number of words to simulate // AIG representation int nPis; // the number of primary inputs int nPos; // the number of primary outputs int nCis; // the number of combinational inputs int nCos; // the number of combinational outputs int nNodes; // the number of internal nodes int nObjs; // nCis + nNodes + nCos + 2 int * pFans0; // fanin0 for all objects int * pFans1; // fanin1 for all objects Vec_Int_t * vCis2Ids; // mapping of CIs into their PI ids Vec_Int_t * vLos; // register outputs Vec_Int_t * vLis; // register inputs // simulation info int * pRefs; // reference counter for each node unsigned * pSims; // simlulation information for each node // recycable memory unsigned * pMems; // allocated simulaton memory int nWordsAlloc; // the number of allocated entries int nMems; // the number of used entries int nMemsMax; // the max number of used entries int MemFree; // next free entry }; static inline int Raig_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } static inline int Raig_Lit2Var( int Lit ) { return Lit >> 1; } static inline int Raig_LitIsCompl( int Lit ) { return Lit & 1; } static inline int Raig_LitNot( int Lit ) { return Lit ^ 1; } static inline int Raig_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } static inline int Raig_LitRegular( int Lit ) { return Lit & ~01; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Find the PO corresponding to the PO driver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Raig_ManFindPo( Aig_Man_t * pAig, int iNode ) { Aig_Obj_t * pObj; int i; Saig_ManForEachPo( pAig, pObj, i ) if ( pObj->iData == iNode ) return i; return -1; } /**Function************************************************************* Synopsis [Creates fast simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Raig_ManCreate_rec( Raig_Man_t * p, Aig_Obj_t * pObj ) { int iFan0, iFan1; assert( !Aig_IsComplement(pObj) ); if ( pObj->iData ) return pObj->iData; assert( !Aig_ObjIsConst1(pObj) ); if ( Aig_ObjIsNode(pObj) ) { iFan0 = Raig_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); iFan0 = (iFan0 << 1) | Aig_ObjFaninC0(pObj); iFan1 = Raig_ManCreate_rec( p, Aig_ObjFanin1(pObj) ); iFan1 = (iFan1 << 1) | Aig_ObjFaninC1(pObj); } else if ( Aig_ObjIsCo(pObj) ) { iFan0 = Raig_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); iFan0 = (iFan0 << 1) | Aig_ObjFaninC0(pObj); iFan1 = 0; } else { iFan0 = iFan1 = 0; Vec_IntPush( p->vCis2Ids, Aig_ObjCioId(pObj) ); } p->pFans0[p->nObjs] = iFan0; p->pFans1[p->nObjs] = iFan1; p->pRefs[p->nObjs] = Aig_ObjRefs(pObj); return pObj->iData = p->nObjs++; } /**Function************************************************************* Synopsis [Creates fast simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Raig_Man_t * Raig_ManCreate( Aig_Man_t * pAig ) { Raig_Man_t * p; Aig_Obj_t * pObj; int i, nObjs; Aig_ManCleanData( pAig ); p = (Raig_Man_t *)ABC_ALLOC( Raig_Man_t, 1 ); memset( p, 0, sizeof(Raig_Man_t) ); p->pAig = pAig; p->nPis = Saig_ManPiNum(pAig); p->nPos = Saig_ManPoNum(pAig); p->nCis = Aig_ManCiNum(pAig); p->nCos = Aig_ManCoNum(pAig); p->nNodes = Aig_ManNodeNum(pAig); nObjs = p->nCis + p->nCos + p->nNodes + 2; p->pFans0 = ABC_ALLOC( int, nObjs ); p->pFans1 = ABC_ALLOC( int, nObjs ); p->pRefs = ABC_ALLOC( int, nObjs ); p->pSims = ABC_CALLOC( unsigned, nObjs ); p->vCis2Ids = Vec_IntAlloc( Aig_ManCiNum(pAig) ); // add objects (0=unused; 1=const1) p->nObjs = 2; pObj = Aig_ManConst1( pAig ); pObj->iData = 1; Aig_ManForEachCi( pAig, pObj, i ) if ( Aig_ObjRefs(pObj) == 0 ) Raig_ManCreate_rec( p, pObj ); Aig_ManForEachCo( pAig, pObj, i ) Raig_ManCreate_rec( p, pObj ); assert( Vec_IntSize(p->vCis2Ids) == Aig_ManCiNum(pAig) ); assert( p->nObjs == nObjs ); // collect flop outputs p->vLos = Vec_IntAlloc( Aig_ManRegNum(pAig) ); Saig_ManForEachLo( pAig, pObj, i ) Vec_IntPush( p->vLos, pObj->iData ); // collect flop inputs p->vLis = Vec_IntAlloc( Aig_ManRegNum(pAig) ); Saig_ManForEachLi( pAig, pObj, i ) { Vec_IntPush( p->vLis, pObj->iData ); assert( p->pRefs[ pObj->iData ] == 0 ); p->pRefs[ pObj->iData ]++; } return p; } /**Function************************************************************* Synopsis [Creates fast simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Raig_ManDelete( Raig_Man_t * p ) { Vec_IntFree( p->vCis2Ids ); Vec_IntFree( p->vLos ); Vec_IntFree( p->vLis ); ABC_FREE( p->pFans0 ); ABC_FREE( p->pFans1 ); ABC_FREE( p->pRefs ); ABC_FREE( p->pSims ); ABC_FREE( p->pMems ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [References simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Raig_ManSimRef( Raig_Man_t * p, int i ) { unsigned * pSim; assert( i > 1 ); assert( p->pSims[i] == 0 ); if ( p->MemFree == 0 ) { unsigned * pPlace, Ent; if ( p->nWordsAlloc == 0 ) { assert( p->pMems == NULL ); p->nWordsAlloc = (1<<17); // -> 1Mb p->nMems = 1; } p->nWordsAlloc *= 2; p->pMems = ABC_REALLOC( unsigned, p->pMems, p->nWordsAlloc ); memset( p->pMems, 0xff, sizeof(unsigned) * (p->nWords + 1) ); pPlace = (unsigned *)&p->MemFree; for ( Ent = p->nMems * (p->nWords + 1); Ent + p->nWords + 1 < (unsigned)p->nWordsAlloc; Ent += p->nWords + 1 ) { *pPlace = Ent; pPlace = p->pMems + Ent; } *pPlace = 0; } p->pSims[i] = p->MemFree; pSim = p->pMems + p->MemFree; p->MemFree = pSim[0]; pSim[0] = p->pRefs[i]; p->nMems++; if ( p->nMemsMax < p->nMems ) p->nMemsMax = p->nMems; return pSim; } /**Function************************************************************* Synopsis [Dereference simulaton info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Raig_ManSimDeref( Raig_Man_t * p, int i ) { unsigned * pSim; assert( i ); if ( i == 1 ) // const 1 return p->pMems; assert( p->pSims[i] > 0 ); pSim = p->pMems + p->pSims[i]; if ( --pSim[0] == 0 ) { pSim[0] = p->MemFree; p->MemFree = p->pSims[i]; p->pSims[i] = 0; p->nMems--; } return pSim; } /**Function************************************************************* Synopsis [Simulates one round.] Description [Returns the number of PO entry if failed; 0 otherwise.] SideEffects [] SeeAlso [] ***********************************************************************/ int Raig_ManSimulateRound( Raig_Man_t * p, int fMiter, int fFirst, int * piPat ) { unsigned * pRes0, * pRes1, * pRes; int i, w, nCis, nCos, iFan0, iFan1, iPioNum; // nove the values to the register outputs Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) { if ( iPioNum < p->nPis ) continue; pRes = Raig_ManSimRef( p, Vec_IntEntry(p->vLos, iPioNum-p->nPis) ); if ( fFirst ) memset( pRes + 1, 0, sizeof(unsigned) * p->nWords ); else { pRes0 = Raig_ManSimDeref( p, Vec_IntEntry(p->vLis, iPioNum-p->nPis) ); for ( w = 1; w <= p->nWords; w++ ) pRes[w] = pRes0[w]; } // handle unused PIs if ( pRes[0] == 0 ) { pRes[0] = 1; Raig_ManSimDeref( p, Vec_IntEntry(p->vLos, iPioNum-p->nPis) ); } } // simulate the logic nCis = nCos = 0; for ( i = 2; i < p->nObjs; i++ ) { if ( p->pFans0[i] == 0 ) // ci always has zero first fanin { iPioNum = Vec_IntEntry( p->vCis2Ids, nCis ); if ( iPioNum < p->nPis ) { pRes = Raig_ManSimRef( p, i ); for ( w = 1; w <= p->nWords; w++ ) pRes[w] = Aig_ManRandom( 0 ); // handle unused PIs if ( pRes[0] == 0 ) { pRes[0] = 1; Raig_ManSimDeref( p, i ); } } else assert( Vec_IntEntry(p->vLos, iPioNum-p->nPis) == i ); nCis++; continue; } if ( p->pFans1[i] == 0 ) // co always has non-zero 1st fanin and zero 2nd fanin { pRes0 = Raig_ManSimDeref( p, Raig_Lit2Var(p->pFans0[i]) ); if ( nCos < p->nPos && fMiter ) { unsigned Const = Raig_LitIsCompl(p->pFans0[i])? ~0 : 0; for ( w = 1; w <= p->nWords; w++ ) if ( pRes0[w] != Const ) { *piPat = 32*(w-1) + Aig_WordFindFirstBit( pRes0[w] ^ Const ); return i; } } else { pRes = Raig_ManSimRef( p, i ); assert( pRes[0] == 1 ); if ( Raig_LitIsCompl(p->pFans0[i]) ) for ( w = 1; w <= p->nWords; w++ ) pRes[w] = ~pRes0[w]; else for ( w = 1; w <= p->nWords; w++ ) pRes[w] = pRes0[w]; } nCos++; continue; } pRes = Raig_ManSimRef( p, i ); assert( pRes[0] > 0 ); iFan0 = p->pFans0[i]; iFan1 = p->pFans1[i]; pRes0 = Raig_ManSimDeref( p, Raig_Lit2Var(p->pFans0[i]) ); pRes1 = Raig_ManSimDeref( p, Raig_Lit2Var(p->pFans1[i]) ); if ( Raig_LitIsCompl(iFan0) && Raig_LitIsCompl(iFan1) ) for ( w = 1; w <= p->nWords; w++ ) pRes[w] = ~(pRes0[w] | pRes1[w]); else if ( Raig_LitIsCompl(iFan0) && !Raig_LitIsCompl(iFan1) ) for ( w = 1; w <= p->nWords; w++ ) pRes[w] = ~pRes0[w] & pRes1[w]; else if ( !Raig_LitIsCompl(iFan0) && Raig_LitIsCompl(iFan1) ) for ( w = 1; w <= p->nWords; w++ ) pRes[w] = pRes0[w] & ~pRes1[w]; else if ( !Raig_LitIsCompl(iFan0) && !Raig_LitIsCompl(iFan1) ) for ( w = 1; w <= p->nWords; w++ ) pRes[w] = pRes0[w] & pRes1[w]; } assert( nCis == p->nCis ); assert( nCos == p->nCos ); assert( p->nMems == 1 + Vec_IntSize(p->vLis) ); return 0; } /**Function************************************************************* Synopsis [Returns the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Cex_t * Raig_ManGenerateCounter( Aig_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat, Vec_Int_t * vCis2Ids ) { Abc_Cex_t * p; unsigned * pData; int f, i, w, iPioId, Counter; p = Abc_CexAlloc( Aig_ManRegNum(pAig), Saig_ManPiNum(pAig), iFrame+1 ); p->iFrame = iFrame; p->iPo = iOut; // fill in the binary data Aig_ManRandom( 1 ); Counter = p->nRegs; pData = ABC_ALLOC( unsigned, nWords ); for ( f = 0; f <= iFrame; f++, Counter += p->nPis ) for ( i = 0; i < Aig_ManCiNum(pAig); i++ ) { iPioId = Vec_IntEntry( vCis2Ids, i ); if ( iPioId >= p->nPis ) continue; for ( w = 0; w < nWords; w++ ) pData[w] = Aig_ManRandom( 0 ); if ( Abc_InfoHasBit( pData, iPat ) ) Abc_InfoSetBit( p->pData, Counter + iPioId ); } ABC_FREE( pData ); return p; } /**Function************************************************************* Synopsis [Returns 1 if the bug is detected, 0 otherwise.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Raig_ManSimulate( Aig_Man_t * pAig, int nWords, int nIters, int TimeLimit, int fMiter, int fVerbose ) { Raig_Man_t * p; Sec_MtrStatus_t Status; int i, iPat, RetValue = 0; abctime clk, clkTotal = Abc_Clock(); assert( Aig_ManRegNum(pAig) > 0 ); Status = Sec_MiterStatus( pAig ); if ( Status.nSat > 0 ) { printf( "Miter is trivially satisfiable (output %d).\n", Status.iOut ); return 1; } if ( Status.nUndec == 0 ) { printf( "Miter is trivially unsatisfiable.\n" ); return 0; } Aig_ManRandom( 1 ); p = Raig_ManCreate( pAig ); p->nWords = nWords; // iterate through objects for ( i = 0; i < nIters; i++ ) { clk = Abc_Clock(); RetValue = Raig_ManSimulateRound( p, fMiter, i==0, &iPat ); if ( fVerbose ) { printf( "Frame %4d out of %4d and timeout %3d sec. ", i+1, nIters, TimeLimit ); printf("Time = %7.2f sec\r", (1.0*Abc_Clock()-clkTotal)/CLOCKS_PER_SEC); } if ( RetValue > 0 ) { int iOut = Raig_ManFindPo(p->pAig, RetValue); assert( pAig->pSeqModel == NULL ); pAig->pSeqModel = Raig_ManGenerateCounter( pAig, i, iOut, nWords, iPat, p->vCis2Ids ); if ( fVerbose ) printf( "Miter is satisfiable after simulation (output %d).\n", iOut ); break; } if ( (Abc_Clock() - clk)/CLOCKS_PER_SEC >= TimeLimit ) { printf( "No bug detected after %d frames with time limit %d seconds.\n", i+1, TimeLimit ); break; } } if ( fVerbose ) { printf( "Maxcut = %8d. AigMem = %7.2f MB. SimMem = %7.2f MB. ", p->nMemsMax, 1.0*(p->nObjs * 16)/(1<<20), 1.0*(p->nMemsMax * 4 * (nWords+1))/(1<<20) ); ABC_PRT( "Total time", Abc_Clock() - clkTotal ); } Raig_ManDelete( p ); return RetValue > 0; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigStrSim.c000066400000000000000000000723721477524141600167160ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigStrSim.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Structural matching using simulation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigStrSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "proof/ssw/ssw.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define SAIG_WORDS 16 static inline Aig_Obj_t * Saig_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; } static inline void Saig_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes hash value of the node using its simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Saig_StrSimHash( Aig_Obj_t * pObj ) { static int s_SPrimes[128] = { 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 }; unsigned * pSims; unsigned uHash = 0; int i; assert( SAIG_WORDS <= 128 ); pSims = (unsigned *)pObj->pData; for ( i = 0; i < SAIG_WORDS; i++ ) uHash ^= pSims[i] * s_SPrimes[i & 0x7F]; return uHash; } /**Function************************************************************* Synopsis [Computes hash value of the node using its simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_StrSimIsEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) { unsigned * pSims0 = (unsigned *)pObj0->pData; unsigned * pSims1 = (unsigned *)pObj1->pData; int i; for ( i = 0; i < SAIG_WORDS; i++ ) if ( pSims0[i] != pSims1[i] ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if simulation info is zero.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_StrSimIsZero( Aig_Obj_t * pObj ) { unsigned * pSims = (unsigned *)pObj->pData; int i; for ( i = 0; i < SAIG_WORDS; i++ ) if ( pSims[i] != 0 ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if simulation info is one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_StrSimIsOne( Aig_Obj_t * pObj ) { unsigned * pSims = (unsigned *)pObj->pData; int i; for ( i = 0; i < SAIG_WORDS; i++ ) if ( pSims[i] != ~0 ) return 0; return 1; } /**Function************************************************************* Synopsis [Assigns random simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_StrSimAssignRandom( Aig_Obj_t * pObj ) { unsigned * pSims = (unsigned *)pObj->pData; int i; for ( i = 0; i < SAIG_WORDS; i++ ) pSims[i] = Aig_ManRandom(0); } /**Function************************************************************* Synopsis [Assigns constant 0 simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_StrSimAssignOne( Aig_Obj_t * pObj ) { unsigned * pSims = (unsigned *)pObj->pData; int i; for ( i = 0; i < SAIG_WORDS; i++ ) pSims[i] = ~0; } /**Function************************************************************* Synopsis [Assigns constant 0 simulation info.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_StrSimAssignZeroInit( Aig_Obj_t * pObj ) { unsigned * pSims = (unsigned *)pObj->pData; pSims[0] = 0; } /**Function************************************************************* Synopsis [Simulated one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_StrSimulateNode( Aig_Obj_t * pObj, int i ) { unsigned * pSims = (unsigned *)pObj->pData; unsigned * pSims0 = (unsigned *)Aig_ObjFanin0(pObj)->pData; unsigned * pSims1 = (unsigned *)Aig_ObjFanin1(pObj)->pData; if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) pSims[i] = ~(pSims0[i] | pSims1[i]); else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) pSims[i] = (~pSims0[i] & pSims1[i]); else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) pSims[i] = (pSims0[i] & ~pSims1[i]); else // if ( !Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) pSims[i] = (pSims0[i] & pSims1[i]); } /**Function************************************************************* Synopsis [Saves output of one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_StrSimSaveOutput( Aig_Obj_t * pObj, int i ) { unsigned * pSims = (unsigned *)pObj->pData; unsigned * pSims0 = (unsigned *)Aig_ObjFanin0(pObj)->pData; if ( Aig_ObjFaninC0(pObj) ) pSims[i] = ~pSims0[i]; else pSims[i] = pSims0[i]; } /**Function************************************************************* Synopsis [Transfers simulation output to another node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_StrSimTransfer( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) { unsigned * pSims0 = (unsigned *)pObj0->pData; unsigned * pSims1 = (unsigned *)pObj1->pData; int i; for ( i = 0; i < SAIG_WORDS; i++ ) pSims1[i] = pSims0[i]; } /**Function************************************************************* Synopsis [Transfers simulation output to another node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_StrSimTransferNext( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int i ) { unsigned * pSims0 = (unsigned *)pObj0->pData; unsigned * pSims1 = (unsigned *)pObj1->pData; assert( i < SAIG_WORDS - 1 ); pSims1[i+1] = pSims0[i]; } /**Function************************************************************* Synopsis [Perform one round of simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_StrSimulateRound( Aig_Man_t * p0, Aig_Man_t * p1 ) { Aig_Obj_t * pObj0, * pObj1; int f, i; // simulate the nodes Aig_ManForEachObj( p0, pObj0, i ) { if ( !Aig_ObjIsCi(pObj0) && !Aig_ObjIsNode(pObj0) ) continue; pObj1 = Aig_ObjRepr(p0, pObj0); if ( pObj1 == NULL ) continue; assert( Aig_ObjRepr(p1, pObj1) == pObj0 ); Saig_StrSimAssignRandom( pObj0 ); Saig_StrSimTransfer( pObj0, pObj1 ); } // simulate the timeframes for ( f = 0; f < SAIG_WORDS; f++ ) { // simulate the first AIG Aig_ManForEachNode( p0, pObj0, i ) if ( Aig_ObjRepr(p0, pObj0) == NULL ) Saig_StrSimulateNode( pObj0, f ); Saig_ManForEachLi( p0, pObj0, i ) Saig_StrSimSaveOutput( pObj0, f ); if ( f < SAIG_WORDS - 1 ) Saig_ManForEachLiLo( p0, pObj0, pObj1, i ) Saig_StrSimTransferNext( pObj0, pObj1, f ); // simulate the second AIG Aig_ManForEachNode( p1, pObj1, i ) if ( Aig_ObjRepr(p1, pObj1) == NULL ) Saig_StrSimulateNode( pObj1, f ); Saig_ManForEachLi( p1, pObj1, i ) Saig_StrSimSaveOutput( pObj1, f ); if ( f < SAIG_WORDS - 1 ) Saig_ManForEachLiLo( p1, pObj1, pObj0, i ) Saig_StrSimTransferNext( pObj1, pObj0, f ); } } /**Function************************************************************* Synopsis [Checks if the entry exists in the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Saig_StrSimTableLookup( Aig_Obj_t ** ppTable, Aig_Obj_t ** ppNexts, int nTableSize, Aig_Obj_t * pObj ) { Aig_Obj_t * pEntry; int iEntry; // find the hash entry iEntry = Saig_StrSimHash( pObj ) % nTableSize; // check if there are nodes with this signatures for ( pEntry = ppTable[iEntry]; pEntry; pEntry = Saig_ObjNext(ppNexts,pEntry) ) if ( Saig_StrSimIsEqual( pEntry, pObj ) ) return pEntry; return NULL; } /**Function************************************************************* Synopsis [Inserts the entry into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_StrSimTableInsert( Aig_Obj_t ** ppTable, Aig_Obj_t ** ppNexts, int nTableSize, Aig_Obj_t * pObj ) { // find the hash entry int iEntry = Saig_StrSimHash( pObj ) % nTableSize; // check if there are nodes with this signatures if ( ppTable[iEntry] == NULL ) ppTable[iEntry] = pObj; else { Saig_ObjSetNext( ppNexts, pObj, Saig_ObjNext(ppNexts, ppTable[iEntry]) ); Saig_ObjSetNext( ppNexts, ppTable[iEntry], pObj ); } } /**Function************************************************************* Synopsis [Perform one round of matching.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_StrSimDetectUnique( Aig_Man_t * p0, Aig_Man_t * p1 ) { Aig_Obj_t ** ppTable, ** ppNexts, ** ppCands; Aig_Obj_t * pObj, * pEntry; int i, nTableSize, Counter; // allocate the hash table hashing simulation info into nodes nTableSize = Abc_PrimeCudd( Aig_ManObjNum(p0)/2 ); ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize ); ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p0) ); ppCands = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p0) ); // hash nodes of the first AIG Aig_ManForEachObj( p0, pObj, i ) { if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) continue; if ( Aig_ObjRepr(p0, pObj) ) continue; if ( Saig_StrSimIsZero(pObj) || Saig_StrSimIsOne(pObj) ) continue; // check if the entry exists pEntry = Saig_StrSimTableLookup( ppTable, ppNexts, nTableSize, pObj ); if ( pEntry == NULL ) // insert Saig_StrSimTableInsert( ppTable, ppNexts, nTableSize, pObj ); else // mark the entry as not unique pEntry->fMarkA = 1; } // hash nodes from the second AIG Aig_ManForEachObj( p1, pObj, i ) { if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) continue; if ( Aig_ObjRepr(p1, pObj) ) continue; if ( Saig_StrSimIsZero(pObj) || Saig_StrSimIsOne(pObj) ) continue; // check if the entry exists pEntry = Saig_StrSimTableLookup( ppTable, ppNexts, nTableSize, pObj ); if ( pEntry == NULL ) // skip continue; // if there is no candidate, label it if ( Saig_ObjNext( ppCands, pEntry ) == NULL ) Saig_ObjSetNext( ppCands, pEntry, pObj ); else // mark the entry as not unique pEntry->fMarkA = 1; } // create representatives for the unique entries Counter = 0; for ( i = 0; i < nTableSize; i++ ) for ( pEntry = ppTable[i]; pEntry; pEntry = Saig_ObjNext(ppNexts,pEntry) ) if ( !pEntry->fMarkA && (pObj = Saig_ObjNext( ppCands, pEntry )) ) { // assert( Aig_ObjIsNode(pEntry) == Aig_ObjIsNode(pObj) ); if ( Aig_ObjType(pEntry) != Aig_ObjType(pObj) ) continue; Aig_ObjSetRepr( p0, pEntry, pObj ); Aig_ObjSetRepr( p1, pObj, pEntry ); Counter++; } // cleanup Aig_ManCleanMarkA( p0 ); ABC_FREE( ppTable ); ABC_FREE( ppNexts ); ABC_FREE( ppCands ); return Counter; } /**Function************************************************************* Synopsis [Counts the number of matched flops.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_StrSimCountMatchedFlops( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, Counter = 0; Saig_ManForEachLo( p, pObj, i ) if ( Aig_ObjRepr(p, pObj) ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Counts the number of matched nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_StrSimCountMatchedNodes( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, Counter = 0; Aig_ManForEachNode( p, pObj, i ) if ( Aig_ObjRepr(p, pObj) ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Performs structural matching of two AIGs using simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_StrSimPrepareAig( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i; Aig_ManReprStart( p, Aig_ManObjNumMax(p) ); // allocate simulation info p->pData2 = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), SAIG_WORDS ); Aig_ManForEachObj( p, pObj, i ) pObj->pData = Vec_PtrEntry( (Vec_Ptr_t *)p->pData2, i ); // set simulation info for constant1 and register outputs Saig_StrSimAssignOne( Aig_ManConst1(p) ); Saig_ManForEachLo( p, pObj, i ) Saig_StrSimAssignZeroInit( pObj ); } /**Function************************************************************* Synopsis [Performs structural matching of two AIGs using simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_StrSimSetInitMatching( Aig_Man_t * p0, Aig_Man_t * p1 ) { Aig_Obj_t * pObj0, * pObj1; int i; pObj0 = Aig_ManConst1( p0 ); pObj1 = Aig_ManConst1( p1 ); Aig_ObjSetRepr( p0, pObj0, pObj1 ); Aig_ObjSetRepr( p1, pObj1, pObj0 ); Saig_ManForEachPi( p0, pObj0, i ) { pObj1 = Aig_ManCi( p1, i ); Aig_ObjSetRepr( p0, pObj0, pObj1 ); Aig_ObjSetRepr( p1, pObj1, pObj0 ); } } /**Function************************************************************* Synopsis [Performs structural matching of two AIGs using simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_StrSimSetFinalMatching( Aig_Man_t * p0, Aig_Man_t * p1 ) { Aig_Obj_t * pObj0, * pObj1; Aig_Obj_t * pFanin00, * pFanin01; Aig_Obj_t * pFanin10, * pFanin11; int i, CountAll = 0, CountNot = 0; Aig_ManIncrementTravId( p0 ); Aig_ManForEachObj( p0, pObj0, i ) { pObj1 = Aig_ObjRepr( p0, pObj0 ); if ( pObj1 == NULL ) continue; CountAll++; assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) ); if ( Aig_ObjIsNode(pObj0) ) { assert( Aig_ObjIsNode(pObj1) ); pFanin00 = Aig_ObjFanin0(pObj0); pFanin01 = Aig_ObjFanin1(pObj0); pFanin10 = Aig_ObjFanin0(pObj1); pFanin11 = Aig_ObjFanin1(pObj1); if ( Aig_ObjRepr(p0, pFanin00) != pFanin10 || Aig_ObjRepr(p0, pFanin01) != pFanin11 ) { Aig_ObjSetTravIdCurrent(p0, pObj0); CountNot++; } } else if ( Saig_ObjIsLo(p0, pObj0) ) { assert( Saig_ObjIsLo(p1, pObj1) ); pFanin00 = Aig_ObjFanin0( Saig_ObjLoToLi(p0, pObj0) ); pFanin10 = Aig_ObjFanin0( Saig_ObjLoToLi(p1, pObj1) ); if ( Aig_ObjRepr(p0, pFanin00) != pFanin10 ) { Aig_ObjSetTravIdCurrent(p0, pObj0); CountNot++; } } } // remove irrelevant matches Aig_ManForEachObj( p0, pObj0, i ) { pObj1 = Aig_ObjRepr( p0, pObj0 ); if ( pObj1 == NULL ) continue; assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) ); if ( Aig_ObjIsTravIdCurrent( p0, pObj0 ) ) { Aig_ObjSetRepr( p0, pObj0, NULL ); Aig_ObjSetRepr( p1, pObj1, NULL ); } } Abc_Print( 1, "Total matches = %6d. Wrong matches = %6d. Ratio = %5.2f %%\n", CountAll, CountNot, 100.0*CountNot/CountAll ); } /**Function************************************************************* Synopsis [Returns the number of dangling nodes removed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_StrSimSetContiguousMatching_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pFanout; int i, iFanout = -1; if ( Aig_ObjIsTravIdCurrent(p, pObj) ) return; Aig_ObjSetTravIdCurrent(p, pObj); if ( Saig_ObjIsPo( p, pObj ) ) return; if ( Saig_ObjIsLi( p, pObj ) ) { Saig_StrSimSetContiguousMatching_rec( p, Saig_ObjLiToLo(p, pObj) ); return; } assert( Aig_ObjIsCi(pObj) || Aig_ObjIsNode(pObj) ); if ( Aig_ObjRepr(p, pObj) == NULL ) return; // go through the fanouts Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) Saig_StrSimSetContiguousMatching_rec( p, pFanout ); // go through the fanins if ( !Aig_ObjIsCi( pObj ) ) { Saig_StrSimSetContiguousMatching_rec( p, Aig_ObjFanin0(pObj) ); Saig_StrSimSetContiguousMatching_rec( p, Aig_ObjFanin1(pObj) ); } } /**Function************************************************************* Synopsis [Performs structural matching of two AIGs using simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_StrSimSetContiguousMatching( Aig_Man_t * p0, Aig_Man_t * p1 ) { Aig_Obj_t * pObj0, * pObj1; int i, CountAll = 0, CountNot = 0; // mark nodes reachable through the PIs Aig_ManIncrementTravId( p0 ); Aig_ObjSetTravIdCurrent( p0, Aig_ManConst1(p0) ); Saig_ManForEachPi( p0, pObj0, i ) Saig_StrSimSetContiguousMatching_rec( p0, pObj0 ); // remove irrelevant matches Aig_ManForEachObj( p0, pObj0, i ) { pObj1 = Aig_ObjRepr( p0, pObj0 ); if ( pObj1 == NULL ) continue; CountAll++; assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) ); if ( !Aig_ObjIsTravIdCurrent( p0, pObj0 ) ) { Aig_ObjSetRepr( p0, pObj0, NULL ); Aig_ObjSetRepr( p1, pObj1, NULL ); CountNot++; } } Abc_Print( 1, "Total matches = %6d. Wrong matches = %6d. Ratio = %5.2f %%\n", CountAll, CountNot, 100.0*CountNot/CountAll ); } /**Function************************************************************* Synopsis [Establishes relationship between nodes using pairing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_StrSimMatchingExtendOne( Aig_Man_t * p, Vec_Ptr_t * vNodes ) { Aig_Obj_t * pNext, * pObj; int i, k, iFan = -1; Vec_PtrClear( vNodes ); Aig_ManIncrementTravId( p ); Aig_ManForEachObj( p, pObj, i ) { if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) continue; if ( Aig_ObjRepr( p, pObj ) != NULL ) continue; if ( Saig_ObjIsLo(p, pObj) ) { pNext = Saig_ObjLoToLi(p, pObj); pNext = Aig_ObjFanin0(pNext); if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) && !Aig_ObjIsConst1(pNext) ) { Aig_ObjSetTravIdCurrent(p, pNext); Vec_PtrPush( vNodes, pNext ); } } if ( Aig_ObjIsNode(pObj) ) { pNext = Aig_ObjFanin0(pObj); if ( Aig_ObjRepr( p, pNext )&& !Aig_ObjIsTravIdCurrent(p, pNext) ) { Aig_ObjSetTravIdCurrent(p, pNext); Vec_PtrPush( vNodes, pNext ); } pNext = Aig_ObjFanin1(pObj); if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) ) { Aig_ObjSetTravIdCurrent(p, pNext); Vec_PtrPush( vNodes, pNext ); } } Aig_ObjForEachFanout( p, pObj, pNext, iFan, k ) { if ( Saig_ObjIsPo(p, pNext) ) continue; if ( Saig_ObjIsLi(p, pNext) ) pNext = Saig_ObjLiToLo(p, pNext); if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) ) { Aig_ObjSetTravIdCurrent(p, pNext); Vec_PtrPush( vNodes, pNext ); } } } } /**Function************************************************************* Synopsis [Establishes relationship between nodes using pairing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ssw_StrSimMatchingCountUnmached( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, Counter = 0; Aig_ManForEachObj( p, pObj, i ) { if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) continue; if ( Aig_ObjRepr( p, pObj ) != NULL ) continue; Counter++; } return Counter; } /**Function************************************************************* Synopsis [Establishes relationship between nodes using pairing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ssw_StrSimMatchingExtend( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose ) { Vec_Ptr_t * vNodes0, * vNodes1; Aig_Obj_t * pNext0, * pNext1; int d, k; vNodes0 = Vec_PtrAlloc( 1000 ); vNodes1 = Vec_PtrAlloc( 1000 ); if ( fVerbose ) { int nUnmached = Ssw_StrSimMatchingCountUnmached(p0); Abc_Print( 1, "Extending islands by %d steps:\n", nDist ); Abc_Print( 1, "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n", 0, Aig_ManCiNum(p0) + Aig_ManNodeNum(p0), nUnmached, 100.0 * nUnmached/(Aig_ManCiNum(p0) + Aig_ManNodeNum(p0)) ); } for ( d = 0; d < nDist; d++ ) { Ssw_StrSimMatchingExtendOne( p0, vNodes0 ); Ssw_StrSimMatchingExtendOne( p1, vNodes1 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pNext0, k ) { pNext1 = Aig_ObjRepr( p0, pNext0 ); if ( pNext1 == NULL ) continue; assert( pNext0 == Aig_ObjRepr( p1, pNext1 ) ); if ( Saig_ObjIsPi(p1, pNext1) ) continue; Aig_ObjSetRepr( p0, pNext0, NULL ); Aig_ObjSetRepr( p1, pNext1, NULL ); } Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pNext1, k ) { pNext0 = Aig_ObjRepr( p1, pNext1 ); if ( pNext0 == NULL ) continue; assert( pNext1 == Aig_ObjRepr( p0, pNext0 ) ); if ( Saig_ObjIsPi(p0, pNext0) ) continue; Aig_ObjSetRepr( p0, pNext0, NULL ); Aig_ObjSetRepr( p1, pNext1, NULL ); } if ( fVerbose ) { int nUnmached = Ssw_StrSimMatchingCountUnmached(p0); Abc_Print( 1, "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n", d+1, Aig_ManCiNum(p0) + Aig_ManNodeNum(p0), nUnmached, 100.0 * nUnmached/(Aig_ManCiNum(p0) + Aig_ManNodeNum(p0)) ); } } Vec_PtrFree( vNodes0 ); Vec_PtrFree( vNodes1 ); } /**Function************************************************************* Synopsis [Performs structural matching of two AIGs using simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter ) { extern Aig_Man_t * Saig_ManWindowExtractMiter( Aig_Man_t * p0, Aig_Man_t * p1 ); Vec_Int_t * vPairs; Aig_Man_t * pPart0, * pPart1; Aig_Obj_t * pObj0, * pObj1; int i, nMatches; abctime clk, clkTotal = Abc_Clock(); Aig_ManRandom( 1 ); // consider the case when a miter is given if ( p1 == NULL ) { if ( fVerbose ) { Aig_ManPrintStats( p0 ); } // demiter the miter if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) ) { Abc_Print( 1, "Demitering has failed.\n" ); return NULL; } } else { pPart0 = Aig_ManDupSimple( p0 ); pPart1 = Aig_ManDupSimple( p1 ); } if ( fVerbose ) { Aig_ManPrintStats( pPart0 ); Aig_ManPrintStats( pPart1 ); } // start simulation Saig_StrSimPrepareAig( pPart0 ); Saig_StrSimPrepareAig( pPart1 ); Saig_StrSimSetInitMatching( pPart0, pPart1 ); if ( fVerbose ) { Abc_Print( 1, "Allocated %6.2f MB to simulate the first AIG.\n", 1.0 * Aig_ManObjNumMax(pPart0) * SAIG_WORDS * sizeof(unsigned) / (1<<20) ); Abc_Print( 1, "Allocated %6.2f MB to simulate the second AIG.\n", 1.0 * Aig_ManObjNumMax(pPart1) * SAIG_WORDS * sizeof(unsigned) / (1<<20) ); } // iterate matching nMatches = 1; for ( i = 0; nMatches > 0; i++ ) { clk = Abc_Clock(); Saig_StrSimulateRound( pPart0, pPart1 ); nMatches = Saig_StrSimDetectUnique( pPart0, pPart1 ); if ( fVerbose ) { int nFlops = Saig_StrSimCountMatchedFlops(pPart0); int nNodes = Saig_StrSimCountMatchedNodes(pPart0); Abc_Print( 1, "%3d : Match =%6d. FF =%6d. (%6.2f %%) Node =%6d. (%6.2f %%) ", i, nMatches, nFlops, 100.0*nFlops/Aig_ManRegNum(pPart0), nNodes, 100.0*nNodes/Aig_ManNodeNum(pPart0) ); ABC_PRT( "Time", Abc_Clock() - clk ); } if ( i == 20 ) break; } // cleanup Vec_PtrFree( (Vec_Ptr_t *)pPart0->pData2 ); pPart0->pData2 = NULL; Vec_PtrFree( (Vec_Ptr_t *)pPart1->pData2 ); pPart1->pData2 = NULL; // extend the islands Aig_ManFanoutStart( pPart0 ); Aig_ManFanoutStart( pPart1 ); if ( nDist ) Ssw_StrSimMatchingExtend( pPart0, pPart1, nDist, fVerbose ); Saig_StrSimSetFinalMatching( pPart0, pPart1 ); // Saig_StrSimSetContiguousMatching( pPart0, pPart1 ); // copy the results into array vPairs = Vec_IntAlloc( 2*Aig_ManObjNumMax(pPart0) ); Aig_ManForEachObj( pPart0, pObj0, i ) { pObj1 = Aig_ObjRepr(pPart0, pObj0); if ( pObj1 == NULL ) continue; assert( pObj0 == Aig_ObjRepr(pPart1, pObj1) ); Vec_IntPush( vPairs, pObj0->Id ); Vec_IntPush( vPairs, pObj1->Id ); } // this procedure adds matching of PO and LI if ( ppMiter ) *ppMiter = Saig_ManWindowExtractMiter( pPart0, pPart1 ); Aig_ManFanoutStop( pPart0 ); Aig_ManFanoutStop( pPart1 ); Aig_ManStop( pPart0 ); Aig_ManStop( pPart1 ); ABC_PRT( "Total runtime", Abc_Clock() - clkTotal ); return vPairs; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigSwitch.c000066400000000000000000000406301477524141600167260ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigSwitch.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Returns switching propabilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "base/main/main.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Saig_SimObj_t_ Saig_SimObj_t; struct Saig_SimObj_t_ { int iFan0; int iFan1; unsigned Type : 8; unsigned Number : 24; unsigned pData[1]; }; static inline int Saig_SimObjFaninC0( Saig_SimObj_t * pObj ) { return pObj->iFan0 & 1; } static inline int Saig_SimObjFaninC1( Saig_SimObj_t * pObj ) { return pObj->iFan1 & 1; } static inline int Saig_SimObjFanin0( Saig_SimObj_t * pObj ) { return pObj->iFan0 >> 1; } static inline int Saig_SimObjFanin1( Saig_SimObj_t * pObj ) { return pObj->iFan1 >> 1; } //typedef struct Aig_CMan_t_ Aig_CMan_t; //static Aig_CMan_t * Aig_CManCreate( Aig_Man_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates fast simulation manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Saig_SimObj_t * Saig_ManCreateMan( Aig_Man_t * p ) { Saig_SimObj_t * pAig, * pEntry; Aig_Obj_t * pObj; int i; pAig = ABC_CALLOC( Saig_SimObj_t, Aig_ManObjNumMax(p)+1 ); // printf( "Allocating %7.2f MB.\n", 1.0 * sizeof(Saig_SimObj_t) * (Aig_ManObjNumMax(p)+1)/(1<<20) ); Aig_ManForEachObj( p, pObj, i ) { pEntry = pAig + i; pEntry->Type = pObj->Type; if ( Aig_ObjIsCi(pObj) || i == 0 ) { if ( Saig_ObjIsLo(p, pObj) ) { pEntry->iFan0 = (Saig_ObjLoToLi(p, pObj)->Id << 1); pEntry->iFan1 = -1; } continue; } pEntry->iFan0 = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj); if ( Aig_ObjIsCo(pObj) ) continue; assert( Aig_ObjIsNode(pObj) ); pEntry->iFan1 = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj); } pEntry = pAig + Aig_ManObjNumMax(p); pEntry->Type = AIG_OBJ_VOID; return pAig; } /**Function************************************************************* Synopsis [Simulated one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Saig_ManSimulateNode2( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj ) { Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj ); Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pObj ); if ( Saig_SimObjFaninC0(pObj) && Saig_SimObjFaninC1(pObj) ) pObj->pData[0] = ~(pObj0->pData[0] | pObj1->pData[0]); else if ( Saig_SimObjFaninC0(pObj) && !Saig_SimObjFaninC1(pObj) ) pObj->pData[0] = (~pObj0->pData[0] & pObj1->pData[0]); else if ( !Saig_SimObjFaninC0(pObj) && Saig_SimObjFaninC1(pObj) ) pObj->pData[0] = (pObj0->pData[0] & ~pObj1->pData[0]); else // if ( !Saig_SimObjFaninC0(pObj) && !Saig_SimObjFaninC1(pObj) ) pObj->pData[0] = (pObj0->pData[0] & pObj1->pData[0]); } /**Function************************************************************* Synopsis [Simulated one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Saig_ManSimulateNode( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj ) { Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj ); Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pObj ); pObj->pData[0] = (Saig_SimObjFaninC0(pObj)? ~pObj0->pData[0] : pObj0->pData[0]) & (Saig_SimObjFaninC1(pObj)? ~pObj1->pData[0] : pObj1->pData[0]); } /**Function************************************************************* Synopsis [Simulated buffer/inverter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Saig_ManSimulateOneInput( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj ) { Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj ); if ( Saig_SimObjFaninC0(pObj) ) pObj->pData[0] = ~pObj0->pData[0]; else // if ( !Saig_SimObjFaninC0(pObj) ) pObj->pData[0] = pObj0->pData[0]; } /**Function************************************************************* Synopsis [Simulates the timeframes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManSimulateFrames( Saig_SimObj_t * pAig, int nFrames, int nPref ) { Saig_SimObj_t * pEntry; int f; for ( f = 0; f < nFrames; f++ ) { for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ ) { if ( pEntry->Type == AIG_OBJ_AND ) Saig_ManSimulateNode( pAig, pEntry ); else if ( pEntry->Type == AIG_OBJ_CO ) Saig_ManSimulateOneInput( pAig, pEntry ); else if ( pEntry->Type == AIG_OBJ_CI ) { if ( pEntry->iFan0 == 0 ) // true PI pEntry->pData[0] = Aig_ManRandom( 0 ); else if ( f > 0 ) // register output Saig_ManSimulateOneInput( pAig, pEntry ); } else if ( pEntry->Type == AIG_OBJ_CONST1 ) pEntry->pData[0] = ~0; else if ( pEntry->Type != AIG_OBJ_NONE ) assert( 0 ); if ( f >= nPref ) pEntry->Number += Aig_WordCountOnes( pEntry->pData[0] ); } } } /**Function************************************************************* Synopsis [Computes switching activity of one node.] Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] SideEffects [] SeeAlso [] ***********************************************************************/ float Saig_ManComputeSwitching( int nOnes, int nSimWords ) { int nTotal = 32 * nSimWords; return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal; } /**Function************************************************************* Synopsis [Computes switching activity of one node.] Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] SideEffects [] SeeAlso [] ***********************************************************************/ float Saig_ManComputeProbOne( int nOnes, int nSimWords ) { int nTotal = 32 * nSimWords; return (float)nOnes / nTotal; } /**Function************************************************************* Synopsis [Computes switching activity of one node.] Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] SideEffects [] SeeAlso [] ***********************************************************************/ float Saig_ManComputeProbOnePlus( int nOnes, int nSimWords, int fCompl ) { int nTotal = 32 * nSimWords; if ( fCompl ) return (float)(nTotal-nOnes) / nTotal; else return (float)nOnes / nTotal; } /**Function************************************************************* Synopsis [Compute switching probabilities of all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Saig_ManComputeSwitchProb4s( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ) { Saig_SimObj_t * pAig, * pEntry; Vec_Int_t * vSwitching; float * pSwitching; int nFramesReal; abctime clk;//, clkTotal = Abc_Clock(); vSwitching = Vec_IntStart( Aig_ManObjNumMax(p) ); pSwitching = (float *)vSwitching->pArray; clk = Abc_Clock(); pAig = Saig_ManCreateMan( p ); //ABC_PRT( "\nCreation ", Abc_Clock() - clk ); Aig_ManRandom( 1 ); // get the number of frames to simulate // if the parameter "seqsimframes" is defined, use it // otherwise, use the given number of frames "nFrames" nFramesReal = nFrames; if ( Abc_FrameReadFlag("seqsimframes") ) nFramesReal = atoi( Abc_FrameReadFlag("seqsimframes") ); if ( nFramesReal <= nPref ) { printf( "The total number of frames (%d) should exceed prefix (%d).\n", nFramesReal, nPref );\ printf( "Setting the total number of frames to be %d.\n", nFrames ); nFramesReal = nFrames; } //printf( "Simulating %d frames.\n", nFramesReal ); clk = Abc_Clock(); Saig_ManSimulateFrames( pAig, nFramesReal, nPref ); //ABC_PRT( "Simulation", Abc_Clock() - clk ); clk = Abc_Clock(); for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ ) { /* if ( pEntry->Type == AIG_OBJ_AND ) { Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pEntry ); Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pEntry ); printf( "%5.2f = %5.2f * %5.2f (%7.4f)\n", Saig_ManComputeProbOnePlus( pEntry->Number, nFrames - nPref, 0 ), Saig_ManComputeProbOnePlus( pObj0->Number, nFrames - nPref, Saig_SimObjFaninC0(pEntry) ), Saig_ManComputeProbOnePlus( pObj1->Number, nFrames - nPref, Saig_SimObjFaninC1(pEntry) ), Saig_ManComputeProbOnePlus( pEntry->Number, nFrames - nPref, 0 ) - Saig_ManComputeProbOnePlus( pObj0->Number, nFrames - nPref, Saig_SimObjFaninC0(pEntry) ) * Saig_ManComputeProbOnePlus( pObj1->Number, nFrames - nPref, Saig_SimObjFaninC1(pEntry) ) ); } */ if ( fProbOne ) pSwitching[pEntry-pAig] = Saig_ManComputeProbOne( pEntry->Number, nFramesReal - nPref ); else pSwitching[pEntry-pAig] = Saig_ManComputeSwitching( pEntry->Number, nFramesReal - nPref ); //printf( "%3d : %7.2f\n", pEntry-pAig, pSwitching[pEntry-pAig] ); } ABC_FREE( pAig ); //ABC_PRT( "Switch ", Abc_Clock() - clk ); //ABC_PRT( "TOTAL ", Abc_Clock() - clkTotal ); // Aig_CManCreate( p ); return vSwitching; } typedef struct Aig_CMan_t_ Aig_CMan_t; struct Aig_CMan_t_ { // parameters int nIns; int nNodes; int nOuts; // current state int iNode; int iDiff0; int iDiff1; unsigned char * pCur; // stored data int iPrev; int nBytes; unsigned char Data[0]; }; /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_CMan_t * Aig_CManStart( int nIns, int nNodes, int nOuts ) { Aig_CMan_t * p; p = (Aig_CMan_t *)ABC_ALLOC( char, sizeof(Aig_CMan_t) + 2*(2*nNodes + nOuts) ); memset( p, 0, sizeof(Aig_CMan_t) ); // set parameters p->nIns = nIns; p->nOuts = nOuts; p->nNodes = nNodes; p->nBytes = 2*(2*nNodes + nOuts); // prepare the manager p->iNode = 1 + p->nIns; p->iPrev = -1; p->pCur = p->Data; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_CManStop( Aig_CMan_t * p ) { ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_CManRestart( Aig_CMan_t * p ) { assert( p->iNode == 1 + p->nIns + p->nNodes + p->nOuts ); p->iNode = 1 + p->nIns; p->iPrev = -1; p->pCur = p->Data; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_CManStoreNum( Aig_CMan_t * p, unsigned x ) { while ( x & ~0x7f ) { *p->pCur++ = (x & 0x7f) | 0x80; x >>= 7; } *p->pCur++ = x; assert( p->pCur - p->Data < p->nBytes - 10 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_CManRestoreNum( Aig_CMan_t * p ) { int ch, i, x = 0; for ( i = 0; (ch = *p->pCur++) & 0x80; i++ ) x |= (ch & 0x7f) << (7 * i); return x | (ch << (7 * i)); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_CManAddNode( Aig_CMan_t * p, int iFan0, int iFan1 ) { assert( iFan0 < iFan1 ); assert( iFan1 < (p->iNode << 1) ); Aig_CManStoreNum( p, (p->iNode++ << 1) - iFan1 ); Aig_CManStoreNum( p, iFan1 - iFan0 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_CManAddPo( Aig_CMan_t * p, int iFan0 ) { if ( p->iPrev == -1 ) Aig_CManStoreNum( p, p->iNode - iFan0 ); else if ( p->iPrev <= iFan0 ) Aig_CManStoreNum( p, (iFan0 - p->iPrev) << 1 ); else Aig_CManStoreNum( p,((p->iPrev - iFan0) << 1) | 1 ); p->iPrev = iFan0; p->iNode++; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_CManGetNode( Aig_CMan_t * p, int * piFan0, int * piFan1 ) { *piFan1 = (p->iNode++ << 1) - Aig_CManRestoreNum( p ); *piFan0 = *piFan1 - Aig_CManRestoreNum( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Aig_CManGetPo( Aig_CMan_t * p ) { int Num = Aig_CManRestoreNum( p ); if ( p->iPrev == -1 ) p->iPrev = p->iNode; p->iNode++; if ( Num & 1 ) return p->iPrev = p->iPrev + (Num >> 1); return p->iPrev = p->iPrev - (Num >> 1); } /**Function************************************************************* Synopsis [Compute switching probabilities of all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_CMan_t * Aig_CManCreate( Aig_Man_t * p ) { Aig_CMan_t * pCMan; Aig_Obj_t * pObj; int i; pCMan = Aig_CManStart( Aig_ManCiNum(p), Aig_ManNodeNum(p), Aig_ManCoNum(p) ); Aig_ManForEachNode( p, pObj, i ) Aig_CManAddNode( pCMan, (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj), (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj) ); Aig_ManForEachCo( p, pObj, i ) Aig_CManAddPo( pCMan, (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj) ); printf( "\nBytes alloc = %5d. Bytes used = %7d. Ave per node = %4.2f. \n", pCMan->nBytes, (int)(pCMan->pCur - pCMan->Data), 1.0 * (pCMan->pCur - pCMan->Data) / (pCMan->nNodes + pCMan->nOuts ) ); // Aig_CManStop( pCMan ); return pCMan; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigSynch.c000066400000000000000000000501351477524141600165520ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigSynch.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Computation of synchronizing sequence.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigSynch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // 0 1 x // 00 01 11 // 0 00 00 00 00 // 1 01 00 01 11 // x 11 00 11 11 static inline unsigned Saig_SynchNot( unsigned w ) { return w^((~(w&(w>>1)))&0x55555555); } static inline unsigned Saig_SynchAnd( unsigned u, unsigned w ) { return (u&w)|((((u&(u>>1)&w&~(w>>1))|(w&(w>>1)&u&~(u>>1)))&0x55555555)<<1); } static inline unsigned Saig_SynchRandomBinary() { return Aig_ManRandom(0) & 0x55555555; } static inline unsigned Saig_SynchRandomTernary() { unsigned w = Aig_ManRandom(0); return w^((~w)&(w>>1)&0x55555555); } static inline unsigned Saig_SynchTernary( int v ) { assert( v == 0 || v == 1 || v == 3 ); return v? ((v==1)? 0x55555555 : 0xffffffff) : 0; } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Initializes registers to the ternary state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_SynchSetConstant1( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords ) { Aig_Obj_t * pObj; unsigned * pSim; int w; pObj = Aig_ManConst1( pAig ); pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); for ( w = 0; w < nWords; w++ ) pSim[w] = 0x55555555; } /**Function************************************************************* Synopsis [Initializes registers to the ternary state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_SynchInitRegsTernary( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords ) { Aig_Obj_t * pObj; unsigned * pSim; int i, w; Saig_ManForEachLo( pAig, pObj, i ) { pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); for ( w = 0; w < nWords; w++ ) pSim[w] = 0xffffffff; } } /**Function************************************************************* Synopsis [Initializes registers to the given binary state.] Description [The binary state is stored in pObj->fMarkA.] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_SynchInitRegsBinary( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords ) { Aig_Obj_t * pObj; unsigned * pSim; int i, w; Saig_ManForEachLo( pAig, pObj, i ) { pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); for ( w = 0; w < nWords; w++ ) pSim[w] = Saig_SynchTernary( pObj->fMarkA ); } } /**Function************************************************************* Synopsis [Initializes random binary primary inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_SynchInitPisRandom( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords ) { Aig_Obj_t * pObj; unsigned * pSim; int i, w; Saig_ManForEachPi( pAig, pObj, i ) { pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); for ( w = 0; w < nWords; w++ ) pSim[w] = Saig_SynchRandomBinary(); } } /**Function************************************************************* Synopsis [Initializes random binary primary inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_SynchInitPisGiven( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords, char * pValues ) { Aig_Obj_t * pObj; unsigned * pSim; int i, w; Saig_ManForEachPi( pAig, pObj, i ) { pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); for ( w = 0; w < nWords; w++ ) pSim[w] = Saig_SynchTernary( pValues[i] ); } } /**Function************************************************************* Synopsis [Performs ternary simulation of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_SynchTernarySimulate( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords ) { Aig_Obj_t * pObj; unsigned * pSim0, * pSim1, * pSim; int i, w; // simulate nodes Aig_ManForEachNode( pAig, pObj, i ) { pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); pSim0 = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjFaninId0(pObj) ); pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjFaninId1(pObj) ); if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) { for ( w = 0; w < nWords; w++ ) pSim[w] = Saig_SynchAnd( Saig_SynchNot(pSim0[w]), Saig_SynchNot(pSim1[w]) ); } else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) { for ( w = 0; w < nWords; w++ ) pSim[w] = Saig_SynchAnd( pSim0[w], Saig_SynchNot(pSim1[w]) ); } else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) { for ( w = 0; w < nWords; w++ ) pSim[w] = Saig_SynchAnd( Saig_SynchNot(pSim0[w]), pSim1[w] ); } else // if ( !Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) { for ( w = 0; w < nWords; w++ ) pSim[w] = Saig_SynchAnd( pSim0[w], pSim1[w] ); } } // transfer values to register inputs Saig_ManForEachLi( pAig, pObj, i ) { pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); pSim0 = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjFaninId0(pObj) ); if ( Aig_ObjFaninC0(pObj) ) { for ( w = 0; w < nWords; w++ ) pSim[w] = Saig_SynchNot( pSim0[w] ); } else { for ( w = 0; w < nWords; w++ ) pSim[w] = pSim0[w]; } } } /**Function************************************************************* Synopsis [Performs ternary simulation of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_SynchTernaryTransferState( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords ) { Aig_Obj_t * pObjLi, * pObjLo; unsigned * pSim0, * pSim1; int i, w; Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) { pSim0 = (unsigned *)Vec_PtrEntry( vSimInfo, pObjLi->Id ); pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, pObjLo->Id ); for ( w = 0; w < nWords; w++ ) pSim1[w] = pSim0[w]; } } /**Function************************************************************* Synopsis [Returns the number of Xs in the smallest ternary pattern.] Description [Returns the number of this pattern.] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_SynchCountX( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords, int * piPat ) { Aig_Obj_t * pObj; unsigned * pSim; int * pCounters, i, w, b; int iPatBest, iTernMin; // count the number of ternary values in each pattern pCounters = ABC_CALLOC( int, nWords * 16 ); Saig_ManForEachLi( pAig, pObj, i ) { pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); for ( w = 0; w < nWords; w++ ) for ( b = 0; b < 16; b++ ) if ( ((pSim[w] >> (b << 1)) & 3) == 3 ) pCounters[16 * w + b]++; } // get the best pattern iPatBest = -1; iTernMin = 1 + Saig_ManRegNum(pAig); for ( b = 0; b < 16 * nWords; b++ ) if ( iTernMin > pCounters[b] ) { iTernMin = pCounters[b]; iPatBest = b; if ( iTernMin == 0 ) break; } ABC_FREE( pCounters ); *piPat = iPatBest; return iTernMin; } /**Function************************************************************* Synopsis [Saves the best pattern found and initializes the registers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_SynchSavePattern( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords, int iPat, Vec_Str_t * vSequence ) { Aig_Obj_t * pObj, * pObjLi, * pObjLo; unsigned * pSim; int Counter, Value, i, w; assert( iPat < 16 * nWords ); Saig_ManForEachPi( pAig, pObj, i ) { pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); Value = (pSim[iPat>>4] >> ((iPat&0xf) << 1)) & 3; Vec_StrPush( vSequence, (char)Value ); // printf( "%d ", Value ); } // printf( "\n" ); Counter = 0; Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) { pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObjLi->Id ); Value = (pSim[iPat>>4] >> ((iPat&0xf) << 1)) & 3; Counter += (Value == 3); // save patern in the same register pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObjLo->Id ); for ( w = 0; w < nWords; w++ ) pSim[w] = Saig_SynchTernary( Value ); } return Counter; } /**Function************************************************************* Synopsis [Implement synchronizing sequence.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Saig_SynchSequenceRun( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, Vec_Str_t * vSequence, int fTernary ) { unsigned * pSim; Aig_Obj_t * pObj; int Counter, nIters, Value, i; assert( Vec_StrSize(vSequence) % Saig_ManPiNum(pAig) == 0 ); nIters = Vec_StrSize(vSequence) / Saig_ManPiNum(pAig); Saig_SynchSetConstant1( pAig, vSimInfo, 1 ); if ( fTernary ) Saig_SynchInitRegsTernary( pAig, vSimInfo, 1 ); else Saig_SynchInitRegsBinary( pAig, vSimInfo, 1 ); for ( i = 0; i < nIters; i++ ) { Saig_SynchInitPisGiven( pAig, vSimInfo, 1, Vec_StrArray(vSequence) + i * Saig_ManPiNum(pAig) ); Saig_SynchTernarySimulate( pAig, vSimInfo, 1 ); Saig_SynchTernaryTransferState( pAig, vSimInfo, 1 ); } // save the resulting state in the registers Counter = 0; Saig_ManForEachLo( pAig, pObj, i ) { pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); Value = pSim[0] & 3; assert( Value != 2 ); Counter += (Value == 3); pObj->fMarkA = Value; } return Counter; } /**Function************************************************************* Synopsis [Determines synchronizing sequence using ternary simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Saig_SynchSequence( Aig_Man_t * pAig, int nWords ) { int nStepsMax = 100; // the maximum number of simulation steps int nTriesMax = 100; // the maximum number of attempts at each step int fVerify = 1; // verify the resulting pattern Vec_Str_t * vSequence; Vec_Ptr_t * vSimInfo; int nTerPrev, nTerCur = 0, nTerCur2; int iPatBest, RetValue, s, t; assert( Saig_ManRegNum(pAig) > 0 ); // reset random numbers Aig_ManRandom( 1 ); // start the sequence vSequence = Vec_StrAlloc( 20 * Saig_ManRegNum(pAig) ); // create sim info and init registers vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(pAig), nWords ); Saig_SynchSetConstant1( pAig, vSimInfo, nWords ); // iterate over the timeframes nTerPrev = Saig_ManRegNum(pAig); Saig_SynchInitRegsTernary( pAig, vSimInfo, nWords ); for ( s = 0; s < nStepsMax && nTerPrev > 0; s++ ) { for ( t = 0; t < nTriesMax; t++ ) { Saig_SynchInitPisRandom( pAig, vSimInfo, nWords ); Saig_SynchTernarySimulate( pAig, vSimInfo, nWords ); nTerCur = Saig_SynchCountX( pAig, vSimInfo, nWords, &iPatBest ); if ( nTerCur < nTerPrev ) break; } if ( t == nTriesMax ) break; nTerCur2 = Saig_SynchSavePattern( pAig, vSimInfo, nWords, iPatBest, vSequence ); assert( nTerCur == nTerCur2 ); nTerPrev = nTerCur; } if ( nTerPrev > 0 ) { printf( "Count not initialize %d registers.\n", nTerPrev ); Vec_PtrFree( vSimInfo ); Vec_StrFree( vSequence ); return NULL; } // verify that the sequence is correct if ( fVerify ) { RetValue = Saig_SynchSequenceRun( pAig, vSimInfo, vSequence, 1 ); assert( RetValue == 0 ); Aig_ManCleanMarkA( pAig ); } Vec_PtrFree( vSimInfo ); return vSequence; } /**Function************************************************************* Synopsis [Duplicates the AIG to have constant-0 initial state.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDupInitZero( Aig_Man_t * p ) { Aig_Man_t * pNew; Aig_Obj_t * pObj; int i; pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); Saig_ManForEachPi( p, pObj, i ) pObj->pData = Aig_ObjCreateCi( pNew ); Saig_ManForEachLo( p, pObj, i ) pObj->pData = Aig_NotCond( Aig_ObjCreateCi( pNew ), pObj->fMarkA ); Aig_ManForEachNode( p, pObj, i ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); Saig_ManForEachPo( p, pObj, i ) pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); Saig_ManForEachLi( p, pObj, i ) pObj->pData = Aig_ObjCreateCo( pNew, Aig_NotCond( Aig_ObjChild0Copy(pObj), pObj->fMarkA ) ); Aig_ManSetRegNum( pNew, Saig_ManRegNum(p) ); assert( Aig_ManNodeNum(pNew) == Aig_ManNodeNum(p) ); return pNew; } /**Function************************************************************* Synopsis [Determines synchronizing sequence using ternary simulation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_SynchSequenceApply( Aig_Man_t * pAig, int nWords, int fVerbose ) { Aig_Man_t * pAigZero; Vec_Str_t * vSequence; Vec_Ptr_t * vSimInfo; int RetValue; abctime clk; clk = Abc_Clock(); // derive synchronization sequence vSequence = Saig_SynchSequence( pAig, nWords ); if ( vSequence == NULL ) printf( "Design 1: Synchronizing sequence is not found. " ); else if ( fVerbose ) printf( "Design 1: Synchronizing sequence of length %4d is found. ", Vec_StrSize(vSequence) / Saig_ManPiNum(pAig) ); if ( fVerbose ) { ABC_PRT( "Time", Abc_Clock() - clk ); } else printf( "\n" ); if ( vSequence == NULL ) { printf( "Quitting synchronization.\n" ); return NULL; } // apply synchronization sequence vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(pAig), 1 ); RetValue = Saig_SynchSequenceRun( pAig, vSimInfo, vSequence, 1 ); assert( RetValue == 0 ); // duplicate pAigZero = Saig_ManDupInitZero( pAig ); // cleanup Vec_PtrFree( vSimInfo ); Vec_StrFree( vSequence ); Aig_ManCleanMarkA( pAig ); return pAigZero; } /**Function************************************************************* Synopsis [Creates SEC miter for two designs without initial state.] Description [The designs (pAig1 and pAig2) are assumed to have ternary initial state. Determines synchronizing sequences using ternary simulation. Simulates the sequences on both designs to come up with equivalent binary initial states. Create seq miter for the designs starting in these states.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_Synchronize( Aig_Man_t * pAig1, Aig_Man_t * pAig2, int nWords, int fVerbose ) { Aig_Man_t * pAig1z, * pAig2z, * pMiter; Vec_Str_t * vSeq1, * vSeq2; Vec_Ptr_t * vSimInfo; int RetValue; abctime clk; /* { unsigned u = Saig_SynchRandomTernary(); unsigned w = Saig_SynchRandomTernary(); unsigned x = Saig_SynchNot( u ); unsigned y = Saig_SynchNot( w ); unsigned z = Saig_SynchAnd( x, y ); Extra_PrintBinary( stdout, &u, 32 ); printf( "\n" ); Extra_PrintBinary( stdout, &w, 32 ); printf( "\n" ); printf( "\n" ); Extra_PrintBinary( stdout, &x, 32 ); printf( "\n" ); Extra_PrintBinary( stdout, &y, 32 ); printf( "\n" ); printf( "\n" ); Extra_PrintBinary( stdout, &z, 32 ); printf( "\n" ); } */ // report statistics if ( fVerbose ) { printf( "Design 1: " ); Aig_ManPrintStats( pAig1 ); printf( "Design 2: " ); Aig_ManPrintStats( pAig2 ); } // synchronize the first design clk = Abc_Clock(); vSeq1 = Saig_SynchSequence( pAig1, nWords ); if ( vSeq1 == NULL ) printf( "Design 1: Synchronizing sequence is not found. " ); else if ( fVerbose ) printf( "Design 1: Synchronizing sequence of length %4d is found. ", Vec_StrSize(vSeq1) / Saig_ManPiNum(pAig1) ); if ( fVerbose ) { ABC_PRT( "Time", Abc_Clock() - clk ); } else printf( "\n" ); // synchronize the first design clk = Abc_Clock(); vSeq2 = Saig_SynchSequence( pAig2, nWords ); if ( vSeq2 == NULL ) printf( "Design 2: Synchronizing sequence is not found. " ); else if ( fVerbose ) printf( "Design 2: Synchronizing sequence of length %4d is found. ", Vec_StrSize(vSeq2) / Saig_ManPiNum(pAig2) ); if ( fVerbose ) { ABC_PRT( "Time", Abc_Clock() - clk ); } else printf( "\n" ); // quit if one of the designs cannot be synchronized if ( vSeq1 == NULL || vSeq2 == NULL ) { printf( "Quitting synchronization.\n" ); if ( vSeq1 ) Vec_StrFree( vSeq1 ); if ( vSeq2 ) Vec_StrFree( vSeq2 ); return NULL; } clk = Abc_Clock(); vSimInfo = Vec_PtrAllocSimInfo( Abc_MaxInt( Aig_ManObjNumMax(pAig1), Aig_ManObjNumMax(pAig2) ), 1 ); // process Design 1 RetValue = Saig_SynchSequenceRun( pAig1, vSimInfo, vSeq1, 1 ); assert( RetValue == 0 ); RetValue = Saig_SynchSequenceRun( pAig1, vSimInfo, vSeq2, 0 ); assert( RetValue == 0 ); // process Design 2 RetValue = Saig_SynchSequenceRun( pAig2, vSimInfo, vSeq2, 1 ); assert( RetValue == 0 ); // duplicate designs pAig1z = Saig_ManDupInitZero( pAig1 ); pAig2z = Saig_ManDupInitZero( pAig2 ); pMiter = Saig_ManCreateMiter( pAig1z, pAig2z, 0 ); Aig_ManCleanup( pMiter ); Aig_ManStop( pAig1z ); Aig_ManStop( pAig2z ); // cleanup Vec_PtrFree( vSimInfo ); Vec_StrFree( vSeq1 ); Vec_StrFree( vSeq2 ); Aig_ManCleanMarkA( pAig1 ); Aig_ManCleanMarkA( pAig2 ); if ( fVerbose ) { printf( "Miter of the synchronized designs is constructed. " ); ABC_PRT( "Time", Abc_Clock() - clk ); } return pMiter; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigTempor.c000066400000000000000000000206511477524141600167340ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigTempor.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Temporal decomposition.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigTempor.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "sat/bmc/bmc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates initialized timeframes for temporal decomposition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManTemporFrames( Aig_Man_t * pAig, int nFrames ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, f; // start the frames package Aig_ManCleanData( pAig ); pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); pFrames->pName = Abc_UtilStrsav( pAig->pName ); // initiliaze the flops Saig_ManForEachLo( pAig, pObj, i ) pObj->pData = Aig_ManConst0(pFrames); // for each timeframe for ( f = 0; f < nFrames; f++ ) { Aig_ManConst1(pAig)->pData = Aig_ManConst1(pFrames); Saig_ManForEachPi( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi(pFrames); Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); Aig_ManForEachCo( pAig, pObj, i ) pObj->pData = Aig_ObjChild0Copy(pObj); Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) pObjLo->pData = pObjLi->pData; } // create POs for the flop inputs Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreateCo( pFrames, (Aig_Obj_t *)pObj->pData ); Aig_ManCleanup( pFrames ); return pFrames; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManTemporDecompose( Aig_Man_t * pAig, int nFrames ) { Aig_Man_t * pAigNew, * pFrames; Aig_Obj_t * pObj, * pReset; int i; if ( pAig->nConstrs > 0 ) { printf( "The AIG manager should have no constraints.\n" ); return NULL; } // create initialized timeframes pFrames = Saig_ManTemporFrames( pAig, nFrames ); assert( Aig_ManCoNum(pFrames) == Aig_ManRegNum(pAig) ); // start the new manager Aig_ManCleanData( pAig ); pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); pAigNew->pName = Abc_UtilStrsav( pAig->pName ); // map the constant node and primary inputs Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); Saig_ManForEachPi( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( pAigNew ); // insert initialization logic Aig_ManConst1(pFrames)->pData = Aig_ManConst1( pAigNew ); Aig_ManForEachCi( pFrames, pObj, i ) pObj->pData = Aig_ObjCreateCi( pAigNew ); Aig_ManForEachNode( pFrames, pObj, i ) pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); Aig_ManForEachCo( pFrames, pObj, i ) pObj->pData = Aig_ObjChild0Copy(pObj); // create reset latch (the first one among the latches) pReset = Aig_ObjCreateCi( pAigNew ); // create flop output values Saig_ManForEachLo( pAig, pObj, i ) pObj->pData = Aig_Mux( pAigNew, pReset, Aig_ObjCreateCi(pAigNew), (Aig_Obj_t *)Aig_ManCo(pFrames, i)->pData ); Aig_ManStop( pFrames ); // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create primary outputs Saig_ManForEachPo( pAig, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); // create reset latch (the first one among the latches) Aig_ObjCreateCo( pAigNew, Aig_ManConst1(pAigNew) ); // create latch inputs Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); // finalize Aig_ManCleanup( pAigNew ); Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig)+1 ); // + reset latch (011111...) return pAigNew; } /**Function************************************************************* Synopsis [Find index of first non-zero entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Vec_IntLastNonZeroBeforeLimit( Vec_Int_t * vTemp, int Limit ) { int Entry, i; if ( vTemp == NULL ) return -1; Vec_IntForEachEntryReverse( vTemp, Entry, i ) { if ( i >= Limit ) continue; if ( Entry ) return i; } return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManTempor( Aig_Man_t * pAig, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fUseTransSigs, int fVerbose, int fVeryVerbose ) { extern int Saig_ManPhasePrefixLength( Aig_Man_t * p, int fVerbose, int fVeryVerbose, Vec_Int_t ** pvTrans ); Vec_Int_t * vTransSigs = NULL; int RetValue, nFramesFinished = -1; assert( nFrames >= 0 ); if ( nFrames == 0 ) { nFrames = Saig_ManPhasePrefixLength( pAig, fVerbose, fVeryVerbose, &vTransSigs ); if ( nFrames == 0 ) { Vec_IntFreeP( &vTransSigs ); printf( "The leading sequence has length 0. Temporal decomposition is not performed.\n" ); return NULL; } if ( nFrames == 1 ) { Vec_IntFreeP( &vTransSigs ); printf( "The leading sequence has length 1. Temporal decomposition is not performed.\n" ); return NULL; } if ( fUseTransSigs ) { int Entry, i, iLast = -1; Vec_IntForEachEntry( vTransSigs, Entry, i ) iLast = Entry ? i :iLast; if ( iLast > 0 && iLast < nFrames ) { Abc_Print( 1, "Reducing frame count from %d to %d to fit the last transient.\n", nFrames, iLast ); nFrames = iLast; } } Abc_Print( 1, "Using computed frame number (%d).\n", nFrames ); } else Abc_Print( 1, "Using user-given frame number (%d).\n", nFrames ); // run BMC2 if ( fUseBmc ) { RetValue = Saig_BmcPerform( pAig, 0, nFrames, 2000, TimeOut, nConfLimit, 0, fVerbose, 0, &nFramesFinished, 0, 0 ); if ( RetValue == 0 ) { Vec_IntFreeP( &vTransSigs ); printf( "A cex found in the first %d frames.\n", nFrames ); return NULL; } if ( nFramesFinished + 1 < nFrames ) { int iLastBefore = Vec_IntLastNonZeroBeforeLimit( vTransSigs, nFramesFinished ); if ( iLastBefore < 1 || !fUseTransSigs ) { Vec_IntFreeP( &vTransSigs ); printf( "BMC for %d frames could not be completed. A cex may exist!\n", nFrames ); return NULL; } assert( iLastBefore < nFramesFinished ); printf( "BMC succeeded to frame %d. Adjusting frame count to be (%d) based on the last transient signal.\n", nFramesFinished, iLastBefore ); nFrames = iLastBefore; } } Vec_IntFreeP( &vTransSigs ); return Saig_ManTemporDecompose( pAig, nFrames ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigTrans.c000066400000000000000000000342471477524141600165630ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigTrans.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Dynamic simplification of the transition relation.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigTrans.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" #include "proof/fra/fra.h" ABC_NAMESPACE_IMPL_START /* A similar approach is presented in the his paper: A. Kuehlmann. Dynamic transition relation simplification for bounded property checking. ICCAD'04, pp. 50-57. */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Maps a node/frame into a node of a different manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Saig_ManStartMap1( Aig_Man_t * p, int nFrames ) { Vec_Int_t * vMap; int i; assert( p->pData == NULL ); vMap = Vec_IntAlloc( Aig_ManObjNumMax(p) * nFrames ); for ( i = 0; i < vMap->nCap; i++ ) vMap->pArray[i] = -1; vMap->nSize = vMap->nCap; p->pData = vMap; } static inline void Saig_ManStopMap1( Aig_Man_t * p ) { assert( p->pData != NULL ); Vec_IntFree( (Vec_Int_t *)p->pData ); p->pData = NULL; } static inline int Saig_ManHasMap1( Aig_Man_t * p ) { return (int)(p->pData != NULL); } static inline void Saig_ManSetMap1( Aig_Man_t * p, Aig_Obj_t * pOld, int f1, Aig_Obj_t * pNew ) { Vec_Int_t * vMap = (Vec_Int_t *)p->pData; int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id; assert( !Aig_IsComplement(pOld) ); assert( !Aig_IsComplement(pNew) ); Vec_IntWriteEntry( vMap, nOffset, pNew->Id ); } static inline int Saig_ManGetMap1( Aig_Man_t * p, Aig_Obj_t * pOld, int f1 ) { Vec_Int_t * vMap = (Vec_Int_t *)p->pData; int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id; return Vec_IntEntry( vMap, nOffset ); } /**Function************************************************************* Synopsis [Maps a node/frame into a node/frame of a different manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Saig_ManStartMap2( Aig_Man_t * p, int nFrames ) { Vec_Int_t * vMap; int i; assert( p->pData2 == NULL ); vMap = Vec_IntAlloc( Aig_ManObjNumMax(p) * nFrames * 2 ); for ( i = 0; i < vMap->nCap; i++ ) vMap->pArray[i] = -1; vMap->nSize = vMap->nCap; p->pData2 = vMap; } static inline void Saig_ManStopMap2( Aig_Man_t * p ) { assert( p->pData2 != NULL ); Vec_IntFree( (Vec_Int_t *)p->pData2 ); p->pData2 = NULL; } static inline int Saig_ManHasMap2( Aig_Man_t * p ) { return (int)(p->pData2 != NULL); } static inline void Saig_ManSetMap2( Aig_Man_t * p, Aig_Obj_t * pOld, int f1, Aig_Obj_t * pNew, int f2 ) { Vec_Int_t * vMap = (Vec_Int_t *)p->pData2; int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id; assert( !Aig_IsComplement(pOld) ); assert( !Aig_IsComplement(pNew) ); Vec_IntWriteEntry( vMap, 2*nOffset + 0, pNew->Id ); Vec_IntWriteEntry( vMap, 2*nOffset + 1, f2 ); } static inline int Saig_ManGetMap2( Aig_Man_t * p, Aig_Obj_t * pOld, int f1, int * pf2 ) { Vec_Int_t * vMap = (Vec_Int_t *)p->pData2; int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id; *pf2 = Vec_IntEntry( vMap, 2*nOffset + 1 ); return Vec_IntEntry( vMap, 2*nOffset ); } /**Function************************************************************* Synopsis [Create mapping for the first nFrames timeframes of pAig.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManCreateMapping( Aig_Man_t * pAig, Aig_Man_t * pFrames, int nFrames ) { Aig_Obj_t * pObj, * pObjFrame, * pObjRepr; int i, f, iNum, iFrame; assert( pFrames->pReprs != NULL ); // mapping from nodes into their representatives // start step mapping for both orignal manager and fraig Saig_ManStartMap2( pAig, nFrames ); Saig_ManStartMap2( pFrames, 1 ); // for each object in each frame for ( f = 0; f < nFrames; f++ ) Aig_ManForEachObj( pAig, pObj, i ) { // get the frame object iNum = Saig_ManGetMap1( pAig, pObj, f ); pObjFrame = Aig_ManObj( pFrames, iNum ); // if the node has no prototype, map it into itself if ( pObjFrame == NULL ) { Saig_ManSetMap2( pAig, pObj, f, pObj, f ); continue; } // get the representative object pObjRepr = Aig_ObjRepr( pFrames, pObjFrame ); if ( pObjRepr == NULL ) pObjRepr = pObjFrame; // check if this is the first time this object is reached if ( Saig_ManGetMap2( pFrames, pObjRepr, 0, &iFrame ) == -1 ) Saig_ManSetMap2( pFrames, pObjRepr, 0, pObj, f ); // set the map for the main object iNum = Saig_ManGetMap2( pFrames, pObjRepr, 0, &iFrame ); Saig_ManSetMap2( pAig, pObj, f, Aig_ManObj(pAig, iNum), iFrame ); } Saig_ManStopMap2( pFrames ); assert( Saig_ManHasMap2(pAig) ); } /**Function************************************************************* Synopsis [Unroll without initialization.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManFramesNonInitial( Aig_Man_t * pAig, int nFrames ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo; int i, f; assert( Saig_ManRegNum(pAig) > 0 ); // start node map Saig_ManStartMap1( pAig, nFrames ); // start the new manager pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames ); // create variables for register outputs Saig_ManForEachLo( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( pFrames ); // add timeframes for ( f = 0; f < nFrames; f++ ) { // create PI nodes for this frame Saig_ManForEachPi( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( pFrames ); // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // create POs for this frame Saig_ManForEachPo( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) ); // save register inputs Saig_ManForEachLi( pAig, pObj, i ) pObj->pData = Aig_ObjChild0Copy(pObj); // save the mapping Aig_ManForEachObj( pAig, pObj, i ) { assert( pObj->pData != NULL ); Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) ); } // quit if the last frame if ( f == nFrames - 1 ) break; // transfer to register outputs Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) pObjLo->pData = pObjLi->pData; } // remember register outputs Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) Aig_ObjCreateCo( pFrames, (Aig_Obj_t *)pObjLi->pData ); Aig_ManCleanup( pFrames ); return pFrames; } /**Function************************************************************* Synopsis [Unroll with initialization and mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManFramesInitialMapped( Aig_Man_t * pAig, int nFrames, int nFramesMax, int fInit ) { Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pRepr; int i, f, iNum1, iNum2, iFrame2; assert( nFrames <= nFramesMax ); assert( Saig_ManRegNum(pAig) > 0 ); // start node map Saig_ManStartMap1( pAig, nFramesMax ); // start the new manager pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFramesMax ); // create variables for register outputs if ( fInit ) { Saig_ManForEachLo( pAig, pObj, i ) { pObj->pData = Aig_ManConst0( pFrames ); Saig_ManSetMap1( pAig, pObj, 0, Aig_Regular((Aig_Obj_t *)pObj->pData) ); } } else { // create PIs first for ( f = 0; f < nFramesMax; f++ ) Saig_ManForEachPi( pAig, pObj, i ) Aig_ObjCreateCi( pFrames ); // create registers second Saig_ManForEachLo( pAig, pObj, i ) { pObj->pData = Aig_ObjCreateCi( pFrames ); Saig_ManSetMap1( pAig, pObj, 0, Aig_Regular((Aig_Obj_t *)pObj->pData) ); } } // add timeframes for ( f = 0; f < nFramesMax; f++ ) { // map the constant node pObj = Aig_ManConst1(pAig); pObj->pData = Aig_ManConst1( pFrames ); Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) ); // create PI nodes for this frame Saig_ManForEachPi( pAig, pObj, i ) { if ( fInit ) pObj->pData = Aig_ObjCreateCi( pFrames ); else pObj->pData = Aig_ManCi( pFrames, f * Saig_ManPiNum(pAig) + i ); Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) ); } // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) { pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) ); if ( !Saig_ManHasMap2(pAig) ) continue; if ( f < nFrames ) { // get the mapping for this node iNum2 = Saig_ManGetMap2( pAig, pObj, f, &iFrame2 ); } else { // get the mapping for this node iNum2 = Saig_ManGetMap2( pAig, pObj, nFrames-1, &iFrame2 ); iFrame2 += f - (nFrames-1); } assert( iNum2 != -1 ); assert( f >= iFrame2 ); // get the corresponding frames node iNum1 = Saig_ManGetMap1( pAig, Aig_ManObj(pAig, iNum2), iFrame2 ); pRepr = Aig_ManObj( pFrames, iNum1 ); // compare the phases of these nodes pObj->pData = Aig_NotCond( pRepr, pRepr->fPhase ^ Aig_ObjPhaseReal((Aig_Obj_t *)pObj->pData) ); } // create POs for this frame Saig_ManForEachPo( pAig, pObj, i ) { pObj->pData = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) ); Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) ); } // save register inputs Saig_ManForEachLi( pAig, pObj, i ) { pObj->pData = Aig_ObjChild0Copy(pObj); Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) ); } // quit if the last frame if ( f == nFramesMax - 1 ) break; // transfer to register outputs Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) { pObjLo->pData = pObjLi->pData; if ( !fInit ) Saig_ManSetMap1( pAig, pObjLo, f+1, Aig_Regular((Aig_Obj_t *)pObjLo->pData) ); } } if ( !fInit ) { // create registers Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) Aig_ObjCreateCo( pFrames, (Aig_Obj_t *)pObjLi->pData ); // set register number Aig_ManSetRegNum( pFrames, pAig->nRegs ); } Aig_ManCleanup( pFrames ); Saig_ManStopMap1( pAig ); return pFrames; } /**Function************************************************************* Synopsis [Implements dynamic simplification.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManTimeframeSimplify( Aig_Man_t * pAig, int nFrames, int nFramesMax, int fInit, int fVerbose ) { // extern Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax, int fProve ); Aig_Man_t * pFrames, * pFraig, * pRes1, * pRes2; abctime clk; // create uninitialized timeframes with map1 pFrames = Saig_ManFramesNonInitial( pAig, nFrames ); // perform fraiging for the unrolled timeframes clk = Abc_Clock(); pFraig = Fra_FraigEquivence( pFrames, 1000, 0 ); // report the results if ( fVerbose ) { Aig_ManPrintStats( pFrames ); Aig_ManPrintStats( pFraig ); ABC_PRT( "Fraiging", Abc_Clock() - clk ); } Aig_ManStop( pFraig ); assert( pFrames->pReprs != NULL ); // create AIG with map2 Saig_ManCreateMapping( pAig, pFrames, nFrames ); Aig_ManStop( pFrames ); Saig_ManStopMap1( pAig ); // create reduced initialized timeframes clk = Abc_Clock(); pRes2 = Saig_ManFramesInitialMapped( pAig, nFrames, nFramesMax, fInit ); ABC_PRT( "Mapped", Abc_Clock() - clk ); // free mapping Saig_ManStopMap2( pAig ); clk = Abc_Clock(); pRes1 = Saig_ManFramesInitialMapped( pAig, nFrames, nFramesMax, fInit ); ABC_PRT( "Normal", Abc_Clock() - clk ); // report the results if ( fVerbose ) { Aig_ManPrintStats( pRes1 ); Aig_ManPrintStats( pRes2 ); } Aig_ManStop( pRes1 ); assert( !Saig_ManHasMap1(pAig) ); assert( !Saig_ManHasMap2(pAig) ); return pRes2; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saigUnfold2.c000066400000000000000000000421671477524141600170050ustar00rootroot00000000000000 int Saig_ManFilterUsingIndOne2( Aig_Man_t * p, Aig_Man_t * pFrame, sat_solver * pSat, Cnf_Dat_t * pCnf, int nConfs, int nProps, int Counter , int type_ /* jlong -- */ ) { Aig_Obj_t * pObj; int Lit, status; pObj = Aig_ManCo( pFrame, Counter*3+type_ ); /* which co */ Lit = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ); status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfs, 0, 0, 0 ); if ( status == l_False ) /* unsat */ return status; if ( status == l_Undef ) { printf( "Solver returned undecided.\n" ); return status; } assert( status == l_True ); return status; } Aig_Man_t * Saig_ManCreateIndMiter2( Aig_Man_t * pAig, Vec_Vec_t * vCands ) { int nFrames = 3; Vec_Ptr_t * vNodes; Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; Aig_Obj_t ** pObjMap; int i, f, k; // create mapping for the frames nodes pObjMap = ABC_CALLOC( Aig_Obj_t *, nFrames * Aig_ManObjNumMax(pAig) ); // start the fraig package pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); pFrames->pName = Abc_UtilStrsav( pAig->pName ); pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); // map constant nodes for ( f = 0; f < nFrames; f++ ) Aig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); // create PI nodes for the frames for ( f = 0; f < nFrames; f++ ) Aig_ManForEachPiSeq( pAig, pObj, i ) Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, Aig_ObjCreateCi(pFrames) ); // set initial state for the latches Aig_ManForEachLoSeq( pAig, pObj, i ) Aig_ObjSetFrames( pObjMap, nFrames, pObj, 0, Aig_ObjCreateCi(pFrames) ); // add timeframes for ( f = 0; f < nFrames; f++ ) { // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) { pObjNew = Aig_And( pFrames, Aig_ObjChild0Frames(pObjMap,nFrames,pObj,f), Aig_ObjChild1Frames(pObjMap,nFrames,pObj,f) ); Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); } // set the latch inputs and copy them into the latch outputs of the next frame Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i ) { pObjNew = Aig_ObjChild0Frames(pObjMap,nFrames,pObjLi,f); if ( f < nFrames - 1 ) Aig_ObjSetFrames( pObjMap, nFrames, pObjLo, f+1, pObjNew ); } } // go through the candidates Vec_VecForEachLevel( vCands, vNodes, i ) { Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) { Aig_Obj_t * pObjR = Aig_Regular(pObj); Aig_Obj_t * pNode0 = pObjMap[nFrames*Aig_ObjId(pObjR)+0]; Aig_Obj_t * pNode1 = pObjMap[nFrames*Aig_ObjId(pObjR)+1]; { Aig_Obj_t * pFan0 = Aig_NotCond( pNode0, Aig_IsComplement(pObj) ); Aig_Obj_t * pFan1 = Aig_NotCond( pNode1, !Aig_IsComplement(pObj) ); Aig_Obj_t * pMiter = Aig_And( pFrames, pFan0, pFan1 ); Aig_ObjCreateCo( pFrames, pMiter ); /* need to check p & Xp is satisfiable */ /* jlong -- begin */ { Aig_Obj_t * pMiter2 = Aig_And( pFrames, pFan0, Aig_Not(pFan1)); Aig_ObjCreateCo( pFrames, pMiter2 ); } /* jlong -- end */ } { /* jlong -- begin */ Aig_Obj_t * pNode2 = pObjMap[nFrames*Aig_ObjId(pObjR)+2]; Aig_Obj_t * pFan0 = Aig_NotCond( pNode0, Aig_IsComplement(pObj) ); Aig_Obj_t * pFan1 = Aig_NotCond( pNode1, Aig_IsComplement(pObj) ); Aig_Obj_t * pFan2 = Aig_NotCond( pNode2, !Aig_IsComplement(pObj) ); Aig_Obj_t * pMiter = Aig_And( pFrames, Aig_And(pFrames, pFan0, pFan1 ), pFan2); Aig_ObjCreateCo( pFrames, pMiter ); /* jlong -- end */ } } } Aig_ManCleanup( pFrames ); ABC_FREE( pObjMap ); //Aig_ManShow( pAig, 0, NULL ); //Aig_ManShow( pFrames, 0, NULL ); return pFrames; } /**Function************************************************************* Synopsis [Detects constraints functionally.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManFilterUsingInd2( Aig_Man_t * p, Vec_Vec_t * vCands, int nConfs, int nProps, int fVerbose ) { Vec_Ptr_t * vNodes; Aig_Man_t * pFrames; sat_solver * pSat; Cnf_Dat_t * pCnf; Aig_Obj_t * pObj; int i, k, k2, Counter; /* Vec_VecForEachLevel( vCands, vNodes, i ) Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) printf( "%d ", Aig_ObjId(Aig_Regular(pObj)) ); printf( "\n" ); */ // create timeframes // pFrames = Saig_ManUnrollInd( p ); pFrames = Saig_ManCreateIndMiter2( p, vCands ); assert( Aig_ManCoNum(pFrames) == Vec_VecSizeSize(vCands)*3 ); // start the SAT solver pCnf = Cnf_DeriveSimple( pFrames, Aig_ManCoNum(pFrames) ); pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); // check candidates if ( fVerbose ) printf( "Filtered cands: \n" ); Counter = 0; Vec_VecForEachLevel( vCands, vNodes, i ) { assert(i==0); /* only one item */ k2 = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) { if ( Saig_ManFilterUsingIndOne2( p, pFrames, pSat, pCnf, nConfs, nProps, Counter++ , 0) == l_False) // if ( Saig_ManFilterUsingIndOne_old( p, pSat, pCnf, nConfs, pObj ) ) { Vec_PtrWriteEntry( vNodes, k2++, pObj ); if ( fVerbose ) printf( "%d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); printf( " type I : %d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); Vec_PtrPush(p->unfold2_type_I, pObj); } /* jlong -- begin */ else if ( Saig_ManFilterUsingIndOne2( p, pFrames, pSat, pCnf, nConfs, nProps, Counter-1 , 1) == l_True ) /* can be self-conflicting */ { if ( Saig_ManFilterUsingIndOne2( p, pFrames, pSat, pCnf, nConfs, nProps, Counter-1 , 2) == l_False ){ //Vec_PtrWriteEntry( vNodes, k2++, pObj ); if ( fVerbose ) printf( "%d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); printf( " type II: %d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); Vec_PtrWriteEntry( vNodes, k2++, pObj ); /* add type II constraints */ Vec_PtrPush(p->unfold2_type_II, pObj); } } /* jlong -- end */ } Vec_PtrShrink( vNodes, k2 ); } // clean up Cnf_DataFree( pCnf ); sat_solver_delete( pSat ); if ( fVerbose ) Aig_ManPrintStats( pFrames ); Aig_ManStop( pFrames ); } /**Function************************************************************* Synopsis [Returns the number of variables implied by the output.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Ssw_ManFindDirectImplications2( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fVerbose ) { Vec_Vec_t * vCands = NULL; Vec_Ptr_t * vNodes; Cnf_Dat_t * pCnf; sat_solver * pSat; Aig_Man_t * pFrames; Aig_Obj_t * pObj, * pRepr, * pReprR; int i, f, k, value; assert(nFrames == 1); vCands = Vec_VecAlloc( nFrames ); assert(nFrames == 1); // perform unrolling pFrames = Saig_ManUnrollCOI( p, nFrames ); assert( Aig_ManCoNum(pFrames) == 1 ); // start the SAT solver pCnf = Cnf_DeriveSimple( pFrames, 0 ); pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); if ( pSat != NULL ) { Aig_ManIncrementTravId( p ); for ( f = 0; f < nFrames; f++ ) { Aig_ManForEachObj( p, pObj, i ) { if ( !Aig_ObjIsCand(pObj) ) continue; //--jlong : also use internal nodes as well /* if ( !Aig_ObjIsCi(pObj) ) */ /* continue; */ if ( Aig_ObjIsTravIdCurrent(p, pObj) ) continue; // get the node from timeframes pRepr = p->pObjCopies[nFrames*i + nFrames-1-f]; pReprR = Aig_Regular(pRepr); if ( pCnf->pVarNums[Aig_ObjId(pReprR)] < 0 ) continue; // value = pSat->assigns[ pCnf->pVarNums[Aig_ObjId(pReprR)] ]; value = sat_solver_get_var_value( pSat, pCnf->pVarNums[Aig_ObjId(pReprR)] ); if ( value == l_Undef ) continue; // label this node as taken Aig_ObjSetTravIdCurrent(p, pObj); if ( Saig_ObjIsLo(p, pObj) ) Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin0(Saig_ObjLoToLi(p, pObj)) ); // remember the node Vec_VecPush( vCands, f, Aig_NotCond( pObj, (value == l_True) ^ Aig_IsComplement(pRepr) ) ); // printf( "%s%d ", (value == l_False)? "":"!", i ); } } // printf( "\n" ); sat_solver_delete( pSat ); } Aig_ManStop( pFrames ); Cnf_DataFree( pCnf ); if ( fVerbose ) { printf( "Found %3d candidates.\n", Vec_VecSizeSize(vCands) ); Vec_VecForEachLevel( vCands, vNodes, k ) { printf( "Level %d. Cands =%d ", k, Vec_PtrSize(vNodes) ); // Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) // printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); printf( "\n" ); } } ABC_FREE( p->pObjCopies ); /* -- jlong -- this does the SAT proof of the constraints */ Saig_ManFilterUsingInd2( p, vCands, nConfs, nProps, fVerbose ); if ( Vec_VecSizeSize(vCands) ) printf( "Found %3d constraints after filtering.\n", Vec_VecSizeSize(vCands) ); if ( fVerbose ) { Vec_VecForEachLevel( vCands, vNodes, k ) { printf( "Level %d. Constr =%d ", k, Vec_PtrSize(vNodes) ); // Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) // printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); printf( "\n" ); } } return vCands; } /**Function************************************************************* Synopsis [Duplicates the AIG while unfolding constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDupUnfoldConstrsFunc2( Aig_Man_t * pAig, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose , int * typeII_cnt){ Aig_Man_t * pNew; Vec_Vec_t * vCands; Vec_Ptr_t * vNewFlops; Aig_Obj_t * pObj; int i, k, nNewFlops; const int fCompl = 0 ; if ( fOldAlgo ) vCands = Saig_ManDetectConstrFunc( pAig, nFrames, nConfs, nProps, fVerbose ); else vCands = Ssw_ManFindDirectImplications2( pAig, nFrames, nConfs, nProps, fVerbose ); if ( vCands == NULL || Vec_VecSizeSize(vCands) == 0 ) { Vec_VecFreeP( &vCands ); return Aig_ManDupDfs( pAig ); } // create new manager pNew = Aig_ManDupWithoutPos( pAig ); /* good */ pNew->nConstrs = pAig->nConstrs + Vec_VecSizeSize(vCands); pNew->nConstrs = pAig->nConstrs + Vec_PtrSize(pAig->unfold2_type_II) + Vec_PtrSize(pAig->unfold2_type_I); // pNew->nConstrsTypeII = Vec_PtrSize(pAig->unfold2_type_II); *typeII_cnt = Vec_PtrSize(pAig->unfold2_type_II); /* new set of registers */ // add normal POs Saig_ManForEachPo( pAig, pObj, i ) Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); // create constraint outputs vNewFlops = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry(Aig_Obj_t * , pAig->unfold2_type_I, pObj, k){ Aig_Obj_t * x = Aig_ObjRealCopy(pObj); Aig_ObjCreateCo(pNew, x); } Vec_PtrForEachEntry(Aig_Obj_t * , pAig->unfold2_type_II, pObj, k){ Aig_Obj_t * type_II_latch = Aig_ObjCreateCi(pNew); /* will get connected later; */ Aig_Obj_t * x = Aig_ObjRealCopy(pObj); Aig_Obj_t * n = Aig_And(pNew, Aig_NotCond(type_II_latch, fCompl), Aig_NotCond(x, fCompl)); Aig_ObjCreateCo(pNew, n);//Aig_Not(n)); } // add latch outputs Saig_ManForEachLi( pAig, pObj, i ) Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); Vec_PtrForEachEntry(Aig_Obj_t * , pAig->unfold2_type_II, pObj, k){ Aig_Obj_t * x = Aig_ObjRealCopy(pObj); Aig_ObjCreateCo(pNew, x); } // add new latch outputs nNewFlops = Vec_PtrSize(pAig->unfold2_type_II); //assert( nNewFlops == Vec_PtrSize(vNewFlops) ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) + nNewFlops ); printf("#reg after unfold2: %d\n", Aig_ManRegNum(pAig) + nNewFlops ); Vec_VecFreeP( &vCands ); Vec_PtrFree( vNewFlops ); return pNew; } /**Function************************************************************* Synopsis [Duplicates the AIG while unfolding constraints.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManDupFoldConstrsFunc2( Aig_Man_t * pAig, int fCompl, int fVerbose , int typeII_cnt) { Aig_Man_t * pAigNew; Aig_Obj_t * pMiter, * pFlopOut, * pFlopIn, * pObj; int i, typeII_cc, type_II; if ( Aig_ManConstrNum(pAig) == 0 ) return Aig_ManDupDfs( pAig ); assert( Aig_ManConstrNum(pAig) < Saig_ManPoNum(pAig) ); // start the new manager pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); pAigNew->pName = Abc_UtilStrsav( pAig->pName ); pAigNew->pSpec = Abc_UtilStrsav( pAig->pSpec ); // map the constant node Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); // create variables for PIs Aig_ManForEachCi( pAig, pObj, i ) pObj->pData = Aig_ObjCreateCi( pAigNew ); // add internal nodes of this frame Aig_ManForEachNode( pAig, pObj, i ) pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // OR the constraint outputs pMiter = Aig_ManConst0( pAigNew ); typeII_cc = 0;//typeII_cnt; typeII_cnt = 0; type_II = 0; Saig_ManForEachPo( pAig, pObj, i ) { if ( i < Saig_ManPoNum(pAig)-Aig_ManConstrNum(pAig) ) continue; if (i + typeII_cnt >= Saig_ManPoNum(pAig) ) { type_II = 1; } /* now we got the constraint */ if (type_II) { Aig_Obj_t * type_II_latch = Aig_ObjCreateCi(pAigNew); /* will get connected later; */ pMiter = Aig_Or(pAigNew, pMiter, Aig_And(pAigNew, Aig_NotCond(type_II_latch, fCompl), Aig_NotCond( Aig_ObjChild0Copy(pObj), fCompl ) ) ); printf( "modeling typeII : %d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); } else pMiter = Aig_Or( pAigNew, pMiter, Aig_NotCond( Aig_ObjChild0Copy(pObj), fCompl ) ); } // create additional flop if ( Saig_ManRegNum(pAig) > 0 ) { pFlopOut = Aig_ObjCreateCi( pAigNew ); pFlopIn = Aig_Or( pAigNew, pMiter, pFlopOut ); } else pFlopIn = pMiter; // create primary output Saig_ManForEachPo( pAig, pObj, i ) { if ( i >= Saig_ManPoNum(pAig)-Aig_ManConstrNum(pAig) ) continue; pMiter = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_Not(pFlopIn) ); Aig_ObjCreateCo( pAigNew, pMiter ); } // transfer to register outputs { /* the same for type I and type II */ Aig_Obj_t * pObjLi, *pObjLo; Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) { if( i + typeII_cc < Aig_ManRegNum(pAig)) { Aig_Obj_t *c = Aig_Mux(pAigNew, Aig_Not(pFlopIn), Aig_ObjChild0Copy(pObjLi) , (Aig_Obj_t*)pObjLo->pData); Aig_ObjCreateCo( pAigNew, c); } else { printf ( "skipping: reg%d\n", i); Aig_ObjCreateCo( pAigNew,Aig_ObjChild0Copy(pObjLi)); } } } if(0)Saig_ManForEachLi( pAig, pObj, i ) { Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); } Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) ); type_II = 0; Saig_ManForEachPo( pAig, pObj, i ) { if ( i < Saig_ManPoNum(pAig)-Aig_ManConstrNum(pAig) ) continue; if (i + typeII_cnt >= Saig_ManPoNum(pAig) ) { type_II = 1; } /* now we got the constraint */ if (type_II) { Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj)); Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAigNew)+1 ); printf( "Latch for typeII : %d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); } } // create additional flop if ( Saig_ManRegNum(pAig) > 0 ) { Aig_ObjCreateCo( pAigNew, pFlopIn ); Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAigNew)+1 ); } printf("#reg after fold2: %d\n", Aig_ManRegNum(pAigNew)); // perform cleanup Aig_ManCleanup( pAigNew ); Aig_ManSeqCleanup( pAigNew ); return pAigNew; } abc-0.52/src/aig/saig/saigWnd.c000066400000000000000000000635511477524141600162240ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saigWnd.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [Sequential windowing.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saigWnd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the array of PI/internal nodes.] Description [Marks all the visited nodes with the current ID. Does not collect constant node and PO/LI nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManWindowOutline_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist, Vec_Ptr_t * vNodes, int * pDists ) { Aig_Obj_t * pMatch, * pFanout; int fCollected, iFanout = -1, i; if ( nDist == 0 ) return; if ( pDists[pObj->Id] >= nDist ) return; pDists[pObj->Id] = nDist; fCollected = Aig_ObjIsTravIdCurrent( p, pObj ); Aig_ObjSetTravIdCurrent( p, pObj ); if ( Aig_ObjIsConst1(pObj) ) return; if ( Saig_ObjIsPo(p, pObj) ) return; if ( Saig_ObjIsLi(p, pObj) ) { pMatch = Saig_ObjLiToLo( p, pObj ); if ( !Aig_ObjIsTravIdCurrent( p, pMatch ) ) Saig_ManWindowOutline_rec( p, pMatch, nDist, vNodes, pDists ); Saig_ManWindowOutline_rec( p, Aig_ObjFanin0(pObj), nDist-1, vNodes, pDists ); return; } if ( !fCollected ) Vec_PtrPush( vNodes, pObj ); if ( Saig_ObjIsPi(p, pObj) ) return; if ( Saig_ObjIsLo(p, pObj) ) { pMatch = Saig_ObjLoToLi( p, pObj ); if ( !Aig_ObjIsTravIdCurrent( p, pMatch ) ) Saig_ManWindowOutline_rec( p, pMatch, nDist, vNodes, pDists ); Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) Saig_ManWindowOutline_rec( p, pFanout, nDist-1, vNodes, pDists ); return; } assert( Aig_ObjIsNode(pObj) ); Saig_ManWindowOutline_rec( p, Aig_ObjFanin0(pObj), nDist-1, vNodes, pDists ); Saig_ManWindowOutline_rec( p, Aig_ObjFanin1(pObj), nDist-1, vNodes, pDists ); Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) Saig_ManWindowOutline_rec( p, pFanout, nDist-1, vNodes, pDists ); } /**Function************************************************************* Synopsis [Returns the array of PI/internal nodes.] Description [Marks all the visited nodes with the current ID.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Saig_ManWindowOutline( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObjLi, * pObjLo; int * pDists, i; pDists = ABC_CALLOC( int, Aig_ManObjNumMax(p) ); vNodes = Vec_PtrAlloc( 1000 ); Aig_ManIncrementTravId( p ); Saig_ManWindowOutline_rec( p, pObj, nDist, vNodes, pDists ); 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) == Aig_ObjIsTravIdCurrent(p, pObjLo) ); ABC_FREE( pDists ); return vNodes; } /**Function************************************************************* Synopsis [Returns 1 if the node has unlabeled fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Saig_ObjHasUnlabeledFanout( Aig_Man_t * p, Aig_Obj_t * pObj ) { Aig_Obj_t * pFanout; int iFanout = -1, i; Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) if ( Saig_ObjIsPo(p, pFanout) || !Aig_ObjIsTravIdCurrent(p, pFanout) ) return pFanout; return NULL; } /**Function************************************************************* Synopsis [Collects primary inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Saig_ManWindowCollectPis( Aig_Man_t * p, Vec_Ptr_t * vNodes ) { Vec_Ptr_t * vNodesPi; Aig_Obj_t * pObj, * pMatch, * pFanin; int i; vNodesPi = Vec_PtrAlloc( 1000 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { if ( Saig_ObjIsPi(p, pObj) ) { assert( pObj->pData == NULL ); Vec_PtrPush( vNodesPi, pObj ); } else if ( Saig_ObjIsLo(p, pObj) ) { pMatch = Saig_ObjLoToLi( p, pObj ); pFanin = Aig_ObjFanin0(pMatch); if ( !Aig_ObjIsTravIdCurrent(p, pFanin) && pFanin->pData == NULL ) Vec_PtrPush( vNodesPi, pFanin ); } else { assert( Aig_ObjIsNode(pObj) ); pFanin = Aig_ObjFanin0(pObj); if ( !Aig_ObjIsTravIdCurrent(p, pFanin) && pFanin->pData == NULL ) Vec_PtrPush( vNodesPi, pFanin ); pFanin = Aig_ObjFanin1(pObj); if ( !Aig_ObjIsTravIdCurrent(p, pFanin) && pFanin->pData == NULL ) Vec_PtrPush( vNodesPi, pFanin ); } } return vNodesPi; } /**Function************************************************************* Synopsis [Collects primary outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Saig_ManWindowCollectPos( Aig_Man_t * p, Vec_Ptr_t * vNodes, Vec_Ptr_t ** pvPointers ) { Vec_Ptr_t * vNodesPo; Aig_Obj_t * pObj, * pPointer; int i; vNodesPo = Vec_PtrAlloc( 1000 ); if ( pvPointers ) *pvPointers = Vec_PtrAlloc( 1000 ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { if ( (pPointer = Saig_ObjHasUnlabeledFanout(p, pObj)) ) { Vec_PtrPush( vNodesPo, pObj ); if ( pvPointers ) Vec_PtrPush( *pvPointers, pPointer ); } } return vNodesPo; } /**Function************************************************************* Synopsis [Extracts the window AIG from the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManWindowExtractNodes( Aig_Man_t * p, Vec_Ptr_t * vNodes ) { Aig_Man_t * pNew; Aig_Obj_t * pObj, * pMatch; Vec_Ptr_t * vNodesPi, * vNodesPo; int i, nRegCount; Aig_ManCleanData( p ); // create the new manager pNew = Aig_ManStart( Vec_PtrSize(vNodes) ); pNew->pName = Abc_UtilStrsav( "wnd" ); pNew->pSpec = NULL; // map constant nodes pObj = Aig_ManConst1( p ); pObj->pData = Aig_ManConst1( pNew ); // create real PIs vNodesPi = Saig_ManWindowCollectPis( p, vNodes ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodesPi, pObj, i ) pObj->pData = Aig_ObjCreateCi(pNew); Vec_PtrFree( vNodesPi ); // create register outputs Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { if ( Saig_ObjIsLo(p, pObj) ) pObj->pData = Aig_ObjCreateCi(pNew); } // create internal nodes Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { if ( Aig_ObjIsNode(pObj) ) pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); } // create POs vNodesPo = Saig_ManWindowCollectPos( p, vNodes, NULL ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodesPo, pObj, i ) Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObj->pData ); Vec_PtrFree( vNodesPo ); // create register inputs nRegCount = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) { if ( Saig_ObjIsLo(p, pObj) ) { pMatch = Saig_ObjLoToLi( p, pObj ); Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch) ); nRegCount++; } } Aig_ManSetRegNum( pNew, nRegCount ); Aig_ManCleanup( pNew ); return pNew; } static void Saig_ManWindowInsertSmall_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjSmall, Vec_Ptr_t * vBigNode2SmallPo, Vec_Ptr_t * vSmallPi2BigNode ); /**Function************************************************************* Synopsis [Adds nodes for the big manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManWindowInsertBig_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjBig, Vec_Ptr_t * vBigNode2SmallPo, Vec_Ptr_t * vSmallPi2BigNode ) { Aig_Obj_t * pMatch; if ( pObjBig->pData ) return; if ( (pMatch = (Aig_Obj_t *)Vec_PtrEntry( vBigNode2SmallPo, pObjBig->Id )) ) { Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin0(pMatch), vBigNode2SmallPo, vSmallPi2BigNode ); pObjBig->pData = Aig_ObjChild0Copy(pMatch); return; } assert( Aig_ObjIsNode(pObjBig) ); Saig_ManWindowInsertBig_rec( pNew, Aig_ObjFanin0(pObjBig), vBigNode2SmallPo, vSmallPi2BigNode ); Saig_ManWindowInsertBig_rec( pNew, Aig_ObjFanin1(pObjBig), vBigNode2SmallPo, vSmallPi2BigNode ); pObjBig->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObjBig), Aig_ObjChild1Copy(pObjBig) ); } /**Function************************************************************* Synopsis [Adds nodes for the small manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManWindowInsertSmall_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjSmall, Vec_Ptr_t * vBigNode2SmallPo, Vec_Ptr_t * vSmallPi2BigNode ) { Aig_Obj_t * pMatch; if ( pObjSmall->pData ) return; if ( (pMatch = (Aig_Obj_t *)Vec_PtrEntry( vSmallPi2BigNode, pObjSmall->Id )) ) { Saig_ManWindowInsertBig_rec( pNew, pMatch, vBigNode2SmallPo, vSmallPi2BigNode ); pObjSmall->pData = pMatch->pData; return; } assert( Aig_ObjIsNode(pObjSmall) ); Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin0(pObjSmall), vBigNode2SmallPo, vSmallPi2BigNode ); Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin1(pObjSmall), vBigNode2SmallPo, vSmallPi2BigNode ); pObjSmall->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObjSmall), Aig_ObjChild1Copy(pObjSmall) ); } /**Function************************************************************* Synopsis [Extracts the network from the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManWindowInsertNodes( Aig_Man_t * p, Vec_Ptr_t * vNodes, Aig_Man_t * pWnd ) { Aig_Man_t * pNew; Vec_Ptr_t * vBigNode2SmallPo, * vSmallPi2BigNode; Vec_Ptr_t * vNodesPi, * vNodesPo; Aig_Obj_t * pObj; int i; // set mapping of small PIs into big nodes vSmallPi2BigNode = Vec_PtrStart( Aig_ManObjNumMax(pWnd) ); vNodesPi = Saig_ManWindowCollectPis( p, vNodes ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodesPi, pObj, i ) Vec_PtrWriteEntry( vSmallPi2BigNode, Aig_ManCi(pWnd, i)->Id, pObj ); assert( i == Saig_ManPiNum(pWnd) ); Vec_PtrFree( vNodesPi ); // set mapping of big nodes into small POs vBigNode2SmallPo = Vec_PtrStart( Aig_ManObjNumMax(p) ); vNodesPo = Saig_ManWindowCollectPos( p, vNodes, NULL ); Vec_PtrForEachEntry( Aig_Obj_t *, vNodesPo, pObj, i ) Vec_PtrWriteEntry( vBigNode2SmallPo, pObj->Id, Aig_ManCo(pWnd, i) ); assert( i == Saig_ManPoNum(pWnd) ); Vec_PtrFree( vNodesPo ); // create the new manager Aig_ManCleanData( p ); Aig_ManCleanData( pWnd ); pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); pNew->pName = Abc_UtilStrsav( p->pName ); pNew->pSpec = Abc_UtilStrsav( p->pSpec ); // map constant nodes pObj = Aig_ManConst1( p ); pObj->pData = Aig_ManConst1( pNew ); pObj = Aig_ManConst1( pWnd ); pObj->pData = Aig_ManConst1( pNew ); // create real PIs Aig_ManForEachCi( p, pObj, i ) if ( Saig_ObjIsPi(p, pObj) || !Aig_ObjIsTravIdCurrent(p, pObj) ) pObj->pData = Aig_ObjCreateCi(pNew); // create additional latch outputs Saig_ManForEachLo( pWnd, pObj, i ) pObj->pData = Aig_ObjCreateCi(pNew); // create internal nodes starting from the big Aig_ManForEachCo( p, pObj, i ) if ( Saig_ObjIsPo(p, pObj) || !Aig_ObjIsTravIdCurrent(p, pObj) ) { Saig_ManWindowInsertBig_rec( pNew, Aig_ObjFanin0(pObj), vBigNode2SmallPo, vSmallPi2BigNode ); pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } // create internal nodes starting from the small Saig_ManForEachLi( pWnd, pObj, i ) { Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin0(pObj), vBigNode2SmallPo, vSmallPi2BigNode ); pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); } Vec_PtrFree( vBigNode2SmallPo ); Vec_PtrFree( vSmallPi2BigNode ); // set the new number of registers assert( Aig_ManCiNum(pNew) - Aig_ManCiNum(p) == Aig_ManCoNum(pNew) - Aig_ManCoNum(p) ); Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) + (Aig_ManCiNum(pNew) - Aig_ManCiNum(p)) ); Aig_ManCleanup( pNew ); return pNew; } /**Function************************************************************* Synopsis [Find a good object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Saig_ManFindPivot( Aig_Man_t * p ) { Aig_Obj_t * pObj; int i, Counter; if ( Aig_ManRegNum(p) > 0 ) { if ( Aig_ManRegNum(p) == 1 ) return Saig_ManLo( p, 0 ); Saig_ManForEachLo( p, pObj, i ) { if ( i == Aig_ManRegNum(p)/2 ) return pObj; } } else { Counter = 0; assert( Aig_ManNodeNum(p) > 1 ); Aig_ManForEachNode( p, pObj, i ) { if ( Counter++ == Aig_ManNodeNum(p)/2 ) return pObj; } } return NULL; } /**Function************************************************************* Synopsis [Computes sequential window of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManWindowExtract( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist ) { Aig_Man_t * pWnd; Vec_Ptr_t * vNodes; Aig_ManFanoutStart( p ); vNodes = Saig_ManWindowOutline( p, pObj, nDist ); pWnd = Saig_ManWindowExtractNodes( p, vNodes ); Vec_PtrFree( vNodes ); Aig_ManFanoutStop( p ); return pWnd; } /**Function************************************************************* Synopsis [Computes sequential window of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManWindowInsert( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist, Aig_Man_t * pWnd ) { Aig_Man_t * pNew, * pWndTest; Vec_Ptr_t * vNodes; Aig_ManFanoutStart( p ); vNodes = Saig_ManWindowOutline( p, pObj, nDist ); pWndTest = Saig_ManWindowExtractNodes( p, vNodes ); if ( Saig_ManPiNum(pWndTest) != Saig_ManPiNum(pWnd) || Saig_ManPoNum(pWndTest) != Saig_ManPoNum(pWnd) ) { printf( "The window cannot be reinserted because PI/PO counts do not match.\n" ); Aig_ManStop( pWndTest ); Vec_PtrFree( vNodes ); Aig_ManFanoutStop( p ); return NULL; } Aig_ManStop( pWndTest ); Vec_PtrFree( vNodes ); // insert the nodes Aig_ManCleanData( p ); vNodes = Saig_ManWindowOutline( p, pObj, nDist ); pNew = Saig_ManWindowInsertNodes( p, vNodes, pWnd ); Vec_PtrFree( vNodes ); Aig_ManFanoutStop( p ); return pNew; } /**Function************************************************************* Synopsis [Tests the above computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManWindowTest( Aig_Man_t * p ) { int nDist = 3; Aig_Man_t * pWnd, * pNew; Aig_Obj_t * pPivot; pPivot = Saig_ManFindPivot( p ); assert( pPivot != NULL ); pWnd = Saig_ManWindowExtract( p, pPivot, nDist ); pNew = Saig_ManWindowInsert( p, pPivot, nDist, pWnd ); Aig_ManStop( pWnd ); return pNew; } /**Function************************************************************* Synopsis [Collects the nodes that are not linked to each other.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Saig_ManCollectedDiffNodes( Aig_Man_t * p0, Aig_Man_t * p1 ) { Vec_Ptr_t * vNodes; Aig_Obj_t * pObj0, * pObj1; int i; // collect nodes that are not linked Aig_ManIncrementTravId( p0 ); vNodes = Vec_PtrAlloc( 1000 ); Aig_ManForEachObj( p0, pObj0, i ) { pObj1 = Aig_ObjRepr( p0, pObj0 ); if ( pObj1 != NULL ) { assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) ); continue; } // mark and collect unmatched objects Aig_ObjSetTravIdCurrent( p0, pObj0 ); if ( Aig_ObjIsNode(pObj0) || Aig_ObjIsCi(pObj0) ) Vec_PtrPush( vNodes, pObj0 ); } // make sure LI/LO are labeled/unlabeled mutually Saig_ManForEachLiLo( p0, pObj0, pObj1, i ) assert( Aig_ObjIsTravIdCurrent(p0, pObj0) == Aig_ObjIsTravIdCurrent(p0, pObj1) ); return vNodes; } /**Function************************************************************* Synopsis [Creates PIs of the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManWindowCreatePis( Aig_Man_t * pNew, Aig_Man_t * p0, Aig_Man_t * p1, Vec_Ptr_t * vNodes0 ) { Aig_Obj_t * pObj, * pMatch, * pFanin; int i, Counter = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pObj, i ) { if ( Saig_ObjIsLo(p0, pObj) ) { pMatch = Saig_ObjLoToLi( p0, pObj ); pFanin = Aig_ObjFanin0(pMatch); if ( !Aig_ObjIsTravIdCurrent(p0, pFanin) && pFanin->pData == NULL ) { pFanin->pData = Aig_ObjCreateCi(pNew); pMatch = Aig_ObjRepr( p0, pFanin ); assert( pFanin == Aig_ObjRepr( p1, pMatch ) ); assert( pMatch != NULL ); pMatch->pData = pFanin->pData; Counter++; } } else { assert( Aig_ObjIsNode(pObj) ); pFanin = Aig_ObjFanin0(pObj); if ( !Aig_ObjIsTravIdCurrent(p0, pFanin) && pFanin->pData == NULL ) { pFanin->pData = Aig_ObjCreateCi(pNew); pMatch = Aig_ObjRepr( p0, pFanin ); assert( pFanin == Aig_ObjRepr( p1, pMatch ) ); assert( pMatch != NULL ); pMatch->pData = pFanin->pData; Counter++; } pFanin = Aig_ObjFanin1(pObj); if ( !Aig_ObjIsTravIdCurrent(p0, pFanin) && pFanin->pData == NULL ) { pFanin->pData = Aig_ObjCreateCi(pNew); pMatch = Aig_ObjRepr( p0, pFanin ); assert( pFanin == Aig_ObjRepr( p1, pMatch ) ); assert( pMatch != NULL ); pMatch->pData = pFanin->pData; Counter++; } } } // printf( "Added %d primary inputs.\n", Counter ); } /**Function************************************************************* Synopsis [Creates POs of the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Saig_ManWindowCreatePos( Aig_Man_t * pNew, Aig_Man_t * p0, Aig_Man_t * p1 ) { Aig_Obj_t * pObj0, * pObj1, * pMiter; Aig_Obj_t * pFanin0, * pFanin1; int i; Aig_ManForEachObj( p0, pObj0, i ) { if ( Aig_ObjIsTravIdCurrent(p0, pObj0) ) continue; if ( Aig_ObjIsConst1(pObj0) ) continue; if ( Aig_ObjIsCi(pObj0) ) continue; pObj1 = Aig_ObjRepr( p0, pObj0 ); assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) ); if ( Aig_ObjIsCo(pObj0) ) { pFanin0 = Aig_ObjFanin0(pObj0); pFanin1 = Aig_ObjFanin0(pObj1); assert( Aig_ObjIsTravIdCurrent(p0, pFanin0) == Aig_ObjIsTravIdCurrent(p1, pFanin1) ); if ( Aig_ObjIsTravIdCurrent(p0, pFanin0) ) { pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pFanin0->pData, (Aig_Obj_t *)pFanin1->pData ); Aig_ObjCreateCo( pNew, pMiter ); } } else { assert( Aig_ObjIsNode(pObj0) ); pFanin0 = Aig_ObjFanin0(pObj0); pFanin1 = Aig_ObjFanin0(pObj1); assert( Aig_ObjIsTravIdCurrent(p0, pFanin0) == Aig_ObjIsTravIdCurrent(p1, pFanin1) ); if ( Aig_ObjIsTravIdCurrent(p0, pFanin0) ) { pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pFanin0->pData, (Aig_Obj_t *)pFanin1->pData ); Aig_ObjCreateCo( pNew, pMiter ); } pFanin0 = Aig_ObjFanin1(pObj0); pFanin1 = Aig_ObjFanin1(pObj1); assert( Aig_ObjIsTravIdCurrent(p0, pFanin0) == Aig_ObjIsTravIdCurrent(p1, pFanin1) ); if ( Aig_ObjIsTravIdCurrent(p0, pFanin0) ) { pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pFanin0->pData, (Aig_Obj_t *)pFanin1->pData ); Aig_ObjCreateCo( pNew, pMiter ); } } } } /**Function************************************************************* Synopsis [Extracts the window AIG from the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Saig_ManWindowExtractMiter( Aig_Man_t * p0, Aig_Man_t * p1 ) { Aig_Man_t * pNew; Aig_Obj_t * pObj0, * pObj1, * pMatch0, * pMatch1; Vec_Ptr_t * vNodes0, * vNodes1; int i, nRegCount; // add matching of POs and LIs Saig_ManForEachPo( p0, pObj0, i ) { pObj1 = Aig_ManCo( p1, i ); Aig_ObjSetRepr( p0, pObj0, pObj1 ); Aig_ObjSetRepr( p1, pObj1, pObj0 ); } Saig_ManForEachLi( p0, pObj0, i ) { pMatch0 = Saig_ObjLiToLo( p0, pObj0 ); pMatch1 = Aig_ObjRepr( p0, pMatch0 ); if ( pMatch1 == NULL ) continue; assert( pMatch0 == Aig_ObjRepr( p1, pMatch1 ) ); pObj1 = Saig_ObjLoToLi( p1, pMatch1 ); Aig_ObjSetRepr( p0, pObj0, pObj1 ); Aig_ObjSetRepr( p1, pObj1, pObj0 ); } // clean the markings Aig_ManCleanData( p0 ); Aig_ManCleanData( p1 ); // collect nodes that are not linked vNodes0 = Saig_ManCollectedDiffNodes( p0, p1 ); vNodes1 = Saig_ManCollectedDiffNodes( p1, p0 ); // create the new manager pNew = Aig_ManStart( Vec_PtrSize(vNodes0) + Vec_PtrSize(vNodes1) ); pNew->pName = Abc_UtilStrsav( "wnd" ); pNew->pSpec = NULL; // map constant nodes pObj0 = Aig_ManConst1( p0 ); pObj0->pData = Aig_ManConst1( pNew ); pObj1 = Aig_ManConst1( p1 ); pObj1->pData = Aig_ManConst1( pNew ); // create real PIs Saig_ManWindowCreatePis( pNew, p0, p1, vNodes0 ); Saig_ManWindowCreatePis( pNew, p1, p0, vNodes1 ); // create register outputs Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pObj0, i ) { if ( Saig_ObjIsLo(p0, pObj0) ) pObj0->pData = Aig_ObjCreateCi(pNew); } Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pObj1, i ) { if ( Saig_ObjIsLo(p1, pObj1) ) pObj1->pData = Aig_ObjCreateCi(pNew); } // create internal nodes Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pObj0, i ) { if ( Aig_ObjIsNode(pObj0) ) pObj0->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj0), Aig_ObjChild1Copy(pObj0) ); } Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pObj1, i ) { if ( Aig_ObjIsNode(pObj1) ) pObj1->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj1), Aig_ObjChild1Copy(pObj1) ); } // create POs Saig_ManWindowCreatePos( pNew, p0, p1 ); // Saig_ManWindowCreatePos( pNew, p1, p0 ); // create register inputs nRegCount = 0; Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pObj0, i ) { if ( Saig_ObjIsLo(p0, pObj0) ) { pMatch0 = Saig_ObjLoToLi( p0, pObj0 ); Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch0) ); nRegCount++; } } Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pObj1, i ) { if ( Saig_ObjIsLo(p1, pObj1) ) { pMatch1 = Saig_ObjLoToLi( p1, pObj1 ); Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch1) ); nRegCount++; } } Aig_ManSetRegNum( pNew, nRegCount ); Aig_ManCleanup( pNew ); Vec_PtrFree( vNodes0 ); Vec_PtrFree( vNodes1 ); return pNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/aig/saig/saig_.c000066400000000000000000000026471477524141600157110ustar00rootroot00000000000000/**CFile**************************************************************** FileName [saig_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Sequential AIG package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: saig_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "saig.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/000077500000000000000000000000001477524141600137015ustar00rootroot00000000000000abc-0.52/src/base/abc/000077500000000000000000000000001477524141600144265ustar00rootroot00000000000000abc-0.52/src/base/abc/abc.h000066400000000000000000002567501477524141600153430ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abc.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [External declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abc.h,v 1.1 2008/05/14 22:13:11 wudenni Exp $] ***********************************************************************/ #ifndef ABC__base__abc__abc_h #define ABC__base__abc__abc_h //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// #include #include #include #include #include "misc/vec/vec.h" #include "aig/hop/hop.h" #include "aig/gia/gia.h" #include "misc/st/st.h" #include "misc/st/stmm.h" #include "misc/nm/nm.h" #include "misc/mem/mem.h" #include "misc/util/utilCex.h" #include "misc/extra/extra.h" //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_START // network types typedef enum { ABC_NTK_NONE = 0, // 0: unknown ABC_NTK_NETLIST, // 1: network with PIs/POs, latches, nodes, and nets ABC_NTK_LOGIC, // 2: network with PIs/POs, latches, and nodes ABC_NTK_STRASH, // 3: structurally hashed AIG (two input AND gates with c-attributes on edges) ABC_NTK_OTHER // 4: unused } Abc_NtkType_t; // network functionality typedef enum { ABC_FUNC_NONE = 0, // 0: unknown ABC_FUNC_SOP, // 1: sum-of-products ABC_FUNC_BDD, // 2: binary decision diagrams ABC_FUNC_AIG, // 3: and-inverter graphs ABC_FUNC_MAP, // 4: standard cell library ABC_FUNC_BLIFMV, // 5: BLIF-MV node functions ABC_FUNC_BLACKBOX, // 6: black box about which nothing is known ABC_FUNC_OTHER // 7: unused } Abc_NtkFunc_t; // Supported type/functionality combinations: /*------------------------------------------| | | SOP | BDD | AIG | Map | |-----------|-------|-------|-------|-------| | Netlist | x | | x | x | |-----------|-------|-------|-------|-------| | Logic | x | x | x | x | |-----------|-------|-------|-------|-------| | Strash | | | x | | --------------------------------------------|*/ // object types typedef enum { ABC_OBJ_NONE = 0, // 0: unknown ABC_OBJ_CONST1, // 1: constant 1 node (AIG only) ABC_OBJ_PI, // 2: primary input terminal ABC_OBJ_PO, // 3: primary output terminal ABC_OBJ_BI, // 4: box input terminal ABC_OBJ_BO, // 5: box output terminal ABC_OBJ_NET, // 6: net ABC_OBJ_NODE, // 7: node ABC_OBJ_LATCH, // 8: latch ABC_OBJ_WHITEBOX, // 9: box with known contents ABC_OBJ_BLACKBOX, // 10: box with unknown contents ABC_OBJ_NUMBER // 11: unused } Abc_ObjType_t; // latch initial values typedef enum { ABC_INIT_NONE = 0, // 0: unknown ABC_INIT_ZERO, // 1: zero ABC_INIT_ONE, // 2: one ABC_INIT_DC, // 3: don't-care ABC_INIT_OTHER // 4: unused } Abc_InitType_t; //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// //////////////////////////////////////////////////////////////////////// typedef struct Abc_Des_t_ Abc_Des_t; typedef struct Abc_Ntk_t_ Abc_Ntk_t; typedef struct Abc_Obj_t_ Abc_Obj_t; typedef struct Abc_Aig_t_ Abc_Aig_t; typedef struct Abc_ManTime_t_ Abc_ManTime_t; typedef struct Abc_ManCut_t_ Abc_ManCut_t; typedef struct Abc_Time_t_ Abc_Time_t; struct Abc_Time_t_ { float Rise; float Fall; }; struct Abc_Obj_t_ // 48/72 bytes (32-bits/64-bits) { Abc_Ntk_t * pNtk; // the host network Abc_Obj_t * pNext; // the next pointer in the hash table int Id; // the object ID unsigned Type : 4; // the object type unsigned fMarkA : 1; // the multipurpose mark unsigned fMarkB : 1; // the multipurpose mark unsigned fMarkC : 1; // the multipurpose mark unsigned fPhase : 1; // the flag to mark the phase of equivalent node unsigned fExor : 1; // marks AIG node that is a root of EXOR unsigned fPersist: 1; // marks the persistant AIG node unsigned fCompl0 : 1; // complemented attribute of the first fanin in the AIG unsigned fCompl1 : 1; // complemented attribute of the second fanin in the AIG unsigned Level : 20; // the level of the node Vec_Int_t vFanins; // the array of fanins Vec_Int_t vFanouts; // the array of fanouts union { void * pData; // the network specific data int iData; }; // (SOP, BDD, gate, equiv class, etc) union { void * pTemp; // temporary store for user's data Abc_Obj_t * pCopy; // the copy of this object int iTemp; float dTemp; }; }; struct Abc_Ntk_t_ { // general information Abc_NtkType_t ntkType; // type of the network Abc_NtkFunc_t ntkFunc; // functionality of the network char * pName; // the network name char * pSpec; // the name of the spec file if present Nm_Man_t * pManName; // name manager (stores names of objects) // components of the network Vec_Ptr_t * vObjs; // the array of all objects (net, nodes, latches, etc) Vec_Ptr_t * vPis; // the array of primary inputs Vec_Ptr_t * vPos; // the array of primary outputs Vec_Ptr_t * vCis; // the array of combinational inputs (PIs, latches) Vec_Ptr_t * vCos; // the array of combinational outputs (POs, asserts, latches) Vec_Ptr_t * vPios; // the array of PIOs Vec_Ptr_t * vBoxes; // the array of boxes Vec_Ptr_t * vLtlProperties; // the number of living objects int nObjCounts[ABC_OBJ_NUMBER]; // the number of objects by type int nObjs; // the number of live objs int nConstrs; // the number of constraints int nBarBufs; // the number of barrier buffers int nBarBufs2; // the number of barrier buffers // the backup network and the step number Abc_Ntk_t * pNetBackup; // the pointer to the previous backup network int iStep; // the generation number for the given network // hierarchy Abc_Des_t * pDesign; // design (hierarchical networks only) Abc_Ntk_t * pAltView; // alternative structural view of the network int fHieVisited; // flag to mark the visited network int fHiePath; // flag to mark the network on the path int Id; // model ID double dTemp; // temporary value // miscellaneous data members int nTravIds; // the unique traversal IDs of nodes Vec_Int_t vTravIds; // trav IDs of the objects Mem_Fixed_t * pMmObj; // memory manager for objects Mem_Step_t * pMmStep; // memory manager for arrays void * pManFunc; // functionality manager (AIG manager, BDD manager, or memory manager for SOPs) Abc_ManTime_t * pManTime; // the timing manager (for mapped networks) stores arrival/required times for all nodes void * pManCut; // the cut manager (for AIGs) stores information about the cuts computed for the nodes float AndGateDelay; // an average estimated delay of one AND gate int LevelMax; // maximum number of levels Vec_Int_t * vLevelsR; // level in the reverse topological order (for AIGs) Vec_Ptr_t * vSupps; // CO support information int * pModel; // counter-example (for miters) Abc_Cex_t * pSeqModel; // counter-example (for sequential miters) Vec_Ptr_t * vSeqModelVec; // vector of counter-examples (for sequential miters) Abc_Ntk_t * pExdc; // the EXDC network (if given) void * pExcare; // the EXDC network (if given) void * pData; // misc Abc_Ntk_t * pCopy; // copy of this network void * pBSMan; // application manager void * pSCLib; // SC library Vec_Int_t * vGates; // SC library gates Vec_Int_t * vPhases; // fanins phases in the mapped netlist char * pWLoadUsed; // wire load model used float * pLutTimes; // arrivals/requireds/slacks using LUT-delay model Vec_Ptr_t * vOnehots; // names of one-hot-encoded registers Vec_Int_t * vObjPerm; // permutation saved Vec_Int_t * vTopo; Vec_Ptr_t * vAttrs; // managers of various node attributes (node functionality, global BDDs, etc) Vec_Int_t * vNameIds; // name IDs Vec_Int_t * vFins; // obj/type info Vec_Int_t * vOrigNodeIds; // original node IDs }; struct Abc_Des_t_ { char * pName; // the name of the library void * pManFunc; // functionality manager for the nodes Vec_Ptr_t * vTops; // the array of top-level modules Vec_Ptr_t * vModules; // the array of modules st__table * tModules; // the table hashing module names into their networks Abc_Des_t * pLibrary; // the library used to map this design void * pGenlib; // the genlib library used to map this design }; //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// // transforming floats into ints and back static inline unsigned Abc_InfoRandomWord() { return ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())); } // #define RAND_MAX 0x7fff static inline void Abc_InfoRandom( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = Abc_InfoRandomWord(); } static inline void Abc_InfoClear( unsigned * p, int nWords ) { memset( p, 0, sizeof(unsigned) * nWords ); } static inline void Abc_InfoFill( unsigned * p, int nWords ) { memset( p, 0xff, sizeof(unsigned) * nWords );} static inline void Abc_InfoNot( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = ~p[i]; } static inline int Abc_InfoIsZero( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) if ( p[i] ) return 0; return 1; } static inline int Abc_InfoIsOne( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~p[i] ) return 0; return 1; } static inline void Abc_InfoCopy( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = q[i]; } static inline void Abc_InfoAnd( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] &= q[i]; } static inline void Abc_InfoOr( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] |= q[i]; } static inline void Abc_InfoXor( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] ^= q[i]; } static inline int Abc_InfoIsOrOne( unsigned * p, unsigned * q, int nWords ){ int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~(p[i] | q[i]) ) return 0; return 1; } static inline int Abc_InfoIsOrOne3( unsigned * p, unsigned * q, unsigned * r, int nWords ){ int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~(p[i] | q[i] | r[i]) ) return 0; return 1; } // checking the network type static inline int Abc_NtkIsNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_NETLIST; } static inline int Abc_NtkIsLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_LOGIC; } static inline int Abc_NtkIsStrash( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_STRASH; } static inline int Abc_NtkHasSop( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP; } static inline int Abc_NtkHasBdd( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD; } static inline int Abc_NtkHasAig( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG; } static inline int Abc_NtkHasMapping( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP; } static inline int Abc_NtkHasBlifMv( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLIFMV; } static inline int Abc_NtkHasBlackbox( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLACKBOX; } static inline int Abc_NtkIsSopNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_NTK_NETLIST; } static inline int Abc_NtkIsBddNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD && pNtk->ntkType == ABC_NTK_NETLIST; } static inline int Abc_NtkIsAigNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG && pNtk->ntkType == ABC_NTK_NETLIST; } static inline int Abc_NtkIsMappedNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_NTK_NETLIST; } static inline int Abc_NtkIsBlifMvNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLIFMV && pNtk->ntkType == ABC_NTK_NETLIST; } static inline int Abc_NtkIsSopLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_NTK_LOGIC ; } static inline int Abc_NtkIsBddLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD && pNtk->ntkType == ABC_NTK_LOGIC ; } static inline int Abc_NtkIsAigLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG && pNtk->ntkType == ABC_NTK_LOGIC ; } static inline int Abc_NtkIsMappedLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_NTK_LOGIC ; } // reading data members of the network static inline char * Abc_NtkName( Abc_Ntk_t * pNtk ) { return pNtk->pName; } static inline char * Abc_NtkSpec( Abc_Ntk_t * pNtk ) { return pNtk->pSpec; } static inline Abc_Ntk_t * Abc_NtkExdc( Abc_Ntk_t * pNtk ) { return pNtk->pExdc; } static inline Abc_Ntk_t * Abc_NtkBackup( Abc_Ntk_t * pNtk ) { return pNtk->pNetBackup; } static inline int Abc_NtkStep ( Abc_Ntk_t * pNtk ) { return pNtk->iStep; } // setting data members of the network static inline void Abc_NtkSetName ( Abc_Ntk_t * pNtk, char * pName ) { pNtk->pName = pName; } static inline void Abc_NtkSetSpec ( Abc_Ntk_t * pNtk, char * pName ) { pNtk->pSpec = pName; } static inline void Abc_NtkSetBackup( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNetBackup ) { pNtk->pNetBackup = pNetBackup; } static inline void Abc_NtkSetStep ( Abc_Ntk_t * pNtk, int iStep ) { pNtk->iStep = iStep; } // getting the number of objects static inline int Abc_NtkObjNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjs; } static inline int Abc_NtkObjNumMax( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vObjs); } static inline int Abc_NtkPiNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vPis); } static inline int Abc_NtkPoNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vPos); } static inline int Abc_NtkCiNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vCis); } static inline int Abc_NtkCoNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vCos); } static inline int Abc_NtkBoxNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vBoxes); } static inline int Abc_NtkBiNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BI]; } static inline int Abc_NtkBoNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BO]; } static inline int Abc_NtkNetNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_NET]; } static inline int Abc_NtkNodeNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_NODE]; } static inline int Abc_NtkLatchNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_LATCH]; } static inline int Abc_NtkWhiteboxNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_WHITEBOX]; } static inline int Abc_NtkBlackboxNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BLACKBOX]; } static inline int Abc_NtkIsComb( Abc_Ntk_t * pNtk ) { return Abc_NtkLatchNum(pNtk) == 0; } static inline int Abc_NtkHasOnlyLatchBoxes(Abc_Ntk_t * pNtk ){ return Abc_NtkLatchNum(pNtk) == Abc_NtkBoxNum(pNtk); } static inline int Abc_NtkConstrNum( Abc_Ntk_t * pNtk ) { return pNtk->nConstrs; } // creating simple objects extern ABC_DLL Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ); static inline Abc_Obj_t * Abc_NtkCreatePi( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_PI ); } static inline Abc_Obj_t * Abc_NtkCreatePo( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_PO ); } static inline Abc_Obj_t * Abc_NtkCreateBi( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BI ); } static inline Abc_Obj_t * Abc_NtkCreateBo( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BO ); } static inline Abc_Obj_t * Abc_NtkCreateNet( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NET ); } static inline Abc_Obj_t * Abc_NtkCreateNode( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NODE ); } static inline Abc_Obj_t * Abc_NtkCreateLatch( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_LATCH ); } static inline Abc_Obj_t * Abc_NtkCreateWhitebox( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_WHITEBOX ); } static inline Abc_Obj_t * Abc_NtkCreateBlackbox( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BLACKBOX ); } // reading objects static inline Abc_Obj_t * Abc_NtkObj( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vObjs, i ); } static inline Abc_Obj_t * Abc_NtkPi( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPis, i ); } static inline Abc_Obj_t * Abc_NtkPo( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPos, i ); } static inline Abc_Obj_t * Abc_NtkCi( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, i ); } static inline Abc_Obj_t * Abc_NtkCo( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, i ); } static inline Abc_Obj_t * Abc_NtkBox( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vBoxes, i ); } // working with complemented attributes of objects static inline int Abc_ObjIsComplement( Abc_Obj_t * p ) { return (int )((ABC_PTRUINT_T)p & (ABC_PTRUINT_T)01); } static inline Abc_Obj_t * Abc_ObjRegular( Abc_Obj_t * p ) { return (Abc_Obj_t *)((ABC_PTRUINT_T)p & ~(ABC_PTRUINT_T)01); } static inline Abc_Obj_t * Abc_ObjNot( Abc_Obj_t * p ) { return (Abc_Obj_t *)((ABC_PTRUINT_T)p ^ (ABC_PTRUINT_T)01); } static inline Abc_Obj_t * Abc_ObjNotCond( Abc_Obj_t * p, int c ) { return (Abc_Obj_t *)((ABC_PTRUINT_T)p ^ (ABC_PTRUINT_T)(c!=0)); } // reading data members of the object static inline unsigned Abc_ObjType( Abc_Obj_t * pObj ) { return pObj->Type; } static inline unsigned Abc_ObjId( Abc_Obj_t * pObj ) { return pObj->Id; } static inline int Abc_ObjLevel( Abc_Obj_t * pObj ) { return pObj->Level; } static inline Vec_Int_t * Abc_ObjFaninVec( Abc_Obj_t * pObj ) { return &pObj->vFanins; } static inline Vec_Int_t * Abc_ObjFanoutVec( Abc_Obj_t * pObj ) { return &pObj->vFanouts; } static inline Abc_Obj_t * Abc_ObjCopy( Abc_Obj_t * pObj ) { return pObj->pCopy; } static inline Abc_Ntk_t * Abc_ObjNtk( Abc_Obj_t * pObj ) { return pObj->pNtk; } static inline Abc_Ntk_t * Abc_ObjModel( Abc_Obj_t * pObj ) { assert( pObj->Type == ABC_OBJ_WHITEBOX ); return (Abc_Ntk_t *)pObj->pData; } static inline void * Abc_ObjData( Abc_Obj_t * pObj ) { return pObj->pData; } static inline Abc_Obj_t * Abc_ObjEquiv( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pData; } static inline Abc_Obj_t * Abc_ObjCopyCond( Abc_Obj_t * pObj ) { return Abc_ObjRegular(pObj)->pCopy? Abc_ObjNotCond(Abc_ObjRegular(pObj)->pCopy, Abc_ObjIsComplement(pObj)) : NULL; } // setting data members of the network static inline void Abc_ObjSetLevel( Abc_Obj_t * pObj, int Level ) { pObj->Level = Level; } static inline void Abc_ObjSetCopy( Abc_Obj_t * pObj, Abc_Obj_t * pCopy ) { pObj->pCopy = pCopy; } static inline void Abc_ObjSetData( Abc_Obj_t * pObj, void * pData ) { pObj->pData = pData; } // checking the object type static inline int Abc_ObjIsNone( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NONE; } static inline int Abc_ObjIsPi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI; } static inline int Abc_ObjIsPo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO; } static inline int Abc_ObjIsBi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BI; } static inline int Abc_ObjIsBo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BO; } static inline int Abc_ObjIsCi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI || pObj->Type == ABC_OBJ_BO; } static inline int Abc_ObjIsCo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO || pObj->Type == ABC_OBJ_BI; } static inline int Abc_ObjIsTerm( Abc_Obj_t * pObj ) { return Abc_ObjIsCi(pObj) || Abc_ObjIsCo(pObj); } static inline int Abc_ObjIsNet( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NET; } static inline int Abc_ObjIsNode( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NODE; } static inline int Abc_ObjIsLatch( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_LATCH; } static inline int Abc_ObjIsBox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_LATCH || pObj->Type == ABC_OBJ_WHITEBOX || pObj->Type == ABC_OBJ_BLACKBOX; } static inline int Abc_ObjIsWhitebox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_WHITEBOX;} static inline int Abc_ObjIsBlackbox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BLACKBOX;} static inline int Abc_ObjIsBarBuf( Abc_Obj_t * pObj ) { return Abc_NtkHasMapping(pObj->pNtk) && Abc_ObjIsNode(pObj) && Vec_IntSize(&pObj->vFanins) == 1 && pObj->pData == NULL; } static inline void Abc_ObjBlackboxToWhitebox( Abc_Obj_t * pObj ) { assert( Abc_ObjIsBlackbox(pObj) ); pObj->Type = ABC_OBJ_WHITEBOX; pObj->pNtk->nObjCounts[ABC_OBJ_BLACKBOX]--; pObj->pNtk->nObjCounts[ABC_OBJ_WHITEBOX]++; } // working with fanin/fanout edges static inline int Abc_ObjFaninNum( Abc_Obj_t * pObj ) { return pObj->vFanins.nSize; } static inline int Abc_ObjFanoutNum( Abc_Obj_t * pObj ) { return pObj->vFanouts.nSize; } static inline int Abc_ObjFaninId( Abc_Obj_t * pObj, int i) { return pObj->vFanins.pArray[i]; } static inline int Abc_ObjFaninId0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0]; } static inline int Abc_ObjFaninId1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1]; } static inline int Abc_ObjFanoutEdgeNum( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ) { assert( Abc_NtkHasAig(pObj->pNtk) ); if ( Abc_ObjFaninId0(pFanout) == pObj->Id ) return 0; if ( Abc_ObjFaninId1(pFanout) == pObj->Id ) return 1; assert( 0 ); return -1; } static inline Abc_Obj_t * Abc_ObjFanout( Abc_Obj_t * pObj, int i ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[i] ]; } static inline Abc_Obj_t * Abc_ObjFanout0( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[0] ]; } static inline Abc_Obj_t * Abc_ObjFanin( Abc_Obj_t * pObj, int i ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[i] ]; } static inline Abc_Obj_t * Abc_ObjFanin0( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[0] ]; } static inline Abc_Obj_t * Abc_ObjFanin1( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[1] ]; } static inline Abc_Obj_t * Abc_ObjFanin0Ntk( Abc_Obj_t * pObj ) { return (Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanin0(pObj) : pObj); } static inline Abc_Obj_t * Abc_ObjFanout0Ntk( Abc_Obj_t * pObj ) { return (Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanout0(pObj) : pObj); } static inline int Abc_ObjFaninC0( Abc_Obj_t * pObj ) { return pObj->fCompl0; } static inline int Abc_ObjFaninC1( Abc_Obj_t * pObj ) { return pObj->fCompl1; } static inline int Abc_ObjFaninC( Abc_Obj_t * pObj, int i ) { assert( i >=0 && i < 2 ); return i? pObj->fCompl1 : pObj->fCompl0; } static inline void Abc_ObjSetFaninC( Abc_Obj_t * pObj, int i ){ assert( i >=0 && i < 2 ); if ( i ) pObj->fCompl1 = 1; else pObj->fCompl0 = 1; } static inline void Abc_ObjXorFaninC( Abc_Obj_t * pObj, int i ){ assert( i >=0 && i < 2 ); if ( i ) pObj->fCompl1^= 1; else pObj->fCompl0^= 1; } static inline Abc_Obj_t * Abc_ObjChild( Abc_Obj_t * pObj, int i ) { return Abc_ObjNotCond( Abc_ObjFanin(pObj,i), Abc_ObjFaninC(pObj,i) );} static inline Abc_Obj_t * Abc_ObjChild0( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) ); } static inline Abc_Obj_t * Abc_ObjChild1( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin1(pObj), Abc_ObjFaninC1(pObj) ); } static inline Abc_Obj_t * Abc_ObjChildCopy( Abc_Obj_t * pObj, int i ){ return Abc_ObjNotCond( Abc_ObjFanin(pObj,i)->pCopy, Abc_ObjFaninC(pObj,i) ); } static inline Abc_Obj_t * Abc_ObjChild0Copy( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); } static inline Abc_Obj_t * Abc_ObjChild1Copy( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC1(pObj) ); } static inline Abc_Obj_t * Abc_ObjChild0Data( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Abc_ObjFanin0(pObj)->pData, Abc_ObjFaninC0(pObj) ); } static inline Abc_Obj_t * Abc_ObjChild1Data( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Abc_ObjFanin1(pObj)->pData, Abc_ObjFaninC1(pObj) ); } static inline Abc_Obj_t * Abc_ObjFromLit( Abc_Ntk_t * p, int iLit ) { return Abc_ObjNotCond( Abc_NtkObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit) ); } static inline int Abc_ObjToLit( Abc_Obj_t * p ) { return Abc_Var2Lit( Abc_ObjId(Abc_ObjRegular(p)), Abc_ObjIsComplement(p) ); } static inline int Abc_ObjFaninPhase( Abc_Obj_t * p, int i ) { assert(p->pNtk->vPhases); assert( i >= 0 && i < Abc_ObjFaninNum(p) ); return (Vec_IntEntry(p->pNtk->vPhases, Abc_ObjId(p)) >> i) & 1; } static inline void Abc_ObjFaninFlipPhase( Abc_Obj_t * p,int i){ assert(p->pNtk->vPhases); assert( i >= 0 && i < Abc_ObjFaninNum(p) ); *Vec_IntEntryP(p->pNtk->vPhases, Abc_ObjId(p)) ^= (1 << i); } // checking the AIG node types static inline int Abc_AigNodeIsConst( Abc_Obj_t * pNode ) { assert(Abc_NtkIsStrash(Abc_ObjRegular(pNode)->pNtk)); return Abc_ObjRegular(pNode)->Type == ABC_OBJ_CONST1; } static inline int Abc_AigNodeIsAnd( Abc_Obj_t * pNode ) { assert(!Abc_ObjIsComplement(pNode)); assert(Abc_NtkIsStrash(pNode->pNtk)); return Abc_ObjFaninNum(pNode) == 2; } static inline int Abc_AigNodeIsChoice( Abc_Obj_t * pNode ) { assert(!Abc_ObjIsComplement(pNode)); assert(Abc_NtkIsStrash(pNode->pNtk)); return pNode->pData != NULL && Abc_ObjFanoutNum(pNode) > 0; } // handling persistent nodes static inline int Abc_NodeIsPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); return pNode->fPersist; } static inline void Abc_NodeSetPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); pNode->fPersist = 1; } static inline void Abc_NodeClearPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); pNode->fPersist = 0; } // working with the traversal ID static inline void Abc_NtkIncrementTravId( Abc_Ntk_t * p ) { if (!p->vTravIds.pArray) Vec_IntFill(&p->vTravIds, Abc_NtkObjNumMax(p)+500, 0); p->nTravIds++; assert(p->nTravIds < (1<<30)); } static inline int Abc_NodeTravId( Abc_Obj_t * p ) { return Vec_IntGetEntry(&Abc_ObjNtk(p)->vTravIds, Abc_ObjId(p)); } static inline void Abc_NodeSetTravId( Abc_Obj_t * p, int TravId ) { Vec_IntSetEntry(&Abc_ObjNtk(p)->vTravIds, Abc_ObjId(p), TravId ); } static inline void Abc_NodeSetTravIdCurrent( Abc_Obj_t * p ) { Abc_NodeSetTravId( p, Abc_ObjNtk(p)->nTravIds ); } static inline void Abc_NodeSetTravIdPrevious( Abc_Obj_t * p ) { Abc_NodeSetTravId( p, Abc_ObjNtk(p)->nTravIds-1 ); } static inline int Abc_NodeIsTravIdCurrent( Abc_Obj_t * p ) { return (Abc_NodeTravId(p) == Abc_ObjNtk(p)->nTravIds); } static inline int Abc_NodeIsTravIdPrevious( Abc_Obj_t * p ) { return (Abc_NodeTravId(p) == Abc_ObjNtk(p)->nTravIds-1); } static inline void Abc_NodeSetTravIdCurrentId( Abc_Ntk_t * p, int i) { Vec_IntSetEntry(&p->vTravIds, i, p->nTravIds ); } static inline int Abc_NodeIsTravIdCurrentId( Abc_Ntk_t * p, int i) { return (Vec_IntGetEntry(&p->vTravIds, i) == p->nTravIds); } // checking initial state of the latches static inline void Abc_LatchSetInitNone( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_NONE; } static inline void Abc_LatchSetInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_ZERO; } static inline void Abc_LatchSetInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_ONE; } static inline void Abc_LatchSetInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_DC; } static inline int Abc_LatchIsInitNone( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_NONE; } static inline int Abc_LatchIsInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_ZERO; } static inline int Abc_LatchIsInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_ONE; } static inline int Abc_LatchIsInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_DC; } static inline int Abc_LatchInit( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return (int)(ABC_PTRINT_T)pLatch->pData; } // global BDDs of the nodes static inline void * Abc_NtkGlobalBdd( Abc_Ntk_t * pNtk ) { return Vec_PtrEntry(pNtk->vAttrs, VEC_ATTR_GLOBAL_BDD); } static inline void * Abc_NtkGlobalBddMan( Abc_Ntk_t * pNtk ) { return Vec_AttMan( (Vec_Att_t *)Abc_NtkGlobalBdd(pNtk) ); } static inline void ** Abc_NtkGlobalBddArray( Abc_Ntk_t * pNtk ) { return Vec_AttArray( (Vec_Att_t *)Abc_NtkGlobalBdd(pNtk) ); } static inline void * Abc_ObjGlobalBdd( Abc_Obj_t * pObj ) { return Vec_AttEntry( (Vec_Att_t *)Abc_NtkGlobalBdd(pObj->pNtk), pObj->Id ); } static inline void Abc_ObjSetGlobalBdd( Abc_Obj_t * pObj, void * bF ) { Vec_AttWriteEntry( (Vec_Att_t *)Abc_NtkGlobalBdd(pObj->pNtk), pObj->Id, bF ); } // MV variables of the nodes static inline void * Abc_NtkMvVar( Abc_Ntk_t * pNtk ) { return Vec_PtrEntry(pNtk->vAttrs, VEC_ATTR_MVVAR); } static inline void * Abc_NtkMvVarMan( Abc_Ntk_t * pNtk ) { return Abc_NtkMvVar(pNtk)? Vec_AttMan( (Vec_Att_t *)Abc_NtkMvVar(pNtk) ) : NULL; } static inline void * Abc_ObjMvVar( Abc_Obj_t * pObj ) { return Abc_NtkMvVar(pObj->pNtk)? Vec_AttEntry( (Vec_Att_t *)Abc_NtkMvVar(pObj->pNtk), pObj->Id ) : NULL; } static inline int Abc_ObjMvVarNum( Abc_Obj_t * pObj ) { return (Abc_NtkMvVar(pObj->pNtk) && Abc_ObjMvVar(pObj))? *((int*)Abc_ObjMvVar(pObj)) : 2; } static inline void Abc_ObjSetMvVar( Abc_Obj_t * pObj, void * pV) { Vec_AttWriteEntry( (Vec_Att_t *)Abc_NtkMvVar(pObj->pNtk), pObj->Id, pV ); } //////////////////////////////////////////////////////////////////////// /// ITERATORS /// //////////////////////////////////////////////////////////////////////// // objects of the network #define Abc_NtkForEachObj( pNtk, pObj, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pObj) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ if ( (pObj) == NULL ) {} else #define Abc_NtkForEachObjReverse( pNtk, pNode, i ) \ for ( i = Vec_PtrSize((pNtk)->vObjs) - 1; (i >= 0) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i-- ) \ if ( (pNode) == NULL ) {} else #define Abc_NtkForEachObjVec( vIds, pNtk, pObj, i ) \ for ( i = 0; i < Vec_IntSize(vIds) && (((pObj) = Abc_NtkObj(pNtk, Vec_IntEntry(vIds,i))), 1); i++ ) \ if ( (pObj) == NULL ) {} else #define Abc_NtkForEachObjVecStart( vIds, pNtk, pObj, i, Start ) \ for ( i = Start; i < Vec_IntSize(vIds) && (((pObj) = Abc_NtkObj(pNtk, Vec_IntEntry(vIds,i))), 1); i++ ) \ if ( (pObj) == NULL ) {} else #define Abc_NtkForEachNet( pNtk, pNet, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNet) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ if ( (pNet) == NULL || !Abc_ObjIsNet(pNet) ) {} else #define Abc_NtkForEachNode( pNtk, pNode, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) ) {} else #define Abc_NtkForEachNodeNotBarBuf( pNtk, pNode, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) || Abc_ObjIsBarBuf(pNode) ) {} else #define Abc_NtkForEachNode1( pNtk, pNode, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) || !Abc_ObjFaninNum(pNode) ) {} else #define Abc_NtkForEachNodeNotBarBuf1( pNtk, pNode, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) || !Abc_ObjFaninNum(pNode) || Abc_ObjIsBarBuf(pNode) ) {} else #define Abc_NtkForEachNodeReverse( pNtk, pNode, i ) \ for ( i = Vec_PtrSize((pNtk)->vObjs) - 1; (i >= 0) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i-- ) \ if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) ) {} else #define Abc_NtkForEachNodeReverse1( pNtk, pNode, i ) \ for ( i = Vec_PtrSize((pNtk)->vObjs) - 1; (i >= 0) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i-- ) \ if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) || !Abc_ObjFaninNum(pNode) ) {} else #define Abc_NtkForEachBarBuf( pNtk, pNode, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ if ( (pNode) == NULL || !Abc_ObjIsBarBuf(pNode) ) {} else #define Abc_NtkForEachGate( pNtk, pNode, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ if ( (pNode) == NULL || !Abc_ObjIsGate(pNode) ) {} else #define Abc_AigForEachAnd( pNtk, pNode, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ if ( (pNode) == NULL || !Abc_AigNodeIsAnd(pNode) ) {} else #define Abc_NtkForEachNodeCi( pNtk, pNode, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ if ( (pNode) == NULL || (!Abc_ObjIsNode(pNode) && !Abc_ObjIsCi(pNode)) ) {} else #define Abc_NtkForEachNodeCo( pNtk, pNode, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ if ( (pNode) == NULL || (!Abc_ObjIsNode(pNode) && !Abc_ObjIsCo(pNode)) ) {} else // various boxes #define Abc_NtkForEachBox( pNtk, pObj, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) #define Abc_NtkForEachLatch( pNtk, pObj, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \ if ( !Abc_ObjIsLatch(pObj) ) {} else #define Abc_NtkForEachLatchInput( pNtk, pObj, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)); i++ ) \ if ( !(Abc_ObjIsLatch(Abc_NtkBox(pNtk, i)) && (((pObj) = Abc_ObjFanin0(Abc_NtkBox(pNtk, i))), 1)) ) {} else #define Abc_NtkForEachLatchOutput( pNtk, pObj, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)); i++ ) \ if ( !(Abc_ObjIsLatch(Abc_NtkBox(pNtk, i)) && (((pObj) = Abc_ObjFanout0(Abc_NtkBox(pNtk, i))), 1)) ) {} else #define Abc_NtkForEachWhitebox( pNtk, pObj, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \ if ( !Abc_ObjIsWhitebox(pObj) ) {} else #define Abc_NtkForEachBlackbox( pNtk, pObj, i ) \ for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \ if ( !Abc_ObjIsBlackbox(pObj) ) {} else // inputs and outputs #define Abc_NtkForEachPi( pNtk, pPi, i ) \ for ( i = 0; (i < Abc_NtkPiNum(pNtk)) && (((pPi) = Abc_NtkPi(pNtk, i)), 1); i++ ) #define Abc_NtkForEachCi( pNtk, pCi, i ) \ for ( i = 0; (i < Abc_NtkCiNum(pNtk)) && (((pCi) = Abc_NtkCi(pNtk, i)), 1); i++ ) #define Abc_NtkForEachPo( pNtk, pPo, i ) \ for ( i = 0; (i < Abc_NtkPoNum(pNtk)) && (((pPo) = Abc_NtkPo(pNtk, i)), 1); i++ ) #define Abc_NtkForEachCo( pNtk, pCo, i ) \ for ( i = 0; (i < Abc_NtkCoNum(pNtk)) && (((pCo) = Abc_NtkCo(pNtk, i)), 1); i++ ) #define Abc_NtkForEachLiPo( pNtk, pCo, i ) \ for ( i = 0; (i < Abc_NtkCoNum(pNtk)) && (((pCo) = Abc_NtkCo(pNtk, i < pNtk->nBarBufs ? Abc_NtkCoNum(pNtk) - pNtk->nBarBufs + i : i - pNtk->nBarBufs)), 1); i++ ) // fanin and fanouts #define Abc_ObjForEachFanin( pObj, pFanin, i ) \ for ( i = 0; (i < Abc_ObjFaninNum(pObj)) && (((pFanin) = Abc_ObjFanin(pObj, i)), 1); i++ ) #define Abc_ObjForEachFanout( pObj, pFanout, i ) \ for ( i = 0; (i < Abc_ObjFanoutNum(pObj)) && (((pFanout) = Abc_ObjFanout(pObj, i)), 1); i++ ) #define Abc_ObjForEachFaninId( pObj, iFanin, i ) \ for ( i = 0; (i < Abc_ObjFaninNum(pObj)) && (((iFanin) = Abc_ObjFaninId(pObj, i)), 1); i++ ) #define Abc_ObjForEachFanoutId( pObj, iFanout, i ) \ for ( i = 0; (i < Abc_ObjFanoutNum(pObj)) && (((iFanout) = Abc_ObjFanoutId(pObj, i)), 1); i++ ) // cubes and literals #define Abc_CubeForEachVar( pCube, Value, i ) \ for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); i++ ) #define Abc_SopForEachCube( pSop, nFanins, pCube ) \ for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 ) #define Abc_SopForEachCubePair( pSop, nFanins, pCube, pCube2 ) \ Abc_SopForEachCube( pSop, nFanins, pCube ) \ Abc_SopForEachCube( pCube + (nFanins) + 3, nFanins, pCube2 ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// /*=== abcAig.c ==========================================================*/ extern ABC_DLL Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_AigFree( Abc_Aig_t * pMan ); extern ABC_DLL int Abc_AigCleanup( Abc_Aig_t * pMan ); extern ABC_DLL int Abc_AigCheck( Abc_Aig_t * pMan ); extern ABC_DLL int Abc_AigLevel( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); extern ABC_DLL Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); extern ABC_DLL Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType ); extern ABC_DLL Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType ); extern ABC_DLL Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); 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 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 ); extern ABC_DLL int Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode ); extern ABC_DLL void Abc_AigPrintNode( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot ); extern ABC_DLL void Abc_AigCheckFaninOrder( Abc_Aig_t * pMan ); extern ABC_DLL void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Abc_AigUpdateStart( Abc_Aig_t * pMan, Vec_Ptr_t ** pvUpdatedNets ); extern ABC_DLL void Abc_AigUpdateStop( Abc_Aig_t * pMan ); extern ABC_DLL void Abc_AigUpdateReset( Abc_Aig_t * pMan ); /*=== abcAttach.c ==========================================================*/ extern ABC_DLL int Abc_NtkAttach( Abc_Ntk_t * pNtk ); /*=== abcBarBuf.c ==========================================================*/ extern ABC_DLL Abc_Ntk_t * Abc_NtkToBarBufs( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkFromBarBufs( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkBarBufsToBuffers( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkBarBufsFromBuffers( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtk ); /*=== abcBlifMv.c ==========================================================*/ extern ABC_DLL void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues ); extern ABC_DLL Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic ); extern ABC_DLL int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk ); extern ABC_DLL char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ); extern ABC_DLL int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ); /*=== abcBalance.c ==========================================================*/ extern ABC_DLL Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, int fDuplicate, int fSelective, int fUpdateLevel ); /*=== abcCheck.c ==========================================================*/ extern ABC_DLL int Abc_NtkCheck( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkCheckRead( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkDoCheck( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ); extern ABC_DLL int Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb ); extern ABC_DLL int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk ); /*=== abcCollapse.c ==========================================================*/ extern ABC_DLL Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fReverse, int 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 ==========================================================*/ extern ABC_DLL void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ); extern ABC_DLL void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ); extern ABC_DLL void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fFirst ); extern ABC_DLL void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ); extern ABC_DLL void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj ); /*=== abcDar.c ============================================================*/ extern ABC_DLL int Abc_NtkPhaseFrameNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkDarPrintCone( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkBalanceExor( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ); extern ABC_DLL Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchConst, int fLatchEqual, int fSaveNames, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose ); /*=== abcDelay.c ==========================================================*/ extern ABC_DLL float Abc_NtkDelayTraceLut( Abc_Ntk_t * pNtk, int fUseLutLib ); /*=== abcDfs.c ==========================================================*/ extern ABC_DLL Vec_Ptr_t * Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll ); extern ABC_DLL Vec_Ptr_t * Abc_NtkDfs2( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsReverseNodesContained( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsSeq( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll ); extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsIterNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ); extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsHie( Abc_Ntk_t * pNtk, int fCollectAll ); extern ABC_DLL int Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsWithBoxes( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Abc_NtkSupport( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); extern ABC_DLL Vec_Int_t * Abc_NtkNodeSupportInt( Abc_Ntk_t * pNtk, int iCo ); extern ABC_DLL int Abc_NtkFunctionalIso( Abc_Ntk_t * pNtk, int iCo1, int iCo2, int fCommon ); extern ABC_DLL Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos ); extern ABC_DLL Vec_Ptr_t * Abc_AigDfsMap( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, int fTfi ); extern ABC_DLL Vec_Vec_t * Abc_NtkLevelize( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkLevel( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkLevelR( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkIsAcyclicWithBoxes( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis ); /*=== abcExact.c ==========================================================*/ extern ABC_DLL int Abc_ExactInputNum(); extern ABC_DLL int Abc_ExactIsRunning(); extern ABC_DLL Abc_Obj_t * Abc_ExactBuildNode( word * pTruth, int nVars, int * pArrTimeProfile, Abc_Obj_t ** pFanins, Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrivalTimes, int nBTLimit, int nStartGates, int fVerbose ); /*=== abcFanio.c ==========================================================*/ extern ABC_DLL void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ); extern ABC_DLL void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ); extern ABC_DLL void Abc_ObjRemoveFanins( Abc_Obj_t * pObj ); extern ABC_DLL void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew ); extern ABC_DLL void Abc_ObjPatchFanoutFanin( Abc_Obj_t * pObj, int iObjNew ); 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 ); extern ABC_DLL void Abc_NtkSortSops( Abc_Ntk_t * pNtk ); /*=== abcFraig.c ==========================================================*/ extern ABC_DLL Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ); extern ABC_DLL void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ); extern ABC_DLL Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkFraigStore( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkFraigRestore( int nPatsRand, int nPatsDyna, int nBTLimit ); 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, 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 ); extern ABC_DLL int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ); extern ABC_DLL Gia_Man_t * Abc_NtkAigToGia( Abc_Ntk_t * p, int fGiaSimple ); extern ABC_DLL int Abc_NtkMapToSopUsingLibrary( Abc_Ntk_t * pNtk, void* library ); extern ABC_DLL int Abc_NtkMapToSop( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit ); extern ABC_DLL int Abc_NtkToBdd( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkToAig( Abc_Ntk_t * pNtk ); /*=== abcHaig.c ==========================================================*/ extern ABC_DLL int Abc_NtkHaigStart( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkHaigStop( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkHaigUse( Abc_Ntk_t * pNtk ); /*=== abcHie.c ==========================================================*/ extern ABC_DLL Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL ); extern ABC_DLL void Abc_NtkPrintBoxInfo( Abc_Ntk_t * pNtk ); /*=== abcHieGia.c ==========================================================*/ extern ABC_DLL Gia_Man_t * Abc_NtkFlattenHierarchyGia( Abc_Ntk_t * pNtk, Vec_Ptr_t ** pvBuffers, int fVerbose ); extern ABC_DLL void Abc_NtkInsertHierarchyGia( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNew, int fVerbose ); /*=== abcLatch.c ==========================================================*/ extern ABC_DLL int Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch ); extern ABC_DLL int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Int_t * Abc_NtkCollectLatchValues( Abc_Ntk_t * pNtk ); extern ABC_DLL char * Abc_NtkCollectLatchValuesStr( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ); extern ABC_DLL Abc_Obj_t * Abc_NtkAddLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pDriver, Abc_InitType_t Init ); extern ABC_DLL void Abc_NtkConvertDcLatches( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Abc_NtkConverLatchNamesIntoNumbers( Abc_Ntk_t * pNtk ); /*=== abcLib.c ==========================================================*/ extern ABC_DLL Abc_Des_t * Abc_DesCreate( char * pName ); extern ABC_DLL void Abc_DesCleanManPointer( Abc_Des_t * p, void * pMan ); extern ABC_DLL void Abc_DesFree( Abc_Des_t * p, Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Des_t * Abc_DesDup( Abc_Des_t * p ); extern ABC_DLL void Abc_DesPrint( Abc_Des_t * p ); extern ABC_DLL int Abc_DesAddModel( Abc_Des_t * p, Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_DesFindModelByName( Abc_Des_t * p, char * pName ); extern ABC_DLL int Abc_DesFindTopLevelModels( Abc_Des_t * p ); extern ABC_DLL Abc_Ntk_t * Abc_DesDeriveRoot( Abc_Des_t * p ); /*=== abcLog.c ==========================================================*/ extern ABC_DLL void Abc_NtkWriteLogFile( char * pFileName, Abc_Cex_t * pSeqCex, int Status, int nFrames, char * pCommand ); /*=== abcMap.c ==========================================================*/ extern ABC_DLL Abc_Obj_t * Abc_NtkFetchTwinNode( Abc_Obj_t * pNode ); /*=== abcMiter.c ==========================================================*/ extern ABC_DLL int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NodeMinimumBase( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode ); /*=== abcMiter.c ==========================================================*/ extern ABC_DLL Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize, int fImplic, int fMulti ); extern ABC_DLL void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pNode ); extern ABC_DLL Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOr, int fCompl2 ); extern ABC_DLL Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ); extern ABC_DLL Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 ); extern ABC_DLL Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist ); extern ABC_DLL Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter ); extern ABC_DLL void Abc_NtkMiterReport( Abc_Ntk_t * pMiter ); extern ABC_DLL Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial, int fVerbose ); extern ABC_DLL int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd, int fXor ); /*=== abcNames.c ====================================================*/ extern ABC_DLL char * Abc_ObjName( Abc_Obj_t * pNode ); extern ABC_DLL char * Abc_ObjAssignName( Abc_Obj_t * pObj, char * pName, char * pSuffix ); extern ABC_DLL char * Abc_ObjNamePrefix( Abc_Obj_t * pObj, char * pPrefix ); extern ABC_DLL char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix ); extern ABC_DLL char * Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits ); extern ABC_DLL void Abc_NtkTrasferNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); extern ABC_DLL void Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); extern ABC_DLL Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode ); extern ABC_DLL Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames ); extern ABC_DLL void Abc_NodeFreeNames( Vec_Ptr_t * vNames ); extern ABC_DLL char ** Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollectCos ); extern ABC_DLL int Abc_NodeCompareNames( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ); extern ABC_DLL void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb ); 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 ); /*=== abcNetlist.c ==========================================================*/ extern ABC_DLL Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk ); /*=== abcNtbdd.c ==========================================================*/ extern ABC_DLL Abc_Ntk_t * Abc_NtkDeriveFromBdd( void * dd, void * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi ); extern ABC_DLL Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk, int fGlobal, int Limit, 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 ==========================================================*/ extern ABC_DLL Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan ); extern ABC_DLL Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ); extern ABC_DLL Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ); extern ABC_DLL void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); extern ABC_DLL Abc_Ntk_t * Abc_NtkStartRead( char * pName ); extern ABC_DLL void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkDupDfs( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkDupDfsNoBarBufs( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkDupTransformMiter( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis ); extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis ); extern ABC_DLL void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ); 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 * pInPermFile, char * pOutPermFile, 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, 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 ); extern ABC_DLL Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ); extern ABC_DLL void Abc_NtkDeleteObj( Abc_Obj_t * pObj ); extern ABC_DLL void Abc_NtkDeleteObjPo( Abc_Obj_t * pObj ); extern ABC_DLL void Abc_NtkDeleteObj_rec( Abc_Obj_t * pObj, int fOnlyNodes ); extern ABC_DLL void Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj ); extern ABC_DLL Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName ); extern ABC_DLL Abc_Obj_t * Abc_NtkDupBox( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pBox, int fCopyName ); extern ABC_DLL Abc_Obj_t * Abc_NtkCloneObj( Abc_Obj_t * pNode ); extern ABC_DLL Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName ); extern ABC_DLL Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName ); extern ABC_DLL Abc_Obj_t * Abc_NtkFindCi( Abc_Ntk_t * pNtk, char * pName ); extern ABC_DLL Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName ); extern ABC_DLL Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName ); extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ); extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ); extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 ); extern ABC_DLL int Abc_NodeIsConst( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NodeIsConst0( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NodeIsConst1( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NodeIsBuf( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NodeIsInv( Abc_Obj_t * pNode ); extern ABC_DLL void Abc_NodeComplement( Abc_Obj_t * pNode ); extern ABC_DLL void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ); /*=== abcOdc.c ==========================================================*/ typedef struct Odc_Man_t_ Odc_Man_t; extern ABC_DLL Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose ); extern ABC_DLL void Abc_NtkDontCareClear( Odc_Man_t * p ); extern ABC_DLL void Abc_NtkDontCareFree( Odc_Man_t * p ); extern ABC_DLL int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth ); /*=== abcPrint.c ==========================================================*/ extern ABC_DLL float Abc_NtkMfsTotalSwitching( Abc_Ntk_t * pNtk ); extern ABC_DLL float Abc_NtkMfsTotalGlitching( Abc_Ntk_t * pNtk, int nPats, int Prob, int fVerbose ); extern ABC_DLL void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf, int fSkipSmall, int fPrintMem ); extern ABC_DLL void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintFlops ); extern ABC_DLL void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk, int fUseFanio, int fUsePio, int fUseSupp, int fUseCone ); extern ABC_DLL void Abc_NtkPrintFanioNew( FILE * pFile, Abc_Ntk_t * pNtk, int fMffc ); extern ABC_DLL void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode ); extern ABC_DLL void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ); extern ABC_DLL void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ); extern ABC_DLL void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes, int fOutputs, int fVerbose ); extern ABC_DLL void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode ); extern ABC_DLL void Abc_NtkPrintSkews( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintAll ); extern ABC_DLL void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj ); extern ABC_DLL void Abc_NtkShow6VarFunc( char * pF0, char * pF1 ); /*=== abcProve.c ==========================================================*/ extern ABC_DLL int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pParams ); extern ABC_DLL int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ); /*=== abcRec3.c ==========================================================*/ extern ABC_DLL void Abc_NtkRecStart3( Gia_Man_t * p, int nVars, int nCuts, int fFuncOnly, int fVerbose ); extern ABC_DLL void Abc_NtkRecStop3(); extern ABC_DLL void Abc_NtkRecAdd3( Abc_Ntk_t * pNtk, int fUseSOPB ); extern ABC_DLL void Abc_NtkRecPs3(int fPrintLib); extern ABC_DLL Gia_Man_t * Abc_NtkRecGetGia3(); extern ABC_DLL int Abc_NtkRecIsRunning3(); extern ABC_DLL void Abc_NtkRecLibMerge3(Gia_Man_t * pGia); extern ABC_DLL int Abc_NtkRecInputNum3(); //extern ABC_DLL void Abc_NtkRecFilter3(int nLimit); /*=== abcReconv.c ==========================================================*/ extern ABC_DLL Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop ); extern ABC_DLL void Abc_NtkManCutStop( Abc_ManCut_t * p ); extern ABC_DLL Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p ); extern ABC_DLL Vec_Ptr_t * Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p ); extern ABC_DLL Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p ); extern ABC_DLL Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, int fContain ); extern ABC_DLL void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited, int fIncludeFanins ); extern ABC_DLL Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins, int LevelMax ); /*=== abcRefs.c ==========================================================*/ 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, 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 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 ==========================================================*/ extern ABC_DLL int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fVerbose, ABC_INT64_T * pNumConfs, ABC_INT64_T * pNumInspects ); extern ABC_DLL void * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fAllPrimes ); /*=== abcSop.c ==========================================================*/ extern ABC_DLL char * Abc_SopRegister( Mem_Flex_t * pMan, const char * pName ); extern ABC_DLL char * Abc_SopStart( Mem_Flex_t * pMan, int nCubes, int nVars ); extern ABC_DLL char * Abc_SopCreateConst0( Mem_Flex_t * pMan ); extern ABC_DLL char * Abc_SopCreateConst1( Mem_Flex_t * pMan ); extern ABC_DLL char * Abc_SopCreateAnd2( Mem_Flex_t * pMan, int fCompl0, int fCompl1 ); extern ABC_DLL char * Abc_SopCreateAnd( Mem_Flex_t * pMan, int nVars, int * pfCompl ); extern ABC_DLL char * Abc_SopCreateNand( Mem_Flex_t * pMan, int nVars ); extern ABC_DLL char * Abc_SopCreateOr( Mem_Flex_t * pMan, int nVars, int * pfCompl ); extern ABC_DLL char * Abc_SopCreateOrMultiCube( Mem_Flex_t * pMan, int nVars, int * pfCompl ); extern ABC_DLL char * Abc_SopCreateNor( Mem_Flex_t * pMan, int nVars ); extern ABC_DLL char * Abc_SopCreateXor( Mem_Flex_t * pMan, int nVars ); extern ABC_DLL char * Abc_SopCreateXorSpecial( Mem_Flex_t * pMan, int nVars ); extern ABC_DLL char * Abc_SopCreateNxor( Mem_Flex_t * pMan, int nVars ); extern ABC_DLL char * Abc_SopCreateMux( Mem_Flex_t * pMan ); extern ABC_DLL char * Abc_SopCreateInv( Mem_Flex_t * pMan ); extern ABC_DLL char * Abc_SopCreateBuf( Mem_Flex_t * pMan ); extern ABC_DLL char * Abc_SopCreateFromTruth( Mem_Flex_t * pMan, int nVars, unsigned * pTruth ); extern ABC_DLL char * Abc_SopCreateFromIsop( Mem_Flex_t * pMan, int nVars, Vec_Int_t * vCover ); extern ABC_DLL char * Abc_SopCreateFromTruthIsop( Mem_Flex_t * pMan, int nVars, word * pTruth, Vec_Int_t * vCover ); extern ABC_DLL int Abc_SopGetCubeNum( char * pSop ); extern ABC_DLL int Abc_SopGetLitNum( char * pSop ); extern ABC_DLL int Abc_SopGetVarNum( char * pSop ); extern ABC_DLL int Abc_SopGetPhase( char * pSop ); extern ABC_DLL int Abc_SopGetIthCareLit( char * pSop, int i ); extern ABC_DLL void Abc_SopComplement( char * pSop ); extern ABC_DLL void Abc_SopComplementVar( char * pSop, int iVar ); extern ABC_DLL int Abc_SopIsComplement( char * pSop ); extern ABC_DLL int Abc_SopIsConst0( char * pSop ); extern ABC_DLL int Abc_SopIsConst1( char * pSop ); extern ABC_DLL int Abc_SopIsBuf( char * pSop ); extern ABC_DLL int Abc_SopIsInv( char * pSop ); extern ABC_DLL int Abc_SopIsAndType( char * pSop ); extern ABC_DLL int Abc_SopIsOrType( char * pSop ); 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 ); extern ABC_DLL char * Abc_SopDecoderLog( Mem_Flex_t * pMan, int nValues ); extern ABC_DLL word Abc_SopToTruth( char * pSop, int nInputs ); extern ABC_DLL void Abc_SopToTruth7( char * pSop, int nInputs, word r[2] ); extern ABC_DLL void Abc_SopToTruthBig( char * pSop, int nInputs, word ** pVars, word * pCube, word * pRes ); /*=== abcStrash.c ==========================================================*/ extern ABC_DLL Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, int fCleanup ); extern ABC_DLL Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, int fCleanup ); extern ABC_DLL Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord ); extern ABC_DLL Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int fRecord ); extern ABC_DLL int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos ); extern ABC_DLL Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ); /*=== abcSweep.c ==========================================================*/ extern ABC_DLL int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ); extern ABC_DLL int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose ); extern ABC_DLL int Abc_NtkCleanupNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, int fVerbose ); extern ABC_DLL int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose ); extern ABC_DLL int Abc_NtkSweepBufsInvs( Abc_Ntk_t * pNtk, int fVerbose ); /*=== abcTiming.c ==========================================================*/ extern ABC_DLL Abc_Time_t * Abc_NtkReadDefaultArrival( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode ); extern ABC_DLL Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode ); extern ABC_DLL float Abc_NtkReadDefaultArrivalWorst( Abc_Ntk_t * pNtk ); extern ABC_DLL float Abc_NtkReadDefaultRequiredWorst( Abc_Ntk_t * pNtk ); extern ABC_DLL float Abc_NodeReadArrivalAve( Abc_Obj_t * pNode ); extern ABC_DLL float Abc_NodeReadRequiredAve( Abc_Obj_t * pNode ); extern ABC_DLL float Abc_NodeReadArrivalWorst( Abc_Obj_t * pNode ); extern ABC_DLL float Abc_NodeReadRequiredWorst( Abc_Obj_t * pNode ); extern ABC_DLL Abc_Time_t * Abc_NtkReadDefaultInputDrive( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Time_t * Abc_NtkReadDefaultOutputLoad( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Time_t * Abc_NodeReadInputDrive( Abc_Ntk_t * pNtk, int iPi ); extern ABC_DLL Abc_Time_t * Abc_NodeReadOutputLoad( Abc_Ntk_t * pNtk, int iPo ); extern ABC_DLL float Abc_NodeReadInputDriveWorst( Abc_Ntk_t * pNtk, int iPi ); extern ABC_DLL float Abc_NodeReadOutputLoadWorst( Abc_Ntk_t * pNtk, int iPo ); extern ABC_DLL void Abc_NtkTimeSetDefaultArrival( Abc_Ntk_t * pNtk, float Rise, float Fall ); extern ABC_DLL void Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall ); extern ABC_DLL void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ); extern ABC_DLL void Abc_NtkTimeSetRequired( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ); extern ABC_DLL void Abc_NtkTimeSetDefaultInputDrive( Abc_Ntk_t * pNtk, float Rise, float Fall ); extern ABC_DLL void Abc_NtkTimeSetDefaultOutputLoad( Abc_Ntk_t * pNtk, float Rise, float Fall ); extern ABC_DLL void Abc_NtkTimeSetInputDrive( Abc_Ntk_t * pNtk, int PiNum, float Rise, float Fall ); extern ABC_DLL void Abc_NtkTimeSetOutputLoad( Abc_Ntk_t * pNtk, int PoNum, float Rise, float Fall ); extern ABC_DLL void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkOld ); extern ABC_DLL void Abc_ManTimeStop( Abc_ManTime_t * p ); extern ABC_DLL void Abc_ManTimeDup( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ); extern ABC_DLL void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtk ); extern ABC_DLL float * Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk ); extern ABC_DLL float * Abc_NtkGetCoRequiredFloats( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Time_t * Abc_NtkGetCiArrivalTimes( Abc_Ntk_t * pNtk ); extern ABC_DLL Abc_Time_t * Abc_NtkGetCoRequiredTimes( Abc_Ntk_t * pNtk ); extern ABC_DLL float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk, Abc_Obj_t * pOut, Abc_Obj_t * pIn, int fPrint ); extern ABC_DLL int Abc_ObjLevelNew( Abc_Obj_t * pObj ); extern ABC_DLL int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj ); extern ABC_DLL int Abc_ObjRequiredLevel( Abc_Obj_t * pObj ); extern ABC_DLL int Abc_ObjReverseLevel( Abc_Obj_t * pObj ); extern ABC_DLL void Abc_ObjSetReverseLevel( Abc_Obj_t * pObj, int LevelR ); extern ABC_DLL void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease ); extern ABC_DLL void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ); extern ABC_DLL void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ); extern ABC_DLL void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ); /*=== abcUtil.c ==========================================================*/ extern ABC_DLL void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan ); extern ABC_DLL void Abc_NtkOrderCisCos( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetCubePairNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetLitNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetLitFactNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetBddNodeNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetAigNodeNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetClauseNum( Abc_Ntk_t * pNtk ); extern ABC_DLL double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetBufNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetLargeNodeNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetFanoutMax( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkGetTotalFanins( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkCleanCopy_rec( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkCleanData( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkFillTemp( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkCountCopy( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Abc_NtkSaveCopy( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies ); extern ABC_DLL void Abc_NtkCleanNext( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkCleanNext_rec( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkCleanMarkA( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkCleanMarkB( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkCleanMarkC( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkCleanMarkAB( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkCleanMarkABC( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NodeFindFanin( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ); extern ABC_DLL Abc_Obj_t * Abc_NodeFindCoFanout( Abc_Obj_t * pNode ); extern ABC_DLL Abc_Obj_t * Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode ); extern ABC_DLL Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, int fDuplicate ); extern ABC_DLL void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NodeIsExorType( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NodeIsMuxType( Abc_Obj_t * pNode ); extern ABC_DLL int Abc_NodeIsMuxControlType( Abc_Obj_t * pNode ); extern ABC_DLL Abc_Obj_t * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE ); extern ABC_DLL int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc, Abc_Ntk_t ** ppNtk1, Abc_Ntk_t ** ppNtk2, int * pfDelete1, int * pfDelete2, int fCheck ); extern ABC_DLL void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); extern ABC_DLL void Abc_NodeCollectFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); extern ABC_DLL Vec_Ptr_t * Abc_NtkCollectLatches( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NodeCompareLevelsIncrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ); extern ABC_DLL int Abc_NodeCompareLevelsDecrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ); extern ABC_DLL Vec_Int_t * Abc_NtkFanoutCounts( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk ); extern ABC_DLL Vec_Int_t * Abc_NtkGetCiIds( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkReassignIds( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_ObjPointerCompare( void ** pp1, void ** pp2 ); extern ABC_DLL void Abc_NtkTransferCopy( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkInvertConstraints( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkPrintCiLevels( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkReverseTopoOrder( Abc_Ntk_t * pNtk ); extern ABC_DLL int Abc_NtkIsTopo( Abc_Ntk_t * pNtk ); extern ABC_DLL void Abc_NtkTransferPhases( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk ); extern ABC_DLL Gia_Man_t * Abc_SopSynthesizeOne( char * pSop, int fClp ); /*=== abcVerify.c ==========================================================*/ extern ABC_DLL int * Abc_NtkVerifyGetCleanModel( Abc_Ntk_t * pNtk, int nFrames ); extern ABC_DLL int * Abc_NtkVerifySimulatePattern( Abc_Ntk_t * pNtk, int * pModel ); extern ABC_DLL int Abc_NtkIsTrueCex( Abc_Ntk_t * pNtk, Abc_Cex_t * pCex ); extern ABC_DLL int Abc_NtkIsValidCex( Abc_Ntk_t * pNtk, Abc_Cex_t * pCex ); ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/base/abc/abcAig.c000066400000000000000000001422101477524141600157400ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcAig.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Simple structural hashing package.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" ABC_NAMESPACE_IMPL_START /* AIG is an And-Inv Graph with structural hashing. It is always structurally hashed. It means that at any time: - for each AND gate, there are no other AND gates with the same children - the constants are propagated - there is no single-input nodes (inverters/buffers) Additionally the following invariants are satisfied: - there are no dangling nodes (the nodes without fanout) - the level of each AND gate reflects the levels of this fanins - the EXOR-status of each node is up-to-date - the AND nodes are in the topological order - the constant 1 node has always number 0 in the object list The operations that are performed on AIGs: - building new nodes (Abc_AigAnd) - performing elementary Boolean operations (Abc_AigOr, Abc_AigXor, etc) - replacing one node by another (Abc_AigReplace) - propagating constants (Abc_AigReplace) When AIG is duplicated, the new graph is structurally hashed too. If this repeated hashing leads to fewer nodes, it means the original AIG was not strictly hashed (one of the conditions above is violated). */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// // the simple AIG manager struct Abc_Aig_t_ { Abc_Ntk_t * pNtkAig; // the AIG network Abc_Obj_t * pConst1; // the constant 1 object (not a node!) Abc_Obj_t ** pBins; // the table bins int nBins; // the size of the table int nEntries; // the total number of entries in the table Vec_Ptr_t * vNodes; // the temporary array of nodes Vec_Ptr_t * vStackReplaceOld; // the nodes to be replaced Vec_Ptr_t * vStackReplaceNew; // the nodes to be used for replacement Vec_Vec_t * vLevels; // the nodes to be updated Vec_Vec_t * vLevelsR; // the nodes to be updated Vec_Ptr_t * vAddedCells; // the added nodes Vec_Ptr_t * vUpdatedNets; // the nodes whose fanouts have changed int nStrash0; int nStrash1; int nStrash5; int nStrash2; }; // iterators through the entries in the linked lists of nodes #define Abc_AigBinForEachEntry( pBin, pEnt ) \ for ( pEnt = pBin; \ pEnt; \ pEnt = pEnt->pNext ) #define Abc_AigBinForEachEntrySafe( pBin, pEnt, pEnt2 ) \ for ( pEnt = pBin, \ pEnt2 = pEnt? pEnt->pNext: NULL; \ pEnt; \ pEnt = pEnt2, \ pEnt2 = pEnt? pEnt->pNext: NULL ) // hash key for the structural hash table //static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; } //static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)((a)->Id + (b)->Id) * ((a)->Id + (b)->Id + 1) / 2) % TableSize; } // hashing the node static unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { unsigned Key = 0; Key ^= Abc_ObjRegular(p0)->Id * 7937; Key ^= Abc_ObjRegular(p1)->Id * 2971; Key ^= Abc_ObjIsComplement(p0) * 911; Key ^= Abc_ObjIsComplement(p1) * 353; return Key % TableSize; } // structural hash table procedures static Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); static Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd ); static void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis ); static void Abc_AigResize( Abc_Aig_t * pMan ); // incremental AIG procedures static void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ); static void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan ); static void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan ); static void Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ); static void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates the local AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig ) { Abc_Aig_t * pMan; // start the manager pMan = ABC_ALLOC( Abc_Aig_t, 1 ); memset( pMan, 0, sizeof(Abc_Aig_t) ); // allocate the table pMan->nBins = Abc_PrimeCudd( 10000 ); pMan->pBins = ABC_ALLOC( Abc_Obj_t *, pMan->nBins ); memset( pMan->pBins, 0, sizeof(Abc_Obj_t *) * pMan->nBins ); pMan->vNodes = Vec_PtrAlloc( 100 ); pMan->vLevels = Vec_VecAlloc( 100 ); pMan->vLevelsR = Vec_VecAlloc( 100 ); pMan->vStackReplaceOld = Vec_PtrAlloc( 100 ); pMan->vStackReplaceNew = Vec_PtrAlloc( 100 ); // create the constant node assert( pNtkAig->vObjs->nSize == 0 ); pMan->pConst1 = Abc_NtkCreateObj( pNtkAig, ABC_OBJ_NODE ); pMan->pConst1->Type = ABC_OBJ_CONST1; pMan->pConst1->fPhase = 1; pNtkAig->nObjCounts[ABC_OBJ_NODE]--; // save the current network pMan->pNtkAig = pNtkAig; return pMan; } /**Function************************************************************* Synopsis [Deallocates the local AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigFree( Abc_Aig_t * pMan ) { assert( Vec_PtrSize( pMan->vStackReplaceOld ) == 0 ); assert( Vec_PtrSize( pMan->vStackReplaceNew ) == 0 ); // free the table if ( pMan->vAddedCells ) Vec_PtrFree( pMan->vAddedCells ); if ( pMan->vUpdatedNets ) Vec_PtrFree( pMan->vUpdatedNets ); Vec_VecFree( pMan->vLevels ); Vec_VecFree( pMan->vLevelsR ); Vec_PtrFree( pMan->vStackReplaceOld ); Vec_PtrFree( pMan->vStackReplaceNew ); Vec_PtrFree( pMan->vNodes ); ABC_FREE( pMan->pBins ); ABC_FREE( pMan ); } /**Function************************************************************* Synopsis [Returns the number of dangling nodes removed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_AigCleanup( Abc_Aig_t * pMan ) { Vec_Ptr_t * vDangles; Abc_Obj_t * pAnd; int i, nNodesOld; // printf( "Strash0 = %d. Strash1 = %d. Strash100 = %d. StrashM = %d.\n", // pMan->nStrash0, pMan->nStrash1, pMan->nStrash5, pMan->nStrash2 ); nNodesOld = pMan->nEntries; // collect the AND nodes that do not fanout vDangles = Vec_PtrAlloc( 100 ); for ( i = 0; i < pMan->nBins; i++ ) Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) if ( Abc_ObjFanoutNum(pAnd) == 0 ) Vec_PtrPush( vDangles, pAnd ); // process the dangling nodes and their MFFCs Vec_PtrForEachEntry( Abc_Obj_t *, vDangles, pAnd, i ) Abc_AigDeleteNode( pMan, pAnd ); Vec_PtrFree( vDangles ); return nNodesOld - pMan->nEntries; } /**Function************************************************************* Synopsis [Makes sure that every node in the table is in the network and vice versa.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_AigCheck( Abc_Aig_t * pMan ) { Abc_Obj_t * pObj, * pAnd; int i, nFanins, Counter; Abc_NtkForEachNode( pMan->pNtkAig, pObj, i ) { nFanins = Abc_ObjFaninNum(pObj); if ( nFanins == 0 ) { if ( !Abc_AigNodeIsConst(pObj) ) { printf( "Abc_AigCheck: The AIG has non-standard constant nodes.\n" ); return 0; } continue; } if ( nFanins == 1 ) { printf( "Abc_AigCheck: The AIG has single input nodes.\n" ); return 0; } if ( nFanins > 2 ) { printf( "Abc_AigCheck: The AIG has non-standard nodes.\n" ); return 0; } if ( pObj->Level != 1 + (unsigned)Abc_MaxInt( Abc_ObjFanin0(pObj)->Level, Abc_ObjFanin1(pObj)->Level ) ) printf( "Abc_AigCheck: Node \"%s\" has level that does not agree with the fanin levels.\n", Abc_ObjName(pObj) ); pAnd = Abc_AigAndLookup( pMan, Abc_ObjChild0(pObj), Abc_ObjChild1(pObj) ); if ( pAnd != pObj ) printf( "Abc_AigCheck: Node \"%s\" is not in the structural hashing table.\n", Abc_ObjName(pObj) ); } // count the number of nodes in the table Counter = 0; for ( i = 0; i < pMan->nBins; i++ ) Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) Counter++; if ( Counter != Abc_NtkNodeNum(pMan->pNtkAig) ) { printf( "Abc_AigCheck: The number of nodes in the structural hashing table is wrong.\n" ); return 0; } // if the node is a choice node, nodes in its class should not have fanouts Abc_NtkForEachNode( pMan->pNtkAig, pObj, i ) if ( Abc_AigNodeIsChoice(pObj) ) for ( pAnd = (Abc_Obj_t *)pObj->pData; pAnd; pAnd = (Abc_Obj_t *)pAnd->pData ) if ( Abc_ObjFanoutNum(pAnd) > 0 ) { printf( "Abc_AigCheck: Representative %s", Abc_ObjName(pAnd) ); printf( " of choice node %s has %d fanouts.\n", Abc_ObjName(pObj), Abc_ObjFanoutNum(pAnd) ); return 0; } return 1; } /**Function************************************************************* Synopsis [Computes the number of logic levels not counting PIs/POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_AigLevel( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, LevelsMax; assert( Abc_NtkIsStrash(pNtk) ); if ( pNtk->nBarBufs ) return Abc_NtkLevel( pNtk ); // perform the traversal LevelsMax = 0; Abc_NtkForEachCo( pNtk, pNode, i ) if ( LevelsMax < (int)Abc_ObjFanin0(pNode)->Level ) LevelsMax = (int)Abc_ObjFanin0(pNode)->Level; return LevelsMax; } /**Function************************************************************* Synopsis [Performs canonicization step.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) { Abc_Obj_t * pAnd; unsigned Key; // check if it is a good time for table resizing if ( pMan->nEntries > 2 * pMan->nBins ) Abc_AigResize( pMan ); // order the arguments if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) pAnd = p0, p0 = p1, p1 = pAnd; // create the new node pAnd = Abc_NtkCreateNode( pMan->pNtkAig ); Abc_ObjAddFanin( pAnd, p0 ); Abc_ObjAddFanin( pAnd, p1 ); // set the level of the new node pAnd->Level = 1 + Abc_MaxInt( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level ); pAnd->fExor = Abc_NodeIsExorType(pAnd); pAnd->fPhase = (Abc_ObjIsComplement(p0) ^ Abc_ObjRegular(p0)->fPhase) & (Abc_ObjIsComplement(p1) ^ Abc_ObjRegular(p1)->fPhase); // add the node to the corresponding linked list in the table Key = Abc_HashKey2( p0, p1, pMan->nBins ); pAnd->pNext = pMan->pBins[Key]; pMan->pBins[Key] = pAnd; pMan->nEntries++; // create the cuts if defined // if ( pAnd->pNtk->pManCut ) // Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd ); pAnd->pCopy = NULL; // add the node to the list of updated nodes if ( pMan->vAddedCells ) Vec_PtrPush( pMan->vAddedCells, pAnd ); return pAnd; } /**Function************************************************************* Synopsis [Performs canonicization step.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd ) { Abc_Obj_t * pTemp; unsigned Key; assert( !Abc_ObjIsComplement(pAnd) ); // order the arguments if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) pTemp = p0, p0 = p1, p1 = pTemp; // create the new node Abc_ObjAddFanin( pAnd, p0 ); Abc_ObjAddFanin( pAnd, p1 ); // set the level of the new node pAnd->Level = 1 + Abc_MaxInt( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level ); pAnd->fExor = Abc_NodeIsExorType(pAnd); // add the node to the corresponding linked list in the table Key = Abc_HashKey2( p0, p1, pMan->nBins ); pAnd->pNext = pMan->pBins[Key]; pMan->pBins[Key] = pAnd; pMan->nEntries++; // create the cuts if defined // if ( pAnd->pNtk->pManCut ) // Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd ); pAnd->pCopy = NULL; // add the node to the list of updated nodes // if ( pMan->vAddedCells ) // Vec_PtrPush( pMan->vAddedCells, pAnd ); return pAnd; } /**Function************************************************************* Synopsis [Performs canonicization step.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) { Abc_Obj_t * pAnd, * pConst1; unsigned Key; assert( Abc_ObjRegular(p0)->pNtk->pManFunc == pMan ); assert( Abc_ObjRegular(p1)->pNtk->pManFunc == pMan ); // check for trivial cases pConst1 = Abc_AigConst1(pMan->pNtkAig); if ( p0 == p1 ) return p0; if ( p0 == Abc_ObjNot(p1) ) return Abc_ObjNot(pConst1); if ( Abc_ObjRegular(p0) == pConst1 ) { if ( p0 == pConst1 ) return p1; return Abc_ObjNot(pConst1); } if ( Abc_ObjRegular(p1) == pConst1 ) { if ( p1 == pConst1 ) return p0; return Abc_ObjNot(pConst1); } /* { int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) ); int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) ); if ( nFans0 == 0 || nFans1 == 0 ) pMan->nStrash0++; else if ( nFans0 == 1 || nFans1 == 1 ) pMan->nStrash1++; else if ( nFans0 <= 100 && nFans1 <= 100 ) pMan->nStrash5++; else pMan->nStrash2++; } */ { int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) ); int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) ); if ( nFans0 == 0 || nFans1 == 0 ) return NULL; } // order the arguments if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) pAnd = p0, p0 = p1, p1 = pAnd; // get the hash key for these two nodes Key = Abc_HashKey2( p0, p1, pMan->nBins ); // find the matching node in the table Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd ) if ( p0 == Abc_ObjChild0(pAnd) && p1 == Abc_ObjChild1(pAnd) ) { // assert( Abc_ObjFanoutNum(Abc_ObjRegular(p0)) && Abc_ObjFanoutNum(p1) ); return pAnd; } return NULL; } /**Function************************************************************* Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType ) { Abc_Obj_t * pNode1, * pNode2, * pNode; // set the flag to zero if ( pType ) *pType = 0; // check the case of XOR(a,b) = OR(ab, a'b')' if ( (pNode1 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), Abc_ObjNot(p1))) && (pNode2 = Abc_AigAndLookup(pMan, p0, p1)) ) { pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); if ( pNode && pType ) *pType = 1; return pNode; } // check the case of XOR(a,b) = OR(a'b, ab') if ( (pNode1 = Abc_AigAndLookup(pMan, p0, Abc_ObjNot(p1))) && (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), p1)) ) { pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); return pNode? Abc_ObjNot(pNode) : NULL; } return NULL; } /**Function************************************************************* Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType ) { Abc_Obj_t * pNode1, * pNode2, * pNode; // set the flag to zero if ( pType ) *pType = 0; // check the case of MUX(c,t,e) = OR(ct', c'e')' if ( (pNode1 = Abc_AigAndLookup(pMan, pC, Abc_ObjNot(pT))) && (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), Abc_ObjNot(pE))) ) { pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); if ( pNode && pType ) *pType = 1; return pNode; } // check the case of MUX(c,t,e) = OR(ct, c'e) if ( (pNode1 = Abc_AigAndLookup(pMan, pC, pT)) && (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), pE)) ) { pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); return pNode? Abc_ObjNot(pNode) : NULL; } return NULL; } /**Function************************************************************* Synopsis [Deletes an AIG node from the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis ) { Abc_Obj_t * pAnd, * pAnd0, * pAnd1, ** ppPlace; unsigned Key; assert( !Abc_ObjIsComplement(pThis) ); assert( Abc_ObjIsNode(pThis) ); assert( Abc_ObjFaninNum(pThis) == 2 ); assert( pMan->pNtkAig == pThis->pNtk ); // get the hash key for these two nodes pAnd0 = Abc_ObjRegular( Abc_ObjChild0(pThis) ); pAnd1 = Abc_ObjRegular( Abc_ObjChild1(pThis) ); Key = Abc_HashKey2( Abc_ObjChild0(pThis), Abc_ObjChild1(pThis), pMan->nBins ); // find the matching node in the table ppPlace = pMan->pBins + Key; Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd ) { if ( pAnd != pThis ) { ppPlace = &pAnd->pNext; continue; } *ppPlace = pAnd->pNext; break; } assert( pAnd == pThis ); pMan->nEntries--; // delete the cuts if defined if ( pThis->pNtk->pManCut ) Abc_NodeFreeCuts( pThis->pNtk->pManCut, pThis ); } /**Function************************************************************* Synopsis [Resizes the hash table of AIG nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigResize( Abc_Aig_t * pMan ) { Abc_Obj_t ** pBinsNew; Abc_Obj_t * pEnt, * pEnt2; int nBinsNew, Counter, i; abctime clk; unsigned Key; clk = Abc_Clock(); // get the new table size nBinsNew = Abc_PrimeCudd( 3 * pMan->nBins ); // allocate a new array pBinsNew = ABC_ALLOC( Abc_Obj_t *, nBinsNew ); memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * nBinsNew ); // rehash the entries from the old table Counter = 0; for ( i = 0; i < pMan->nBins; i++ ) Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 ) { Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), nBinsNew ); pEnt->pNext = pBinsNew[Key]; pBinsNew[Key] = pEnt; Counter++; } assert( Counter == pMan->nEntries ); // printf( "Increasing the structural table size from %6d to %6d. ", pMan->nBins, nBinsNew ); // ABC_PRT( "Time", Abc_Clock() - clk ); // replace the table and the parameters ABC_FREE( pMan->pBins ); pMan->pBins = pBinsNew; pMan->nBins = nBinsNew; } /**Function************************************************************* Synopsis [Resizes the hash table of AIG nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigRehash( Abc_Aig_t * pMan ) { Abc_Obj_t ** pBinsNew; Abc_Obj_t * pEnt, * pEnt2; int * pArray; unsigned Key; int Counter, Temp, i; // allocate a new array pBinsNew = ABC_ALLOC( Abc_Obj_t *, pMan->nBins ); memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * pMan->nBins ); // rehash the entries from the old table Counter = 0; for ( i = 0; i < pMan->nBins; i++ ) Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 ) { // swap the fanins if needed pArray = pEnt->vFanins.pArray; if ( pArray[0] > pArray[1] ) { Temp = pArray[0]; pArray[0] = pArray[1]; pArray[1] = Temp; Temp = pEnt->fCompl0; pEnt->fCompl0 = pEnt->fCompl1; pEnt->fCompl1 = Temp; } // rehash the node Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), pMan->nBins ); pEnt->pNext = pBinsNew[Key]; pBinsNew[Key] = pEnt; Counter++; } assert( Counter == pMan->nEntries ); // replace the table and the parameters ABC_FREE( pMan->pBins ); pMan->pBins = pBinsNew; } /**Function************************************************************* Synopsis [Performs canonicization step.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk ) { assert( Abc_NtkIsStrash(pNtk) ); return ((Abc_Aig_t *)pNtk->pManFunc)->pConst1; } /**Function************************************************************* Synopsis [Performs canonicization step.] Description [The argument nodes can be complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) { Abc_Obj_t * pAnd; if ( (pAnd = Abc_AigAndLookup( pMan, p0, p1 )) ) return pAnd; return Abc_AigAndCreate( pMan, p0, p1 ); } /**Function************************************************************* Synopsis [Implements Boolean OR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) { return Abc_ObjNot( Abc_AigAnd( pMan, Abc_ObjNot(p0), Abc_ObjNot(p1) ) ); } /**Function************************************************************* Synopsis [Implements Boolean XOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) { return Abc_AigOr( pMan, Abc_AigAnd(pMan, p0, Abc_ObjNot(p1)), Abc_AigAnd(pMan, p1, Abc_ObjNot(p0)) ); } /**Function************************************************************* Synopsis [Implements Boolean XOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_AigMux( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * p1, Abc_Obj_t * p0 ) { return Abc_AigOr( pMan, Abc_AigAnd(pMan, pC, p1), Abc_AigAnd(pMan, Abc_ObjNot(pC), p0) ); } /**Function************************************************************* Synopsis [Implements the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_AigMiter_rec( Abc_Aig_t * pMan, Abc_Obj_t ** ppObjs, int nObjs ) { Abc_Obj_t * pObj1, * pObj2; if ( nObjs == 1 ) return ppObjs[0]; pObj1 = Abc_AigMiter_rec( pMan, ppObjs, nObjs/2 ); pObj2 = Abc_AigMiter_rec( pMan, ppObjs + nObjs/2, nObjs - nObjs/2 ); return Abc_AigOr( pMan, pObj1, pObj2 ); } /**Function************************************************************* Synopsis [Implements the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs, int fImplic ) { int i; if ( vPairs->nSize == 0 ) return Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) ); assert( vPairs->nSize % 2 == 0 ); // go through the cubes of the node's SOP if ( fImplic ) { for ( i = 0; i < vPairs->nSize; i += 2 ) vPairs->pArray[i/2] = Abc_AigAnd( pMan, (Abc_Obj_t *)vPairs->pArray[i], Abc_ObjNot((Abc_Obj_t *)vPairs->pArray[i+1]) ); } else { for ( i = 0; i < vPairs->nSize; i += 2 ) vPairs->pArray[i/2] = Abc_AigXor( pMan, (Abc_Obj_t *)vPairs->pArray[i], (Abc_Obj_t *)vPairs->pArray[i+1] ); } vPairs->nSize = vPairs->nSize/2; return Abc_AigMiter_rec( pMan, (Abc_Obj_t **)vPairs->pArray, vPairs->nSize ); } /**Function************************************************************* Synopsis [Implements the miter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_AigMiter2( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs ) { Abc_Obj_t * pMiter, * pXor; int i; assert( vPairs->nSize % 2 == 0 ); // go through the cubes of the node's SOP pMiter = Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) ); for ( i = 0; i < vPairs->nSize; i += 2 ) { pXor = Abc_AigXor( pMan, (Abc_Obj_t *)vPairs->pArray[i], (Abc_Obj_t *)vPairs->pArray[i+1] ); pMiter = Abc_AigOr( pMan, pMiter, pXor ); } return pMiter; } /**Function************************************************************* Synopsis [Replaces one AIG node by the other.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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 ); Vec_PtrPush( pMan->vStackReplaceOld, pOld ); Vec_PtrPush( pMan->vStackReplaceNew, pNew ); assert( !Abc_ObjIsComplement(pOld) ); // process the replacements while ( Vec_PtrSize(pMan->vStackReplaceOld) ) { 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 ) { Abc_AigUpdateLevel_int( pMan ); if ( pMan->pNtkAig->vLevelsR ) Abc_AigUpdateLevelR_int( pMan ); } return 1; } /**Function************************************************************* Synopsis [Performs internal replacement step.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ) { Abc_Obj_t * pFanin1, * pFanin2, * pFanout, * pFanoutNew, * pFanoutFanout; int k, v, iFanin; // make sure the old node is regular and has fanouts // (the new node can be complemented and can have fanouts) assert( !Abc_ObjIsComplement(pOld) ); assert( Abc_ObjFanoutNum(pOld) > 0 ); // look at the fanouts of old node Abc_NodeCollectFanouts( pOld, pMan->vNodes ); Vec_PtrForEachEntry( Abc_Obj_t *, pMan->vNodes, pFanout, k ) { if ( Abc_ObjIsCo(pFanout) ) { 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 iFanin = Vec_IntFind( &pFanout->vFanins, pOld->Id ); assert( iFanin == 0 || iFanin == 1 ); // get the new fanin pFanin1 = Abc_ObjNotCond( pNew, Abc_ObjFaninC(pFanout, iFanin) ); assert( Abc_ObjRegular(pFanin1) != pFanout ); // get another fanin pFanin2 = Abc_ObjChild( pFanout, iFanin ^ 1 ); assert( Abc_ObjRegular(pFanin2) != pFanout ); // check if the node with these fanins exists if ( (pFanoutNew = Abc_AigAndLookup( pMan, pFanin1, pFanin2 )) ) { // such node exists (it may be a constant) // schedule replacement of the old fanout by the new fanout Vec_PtrPush( pMan->vStackReplaceOld, pFanout ); Vec_PtrPush( pMan->vStackReplaceNew, pFanoutNew ); continue; } // such node does not exist - modify the old fanout node // (this way the change will not propagate all the way to the COs) assert( Abc_ObjRegular(pFanin1) != Abc_ObjRegular(pFanin2) ); // if the node is in the level structure, remove it if ( pFanout->fMarkA ) Abc_AigRemoveFromLevelStructure( pMan->vLevels, pFanout ); // if the node is in the level structure, remove it if ( pFanout->fMarkB ) Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanout ); // remove the old fanout node from the structural hashing table Abc_AigAndDelete( pMan, pFanout ); // remove the fanins of the old fanout Abc_ObjRemoveFanins( pFanout ); // recreate the old fanout with new fanins and add it to the table Abc_AigAndCreateFrom( pMan, pFanin1, pFanin2, pFanout ); assert( Abc_AigNodeIsAcyclic(pFanout, pFanout) ); if ( fUpdateLevel ) { // schedule the updated fanout for updating direct level assert( pFanout->fMarkA == 0 ); pFanout->fMarkA = 1; Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout ); // schedule the updated fanout for updating reverse level if ( pMan->pNtkAig->vLevelsR ) { assert( pFanout->fMarkB == 0 ); pFanout->fMarkB = 1; Vec_VecPush( pMan->vLevelsR, Abc_ObjReverseLevel(pFanout), pFanout ); } } // the fanout has changed, update EXOR status of its fanouts Abc_ObjForEachFanout( pFanout, pFanoutFanout, v ) if ( Abc_AigNodeIsAnd(pFanoutFanout) ) pFanoutFanout->fExor = Abc_NodeIsExorType(pFanoutFanout); } // if the node has no fanouts left, remove its MFFC if ( Abc_ObjFanoutNum(pOld) == 0 ) Abc_AigDeleteNode( pMan, pOld ); } /**Function************************************************************* Synopsis [Performs internal deletion step.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pNode ) { Abc_Obj_t * pNode0, * pNode1, * pTemp; int i, k; // make sure the node is regular and dangling assert( !Abc_ObjIsComplement(pNode) ); assert( Abc_ObjIsNode(pNode) ); assert( Abc_ObjFaninNum(pNode) == 2 ); assert( Abc_ObjFanoutNum(pNode) == 0 ); // when deleting an old node that is scheduled for replacement, remove it from the replacement queue Vec_PtrForEachEntry( Abc_Obj_t *, pMan->vStackReplaceOld, pTemp, i ) if ( pNode == pTemp ) { // remove the entry from the replacement array for ( k = i; k < pMan->vStackReplaceOld->nSize - 1; k++ ) { pMan->vStackReplaceOld->pArray[k] = pMan->vStackReplaceOld->pArray[k+1]; pMan->vStackReplaceNew->pArray[k] = pMan->vStackReplaceNew->pArray[k+1]; } pMan->vStackReplaceOld->nSize--; pMan->vStackReplaceNew->nSize--; } // when deleting a new node that should replace another node, do not delete Vec_PtrForEachEntry( Abc_Obj_t *, pMan->vStackReplaceNew, pTemp, i ) if ( pNode == Abc_ObjRegular(pTemp) ) return; // remember the node's fanins pNode0 = Abc_ObjFanin0( pNode ); pNode1 = Abc_ObjFanin1( pNode ); // add the node to the list of updated nodes if ( pMan->vUpdatedNets ) { Vec_PtrPushUnique( pMan->vUpdatedNets, pNode0 ); Vec_PtrPushUnique( pMan->vUpdatedNets, pNode1 ); } // remove the node from the table Abc_AigAndDelete( pMan, pNode ); // if the node is in the level structure, remove it if ( pNode->fMarkA ) Abc_AigRemoveFromLevelStructure( pMan->vLevels, pNode ); if ( pNode->fMarkB ) Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pNode ); // remove the node from the network Abc_NtkDeleteObj( pNode ); // call recursively for the fanins if ( Abc_ObjIsNode(pNode0) && pNode0->vFanouts.nSize == 0 ) Abc_AigDeleteNode( pMan, pNode0 ); if ( Abc_ObjIsNode(pNode1) && pNode1->vFanouts.nSize == 0 ) Abc_AigDeleteNode( pMan, pNode1 ); } /**Function************************************************************* Synopsis [Updates the level of the node after it has changed.] Description [This procedure is based on the observation that after the node's level has changed, the fanouts levels can change too, but the new fanout levels are always larger than the node's level. As a result, we can accumulate the nodes to be updated in the queue and process them in the increasing order of levels.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan ) { Abc_Obj_t * pNode, * pFanout; Vec_Ptr_t * vVec; int LevelNew, i, k, v; // go through the nodes and update the level of their fanouts Vec_VecForEachLevel( pMan->vLevels, vVec, i ) { if ( Vec_PtrSize(vVec) == 0 ) continue; Vec_PtrForEachEntry( Abc_Obj_t *, vVec, pNode, k ) { if ( pNode == NULL ) continue; assert( Abc_ObjIsNode(pNode) ); assert( (int)pNode->Level == i ); // clean the mark assert( pNode->fMarkA == 1 ); pNode->fMarkA = 0; // iterate through the fanouts Abc_ObjForEachFanout( pNode, pFanout, v ) { if ( Abc_ObjIsCo(pFanout) ) continue; // get the new level of this fanout LevelNew = 1 + Abc_MaxInt( Abc_ObjFanin0(pFanout)->Level, Abc_ObjFanin1(pFanout)->Level ); assert( LevelNew > i ); if ( (int)pFanout->Level == LevelNew ) // no change continue; // if the fanout is present in the data structure, pull it out if ( pFanout->fMarkA ) Abc_AigRemoveFromLevelStructure( pMan->vLevels, pFanout ); // update the fanout level pFanout->Level = LevelNew; // add the fanout to the data structure to update its fanouts assert( pFanout->fMarkA == 0 ); pFanout->fMarkA = 1; Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout ); } } Vec_PtrClear( vVec ); } } /**Function************************************************************* Synopsis [Updates the level of the node after it has changed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan ) { Abc_Obj_t * pNode, * pFanin, * pFanout; Vec_Ptr_t * vVec; int LevelNew, i, k, v, j; // go through the nodes and update the level of their fanouts Vec_VecForEachLevel( pMan->vLevelsR, vVec, i ) { if ( Vec_PtrSize(vVec) == 0 ) continue; Vec_PtrForEachEntry( Abc_Obj_t *, vVec, pNode, k ) { if ( pNode == NULL ) continue; assert( Abc_ObjIsNode(pNode) ); assert( Abc_ObjReverseLevel(pNode) == i ); // clean the mark assert( pNode->fMarkB == 1 ); pNode->fMarkB = 0; // iterate through the fanins Abc_ObjForEachFanin( pNode, pFanin, v ) { if ( Abc_ObjIsCi(pFanin) ) continue; // get the new reverse level of this fanin LevelNew = 0; Abc_ObjForEachFanout( pFanin, pFanout, j ) if ( LevelNew < Abc_ObjReverseLevel(pFanout) ) LevelNew = Abc_ObjReverseLevel(pFanout); LevelNew += 1; assert( LevelNew > i ); if ( Abc_ObjReverseLevel(pFanin) == LevelNew ) // no change continue; // if the fanin is present in the data structure, pull it out if ( pFanin->fMarkB ) Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanin ); // update the reverse level Abc_ObjSetReverseLevel( pFanin, LevelNew ); // add the fanin to the data structure to update its fanins assert( pFanin->fMarkB == 0 ); pFanin->fMarkB = 1; Vec_VecPush( pMan->vLevelsR, LevelNew, pFanin ); } } Vec_PtrClear( vVec ); } } /**Function************************************************************* Synopsis [Removes the node from the level structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ) { Vec_Ptr_t * vVecTemp; Abc_Obj_t * pTemp; int m; assert( pNode->fMarkA ); vVecTemp = Vec_VecEntry( vStruct, pNode->Level ); Vec_PtrForEachEntry( Abc_Obj_t *, vVecTemp, pTemp, m ) { if ( pTemp != pNode ) continue; Vec_PtrWriteEntry( vVecTemp, m, NULL ); break; } assert( m < Vec_PtrSize(vVecTemp) ); // found pNode->fMarkA = 0; } /**Function************************************************************* Synopsis [Removes the node from the level structure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ) { Vec_Ptr_t * vVecTemp; Abc_Obj_t * pTemp; int m; assert( pNode->fMarkB ); vVecTemp = Vec_VecEntry( vStruct, Abc_ObjReverseLevel(pNode) ); Vec_PtrForEachEntry( Abc_Obj_t *, vVecTemp, pTemp, m ) { if ( pTemp != pNode ) continue; Vec_PtrWriteEntry( vVecTemp, m, NULL ); break; } assert( m < Vec_PtrSize(vVecTemp) ); // found pNode->fMarkB = 0; } /**Function************************************************************* Synopsis [Returns 1 if the node has at least one complemented fanout.] Description [A fanout is complemented if the fanout's fanin edge pointing to the given node is complemented.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode ) { Abc_Obj_t * pFanout; int i, iFanin; Abc_ObjForEachFanout( pNode, pFanout, i ) { iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id ); assert( iFanin >= 0 ); if ( Abc_ObjFaninC( pFanout, iFanin ) ) return 1; } return 0; } /**Function************************************************************* Synopsis [Returns 1 if the node has at least one complemented fanout.] Description [A fanout is complemented if the fanout's fanin edge pointing to the given node is complemented. Only the fanouts with current TravId are counted.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode ) { Abc_Obj_t * pFanout; int i, iFanin; Abc_ObjForEachFanout( pNode, pFanout, i ) { if ( !Abc_NodeIsTravIdCurrent(pFanout) ) continue; iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id ); assert( iFanin >= 0 ); if ( Abc_ObjFaninC( pFanout, iFanin ) ) return 1; } return 0; } /**Function************************************************************* Synopsis [Prints the AIG node for debugging purposes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigPrintNode( Abc_Obj_t * pNode ) { Abc_Obj_t * pNodeR = Abc_ObjRegular(pNode); if ( Abc_ObjIsCi(pNodeR) ) { printf( "CI %4s%s.\n", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" ); return; } if ( Abc_AigNodeIsConst(pNodeR) ) { printf( "Constant 1 %s.\n", Abc_ObjIsComplement(pNode)? "(complemented)" : "" ); return; } // print the node's function printf( "%7s%s", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" ); printf( " = " ); printf( "%7s%s", Abc_ObjName(Abc_ObjFanin0(pNodeR)), Abc_ObjFaninC0(pNodeR)? "\'" : "" ); printf( " * " ); printf( "%7s%s", Abc_ObjName(Abc_ObjFanin1(pNodeR)), Abc_ObjFaninC1(pNodeR)? "\'" : "" ); printf( "\n" ); } /**Function************************************************************* Synopsis [Check if the node has a combination loop of depth 1 or 2.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot ) { Abc_Obj_t * pFanin0, * pFanin1; Abc_Obj_t * pChild00, * pChild01; Abc_Obj_t * pChild10, * pChild11; if ( !Abc_AigNodeIsAnd(pNode) ) return 1; pFanin0 = Abc_ObjFanin0(pNode); pFanin1 = Abc_ObjFanin1(pNode); if ( pRoot == pFanin0 || pRoot == pFanin1 ) return 0; if ( Abc_ObjIsCi(pFanin0) ) { pChild00 = NULL; pChild01 = NULL; } else { pChild00 = Abc_ObjFanin0(pFanin0); pChild01 = Abc_ObjFanin1(pFanin0); if ( pRoot == pChild00 || pRoot == pChild01 ) return 0; } if ( Abc_ObjIsCi(pFanin1) ) { pChild10 = NULL; pChild11 = NULL; } else { pChild10 = Abc_ObjFanin0(pFanin1); pChild11 = Abc_ObjFanin1(pFanin1); if ( pRoot == pChild10 || pRoot == pChild11 ) return 0; } return 1; } /**Function************************************************************* Synopsis [Resizes the hash table of AIG nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigCheckFaninOrder( Abc_Aig_t * pMan ) { Abc_Obj_t * pEnt; int i; for ( i = 0; i < pMan->nBins; i++ ) Abc_AigBinForEachEntry( pMan->pBins[i], pEnt ) { if ( Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id > Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id ) { // int i0 = Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id; // int i1 = Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id; printf( "Node %d has incorrect ordering of fanins.\n", pEnt->Id ); } } } /**Function************************************************************* Synopsis [Sets the correct phase of the nodes.] Description [The AIG nodes should be in the DFS order.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; assert( Abc_NtkIsDfsOrdered(pNtk) ); Abc_AigConst1(pNtk)->fPhase = 1; Abc_NtkForEachPi( pNtk, pObj, i ) pObj->fPhase = 0; Abc_NtkForEachLatchOutput( pNtk, pObj, i ) pObj->fPhase = Abc_LatchIsInit1(pObj); Abc_AigForEachAnd( pNtk, pObj, i ) pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)) & (Abc_ObjFanin1(pObj)->fPhase ^ Abc_ObjFaninC1(pObj)); Abc_NtkForEachPo( pNtk, pObj, i ) pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)); Abc_NtkForEachLatchInput( pNtk, pObj, i ) pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)); } /**Function************************************************************* Synopsis [Start the update list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_AigUpdateStart( Abc_Aig_t * pMan, Vec_Ptr_t ** pvUpdatedNets ) { assert( pMan->vAddedCells == NULL ); pMan->vAddedCells = Vec_PtrAlloc( 1000 ); pMan->vUpdatedNets = Vec_PtrAlloc( 1000 ); *pvUpdatedNets = pMan->vUpdatedNets; return pMan->vAddedCells; } /**Function************************************************************* Synopsis [Start the update list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigUpdateStop( Abc_Aig_t * pMan ) { assert( pMan->vAddedCells != NULL ); Vec_PtrFree( pMan->vAddedCells ); Vec_PtrFree( pMan->vUpdatedNets ); pMan->vAddedCells = NULL; pMan->vUpdatedNets = NULL; } /**Function************************************************************* Synopsis [Start the update list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigUpdateReset( Abc_Aig_t * pMan ) { assert( pMan->vAddedCells != NULL ); Vec_PtrClear( pMan->vAddedCells ); Vec_PtrClear( pMan->vUpdatedNets ); } /**Function************************************************************* Synopsis [Start the update list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_AigCountNext( Abc_Aig_t * pMan ) { Abc_Obj_t * pAnd; int i, Counter = 0, CounterTotal = 0; // count how many nodes have pNext set for ( i = 0; i < pMan->nBins; i++ ) Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) { Counter += (pAnd->pNext != NULL); CounterTotal++; } printf( "Counter = %d. Nodes = %d. Ave = %6.2f\n", Counter, CounterTotal, 1.0 * CounterTotal/pMan->nBins ); return Counter; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// void Abc_NtkHelloWorld( Abc_Ntk_t * pNtk ) { printf( "Hello, World!\n" ); } ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcBarBuf.c000066400000000000000000000445061477524141600164120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcHie.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures to handle hierarchy.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcHie.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define ABC_OBJ_VOID ((Abc_Obj_t *)(ABC_PTRINT_T)1) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks the the hie design has no duplicated networks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCheckSingleInstance( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pTemp, * pModel; Abc_Obj_t * pBox; int i, k, RetValue = 1; if ( pNtk->pDesign == NULL ) return 1; Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i ) pTemp->fHieVisited = 0; Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i ) Abc_NtkForEachBox( pTemp, pBox, k ) { pModel = (Abc_Ntk_t *)pBox->pData; if ( pModel == NULL ) continue; if ( Abc_NtkLatchNum(pModel) > 0 ) { printf( "Network \"%s\" contains %d flops.\n", Abc_NtkName(pNtk), Abc_NtkLatchNum(pModel) ); RetValue = 0; } if ( pModel->fHieVisited ) { printf( "Network \"%s\" contains box \"%s\" whose model \"%s\" is instantiated more than once.\n", Abc_NtkName(pNtk), Abc_ObjName(pBox), Abc_NtkName(pModel) ); RetValue = 0; } pModel->fHieVisited = 1; } Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i ) pTemp->fHieVisited = 0; return RetValue; } /**Function************************************************************* Synopsis [Collect PIs and POs of internal networks in the topo order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCollectPiPos_rec( Abc_Obj_t * pNet, Vec_Ptr_t * vLiMaps, Vec_Ptr_t * vLoMaps ) { extern int Abc_NtkCollectPiPos_int( Abc_Obj_t * pBox, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLiMaps, Vec_Ptr_t * vLoMaps ); Abc_Obj_t * pObj, * pFanin; int i, Counter = 0; assert( Abc_ObjIsNet(pNet) ); if ( Abc_NodeIsTravIdCurrent( pNet ) ) return 0; Abc_NodeSetTravIdCurrent( pNet ); pObj = Abc_ObjFanin0(pNet); if ( Abc_ObjIsNode(pObj) ) Abc_ObjForEachFanin( pObj, pFanin, i ) Counter += Abc_NtkCollectPiPos_rec( pFanin, vLiMaps, vLoMaps ); if ( Abc_ObjIsNode(pObj) ) return Counter; if ( Abc_ObjIsBo(pObj) ) pObj = Abc_ObjFanin0(pObj); assert( Abc_ObjIsBox(pObj) ); Abc_ObjForEachFanout( pObj, pFanin, i ) Abc_NodeSetTravIdCurrent( Abc_ObjFanout0(pFanin) ); Abc_ObjForEachFanin( pObj, pFanin, i ) Counter += Abc_NtkCollectPiPos_rec( Abc_ObjFanin0(pFanin), vLiMaps, vLoMaps ); Counter += Abc_NtkCollectPiPos_int( pObj, Abc_ObjModel(pObj), vLiMaps, vLoMaps ); return Counter; } int Abc_NtkCollectPiPos_int( Abc_Obj_t * pBox, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLiMaps, Vec_Ptr_t * vLoMaps ) { Abc_Obj_t * pObj; int i, Counter = 0; // mark primary inputs Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NodeSetTravIdCurrent( Abc_ObjFanout0(pObj) ); // add primary inputs if ( pBox ) { Abc_ObjForEachFanin( pBox, pObj, i ) Vec_PtrPush( vLiMaps, pObj ); Abc_NtkForEachPi( pNtk, pObj, i ) Vec_PtrPush( vLoMaps, pObj ); } // visit primary outputs Abc_NtkForEachPo( pNtk, pObj, i ) Counter += Abc_NtkCollectPiPos_rec( Abc_ObjFanin0(pObj), vLiMaps, vLoMaps ); // add primary outputs if ( pBox ) { Abc_NtkForEachPo( pNtk, pObj, i ) Vec_PtrPush( vLiMaps, pObj ); Abc_ObjForEachFanout( pBox, pObj, i ) Vec_PtrPush( vLoMaps, pObj ); Counter++; } return Counter; } int Abc_NtkCollectPiPos( Abc_Ntk_t * pNtk, Vec_Ptr_t ** pvLiMaps, Vec_Ptr_t ** pvLoMaps ) { assert( Abc_NtkIsNetlist(pNtk) ); *pvLiMaps = Vec_PtrAlloc( 1000 ); *pvLoMaps = Vec_PtrAlloc( 1000 ); return Abc_NtkCollectPiPos_int( NULL, pNtk, *pvLiMaps, *pvLoMaps ); } /**Function************************************************************* Synopsis [Derives logic network with barbufs from the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkToBarBufs_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNet ) { Abc_Obj_t * pObj, * pFanin; int i; assert( Abc_ObjIsNet(pNet) ); if ( pNet->pCopy ) return pNet->pCopy; pObj = Abc_ObjFanin0(pNet); assert( Abc_ObjIsNode(pObj) ); pNet->pCopy = Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_ObjForEachFanin( pObj, pFanin, i ) Abc_ObjAddFanin( pObj->pCopy, Abc_NtkToBarBufs_rec(pNtkNew, pFanin) ); return pNet->pCopy; } Abc_Ntk_t * Abc_NtkToBarBufs( Abc_Ntk_t * pNtk ) { char Buffer[1000]; Vec_Ptr_t * vLiMaps, * vLoMaps; Abc_Ntk_t * pNtkNew, * pTemp; Abc_Obj_t * pLatch, * pObjLi, * pObjLo; Abc_Obj_t * pObj, * pLiMap, * pLoMap; int i, k, nBoxes; assert( Abc_NtkIsNetlist(pNtk) ); if ( !Abc_NtkCheckSingleInstance(pNtk) ) return NULL; assert( pNtk->pDesign != NULL ); // start the network pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, pNtk->ntkFunc, 1 ); pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // clone CIs/CIs/boxes Abc_NtkCleanCopy_rec( pNtk ); Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjFanout0(pObj)->pCopy = Abc_NtkDupObj( pNtkNew, pObj, 1 ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 1 ); // create latches and transfer copy labels nBoxes = Abc_NtkCollectPiPos( pNtk, &vLiMaps, &vLoMaps ); Vec_PtrForEachEntryTwo( Abc_Obj_t *, vLiMaps, Abc_Obj_t *, vLoMaps, pLiMap, pLoMap, i ) { pObjLi = Abc_NtkCreateBi(pNtkNew); pLatch = Abc_NtkCreateLatch(pNtkNew); pObjLo = Abc_NtkCreateBo(pNtkNew); Abc_ObjAddFanin( pLatch, pObjLi ); Abc_ObjAddFanin( pObjLo, pLatch ); pLatch->pData = (void *)ABC_INIT_ZERO; pTemp = NULL; if ( Abc_ObjFanin0(pLiMap)->pNtk != pNtk ) pTemp = Abc_ObjFanin0(pLiMap)->pNtk; else if ( Abc_ObjFanout0(pLoMap)->pNtk != pNtk ) pTemp = Abc_ObjFanout0(pLoMap)->pNtk; else assert( 0 ); sprintf( Buffer, "_%s_in", Abc_NtkName(pTemp) ); Abc_ObjAssignName( pObjLi, Abc_ObjName(Abc_ObjFanin0(pLiMap)), Buffer ); sprintf( Buffer, "_%s_out", Abc_NtkName(pTemp) ); Abc_ObjAssignName( pObjLo, Abc_ObjName(Abc_ObjFanout0(pLoMap)), Buffer ); pLiMap->pCopy = pObjLi; Abc_ObjFanout0(pLoMap)->pCopy = pObjLo; assert( Abc_ObjIsNet(Abc_ObjFanout0(pLoMap)) ); } Vec_PtrFree( vLiMaps ); Vec_PtrFree( vLoMaps ); // rebuild networks Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i ) Abc_NtkForEachCo( pTemp, pObj, k ) Abc_ObjAddFanin( pObj->pCopy, Abc_NtkToBarBufs_rec(pNtkNew, Abc_ObjFanin0(pObj)) ); pNtkNew->nBarBufs = Abc_NtkLatchNum(pNtkNew); printf( "Hierarchy reader flattened %d instances of logic boxes and introduced %d barbufs.\n", nBoxes, pNtkNew->nBarBufs ); return pNtkNew; } /**Function************************************************************* Synopsis [Converts the logic with barbufs into a hierarchical network.] Description [The base network is the original hierarchical network. The second argument is the optimized network with barbufs. This procedure reconstructs the original hierarcical network which adding logic from the optimized network. It is assumed that the PIs/POs of the original network one-to-one mapping with the flops of the optimized network.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkFromBarBufs_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; if ( pObj->pCopy ) return pObj->pCopy; Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_ObjForEachFanin( pObj, pFanin, i ) Abc_ObjAddFanin( pObj->pCopy, Abc_NtkFromBarBufs_rec(pNtkNew, pFanin) ); return pObj->pCopy; } Abc_Ntk_t * Abc_NtkFromBarBufs( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew, * pTemp; Vec_Ptr_t * vLiMaps, * vLoMaps; Abc_Obj_t * pObj, * pLiMap, * pLoMap; int i, k; assert( pNtkBase->pDesign != NULL ); assert( Abc_NtkIsNetlist(pNtk) ); assert( Abc_NtkIsNetlist(pNtkBase) ); assert( Abc_NtkLatchNum(pNtkBase) == 0 ); assert( Abc_NtkLatchNum(pNtk) == pNtk->nBarBufs ); assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); assert( Abc_NtkBlackboxNum(pNtk) == 0 ); assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkBase) ); assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkBase) ); // start networks Abc_NtkCleanCopy_rec( pNtkBase ); Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkBase->pDesign->vModules, pTemp, i ) pTemp->pCopy = Abc_NtkStartFrom( pTemp, pNtk->ntkType, pNtk->ntkFunc ); Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkBase->pDesign->vModules, pTemp, i ) pTemp->pCopy->pAltView = pTemp->pAltView ? pTemp->pAltView->pCopy : NULL; // update box models Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkBase->pDesign->vModules, pTemp, i ) Abc_NtkForEachBox( pTemp, pObj, k ) if ( Abc_ObjIsWhitebox(pObj) || Abc_ObjIsBlackbox(pObj) ) pObj->pCopy->pData = Abc_ObjModel(pObj)->pCopy; // create the design pNtkNew = pNtkBase->pCopy; pNtkNew->pDesign = Abc_DesCreate( pNtkBase->pDesign->pName ); Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkBase->pDesign->vModules, pTemp, i ) Abc_DesAddModel( pNtkNew->pDesign, pTemp->pCopy ); Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkBase->pDesign->vTops, pTemp, i ) Vec_PtrPush( pNtkNew->pDesign->vTops, pTemp->pCopy ); assert( Vec_PtrEntry(pNtkNew->pDesign->vTops, 0) == pNtkNew ); // transfer copy attributes to pNtk Abc_NtkCleanCopy( pNtk ); Abc_NtkForEachPi( pNtk, pObj, i ) pObj->pCopy = Abc_NtkPi(pNtkNew, i); Abc_NtkForEachPo( pNtk, pObj, i ) pObj->pCopy = Abc_NtkPo(pNtkNew, i); Abc_NtkCollectPiPos( pNtkBase, &vLiMaps, &vLoMaps ); assert( Vec_PtrSize(vLiMaps) == Abc_NtkLatchNum(pNtk) ); assert( Vec_PtrSize(vLoMaps) == Abc_NtkLatchNum(pNtk) ); Vec_PtrForEachEntryTwo( Abc_Obj_t *, vLiMaps, Abc_Obj_t *, vLoMaps, pLiMap, pLoMap, i ) { pObj = Abc_NtkBox( pNtk, i ); Abc_ObjFanin0(pObj)->pCopy = pLiMap->pCopy; Abc_ObjFanout0(pObj)->pCopy = pLoMap->pCopy; } Vec_PtrFree( vLiMaps ); Vec_PtrFree( vLoMaps ); // create internal nodes Abc_NtkForEachCo( pNtk, pObj, i ) Abc_ObjAddFanin( pObj->pCopy, Abc_NtkFromBarBufs_rec(pObj->pCopy->pNtk, Abc_ObjFanin0(pObj)) ); // transfer net names Abc_NtkForEachCi( pNtk, pObj, i ) { if ( Abc_ObjFanoutNum(pObj->pCopy) == 0 ) // handle PI without fanout Abc_ObjAddFanin( Abc_NtkCreateNet(pObj->pCopy->pNtk), pObj->pCopy ); Nm_ManStoreIdName( pObj->pCopy->pNtk->pManName, Abc_ObjFanout0(pObj->pCopy)->Id, Abc_ObjFanout0(pObj->pCopy)->Type, Abc_ObjName(Abc_ObjFanout0(pObj)), NULL ); } Abc_NtkForEachCo( pNtk, pObj, i ) Nm_ManStoreIdName( pObj->pCopy->pNtk->pManName, Abc_ObjFanin0(pObj->pCopy)->Id, Abc_ObjFanin0(pObj->pCopy)->Type, Abc_ObjName(Abc_ObjFanin0(pObj)), NULL ); return pNtkNew; } /**Function************************************************************* Synopsis [Collect nodes in the barbuf-friendly order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkToBarBufsCollect_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanin; int i; if ( Abc_NodeIsTravIdCurrent( pObj ) ) return; Abc_NodeSetTravIdCurrent( pObj ); assert( Abc_ObjIsNode(pObj) ); Abc_ObjForEachFanin( pObj, pFanin, i ) Abc_NtkToBarBufsCollect_rec( pFanin, vNodes ); Vec_PtrPush( vNodes, pObj ); } Vec_Ptr_t * Abc_NtkToBarBufsCollect( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i; assert( Abc_NtkIsLogic(pNtk) ); assert( pNtk->nBarBufs > 0 ); assert( pNtk->nBarBufs == Abc_NtkLatchNum(pNtk) ); vNodes = Vec_PtrAlloc( Abc_NtkObjNum(pNtk) ); Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachCi( pNtk, pObj, i ) { if ( i >= Abc_NtkCiNum(pNtk) - pNtk->nBarBufs ) break; Vec_PtrPush( vNodes, pObj ); Abc_NodeSetTravIdCurrent( pObj ); } Abc_NtkForEachCo( pNtk, pObj, i ) { if ( i < Abc_NtkCoNum(pNtk) - pNtk->nBarBufs ) continue; Abc_NtkToBarBufsCollect_rec( Abc_ObjFanin0(pObj), vNodes ); Vec_PtrPush( vNodes, pObj ); Vec_PtrPush( vNodes, Abc_ObjFanout0(pObj) ); Vec_PtrPush( vNodes, Abc_ObjFanout0(Abc_ObjFanout0(pObj)) ); Abc_NodeSetTravIdCurrent( pObj ); Abc_NodeSetTravIdCurrent( Abc_ObjFanout0(pObj) ); Abc_NodeSetTravIdCurrent( Abc_ObjFanout0(Abc_ObjFanout0(pObj)) ); } Abc_NtkForEachCo( pNtk, pObj, i ) { if ( i >= Abc_NtkCoNum(pNtk) - pNtk->nBarBufs ) break; Abc_NtkToBarBufsCollect_rec( Abc_ObjFanin0(pObj), vNodes ); Vec_PtrPush( vNodes, pObj ); Abc_NodeSetTravIdCurrent( pObj ); } assert( Vec_PtrSize(vNodes) == Abc_NtkObjNum(pNtk) ); return vNodes; } /**Function************************************************************* Synopsis [Count barrier buffers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCountBarBufs( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i, Counter = 0; Abc_NtkForEachNode( pNtk, pObj, i ) Counter += Abc_ObjIsBarBuf( pObj ); return Counter; } /**Function************************************************************* Synopsis [Converts the network to dedicated barbufs and back.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkBarBufsToBuffers( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin; int i, k; assert( Abc_NtkIsLogic(pNtk) ); assert( pNtk->pDesign == NULL ); assert( pNtk->nBarBufs > 0 ); assert( pNtk->nBarBufs == Abc_NtkLatchNum(pNtk) ); vNodes = Abc_NtkToBarBufsCollect( pNtk ); // start the network pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, pNtk->ntkFunc, 1 ); pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // create objects Abc_NtkCleanCopy( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { if ( Abc_ObjIsPi(pObj) ) Abc_NtkDupObj( pNtkNew, pObj, 1 ); else if ( Abc_ObjIsPo( pObj) ) Abc_ObjAddFanin( Abc_NtkDupObj(pNtkNew, pObj, 1), Abc_ObjFanin0(pObj)->pCopy ); else if ( Abc_ObjIsBi(pObj) || Abc_ObjIsBo(pObj) ) pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy; else if ( Abc_ObjIsLatch(pObj) ) Abc_ObjAddFanin( (pObj->pCopy = Abc_NtkCreateNode(pNtkNew)), Abc_ObjFanin0(pObj)->pCopy ); else if ( Abc_ObjIsNode(pObj) ) { Abc_NtkDupObj( pNtkNew, pObj, 1 ); Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } else assert( 0 ); } Vec_PtrFree( vNodes ); return pNtkNew; } Abc_Ntk_t * Abc_NtkBarBufsFromBuffers( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin, * pLatch; int i, k, nBarBufs; assert( Abc_NtkIsLogic(pNtkBase) ); assert( Abc_NtkIsLogic(pNtk) ); assert( pNtkBase->nBarBufs == Abc_NtkLatchNum(pNtkBase) ); // start the network pNtkNew = Abc_NtkStartFrom( pNtkBase, pNtk->ntkType, pNtk->ntkFunc ); // transfer PI pointers Abc_NtkForEachPi( pNtk, pObj, i ) pObj->pCopy = Abc_NtkPi(pNtkNew, i); // assuming that the order/number of barbufs remains the same nBarBufs = 0; Abc_NtkForEachNode( pNtk, pObj, i ) { if ( Abc_ObjIsBarBuf(pObj) ) { pLatch = Abc_NtkBox(pNtkNew, nBarBufs++); Abc_ObjAddFanin( Abc_ObjFanin0(pLatch), Abc_ObjFanin0(pObj)->pCopy ); pObj->pCopy = Abc_ObjFanout0(pLatch); } else { Abc_NtkDupObj( pNtkNew, pObj, 1 ); Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } } assert( nBarBufs == pNtkBase->nBarBufs ); // connect POs Abc_NtkForEachPo( pNtk, pObj, i ) Abc_ObjAddFanin( Abc_NtkPo(pNtkNew, i), Abc_ObjFanin0(pObj)->pCopy ); return pNtkNew; } Abc_Ntk_t * Abc_NtkBarBufsOnOffTest( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew, * pNtkNew2; pNtkNew = Abc_NtkBarBufsToBuffers( pNtk ); pNtkNew2 = Abc_NtkBarBufsFromBuffers( pNtk, pNtkNew ); Abc_NtkDelete( pNtkNew ); return pNtkNew2; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcBlifMv.c000066400000000000000000001143371477524141600164300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcBlifMv.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures to process BLIF-MV networks and AIGs.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the Mv-Var manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ) { Vec_Att_t * pAttMan; assert( Abc_NtkMvVar(pNtk) == NULL ); pAttMan = Vec_AttAlloc( Abc_NtkObjNumMax(pNtk) + 1, Mem_FlexStart(), (void(*)(void*))Mem_FlexStop, NULL, NULL ); Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_MVVAR, pAttMan ); //printf( "allocing attr\n" ); } /**Function************************************************************* Synopsis [Stops the Mv-Var manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk ) { Mem_Flex_t * pUserMan; pUserMan = (Mem_Flex_t *)Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, 0 ); Mem_FlexStop( pUserMan, 0 ); } /**Function************************************************************* Synopsis [Duplicate the MV variable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues ) { Mem_Flex_t * pFlex; struct temp { int nValues; char ** pNames; } * pVarStruct; assert( nValues > 1 ); // skip binary signals if ( nValues == 2 ) return; // skip already assigned signals if ( Abc_ObjMvVar(pObj) != NULL ) return; // create the structure pFlex = (Mem_Flex_t *)Abc_NtkMvVarMan( pObj->pNtk ); pVarStruct = (struct temp *)Mem_FlexEntryFetch( pFlex, sizeof(struct temp) ); pVarStruct->nValues = nValues; pVarStruct->pNames = NULL; Abc_ObjSetMvVar( pObj, pVarStruct ); } /**Function************************************************************* Synopsis [Strashes the BLIF-MV netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_StringGetNumber( char ** ppStr ) { char * pStr = *ppStr; int Number = 0; assert( *pStr >= '0' && *pStr <= '9' ); for ( ; *pStr >= '0' && *pStr <= '9'; pStr++ ) Number = 10 * Number + *pStr - '0'; *ppStr = pStr; return Number; } /**Function************************************************************* Synopsis [Strashes one node in the BLIF-MV netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeStrashBlifMv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj ) { int fAddFreeVars = 1; char * pSop; Abc_Obj_t ** pValues, ** pValuesF, ** pValuesF2; Abc_Obj_t * pTemp, * pTemp2, * pFanin, * pFanin2, * pNet; int k, v, Def, DefIndex, Index, nValues, nValuesF, nValuesF2; // start the output values assert( Abc_ObjIsNode(pObj) ); pNet = Abc_ObjFanout0(pObj); nValues = Abc_ObjMvVarNum(pNet); pValues = ABC_ALLOC( Abc_Obj_t *, nValues ); for ( k = 0; k < nValues; k++ ) pValues[k] = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); // get the BLIF-MV formula pSop = (char *)pObj->pData; // skip the value line // while ( *pSop++ != '\n' ); // handle the constant if ( Abc_ObjFaninNum(pObj) == 0 ) { // skip the default if present if ( *pSop == 'd' ) while ( *pSop++ != '\n' ); // skip space if present if ( *pSop == ' ' ) pSop++; // assume don't-care constant to be zero if ( *pSop == '-' ) Index = 0; else Index = Abc_StringGetNumber( &pSop ); assert( Index < nValues ); //////////////////////////////////////////// // adding free variables for binary ND-constants if ( fAddFreeVars && nValues == 2 && *pSop == '-' ) { pValues[1] = Abc_NtkCreatePi(pNtkNew); pValues[0] = Abc_ObjNot( pValues[1] ); Abc_ObjAssignName( pValues[1], "free_var_", Abc_ObjName(pValues[1]) ); } else pValues[Index] = Abc_AigConst1(pNtkNew); //////////////////////////////////////////// // save the values in the fanout net pNet->pCopy = (Abc_Obj_t *)pValues; return 1; } // parse the default line Def = DefIndex = -1; if ( *pSop == 'd' ) { pSop++; if ( *pSop == '=' ) { pSop++; DefIndex = Abc_StringGetNumber( &pSop ); assert( DefIndex < Abc_ObjFaninNum(pObj) ); } else if ( *pSop == '-' ) { pSop++; Def = 0; } else { Def = Abc_StringGetNumber( &pSop ); assert( Def < nValues ); } assert( *pSop == '\n' ); pSop++; } // convert the values while ( *pSop ) { // extract the values for each cube pTemp = Abc_AigConst1(pNtkNew); Abc_ObjForEachFanin( pObj, pFanin, k ) { if ( *pSop == '-' ) { pSop += 2; continue; } if ( *pSop == '!' ) { ABC_FREE( pValues ); printf( "Abc_NodeStrashBlifMv(): Cannot handle complement in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) ); return 0; } if ( *pSop == '{' ) { ABC_FREE( pValues ); printf( "Abc_NodeStrashBlifMv(): Cannot handle braces in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) ); return 0; } // get the value set nValuesF = Abc_ObjMvVarNum(pFanin); pValuesF = (Abc_Obj_t **)pFanin->pCopy; if ( *pSop == '(' ) { pSop++; pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); while ( *pSop != ')' ) { Index = Abc_StringGetNumber( &pSop ); assert( Index < nValuesF ); pTemp2 = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp2, pValuesF[Index] ); assert( *pSop == ')' || *pSop == ',' ); if ( *pSop == ',' ) pSop++; } assert( *pSop == ')' ); pSop++; } else if ( *pSop == '=' ) { pSop++; // get the fanin index Index = Abc_StringGetNumber( &pSop ); assert( Index < Abc_ObjFaninNum(pObj) ); assert( Index != k ); // get the fanin pFanin2 = Abc_ObjFanin( pObj, Index ); nValuesF2 = Abc_ObjMvVarNum(pFanin2); pValuesF2 = (Abc_Obj_t **)pFanin2->pCopy; // create the sum of products of values assert( nValuesF == nValuesF2 ); pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); for ( v = 0; v < nValues; v++ ) pTemp2 = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp2, Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pValuesF[v], pValuesF2[v]) ); } else { Index = Abc_StringGetNumber( &pSop ); assert( Index < nValuesF ); pTemp2 = pValuesF[Index]; } // compute the compute pTemp = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp, pTemp2 ); // advance the reading point assert( *pSop == ' ' ); pSop++; } // check if the output value is an equal construct if ( *pSop == '=' ) { pSop++; // get the output value Index = Abc_StringGetNumber( &pSop ); assert( Index < Abc_ObjFaninNum(pObj) ); // add values of the given fanin with the given cube pFanin = Abc_ObjFanin( pObj, Index ); nValuesF = Abc_ObjMvVarNum(pFanin); pValuesF = (Abc_Obj_t **)pFanin->pCopy; assert( nValuesF == nValues ); // should be guaranteed by the parser for ( k = 0; k < nValuesF; k++ ) pValues[k] = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pValues[k], Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pTemp, pValuesF[k]) ); } else { // get the output value Index = Abc_StringGetNumber( &pSop ); assert( Index < nValues ); pValues[Index] = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pValues[Index], pTemp ); } // advance the reading point assert( *pSop == '\n' ); pSop++; } // compute the default value if ( Def >= 0 || DefIndex >= 0 ) { pTemp = Abc_AigConst1(pNtkNew); for ( k = 0; k < nValues; k++ ) { if ( k == Def ) continue; pTemp = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp, Abc_ObjNot(pValues[k]) ); } // assign the default value if ( Def >= 0 ) pValues[Def] = pTemp; else { assert( DefIndex >= 0 ); // add values of the given fanin with the given cube pFanin = Abc_ObjFanin( pObj, DefIndex ); nValuesF = Abc_ObjMvVarNum(pFanin); pValuesF = (Abc_Obj_t **)pFanin->pCopy; assert( nValuesF == nValues ); // should be guaranteed by the parser for ( k = 0; k < nValuesF; k++ ) pValues[k] = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pValues[k], Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pTemp, pValuesF[k]) ); } } // save the values in the fanout net pNet->pCopy = (Abc_Obj_t *)pValues; return 1; } /**Function************************************************************* Synopsis [Assigns name with index.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_NtkConvertAssignName( Abc_Obj_t * pObj, Abc_Obj_t * pNet, int Index ) { char Suffix[16]; assert( Abc_ObjIsTerm(pObj) ); assert( Abc_ObjIsNet(pNet) ); sprintf( Suffix, "[%d]", Index ); Abc_ObjAssignName( pObj, Abc_ObjName(pNet), Suffix ); } /**Function************************************************************* Synopsis [Strashes the BLIF-MV netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk ) { int fUsePositional = 0; Vec_Ptr_t * vNodes; Abc_Obj_t ** pBits; Abc_Obj_t ** pValues; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pTemp, * pBit, * pNet; int i, k, v, nValues, nValuesMax, nBits; int nCount1, nCount2; assert( Abc_NtkIsNetlist(pNtk) ); assert( Abc_NtkHasBlifMv(pNtk) ); assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); assert( Abc_NtkBlackboxNum(pNtk) == 0 ); // get the largest number of values nValuesMax = 2; Abc_NtkForEachNet( pNtk, pObj, i ) { nValues = Abc_ObjMvVarNum(pObj); if ( nValuesMax < nValues ) nValuesMax = nValues; } nBits = Abc_Base2Log( nValuesMax ); pBits = ABC_ALLOC( Abc_Obj_t *, nBits ); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); // collect the nodes vNodes = Abc_NtkDfs( pNtk, 0 ); // start the network pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); // duplicate the name and the spec pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); // pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName ); nCount1 = nCount2 = 0; // encode the CI nets Abc_NtkIncrementTravId( pNtk ); if ( fUsePositional ) { Abc_NtkForEachCi( pNtk, pObj, i ) { if ( !Abc_ObjIsPi(pObj) ) continue; pNet = Abc_ObjFanout0(pObj); nValues = Abc_ObjMvVarNum(pNet); pValues = ABC_ALLOC( Abc_Obj_t *, nValues ); // create PIs for the values for ( v = 0; v < nValues; v++ ) { pValues[v] = Abc_NtkCreatePi( pNtkNew ); if ( nValuesMax == 2 ) Abc_ObjAssignName( pValues[v], Abc_ObjName(pNet), NULL ); else Abc_NtkConvertAssignName( pValues[v], pNet, v ); } // save the values in the fanout net pNet->pCopy = (Abc_Obj_t *)pValues; // mark the net Abc_NodeSetTravIdCurrent( pNet ); } Abc_NtkForEachCi( pNtk, pObj, i ) { if ( Abc_ObjIsPi(pObj) ) continue; pNet = Abc_ObjFanout0(pObj); nValues = Abc_ObjMvVarNum(pNet); pValues = ABC_ALLOC( Abc_Obj_t *, nValues ); // create PIs for the values for ( v = 0; v < nValues; v++ ) { pValues[v] = Abc_NtkCreateBo( pNtkNew ); if ( nValuesMax == 2 ) Abc_ObjAssignName( pValues[v], Abc_ObjName(pNet), NULL ); else Abc_NtkConvertAssignName( pValues[v], pNet, v ); nCount1++; } // save the values in the fanout net pNet->pCopy = (Abc_Obj_t *)pValues; // mark the net Abc_NodeSetTravIdCurrent( pNet ); } } else { Abc_NtkForEachCi( pNtk, pObj, i ) { if ( !Abc_ObjIsPi(pObj) ) continue; pNet = Abc_ObjFanout0(pObj); nValues = Abc_ObjMvVarNum(pNet); pValues = ABC_ALLOC( Abc_Obj_t *, nValues ); // create PIs for the encoding bits nBits = Abc_Base2Log( nValues ); for ( k = 0; k < nBits; k++ ) { pBits[k] = Abc_NtkCreatePi( pNtkNew ); if ( nValuesMax == 2 ) Abc_ObjAssignName( pBits[k], Abc_ObjName(pNet), NULL ); else Abc_NtkConvertAssignName( pBits[k], pNet, k ); } // encode the values for ( v = 0; v < nValues; v++ ) { pValues[v] = Abc_AigConst1(pNtkNew); for ( k = 0; k < nBits; k++ ) { pBit = Abc_ObjNotCond( pBits[k], (v&(1<pManFunc, pValues[v], pBit ); } } // save the values in the fanout net pNet->pCopy = (Abc_Obj_t *)pValues; // mark the net Abc_NodeSetTravIdCurrent( pNet ); } Abc_NtkForEachCi( pNtk, pObj, i ) { if ( Abc_ObjIsPi(pObj) ) continue; pNet = Abc_ObjFanout0(pObj); nValues = Abc_ObjMvVarNum(pNet); pValues = ABC_ALLOC( Abc_Obj_t *, nValues ); // create PIs for the encoding bits nBits = Abc_Base2Log( nValues ); for ( k = 0; k < nBits; k++ ) { pBits[k] = Abc_NtkCreateBo( pNtkNew ); if ( nValuesMax == 2 ) Abc_ObjAssignName( pBits[k], Abc_ObjName(pNet), NULL ); else Abc_NtkConvertAssignName( pBits[k], pNet, k ); nCount1++; } // encode the values for ( v = 0; v < nValues; v++ ) { pValues[v] = Abc_AigConst1(pNtkNew); for ( k = 0; k < nBits; k++ ) { pBit = Abc_ObjNotCond( pBits[k], (v&(1<pManFunc, pValues[v], pBit ); } } // save the values in the fanout net pNet->pCopy = (Abc_Obj_t *)pValues; // mark the net Abc_NodeSetTravIdCurrent( pNet ); } } // process nodes in the topological order Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) if ( !Abc_NodeStrashBlifMv( pNtkNew, pObj ) ) { Abc_NtkDelete( pNtkNew ); return NULL; } Vec_PtrFree( vNodes ); // encode the CO nets if ( fUsePositional ) { Abc_NtkForEachCo( pNtk, pObj, i ) { if ( !Abc_ObjIsPo(pObj) ) continue; pNet = Abc_ObjFanin0(pObj); // skip marked nets // if ( Abc_NodeIsTravIdCurrent(pNet) ) // continue; // Abc_NodeSetTravIdCurrent( pNet ); nValues = Abc_ObjMvVarNum(pNet); pValues = (Abc_Obj_t **)pNet->pCopy; for ( v = 0; v < nValues; v++ ) { pTemp = Abc_NtkCreatePo( pNtkNew ); Abc_ObjAddFanin( pTemp, pValues[v] ); if ( nValuesMax == 2 ) Abc_ObjAssignName( pTemp, Abc_ObjName(pNet), NULL ); else Abc_NtkConvertAssignName( pTemp, pNet, v ); } } Abc_NtkForEachCo( pNtk, pObj, i ) { if ( Abc_ObjIsPo(pObj) ) continue; pNet = Abc_ObjFanin0(pObj); // skip marked nets // if ( Abc_NodeIsTravIdCurrent(pNet) ) // continue; // Abc_NodeSetTravIdCurrent( pNet ); nValues = Abc_ObjMvVarNum(pNet); pValues = (Abc_Obj_t **)pNet->pCopy; for ( v = 0; v < nValues; v++ ) { pTemp = Abc_NtkCreateBi( pNtkNew ); Abc_ObjAddFanin( pTemp, pValues[v] ); if ( nValuesMax == 2 ) Abc_ObjAssignName( pTemp, Abc_ObjName(pNet), NULL ); else Abc_NtkConvertAssignName( pTemp, pNet, v ); nCount2++; } } } else // if ( fPositional == 0 ) { Abc_NtkForEachCo( pNtk, pObj, i ) { if ( !Abc_ObjIsPo(pObj) ) continue; pNet = Abc_ObjFanin0(pObj); // skip marked nets // if ( Abc_NodeIsTravIdCurrent(pNet) ) // continue; // Abc_NodeSetTravIdCurrent( pNet ); nValues = Abc_ObjMvVarNum(pNet); pValues = (Abc_Obj_t **)pNet->pCopy; nBits = Abc_Base2Log( nValues ); for ( k = 0; k < nBits; k++ ) { pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); for ( v = 0; v < nValues; v++ ) if ( v & (1<pManFunc, pBit, pValues[v] ); pTemp = Abc_NtkCreatePo( pNtkNew ); Abc_ObjAddFanin( pTemp, pBit ); if ( nValuesMax == 2 ) Abc_ObjAssignName( pTemp, Abc_ObjName(pNet), NULL ); else Abc_NtkConvertAssignName( pTemp, pNet, k ); } } Abc_NtkForEachCo( pNtk, pObj, i ) { if ( Abc_ObjIsPo(pObj) ) continue; pNet = Abc_ObjFanin0(pObj); // skip marked nets // if ( Abc_NodeIsTravIdCurrent(pNet) ) // continue; // Abc_NodeSetTravIdCurrent( pNet ); nValues = Abc_ObjMvVarNum(pNet); pValues = (Abc_Obj_t **)pNet->pCopy; nBits = Abc_Base2Log( nValues ); for ( k = 0; k < nBits; k++ ) { pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); for ( v = 0; v < nValues; v++ ) if ( v & (1<pManFunc, pBit, pValues[v] ); pTemp = Abc_NtkCreateBi( pNtkNew ); Abc_ObjAddFanin( pTemp, pBit ); if ( nValuesMax == 2 ) Abc_ObjAssignName( pTemp, Abc_ObjName(pNet), NULL ); else Abc_NtkConvertAssignName( pTemp, pNet, k ); nCount2++; } } } if ( Abc_NtkLatchNum(pNtk) ) { Vec_Ptr_t * vTemp; Abc_Obj_t * pLatch, * pObjLi, * pObjLo; int i; // move free vars to the front among the PIs vTemp = Vec_PtrAlloc( Vec_PtrSize(pNtkNew->vPis) ); Abc_NtkForEachPi( pNtkNew, pObj, i ) if ( strncmp( Abc_ObjName(pObj), "free_var_", 9 ) == 0 ) Vec_PtrPush( vTemp, pObj ); Abc_NtkForEachPi( pNtkNew, pObj, i ) if ( strncmp( Abc_ObjName(pObj), "free_var_", 9 ) != 0 ) Vec_PtrPush( vTemp, pObj ); assert( Vec_PtrSize(vTemp) == Vec_PtrSize(pNtkNew->vPis) ); Vec_PtrFree( pNtkNew->vPis ); pNtkNew->vPis = vTemp; // move free vars to the front among the CIs vTemp = Vec_PtrAlloc( Vec_PtrSize(pNtkNew->vCis) ); Abc_NtkForEachCi( pNtkNew, pObj, i ) if ( strncmp( Abc_ObjName(pObj), "free_var_", 9 ) == 0 ) Vec_PtrPush( vTemp, pObj ); Abc_NtkForEachCi( pNtkNew, pObj, i ) if ( strncmp( Abc_ObjName(pObj), "free_var_", 9 ) != 0 ) Vec_PtrPush( vTemp, pObj ); assert( Vec_PtrSize(vTemp) == Vec_PtrSize(pNtkNew->vCis) ); Vec_PtrFree( pNtkNew->vCis ); pNtkNew->vCis = vTemp; // create registers assert( nCount1 == nCount2 ); for ( i = 0; i < nCount1; i++ ) { // create latch pLatch = Abc_NtkCreateLatch( pNtkNew ); Abc_LatchSetInit0( pLatch ); Abc_ObjAssignName( pLatch, Abc_ObjName(pLatch), NULL ); // connect pObjLi = Abc_NtkCo( pNtkNew, Abc_NtkCoNum(pNtkNew)-nCount1+i ); pObjLo = Abc_NtkCi( pNtkNew, Abc_NtkCiNum(pNtkNew)-nCount1+i ); Abc_ObjAddFanin( pLatch, pObjLi ); Abc_ObjAddFanin( pObjLo, pLatch ); } } // cleanup ABC_FREE( pBits ); Abc_NtkForEachObj( pNtk, pObj, i ) if ( pObj->pCopy ) ABC_FREE( pObj->pCopy ); // remove dangling nodes i = Abc_AigCleanup((Abc_Aig_t *)pNtkNew->pManFunc); // printf( "Cleanup removed %d nodes.\n", i ); // Abc_NtkReassignIds( pNtkNew ); // check integrity if ( !Abc_NtkCheck( pNtkNew ) ) { fprintf( stdout, "Abc_NtkStrashBlifMv(): Network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Extract the MV-skeleton of the BLIF-MV network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkSkeletonBlifMv( Abc_Ntk_t * pNtk ) { int fUsePositional = 0; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pNet, * pNetNew, * pNodeNew, * pTermNew, * pBoxNew; int i, k, v, nValues, nBits; assert( Abc_NtkIsNetlist(pNtk) ); assert( Abc_NtkHasBlifMv(pNtk) ); assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); assert( Abc_NtkBlackboxNum(pNtk) == 0 ); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); // duplicate the name and the spec pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName ); // create the internal box (it is important to put it first!) pBoxNew = Abc_NtkCreateWhitebox( pNtkNew ); // create PIs and their nets Abc_NtkForEachPi( pNtk, pObj, i ) { Abc_NtkDupObj( pNtkNew, pObj, 0 ); pNet = Abc_ObjFanout0(pObj); Abc_NtkDupObj( pNtkNew, pNet, 1 ); Abc_ObjAddFanin( pNet->pCopy, pObj->pCopy ); } // create POs and their nets Abc_NtkForEachPo( pNtk, pObj, i ) { Abc_NtkDupObj( pNtkNew, pObj, 0 ); pNet = Abc_ObjFanin0(pObj); if ( pNet->pCopy == NULL ) Abc_NtkDupObj( pNtkNew, pNet, 1 ); Abc_ObjAddFanin( pObj->pCopy, pNet->pCopy ); } // create latches Abc_NtkForEachLatch( pNtk, pObj, i ) { Abc_NtkDupBox( pNtkNew, pObj, 0 ); // latch outputs pNet = Abc_ObjFanout0(Abc_ObjFanout0(pObj)); assert( pNet->pCopy == NULL ); Abc_NtkDupObj( pNtkNew, pNet, 1 ); Abc_ObjAddFanin( pNet->pCopy, Abc_ObjFanout0(pObj)->pCopy ); // latch inputs pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); if ( pNet->pCopy == NULL ) Abc_NtkDupObj( pNtkNew, pNet, 1 ); Abc_ObjAddFanin( Abc_ObjFanin0(pObj)->pCopy, pNet->pCopy ); } // encode the CI nets Abc_NtkIncrementTravId( pNtk ); if ( fUsePositional ) { Abc_NtkForEachCi( pNtk, pObj, i ) { pNet = Abc_ObjFanout0(pObj); nValues = Abc_ObjMvVarNum(pNet); for ( v = 0; v < nValues; v++ ) { pNodeNew = Abc_NtkCreateNode( pNtkNew ); pNodeNew->pData = Abc_SopEncoderPos( (Mem_Flex_t *)pNtkNew->pManFunc, v, nValues ); pNetNew = Abc_NtkCreateNet( pNtkNew ); pTermNew = Abc_NtkCreateBi( pNtkNew ); Abc_ObjAddFanin( pNodeNew, pNet->pCopy ); Abc_ObjAddFanin( pNetNew, pNodeNew ); Abc_ObjAddFanin( pTermNew, pNetNew ); Abc_ObjAddFanin( pBoxNew, pTermNew ); } // mark the net Abc_NodeSetTravIdCurrent( pNet ); } } else { Abc_NtkForEachCi( pNtk, pObj, i ) { pNet = Abc_ObjFanout0(pObj); nValues = Abc_ObjMvVarNum(pNet); nBits = Abc_Base2Log( nValues ); for ( k = 0; k < nBits; k++ ) { pNodeNew = Abc_NtkCreateNode( pNtkNew ); pNodeNew->pData = Abc_SopEncoderLog( (Mem_Flex_t *)pNtkNew->pManFunc, k, nValues ); pNetNew = Abc_NtkCreateNet( pNtkNew ); pTermNew = Abc_NtkCreateBi( pNtkNew ); Abc_ObjAddFanin( pNodeNew, pNet->pCopy ); Abc_ObjAddFanin( pNetNew, pNodeNew ); Abc_ObjAddFanin( pTermNew, pNetNew ); Abc_ObjAddFanin( pBoxNew, pTermNew ); } // mark the net Abc_NodeSetTravIdCurrent( pNet ); } } // encode the CO nets if ( fUsePositional ) { Abc_NtkForEachCo( pNtk, pObj, i ) { pNet = Abc_ObjFanin0(pObj); // skip marked nets if ( Abc_NodeIsTravIdCurrent(pNet) ) continue; Abc_NodeSetTravIdCurrent( pNet ); nValues = Abc_ObjMvVarNum(pNet); pNodeNew = Abc_NtkCreateNode( pNtkNew ); pNodeNew->pData = Abc_SopDecoderPos( (Mem_Flex_t *)pNtkNew->pManFunc, nValues ); for ( v = 0; v < nValues; v++ ) { pTermNew = Abc_NtkCreateBo( pNtkNew ); pNetNew = Abc_NtkCreateNet( pNtkNew ); Abc_ObjAddFanin( pTermNew, pBoxNew ); Abc_ObjAddFanin( pNetNew, pTermNew ); Abc_ObjAddFanin( pNodeNew, pNetNew ); } Abc_ObjAddFanin( pNet->pCopy, pNodeNew ); } } else { Abc_NtkForEachCo( pNtk, pObj, i ) { pNet = Abc_ObjFanin0(pObj); // skip marked nets if ( Abc_NodeIsTravIdCurrent(pNet) ) continue; Abc_NodeSetTravIdCurrent( pNet ); nValues = Abc_ObjMvVarNum(pNet); nBits = Abc_Base2Log( nValues ); pNodeNew = Abc_NtkCreateNode( pNtkNew ); pNodeNew->pData = Abc_SopDecoderLog( (Mem_Flex_t *)pNtkNew->pManFunc, nValues ); for ( k = 0; k < nBits; k++ ) { pTermNew = Abc_NtkCreateBo( pNtkNew ); pNetNew = Abc_NtkCreateNet( pNtkNew ); Abc_ObjAddFanin( pTermNew, pBoxNew ); Abc_ObjAddFanin( pNetNew, pTermNew ); Abc_ObjAddFanin( pNodeNew, pNetNew ); } Abc_ObjAddFanin( pNet->pCopy, pNodeNew ); } } // if it is a BLIF-MV netlist transfer the values of all nets if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) ) { if ( Abc_NtkMvVar( pNtkNew ) == NULL ) Abc_NtkStartMvVars( pNtkNew ); Abc_NtkForEachNet( pNtk, pObj, i ) if ( pObj->pCopy ) Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) ); } // check integrity if ( !Abc_NtkCheck( pNtkNew ) ) { fprintf( stdout, "Abc_NtkSkeletonBlifMv(): Network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Inserts processed network into original base MV network.] Description [The original network remembers the interface of combinational logic (PIs/POs/latches names and values). The processed network may be binary or multi-valued (currently, multi-value is not supported). The resulting network has the same interface as the original network while the internal logic is the same as that of the processed network.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic ) { Abc_Ntk_t * pNtkSkel, * pNtkNew; Abc_Obj_t * pBox; assert( Abc_NtkIsNetlist(pNtkBase) ); assert( Abc_NtkHasBlifMv(pNtkBase) ); assert( Abc_NtkWhiteboxNum(pNtkBase) == 0 ); assert( Abc_NtkBlackboxNum(pNtkBase) == 0 ); assert( Abc_NtkIsNetlist(pNtkLogic) ); assert( Abc_NtkHasBlifMv(pNtkLogic) ); assert( Abc_NtkWhiteboxNum(pNtkLogic) == 0 ); assert( Abc_NtkBlackboxNum(pNtkLogic) == 0 ); // extract the skeleton of the old network pNtkSkel = Abc_NtkSkeletonBlifMv( pNtkBase ); // set the implementation of the box to be the same as the processed network assert( Abc_NtkWhiteboxNum(pNtkSkel) == 1 ); pBox = Abc_NtkBox( pNtkSkel, 0 ); assert( Abc_ObjIsWhitebox(pBox) ); assert( pBox->pData == NULL ); assert( Abc_ObjFaninNum(pBox) == Abc_NtkPiNum(pNtkLogic) ); assert( Abc_ObjFanoutNum(pBox) == Abc_NtkPoNum(pNtkLogic) ); pBox->pData = pNtkLogic; // flatten the hierarchy to insert the processed network pNtkNew = Abc_NtkFlattenLogicHierarchy( pNtkSkel ); pBox->pData = NULL; Abc_NtkDelete( pNtkSkel ); return pNtkNew; } /**Function************************************************************* Synopsis [Converts SOP netlist into BLIF-MV netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk ) { #ifdef ABC_USE_CUDD Mem_Flex_t * pMmFlex; Abc_Obj_t * pNode; Vec_Str_t * vCube; char * pSop0, * pSop1, * pBlifMv, * pCube, * pCur; int Value, nCubes, nSize, i, k; assert( Abc_NtkIsNetlist(pNtk) ); if ( !Abc_NtkToBdd(pNtk) ) { printf( "Converting logic functions to BDDs has failed.\n" ); return 0; } pMmFlex = Mem_FlexStart(); vCube = Vec_StrAlloc( 100 ); Abc_NtkForEachNode( pNtk, pNode, i ) { // convert BDD into cubes for on-set and off-set Abc_NodeBddToCnf( pNode, pMmFlex, vCube, 0, &pSop0, &pSop1 ); // allocate room for the MV-SOP nCubes = Abc_SopGetCubeNum(pSop0) + Abc_SopGetCubeNum(pSop1); nSize = nCubes*(2*Abc_ObjFaninNum(pNode) + 2)+1; pBlifMv = Mem_FlexEntryFetch( pMmFlex, nSize ); // add the cubes pCur = pBlifMv; Abc_SopForEachCube( pSop0, Abc_ObjFaninNum(pNode), pCube ) { Abc_CubeForEachVar( pCube, Value, k ) { *pCur++ = Value; *pCur++ = ' '; } *pCur++ = '0'; *pCur++ = '\n'; } Abc_SopForEachCube( pSop1, Abc_ObjFaninNum(pNode), pCube ) { Abc_CubeForEachVar( pCube, Value, k ) { *pCur++ = Value; *pCur++ = ' '; } *pCur++ = '1'; *pCur++ = '\n'; } *pCur++ = 0; assert( pCur - pBlifMv == nSize ); // update the node representation Cudd_RecursiveDeref( (DdManager *)pNtk->pManFunc, (DdNode *)pNode->pData ); pNode->pData = pBlifMv; } // update the functionality type pNtk->ntkFunc = ABC_FUNC_BLIFMV; Cudd_Quit( (DdManager *)pNtk->pManFunc ); pNtk->pManFunc = pMmFlex; Vec_StrFree( vCube ); #endif return 1; } /**Function************************************************************* Synopsis [Converts SOP into MV-SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ) { char * pMvSop, * pCur; unsigned uCube; int nCubes, nSize, Value, i, k; // consider the case of the constant node if ( Vec_IntSize(vSop0) == 0 || Vec_IntSize(vSop1) == 0 ) { // (temporary) create a tautology cube pMvSop = ABC_ALLOC( char, nVars + 3 ); for ( k = 0; k < nVars; k++ ) pMvSop[k] = '-'; pMvSop[nVars] = '0' + (int)(Vec_IntSize(vSop1) > 0); pMvSop[nVars+1] = '\n'; pMvSop[nVars+2] = 0; return pMvSop; } // find the total number of cubes nCubes = Vec_IntSize(vSop0) + Vec_IntSize(vSop1); // find the size of the MVSOP represented as a C-string // (each cube has nVars variables + one output literal + end-of-line, // and the string is zero-terminated) nSize = nCubes * (nVars + 2) + 1; // allocate memory pMvSop = pCur = ABC_ALLOC( char, nSize ); // fill in the negative polarity cubes Vec_IntForEachEntry( vSop0, uCube, i ) { for ( k = 0; k < nVars; k++ ) { Value = (uCube >> (2*k)) & 3; if ( Value == 1 ) *pCur++ = '0'; else if ( Value == 2 ) *pCur++ = '1'; else if ( Value == 0 ) *pCur++ = '-'; else assert( 0 ); } *pCur++ = '0'; *pCur++ = '\n'; } // fill in the positive polarity cubes Vec_IntForEachEntry( vSop1, uCube, i ) { for ( k = 0; k < nVars; k++ ) { Value = (uCube >> (2*k)) & 3; if ( Value == 1 ) *pCur++ = '0'; else if ( Value == 2 ) *pCur++ = '1'; else if ( Value == 0 ) *pCur++ = '-'; else assert( 0 ); } *pCur++ = '1'; *pCur++ = '\n'; } *pCur++ = 0; assert( pCur - pMvSop == nSize ); return pMvSop; } /**Function************************************************************* Synopsis [A prototype of internal cost evaluation procedure.] Description [This procedure takes the number of variables (nVars), the array of values of the inputs and the output (pVarValues) (note that this array has nVars+1 entries), and an MV-SOP represented as a C-string with one charater for each literal, including inputs and output. Each cube is terminated with the new-line character ('\n'). The string is zero-terminated.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeEvalMvCostInternal( int nVars, int * pVarValues, char * pMvSop ) { // for now, return the number of cubes in the MV-SOP int Counter = 0; while ( *pMvSop ) Counter += (*pMvSop++ == '\n'); return Counter; } /**Function************************************************************* Synopsis [Evaluates the cost of the cut.] Description [The Boolean function of the cut is specified by two SOPs, which represent the negative/positive polarities of the cut function. Converts these two SOPs into a mutually-agreed-upon representation to be passed to the internal cost-evaluation procedure (see the above prototype Abc_NodeEvalMvCostInternal).] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ) { char * pMvSop; int * pVarValues; int i, RetValue; // collect the input and output values (currently, they are binary) pVarValues = ABC_ALLOC( int, nVars + 1 ); for ( i = 0; i <= nVars; i++ ) pVarValues[i] = 2; // prepare MV-SOP for evaluation pMvSop = Abc_NodeConvertSopToMvSop( nVars, vSop0, vSop1 ); // have a look at the MV-SOP: // printf( "%s\n", pMvSop ); // get the result of internal cost evaluation RetValue = Abc_NodeEvalMvCostInternal( nVars, pVarValues, pMvSop ); // cleanup ABC_FREE( pVarValues ); ABC_FREE( pMvSop ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcCheck.c000066400000000000000000000721651477524141600162700ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcCheck.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Consistency checking procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" #include "base/main/main.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Abc_NtkCheckNames( Abc_Ntk_t * pNtk ); static int Abc_NtkCheckPis( Abc_Ntk_t * pNtk ); static int Abc_NtkCheckPos( Abc_Ntk_t * pNtk ); //static int Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ); static int Abc_NtkCheckNet( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ); static int Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ); static int Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch ); static int Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); static int Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); static int Abc_NtkCompareLatches( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); static inline char * Abc_ObjNameNet( Abc_Obj_t * pObj ) { return (Abc_ObjIsNode(pObj) && Abc_NtkIsNetlist(pObj->pNtk)) ? Abc_ObjName(Abc_ObjFanout0(pObj)) : Abc_ObjName(pObj); } //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks the integrity of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCheck( Abc_Ntk_t * pNtk ) { return !Abc_FrameIsFlagEnabled( "check" ) || Abc_NtkDoCheck( pNtk ); } /**Function************************************************************* Synopsis [Checks the integrity of the network after reading.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCheckRead( Abc_Ntk_t * pNtk ) { return !Abc_FrameIsFlagEnabled( "checkread" ) || Abc_NtkDoCheck( pNtk ); } /**Function************************************************************* Synopsis [Checks the integrity of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDoCheck( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pNet, * pNode; int i; // check network types if ( !Abc_NtkIsNetlist(pNtk) && !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) { fprintf( stdout, "NetworkCheck: Unknown network type.\n" ); return 0; } if ( !Abc_NtkHasSop(pNtk) && !Abc_NtkHasBdd(pNtk) && !Abc_NtkHasAig(pNtk) && !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasBlackbox(pNtk) ) { fprintf( stdout, "NetworkCheck: Unknown functionality type.\n" ); return 0; } if ( Abc_NtkHasMapping(pNtk) ) { if ( pNtk->pManFunc != Abc_FrameReadLibGen() ) { fprintf( stdout, "NetworkCheck: The library of the mapped network is not the global library.\n" ); return 0; } } if ( Abc_NtkHasOnlyLatchBoxes(pNtk) ) { // check CI/CO numbers if ( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCiNum(pNtk) ) { fprintf( stdout, "NetworkCheck: Number of CIs does not match number of PIs and latches.\n" ); fprintf( stdout, "One possible reason is that latches are added twice:\n" ); fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" ); return 0; } if ( Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCoNum(pNtk) ) { fprintf( stdout, "NetworkCheck: Number of COs does not match number of POs, asserts, and latches.\n" ); fprintf( stdout, "One possible reason is that latches are added twice:\n" ); fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" ); return 0; } } // check the names if ( !Abc_NtkCheckNames( pNtk ) ) return 0; // check PIs and POs Abc_NtkCleanCopy( pNtk ); if ( !Abc_NtkCheckPis( pNtk ) ) return 0; if ( !Abc_NtkCheckPos( pNtk ) ) return 0; if ( Abc_NtkHasBlackbox(pNtk) ) return 1; // check the connectivity of objects Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_NtkCheckObj( pNtk, pObj ) ) return 0; // if it is a netlist change nets and latches if ( Abc_NtkIsNetlist(pNtk) ) { if ( Abc_NtkNetNum(pNtk) == 0 ) fprintf( stdout, "NetworkCheck: Warning! Netlist has no nets.\n" ); // check the nets Abc_NtkForEachNet( pNtk, pNet, i ) if ( !Abc_NtkCheckNet( pNtk, pNet ) ) return 0; } else { if ( Abc_NtkNetNum(pNtk) != 0 ) { fprintf( stdout, "NetworkCheck: A network that is not a netlist has nets.\n" ); return 0; } } // check the nodes if ( Abc_NtkIsStrash(pNtk) ) { if ( !Abc_AigCheck( (Abc_Aig_t *)pNtk->pManFunc ) ) return 0; } else { Abc_NtkForEachNode( pNtk, pNode, i ) if ( !Abc_NtkCheckNode( pNtk, pNode ) ) return 0; } // check the latches Abc_NtkForEachLatch( pNtk, pNode, i ) if ( !Abc_NtkCheckLatch( pNtk, pNode ) ) return 0; // finally, check for combinational loops // clk = Abc_Clock(); if ( !Abc_NtkIsAcyclic( pNtk ) ) { fprintf( stdout, "NetworkCheck: Network contains a combinational loop.\n" ); return 0; } // ABC_PRT( "Acyclic ", Abc_Clock() - clk ); // check the EXDC network if present if ( pNtk->pExdc ) Abc_NtkCheck( pNtk->pExdc ); /* // check the hierarchy if ( Abc_NtkIsNetlist(pNtk) && pNtk->tName2Model ) { stmm_generator * gen; Abc_Ntk_t * pNtkTemp; char * pName; // check other networks stmm_foreach_item( pNtk->tName2Model, gen, &pName, (char **)&pNtkTemp ) { pNtkTemp->fHiePath = pNtkTemp->fHieVisited = 0; if ( !Abc_NtkCheck( pNtkTemp ) ) return 0; } // check acyclic dependency of the models if ( !Abc_NtkIsAcyclicHierarchy( pNtk ) ) { fprintf( stdout, "NetworkCheck: Network hierarchical dependences contains a cycle.\n" ); return 0; } } */ return 1; } /**Function************************************************************* Synopsis [Checks the names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCheckNames( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj = NULL; // Ensure pObj isn't used uninitialized. Vec_Int_t * vNameIds; char * pName; int i, NameId; if ( Abc_NtkIsNetlist(pNtk) ) return 1; // check that each CI/CO has a name Abc_NtkForEachCi( pNtk, pObj, i ) { pObj = Abc_ObjFanout0Ntk(pObj); if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL ) { fprintf( stdout, "NetworkCheck: CI with ID %d is in the network but not in the name table.\n", pObj->Id ); return 0; } } Abc_NtkForEachCo( pNtk, pObj, i ) { pObj = Abc_ObjFanin0Ntk(pObj); if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL ) { fprintf( stdout, "NetworkCheck: CO with ID %d is in the network but not in the name table.\n", pObj->Id ); return 0; } } assert(pObj); // pObj should point to something here. // return the array of all IDs, which have names vNameIds = Nm_ManReturnNameIds( pNtk->pManName ); // make sure that these IDs correspond to live objects Vec_IntForEachEntry( vNameIds, NameId, i ) { if ( Vec_PtrEntry( pNtk->vObjs, NameId ) == NULL ) { Vec_IntFree( vNameIds ); pName = Nm_ManFindNameById(pObj->pNtk->pManName, NameId); fprintf( stdout, "NetworkCheck: Object with ID %d is deleted but its name \"%s\" remains in the name table.\n", NameId, pName ); return 0; } } Vec_IntFree( vNameIds ); // make sure the CI names are unique if ( !Abc_NtkCheckUniqueCiNames(pNtk) ) return 0; // make sure the CO names are unique if ( !Abc_NtkCheckUniqueCoNames(pNtk) ) return 0; // make sure that if a CO has the same name as a CI, they point directly if ( !Abc_NtkCheckUniqueCioNames(pNtk) ) return 0; return 1; } /**Function************************************************************* Synopsis [Checks the PIs of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCheckPis( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; // check that PIs are indeed PIs Abc_NtkForEachPi( pNtk, pObj, i ) { if ( !Abc_ObjIsPi(pObj) ) { fprintf( stdout, "NetworkCheck: Object \"%s\" (id=%d) is in the PI list but is not a PI.\n", Abc_ObjName(pObj), pObj->Id ); return 0; } if ( pObj->pData ) { fprintf( stdout, "NetworkCheck: A PI \"%s\" has a logic function.\n", Abc_ObjName(pObj) ); return 0; } if ( Abc_ObjFaninNum(pObj) > 0 ) { fprintf( stdout, "NetworkCheck: A PI \"%s\" has fanins.\n", Abc_ObjName(pObj) ); return 0; } pObj->pCopy = (Abc_Obj_t *)1; } Abc_NtkForEachObj( pNtk, pObj, i ) { if ( pObj->pCopy == NULL && Abc_ObjIsPi(pObj) ) { fprintf( stdout, "NetworkCheck: Object \"%s\" (id=%d) is a PI but is not in the PI list.\n", Abc_ObjName(pObj), pObj->Id ); return 0; } pObj->pCopy = NULL; } return 1; } /**Function************************************************************* Synopsis [Checks the POs of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCheckPos( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; // check that POs are indeed POs Abc_NtkForEachPo( pNtk, pObj, i ) { if ( !Abc_ObjIsPo(pObj) ) { fprintf( stdout, "NetworkCheck: Net \"%s\" (id=%d) is in the PO list but is not a PO.\n", Abc_ObjName(pObj), pObj->Id ); return 0; } if ( pObj->pData ) { fprintf( stdout, "NetworkCheck: A PO \"%s\" has a logic function.\n", Abc_ObjName(pObj) ); return 0; } if ( Abc_ObjFaninNum(pObj) != 1 ) { fprintf( stdout, "NetworkCheck: A PO \"%s\" does not have one fanin (but %d).\n", Abc_ObjName(pObj), Abc_ObjFaninNum(pObj) ); return 0; } if ( Abc_ObjFanoutNum(pObj) > 0 ) { fprintf( stdout, "NetworkCheck: A PO \"%s\" has %d fanout(s).\n", Abc_ObjName(pObj), Abc_ObjFanoutNum(pObj) ); return 0; } pObj->pCopy = (Abc_Obj_t *)1; } Abc_NtkForEachObj( pNtk, pObj, i ) { if ( pObj->pCopy == NULL && Abc_ObjIsPo(pObj) ) { fprintf( stdout, "NetworkCheck: Net \"%s\" (id=%d) is in a PO but is not in the PO list.\n", Abc_ObjName(pObj), pObj->Id ); return 0; } pObj->pCopy = NULL; } return 1; } /**Function************************************************************* Synopsis [Checks the connectivity of the object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin, * pFanout; int Value = 1; int i, k; // check the network if ( pObj->pNtk != pNtk ) { fprintf( stdout, "NetworkCheck: Object \"%s\" does not belong to the network.\n", Abc_ObjName(pObj) ); return 0; } // check the object ID if ( pObj->Id < 0 || (int)pObj->Id >= Abc_NtkObjNumMax(pNtk) ) { fprintf( stdout, "NetworkCheck: Object \"%s\" has incorrect ID.\n", Abc_ObjName(pObj) ); return 0; } if ( !Abc_FrameIsFlagEnabled("checkfio") ) return Value; // go through the fanins of the object and make sure fanins have this object as a fanout Abc_ObjForEachFanin( pObj, pFanin, i ) { if ( Vec_IntFind( &pFanin->vFanouts, pObj->Id ) == -1 ) { fprintf( stdout, "NodeCheck: Object \"%s\" has fanin ", Abc_ObjName(pObj) ); fprintf( stdout, "\"%s\" but the fanin does not have it as a fanout.\n", Abc_ObjName(pFanin) ); Value = 0; } } // go through the fanouts of the object and make sure fanouts have this object as a fanin Abc_ObjForEachFanout( pObj, pFanout, i ) { if ( Vec_IntFind( &pFanout->vFanins, pObj->Id ) == -1 ) { fprintf( stdout, "NodeCheck: Object \"%s\" has fanout ", Abc_ObjName(pObj) ); fprintf( stdout, "\"%s\" but the fanout does not have it as a fanin.\n", Abc_ObjName(pFanout) ); Value = 0; } } // make sure fanins are not duplicated for ( i = 0; i < pObj->vFanins.nSize; i++ ) for ( k = i + 1; k < pObj->vFanins.nSize; k++ ) if ( pObj->vFanins.pArray[k] == pObj->vFanins.pArray[i] ) { printf( "Warning: Node %s has", Abc_ObjName(pObj) ); printf( " duplicated fanin %s.\n", Abc_ObjName(Abc_ObjFanin(pObj,k)) ); } // save time: do not check large fanout lists if ( pObj->vFanouts.nSize > 100 ) return Value; // make sure fanouts are not duplicated for ( i = 0; i < pObj->vFanouts.nSize; i++ ) for ( k = i + 1; k < pObj->vFanouts.nSize; k++ ) if ( pObj->vFanouts.pArray[k] == pObj->vFanouts.pArray[i] ) { printf( "Warning: Node %s has", Abc_ObjName(pObj) ); printf( " duplicated fanout %s.\n", Abc_ObjName(Abc_ObjFanout(pObj,k)) ); } return Value; } /**Function************************************************************* Synopsis [Checks the integrity of a net.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCheckNet( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ) { if ( Abc_ObjFaninNum(pNet) == 0 ) { fprintf( stdout, "NetworkCheck: Net \"%s\" is not driven.\n", Abc_ObjName(pNet) ); return 0; } if ( Abc_ObjFaninNum(pNet) > 1 ) { fprintf( stdout, "NetworkCheck: Net \"%s\" has more than one driver.\n", Abc_ObjName(pNet) ); return 0; } return 1; } /**Function************************************************************* Synopsis [Checks the integrity of a node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) { // detect internal nodes that do not have nets if ( Abc_NtkIsNetlist(pNtk) && Abc_ObjFanoutNum(pNode) == 0 ) { fprintf( stdout, "Node (id = %d) has no net to drive.\n", pNode->Id ); return 0; } // the node should have a function assigned unless it is an AIG if ( pNode->pData == NULL ) { if ( Abc_ObjIsBarBuf(pNode) ) return 1; fprintf( stdout, "NodeCheck: An internal node \"%s\" does not have a logic function.\n", Abc_ObjNameNet(pNode) ); return 0; } // the netlist and SOP logic network should have SOPs if ( Abc_NtkHasSop(pNtk) ) { if ( !Abc_SopCheck( (char *)pNode->pData, Abc_ObjFaninNum(pNode) ) ) { fprintf( stdout, "NodeCheck: SOP check for node \"%s\" has failed.\n", Abc_ObjNameNet(pNode) ); return 0; } } else if ( Abc_NtkHasBdd(pNtk) ) { #ifdef ABC_USE_CUDD int nSuppSize = Cudd_SupportSize((DdManager *)pNtk->pManFunc, (DdNode *)pNode->pData); if ( nSuppSize > Abc_ObjFaninNum(pNode) ) { fprintf( stdout, "NodeCheck: BDD of the node \"%s\" has incorrect support size.\n", Abc_ObjNameNet(pNode) ); return 0; } #endif } else if ( !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasAig(pNtk) ) { assert( 0 ); } return 1; } /**Function************************************************************* Synopsis [Checks the integrity of a latch.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch ) { int Value = 1; // check whether the object is a latch if ( !Abc_ObjIsLatch(pLatch) ) { fprintf( stdout, "NodeCheck: Latch \"%s\" is in a latch list but is not a latch.\n", Abc_ObjName(pLatch) ); Value = 0; } // make sure the latch has a reasonable return value if ( (int)(ABC_PTRINT_T)pLatch->pData < ABC_INIT_ZERO || (int)(ABC_PTRINT_T)pLatch->pData > ABC_INIT_DC ) { fprintf( stdout, "NodeCheck: Latch \"%s\" has incorrect reset value (%d).\n", Abc_ObjName(pLatch), (int)(ABC_PTRINT_T)pLatch->pData ); Value = 0; } // make sure the latch has only one fanin if ( Abc_ObjFaninNum(pLatch) != 1 ) { fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanins.\n", Abc_ObjName(pLatch), Abc_ObjFaninNum(pLatch) ); Value = 0; } // make sure the latch has only one fanout if ( Abc_ObjFanoutNum(pLatch) != 1 ) { fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanouts.\n", Abc_ObjName(pLatch), Abc_ObjFanoutNum(pLatch) ); Value = 0; } // make sure the latch input has only one fanin if ( Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) != 1 ) { fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanins.\n", Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) ); Value = 0; } // make sure the latch input has only one fanout if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) != 1 ) { fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanouts.\n", Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) ); Value = 0; } // make sure the latch output has only one fanin if ( Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) != 1 ) { fprintf( stdout, "NodeCheck: Output of latch \"%s\" has wrong number (%d) of fanins.\n", Abc_ObjName(Abc_ObjFanout0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) ); Value = 0; } return Value; } /**Function************************************************************* Synopsis [Compares the PIs of the two networks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) { Abc_Obj_t * pObj1; int i; if ( Abc_NtkPiNum(pNtk1) != Abc_NtkPiNum(pNtk2) ) { printf( "Networks have different number of primary inputs.\n" ); return 0; } // for each PI of pNet1 find corresponding PI of pNet2 and reorder them Abc_NtkForEachPi( pNtk1, pObj1, i ) { if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPi(pNtk2,i)) ) != 0 ) { printf( "Primary input #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPi(pNtk2,i)) ); return 0; } } return 1; } /**Function************************************************************* Synopsis [Compares the POs of the two networks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) { Abc_Obj_t * pObj1; int i; if ( Abc_NtkPoNum(pNtk1) != Abc_NtkPoNum(pNtk2) ) { printf( "Networks have different number of primary outputs.\n" ); return 0; } // for each PO of pNet1 find corresponding PO of pNet2 and reorder them Abc_NtkForEachPo( pNtk1, pObj1, i ) { if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPo(pNtk2,i)) ) != 0 ) { printf( "Primary output #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPo(pNtk2,i)) ); return 0; } } return 1; } /**Function************************************************************* Synopsis [Compares the latches of the two networks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCompareBoxes( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) { Abc_Obj_t * pObj1; int i; assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) ); assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) ); if ( !fComb ) return 1; if ( Abc_NtkBoxNum(pNtk1) != Abc_NtkBoxNum(pNtk2) ) { printf( "Networks have different number of latches.\n" ); return 0; } // for each PI of pNet1 find corresponding PI of pNet2 and reorder them Abc_NtkForEachBox( pNtk1, pObj1, i ) { if ( strcmp( Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) ) != 0 ) { printf( "Box #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", i, Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) ); return 0; } } return 1; } /**Function************************************************************* Synopsis [Compares the signals of the networks.] Description [] SideEffects [Ordering POs by name is a very bad idea! It destroys the natural order of the logic in the circuit.] SeeAlso [] ***********************************************************************/ int Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb ) { Abc_NtkOrderObjsByName( pNtk1, fComb ); Abc_NtkOrderObjsByName( pNtk2, fComb ); if ( !Abc_NtkComparePis( pNtk1, pNtk2, fComb ) ) return 0; if ( !fOnlyPis ) { if ( !Abc_NtkCompareBoxes( pNtk1, pNtk2, fComb ) ) return 0; if ( !Abc_NtkComparePos( pNtk1, pNtk2, fComb ) ) return 0; } return 1; } /**Function************************************************************* Synopsis [Returns 0 if the network hierachy contains a cycle.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkIsAcyclicHierarchy_rec( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNext; Abc_Obj_t * pObj; int i; // return if visited if ( pNtk->fHieVisited ) return 1; pNtk->fHieVisited = 1; // return if black box if ( Abc_NtkHasBlackbox(pNtk) ) return 1; assert( Abc_NtkIsNetlist(pNtk) ); // go through all the children networks Abc_NtkForEachBox( pNtk, pObj, i ) { if ( Abc_ObjIsLatch(pObj) ) continue; pNtkNext = (Abc_Ntk_t *)pObj->pData; assert( pNtkNext != NULL ); if ( pNtkNext->fHiePath ) return 0; pNtk->fHiePath = 1; if ( !Abc_NtkIsAcyclicHierarchy_rec( pNtkNext ) ) return 0; pNtk->fHiePath = 0; } return 1; } /**Function************************************************************* Synopsis [Returns 0 if the network hierachy contains a cycle.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pTemp; int i, RetValue; assert( Abc_NtkIsNetlist(pNtk) && pNtk->pDesign ); // clear the modules Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i ) pTemp->fHieVisited = pTemp->fHiePath = 0; // traverse pNtk->fHiePath = 1; RetValue = Abc_NtkIsAcyclicHierarchy_rec( pNtk ); pNtk->fHiePath = 0; // clear the modules Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i ) pTemp->fHieVisited = pTemp->fHiePath = 0; return RetValue; } /**Function************************************************************* Synopsis [Returns 0 if CI names are repeated.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkNamesCompare( char ** pName1, char ** pName2 ) { return strcmp( *pName1, *pName2 ); } /**Function************************************************************* Synopsis [Returns 0 if CI names are repeated.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNames; Abc_Obj_t * pObj; int i, fRetValue = 1; assert( !Abc_NtkIsNetlist(pNtk) ); vNames = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) ); Abc_NtkForEachCi( pNtk, pObj, i ) Vec_PtrPush( vNames, Abc_ObjName(pObj) ); 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) ) ) { printf( "Abc_NtkCheck: Repeated CI names: %s and %s.\n", (char*)Vec_PtrEntry(vNames,i-1), (char*)Vec_PtrEntry(vNames,i) ); fRetValue = 0; } Vec_PtrFree( vNames ); return fRetValue; } /**Function************************************************************* Synopsis [Returns 0 if CO names are repeated.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNames; Abc_Obj_t * pObj; int i, fRetValue = 1; assert( !Abc_NtkIsNetlist(pNtk) ); vNames = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) Vec_PtrPush( vNames, Abc_ObjName(pObj) ); 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) ); if ( !strcmp( (const char *)Vec_PtrEntry(vNames,i-1), (const char *)Vec_PtrEntry(vNames,i) ) ) { printf( "Abc_NtkCheck: Repeated CO names: %s and %s.\n", (char*)Vec_PtrEntry(vNames,i-1), (char*)Vec_PtrEntry(vNames,i) ); fRetValue = 0; } } Vec_PtrFree( vNames ); return fRetValue; } /**Function************************************************************* Synopsis [Returns 0 if there is a pair of CI/CO with the same name and logic in between.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pObjCi, * pFanin; int i, nCiId, fRetValue = 1; assert( !Abc_NtkIsNetlist(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) { nCiId = Nm_ManFindIdByNameTwoTypes( pNtk->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); if ( nCiId == -1 ) continue; pObjCi = Abc_NtkObj( pNtk, nCiId ); assert( !strcmp( Abc_ObjName(pObj), Abc_ObjName(pObjCi) ) ); pFanin = Abc_ObjFanin0(pObj); if ( pFanin != pObjCi ) { printf( "Abc_NtkCheck: A CI/CO pair share the name (%s) but do not link directly. The name of the CO fanin is %s.\n", Abc_ObjName(pObj), Abc_ObjName(Abc_ObjFanin0(pObj)) ); fRetValue = 0; } } return fRetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcDfs.c000066400000000000000000001655401477524141600157670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcDfs.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures that use depth-first search.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" #include "proof/cec/cec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Performs DFS for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanin; int i; assert( !Abc_ObjIsNet(pNode) ); // if this node is already visited, skip if ( Abc_NodeIsTravIdCurrent( pNode ) ) return; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); // skip the CI if ( Abc_ObjIsCi(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) ) return; assert( Abc_ObjIsNode( pNode ) || Abc_ObjIsBox( pNode ) ); // visit the transitive fanin of the node Abc_ObjForEachFanin( pNode, pFanin, i ) { // pFanin = Abc_ObjFanin( pNode, Abc_ObjFaninNum(pNode)-1-i ); Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(pFanin), vNodes ); } // add the node after the fanins have been added Vec_PtrPush( vNodes, pNode ); } /**Function************************************************************* Synopsis [Returns the DFS ordered array of logic nodes.] Description [Collects only the internal nodes, leaving out CIs and CO. However it marks with the current TravId both CIs and COs.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i; // set the traversal ID Abc_NtkIncrementTravId( pNtk ); // start the array of nodes vNodes = Vec_PtrAlloc( 100 ); if ( pNtk->nBarBufs2 > 0 ) { Abc_NtkForEachBarBuf( pNtk, pObj, i ) { Abc_NodeSetTravIdCurrent( pObj ); Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); Vec_PtrPush( vNodes, pObj ); } } Abc_NtkForEachCo( pNtk, pObj, i ) { Abc_NodeSetTravIdCurrent( pObj ); Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); } // collect dangling nodes if asked to if ( fCollectAll ) { Abc_NtkForEachNode( pNtk, pObj, i ) if ( !Abc_NodeIsTravIdCurrent(pObj) ) Abc_NtkDfs_rec( pObj, vNodes ); } return vNodes; } /**Function************************************************************* Synopsis [Returns the DFS ordered array of logic nodes.] Description [Collects only the internal nodes, leaving out CIs and CO. However it marks with the current TravId both CIs and COs.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDfs2( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes = Vec_PtrAlloc( 100 ); Abc_Obj_t * pObj; int i; Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachCo( pNtk, pObj, i ) { Abc_NodeSetTravIdCurrent( pObj ); Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); } return vNodes; } /**Function************************************************************* Synopsis [Returns the DFS ordered array of logic nodes.] Description [Collects only the internal nodes, leaving out PIs, POs and latches.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) { Vec_Ptr_t * vNodes; int i; // set the traversal ID Abc_NtkIncrementTravId( pNtk ); // start the array of nodes vNodes = Vec_PtrAlloc( 100 ); // go through the PO nodes and call for each of them for ( i = 0; i < nNodes; i++ ) { if ( Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsConst(ppNodes[i]) ) continue; if ( Abc_ObjIsCo(ppNodes[i]) ) { Abc_NodeSetTravIdCurrent(ppNodes[i]); Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(ppNodes[i])), vNodes ); } else if ( Abc_ObjIsNode(ppNodes[i]) || Abc_ObjIsCi(ppNodes[i]) ) Abc_NtkDfs_rec( ppNodes[i], vNodes ); } return vNodes; } /**Function************************************************************* Synopsis [Performs DFS for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanout; int i; assert( !Abc_ObjIsNet(pNode) ); // if this node is already visited, skip if ( Abc_NodeIsTravIdCurrent( pNode ) ) return; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); // skip the CI if ( Abc_ObjIsCo(pNode) ) return; assert( Abc_ObjIsNode( pNode ) ); // visit the transitive fanin of the node pNode = Abc_ObjFanout0Ntk(pNode); Abc_ObjForEachFanout( pNode, pFanout, i ) Abc_NtkDfsReverse_rec( pFanout, vNodes ); // add the node after the fanins have been added Vec_PtrPush( vNodes, pNode ); } /**Function************************************************************* Synopsis [Returns the reverse DFS ordered array of logic nodes.] Description [Collects only the internal nodes, leaving out CIs/COs. However it marks both CIs and COs with the current TravId.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pFanout; int i, k; // set the traversal ID Abc_NtkIncrementTravId( pNtk ); // start the array of nodes vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachCi( pNtk, pObj, i ) { Abc_NodeSetTravIdCurrent( pObj ); pObj = Abc_ObjFanout0Ntk(pObj); Abc_ObjForEachFanout( pObj, pFanout, k ) Abc_NtkDfsReverse_rec( pFanout, vNodes ); } // add constant nodes in the end if ( !Abc_NtkIsStrash(pNtk) ) { Abc_NtkForEachNode( pNtk, pObj, i ) if ( Abc_NodeIsConst(pObj) ) Vec_PtrPush( vNodes, pObj ); } return vNodes; } /**Function************************************************************* Synopsis [Performs DFS for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDfsReverseNodes_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanout; int i; assert( !Abc_ObjIsNet(pNode) ); // if this node is already visited, skip if ( Abc_NodeIsTravIdCurrent( pNode ) ) return; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); // skip the CI if ( Abc_ObjIsCo(pNode) ) return; assert( Abc_ObjIsNode( pNode ) ); // visit the transitive fanin of the node pNode = Abc_ObjFanout0Ntk(pNode); Abc_ObjForEachFanout( pNode, pFanout, i ) Abc_NtkDfsReverseNodes_rec( pFanout, vNodes ); // add the node after the fanins have been added // Vec_PtrPush( vNodes, pNode ); Vec_PtrFillExtra( vNodes, pNode->Level + 1, NULL ); pNode->pCopy = (Abc_Obj_t *)Vec_PtrEntry( vNodes, pNode->Level ); Vec_PtrWriteEntry( vNodes, pNode->Level, pNode ); } /**Function************************************************************* Synopsis [Returns the levelized array of TFO nodes.] Description [Collects the levelized array of internal nodes, leaving out CIs/COs. However it marks both CIs and COs with the current TravId.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pFanout; int i, k; assert( Abc_NtkIsStrash(pNtk) ); // set the traversal ID Abc_NtkIncrementTravId( pNtk ); // start the array of nodes vNodes = Vec_PtrStart( Abc_AigLevel(pNtk) + 1 ); for ( i = 0; i < nNodes; i++ ) { pObj = ppNodes[i]; assert( Abc_ObjIsCi(pObj) ); Abc_NodeSetTravIdCurrent( pObj ); pObj = Abc_ObjFanout0Ntk(pObj); Abc_ObjForEachFanout( pObj, pFanout, k ) Abc_NtkDfsReverseNodes_rec( pFanout, vNodes ); } return vNodes; } /**Function************************************************************* Synopsis [Returns the levelized array of TFO nodes.] Description [Collects the levelized array of internal nodes, leaving out CIs/COs. However it marks both CIs and COs with the current TravId. Collects only the nodes whose support does not exceed the set of given CI nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDfsReverseNodesContained( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pFanout, * pFanin; int i, k, m, nLevels; // set the levels nLevels = Abc_NtkLevel( pNtk ); // set the traversal ID Abc_NtkIncrementTravId( pNtk ); // start the array of nodes vNodes = Vec_PtrStart( nLevels + 2 ); for ( i = 0; i < nNodes; i++ ) { pObj = ppNodes[i]; assert( Abc_ObjIsCi(pObj) ); Abc_NodeSetTravIdCurrent( pObj ); // add to the array assert( pObj->Level == 0 ); pObj->pCopy = (Abc_Obj_t *)Vec_PtrEntry( vNodes, pObj->Level ); Vec_PtrWriteEntry( vNodes, pObj->Level, pObj ); } // iterate through the levels for ( i = 0; i <= nLevels; i++ ) { // iterate through the nodes on each level for ( pObj = (Abc_Obj_t *)Vec_PtrEntry(vNodes, i); pObj; pObj = pObj->pCopy ) { // iterate through the fanouts of each node Abc_ObjForEachFanout( pObj, pFanout, k ) { // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pFanout) ) continue; // visit the fanins of this fanout Abc_ObjForEachFanin( pFanout, pFanin, m ) { if ( !Abc_NodeIsTravIdCurrent(pFanin) ) break; } if ( m < Abc_ObjFaninNum(pFanout) ) continue; // all fanins are already collected // mark the node as visited Abc_NodeSetTravIdCurrent( pFanout ); // handle the COs if ( Abc_ObjIsCo(pFanout) ) pFanout->Level = nLevels + 1; // add to the array pFanout->pCopy = (Abc_Obj_t *)Vec_PtrEntry( vNodes, pFanout->Level ); Vec_PtrWriteEntry( vNodes, pFanout->Level, pFanout ); // handle the COs if ( Abc_ObjIsCo(pFanout) ) pFanout->Level = 0; } } } return vNodes; } /**Function************************************************************* Synopsis [Performs DFS for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDfsSeq_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanin; int i; // if this node is already visited, skip if ( Abc_NodeIsTravIdCurrent( pNode ) ) return; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); // visit the transitive fanin of the node Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_NtkDfsSeq_rec( pFanin, vNodes ); // add the node after the fanins have been added Vec_PtrPush( vNodes, pNode ); } /**Function************************************************************* Synopsis [Returns the array of nodes and latches reachable from POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDfsSeq( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i; assert( !Abc_NtkIsNetlist(pNtk) ); // set the traversal ID Abc_NtkIncrementTravId( pNtk ); // start the array of nodes vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_NtkDfsSeq_rec( pObj, vNodes ); // mark the PIs Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkDfsSeq_rec( pObj, vNodes ); return vNodes; } /**Function************************************************************* Synopsis [Performs DFS for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDfsSeqReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanout; int i; // if this node is already visited, skip if ( Abc_NodeIsTravIdCurrent( pNode ) ) return; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); // visit the transitive fanin of the node Abc_ObjForEachFanout( pNode, pFanout, i ) Abc_NtkDfsSeqReverse_rec( pFanout, vNodes ); // add the node after the fanins have been added Vec_PtrPush( vNodes, pNode ); } /**Function************************************************************* Synopsis [Returns the array of nodes and latches reachable from POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i; assert( !Abc_NtkIsNetlist(pNtk) ); // set the traversal ID Abc_NtkIncrementTravId( pNtk ); // start the array of nodes vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkDfsSeqReverse_rec( pObj, vNodes ); // mark the logic feeding into POs Abc_NtkForEachPo( pNtk, pObj, i ) Abc_NtkDfsSeq_rec( pObj, vNodes ); return vNodes; } /**Function************************************************************* Synopsis [Iterative version of the DFS procedure.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDfs_iter( Vec_Ptr_t * vStack, Abc_Obj_t * pRoot, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pNode, * pFanin; int iFanin; // if this node is already visited, skip if ( Abc_NodeIsTravIdCurrent( pRoot ) ) return; // mark the node as visited Abc_NodeSetTravIdCurrent( pRoot ); // skip the CI if ( Abc_ObjIsCi(pRoot) || (Abc_NtkIsStrash(pRoot->pNtk) && Abc_AigNodeIsConst(pRoot)) ) return; // add the CI Vec_PtrClear( vStack ); Vec_PtrPush( vStack, pRoot ); Vec_PtrPush( vStack, (void *)0 ); while ( Vec_PtrSize(vStack) > 0 ) { // get the node and its fanin iFanin = (int)(ABC_PTRINT_T)Vec_PtrPop(vStack); pNode = (Abc_Obj_t *)Vec_PtrPop(vStack); assert( !Abc_ObjIsNet(pNode) ); // add it to the array of nodes if we finished if ( iFanin == Abc_ObjFaninNum(pNode) ) { Vec_PtrPush( vNodes, pNode ); continue; } // explore the next fanin Vec_PtrPush( vStack, pNode ); Vec_PtrPush( vStack, (void *)(ABC_PTRINT_T)(iFanin+1) ); // get the fanin pFanin = Abc_ObjFanin0Ntk( Abc_ObjFanin(pNode,iFanin) ); // if this node is already visited, skip if ( Abc_NodeIsTravIdCurrent( pFanin ) ) continue; // mark the node as visited Abc_NodeSetTravIdCurrent( pFanin ); // skip the CI if ( Abc_ObjIsCi(pFanin) || (Abc_NtkIsStrash(pFanin->pNtk) && Abc_AigNodeIsConst(pFanin)) ) continue; Vec_PtrPush( vStack, pFanin ); Vec_PtrPush( vStack, (void *)0 ); } } /**Function************************************************************* Synopsis [Returns the DFS ordered array of logic nodes.] Description [Collects only the internal nodes, leaving CIs and CO. However it marks with the current TravId both CIs and COs.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll ) { Vec_Ptr_t * vNodes, * vStack; Abc_Obj_t * pObj; int i; // set the traversal ID Abc_NtkIncrementTravId( pNtk ); // start the array of nodes vNodes = Vec_PtrAlloc( 1000 ); vStack = Vec_PtrAlloc( 1000 ); Abc_NtkForEachCo( pNtk, pObj, i ) { Abc_NodeSetTravIdCurrent( pObj ); Abc_NtkDfs_iter( vStack, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); } // collect dangling nodes if asked to if ( fCollectAll ) { Abc_NtkForEachNode( pNtk, pObj, i ) if ( !Abc_NodeIsTravIdCurrent(pObj) ) Abc_NtkDfs_iter( vStack, pObj, vNodes ); } Vec_PtrFree( vStack ); return vNodes; } /**Function************************************************************* Synopsis [Returns the DFS ordered array of logic nodes.] Description [Collects only the internal nodes, leaving CIs and CO. However it marks with the current TravId both CIs and COs.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDfsIterNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ) { Vec_Ptr_t * vNodes, * vStack; Abc_Obj_t * pObj; int i; Abc_NtkIncrementTravId( pNtk ); vNodes = Vec_PtrAlloc( 1000 ); vStack = Vec_PtrAlloc( 1000 ); Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) if ( !Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pObj)) ) Abc_NtkDfs_iter( vStack, Abc_ObjRegular(pObj), vNodes ); Vec_PtrFree( vStack ); return vNodes; } /**Function************************************************************* Synopsis [Performs DFS for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDfsHie_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanin; int i; // if this node is already visited, skip if ( Abc_NodeIsTravIdCurrent( pObj ) ) return; // mark the node as visited Abc_NodeSetTravIdCurrent( pObj ); // visit the transitive fanin of the node Abc_ObjForEachFanin( pObj, pFanin, i ) Abc_NtkDfsHie_rec( pFanin, vNodes ); // add the node after the fanins have been added Vec_PtrPush( vNodes, pObj ); } /**Function************************************************************* Synopsis [Returns the DFS ordered array of all objects.] Description [This procedure collects everything from POs to PIs.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDfsHie( Abc_Ntk_t * pNtk, int fCollectAll ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i; // set the traversal ID Abc_NtkIncrementTravId( pNtk ); // start the array of nodes vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_NtkDfsHie_rec( pObj, vNodes ); // collect dangling nodes if asked to if ( fCollectAll ) { Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_NodeIsTravIdCurrent(pObj) ) Abc_NtkDfs_rec( pObj, vNodes ); } return vNodes; } /**Function************************************************************* Synopsis [Returns 1 if the ordering of nodes is DFS.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode, * pFanin; int i, k; // set the traversal ID Abc_NtkIncrementTravId( pNtk ); // mark the CIs Abc_NtkForEachCi( pNtk, pNode, i ) Abc_NodeSetTravIdCurrent( pNode ); // go through the nodes Abc_NtkForEachNode( pNtk, pNode, i ) { // check the fanins of the node Abc_ObjForEachFanin( pNode, pFanin, k ) if ( !Abc_NodeIsTravIdCurrent(pFanin) ) return 0; // check the choices of the node if ( Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsChoice(pNode) ) for ( pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pFanin = (Abc_Obj_t *)pFanin->pData ) if ( !Abc_NodeIsTravIdCurrent(pFanin) ) return 0; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); } return 1; } /**Function************************************************************* Synopsis [Create DFS ordering of nets.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDfsNets_rec( Abc_Obj_t * pNet, Vec_Ptr_t * vNets ) { Abc_Obj_t * pNext; Abc_Obj_t * pNode; int i; assert( Abc_ObjIsNet(pNet) ); if ( Abc_NodeIsTravIdCurrent( pNet ) ) return; Abc_NodeSetTravIdCurrent( pNet ); pNode = Abc_ObjFanin0( pNet ); Abc_ObjForEachFanin( pNode, pNext, i ) Abc_NtkDfsNets_rec( pNext, vNets ); Abc_ObjForEachFanout( pNode, pNext, i ) Vec_PtrPush( vNets, pNext ); } Vec_Ptr_t * Abc_NtkDfsNets( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNets; Abc_Obj_t * pObj; int i; vNets = Vec_PtrAlloc( 100 ); Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachCi( pNtk, pObj, i ) Abc_NodeSetTravIdCurrent( Abc_ObjFanout0(pObj) ); Abc_NtkForEachCi( pNtk, pObj, i ) Vec_PtrPush( vNets, Abc_ObjFanout0(pObj) ); Abc_NtkForEachCo( pNtk, pObj, i ) Abc_NtkDfsNets_rec( Abc_ObjFanin0(pObj), vNets ); return vNets; } /**Function************************************************************* Synopsis [Returns the DFS ordered array of logic nodes.] Description [Collects only the internal nodes, leaving out CIs and CO. However it marks with the current TravId both CIs and COs.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDfsWithBoxes_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanin; int i; assert( !Abc_ObjIsNet(pNode) ); if ( Abc_ObjIsBo(pNode) ) pNode = Abc_ObjFanin0(pNode); if ( Abc_ObjIsPi(pNode) ) return; assert( Abc_ObjIsNode( pNode ) || Abc_ObjIsBox( pNode ) ); if ( Abc_NodeIsTravIdCurrent( pNode ) ) return; Abc_NodeSetTravIdCurrent( pNode ); Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( Abc_ObjIsBox(pNode) ) pFanin = Abc_ObjFanin0(pFanin); assert( Abc_ObjIsNet(pFanin) ); Abc_NtkDfsWithBoxes_rec( Abc_ObjFanin0Ntk(pFanin), vNodes ); } Vec_PtrPush( vNodes, pNode ); } Vec_Ptr_t * Abc_NtkDfsWithBoxes( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i; Abc_NtkIncrementTravId( pNtk ); vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachPo( pNtk, pObj, i ) { assert( Abc_ObjIsNet(Abc_ObjFanin0(pObj)) ); Abc_NtkDfsWithBoxes_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); } return vNodes; } /**Function************************************************************* Synopsis [Performs DFS for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkNodeSupport_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanin; int i; assert( !Abc_ObjIsNet(pNode) ); // if this node is already visited, skip if ( Abc_NodeIsTravIdCurrent( pNode ) ) return; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); // collect the CI if ( Abc_ObjIsCi(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_ObjFaninNum(pNode) == 0) ) { Vec_PtrPush( vNodes, pNode ); return; } assert( Abc_ObjIsNode( pNode ) ); // visit the transitive fanin of the node Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_NtkNodeSupport_rec( Abc_ObjFanin0Ntk(pFanin), vNodes ); } /**Function************************************************************* Synopsis [Returns the set of CI nodes in the support of the given nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkSupport( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pNode; int i; // set the traversal ID Abc_NtkIncrementTravId( pNtk ); // start the array of nodes vNodes = Vec_PtrAlloc( 100 ); // go through the PO nodes and call for each of them Abc_NtkForEachCo( pNtk, pNode, i ) Abc_NtkNodeSupport_rec( Abc_ObjFanin0(pNode), vNodes ); // add unused CIs Abc_NtkForEachCi( pNtk, pNode, i ) if ( !Abc_NodeIsTravIdCurrent( pNode ) ) Vec_PtrPush( vNodes, pNode ); assert( Vec_PtrSize(vNodes) == Abc_NtkCiNum(pNtk) ); return vNodes; } /**Function************************************************************* Synopsis [Returns the set of CI nodes in the support of the given nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) { Vec_Ptr_t * vNodes; int i; // set the traversal ID Abc_NtkIncrementTravId( pNtk ); // start the array of nodes 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]) && Abc_ObjFaninNum(Abc_ObjFanin0(ppNodes[i])) != 0 ) Abc_NtkNodeSupport_rec( Abc_ObjFanin0(ppNodes[i]), vNodes ); else if ( !Abc_ObjIsCo(ppNodes[i]) && Abc_ObjFaninNum(ppNodes[i]) != 0 ) Abc_NtkNodeSupport_rec( ppNodes[i], vNodes ); return vNodes; } /**Function************************************************************* Synopsis [Returns the set of CI node IDs in the support of the given node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkNodeSupportInt_rec( Abc_Obj_t * pNode, Vec_Int_t * vNodes ) { Abc_Obj_t * pFanin; int i; assert( !Abc_ObjIsNet(pNode) ); // if this node is already visited, skip if ( Abc_NodeIsTravIdCurrent( pNode ) ) return; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); // collect the CI if ( Abc_ObjIsCi(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_ObjFaninNum(pNode) == 0) ) { if ( Abc_ObjIsCi(pNode) ) Vec_IntPush( vNodes, pNode->iTemp ); return; } assert( Abc_ObjIsNode( pNode ) ); // visit the transitive fanin of the node Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_NtkNodeSupportInt_rec( Abc_ObjFanin0Ntk(pFanin), vNodes ); } Vec_Int_t * Abc_NtkNodeSupportInt( Abc_Ntk_t * pNtk, int iCo ) { Vec_Int_t * vNodes; Abc_Obj_t * pObj; int i; if ( iCo < 0 || iCo >= Abc_NtkCoNum(pNtk) ) return NULL; // save node indices in the CI nodes Abc_NtkForEachCi( pNtk, pObj, i ) pObj->iTemp = i; // collect the indexes of CI nodes in the TFI of the CO node Abc_NtkIncrementTravId( pNtk ); pObj = Abc_NtkCo( pNtk, iCo ); vNodes = Vec_IntAlloc( 100 ); Abc_NtkNodeSupportInt_rec( Abc_ObjFanin0(pObj), vNodes ); Vec_IntSort( vNodes, 0 ); return vNodes; } /**Function************************************************************* Synopsis [Derives GIA comparing two outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkFunctionalIsoGia_rec( Gia_Man_t * pNew, Abc_Obj_t * pNode ) { int iLit0, iLit1; if ( Abc_NodeIsTravIdCurrent(pNode) || Abc_ObjFaninNum(pNode) == 0 || Abc_ObjIsCi(pNode) ) return pNode->iTemp; assert( Abc_ObjIsNode( pNode ) ); Abc_NodeSetTravIdCurrent( pNode ); iLit0 = Abc_NtkFunctionalIsoGia_rec( pNew, Abc_ObjFanin0(pNode) ); iLit1 = Abc_NtkFunctionalIsoGia_rec( pNew, Abc_ObjFanin1(pNode) ); iLit0 = Abc_LitNotCond( iLit0, Abc_ObjFaninC0(pNode) ); iLit1 = Abc_LitNotCond( iLit1, Abc_ObjFaninC1(pNode) ); return (pNode->iTemp = Gia_ManHashAnd(pNew, iLit0, iLit1)); } Gia_Man_t * Abc_NtkFunctionalIsoGia( Abc_Ntk_t * pNtk, int iCo1, int iCo2, int fCommon ) { Gia_Man_t * pNew = NULL, * pTemp; Vec_Int_t * vSupp1 = Abc_NtkNodeSupportInt( pNtk, iCo1 ); Vec_Int_t * vSupp2 = Abc_NtkNodeSupportInt( pNtk, iCo2 ); if ( Vec_IntSize(vSupp1) == Vec_IntSize(vSupp2) ) { Abc_Obj_t * pObj; int i, iCi, iLit1, iLit2; pNew = Gia_ManStart( 1000 ); pNew->pName = Abc_UtilStrsav( pNtk->pName ); pNew->pSpec = Abc_UtilStrsav( pNtk->pSpec ); Gia_ManHashStart( pNew ); // put commom together if ( fCommon ) { Vec_Int_t * vCommon = Vec_IntAlloc( Vec_IntSize(vSupp1) ); Vec_IntTwoRemoveCommon( vSupp1, vSupp2, vCommon ); Vec_IntAppend( vSupp1, vCommon ); Vec_IntAppend( vSupp2, vCommon ); Vec_IntFree( vCommon ); assert( Vec_IntSize(vSupp1) == Vec_IntSize(vSupp2) ); } // primary inputs Abc_AigConst1(pNtk)->iTemp = 1; Vec_IntForEachEntry( vSupp1, iCi, i ) Abc_NtkCi(pNtk, iCi)->iTemp = Gia_ManAppendCi(pNew); // create the first cone Abc_NtkIncrementTravId( pNtk ); pObj = Abc_NtkCo( pNtk, iCo1 ); iLit1 = Abc_NtkFunctionalIsoGia_rec( pNew, Abc_ObjFanin0(pObj) ); iLit1 = Abc_LitNotCond( iLit1, Abc_ObjFaninC0(pObj) ); // primary inputs Vec_IntForEachEntry( vSupp2, iCi, i ) Abc_NtkCi(pNtk, iCi)->iTemp = Gia_ManCiLit(pNew, i); // create the second cone Abc_NtkIncrementTravId( pNtk ); pObj = Abc_NtkCo( pNtk, iCo2 ); iLit2 = Abc_NtkFunctionalIsoGia_rec( pNew, Abc_ObjFanin0(pObj) ); iLit2 = Abc_LitNotCond( iLit2, Abc_ObjFaninC0(pObj) ); Gia_ManAppendCo( pNew, iLit1 ); Gia_ManAppendCo( pNew, iLit2 ); // perform cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); } Vec_IntFree( vSupp1 ); Vec_IntFree( vSupp2 ); return pNew; } int Abc_NtkFunctionalIsoInt( Abc_Ntk_t * pNtk, int iCo1, int iCo2, int fCommon ) { Gia_Man_t * pGia; int Value; assert( Abc_NtkIsStrash(pNtk) ); if ( iCo1 < 0 || iCo1 >= Abc_NtkCoNum(pNtk) ) return 0; if ( iCo2 < 0 || iCo2 >= Abc_NtkCoNum(pNtk) ) return 0; pGia = Abc_NtkFunctionalIsoGia( pNtk, iCo1, iCo2, fCommon ); if ( pGia == NULL ) return 0; Value = Cec_ManVerifySimple( pGia ); Gia_ManStop( pGia ); return (int)(Value == 1); } int Abc_NtkFunctionalIso( Abc_Ntk_t * pNtk, int iCo1, int iCo2, int fCommon ) { Abc_Ntk_t * pNtkNew; int Result; if ( Abc_NtkIsStrash(pNtk) ) return Abc_NtkFunctionalIsoInt( pNtk, iCo1, iCo2, fCommon ); pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 ); Result = Abc_NtkFunctionalIsoInt( pNtkNew, iCo1, iCo2, fCommon ); Abc_NtkDelete( pNtkNew ); return Result; } /**Function************************************************************* Synopsis [Computes support size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjSuppSize_rec( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i, Counter = 0; if ( Abc_NodeIsTravIdCurrent(pObj) ) return 0; Abc_NodeSetTravIdCurrent(pObj); if ( Abc_ObjIsPi(pObj) ) return 1; assert( Abc_ObjIsNode(pObj) || Abc_ObjIsBox(pObj) ); Abc_ObjForEachFanin( pObj, pFanin, i ) Counter += Abc_ObjSuppSize_rec( pFanin ); return Counter; } /**Function************************************************************* Synopsis [Computes support size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjSuppSize( Abc_Obj_t * pObj ) { Abc_NtkIncrementTravId( Abc_ObjNtk(pObj) ); return Abc_ObjSuppSize_rec( pObj ); } /**Function************************************************************* Synopsis [Computes support size of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkSuppSizeTest( Abc_Ntk_t * p ) { Abc_Obj_t * pObj; int i, Counter = 0; abctime clk = Abc_Clock(); Abc_NtkForEachObj( p, pObj, i ) if ( Abc_ObjIsNode(pObj) ) Counter += (Abc_ObjSuppSize(pObj) <= 16); printf( "Nodes with small support %d (out of %d)\n", Counter, Abc_NtkNodeNum(p) ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return Counter; } /**Function************************************************************* Synopsis [Computes the sum total of supports of all outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSupportSum( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vSupp; Abc_Obj_t * pObj; int i, nTotalSupps = 0; Abc_NtkForEachCo( pNtk, pObj, i ) { vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); nTotalSupps += Vec_PtrSize( vSupp ); Vec_PtrFree( vSupp ); } printf( "Total supports = %d.\n", nTotalSupps ); } /**Function************************************************************* Synopsis [Performs DFS for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_AigDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanin; int i; // if this node is already visited, skip if ( Abc_NodeIsTravIdCurrent( pNode ) ) return; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); // skip the PI if ( Abc_ObjIsCi(pNode) || Abc_AigNodeIsConst(pNode) ) return; assert( Abc_ObjIsNode( pNode ) ); // visit the transitive fanin of the node Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_AigDfs_rec( pFanin, vNodes ); // visit the equivalent nodes if ( Abc_AigNodeIsChoice( pNode ) ) for ( pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pFanin = (Abc_Obj_t *)pFanin->pData ) Abc_AigDfs_rec( pFanin, vNodes ); // add the node after the fanins have been added Vec_PtrPush( vNodes, pNode ); } /**Function************************************************************* Synopsis [Returns the DFS ordered array of logic nodes.] Description [Collects only the internal nodes, leaving out CIs/COs. However it marks both CIs and COs with the current TravId.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pNode; int i; assert( Abc_NtkIsStrash(pNtk) ); // set the traversal ID Abc_NtkIncrementTravId( pNtk ); // start the array of nodes vNodes = Vec_PtrAlloc( 100 ); // go through the PO nodes and call for each of them Abc_NtkForEachCo( pNtk, pNode, i ) { Abc_AigDfs_rec( Abc_ObjFanin0(pNode), vNodes ); Abc_NodeSetTravIdCurrent( pNode ); if ( fCollectCos ) Vec_PtrPush( vNodes, pNode ); } // collect dangling nodes if asked to if ( fCollectAll ) { Abc_NtkForEachNode( pNtk, pNode, i ) if ( !Abc_NodeIsTravIdCurrent(pNode) ) Abc_AigDfs_rec( pNode, vNodes ); } return vNodes; } /**Function************************************************************* Synopsis [Returns the DFS ordered array of logic nodes.] Description [Collects only the internal nodes, leaving out CIs/COs. However it marks both CIs and COs with the current TravId.] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_AigDfsMap( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pNode; int i; assert( Abc_NtkIsStrash(pNtk) ); // set the traversal ID Abc_NtkIncrementTravId( pNtk ); // start the array of nodes vNodes = Vec_PtrAlloc( 100 ); // collect cones of barbufs Abc_NtkForEachCo( pNtk, pNode, i ) { if ( i < Abc_NtkCoNum(pNtk) - pNtk->nBarBufs ) continue; Abc_AigDfs_rec( Abc_ObjFanin0(pNode), vNodes ); Abc_NodeSetTravIdCurrent( pNode ); // collect latch as a placeholder assert( Abc_ObjIsLatch(Abc_ObjFanout0(pNode)) ); Vec_PtrPush( vNodes, Abc_ObjFanout0(pNode) ); } // collect nodes of real POs Abc_NtkForEachCo( pNtk, pNode, i ) { if ( i >= Abc_NtkCoNum(pNtk) - pNtk->nBarBufs ) break; Abc_AigDfs_rec( Abc_ObjFanin0(pNode), vNodes ); assert( Abc_ObjIsCo(pNode) ); Abc_NodeSetTravIdCurrent( pNode ); } return vNodes; } /**Function************************************************************* Synopsis [Collects nodes in the DFS manner by level.] Description [The number of levels should be set!!!] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels ) { Abc_Obj_t * pFanout; int i; // if this node is already visited, skip if ( Abc_NodeIsTravIdCurrent( pNode ) ) return; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); // skip the terminals if ( Abc_ObjIsCo(pNode) ) return; assert( Abc_ObjIsNode(pNode) ); // add the node to the structure Vec_VecPush( vLevels, pNode->Level, pNode ); // visit the TFO Abc_ObjForEachFanout( pNode, pFanout, i ) Abc_DfsLevelizedTfo_rec( pFanout, vLevels ); } /**Function************************************************************* Synopsis [Collects nodes in the DFS manner by level.] Description [The number of levels should be set!!!] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, int fTfi ) { Vec_Vec_t * vLevels; Abc_Obj_t * pFanout; int i; assert( fTfi == 0 ); assert( !Abc_NtkIsNetlist(pNode->pNtk) ); // set the traversal ID Abc_NtkIncrementTravId( pNode->pNtk ); vLevels = Vec_VecAlloc( 100 ); if ( Abc_ObjIsNode(pNode) ) Abc_DfsLevelizedTfo_rec( pNode, vLevels ); else { assert( Abc_ObjIsCi(pNode) ); Abc_NodeSetTravIdCurrent( pNode ); Abc_ObjForEachFanout( pNode, pFanout, i ) Abc_DfsLevelizedTfo_rec( pFanout, vLevels ); } return vLevels; } /**Function************************************************************* Synopsis [Recursively counts the number of logic levels of one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkLevel_rec( Abc_Obj_t * pNode ) { Abc_Obj_t * pNext; int i, Level; assert( !Abc_ObjIsNet(pNode) ); // skip the PI if ( Abc_ObjIsCi(pNode) ) return pNode->Level; assert( Abc_ObjIsNode( pNode ) || pNode->Type == ABC_OBJ_CONST1); // if this node is already visited, return if ( Abc_NodeIsTravIdCurrent( pNode ) ) return pNode->Level; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); // visit the transitive fanin pNode->Level = 0; Abc_ObjForEachFanin( pNode, pNext, i ) { Level = Abc_NtkLevel_rec( Abc_ObjFanin0Ntk(pNext) ); if ( pNode->Level < (unsigned)Level ) pNode->Level = Level; } if ( Abc_ObjFaninNum(pNode) > 0 && !Abc_ObjIsBarBuf(pNode) ) pNode->Level++; return pNode->Level; } /**Function************************************************************* Synopsis [Recursively counts the number of logic levels of one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkLevelReverse_rec( Abc_Obj_t * pNode ) { Abc_Obj_t * pNext; int i, Level; assert( !Abc_ObjIsNet(pNode) ); // skip the PI if ( Abc_ObjIsCo(pNode) ) return pNode->Level; assert( Abc_ObjIsNode( pNode ) || pNode->Type == ABC_OBJ_CONST1); // if this node is already visited, return if ( Abc_NodeIsTravIdCurrent( pNode ) ) return pNode->Level; // mark the node as visited Abc_NodeSetTravIdCurrent( pNode ); // visit the transitive fanin pNode->Level = 0; Abc_ObjForEachFanout( pNode, pNext, i ) { Level = Abc_NtkLevelReverse_rec( Abc_ObjFanout0Ntk(pNext) ); if ( pNode->Level < (unsigned)Level ) pNode->Level = Level; } if ( Abc_ObjFaninNum(pNode) > 0 && !Abc_ObjIsBarBuf(pNode) ) pNode->Level++; return pNode->Level; } /**Function************************************************************* Synopsis [Computes the number of logic levels not counting PIs/POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Vec_t * Abc_NtkLevelize( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; Vec_Vec_t * vLevels; int nLevels, i; nLevels = Abc_NtkLevel( pNtk ); vLevels = Vec_VecStart( nLevels + 1 ); Abc_NtkForEachNode( pNtk, pObj, i ) { assert( (int)pObj->Level <= nLevels ); Vec_VecPush( vLevels, pObj->Level, pObj ); } return vLevels; } /**Function************************************************************* Synopsis [Computes the number of logic levels not counting PIs/POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkLevel( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, LevelsMax; // set the CI levels if ( pNtk->pManTime == NULL || pNtk->AndGateDelay <= 0 ) Abc_NtkForEachCi( pNtk, pNode, i ) pNode->Level = 0; else Abc_NtkForEachCi( pNtk, pNode, i ) pNode->Level = (int)(Abc_MaxFloat(0, Abc_NodeReadArrivalWorst(pNode)) / pNtk->AndGateDelay); // perform the traversal LevelsMax = 0; Abc_NtkIncrementTravId( pNtk ); if ( pNtk->nBarBufs == 0 ) { Abc_NtkForEachNode( pNtk, pNode, i ) { Abc_NtkLevel_rec( pNode ); if ( LevelsMax < (int)pNode->Level ) LevelsMax = (int)pNode->Level; } } else { Abc_NtkForEachLiPo( pNtk, pNode, i ) { Abc_Obj_t * pDriver = Abc_ObjFanin0(pNode); Abc_NtkLevel_rec( pDriver ); if ( LevelsMax < (int)pDriver->Level ) LevelsMax = (int)pDriver->Level; // transfer the delay if ( i < pNtk->nBarBufs ) Abc_ObjFanout0(Abc_ObjFanout0(pNode))->Level = pDriver->Level; } } return LevelsMax; } /**Function************************************************************* Synopsis [Computes the number of logic levels not counting PIs/POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, LevelsMax; // set the CO levels to zero Abc_NtkForEachCo( pNtk, pNode, i ) pNode->Level = 0; // perform the traversal LevelsMax = 0; Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachNode( pNtk, pNode, i ) { Abc_NtkLevelReverse_rec( pNode ); if ( LevelsMax < (int)pNode->Level ) LevelsMax = (int)pNode->Level; } return LevelsMax; } int Abc_NtkLevelR( Abc_Ntk_t * pNtk ) { int i, LevelMax = Abc_NtkLevelReverse( pNtk ); Abc_Obj_t * pNode; Abc_NtkForEachObj( pNtk, pNode, i ) pNode->Level = (int)(LevelMax - pNode->Level + 1); return LevelMax; } /**Function************************************************************* Synopsis [Recursively detects combinational loops.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode ) { Abc_Ntk_t * pNtk = pNode->pNtk; Abc_Obj_t * pFanin; int fAcyclic, i; assert( !Abc_ObjIsNet(pNode) ); if ( Abc_ObjIsCi(pNode) || Abc_ObjIsBox(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) ) return 1; assert( Abc_ObjIsNode(pNode) ); // make sure the node is not visited assert( !Abc_NodeIsTravIdPrevious(pNode) ); // check if the node is part of the combinational loop if ( Abc_NodeIsTravIdCurrent(pNode) ) { fprintf( stdout, "Network \"%s\" contains combinational loop!\n", Abc_NtkName(pNtk) ); fprintf( stdout, "Node \"%s\" is encountered twice on the following path to the COs:\n", Abc_ObjName(pNode) ); return 0; } // mark this node as a node on the current path Abc_NodeSetTravIdCurrent( pNode ); // visit the transitive fanin Abc_ObjForEachFanin( pNode, pFanin, i ) { pFanin = Abc_ObjFanin0Ntk(pFanin); // make sure there is no mixing of networks assert( pFanin->pNtk == pNode->pNtk ); // check if the fanin is visited if ( Abc_NodeIsTravIdPrevious(pFanin) ) continue; // traverse the fanin's cone searching for the loop if ( (fAcyclic = Abc_NtkIsAcyclic_rec(pFanin)) ) continue; // return as soon as the loop is detected fprintf( stdout, " %s ->", Abc_ObjName(pFanin) ); return 0; } // visit choices if ( Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsChoice(pNode) ) { for ( pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pFanin = (Abc_Obj_t *)pFanin->pData ) { // check if the fanin is visited if ( Abc_NodeIsTravIdPrevious(pFanin) ) continue; // traverse the fanin's cone searching for the loop if ( (fAcyclic = Abc_NtkIsAcyclic_rec(pFanin)) ) continue; // return as soon as the loop is detected fprintf( stdout, " %s", Abc_ObjName(pFanin) ); fprintf( stdout, " (choice of %s) -> ", Abc_ObjName(pNode) ); return 0; } } // mark this node as a visited node Abc_NodeSetTravIdPrevious( pNode ); return 1; } /**Function************************************************************* Synopsis [Detects combinational loops.] Description [This procedure is based on the idea suggested by Donald Chai. As we traverse the network and visit the nodes, we need to distinquish three types of nodes: (1) those that are visited for the first time, (2) those that have been visited in this traversal but are currently not on the traversal path, (3) those that have been visited and are currently on the travesal path. When the node of type (3) is encountered, it means that there is a combinational loop. To mark the three types of nodes, two new values of the traversal IDs are used.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int fAcyclic; int i; // set the traversal ID for this DFS ordering Abc_NtkIncrementTravId( pNtk ); Abc_NtkIncrementTravId( pNtk ); // pNode->TravId == pNet->nTravIds means "pNode is on the path" // pNode->TravId == pNet->nTravIds - 1 means "pNode is visited but is not on the path" // pNode->TravId < pNet->nTravIds - 1 means "pNode is not visited" // traverse the network to detect cycles fAcyclic = 1; Abc_NtkForEachCo( pNtk, pNode, i ) { pNode = Abc_ObjFanin0Ntk(Abc_ObjFanin0(pNode)); if ( Abc_NodeIsTravIdPrevious(pNode) ) continue; // traverse the output logic cone if ( (fAcyclic = Abc_NtkIsAcyclic_rec(pNode)) ) continue; // stop as soon as the first loop is detected fprintf( stdout, " CO \"%s\"\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); break; } return fAcyclic; } /**Function************************************************************* Synopsis [Checks for the loops with boxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkIsAcyclicWithBoxes_rec( Abc_Obj_t * pNode ) { Abc_Ntk_t * pNtk = pNode->pNtk; Abc_Obj_t * pFanin; int fAcyclic, i; assert( !Abc_ObjIsNet(pNode) ); if ( Abc_ObjIsPi(pNode) || Abc_ObjIsLatch(pNode) || Abc_ObjIsBlackbox(pNode) ) return 1; assert( Abc_ObjIsNode(pNode) || Abc_ObjIsBox(pNode) ); // make sure the node is not visited assert( !Abc_NodeIsTravIdPrevious(pNode) ); // check if the node is part of the combinational loop if ( Abc_NodeIsTravIdCurrent(pNode) ) { fprintf( stdout, "Network \"%s\" contains combinational loop!\n", Abc_NtkName(pNtk) ); if ( Abc_ObjIsBox(pNode) ) fprintf( stdout, "Box \"%s\" is encountered twice on the following path to the COs:\n", Abc_ObjName(pNode) ); else fprintf( stdout, "Node \"%s\" is encountered twice on the following path to the COs:\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); return 0; } // mark this node as a node on the current path Abc_NodeSetTravIdCurrent( pNode ); // visit the transitive fanin Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( Abc_ObjIsBox(pNode) ) pFanin = Abc_ObjFanin0(pFanin); pFanin = Abc_ObjFanin0Ntk(pFanin); if ( Abc_ObjIsBo(pFanin) ) pFanin = Abc_ObjFanin0(pFanin); // check if the fanin is visited if ( Abc_ObjIsPi(pFanin) || Abc_ObjIsLatch(pFanin) || Abc_ObjIsBlackbox(pFanin) ) continue; assert( Abc_ObjIsNode(pFanin) || Abc_ObjIsBox(pFanin) ); if ( Abc_NodeIsTravIdPrevious(pFanin) ) continue; // traverse the fanin's cone searching for the loop if ( (fAcyclic = Abc_NtkIsAcyclicWithBoxes_rec(pFanin)) ) continue; // return as soon as the loop is detected fprintf( stdout, " %s ->", Abc_ObjName( Abc_ObjIsBox(pFanin) ? pFanin : Abc_ObjFanout0(pFanin) ) ); return 0; } // mark this node as a visited node assert( Abc_ObjIsNode(pNode) || Abc_ObjIsBox(pNode) ); Abc_NodeSetTravIdPrevious( pNode ); return 1; } int Abc_NtkIsAcyclicWithBoxes( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int fAcyclic; int i; // set the traversal ID for this DFS ordering Abc_NtkIncrementTravId( pNtk ); Abc_NtkIncrementTravId( pNtk ); // pNode->TravId == pNet->nTravIds means "pNode is on the path" // pNode->TravId == pNet->nTravIds - 1 means "pNode is visited but is not on the path" // pNode->TravId < pNet->nTravIds - 1 means "pNode is not visited" // traverse the network to detect cycles fAcyclic = 1; Abc_NtkForEachPo( pNtk, pNode, i ) { pNode = Abc_ObjFanin0Ntk(Abc_ObjFanin0(pNode)); if ( Abc_ObjIsBo(pNode) ) pNode = Abc_ObjFanin0(pNode); if ( Abc_NodeIsTravIdPrevious(pNode) ) continue; // traverse the output logic cone if ( (fAcyclic = Abc_NtkIsAcyclicWithBoxes_rec(pNode)) ) continue; // stop as soon as the first loop is detected fprintf( stdout, " PO \"%s\"\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); break; } if ( fAcyclic ) { Abc_NtkForEachLatchInput( pNtk, pNode, i ) { pNode = Abc_ObjFanin0Ntk(Abc_ObjFanin0(pNode)); if ( Abc_ObjIsBo(pNode) ) pNode = Abc_ObjFanin0(pNode); if ( Abc_NodeIsTravIdPrevious(pNode) ) continue; // traverse the output logic cone if ( (fAcyclic = Abc_NtkIsAcyclicWithBoxes_rec(pNode)) ) continue; // stop as soon as the first loop is detected fprintf( stdout, " PO \"%s\"\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); break; } } return fAcyclic; } /**Function************************************************************* Synopsis [Analyses choice nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeSetChoiceLevel_rec( Abc_Obj_t * pNode, int fMaximum ) { Abc_Obj_t * pTemp; int Level1, Level2, Level, LevelE; // skip the visited node if ( Abc_NodeIsTravIdCurrent( pNode ) ) return (int)(ABC_PTRINT_T)pNode->pCopy; Abc_NodeSetTravIdCurrent( pNode ); // compute levels of the children nodes Level1 = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin0(pNode), fMaximum ); Level2 = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin1(pNode), fMaximum ); Level = 1 + Abc_MaxInt( Level1, Level2 ); if ( pNode->pData ) { LevelE = Abc_NodeSetChoiceLevel_rec( (Abc_Obj_t *)pNode->pData, fMaximum ); if ( fMaximum ) Level = Abc_MaxInt( Level, LevelE ); else Level = Abc_MinInt( Level, LevelE ); // set the level of all equivalent nodes to be the same minimum for ( pTemp = (Abc_Obj_t *)pNode->pData; pTemp; pTemp = (Abc_Obj_t *)pTemp->pData ) pTemp->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Level; } pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Level; return Level; } /**Function************************************************************* Synopsis [Resets the levels of the nodes in the choice graph.] Description [Makes the level of the choice nodes to be equal to the maximum of the level of the nodes in the equivalence class. This way sorting by level leads to the reverse topological order, which is needed for the required time computation.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_AigSetChoiceLevels( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i, LevelMax, LevelCur; assert( Abc_NtkIsStrash(pNtk) ); // set the new travid counter Abc_NtkIncrementTravId( pNtk ); // set levels of the CI and constant Abc_NtkForEachCi( pNtk, pObj, i ) { Abc_NodeSetTravIdCurrent( pObj ); pObj->pCopy = NULL; } pObj = Abc_AigConst1( pNtk ); Abc_NodeSetTravIdCurrent( pObj ); pObj->pCopy = NULL; // set levels of all other nodes LevelMax = 0; Abc_NtkForEachCo( pNtk, pObj, i ) { LevelCur = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin0(pObj), 1 ); LevelMax = Abc_MaxInt( LevelMax, LevelCur ); } return LevelMax; } /**Function************************************************************* Synopsis [Returns nodes by level from the smallest to the largest.] Description [Correctly handles the case of choice nodes, by first spreading them out across several levels and then collecting.] SideEffects [What happens with dangling nodes???] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis ) { Vec_Ptr_t * vNodes, * vLevels; Abc_Obj_t * pNode, ** ppHead; int LevelMax, i; assert( Abc_NtkIsStrash(pNtk) ); // set the correct levels Abc_NtkCleanCopy( pNtk ); LevelMax = Abc_AigSetChoiceLevels( pNtk ); // relink nodes by level vLevels = Vec_PtrStart( LevelMax + 1 ); Abc_NtkForEachNode( pNtk, pNode, i ) { ppHead = ((Abc_Obj_t **)vLevels->pArray) + (int)(ABC_PTRINT_T)pNode->pCopy; pNode->pCopy = *ppHead; *ppHead = pNode; } // recollect nodes vNodes = Vec_PtrStart( Abc_NtkNodeNum(pNtk) ); Vec_PtrForEachEntryStart( Abc_Obj_t *, vLevels, pNode, i, !fCollectCis ) for ( ; pNode; pNode = pNode->pCopy ) Vec_PtrPush( vNodes, pNode ); Vec_PtrFree( vLevels ); return vNodes; } /**Function************************************************************* Synopsis [Count the number of nodes in the subgraph.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjSugraphSize( Abc_Obj_t * pObj ) { if ( Abc_ObjIsCi(pObj) ) return 0; if ( Abc_ObjFanoutNum(pObj) > 1 ) return 0; return 1 + Abc_ObjSugraphSize(Abc_ObjFanin0(pObj)) + Abc_ObjSugraphSize(Abc_ObjFanin1(pObj)); } /**Function************************************************************* Synopsis [Prints subgraphs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkPrintSubraphSizes( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; assert( Abc_NtkIsStrash(pNtk) ); Abc_NtkForEachNode( pNtk, pObj, i ) if ( Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsExorType(pObj) ) printf( "%d(%d) ", 1 + Abc_ObjSugraphSize(Abc_ObjFanin0(pObj)) + Abc_ObjSugraphSize(Abc_ObjFanin1(pObj)), Abc_ObjFanoutNum(pObj) ); printf( "\n" ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcFanOrder.c000066400000000000000000000512121477524141600167410ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcFanOrder.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Fanin ordering procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcFanOrder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reorder fanins of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkOrderFaninsById( Abc_Ntk_t * pNtk ) { Vec_Int_t * vOrder; Vec_Str_t * vStore; Abc_Obj_t * pNode; char * pSop, * pSopNew; char * pCube, * pCubeNew; int nVars, i, v, * pOrder; assert( Abc_NtkHasSop(pNtk) ); vOrder = Vec_IntAlloc( 100 ); vStore = Vec_StrAlloc( 100 ); Abc_NtkForEachNode( pNtk, pNode, i ) { pSop = (char *)pNode->pData; nVars = Abc_SopGetVarNum(pSop); assert( nVars == Abc_ObjFaninNum(pNode) ); Vec_IntClear( vOrder ); for ( v = 0; v < nVars; v++ ) Vec_IntPush( vOrder, v ); pOrder = Vec_IntArray(vOrder); Vec_IntSelectSortCost( pOrder, nVars, &pNode->vFanins ); // copy the cover Vec_StrGrow( vStore, 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 Abc_SopForEachCube( pSop, nVars, pCube ) { for ( v = 0; v < nVars; v++ ) pCubeNew[v] = '-'; for ( v = 0; v < nVars; v++ ) if ( pCube[pOrder[v]] == '0' ) pCubeNew[v] = '0'; else if ( pCube[pOrder[v]] == '1' ) pCubeNew[v] = '1'; pCubeNew += nVars + 3; } pNode->pData = pSopNew; Vec_IntSort( &pNode->vFanins, 0 ); // Vec_IntPrint( vOrder ); } Vec_IntFree( vOrder ); Vec_StrFree( vStore ); } /**Function************************************************************* Synopsis [Returns fanin permutation to reorders columns lexicographically.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSopTranspose( char * pSop, int nVars, Vec_Ptr_t * vCubes, Vec_Str_t * vStore ) { char * pCube; int nCubes, v, c; // collect original cubes Vec_PtrClear( vCubes ); Abc_SopForEachCube( pSop, nVars, pCube ) Vec_PtrPush( vCubes, pCube ); // rebuild the cubes Vec_StrClear( vStore ); for ( v = 0; v < nVars; v++ ) { Vec_PtrForEachEntry( char *, vCubes, pCube, c ) Vec_StrPush( vStore, pCube[v] ); Vec_StrPush( vStore, '\0' ); } // get the cubes nCubes = Vec_PtrSize( vCubes ); Vec_PtrClear( vCubes ); for ( v = 0; v < nVars; v++ ) Vec_PtrPush( vCubes, Vec_StrEntryP(vStore, v*(nCubes+1)) ); } static inline void Vec_StrSelectSortCost( char ** pArray, int nSize, Vec_Int_t * vPerm ) { int i, j, best_i, * pPerm; Vec_IntClear( vPerm ); for ( i = 0; i < nSize; i++ ) Vec_IntPush( vPerm, i ); pPerm = Vec_IntArray( vPerm ); for ( i = 0; i < nSize-1; i++ ) { best_i = i; for ( j = i+1; j < nSize; j++ ) if ( strcmp(pArray[j], pArray[best_i]) < 0 ) best_i = j; ABC_SWAP( char *, pArray[i], pArray[best_i] ); ABC_SWAP( int, pPerm[i], pPerm[best_i] ); } } void Abc_NtkOrderFaninsBySortingColumns( Abc_Ntk_t * pNtk ) { Vec_Int_t * vOrder; Vec_Int_t * vCounts; Vec_Int_t * vFanins; Vec_Str_t * vStore; Vec_Ptr_t * vCubes; Abc_Obj_t * pNode; char * pSop, * pSopNew; char * pCube, * pCubeNew; int nVars, i, v, * pOrder; assert( Abc_NtkHasSop(pNtk) ); vOrder = Vec_IntAlloc( 100 ); vStore = Vec_StrAlloc( 100 ); vCubes = Vec_PtrAlloc( 100 ); vCounts = Vec_IntAlloc( 100 ); vFanins = Vec_IntAlloc( 100 ); Abc_NtkForEachNode( pNtk, pNode, i ) { pSop = (char *)pNode->pData; nVars = Abc_SopGetVarNum(pSop); assert( nVars == Abc_ObjFaninNum(pNode) ); // create a transposed SOP Abc_NtkSopTranspose( pSop, nVars, vCubes, vStore ); // create permutation Vec_StrSelectSortCost( (char **)Vec_PtrArray(vCubes), nVars, vOrder ); pOrder = Vec_IntArray(vOrder); // copy the cover Vec_StrGrow( vStore, 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 Abc_SopForEachCube( pSop, nVars, pCube ) { for ( v = 0; v < nVars; v++ ) pCubeNew[v] = '-'; for ( v = 0; v < nVars; v++ ) if ( pCube[pOrder[v]] == '0' ) pCubeNew[v] = '0'; else if ( pCube[pOrder[v]] == '1' ) pCubeNew[v] = '1'; pCubeNew += nVars + 3; } pNode->pData = pSopNew; // generate the fanin order Vec_IntClear( vFanins ); for ( v = 0; v < nVars; v++ ) Vec_IntPush( vFanins, Abc_ObjFaninId( pNode, pOrder[v] ) ); Vec_IntClear( &pNode->vFanins ); Vec_IntAppend( &pNode->vFanins, vFanins ); } Vec_IntFree( vFanins ); Vec_IntFree( vCounts ); Vec_IntFree( vOrder ); Vec_StrFree( vStore ); Vec_PtrFree( vCubes ); } /**Function************************************************************* Synopsis [Reorders columns by literal and then lexicographically.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_StrSelectSortCost2( char ** pArray, int nSize, Vec_Int_t * vCounts, Vec_Int_t * vPerm ) { int i, j, best_i, * pPerm; Vec_IntClear( vPerm ); for ( i = 0; i < nSize; i++ ) Vec_IntPush( vPerm, i ); pPerm = Vec_IntArray( vPerm ); for ( i = 0; i < nSize-1; i++ ) { best_i = i; for ( j = i+1; j < nSize; j++ ) if ( Vec_IntEntry(vCounts, pPerm[j]) < Vec_IntEntry(vCounts, pPerm[best_i]) || (Vec_IntEntry(vCounts, pPerm[j]) == Vec_IntEntry(vCounts, pPerm[best_i]) && strcmp(pArray[j], pArray[best_i]) < 0) ) best_i = j; ABC_SWAP( char *, pArray[i], pArray[best_i] ); ABC_SWAP( int, pPerm[i], pPerm[best_i] ); } } void Abc_NtkOrderFaninsByLitCount( Abc_Ntk_t * pNtk ) { Vec_Int_t * vOrder; Vec_Int_t * vCounts; Vec_Int_t * vFanins; Vec_Str_t * vStore; Vec_Ptr_t * vCubes; Abc_Obj_t * pNode; char * pSop, * pSopNew; char * pCube, * pCubeNew; int nVars, i, v, * pOrder; assert( Abc_NtkHasSop(pNtk) ); vOrder = Vec_IntAlloc( 100 ); vStore = Vec_StrAlloc( 100 ); vCubes = Vec_PtrAlloc( 100 ); vCounts = Vec_IntAlloc( 100 ); vFanins = Vec_IntAlloc( 100 ); Abc_NtkForEachNode( pNtk, pNode, i ) { pSop = (char *)pNode->pData; nVars = Abc_SopGetVarNum(pSop); assert( nVars == Abc_ObjFaninNum(pNode) ); // count literals Vec_IntFill( vCounts, nVars, 0 ); Abc_SopForEachCube( pSop, nVars, pCube ) for ( v = 0; v < nVars; v++ ) if ( pCube[v] != '-' ) Vec_IntAddToEntry( vCounts, v, 1 ); // create a transposed SOP Abc_NtkSopTranspose( pSop, nVars, vCubes, vStore ); // create permutation Vec_StrSelectSortCost2( (char **)Vec_PtrArray(vCubes), nVars, vCounts, vOrder ); pOrder = Vec_IntArray(vOrder); /* // find good order Vec_IntClear( vOrder ); for ( v = 0; v < nVars; v++ ) Vec_IntPush( vOrder, v ); pOrder = Vec_IntArray(vOrder); Vec_IntSelectSortCost( pOrder, nVars, vCounts ); */ // copy the cover Vec_StrGrow( vStore, 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 Abc_SopForEachCube( pSop, nVars, pCube ) { for ( v = 0; v < nVars; v++ ) pCubeNew[v] = '-'; for ( v = 0; v < nVars; v++ ) if ( pCube[pOrder[v]] == '0' ) pCubeNew[v] = '0'; else if ( pCube[pOrder[v]] == '1' ) pCubeNew[v] = '1'; pCubeNew += nVars + 3; } pNode->pData = pSopNew; // generate the fanin order Vec_IntClear( vFanins ); for ( v = 0; v < nVars; v++ ) Vec_IntPush( vFanins, Abc_ObjFaninId( pNode, pOrder[v] ) ); Vec_IntClear( &pNode->vFanins ); Vec_IntAppend( &pNode->vFanins, vFanins ); } Vec_IntFree( vFanins ); Vec_IntFree( vCounts ); Vec_IntFree( vOrder ); Vec_StrFree( vStore ); Vec_PtrFree( vCubes ); } void Abc_NtkOrderFaninsByLitCountAndCubeCount( Abc_Ntk_t * pNtk ) { // assuming that the fanins are sorted by the number of literals in each cube // this procedure sorts the literals appearing only once by the number of their cube Vec_Int_t * vOrder; Vec_Int_t * vCounts; Vec_Int_t * vFanins; Vec_Int_t * vCubeNum; Vec_Str_t * vStore; Abc_Obj_t * pNode; char * pSop, * pSopNew; char * pCube, * pCubeNew; int nVars, i, v, iCube, * pOrder; assert( Abc_NtkHasSop(pNtk) ); vStore = Vec_StrAlloc( 100 ); vOrder = Vec_IntAlloc( 100 ); vCounts = Vec_IntAlloc( 100 ); vFanins = Vec_IntAlloc( 100 ); vCubeNum = Vec_IntAlloc( 100 ); Abc_NtkForEachNode( pNtk, pNode, i ) { pSop = (char *)pNode->pData; nVars = Abc_SopGetVarNum(pSop); assert( nVars == Abc_ObjFaninNum(pNode) ); // count literals and remember the cube where each literal appears Vec_IntFill( vCounts, nVars, 0 ); Vec_IntFill( vCubeNum, nVars, 0 ); iCube = 0; Abc_SopForEachCube( pSop, nVars, pCube ) { for ( v = 0; v < nVars; v++ ) if ( pCube[v] != '-' ) { Vec_IntAddToEntry( vCounts, v, 1 ); Vec_IntWriteEntry( vCubeNum, v, iCube ); } iCube++; } // create new order for ( v = 0; v < nVars; v++ ) if ( Vec_IntEntry(vCounts, v) == 1 ) Vec_IntWriteEntry( vCounts, v, Vec_IntEntry(vCubeNum, v) ); else Vec_IntWriteEntry( vCounts, v, ABC_INFINITY ); // find good order Vec_IntClear( vOrder ); for ( v = 0; v < nVars; v++ ) Vec_IntPush( vOrder, v ); pOrder = Vec_IntArray(vOrder); Vec_IntSelectSortCost( pOrder, nVars, vCounts ); // copy the cover Vec_StrGrow( vStore, 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 Abc_SopForEachCube( pSop, nVars, pCube ) { for ( v = 0; v < nVars; v++ ) pCubeNew[v] = '-'; for ( v = 0; v < nVars; v++ ) if ( pCube[pOrder[v]] == '0' ) pCubeNew[v] = '0'; else if ( pCube[pOrder[v]] == '1' ) pCubeNew[v] = '1'; pCubeNew += nVars + 3; } pNode->pData = pSopNew; // generate the fanin order Vec_IntClear( vFanins ); for ( v = 0; v < nVars; v++ ) Vec_IntPush( vFanins, Abc_ObjFaninId( pNode, pOrder[v] ) ); Vec_IntClear( &pNode->vFanins ); Vec_IntAppend( &pNode->vFanins, vFanins ); } Vec_IntFree( vCubeNum ); Vec_IntFree( vFanins ); Vec_IntFree( vCounts ); Vec_IntFree( vOrder ); Vec_StrFree( vStore ); } /**Function************************************************************* Synopsis [Split large nodes by dividing their SOPs in half.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeSplitLarge( Abc_Obj_t * pNode ) { Abc_Obj_t * pNode1, * pNode2, * pFanin; int CutPoint, nVars = Abc_ObjFaninNum(pNode); int i, nCubes = Abc_SopGetCubeNum((char *)pNode->pData); pNode1 = Abc_NtkDupObj( pNode->pNtk, pNode, 0 ); pNode2 = Abc_NtkDupObj( pNode->pNtk, pNode, 0 ); Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_ObjAddFanin( pNode1, pFanin ); Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_ObjAddFanin( pNode2, pFanin ); // update the node Abc_ObjRemoveFanins( pNode ); Abc_ObjAddFanin( pNode, pNode1 ); Abc_ObjAddFanin( pNode, pNode2 ); pNode->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNode->pNtk->pManFunc, 2, NULL ); // update covers of the nodes assert( nCubes > 1 ); CutPoint = (nCubes / 2) * (nVars + 3); ((char *)pNode1->pData)[CutPoint] = 0; pNode2->pData = (char *)pNode2->pData + CutPoint; } void Abc_NtkSplitLarge( Abc_Ntk_t * pNtk, int nFaninsMax, int nCubesMax ) { Abc_Obj_t * pNode; int nObjOld = Abc_NtkObjNumMax(pNtk); int i, nCubes; assert( Abc_NtkHasSop(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { if ( i == nObjOld ) break; nCubes = Abc_SopGetCubeNum((char *)pNode->pData); if ( (Abc_ObjFaninNum(pNode) > nFaninsMax && nCubes > 1) || nCubes > nCubesMax ) Abc_NodeSplitLarge( pNode ); } } /**Function************************************************************* Synopsis [Sorts the cubes in a topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCompareCubes1( char ** pp1, char ** pp2 ) { return strcmp( *pp1, *pp2 ); } int Abc_NodeCompareCubes2( char ** pp1, char ** pp2 ) { char * pStr1 = *pp1; char * pStr2 = *pp2; int i, nNum1 = 0, nNum2 = 0; for ( i = 0; pStr1[i]; i++ ) { nNum1 += (pStr1[i] != '-'); nNum2 += (pStr2[i] != '-'); } if ( nNum1 > nNum2 ) return -1; if ( nNum1 < nNum2 ) return 1; return strcmp( *pp1, *pp2 ); } void Abc_NodeSortCubes( Abc_Obj_t * pNode, Vec_Ptr_t * vCubes, Vec_Str_t * vStore, int fWeight ) { char * pCube, * pPivot; char * pSop = (char *)pNode->pData; int i, nVars = Abc_ObjFaninNum(pNode); Vec_PtrClear( vCubes ); Abc_SopForEachCube( pSop, nVars, pCube ) { assert( pCube[nVars] == ' ' ); pCube[nVars] = 0; Vec_PtrPush( vCubes, pCube ); } if ( fWeight ) Vec_PtrSort( vCubes, (int (*)(const void *, const void *))Abc_NodeCompareCubes2 ); else 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, (size_t)(nVars + 3) ); pPivot += nVars + 3; } memcpy( pSop, Vec_StrArray(vStore), (size_t)(Vec_PtrSize(vCubes) * (nVars + 3)) ); } void Abc_NtkSortCubes( Abc_Ntk_t * pNtk, int fWeight ) { Vec_Ptr_t * vCubes; Vec_Str_t * vStore; Abc_Obj_t * pNode; int i; assert( Abc_NtkHasSop(pNtk) ); vCubes = Vec_PtrAlloc( 1000 ); vStore = Vec_StrAlloc( 1000 ); Abc_NtkForEachNode( pNtk, pNode, i ) Abc_NodeSortCubes( pNode, vCubes, vStore, fWeight ); Vec_StrFree( vStore ); Vec_PtrFree( vCubes ); } /**Function************************************************************* Synopsis [Sorts fanins of each node to make SOPs more readable.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSortSops( Abc_Ntk_t * pNtk ) { Abc_NtkSortCubes( pNtk, 1 ); Abc_NtkOrderFaninsByLitCount( pNtk ); Abc_NtkSortCubes( pNtk, 0 ); Abc_NtkOrderFaninsByLitCountAndCubeCount( pNtk ); Abc_NtkSortCubes( pNtk, 0 ); } /**Function************************************************************* Synopsis [Makes cover legitimate for "fast_extract".] Description [Iteratively removes distance-1 and contained cubes.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_CubeContain( char * pCube1, char * pCube2, int nVars ) { int v, fCont12 = 1, fCont21 = 1; for ( v = 0; v < nVars; v++ ) { if ( pCube1[v] == pCube2[v] ) continue; if ( pCube1[v] == '-' ) fCont21 = 0; else if ( pCube2[v] == '-' ) fCont12 = 0; else return 0; if ( !fCont12 && !fCont21 ) return 0; } assert( fCont21 || fCont12 ); return (fCont21 << 1) | fCont12; } int Abc_NodeMakeSCCFree( Abc_Obj_t * pNode ) { char * pSop = (char *)pNode->pData; char * pCube, * pCube2, * pSopNew; int nVars = Abc_ObjFaninNum(pNode); int Status, nCount = 0; Abc_SopForEachCubePair( pSop, nVars, pCube, pCube2 ) { if ( pCube[0] == 'z' || pCube2[0] == 'z' ) continue; Status = Abc_CubeContain( pCube, pCube2, nVars ); nCount += (int)(Status > 0); if ( Status & 1 ) pCube2[0] = 'z'; else if ( Status & 2 ) pCube[0] = 'z'; } if ( nCount == 0 ) return 0; // create new cover pSopNew = (char *)pNode->pData; Abc_SopForEachCube( pSop, nVars, pCube ) { if ( pCube[0] == 'z' ) continue; memcpy( pSopNew, pCube, (size_t)(nVars + 3) ); pSopNew += nVars + 3; } *pSopNew = 0; return 1; } void Abc_NodeMakeDist1Free( Abc_Obj_t * pNode ) { char * pSop = (char *)pNode->pData; char * pCube, * pCube2; int i, nVars = Abc_ObjFaninNum(pNode); Abc_SopForEachCube( pSop, nVars, pCube ) Abc_SopForEachCube( pCube + nVars + 3, nVars, pCube2 ) { int Counter = 0, iDiff = -1; for ( i = 0; i < nVars; i++ ) if ( pCube[i] != pCube2[i] ) Counter++, iDiff = i; if ( Counter == 1 && ((pCube[iDiff] == '0' && pCube2[iDiff] == '1') || (pCube[iDiff] == '1' && pCube2[iDiff] == '0')) ) pCube[iDiff] = pCube2[iDiff] = '-'; } } void Abc_NodeCheckDist1Free( Abc_Obj_t * pNode ) { char * pSop = (char *)pNode->pData; char * pCube, * pCube2; int i, nVars = Abc_ObjFaninNum(pNode); Abc_SopForEachCube( pSop, nVars, pCube ) Abc_SopForEachCube( pSop, nVars, pCube2 ) { int Counter = 0; if ( pCube == pCube2 ) continue; for ( i = 0; i < nVars; i++ ) if ( pCube[i] != pCube2[i] ) Counter++; assert( Counter > 1 ); } } int Abc_NodeMakeLegit( Abc_Obj_t * pNode ) { int i, fChanges = 1; for ( i = 0; fChanges; i++ ) { Abc_NodeMakeDist1Free( pNode ); fChanges = Abc_NodeMakeSCCFree( pNode ); } // Abc_NodeCheckDist1Free( pNode ); return i > 1; } int Abc_NtkMakeLegit( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, Counter = 0; assert( Abc_NtkHasSop(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) Counter += Abc_NodeMakeLegit( pNode ); if ( Counter ) Abc_Print( 0, "%d nodes were made dist1-cube-free and/or single-cube-containment-free.\n", Counter ); return 1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcFanio.c000066400000000000000000000307011477524141600162750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcFanio.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Various procedures to connect fanins/fanouts.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcFanio.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Vec_IntPushMem( Mem_Step_t * pMemMan, Vec_Int_t * p, int Entry ) { if ( p->nSize == p->nCap ) { int * pArray; int i; if ( p->nSize == 0 ) p->nCap = 1; if ( pMemMan ) pArray = (int *)Mem_StepEntryFetch( pMemMan, p->nCap * 8 ); else pArray = ABC_ALLOC( int, p->nCap * 2 ); if ( p->pArray ) { for ( i = 0; i < p->nSize; i++ ) pArray[i] = p->pArray[i]; if ( pMemMan ) Mem_StepEntryRecycle( pMemMan, (char *)p->pArray, p->nCap * 4 ); else ABC_FREE( p->pArray ); } p->nCap *= 2; p->pArray = pArray; } p->pArray[p->nSize++] = Entry; } /**Function************************************************************* Synopsis [Creates fanout/fanin relationship between the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) { Abc_Obj_t * pFaninR = Abc_ObjRegular(pFanin); assert( !Abc_ObjIsComplement(pObj) ); assert( pObj->pNtk == pFaninR->pNtk ); assert( pObj->Id >= 0 && pFaninR->Id >= 0 ); assert( !Abc_ObjIsPi(pObj) && !Abc_ObjIsPo(pFaninR) ); // fanin of PI or fanout of PO assert( !Abc_ObjIsCo(pObj) || !Abc_ObjFaninNum(pObj) ); // CO with two fanins assert( !Abc_ObjIsNet(pObj) || !Abc_ObjFaninNum(pObj) ); // net with two fanins Vec_IntPushMem( pObj->pNtk->pMmStep, &pObj->vFanins, pFaninR->Id ); Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninR->vFanouts, pObj->Id ); if ( Abc_ObjIsComplement(pFanin) ) Abc_ObjSetFaninC( pObj, Abc_ObjFaninNum(pObj)-1 ); } /**Function************************************************************* Synopsis [Destroys fanout/fanin relationship between the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) { assert( !Abc_ObjIsComplement(pObj) ); assert( !Abc_ObjIsComplement(pFanin) ); assert( pObj->pNtk == pFanin->pNtk ); assert( pObj->Id >= 0 && pFanin->Id >= 0 ); if ( !Vec_IntRemove( &pObj->vFanins, pFanin->Id ) ) { printf( "The obj %d is not found among the fanins of obj %d ...\n", pFanin->Id, pObj->Id ); return; } if ( !Vec_IntRemove( &pFanin->vFanouts, pObj->Id ) ) { printf( "The obj %d is not found among the fanouts of obj %d ...\n", pObj->Id, pFanin->Id ); return; } } /**Function************************************************************* Synopsis [Destroys fanout/fanin relationship between the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ObjRemoveFanins( Abc_Obj_t * pObj ) { Vec_Int_t * vFaninsOld; Abc_Obj_t * pFanin; int k; // remove old fanins vFaninsOld = &pObj->vFanins; for ( k = vFaninsOld->nSize - 1; k >= 0; k-- ) { pFanin = Abc_NtkObj( pObj->pNtk, vFaninsOld->pArray[k] ); Abc_ObjDeleteFanin( pObj, pFanin ); } pObj->fCompl0 = 0; pObj->fCompl1 = 0; assert( vFaninsOld->nSize == 0 ); } /**Function************************************************************* Synopsis [Replaces a fanin of the node.] Description [The node is pObj. An old fanin of this node (pFaninOld) has to be replaced by a new fanin (pFaninNew). Assumes that the node and the old fanin are not complemented. The new fanin can be complemented. In this case, the polarity of the new fanin will change, compared to the polarity of the old fanin.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew ) { Abc_Obj_t * pFaninNewR = Abc_ObjRegular(pFaninNew); int iFanin;//, nLats;//, fCompl; assert( !Abc_ObjIsComplement(pObj) ); assert( !Abc_ObjIsComplement(pFaninOld) ); assert( pFaninOld != pFaninNewR ); // assert( pObj != pFaninOld ); // assert( pObj != pFaninNewR ); assert( pObj->pNtk == pFaninOld->pNtk ); assert( pObj->pNtk == pFaninNewR->pNtk ); if ( (iFanin = Vec_IntFind( &pObj->vFanins, pFaninOld->Id )) == -1 ) { printf( "Node %s is not among", Abc_ObjName(pFaninOld) ); printf( " the fanins of node %s...\n", Abc_ObjName(pObj) ); return; } // remember the attributes of the old fanin // fCompl = Abc_ObjFaninC(pObj, iFanin); // replace the old fanin entry by the new fanin entry (removes attributes) Vec_IntWriteEntry( &pObj->vFanins, iFanin, pFaninNewR->Id ); // set the attributes of the new fanin // if ( fCompl ^ Abc_ObjIsComplement(pFaninNew) ) // Abc_ObjSetFaninC( pObj, iFanin ); if ( Abc_ObjIsComplement(pFaninNew) ) Abc_ObjXorFaninC( pObj, iFanin ); // if ( Abc_NtkIsSeq(pObj->pNtk) && (nLats = Seq_ObjFaninL(pObj, iFanin)) ) // Seq_ObjSetFaninL( pObj, iFanin, nLats ); // update the fanout of the fanin if ( !Vec_IntRemove( &pFaninOld->vFanouts, pObj->Id ) ) { printf( "Node %s is not among", Abc_ObjName(pObj) ); printf( " the fanouts of its old fanin %s...\n", Abc_ObjName(pFaninOld) ); // return; } Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninNewR->vFanouts, pObj->Id ); } /**Function************************************************************* Synopsis [Replaces pObj by iObjNew in the fanin arrays of the fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ObjPatchFanoutFanin( Abc_Obj_t * pObj, int iObjNew ) { Abc_Obj_t * pFanout; int i, k, Entry; // update fanouts of the node to point to this one Abc_ObjForEachFanout( pObj, pFanout, i ) { Vec_IntForEachEntry( &pFanout->vFanins, Entry, k ) if ( Entry == (int)Abc_ObjId(pObj) ) { Vec_IntWriteEntry( &pFanout->vFanins, k, iObjNew ); break; } assert( k < Vec_IntSize(&pFanout->vFanins) ); } } /**Function************************************************************* Synopsis [Inserts one-input node of the type specified between the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type ) { Abc_Obj_t * pNodeNew; int iFanoutIndex, iFaninIndex; // find pNodeOut among the fanouts of pNodeIn if ( (iFanoutIndex = Vec_IntFind( &pNodeIn->vFanouts, pNodeOut->Id )) == -1 ) { printf( "Node %s is not among", Abc_ObjName(pNodeOut) ); printf( " the fanouts of node %s...\n", Abc_ObjName(pNodeIn) ); return NULL; } // find pNodeIn among the fanins of pNodeOut if ( (iFaninIndex = Vec_IntFind( &pNodeOut->vFanins, pNodeIn->Id )) == -1 ) { printf( "Node %s is not among", Abc_ObjName(pNodeIn) ); printf( " the fanins of node %s...\n", Abc_ObjName(pNodeOut) ); return NULL; } // create the new node pNodeNew = Abc_NtkCreateObj( pNodeIn->pNtk, Type ); // add pNodeIn as fanin and pNodeOut as fanout Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanins, pNodeIn->Id ); Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanouts, pNodeOut->Id ); // update the fanout of pNodeIn Vec_IntWriteEntry( &pNodeIn->vFanouts, iFanoutIndex, pNodeNew->Id ); // update the fanin of pNodeOut Vec_IntWriteEntry( &pNodeOut->vFanins, iFaninIndex, pNodeNew->Id ); return pNodeNew; } /**Function************************************************************* Synopsis [Transfers fanout from the old node to the new node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ObjTransferFanout( Abc_Obj_t * pNodeFrom, Abc_Obj_t * pNodeTo ) { Vec_Ptr_t * vFanouts; int nFanoutsOld, i; assert( !Abc_ObjIsComplement(pNodeFrom) ); assert( !Abc_ObjIsComplement(pNodeTo) ); assert( !Abc_ObjIsPo(pNodeFrom) && !Abc_ObjIsPo(pNodeTo) ); assert( pNodeFrom->pNtk == pNodeTo->pNtk ); assert( pNodeFrom != pNodeTo ); assert( !Abc_ObjIsNode(pNodeFrom) || Abc_ObjFanoutNum(pNodeFrom) > 0 ); // get the fanouts of the old node nFanoutsOld = Abc_ObjFanoutNum(pNodeTo); vFanouts = Vec_PtrAlloc( nFanoutsOld ); Abc_NodeCollectFanouts( pNodeFrom, vFanouts ); // patch the fanin of each of them for ( i = 0; i < vFanouts->nSize; i++ ) Abc_ObjPatchFanin( (Abc_Obj_t *)vFanouts->pArray[i], pNodeFrom, pNodeTo ); assert( Abc_ObjFanoutNum(pNodeFrom) == 0 ); assert( Abc_ObjFanoutNum(pNodeTo) == nFanoutsOld + vFanouts->nSize ); Vec_PtrFree( vFanouts ); } /**Function************************************************************* Synopsis [Replaces the node by a new node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ObjReplace( Abc_Obj_t * pNodeOld, Abc_Obj_t * pNodeNew ) { assert( !Abc_ObjIsComplement(pNodeOld) ); assert( !Abc_ObjIsComplement(pNodeNew) ); assert( pNodeOld->pNtk == pNodeNew->pNtk ); assert( pNodeOld != pNodeNew ); assert( Abc_ObjFanoutNum(pNodeOld) > 0 ); // transfer the fanouts to the old node Abc_ObjTransferFanout( pNodeOld, pNodeNew ); // remove the old node 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin ) { Abc_Obj_t * pObj; int i; Abc_ObjForEachFanin( pFanout, pObj, i ) if ( pObj == pFanin ) return i; return -1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcFunc.c000066400000000000000000001266121477524141600161430ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcFunc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Transformations between different functionality representations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcFunc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" #include "base/main/main.h" #include "map/mio/mio.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define ABC_MAX_CUBES 1000000 #define ABC_MAX_CUBES2 10000 static Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop ); #ifdef ABC_USE_CUDD int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ); static DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot); extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ); extern void Abc_NtkSortCubes( Abc_Ntk_t * pNtk, int fWeight ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Converts the node from SOP to BDD representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ConvertSopToBdd2Count( char * pSop, int nCubes, int nStep, int iVar, int pRes[3] ) { int i; for ( i = 0; i < nCubes; i++ ) if ( pSop[i*nStep+iVar] == '-' ) pRes[0]++, assert( pRes[1] == 0 && pRes[2] == 0 ); else if ( pSop[i*nStep+iVar] == '0' ) pRes[1]++, assert( pRes[2] == 0 ); else if ( pSop[i*nStep+iVar] == '1' ) pRes[2]++; else assert( 0 ); } DdNode * Abc_ConvertSopToBdd2_rec( DdManager * dd, char * pSop, DdNode ** pbVars, int nCubes, int nStep, int iVar ) { DdNode * bRes[5] = {NULL}; int pRes[3] = {0}, i, Start = 0; if ( nCubes == 0 ) return Cudd_ReadLogicZero(dd); if ( iVar == nStep - 3 ) return Cudd_ReadOne(dd); Abc_ConvertSopToBdd2Count( pSop, nCubes, nStep, iVar, pRes ); for ( i = 0; i < 3; Start += pRes[i++] ) bRes[i] = Abc_ConvertSopToBdd2_rec( dd, pSop + Start*nStep, pbVars, pRes[i], nStep, iVar+1 ), Cudd_Ref( bRes[i] ); bRes[3] = Cudd_bddIte( dd, pbVars[iVar], bRes[2], bRes[1] ); Cudd_Ref( bRes[3] ); Cudd_RecursiveDeref( dd, bRes[1] ); Cudd_RecursiveDeref( dd, bRes[2] ); bRes[4] = Cudd_bddOr( dd, bRes[0], bRes[3] ); Cudd_Ref( bRes[4] ); Cudd_RecursiveDeref( dd, bRes[3] ); Cudd_RecursiveDeref( dd, bRes[0] ); Cudd_Deref( bRes[4] ); return bRes[4]; } DdNode * Abc_ConvertSopToBdd2( DdManager * dd, char * pSop, DdNode ** pbVars ) { int nCubes = Abc_SopGetCubeNum(pSop); int nStep = Abc_SopGetVarNum(pSop) + 3; assert( pSop[nCubes*nStep] == '\0' ); return Abc_ConvertSopToBdd2_rec( dd, pSop, pbVars, nCubes, nStep, 0 ); } /**Function************************************************************* Synopsis [Converts the node from SOP to BDD representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop, DdNode ** pbVars ) { DdNode * bSum, * bCube, * bTemp, * bVar; char * pCube; int nVars, Value, v; // start the cover nVars = Abc_SopGetVarNum(pSop); bSum = Cudd_ReadLogicZero(dd); Cudd_Ref( bSum ); if ( Abc_SopIsExorType(pSop) ) { for ( v = 0; v < nVars; v++ ) { bSum = Cudd_bddXor( dd, bTemp = bSum, pbVars? pbVars[v] : Cudd_bddIthVar(dd, v) ); Cudd_Ref( bSum ); Cudd_RecursiveDeref( dd, bTemp ); } } else if ( Abc_SopGetCubeNum(pSop) > ABC_MAX_CUBES2 ) { Cudd_Deref( bSum ); if ( pbVars ) bSum = Abc_ConvertSopToBdd2( dd, pSop, pbVars ); else { DdNode ** pbVars = ABC_ALLOC( DdNode *, nVars ); for ( v = 0; v < nVars; v++ ) pbVars[v] = Cudd_bddIthVar( dd, v ); bSum = Abc_ConvertSopToBdd2( dd, pSop, pbVars ); ABC_FREE( pbVars ); } Cudd_Ref( bSum ); } else { // check the logic function of the node Abc_SopForEachCube( pSop, nVars, pCube ) { bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); Abc_CubeForEachVar( pCube, Value, v ) { if ( Value == '0' ) bVar = Cudd_Not( pbVars? pbVars[v] : Cudd_bddIthVar( dd, v ) ); else if ( Value == '1' ) bVar = pbVars? pbVars[v] : Cudd_bddIthVar( dd, v ); else continue; bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); Cudd_RecursiveDeref( dd, bTemp ); } bSum = Cudd_bddOr( dd, bTemp = bSum, bCube ); Cudd_Ref( bSum ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bCube ); } } // complement the result if necessary bSum = Cudd_NotCond( bSum, !Abc_SopGetPhase(pSop) ); Cudd_Deref( bSum ); return bSum; } /**Function************************************************************* Synopsis [Converts the network from SOP to BDD representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; DdManager * dd, * ddTemp = NULL; Vec_Int_t * vFanins = NULL; int nFaninsMax, i, k, iVar, nCubesMax = 0; assert( Abc_NtkHasSop(pNtk) ); // check SOP sizes Abc_NtkForEachNode( pNtk, pNode, i ) nCubesMax = Abc_MaxInt( nCubesMax, Abc_SopGetCubeNum((char *)pNode->pData) ); if ( nCubesMax > ABC_MAX_CUBES2 ) Abc_NtkSortCubes( pNtk, 0 ); // start the functionality manager nFaninsMax = Abc_NtkGetFaninMax( pNtk ); if ( nFaninsMax == 0 ) printf( "Warning: The network has only constant nodes.\n" ); dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); // start temporary manager for reordered local functions if ( nFaninsMax > 10 ) { ddTemp = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_AutodynEnable( ddTemp, CUDD_REORDER_SYMM_SIFT ); vFanins = Vec_IntAlloc( nFaninsMax ); } // convert each node from SOP to BDD Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_ObjIsBarBuf(pNode) ) continue; assert( pNode->pData ); if ( Abc_ObjFaninNum(pNode) > 10 ) { DdNode * pFunc = Abc_ConvertSopToBdd( ddTemp, (char *)pNode->pData, NULL ); if ( pFunc == NULL ) { printf( "Abc_NtkSopToBdd: Error while converting SOP into BDD.\n" ); return 0; } Cudd_Ref( pFunc ); // find variable mapping Vec_IntFill( vFanins, Abc_ObjFaninNum(pNode), -1 ); for ( k = iVar = 0; k < nFaninsMax; k++ ) if ( ddTemp->invperm[k] < Abc_ObjFaninNum(pNode) ) Vec_IntWriteEntry( vFanins, ddTemp->invperm[k], iVar++ ); assert( iVar == Abc_ObjFaninNum(pNode) ); // transfer to the main manager pNode->pData = Extra_TransferPermute( ddTemp, dd, pFunc, Vec_IntArray(vFanins) ); Cudd_Ref( (DdNode *)pNode->pData ); Cudd_RecursiveDeref( ddTemp, pFunc ); // update variable order Vec_IntClear( vFanins ); for ( k = 0; k < nFaninsMax; k++ ) if ( ddTemp->invperm[k] < Abc_ObjFaninNum(pNode) ) Vec_IntPush( vFanins, Vec_IntEntry(&pNode->vFanins, ddTemp->invperm[k]) ); for ( k = 0; k < Abc_ObjFaninNum(pNode); k++ ) Vec_IntWriteEntry( &pNode->vFanins, k, Vec_IntEntry(vFanins, k) ); } else { pNode->pData = Abc_ConvertSopToBdd( dd, (char *)pNode->pData, NULL ); if ( pNode->pData == NULL ) { printf( "Abc_NtkSopToBdd: Error while converting SOP into BDD.\n" ); return 0; } Cudd_Ref( (DdNode *)pNode->pData ); } } if ( ddTemp ) { // printf( "Reorderings performed = %d.\n", Cudd_ReadReorderings(ddTemp) ); Extra_StopManager( ddTemp ); } Vec_IntFreeP( &vFanins ); Mem_FlexStop( (Mem_Flex_t *)pNtk->pManFunc, 0 ); pNtk->pManFunc = dd; // update the network type pNtk->ntkFunc = ABC_FUNC_BDD; return 1; } /**Function************************************************************* Synopsis [Converts the node from BDD to SOP representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_ConvertBddToSop( Mem_Flex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode ) { int fVerify = 0; char * pSop; DdNode * bFuncNew, * bCover, * zCover, * zCover0, * zCover1; int nCubes = 0, nCubes0, nCubes1, fPhase = 0; assert( bFuncOn == bFuncOnDc || Cudd_bddLeq( dd, bFuncOn, bFuncOnDc ) ); if ( Cudd_IsConstant(bFuncOn) || Cudd_IsConstant(bFuncOnDc) ) { if ( pMan ) pSop = Mem_FlexEntryFetch( pMan, nFanins + 4 ); else pSop = ABC_ALLOC( char, nFanins + 4 ); pSop[0] = ' '; pSop[1] = '0' + (int)(bFuncOn == Cudd_ReadOne(dd)); pSop[2] = '\n'; pSop[3] = '\0'; return pSop; } if ( fMode == -1 ) { // try both phases assert( fAllPrimes == 0 ); // get the ZDD of the negative polarity bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover0 ); Cudd_Ref( zCover0 ); Cudd_Ref( bCover ); Cudd_RecursiveDeref( dd, bCover ); nCubes0 = Abc_CountZddCubes( dd, zCover0 ); // get the ZDD of the positive polarity bCover = Cudd_zddIsop( dd, bFuncOn, bFuncOnDc, &zCover1 ); Cudd_Ref( zCover1 ); Cudd_Ref( bCover ); Cudd_RecursiveDeref( dd, bCover ); nCubes1 = Abc_CountZddCubes( dd, zCover1 ); // compare the number of cubes if ( nCubes1 <= nCubes0 ) { // use positive polarity nCubes = nCubes1; zCover = zCover1; Cudd_RecursiveDerefZdd( dd, zCover0 ); fPhase = 1; } else { // use negative polarity nCubes = nCubes0; zCover = zCover0; Cudd_RecursiveDerefZdd( dd, zCover1 ); fPhase = 0; } } else if ( fMode == 0 ) { // get the ZDD of the negative polarity if ( fAllPrimes ) { zCover = Extra_zddPrimes( dd, Cudd_Not(bFuncOnDc) ); Cudd_Ref( zCover ); } else { bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover ); Cudd_Ref( zCover ); Cudd_Ref( bCover ); Cudd_RecursiveDeref( dd, bCover ); } nCubes = Abc_CountZddCubes( dd, zCover ); fPhase = 0; } else if ( fMode == 1 ) { // get the ZDD of the positive polarity if ( fAllPrimes ) { zCover = Extra_zddPrimes( dd, bFuncOnDc ); Cudd_Ref( zCover ); } else { bCover = Cudd_zddIsop( dd, bFuncOn, bFuncOnDc, &zCover ); Cudd_Ref( zCover ); Cudd_Ref( bCover ); Cudd_RecursiveDeref( dd, bCover ); } nCubes = Abc_CountZddCubes( dd, zCover ); fPhase = 1; } else { assert( 0 ); } if ( nCubes > ABC_MAX_CUBES ) { Cudd_RecursiveDerefZdd( dd, zCover ); printf( "The number of cubes exceeded the predefined limit (%d).\n", ABC_MAX_CUBES ); return NULL; } // allocate memory for the cover if ( pMan ) pSop = Mem_FlexEntryFetch( pMan, (nFanins + 3) * nCubes + 1 ); else pSop = ABC_ALLOC( char, (nFanins + 3) * nCubes + 1 ); pSop[(nFanins + 3) * nCubes] = 0; // create the SOP Vec_StrFill( vCube, nFanins, '-' ); Vec_StrPush( vCube, '\0' ); Abc_ConvertZddToSop( dd, zCover, pSop, nFanins, vCube, fPhase ); Cudd_RecursiveDerefZdd( dd, zCover ); // verify if ( fVerify ) { bFuncNew = Abc_ConvertSopToBdd( dd, pSop, NULL ); Cudd_Ref( bFuncNew ); if ( bFuncOn == bFuncOnDc ) { if ( bFuncNew != bFuncOn ) printf( "Verification failed.\n" ); } else { if ( !Cudd_bddLeq(dd, bFuncOn, bFuncNew) || !Cudd_bddLeq(dd, bFuncNew, bFuncOnDc) ) printf( "Verification failed.\n" ); } Cudd_RecursiveDeref( dd, bFuncNew ); } return pSop; } /**Function************************************************************* Synopsis [Converts the network from BDD to SOP representation.] Description [If the flag is set to 1, forces the direct phase of all covers.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit, int fCubeSort ) { Vec_Int_t * vGuide; Vec_Str_t * vCube; Abc_Obj_t * pNode; Mem_Flex_t * pManNew; DdManager * dd = (DdManager *)pNtk->pManFunc; DdNode * bFunc; int i, nCubes; // compute SOP size vGuide = Vec_IntAlloc( Abc_NtkObjNumMax(pNtk) ); Vec_IntFill( vGuide, Abc_NtkObjNumMax(pNtk), fMode ); if ( nCubeLimit < ABC_INFINITY ) { // collect all BDDs into one array Vec_Ptr_t * vFuncs = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); assert( !Cudd_ReorderingStatus(dd, (Cudd_ReorderingType *)&nCubes) ); Abc_NtkForEachNode( pNtk, pNode, i ) if ( !Abc_ObjIsBarBuf(pNode) ) Vec_PtrWriteEntry( vFuncs, i, pNode->pData ); // compute the number of cubes in the ISOPs and detemine polarity nCubes = Extra_bddCountCubes( dd, (DdNode **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs), fMode, nCubeLimit, Vec_IntArray(vGuide) ); Vec_PtrFree( vFuncs ); if ( nCubes == -1 ) { Vec_IntFree( vGuide ); return 0; } //printf( "The total number of cubes = %d.\n", nCubes ); } assert( Abc_NtkHasBdd(pNtk) ); if ( dd->size > 0 ) Cudd_zddVarsFromBddVars( dd, 2 ); // create the new manager pManNew = Mem_FlexStart(); // go through the objects vCube = Vec_StrAlloc( 100 ); Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_ObjIsBarBuf(pNode) ) continue; assert( pNode->pData ); bFunc = (DdNode *)pNode->pData; pNode->pNext = (Abc_Obj_t *)Abc_ConvertBddToSop( pManNew, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), 0, vCube, Vec_IntEntry(vGuide, i) ); if ( pNode->pNext == NULL ) { Mem_FlexStop( pManNew, 0 ); Abc_NtkCleanNext( pNtk ); // printf( "Converting from BDDs to SOPs has failed.\n" ); Vec_IntFree( vGuide ); Vec_StrFree( vCube ); return 0; } // it may happen that a constant node was created after structural mapping if ( Abc_SopGetVarNum((char *)pNode->pNext) == 0 ) pNode->vFanins.nSize = 0; // check the support if ( Abc_ObjFaninNum(pNode) != Abc_SopGetVarNum((char *)pNode->pNext) ) { printf( "Node %d with level %d has %d fanins but its SOP has support size %d.\n", pNode->Id, pNode->Level, Abc_ObjFaninNum(pNode), Abc_SopGetVarNum((char *)pNode->pNext) ); fflush( stdout ); } assert( Abc_ObjFaninNum(pNode) == Abc_SopGetVarNum((char *)pNode->pNext) ); } Vec_IntFree( vGuide ); Vec_StrFree( vCube ); // update the network type pNtk->ntkFunc = ABC_FUNC_SOP; // set the new manager pNtk->pManFunc = pManNew; // transfer from next to data Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_ObjIsBarBuf(pNode) ) continue; Cudd_RecursiveDeref( dd, (DdNode *)pNode->pData ); pNode->pData = pNode->pNext; pNode->pNext = NULL; } // check for remaining references in the package Extra_StopManager( dd ); // reorder fanins and cubes to make SOPs more human-readable if ( fCubeSort ) Abc_NtkSortSops( pNtk ); return 1; } /**Function************************************************************* Synopsis [Derive the SOP from the ZDD representation of the cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ConvertZddToSop_rec( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase, int * pnCubes ) { DdNode * zC0, * zC1, * zC2; int Index; if ( zCover == dd->zero ) return; if ( zCover == dd->one ) { char * pCube; pCube = pSop + (*pnCubes) * (nFanins + 3); sprintf( pCube, "%s %d\n", vCube->pArray, fPhase ); (*pnCubes)++; return; } Index = zCover->index/2; assert( Index < nFanins ); extraDecomposeCover( dd, zCover, &zC0, &zC1, &zC2 ); vCube->pArray[Index] = '0'; Abc_ConvertZddToSop_rec( dd, zC0, pSop, nFanins, vCube, fPhase, pnCubes ); vCube->pArray[Index] = '1'; Abc_ConvertZddToSop_rec( dd, zC1, pSop, nFanins, vCube, fPhase, pnCubes ); vCube->pArray[Index] = '-'; Abc_ConvertZddToSop_rec( dd, zC2, pSop, nFanins, vCube, fPhase, pnCubes ); } /**Function************************************************************* Synopsis [Derive the BDD for the function in the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ) { int nCubes = 0; Abc_ConvertZddToSop_rec( dd, zCover, pSop, nFanins, vCube, fPhase, &nCubes ); return nCubes; } /**Function************************************************************* Synopsis [Computes the SOPs of the negative and positive phase of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Mem_Flex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 ) { assert( Abc_NtkHasBdd(pNode->pNtk) ); *ppSop0 = Abc_ConvertBddToSop( pMmMan, (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData, (DdNode *)pNode->pData, Abc_ObjFaninNum(pNode), fAllPrimes, vCube, 0 ); *ppSop1 = Abc_ConvertBddToSop( pMmMan, (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData, (DdNode *)pNode->pData, Abc_ObjFaninNum(pNode), fAllPrimes, vCube, 1 ); } /**Function************************************************************* Synopsis [Removes complemented SOP covers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ) { DdManager * dd; DdNode * bFunc; Vec_Str_t * vCube; Abc_Obj_t * pNode; int nFaninsMax, fFound, i; assert( Abc_NtkHasSop(pNtk) ); // check if there are nodes with complemented SOPs fFound = 0; Abc_NtkForEachNode( pNtk, pNode, i ) if ( !Abc_ObjIsBarBuf(pNode) && Abc_SopIsComplement((char *)pNode->pData) ) { fFound = 1; break; } if ( !fFound ) return; // start the BDD package nFaninsMax = Abc_NtkGetFaninMax( pNtk ); if ( nFaninsMax == 0 ) printf( "Warning: The network has only constant nodes.\n" ); dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); // change the cover of negated nodes vCube = Vec_StrAlloc( 100 ); Abc_NtkForEachNode( pNtk, pNode, i ) if ( !Abc_ObjIsBarBuf(pNode) && Abc_SopIsComplement((char *)pNode->pData) ) { bFunc = Abc_ConvertSopToBdd( dd, (char *)pNode->pData, NULL ); Cudd_Ref( bFunc ); pNode->pData = Abc_ConvertBddToSop( (Mem_Flex_t *)pNtk->pManFunc, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), 0, vCube, 1 ); Cudd_RecursiveDeref( dd, bFunc ); assert( !Abc_SopIsComplement((char *)pNode->pData) ); } Vec_StrFree( vCube ); Extra_StopManager( dd ); } /**Function************************************************************* Synopsis [Count the number of paths in the ZDD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_CountZddCubes_rec( DdManager * dd, DdNode * zCover, int * pnCubes ) { DdNode * zC0, * zC1, * zC2; if ( zCover == dd->zero ) return; if ( zCover == dd->one ) { (*pnCubes)++; return; } if ( (*pnCubes) > ABC_MAX_CUBES ) return; extraDecomposeCover( dd, zCover, &zC0, &zC1, &zC2 ); Abc_CountZddCubes_rec( dd, zC0, pnCubes ); Abc_CountZddCubes_rec( dd, zC1, pnCubes ); Abc_CountZddCubes_rec( dd, zC2, pnCubes ); } /**Function************************************************************* Synopsis [Count the number of paths in the ZDD.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ) { int nCubes = 0; Abc_CountZddCubes_rec( dd, zCover, &nCubes ); return nCubes; } /**Function************************************************************* Synopsis [Converts the network from AIG to BDD representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; Hop_Man_t * pMan; DdNode * pFunc; DdManager * dd, * ddTemp = NULL; Vec_Int_t * vFanins = NULL; int nFaninsMax, i, k, iVar; assert( Abc_NtkHasAig(pNtk) ); // start the functionality manager nFaninsMax = Abc_NtkGetFaninMax( pNtk ); if ( nFaninsMax == 0 ) printf( "Warning: The network has only constant nodes.\n" ); dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); // start temporary manager for reordered local functions ddTemp = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); Cudd_AutodynEnable( ddTemp, CUDD_REORDER_SYMM_SIFT ); vFanins = Vec_IntAlloc( nFaninsMax ); // set the mapping of elementary AIG nodes into the elementary BDD nodes pMan = (Hop_Man_t *)pNtk->pManFunc; assert( Hop_ManPiNum(pMan) >= nFaninsMax ); for ( i = 0; i < nFaninsMax; i++ ) Hop_ManPi(pMan, i)->pData = Cudd_bddIthVar(ddTemp, i); // convert each node from SOP to BDD Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_ObjIsBarBuf(pNode) ) continue; pFunc = Abc_ConvertAigToBdd( ddTemp, (Hop_Obj_t *)pNode->pData ); if ( pFunc == NULL ) { printf( "Abc_NtkAigToBdd: Error while converting AIG into BDD.\n" ); return 0; } Cudd_Ref( pFunc ); // find variable mapping Vec_IntFill( vFanins, Abc_ObjFaninNum(pNode), -1 ); for ( k = iVar = 0; k < nFaninsMax; k++ ) if ( ddTemp->invperm[k] < Abc_ObjFaninNum(pNode) ) Vec_IntWriteEntry( vFanins, ddTemp->invperm[k], iVar++ ); assert( iVar == Abc_ObjFaninNum(pNode) ); // transfer to the main manager pNode->pData = Extra_TransferPermute( ddTemp, dd, pFunc, Vec_IntArray(vFanins) ); Cudd_Ref( (DdNode *)pNode->pData ); Cudd_RecursiveDeref( ddTemp, pFunc ); // update variable order Vec_IntClear( vFanins ); for ( k = 0; k < nFaninsMax; k++ ) if ( ddTemp->invperm[k] < Abc_ObjFaninNum(pNode) ) Vec_IntPush( vFanins, Vec_IntEntry(&pNode->vFanins, ddTemp->invperm[k]) ); for ( k = 0; k < Abc_ObjFaninNum(pNode); k++ ) Vec_IntWriteEntry( &pNode->vFanins, k, Vec_IntEntry(vFanins, k) ); } // printf( "Reorderings performed = %d.\n", Cudd_ReadReorderings(ddTemp) ); Extra_StopManager( ddTemp ); Vec_IntFreeP( &vFanins ); Hop_ManStop( (Hop_Man_t *)pNtk->pManFunc ); pNtk->pManFunc = dd; // update the network type pNtk->ntkFunc = ABC_FUNC_BDD; return 1; } /**Function************************************************************* Synopsis [Construct BDDs and mark AIG nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ConvertAigToBdd_rec1( DdManager * dd, Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin0(pObj) ); Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin1(pObj) ); pObj->pData = Cudd_bddAnd( dd, (DdNode *)Hop_ObjChild0Copy(pObj), (DdNode *)Hop_ObjChild1Copy(pObj) ); Cudd_Ref( (DdNode *)pObj->pData ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); } /**Function************************************************************* Synopsis [Dereference BDDs and unmark AIG nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ConvertAigToBdd_rec2( DdManager * dd, Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) return; Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin0(pObj) ); Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin1(pObj) ); Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); pObj->pData = NULL; assert( Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjClearMarkA( pObj ); } /**Function************************************************************* Synopsis [Converts the network from AIG to BDD representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot ) { DdNode * bFunc; // check the case of a constant if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) return Cudd_NotCond( Cudd_ReadOne(dd), Hop_IsComplement(pRoot) ); // construct BDD Abc_ConvertAigToBdd_rec1( dd, Hop_Regular(pRoot) ); // hold on to the result bFunc = Cudd_NotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); Cudd_Ref( bFunc ); // dereference BDD Abc_ConvertAigToBdd_rec2( dd, Hop_Regular(pRoot) ); // return the result Cudd_Deref( bFunc ); return bFunc; } #else int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ) { 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; } #endif /**Function************************************************************* Synopsis [Converts the network from SOP to AIG representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; Hop_Man_t * pMan; int i, Max; assert( Abc_NtkHasSop(pNtk) ); // make dist1-free and SCC-free // Abc_NtkMakeLegit( pNtk ); // start the functionality manager pMan = Hop_ManStart(); Max = Abc_NtkGetFaninMax(pNtk); if ( Max ) Hop_IthVar( pMan, Max-1 ); // convert each node from SOP to BDD Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_ObjIsBarBuf(pNode) ) continue; assert( pNode->pData ); pNode->pData = Abc_ConvertSopToAig( pMan, (char *)pNode->pData ); if ( pNode->pData == NULL ) { Hop_ManStop( pMan ); printf( "Abc_NtkSopToAig: Error while converting SOP into AIG.\n" ); return 0; } } Mem_FlexStop( (Mem_Flex_t *)pNtk->pManFunc, 0 ); pNtk->pManFunc = pMan; // update the network type pNtk->ntkFunc = ABC_FUNC_AIG; return 1; } /**Function************************************************************* Synopsis [Strashes one logic node using its SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Abc_ConvertSopToAigInternal( Hop_Man_t * pMan, char * pSop ) { Hop_Obj_t * pAnd, * pSum; int i, Value, nFanins; char * pCube; // get the number of variables nFanins = Abc_SopGetVarNum(pSop); if ( Abc_SopIsExorType(pSop) ) { pSum = Hop_ManConst0(pMan); for ( i = 0; i < nFanins; i++ ) pSum = Hop_Exor( pMan, pSum, Hop_IthVar(pMan,i) ); } else { // go through the cubes of the node's SOP pSum = Hop_ManConst0(pMan); Abc_SopForEachCube( pSop, nFanins, pCube ) { // create the AND of literals pAnd = Hop_ManConst1(pMan); Abc_CubeForEachVar( pCube, Value, i ) { if ( Value == '1' ) pAnd = Hop_And( pMan, pAnd, Hop_IthVar(pMan,i) ); else if ( Value == '0' ) pAnd = Hop_And( pMan, pAnd, Hop_Not(Hop_IthVar(pMan,i)) ); } // add to the sum of cubes pSum = Hop_Or( pMan, pSum, pAnd ); } } // decide whether to complement the result if ( Abc_SopIsComplement(pSop) ) pSum = Hop_Not(pSum); return pSum; } /**Function************************************************************* Synopsis [Converts the network from AIG to BDD representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop ) { extern Hop_Obj_t * Dec_GraphFactorSop( Hop_Man_t * pMan, char * pSop ); int fUseFactor = 1; // consider the constant node if ( Abc_SopGetVarNum(pSop) == 0 ) return Hop_NotCond( Hop_ManConst1(pMan), Abc_SopIsConst0(pSop) ); // decide when to use factoring if ( fUseFactor && Abc_SopGetVarNum(pSop) > 2 && Abc_SopGetCubeNum(pSop) > 1 && !Abc_SopIsExorType(pSop) ) return Dec_GraphFactorSop( pMan, pSop ); return Abc_ConvertSopToAigInternal( pMan, pSop ); } /**Function************************************************************* Synopsis [Converts the network from AIG to GIA representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ConvertAigToGia_rec1( Gia_Man_t * p, Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; Abc_ConvertAigToGia_rec1( p, Hop_ObjFanin0(pObj) ); Abc_ConvertAigToGia_rec1( p, Hop_ObjFanin1(pObj) ); pObj->iData = Gia_ManAppendAnd2( p, Hop_ObjChild0CopyI(pObj), Hop_ObjChild1CopyI(pObj) ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); } void Abc_ConvertAigToGia_rec2( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) return; Abc_ConvertAigToGia_rec2( Hop_ObjFanin0(pObj) ); Abc_ConvertAigToGia_rec2( Hop_ObjFanin1(pObj) ); assert( Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjClearMarkA( pObj ); } int Abc_ConvertAigToGia( Gia_Man_t * p, Hop_Obj_t * pRoot ) { assert( !Hop_IsComplement(pRoot) ); if ( Hop_ObjIsConst1( pRoot ) ) return 1; Abc_ConvertAigToGia_rec1( p, pRoot ); Abc_ConvertAigToGia_rec2( pRoot ); return pRoot->iData; } /**Function************************************************************* Synopsis [Converts the network from AIG to BDD representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Abc_NtkAigToGia( Abc_Ntk_t * p, int fGiaSimple ) { Gia_Man_t * pNew; Hop_Man_t * pHopMan; Hop_Obj_t * pHopObj; Vec_Int_t * vMapping = NULL; Vec_Ptr_t * vNodes; Abc_Obj_t * pNode, * pFanin; int i, k, nObjs, iGiaObj; assert( Abc_NtkIsAigLogic(p) ); pHopMan = (Hop_Man_t *)p->pManFunc; // create new manager pNew = Gia_ManStart( 10000 ); pNew->pName = Abc_UtilStrsav( Abc_NtkName(p) ); pNew->pSpec = Abc_UtilStrsav( Abc_NtkSpec(p) ); pNew->fGiaSimple = fGiaSimple; Abc_NtkCleanCopy( p ); Hop_ManConst1(pHopMan)->iData = 1; // create primary inputs Abc_NtkForEachCi( p, pNode, i ) pNode->iTemp = Gia_ManAppendCi(pNew); // find the number of objects nObjs = 1 + Abc_NtkCiNum(p) + Abc_NtkCoNum(p); Abc_NtkForEachNode( p, pNode, i ) nObjs += Abc_ObjIsBarBuf(pNode) ? 1 : Hop_DagSize( (Hop_Obj_t *)pNode->pData ); if ( !fGiaSimple ) vMapping = Vec_IntStart( nObjs ); // iterate through nodes used in the mapping vNodes = Abc_NtkDfs( p, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( Abc_ObjIsBarBuf(pNode) ) { assert( !Abc_ObjFaninC0(pNode) ); pNode->iTemp = Gia_ManAppendBuf( pNew, Abc_ObjFanin0(pNode)->iTemp ); continue; } Abc_ObjForEachFanin( pNode, pFanin, k ) Hop_ManPi(pHopMan, k)->iData = pFanin->iTemp; pHopObj = Hop_Regular( (Hop_Obj_t *)pNode->pData ); if ( Hop_DagSize(pHopObj) > 0 ) { assert( Abc_ObjFaninNum(pNode) <= Hop_ManPiNum(pHopMan) ); Abc_ConvertAigToGia( pNew, pHopObj ); iGiaObj = Abc_Lit2Var( pHopObj->iData ); if ( vMapping && Gia_ObjIsAnd(Gia_ManObj(pNew, iGiaObj)) && !Vec_IntEntry(vMapping, iGiaObj) ) { Vec_IntWriteEntry( vMapping, iGiaObj, Vec_IntSize(vMapping) ); Vec_IntPush( vMapping, Abc_ObjFaninNum(pNode) ); Abc_ObjForEachFanin( pNode, pFanin, k ) Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->iTemp) ); Vec_IntPush( vMapping, iGiaObj ); } } pNode->iTemp = Abc_LitNotCond( pHopObj->iData, Hop_IsComplement( (Hop_Obj_t *)pNode->pData ) ); } // create primary outputs Abc_NtkForEachCo( p, pNode, i ) Gia_ManAppendCo( pNew, Abc_ObjFanin0(pNode)->iTemp ); Gia_ManSetRegNum( pNew, Abc_NtkLatchNum(p) ); // copy original IDs pNew->vIdsOrig = Vec_IntStart( Gia_ManObjNum(pNew) ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) Vec_IntWriteEntry( pNew->vIdsOrig, Abc_Lit2Var(pNode->iTemp), Abc_ObjId(pNode) ); Vec_PtrFree( vNodes ); // finish mapping assert( Gia_ManObjNum(pNew) <= nObjs ); assert( pNew->vMapping == NULL ); pNew->vMapping = vMapping; return pNew; } /**Function************************************************************* Synopsis [Construct BDDs and mark AIG nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ConvertAigToAig_rec( Abc_Ntk_t * pNtkAig, Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; Abc_ConvertAigToAig_rec( pNtkAig, Hop_ObjFanin0(pObj) ); Abc_ConvertAigToAig_rec( pNtkAig, Hop_ObjFanin1(pObj) ); pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); } /**Function************************************************************* Synopsis [Converts the network from AIG to BDD representation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_ConvertAigToAig( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObjOld ) { Hop_Man_t * pHopMan; Hop_Obj_t * pRoot; Abc_Obj_t * pFanin; int i; // get the local AIG pHopMan = (Hop_Man_t *)pObjOld->pNtk->pManFunc; pRoot = (Hop_Obj_t *)pObjOld->pData; // check the case of a constant if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) return Abc_ObjNotCond( Abc_AigConst1(pNtkAig), Hop_IsComplement(pRoot) ); // assign the fanin nodes Abc_ObjForEachFanin( pObjOld, pFanin, i ) { assert( pFanin->pCopy != NULL ); Hop_ManPi(pHopMan, i)->pData = pFanin->pCopy; } // construct the AIG Abc_ConvertAigToAig_rec( pNtkAig, Hop_Regular(pRoot) ); Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); // return the result return Abc_ObjNotCond( (Abc_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); } /**Function************************************************************* Synopsis [Unmaps the network with user provided Mio library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMapToSopUsingLibrary( Abc_Ntk_t * pNtk, void* library) { Abc_Obj_t * pNode; char * pSop; int i; assert( Abc_NtkHasMapping(pNtk) ); // update the functionality manager assert( pNtk->pManFunc == (void*) library ); pNtk->pManFunc = Mem_FlexStart(); // update the nodes Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_ObjIsBarBuf(pNode) ) continue; pSop = Mio_GateReadSop((Mio_Gate_t *)pNode->pData); assert( Abc_SopGetVarNum(pSop) == Abc_ObjFaninNum(pNode) ); pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, pSop ); } pNtk->ntkFunc = ABC_FUNC_SOP; return 1; } /**Function************************************************************* Synopsis [Unmaps the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMapToSop( Abc_Ntk_t * pNtk ) { extern void * Abc_FrameReadLibGen(); return Abc_NtkMapToSopUsingLibrary(pNtk, Abc_FrameReadLibGen()); } /**Function************************************************************* Synopsis [Converts SOP functions into BLIF-MV functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkSopToBlifMv( Abc_Ntk_t * pNtk ) { return 1; } /**Function************************************************************* Synopsis [Convers logic network to the SOP form.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit ) { assert( !Abc_NtkIsStrash(pNtk) ); if ( Abc_NtkHasBlackbox(pNtk) ) return 1; if ( Abc_NtkHasSop(pNtk) ) { if ( fMode == -1 ) return 1; if ( !Abc_NtkSopToBdd(pNtk) ) return 0; 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, 1); if ( Abc_NtkHasAig(pNtk) ) { if ( !Abc_NtkAigToBdd(pNtk) ) return 0; return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit, 1); } assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Convers logic network to the SOP form.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkToBdd( Abc_Ntk_t * pNtk ) { assert( !Abc_NtkIsStrash(pNtk) ); if ( Abc_NtkHasBlackbox(pNtk) ) return 1; if ( Abc_NtkHasBdd(pNtk) ) return 1; if ( Abc_NtkHasMapping(pNtk) ) { Abc_NtkMapToSop(pNtk); return Abc_NtkSopToBdd(pNtk); } if ( Abc_NtkHasSop(pNtk) ) { Abc_NtkSopToAig(pNtk); return Abc_NtkAigToBdd(pNtk); } if ( Abc_NtkHasAig(pNtk) ) return Abc_NtkAigToBdd(pNtk); assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Convers logic network to the SOP form.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkToAig( Abc_Ntk_t * pNtk ) { assert( !Abc_NtkIsStrash(pNtk) ); if ( Abc_NtkHasBlackbox(pNtk) ) return 1; if ( Abc_NtkHasAig(pNtk) ) return 1; if ( Abc_NtkHasMapping(pNtk) ) { Abc_NtkMapToSop(pNtk); return Abc_NtkSopToAig(pNtk); } if ( Abc_NtkHasBdd(pNtk) ) { if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 1) ) return 0; return Abc_NtkSopToAig(pNtk); } if ( Abc_NtkHasSop(pNtk) ) return Abc_NtkSopToAig(pNtk); assert( 0 ); return 0; } /**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 /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcHie.c000066400000000000000000000723241477524141600157550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcHie.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures to handle hierarchy.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcHie.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Recursively flattens logic hierarchy of the netlist.] Description [When this procedure is called, the PI/PO nets of the old netlist point to the corresponding nets of the flattened netlist.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFlattenLogicHierarchy2_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, int * pCounter ) { char Suffix[2000] = {0}; Abc_Ntk_t * pNtkModel; Abc_Obj_t * pObj, * pTerm, * pNet, * pFanin; int i, k; // process the blackbox if ( Abc_NtkHasBlackbox(pNtk) ) { // duplicate the blackbox assert( Abc_NtkBoxNum(pNtk) == 1 ); pObj = Abc_NtkBox( pNtk, 0 ); Abc_NtkDupBox( pNtkNew, pObj, 1 ); pObj->pCopy->pData = pNtk; // connect blackbox fanins to the PI nets assert( Abc_ObjFaninNum(pObj->pCopy) == Abc_NtkPiNum(pNtk) ); Abc_NtkForEachPi( pNtk, pTerm, i ) Abc_ObjAddFanin( Abc_ObjFanin(pObj->pCopy,i), Abc_ObjFanout0(pTerm)->pCopy ); // connect blackbox fanouts to the PO nets assert( Abc_ObjFanoutNum(pObj->pCopy) == Abc_NtkPoNum(pNtk) ); Abc_NtkForEachPo( pNtk, pTerm, i ) Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, Abc_ObjFanout(pObj->pCopy,i) ); return; } (*pCounter)++; // create the suffix, which will be appended to the internal names if ( *pCounter ) sprintf( Suffix, "_%s_%d", Abc_NtkName(pNtk), *pCounter ); // duplicate nets of all boxes, including latches Abc_NtkForEachBox( pNtk, pObj, i ) { Abc_ObjForEachFanin( pObj, pTerm, k ) { pNet = Abc_ObjFanin0(pTerm); if ( pNet->pCopy ) continue; pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) ); } Abc_ObjForEachFanout( pObj, pTerm, k ) { pNet = Abc_ObjFanout0(pTerm); if ( pNet->pCopy ) continue; pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) ); } } // mark objects that will not be used Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachPi( pNtk, pTerm, i ) Abc_NodeSetTravIdCurrent( pTerm ); Abc_NtkForEachPo( pNtk, pTerm, i ) { Abc_NodeSetTravIdCurrent( pTerm ); // if the netlist has net names beginning with "abc_property_" // these names will be addes as primary outputs of the network pNet = Abc_ObjFanin0(pTerm); if ( strncmp( Abc_ObjName(pNet), "abc_property", 12 ) ) continue; Abc_ObjAddFanin( Abc_NtkCreatePo(pNet->pCopy->pNtk), pNet->pCopy ); if ( Nm_ManFindNameById(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id) ) Nm_ManDeleteIdName(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id); Abc_ObjAssignName( pNet->pCopy, Abc_ObjName(pNet), Suffix ); } Abc_NtkForEachBox( pNtk, pObj, i ) { if ( Abc_ObjIsLatch(pObj) ) continue; Abc_NodeSetTravIdCurrent( pObj ); Abc_ObjForEachFanin( pObj, pTerm, k ) Abc_NodeSetTravIdCurrent( pTerm ); Abc_ObjForEachFanout( pObj, pTerm, k ) Abc_NodeSetTravIdCurrent( pTerm ); } // duplicate objects that do not have prototypes yet Abc_NtkForEachObj( pNtk, pObj, i ) { if ( Abc_NodeIsTravIdCurrent(pObj) ) continue; if ( pObj->pCopy ) continue; Abc_NtkDupObj( pNtkNew, pObj, 0 ); } // connect objects Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_NodeIsTravIdCurrent(pObj) ) Abc_ObjForEachFanin( pObj, pFanin, k ) if ( !Abc_NodeIsTravIdCurrent(pFanin) ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); // call recursively Abc_NtkForEachBox( pNtk, pObj, i ) { if ( Abc_ObjIsLatch(pObj) ) continue; pNtkModel = (Abc_Ntk_t *)pObj->pData; // check the match between the number of actual and formal parameters assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) ); assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) ); // clean the node copy fields Abc_NtkCleanCopy( pNtkModel ); // map PIs/POs Abc_ObjForEachFanin( pObj, pTerm, k ) Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->pCopy = Abc_ObjFanin0(pTerm)->pCopy; Abc_ObjForEachFanout( pObj, pTerm, k ) Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->pCopy = Abc_ObjFanout0(pTerm)->pCopy; // call recursively Abc_NtkFlattenLogicHierarchy2_rec( pNtkNew, pNtkModel, pCounter ); } // if it is a BLIF-MV netlist transfer the values of all nets if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) ) { if ( Abc_NtkMvVar( pNtkNew ) == NULL ) Abc_NtkStartMvVars( pNtkNew ); Abc_NtkForEachNet( pNtk, pObj, i ) Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) ); } } /**Function************************************************************* Synopsis [Flattens the logic hierarchy of the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy2( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pTerm, * pNet; int i, Counter; extern Abc_Des_t * Abc_DesDupBlackboxes( Abc_Des_t * p, Abc_Ntk_t * pNtkSave ); assert( Abc_NtkIsNetlist(pNtk) ); // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); // duplicate the name and the spec pNtkNew->pName = Abc_UtilStrsav(pNtk->pName); pNtkNew->pSpec = Abc_UtilStrsav(pNtk->pSpec); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); // duplicate PIs/POs and their nets Abc_NtkForEachPi( pNtk, pTerm, i ) { Abc_NtkDupObj( pNtkNew, pTerm, 0 ); pNet = Abc_ObjFanout0( pTerm ); pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) ); Abc_ObjAddFanin( pNet->pCopy, pTerm->pCopy ); } Abc_NtkForEachPo( pNtk, pTerm, i ) { Abc_NtkDupObj( pNtkNew, pTerm, 0 ); pNet = Abc_ObjFanin0( pTerm ); pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) ); Abc_ObjAddFanin( pTerm->pCopy, pNet->pCopy ); } // recursively flatten hierarchy, create internal logic, add new PI/PO names if there are black boxes Counter = -1; Abc_NtkFlattenLogicHierarchy2_rec( pNtkNew, pNtk, &Counter ); printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n", Counter, Abc_NtkBlackboxNum(pNtkNew) ); if ( pNtk->pDesign ) { // pass on the design assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk ); pNtkNew->pDesign = Abc_DesDupBlackboxes( pNtk->pDesign, pNtkNew ); // update the pointers Abc_NtkForEachBlackbox( pNtkNew, pTerm, i ) pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy; } // we may have added property outputs Abc_NtkOrderCisCos( pNtkNew ); // copy the timing information // Abc_ManTimeDup( pNtk, pNtkNew ); // duplicate EXDC if ( pNtk->pExdc ) printf( "EXDC is not transformed.\n" ); if ( !Abc_NtkCheck( pNtkNew ) ) { fprintf( stdout, "Abc_NtkFlattenLogicHierarchy2(): Network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Recursively flattens logic hierarchy of the netlist.] Description [When this procedure is called, the PI/PO nets of the old netlist point to the corresponding nets of the flattened netlist.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFlattenLogicHierarchy_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, int * pCounter, Vec_Str_t * vPref ) { Abc_Ntk_t * pNtkModel; Abc_Obj_t * pObj, * pTerm, * pNet, * pFanin; int i, k, Length; // process the blackbox if ( Abc_NtkHasBlackbox(pNtk) ) { //printf( "Flatting black box \"%s\".\n", pNtk->pName ); // duplicate the blackbox assert( Abc_NtkBoxNum(pNtk) == 1 ); pObj = Abc_NtkBox( pNtk, 0 ); Abc_NtkDupBox( pNtkNew, pObj, 1 ); pObj->pCopy->pData = pNtk; // connect blackbox fanins to the PI nets assert( Abc_ObjFaninNum(pObj->pCopy) == Abc_NtkPiNum(pNtk) ); Abc_NtkForEachPi( pNtk, pTerm, i ) Abc_ObjAddFanin( Abc_ObjFanin(pObj->pCopy,i), Abc_ObjFanout0(pTerm)->pCopy ); // connect blackbox fanouts to the PO nets assert( Abc_ObjFanoutNum(pObj->pCopy) == Abc_NtkPoNum(pNtk) ); Abc_NtkForEachPo( pNtk, pTerm, i ) Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, Abc_ObjFanout(pObj->pCopy,i) ); return; } (*pCounter)++; // create the suffix, which will be appended to the internal names if ( *pCounter ) { char Buffer[20]; sprintf( Buffer, "(%d)", *pCounter ); Vec_StrPrintStr( vPref, Buffer ); } Vec_StrPush( vPref, '|' ); Vec_StrPush( vPref, 0 ); // duplicate nets of all boxes, including latches Abc_NtkForEachBox( pNtk, pObj, i ) { Abc_ObjForEachFanin( pObj, pTerm, k ) { pNet = Abc_ObjFanin0(pTerm); if ( pNet->pCopy ) continue; pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNamePrefix(pNet, Vec_StrArray(vPref)) ); } Abc_ObjForEachFanout( pObj, pTerm, k ) { pNet = Abc_ObjFanout0(pTerm); if ( pNet->pCopy ) continue; pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNamePrefix(pNet, Vec_StrArray(vPref)) ); } } // mark objects that will not be used Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachPi( pNtk, pTerm, i ) Abc_NodeSetTravIdCurrent( pTerm ); Abc_NtkForEachPo( pNtk, pTerm, i ) { Abc_NodeSetTravIdCurrent( pTerm ); // if the netlist has net names beginning with "abc_property_" // these names will be addes as primary outputs of the network pNet = Abc_ObjFanin0(pTerm); if ( strncmp( Abc_ObjName(pNet), "abc_property", 12 ) ) continue; Abc_ObjAddFanin( Abc_NtkCreatePo(pNet->pCopy->pNtk), pNet->pCopy ); if ( Nm_ManFindNameById(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id) ) Nm_ManDeleteIdName(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id); Abc_ObjAssignName( pNet->pCopy, Vec_StrArray(vPref), Abc_ObjName(pNet) ); } Abc_NtkForEachBox( pNtk, pObj, i ) { if ( Abc_ObjIsLatch(pObj) ) continue; Abc_NodeSetTravIdCurrent( pObj ); Abc_ObjForEachFanin( pObj, pTerm, k ) Abc_NodeSetTravIdCurrent( pTerm ); Abc_ObjForEachFanout( pObj, pTerm, k ) Abc_NodeSetTravIdCurrent( pTerm ); } // duplicate objects that do not have prototypes yet Abc_NtkForEachObj( pNtk, pObj, i ) { if ( Abc_NodeIsTravIdCurrent(pObj) ) continue; if ( pObj->pCopy ) continue; Abc_NtkDupObj( pNtkNew, pObj, 0 ); } // connect objects Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_NodeIsTravIdCurrent(pObj) ) Abc_ObjForEachFanin( pObj, pFanin, k ) if ( !Abc_NodeIsTravIdCurrent(pFanin) ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); // call recursively Vec_StrPop( vPref ); Length = Vec_StrSize( vPref ); Abc_NtkForEachBox( pNtk, pObj, i ) { if ( Abc_ObjIsLatch(pObj) ) continue; pNtkModel = (Abc_Ntk_t *)pObj->pData; // check the match between the number of actual and formal parameters assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) ); assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) ); // clean the node copy fields Abc_NtkCleanCopy( pNtkModel ); // map PIs/POs Abc_ObjForEachFanin( pObj, pTerm, k ) Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->pCopy = Abc_ObjFanin0(pTerm)->pCopy; Abc_ObjForEachFanout( pObj, pTerm, k ) Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->pCopy = Abc_ObjFanout0(pTerm)->pCopy; // create name Vec_StrShrink( vPref, Length ); Vec_StrPrintStr( vPref, Abc_NtkName(pNtkModel) ); // call recursively Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtkModel, pCounter, vPref ); } // if it is a BLIF-MV netlist transfer the values of all nets if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) ) { if ( Abc_NtkMvVar( pNtkNew ) == NULL ) Abc_NtkStartMvVars( pNtkNew ); Abc_NtkForEachNet( pNtk, pObj, i ) Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) ); } } /**Function************************************************************* Synopsis [Returns 0 if CI names are repeated.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCompareNames( Abc_Ntk_t ** p1, Abc_Ntk_t ** p2 ) { return strcmp( Abc_NtkName(*p1), Abc_NtkName(*p2) ); } /**Function************************************************************* Synopsis [Prints information about boxes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintBoxInfo( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vMods; Abc_Ntk_t * pModel, * pBoxModel; Abc_Obj_t * pObj; Vec_Int_t * vCounts; int i, k, Num; if ( pNtk->pDesign == NULL || pNtk->pDesign->vModules == NULL ) { // printf( "There is no hierarchy information.\n" ); return; } // sort models by name vMods = pNtk->pDesign->vModules; Vec_PtrSort( vMods, (int(*)(const void *, const void *))Abc_NtkCompareNames ); // Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) // printf( "%s\n", Abc_NtkName(pModel) ); // swap the first model Num = Vec_PtrFind( vMods, pNtk ); assert( Num >= 0 && Num < Vec_PtrSize(vMods) ); pBoxModel = (Abc_Ntk_t *)Vec_PtrEntry(vMods, 0); Vec_PtrWriteEntry(vMods, 0, (Abc_Ntk_t *)Vec_PtrEntry(vMods, Num) ); Vec_PtrWriteEntry(vMods, Num, pBoxModel ); // print models vCounts = Vec_IntStart( Vec_PtrSize(vMods) ); Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) { if ( Abc_NtkBoxNum(pModel) == 0 ) continue; Vec_IntFill( vCounts, Vec_IntSize(vCounts), 0 ); Abc_NtkForEachBox( pModel, pObj, k ) { pBoxModel = (Abc_Ntk_t *)pObj->pData; if ( pBoxModel == NULL ) continue; Num = Vec_PtrFind( vMods, pBoxModel ); assert( Num >= 0 && Num < Vec_PtrSize(vMods) ); Vec_IntAddToEntry( vCounts, Num, 1 ); } // Abc_NtkPrintStats( pModel, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); printf( "MODULE " ); printf( "%-30s : ", Abc_NtkName(pModel) ); printf( "PI=%6d ", Abc_NtkPiNum(pModel) ); printf( "PO=%6d ", Abc_NtkPoNum(pModel) ); printf( "BB=%6d ", Abc_NtkBoxNum(pModel) ); printf( "ND=%6d ", Abc_NtkNodeNum(pModel) ); // sans constants printf( "Lev=%5d ", Abc_NtkLevel(pModel) ); printf( "\n" ); Vec_IntForEachEntry( vCounts, Num, k ) if ( Num ) printf( "%15d : %s\n", Num, Abc_NtkName((Abc_Ntk_t *)Vec_PtrEntry(vMods, k)) ); } Vec_IntFree( vCounts ); Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) { if ( Abc_NtkBoxNum(pModel) != 0 ) continue; printf( "MODULE " ); printf( "%-30s : ", Abc_NtkName(pModel) ); printf( "PI=%6d ", Abc_NtkPiNum(pModel) ); printf( "PO=%6d ", Abc_NtkPoNum(pModel) ); printf( "BB=%6d ", Abc_NtkBoxNum(pModel) ); printf( "ND=%6d ", Abc_NtkNodeNum(pModel) ); printf( "Lev=%5d ", Abc_NtkLevel(pModel) ); printf( "\n" ); } } /**Function************************************************************* Synopsis [Flattens the logic hierarchy of the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk ) { extern Abc_Des_t * Abc_DesDupBlackboxes( Abc_Des_t * p, Abc_Ntk_t * pNtkSave ); Vec_Str_t * vPref; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pTerm, * pNet; int i, Counter = -1; assert( Abc_NtkIsNetlist(pNtk) ); // Abc_NtkPrintBoxInfo( pNtk ); // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); // duplicate the name and the spec pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); // duplicate PIs/POs and their nets Abc_NtkForEachPi( pNtk, pTerm, i ) { Abc_NtkDupObj( pNtkNew, pTerm, 0 ); pNet = Abc_ObjFanout0( pTerm ); pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) ); Abc_ObjAddFanin( pNet->pCopy, pTerm->pCopy ); } Abc_NtkForEachPo( pNtk, pTerm, i ) { Abc_NtkDupObj( pNtkNew, pTerm, 0 ); pNet = Abc_ObjFanin0( pTerm ); pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) ); Abc_ObjAddFanin( pTerm->pCopy, pNet->pCopy ); } // recursively flatten hierarchy, create internal logic, add new PI/PO names if there are black boxes vPref = Vec_StrAlloc( 1000 ); Vec_StrPrintStr( vPref, Abc_NtkName(pNtk) ); Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtk, &Counter, vPref ); printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n", Counter, Abc_NtkBlackboxNum(pNtkNew) ); Vec_StrFree( vPref ); if ( pNtk->pDesign ) { // pass on the design assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk ); pNtkNew->pDesign = Abc_DesDupBlackboxes( pNtk->pDesign, pNtkNew ); // update the pointers Abc_NtkForEachBlackbox( pNtkNew, pTerm, i ) pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy; } // we may have added property outputs Abc_NtkOrderCisCos( pNtkNew ); // copy the timing information // Abc_ManTimeDup( pNtk, pNtkNew ); // duplicate EXDC if ( pNtk->pExdc ) printf( "EXDC is not transformed.\n" ); if ( !Abc_NtkCheck( pNtkNew ) ) { fprintf( stdout, "Abc_NtkFlattenLogicHierarchy(): Network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Extracts blackboxes by making them into additional PIs/POs.] Description [The input netlist has not logic hierarchy. The resulting netlist has additional PIs/POs for each blackbox input/output.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pNet, * pFanin, * pTerm; int i, k; assert( Abc_NtkIsNetlist(pNtk) ); assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); // duplicate the name and the spec pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); // mark the nodes that should not be connected Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachBlackbox( pNtk, pObj, i ) Abc_NodeSetTravIdCurrent( pObj ); Abc_NtkForEachCi( pNtk, pTerm, i ) Abc_NodeSetTravIdCurrent( pTerm ); Abc_NtkForEachCo( pNtk, pTerm, i ) Abc_NodeSetTravIdCurrent( pTerm ); // unmark PIs and LIs/LOs Abc_NtkForEachPi( pNtk, pTerm, i ) Abc_NodeSetTravIdPrevious( pTerm ); Abc_NtkForEachLatchInput( pNtk, pTerm, i ) Abc_NodeSetTravIdPrevious( pTerm ); Abc_NtkForEachLatchOutput( pNtk, pTerm, i ) Abc_NodeSetTravIdPrevious( pTerm ); // copy the box outputs Abc_NtkForEachBlackbox( pNtk, pObj, i ) Abc_ObjForEachFanout( pObj, pTerm, k ) pTerm->pCopy = Abc_NtkCreatePi( pNtkNew ); // duplicate other objects Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_NodeIsTravIdCurrent(pObj) ) Abc_NtkDupObj( pNtkNew, pObj, Abc_ObjIsNet(pObj) ); // connect all objects Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_NodeIsTravIdCurrent(pObj) ) Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); // create unique PO for each net feeding into blackboxes or POs Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachCo( pNtk, pTerm, i ) { // skip latch inputs assert( Abc_ObjFanoutNum(pTerm) <= 1 ); if ( Abc_ObjFanoutNum(pTerm) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pTerm)) ) continue; // check if the net is visited pNet = Abc_ObjFanin0(pTerm); if ( Abc_NodeIsTravIdCurrent(pNet) ) continue; // create PO Abc_NodeSetTravIdCurrent( pNet ); Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNet->pCopy ); } // check integrity if ( !Abc_NtkCheck( pNtkNew ) ) { fprintf( stdout, "Abc_NtkConvertBlackboxes(): Network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Inserts blackboxes into the netlist.] Description [The first arg is the netlist with blackboxes without logic hierarchy. The second arg is a non-hierarchical netlist derived from the above netlist after processing. This procedure create a new netlist, which is comparable to the original netlist with blackboxes, except that it contains logic nodes from the netlist after processing.] SideEffects [This procedure silently assumes that blackboxes appear only in the top-level model. If they appear in other models as well, the name of the model and its number were appended to the names of blackbox inputs/outputs.] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL ) { Abc_Des_t * pDesign; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObjH, * pObjL, * pNetH, * pNetL, * pTermH; int i, k; assert( Abc_NtkIsNetlist(pNtkH) ); assert( Abc_NtkWhiteboxNum(pNtkH) == 0 ); assert( Abc_NtkBlackboxNum(pNtkH) > 0 ); assert( Abc_NtkIsNetlist(pNtkL) ); assert( Abc_NtkWhiteboxNum(pNtkL) == 0 ); assert( Abc_NtkBlackboxNum(pNtkL) == 0 ); // prepare the logic network for copying Abc_NtkCleanCopy( pNtkL ); // start the network pNtkNew = Abc_NtkAlloc( pNtkL->ntkType, pNtkL->ntkFunc, 1 ); // duplicate the name and the spec pNtkNew->pName = Extra_UtilStrsav( pNtkH->pName ); pNtkNew->pSpec = Extra_UtilStrsav( pNtkH->pSpec ); // make sure every PI/PO has a PI/PO in the processed network Abc_NtkForEachPi( pNtkH, pObjH, i ) { pNetH = Abc_ObjFanout0(pObjH); pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) ) { printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the PI %s.\n", Abc_ObjName(pNetH) ); Abc_NtkDelete( pNtkNew ); return NULL; } if ( pNetL->pCopy ) { printf( "Error in Abc_NtkInsertNewLogic(): Primary input %s is repeated twice.\n", Abc_ObjName(pNetH) ); Abc_NtkDelete( pNtkNew ); return NULL; } // create the new net pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); Abc_NtkDupObj( pNtkNew, Abc_ObjFanin0(pNetL), 0 ); } // make sure every BB has a PI/PO in the processed network Abc_NtkForEachBlackbox( pNtkH, pObjH, i ) { // duplicate the box Abc_NtkDupBox( pNtkNew, pObjH, 0 ); pObjH->pCopy->pData = pObjH->pData; // create PIs Abc_ObjForEachFanout( pObjH, pTermH, k ) { pNetH = Abc_ObjFanout0( pTermH ); pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) ) { printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the inpout %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) ); Abc_NtkDelete( pNtkNew ); return NULL; } if ( pNetL->pCopy ) { printf( "Error in Abc_NtkInsertNewLogic(): Box output %s is repeated twice.\n", Abc_ObjName(pNetH) ); Abc_NtkDelete( pNtkNew ); return NULL; } // create net and map the PI pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); Abc_ObjFanin0(pNetL)->pCopy = pTermH->pCopy; } } Abc_NtkForEachPo( pNtkH, pObjH, i ) { pNetH = Abc_ObjFanin0(pObjH); pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) ) { printf( "Error in Abc_NtkInsertNewLogic(): There is no PO corresponding to the PO %s.\n", Abc_ObjName(pNetH) ); Abc_NtkDelete( pNtkNew ); return NULL; } if ( pNetL->pCopy ) continue; // create the new net pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); Abc_NtkDupObj( pNtkNew, Abc_ObjFanout0(pNetL), 0 ); } Abc_NtkForEachBlackbox( pNtkH, pObjH, i ) { Abc_ObjForEachFanin( pObjH, pTermH, k ) { char * pName; pNetH = Abc_ObjFanin0( pTermH ); pName = Abc_ObjName(pNetH); pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) ) { printf( "There is no PO corresponding to the input %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) ); Abc_NtkDelete( pNtkNew ); return NULL; } // create net and map the PO if ( pNetL->pCopy ) { if ( Abc_ObjFanout0(pNetL)->pCopy == NULL ) Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy; else Abc_ObjAddFanin( pTermH->pCopy, pNetL->pCopy ); continue; } pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy; } } // duplicate other objects of the logic network Abc_NtkForEachObj( pNtkL, pObjL, i ) if ( pObjL->pCopy == NULL && !Abc_ObjIsPo(pObjL) ) // skip POs feeding into PIs Abc_NtkDupObj( pNtkNew, pObjL, Abc_ObjIsNet(pObjL) ); // connect objects Abc_NtkForEachObj( pNtkL, pObjL, i ) Abc_ObjForEachFanin( pObjL, pNetL, k ) if ( pObjL->pCopy ) Abc_ObjAddFanin( pObjL->pCopy, pNetL->pCopy ); // transfer the design pDesign = pNtkH->pDesign; pNtkH->pDesign = NULL; assert( Vec_PtrEntry( pDesign->vModules, 0 ) == pNtkH ); Vec_PtrWriteEntry( pDesign->vModules, 0, pNtkNew ); pNtkNew->pDesign = pDesign; // check integrity if ( !Abc_NtkCheck( pNtkNew ) ) { fprintf( stdout, "Abc_NtkInsertNewLogic(): Network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcHieCec.c000066400000000000000000000542671477524141600163760ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcHieCec.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Hierarchical CEC manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcHieCec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" #include "base/io/ioAbc.h" #include "aig/gia/gia.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define Abc_ObjForEachFaninReal( pObj, pFanin, i ) \ for ( i = 0; (i < Abc_ObjFaninNum(pObj)) && (((pFanin) = Abc_ObjFaninReal(pObj, i)), 1); i++ ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the real faniin of the object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline Abc_Obj_t * Abc_ObjFaninReal( Abc_Obj_t * pObj, int i ) { Abc_Obj_t * pRes; if ( Abc_ObjIsBox(pObj) ) pRes = Abc_ObjFanin0( Abc_ObjFanin0( Abc_ObjFanin(pObj, i) ) ); else { assert( Abc_ObjIsPo(pObj) || Abc_ObjIsNode(pObj) ); pRes = Abc_ObjFanin0( Abc_ObjFanin(pObj, i) ); } if ( Abc_ObjIsBo(pRes) ) return Abc_ObjFanin0(pRes); return pRes; } /**Function************************************************************* Synopsis [Performs DFS for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDfsBoxes_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanin; int i; if ( Abc_ObjIsPi(pNode) ) return; assert( Abc_ObjIsNode(pNode) || Abc_ObjIsBox(pNode) ); // if this node is already visited, skip if ( Abc_NodeIsTravIdCurrent( pNode ) ) return; Abc_NodeSetTravIdCurrent( pNode ); // visit the transitive fanin of the node Abc_ObjForEachFaninReal( pNode, pFanin, i ) Abc_NtkDfsBoxes_rec( pFanin, vNodes ); // add the node after the fanins have been added Vec_PtrPush( vNodes, pNode ); } /**Function************************************************************* Synopsis [Returns the array of node and boxes reachable from POs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkDfsBoxes( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i; assert( Abc_NtkIsNetlist(pNtk) ); // set the traversal ID Abc_NtkIncrementTravId( pNtk ); // start the array of nodes vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_NtkDfsBoxes_rec( Abc_ObjFaninReal(pObj, 0), vNodes ); return vNodes; } /**Function************************************************************* Synopsis [Strashes one logic node using its SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkDeriveFlatGiaSop( Gia_Man_t * pGia, int * gFanins, char * pSop ) { char * pCube; int gAnd, gSum; int i, Value, nFanins; // get the number of variables nFanins = Abc_SopGetVarNum(pSop); if ( Abc_SopIsExorType(pSop) ) { gSum = 0; for ( i = 0; i < nFanins; i++ ) gSum = Gia_ManHashXor( pGia, gSum, gFanins[i] ); } else { // go through the cubes of the node's SOP gSum = 0; Abc_SopForEachCube( pSop, nFanins, pCube ) { // create the AND of literals gAnd = 1; Abc_CubeForEachVar( pCube, Value, i ) { if ( Value == '1' ) gAnd = Gia_ManHashAnd( pGia, gAnd, gFanins[i] ); else if ( Value == '0' ) gAnd = Gia_ManHashAnd( pGia, gAnd, Abc_LitNot(gFanins[i]) ); } // add to the sum of cubes gSum = Gia_ManHashAnd( pGia, Abc_LitNot(gSum), Abc_LitNot(gAnd) ); gSum = Abc_LitNot( gSum ); } } // decide whether to complement the result if ( Abc_SopIsComplement(pSop) ) gSum = Abc_LitNot(gSum); return gSum; } /**Function************************************************************* Synopsis [Flattens the logic hierarchy of the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDeriveFlatGia_rec( Gia_Man_t * pGia, Abc_Ntk_t * pNtk ) { int gFanins[16]; Vec_Ptr_t * vOrder = (Vec_Ptr_t *)pNtk->pData; Abc_Obj_t * pObj, * pTerm; Abc_Ntk_t * pNtkModel; int i, k; Abc_NtkForEachPi( pNtk, pTerm, i ) assert( Abc_ObjFanout0(pTerm)->iTemp >= 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) { if ( Abc_ObjIsNode(pObj) ) { char * pSop = (char *)pObj->pData; /* int nLength = strlen(pSop); if ( nLength == 4 ) // buf/inv { assert( pSop[2] == '1' ); assert( pSop[0] == '0' || pSop[0] == '1' ); assert( Abc_ObjFanin0(pObj)->iTemp >= 0 ); Abc_ObjFanout0(pObj)->iTemp = Abc_LitNotCond( Abc_ObjFanin0(pObj)->iTemp, pSop[0]=='0' ); continue; } if ( nLength == 5 ) // and2 { assert( pSop[3] == '1' ); assert( pSop[0] == '0' || pSop[0] == '1' ); assert( pSop[1] == '0' || pSop[1] == '1' ); assert( Abc_ObjFanin0(pObj)->iTemp >= 0 ); assert( Abc_ObjFanin1(pObj)->iTemp >= 0 ); Abc_ObjFanout0(pObj)->iTemp = Gia_ManHashAnd( pGia, Abc_LitNotCond( Abc_ObjFanin0(pObj)->iTemp, pSop[0]=='0' ), Abc_LitNotCond( Abc_ObjFanin1(pObj)->iTemp, pSop[1]=='0' ) ); continue; } */ assert( Abc_ObjFaninNum(pObj) <= 16 ); assert( Abc_ObjFaninNum(pObj) == Abc_SopGetVarNum(pSop) ); Abc_ObjForEachFanin( pObj, pTerm, k ) { gFanins[k] = pTerm->iTemp; assert( gFanins[k] >= 0 ); } Abc_ObjFanout0(pObj)->iTemp = Abc_NtkDeriveFlatGiaSop( pGia, gFanins, pSop ); continue; } assert( Abc_ObjIsBox(pObj) ); pNtkModel = (Abc_Ntk_t *)pObj->pData; Abc_NtkFillTemp( pNtkModel ); // check the match between the number of actual and formal parameters assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) ); assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) ); // assign PIs Abc_ObjForEachFanin( pObj, pTerm, k ) Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->iTemp = Abc_ObjFanin0(pTerm)->iTemp; // call recursively Abc_NtkDeriveFlatGia_rec( pGia, pNtkModel ); // assign POs Abc_ObjForEachFanout( pObj, pTerm, k ) Abc_ObjFanout0(pTerm)->iTemp = Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->iTemp; } Abc_NtkForEachPo( pNtk, pTerm, i ) assert( Abc_ObjFanin0(pTerm)->iTemp >= 0 ); } /**Function************************************************************* Synopsis [Flattens the logic hierarchy of the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Abc_NtkDeriveFlatGia( Abc_Ntk_t * pNtk ) { Gia_Man_t * pTemp, * pGia = NULL; Abc_Obj_t * pTerm; int i; assert( Abc_NtkIsNetlist(pNtk) ); assert( !Abc_NtkLatchNum(pNtk) ); Abc_NtkFillTemp( pNtk ); // start the network pGia = Gia_ManStart( (1<<16) ); pGia->pName = Abc_UtilStrsav( Abc_NtkName(pNtk) ); pGia->pSpec = Abc_UtilStrsav( Abc_NtkSpec(pNtk) ); Gia_ManHashAlloc( pGia ); // create PIs Abc_NtkForEachPi( pNtk, pTerm, i ) Abc_ObjFanout0(pTerm)->iTemp = Gia_ManAppendCi( pGia ); // recursively flatten hierarchy Abc_NtkDeriveFlatGia_rec( pGia, pNtk ); // create POs Abc_NtkForEachPo( pNtk, pTerm, i ) Gia_ManAppendCo( pGia, Abc_ObjFanin0(pTerm)->iTemp ); // prepare return value Gia_ManHashStop( pGia ); Gia_ManSetRegNum( pGia, 0 ); pGia = Gia_ManCleanup( pTemp = pGia ); Gia_ManStop( pTemp ); return pGia; } /**Function************************************************************* Synopsis [Counts the total number of AIG nodes before flattening.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCountAndNodes( Vec_Ptr_t * vOrder ) { Gia_Man_t * pGiaBox; Abc_Ntk_t * pNtkModel; Abc_Obj_t * pObj; int i, Counter = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) { if ( Abc_ObjIsNode(pObj) ) { Counter++; continue; } assert( Abc_ObjIsBox(pObj) ); pNtkModel = (Abc_Ntk_t *)pObj->pData; pGiaBox = (Gia_Man_t *)pNtkModel->pData; Counter += Gia_ManAndNum(pGiaBox); } return Counter; } /**Function************************************************************* Synopsis [Flattens the logic hierarchy of the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Abc_NtkDeriveFlatGia2Derive( Abc_Ntk_t * pNtk, Vec_Ptr_t * vOrder ) { int gFanins[16]; Abc_Ntk_t * pNtkModel; Gia_Man_t * pGiaBox, * pGia = NULL; Gia_Obj_t * pGiaObj; Abc_Obj_t * pTerm, * pObj; int i, k; assert( Abc_NtkIsNetlist(pNtk) ); assert( !Abc_NtkLatchNum(pNtk) ); Abc_NtkFillTemp( pNtk ); // start the network pGia = Gia_ManStart( (1<<15) ); pGia->pName = Abc_UtilStrsav( Abc_NtkName(pNtk) ); pGia->pSpec = Abc_UtilStrsav( Abc_NtkSpec(pNtk) ); Gia_ManHashAlloc( pGia ); // create PIs Abc_NtkForEachPi( pNtk, pTerm, i ) Abc_ObjFanout0(pTerm)->iTemp = Gia_ManAppendCi( pGia ); // recursively flatten hierarchy Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) { if ( Abc_ObjIsNode(pObj) ) { char * pSop = (char *)pObj->pData; assert( Abc_ObjFaninNum(pObj) <= 16 ); assert( Abc_ObjFaninNum(pObj) == Abc_SopGetVarNum(pSop) ); Abc_ObjForEachFanin( pObj, pTerm, k ) { gFanins[k] = pTerm->iTemp; assert( gFanins[k] >= 0 ); } Abc_ObjFanout0(pObj)->iTemp = Abc_NtkDeriveFlatGiaSop( pGia, gFanins, pSop ); continue; } assert( Abc_ObjIsBox(pObj) ); pNtkModel = (Abc_Ntk_t *)pObj->pData; // check the match between the number of actual and formal parameters assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) ); assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) ); /* // assign PIs Abc_ObjForEachFanin( pObj, pTerm, k ) Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->iTemp = Abc_ObjFanin0(pTerm)->iTemp; // call recursively Abc_NtkDeriveFlatGia_rec( pGia, pNtkModel ); // assign POs Abc_ObjForEachFanout( pObj, pTerm, k ) Abc_ObjFanout0(pTerm)->iTemp = Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->iTemp; */ // duplicate the AIG pGiaBox = (Gia_Man_t *)pNtkModel->pData; assert( Abc_ObjFaninNum(pObj) == Gia_ManPiNum(pGiaBox) ); assert( Abc_ObjFanoutNum(pObj) == Gia_ManPoNum(pGiaBox) ); Gia_ManFillValue( pGiaBox ); Gia_ManConst0(pGiaBox)->Value = 0; Abc_ObjForEachFanin( pObj, pTerm, k ) Gia_ManPi(pGiaBox, k)->Value = Abc_ObjFanin0(pTerm)->iTemp; Gia_ManForEachAnd( pGiaBox, pGiaObj, k ) pGiaObj->Value = Gia_ManHashAnd( pGia, Gia_ObjFanin0Copy(pGiaObj), Gia_ObjFanin1Copy(pGiaObj) ); Abc_ObjForEachFanout( pObj, pTerm, k ) Abc_ObjFanout0(pTerm)->iTemp = Gia_ObjFanin0Copy(Gia_ManPo(pGiaBox, k)); } // create POs Abc_NtkForEachPo( pNtk, pTerm, i ) Gia_ManAppendCo( pGia, Abc_ObjFanin0(pTerm)->iTemp ); // prepare return value Gia_ManHashStop( pGia ); Gia_ManSetRegNum( pGia, 0 ); pGia = Gia_ManCleanup( pGiaBox = pGia ); Gia_ManStop( pGiaBox ); printf( "%8d -> ", Abc_NtkCountAndNodes(vOrder) ); Gia_ManPrintStats( pGia, NULL ); return pGia; } /* void Abc_NtkDeriveFlatGia2_rec( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vOrder; Abc_Obj_t * pObj; int i; if ( pNtk->pData != NULL ) return; vOrder = Abc_NtkDfsBoxes( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) if ( Abc_ObjIsBox(pObj) ) Abc_NtkDeriveFlatGia2_rec( (Abc_Ntk_t *)pObj->pData ); pNtk->pData = Abc_NtkDeriveFlatGia2Derive( pNtk, vOrder ); Vec_PtrFree( vOrder ); } Gia_Man_t * Abc_NtkDeriveFlatGia2( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vMods; Abc_Ntk_t * pModel; Gia_Man_t * pGia = NULL; int i; assert( Abc_NtkIsNetlist(pNtk) ); assert( !Abc_NtkLatchNum(pNtk) ); vMods = pNtk->pDesign->vModules; Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) pModel->pData = NULL; Abc_NtkDeriveFlatGia2_rec( pNtk ); pGia = pNtk->pData; pNtk->pData = NULL; Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) Gia_ManStopP( (Gia_Man_t **)&pModel->pData ); return pGia; } */ Gia_Man_t * Abc_NtkDeriveFlatGia2( Abc_Ntk_t * pNtk, Vec_Ptr_t * vModels ) { Vec_Ptr_t * vOrder; Abc_Ntk_t * pModel = NULL; Gia_Man_t * pGia = NULL; int i; Vec_PtrForEachEntry( Abc_Ntk_t *, vModels, pModel, i ) { vOrder = Abc_NtkDfsBoxes( pModel ); pModel->pData = Abc_NtkDeriveFlatGia2Derive( pModel, vOrder ); Vec_PtrFree( vOrder ); } pGia = (Gia_Man_t *)pModel->pData; pModel->pData = NULL; Vec_PtrForEachEntry( Abc_Ntk_t *, vModels, pModel, i ) Gia_ManStopP( (Gia_Man_t **)&pModel->pData ); return pGia; } /**Function************************************************************* Synopsis [Collect models in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCollectHie_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vModels ) { Vec_Ptr_t * vOrder; Abc_Obj_t * pObj; int i; if ( pNtk->iStep >= 0 ) return; vOrder = Abc_NtkDfsBoxes( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) if ( Abc_ObjIsBox(pObj) && (Abc_Ntk_t *)pObj->pData != pNtk ) Abc_NtkCollectHie_rec( (Abc_Ntk_t *)pObj->pData, vModels ); Vec_PtrFree( vOrder ); pNtk->iStep = Vec_PtrSize(vModels); Vec_PtrPush( vModels, pNtk ); } Vec_Ptr_t * Abc_NtkCollectHie( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vMods, * vResult; Abc_Ntk_t * pModel; int i; assert( Abc_NtkIsNetlist(pNtk) ); assert( !Abc_NtkLatchNum(pNtk) ); vResult = Vec_PtrAlloc( 1000 ); if ( pNtk->pDesign == NULL ) { Vec_PtrPush( vResult, pNtk ); return vResult; } vMods = pNtk->pDesign->vModules; Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) pModel->iStep = -1; Abc_NtkCollectHie_rec( pNtk, vResult ); return vResult; } /**Function************************************************************* Synopsis [Counts the number of intstances.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCountInst_rec( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vOrder; Abc_Obj_t * pObj; int i, Counter = 0; if ( pNtk->iStep >= 0 ) return pNtk->iStep; vOrder = Abc_NtkDfsBoxes( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) if ( Abc_ObjIsBox(pObj) && (Abc_Ntk_t *)pObj->pData != pNtk ) Counter += Abc_NtkCountInst_rec( (Abc_Ntk_t *)pObj->pData ); Vec_PtrFree( vOrder ); return pNtk->iStep = 1 + Counter; } void Abc_NtkCountInst( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vMods; Abc_Ntk_t * pModel; int i, Counter; if ( pNtk->pDesign == NULL ) Counter = Abc_NtkNodeNum(pNtk); else { vMods = pNtk->pDesign->vModules; Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) pModel->iStep = -1; Counter = Abc_NtkCountInst_rec( pNtk ); } printf( "Instances = %10d.\n", Counter ); } /**Function************************************************************* Synopsis [Counts the number of nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ double Abc_NtkCountNodes_rec( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vOrder; Abc_Obj_t * pObj; double Counter = 0; int i; if ( pNtk->dTemp >= 0 ) return pNtk->dTemp; vOrder = Abc_NtkDfsBoxes( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) if ( Abc_ObjIsNode(pObj) ) Counter++; else if ( Abc_ObjIsBox(pObj) && (Abc_Ntk_t *)pObj->pData != pNtk ) Counter += Abc_NtkCountNodes_rec( (Abc_Ntk_t *)pObj->pData ); Vec_PtrFree( vOrder ); return pNtk->dTemp = Counter; } void Abc_NtkCountNodes( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vMods; Abc_Ntk_t * pModel; double Counter; int i; if ( pNtk->pDesign == NULL ) Counter = Abc_NtkNodeNum(pNtk); else { vMods = pNtk->pDesign->vModules; Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) pModel->dTemp = -1; Counter = Abc_NtkCountNodes_rec( pNtk ); } printf( "Nodes = %.0f\n", Counter ); } /**Function************************************************************* Synopsis [Checks if there is a recursive definition.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCheckRecursive( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vMods; Abc_Ntk_t * pModel; Abc_Obj_t * pObj; int i, k, RetValue = 0; assert( Abc_NtkIsNetlist(pNtk) ); assert( !Abc_NtkLatchNum(pNtk) ); if ( pNtk->pDesign == NULL ) return RetValue; vMods = pNtk->pDesign->vModules; Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) { Abc_NtkForEachObj( pModel, pObj, k ) if ( Abc_ObjIsBox(pObj) && pObj->pData == (void *)pModel ) { printf( "WARNING: Model \"%s\" contains a recursive definition.\n", Abc_NtkName(pModel) ); RetValue = 1; break; } } return RetValue; } /**Function************************************************************* Synopsis [Performs hierarchical equivalence checking.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Abc_NtkHieCecTest( char * pFileName, int fVerbose ) { int fUseTest = 1; int fUseNew = 0; int fCheck = 1; Vec_Ptr_t * vMods, * vOrder; Abc_Ntk_t * pNtk, * pModel; Gia_Man_t * pGia; int i; abctime clk = Abc_Clock(); // read hierarchical netlist pNtk = Io_ReadBlifMv( pFileName, 0, fCheck ); if ( pNtk == NULL ) { printf( "Reading BLIF file has failed.\n" ); return NULL; } if ( pNtk->pDesign == NULL || pNtk->pDesign->vModules == NULL ) { printf( "There is no hierarchy information.\n" ); // Abc_NtkDelete( pNtk ); // return NULL; } Abc_PrintTime( 1, "Reading file", Abc_Clock() - clk ); assert( Abc_NtkIsNetlist(pNtk) ); assert( !Abc_NtkLatchNum(pNtk) ); /* if ( pNtk->pDesign != NULL ) { clk = Abc_Clock(); Abc_NtkCountNodes( pNtk ); Abc_PrintTime( 1, "Count nodes", Abc_Clock() - clk ); } */ // print stats if ( fVerbose ) Abc_NtkPrintBoxInfo( pNtk ); // test the new data-structure if ( fUseTest ) { extern Gia_Man_t * Au_ManDeriveTest( Abc_Ntk_t * pRoot ); Gia_Man_t * pGia; pGia = Au_ManDeriveTest( pNtk ); Abc_NtkDelete( pNtk ); return pGia; } if ( Abc_NtkCheckRecursive(pNtk) ) return NULL; if ( fUseNew ) { clk = Abc_Clock(); vOrder = Abc_NtkCollectHie( pNtk ); Abc_PrintTime( 1, "Collect DFS ", Abc_Clock() - clk ); // derive GIA clk = Abc_Clock(); pGia = Abc_NtkDeriveFlatGia2( pNtk, vOrder ); Abc_PrintTime( 1, "Deriving GIA", Abc_Clock() - clk ); Gia_ManPrintStats( pGia, NULL ); // Gia_ManStop( pGia ); Vec_PtrFree( vOrder ); } else { // order nodes/boxes of all models vMods = pNtk->pDesign->vModules; Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) pModel->pData = Abc_NtkDfsBoxes( pModel ); // derive GIA clk = Abc_Clock(); pGia = Abc_NtkDeriveFlatGia( pNtk ); Abc_PrintTime( 1, "Deriving GIA", Abc_Clock() - clk ); Gia_ManPrintStats( pGia, NULL ); // clean nodes/boxes of all nodes Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) Vec_PtrFree( (Vec_Ptr_t *)pModel->pData ); } clk = Abc_Clock(); Abc_NtkCountInst( pNtk ); Abc_PrintTime( 1, "Gather stats", Abc_Clock() - clk ); Abc_NtkDelete( pNtk ); return pGia; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcHieGia.c000066400000000000000000000514701477524141600163750ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcHieGia.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures to handle hierarchy.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcHieGia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Transfers the AIG from one manager into another.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeStrashToGia_rec( Gia_Man_t * pNew, Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; Abc_NodeStrashToGia_rec( pNew, Hop_ObjFanin0(pObj) ); Abc_NodeStrashToGia_rec( pNew, Hop_ObjFanin1(pObj) ); pObj->iData = Gia_ManHashAnd( pNew, Hop_ObjChild0CopyI(pObj), Hop_ObjChild1CopyI(pObj) ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA( pObj ); } int Abc_NodeStrashToGia( Gia_Man_t * pNew, Abc_Obj_t * pNode ) { Hop_Man_t * pMan = (Hop_Man_t *)pNode->pNtk->pManFunc; Hop_Obj_t * pRoot = (Hop_Obj_t *)pNode->pData; Abc_Obj_t * pFanin; int i; assert( Abc_ObjIsNode(pNode) ); assert( Abc_NtkHasAig(pNode->pNtk) && !Abc_NtkIsStrash(pNode->pNtk) ); // check the constant case if ( Abc_NodeIsConst(pNode) || Hop_Regular(pRoot) == Hop_ManConst1(pMan) ) return Abc_LitNotCond( 1, Hop_IsComplement(pRoot) ); // set elementary variables Abc_ObjForEachFanin( pNode, pFanin, i ) assert( pFanin->iTemp != -1 ); Abc_ObjForEachFanin( pNode, pFanin, i ) Hop_IthVar(pMan, i)->iData = pFanin->iTemp; // strash the AIG of this node Abc_NodeStrashToGia_rec( pNew, Hop_Regular(pRoot) ); Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); return Abc_LitNotCond( Hop_Regular(pRoot)->iData, Hop_IsComplement(pRoot) ); } /**Function************************************************************* Synopsis [Flattens the logic hierarchy of the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFlattenHierarchyGia2_rec( Gia_Man_t * pNew, Abc_Ntk_t * pNtk, int * pCounter, Vec_Int_t * vBufs ) { Vec_Ptr_t * vDfs = (Vec_Ptr_t *)pNtk->pData; Abc_Obj_t * pObj, * pTerm; int i, k; (*pCounter)++; //printf( "[%d:%d] ", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) ); Vec_PtrForEachEntry( Abc_Obj_t *, vDfs, pObj, i ) { if ( Abc_ObjIsNode(pObj) ) Abc_ObjFanout0(pObj)->iTemp = Abc_NodeStrashToGia( pNew, pObj ); else { int iBufStart = Gia_ManBufNum(pNew); Abc_Ntk_t * pModel = (Abc_Ntk_t *)pObj->pData; assert( !Abc_ObjIsLatch(pObj) ); assert( Abc_NtkPiNum(pModel) == Abc_ObjFaninNum(pObj) ); assert( Abc_NtkPoNum(pModel) == Abc_ObjFanoutNum(pObj) ); Abc_NtkFillTemp( pModel ); Abc_ObjForEachFanin( pObj, pTerm, k ) { assert( Abc_ObjIsNet(Abc_ObjFanin0(pTerm)) ); Abc_ObjFanout0(Abc_NtkPi(pModel, k))->iTemp = Abc_ObjFanin0(pTerm)->iTemp; } if ( vBufs ) Abc_ObjForEachFanin( pObj, pTerm, k ) Abc_ObjFanout0(Abc_NtkPi(pModel, k))->iTemp = Gia_ManAppendBuf( pNew, Abc_ObjFanout0(Abc_NtkPi(pModel, k))->iTemp ); Abc_NtkFlattenHierarchyGia2_rec( pNew, pModel, pCounter, vBufs ); if ( vBufs ) Abc_ObjForEachFanout( pObj, pTerm, k ) Abc_ObjFanin0(Abc_NtkPo(pModel, k))->iTemp = Gia_ManAppendBuf( pNew, Abc_ObjFanin0(Abc_NtkPo(pModel, k))->iTemp ); Abc_ObjForEachFanout( pObj, pTerm, k ) { assert( Abc_ObjIsNet(Abc_ObjFanout0(pTerm)) ); Abc_ObjFanout0(pTerm)->iTemp = Abc_ObjFanin0(Abc_NtkPo(pModel, k))->iTemp; } // save buffers if ( vBufs == NULL ) continue; Vec_IntPush( vBufs, iBufStart ); Vec_IntPush( vBufs, Abc_NtkPiNum(pModel) ); Vec_IntPush( vBufs, Gia_ManBufNum(pNew) - Abc_NtkPoNum(pModel) ); Vec_IntPush( vBufs, Abc_NtkPoNum(pModel) ); } } } Gia_Man_t * Abc_NtkFlattenHierarchyGia2( Abc_Ntk_t * pNtk ) { int fUseBufs = 1; int fUseInter = 0; Gia_Man_t * pNew, * pTemp; Abc_Ntk_t * pModel; Abc_Obj_t * pTerm; int i, Counter = -1; assert( Abc_NtkIsNetlist(pNtk) ); // Abc_NtkPrintBoxInfo( pNtk ); Abc_NtkFillTemp( pNtk ); // start the manager pNew = Gia_ManStart( Abc_NtkObjNumMax(pNtk) ); pNew->pName = Abc_UtilStrsav(pNtk->pName); pNew->pSpec = Abc_UtilStrsav(pNtk->pSpec); if ( fUseBufs ) pNew->vBarBufs = Vec_IntAlloc( 1000 ); // create PIs and buffers Abc_NtkForEachPi( pNtk, pTerm, i ) pTerm->iTemp = Gia_ManAppendCi( pNew ); Abc_NtkForEachPi( pNtk, pTerm, i ) Abc_ObjFanout0(pTerm)->iTemp = fUseInter ? Gia_ManAppendBuf(pNew, pTerm->iTemp) : pTerm->iTemp; // create DFS order of nets if ( !pNtk->pDesign ) pNtk->pData = Abc_NtkDfsWithBoxes( pNtk ); else Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pModel, i ) pModel->pData = Abc_NtkDfsWithBoxes( pModel ); // call recursively Gia_ManHashAlloc( pNew ); Abc_NtkFlattenHierarchyGia2_rec( pNew, pNtk, &Counter, pNew->vBarBufs ); Gia_ManHashStop( pNew ); printf( "Hierarchy reader flattened %d instances of logic boxes.\n", Counter ); // delete DFS order of nets if ( !pNtk->pDesign ) Vec_PtrFreeP( (Vec_Ptr_t **)&pNtk->pData ); else Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pModel, i ) Vec_PtrFreeP( (Vec_Ptr_t **)&pModel->pData ); // create buffers and POs Abc_NtkForEachPo( pNtk, pTerm, i ) pTerm->iTemp = fUseInter ? Gia_ManAppendBuf(pNew, Abc_ObjFanin0(pTerm)->iTemp) : Abc_ObjFanin0(pTerm)->iTemp; Abc_NtkForEachPo( pNtk, pTerm, i ) Gia_ManAppendCo( pNew, pTerm->iTemp ); // save buffers if ( fUseInter ) { Vec_IntPush( pNew->vBarBufs, 0 ); Vec_IntPush( pNew->vBarBufs, Abc_NtkPiNum(pNtk) ); Vec_IntPush( pNew->vBarBufs, Gia_ManBufNum(pNew) - Abc_NtkPoNum(pNtk) ); Vec_IntPush( pNew->vBarBufs, Abc_NtkPoNum(pNtk) ); } if ( fUseBufs ) Vec_IntPrint( pNew->vBarBufs ); // cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Gia_ManPrintBarBufDrivers( Gia_Man_t * p ) { Vec_Int_t * vMap, * vFan, * vCrits; Gia_Obj_t * pObj; int i, iFanin, CountCrit[2] = {0}, CountFans[2] = {0}; // map barbuf drivers into barbuf literals of the first barbuf driven by them vMap = Vec_IntStart( Gia_ManObjNum(p) ); vFan = Vec_IntStart( Gia_ManObjNum(p) ); vCrits = Vec_IntAlloc( 100 ); Gia_ManForEachObj( p, pObj, i ) { // count fanouts if ( Gia_ObjIsBuf(pObj) || Gia_ObjIsCo(pObj) ) Vec_IntAddToEntry( vFan, Gia_ObjFaninId0(pObj, i), 1 ); else if ( Gia_ObjIsAnd(pObj) ) { Vec_IntAddToEntry( vFan, Gia_ObjFaninId0(pObj, i), 1 ); Vec_IntAddToEntry( vFan, Gia_ObjFaninId1(pObj, i), 1 ); } // count critical barbufs if ( Gia_ObjIsBuf(pObj) ) { iFanin = Gia_ObjFaninId0( pObj, i ); if ( iFanin == 0 || Vec_IntEntry(vMap, iFanin) != 0 ) { CountCrit[(int)(iFanin != 0)]++; Vec_IntPush( vCrits, i ); continue; } Vec_IntWriteEntry( vMap, iFanin, Abc_Var2Lit(i, Gia_ObjFaninC0(pObj)) ); } } // check fanouts of the critical barbufs Gia_ManForEachObjVec( vCrits, p, pObj, i ) { assert( Gia_ObjIsBuf(pObj) ); if ( Vec_IntEntry(vFan, i) == 0 ) continue; iFanin = Gia_ObjFaninId0p( p, pObj ); CountFans[(int)(iFanin != 0)]++; } printf( "Detected %d const (out of %d) and %d shared (out of %d) barbufs with fanout.\n", CountFans[0], CountCrit[0], CountFans[1], CountCrit[1] ); Vec_IntFree( vMap ); Vec_IntFree( vFan ); Vec_IntFree( vCrits ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Gia_ManPatchBufDriver( Gia_Man_t * p, int iBuf, int iLit0 ) { Gia_Obj_t * pObjBuf = Gia_ManObj( p, iBuf ); assert( Gia_ObjIsBuf(pObjBuf) ); assert( Gia_ObjId(p, pObjBuf) > Abc_Lit2Var(iLit0) ); pObjBuf->iDiff1 = pObjBuf->iDiff0 = Gia_ObjId(p, pObjBuf) - Abc_Lit2Var(iLit0); pObjBuf->fCompl1 = pObjBuf->fCompl0 = Abc_LitIsCompl(iLit0); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Gia_ManSweepHierarchy( Gia_Man_t * p ) { Vec_Int_t * vMap = Vec_IntStart( Gia_ManObjNum(p) ); Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj, * pObjNew, * pObjNewR; int i, iFanin, CountReals[2] = {0}; // duplicate AIG while propagating constants and equivalences 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) ); pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); iFanin = Gia_ObjFaninId0p( pNew, pObjNew ); if ( iFanin == 0 ) { pObj->Value = Gia_ObjFaninC0(pObjNew); CountReals[0]++; Gia_ManPatchBufDriver( pNew, Gia_ObjId(pNew, pObjNew), 0 ); } else if ( Vec_IntEntry(vMap, iFanin) ) { pObjNewR = Gia_ManObj( pNew, Vec_IntEntry(vMap, iFanin) ); pObj->Value = Abc_Var2Lit( Vec_IntEntry(vMap, iFanin), Gia_ObjFaninC0(pObjNewR) ^ Gia_ObjFaninC0(pObjNew) ); CountReals[1]++; Gia_ManPatchBufDriver( pNew, Gia_ObjId(pNew, pObjNew), 0 ); } else Vec_IntWriteEntry( vMap, iFanin, Gia_ObjId(pNew, pObjNew) ); } 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) ); } Gia_ManHashStop( pNew ); Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); // printf( "Updated %d const and %d shared.\n", CountReals[0], CountReals[1] ); Vec_IntFree( vMap ); return pNew; } /**Function************************************************************* Synopsis [Flattens the logic hierarchy of the netlist.] Description [This procedure requires that models are uniqified.] SideEffects [] SeeAlso [] ***********************************************************************/ int Gia_ManFlattenLogicPrepare( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pTerm, * pBox; int i, k; Abc_NtkFillTemp( pNtk ); Abc_NtkForEachPi( pNtk, pTerm, i ) pTerm->iData = i; Abc_NtkForEachPo( pNtk, pTerm, i ) pTerm->iData = i; Abc_NtkForEachBox( pNtk, pBox, i ) { assert( !Abc_ObjIsLatch(pBox) ); Abc_ObjForEachFanin( pBox, pTerm, k ) pTerm->iData = k; Abc_ObjForEachFanout( pBox, pTerm, k ) pTerm->iData = k; } return Abc_NtkPiNum(pNtk) + Abc_NtkPoNum(pNtk); } int Abc_NtkFlattenHierarchyGia_rec( Gia_Man_t * pNew, Vec_Ptr_t * vSupers, Abc_Obj_t * pObj, Vec_Ptr_t * vBuffers ) { Abc_Ntk_t * pModel; Abc_Obj_t * pBox, * pFanin; int iLit, i; if ( pObj->iTemp != -1 ) return pObj->iTemp; if ( Abc_ObjIsNet(pObj) || Abc_ObjIsPo(pObj) || Abc_ObjIsBi(pObj) ) return (pObj->iTemp = Abc_NtkFlattenHierarchyGia_rec(pNew, vSupers, Abc_ObjFanin0(pObj), vBuffers)); if ( Abc_ObjIsPi(pObj) ) { pBox = (Abc_Obj_t *)Vec_PtrPop( vSupers ); pModel = Abc_ObjModel(pBox); //printf( " Exiting %s\n", Abc_NtkName(pModel) ); assert( Abc_ObjFaninNum(pBox) == Abc_NtkPiNum(pModel) ); assert( pObj->iData >= 0 && pObj->iData < Abc_NtkPiNum(pModel) ); pFanin = Abc_ObjFanin( pBox, pObj->iData ); iLit = Abc_NtkFlattenHierarchyGia_rec( pNew, vSupers, pFanin, vBuffers ); Vec_PtrPush( vSupers, pBox ); //if ( vBuffers ) Vec_PtrPush( vBuffers, pFanin ); // save BI if ( vBuffers ) Vec_PtrPush( vBuffers, pObj ); // save PI return (pObj->iTemp = (vBuffers ? Gia_ManAppendBuf(pNew, iLit) : iLit)); } if ( Abc_ObjIsBo(pObj) ) { pBox = Abc_ObjFanin0(pObj); assert( Abc_ObjIsBox(pBox) ); Vec_PtrPush( vSupers, pBox ); pModel = Abc_ObjModel(pBox); //printf( "Entering %s\n", Abc_NtkName(pModel) ); assert( Abc_ObjFanoutNum(pBox) == Abc_NtkPoNum(pModel) ); assert( pObj->iData >= 0 && pObj->iData < Abc_NtkPoNum(pModel) ); pFanin = Abc_NtkPo( pModel, pObj->iData ); iLit = Abc_NtkFlattenHierarchyGia_rec( pNew, vSupers, pFanin, vBuffers ); Vec_PtrPop( vSupers ); //if ( vBuffers ) Vec_PtrPush( vBuffers, pObj ); // save BO if ( vBuffers ) Vec_PtrPush( vBuffers, pFanin ); // save PO return (pObj->iTemp = (vBuffers ? Gia_ManAppendBuf(pNew, iLit) : iLit)); } assert( Abc_ObjIsNode(pObj) ); Abc_ObjForEachFanin( pObj, pFanin, i ) Abc_NtkFlattenHierarchyGia_rec( pNew, vSupers, pFanin, vBuffers ); return (pObj->iTemp = Abc_NodeStrashToGia( pNew, pObj )); } Gia_Man_t * Abc_NtkFlattenHierarchyGia( Abc_Ntk_t * pNtk, Vec_Ptr_t ** pvBuffers, int fVerbose ) { int fUseBufs = 1; Gia_Man_t * pNew, * pTemp; Abc_Ntk_t * pModel; Abc_Obj_t * pTerm; Vec_Ptr_t * vSupers; Vec_Ptr_t * vBuffers = fUseBufs ? Vec_PtrAlloc(1000) : NULL; int i, Counter = 0; assert( Abc_NtkIsNetlist(pNtk) ); // Abc_NtkPrintBoxInfo( pNtk ); // set the PI/PO numbers Counter -= Abc_NtkPiNum(pNtk) + Abc_NtkPoNum(pNtk); if ( !pNtk->pDesign ) Counter += Gia_ManFlattenLogicPrepare( pNtk ); else Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pModel, i ) Counter += Gia_ManFlattenLogicPrepare( pModel ); // start the manager pNew = Gia_ManStart( Abc_NtkObjNumMax(pNtk) ); pNew->pName = Abc_UtilStrsav(pNtk->pName); pNew->pSpec = Abc_UtilStrsav(pNtk->pSpec); // create PIs and buffers Abc_NtkForEachPi( pNtk, pTerm, i ) pTerm->iTemp = Gia_ManAppendCi( pNew ); // call recursively vSupers = Vec_PtrAlloc( 100 ); Gia_ManHashAlloc( pNew ); Abc_NtkForEachPo( pNtk, pTerm, i ) Abc_NtkFlattenHierarchyGia_rec( pNew, vSupers, pTerm, vBuffers ); Gia_ManHashStop( pNew ); Vec_PtrFree( vSupers ); printf( "Hierarchy reader flattened %d instances of boxes and added %d barbufs (out of %d).\n", pNtk->pDesign ? Vec_PtrSize(pNtk->pDesign->vModules)-1 : 0, Vec_PtrSize(vBuffers), Counter ); // create buffers and POs Abc_NtkForEachPo( pNtk, pTerm, i ) Gia_ManAppendCo( pNew, pTerm->iTemp ); if ( pvBuffers ) *pvBuffers = vBuffers; else Vec_PtrFreeP( &vBuffers ); // cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); // Gia_ManPrintStats( pNew, NULL ); pNew = Gia_ManSweepHierarchy( pTemp = pNew ); Gia_ManStop( pTemp ); // Gia_ManPrintStats( pNew, NULL ); return pNew; } /**Function************************************************************* Synopsis [Inserts the result of mapping into logic hierarchy.] Description [When this procedure is called PIs/POs of pNtk point to the corresponding nodes in network with barbufs.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Gia_ManInsertOne_rec( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNew, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; if ( pObj == NULL ) return Abc_NtkCreateNodeConst0( pNtk ); assert( Abc_ObjNtk(pObj) == pNew ); if ( pObj->pCopy ) return pObj->pCopy; Abc_ObjForEachFanin( pObj, pFanin, i ) Gia_ManInsertOne_rec( pNtk, pNew, pFanin ); pObj->pCopy = Abc_NtkDupObj( pNtk, pObj, 0 ); Abc_ObjForEachFanin( pObj, pFanin, i ) Abc_ObjAddFanin( pObj, pFanin ); return pObj->pCopy; } void Gia_ManInsertOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNew ) { Abc_Obj_t * pObj, * pBox; int i, k; assert( !Abc_NtkHasMapping(pNtk) ); assert( Abc_NtkHasMapping(pNew) ); // check that PIs point to barbufs Abc_NtkForEachPi( pNtk, pObj, i ) assert( !pObj->pCopy || Abc_ObjNtk(pObj->pCopy) == pNew ); // make barbufs point to box outputs Abc_NtkForEachBox( pNtk, pBox, i ) Abc_ObjForEachFanout( pBox, pObj, k ) { pObj->pCopy = Abc_NtkPo(Abc_ObjModel(pBox), k)->pCopy; assert( !pObj->pCopy || Abc_ObjNtk(pObj->pCopy) == pNew ); } // remove internal nodes Abc_NtkForEachNode( pNtk, pObj, i ) Abc_NtkDeleteObj( pObj ); // start traversal from box inputs Abc_NtkForEachBox( pNtk, pBox, i ) Abc_ObjForEachFanin( pBox, pObj, k ) if ( Abc_ObjFaninNum(pObj) == 0 ) Abc_ObjAddFanin( pObj, Gia_ManInsertOne_rec(pNtk, pNew, Abc_NtkPi(Abc_ObjModel(pBox), k)->pCopy) ); // start traversal from primary outputs Abc_NtkForEachPo( pNtk, pObj, i ) if ( Abc_ObjFaninNum(pObj) == 0 ) Abc_ObjAddFanin( pObj, Gia_ManInsertOne_rec(pNtk, pNew, pObj->pCopy) ); // update the functionality manager pNtk->pManFunc = pNew->pManFunc; pNtk->ntkFunc = pNew->ntkFunc; assert( Abc_NtkHasMapping(pNtk) ); } void Abc_NtkInsertHierarchyGia( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNew, int fVerbose ) { Vec_Ptr_t * vBuffers; Gia_Man_t * pGia = Abc_NtkFlattenHierarchyGia( pNtk, &vBuffers, 0 ); Abc_Ntk_t * pModel; Abc_Obj_t * pObj; int i, k = 0; assert( Gia_ManPiNum(pGia) == Abc_NtkPiNum(pNtk) ); assert( Gia_ManPiNum(pGia) == Abc_NtkPiNum(pNew) ); assert( Gia_ManPoNum(pGia) == Abc_NtkPoNum(pNtk) ); assert( Gia_ManPoNum(pGia) == Abc_NtkPoNum(pNew) ); assert( Gia_ManBufNum(pGia) == Vec_PtrSize(vBuffers) ); assert( Gia_ManBufNum(pGia) == pNew->nBarBufs2 ); Gia_ManStop( pGia ); // clean the networks if ( !pNtk->pDesign ) Abc_NtkCleanCopy( pNtk ); else Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pModel, i ) Abc_NtkCleanCopy( pModel ); // annotate PIs and POs of each network with barbufs Abc_NtkForEachPi( pNew, pObj, i ) Abc_NtkPi(pNtk, i)->pCopy = pObj; Abc_NtkForEachPo( pNew, pObj, i ) Abc_NtkPo(pNtk, i)->pCopy = pObj; Abc_NtkForEachBarBuf( pNew, pObj, i ) ((Abc_Obj_t *)Vec_PtrEntry(vBuffers, k++))->pCopy = pObj; Vec_PtrFree( vBuffers ); // connect each model Abc_NtkCleanCopy( pNew ); Gia_ManInsertOne( pNtk, pNew ); if ( pNtk->pDesign ) Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pModel, i ) if ( pModel != pNtk ) Gia_ManInsertOne( pModel, pNew ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcHieNew.c000066400000000000000000001720271477524141600164300ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcHieNew.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [New hierarchy manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcHieNew.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include #include #include #include "misc/vec/vec.h" #include "misc/util/utilNam.h" #include "misc/extra/extra.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define AU_MAX_FANINS 0x1FFFFFFF typedef enum { AU_OBJ_NONE, // 0: non-existent object AU_OBJ_CONST0, // 1: constant node AU_OBJ_PI, // 2: primary input AU_OBJ_PO, // 3: primary output AU_OBJ_FAN, // 4: box output AU_OBJ_FLOP, // 5: flip-flop AU_OBJ_BOX, // 6: box AU_OBJ_NODE, // 7: logic node AU_OBJ_VOID // 8: placeholder } Au_Type_t; typedef struct Au_Man_t_ Au_Man_t; typedef struct Au_Ntk_t_ Au_Ntk_t; typedef struct Au_Obj_t_ Au_Obj_t; struct Au_Obj_t_ // 16 bytes { unsigned Func : 30; // functionality unsigned Value : 2; // node value unsigned Type : 3; // object type unsigned nFanins : 29; // fanin count (related to AU_MAX_FANIN_NUM) int Fanins[2]; // fanin literals }; struct Au_Ntk_t_ { char * pName; // model name Au_Man_t * pMan; // model manager int Id; // model ID // objects Vec_Int_t vPis; // primary inputs (CI id -> handle) Vec_Int_t vPos; // primary outputs (CI id -> handle) Vec_Int_t vObjs; // internal nodes (obj id -> handle) int nObjs[AU_OBJ_VOID]; // counter of objects of each type // memory for objects Vec_Ptr_t * vChunks; // memory pages Vec_Ptr_t vPages; // memory pages int iHandle; // currently available ID int nObjsAlloc; // the total number of objects allocated int nObjsUsed; // the number of useful entries // object attributes int nTravIds; // counter of traversal IDs Vec_Int_t vTravIds; // trav IDs of the objects Vec_Int_t vCopies; // object copies // structural hashing int nHTable; // hash table size int * pHTable; // hash table Au_Obj_t * pConst0; // constant node // statistics int fMark; double nBoxes; double nNodes; double nPorts; double nNodeAnds; double nNodeXors; double nNodeMuxs; }; struct Au_Man_t_ { char * pName; // the name of the library Vec_Ptr_t vNtks; // the array of modules Abc_Nam_t * pFuncs; // hashing functions into integers int nRefs; // reference counter // statistics int nGiaObjMax; // max number of GIA objects double nPortsC0; // const ports double nPortsC1; // const ports double nPortsNC; // non-const ports }; static inline int Au_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } static inline int Au_Lit2Var( int Lit ) { return Lit >> 1; } static inline int Au_LitIsCompl( int Lit ) { return Lit & 1; } static inline int Au_LitNot( int Lit ) { return Lit ^ 1; } static inline int Au_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } static inline int Au_LitRegular( int Lit ) { return Lit & ~01; } static inline Au_Obj_t * Au_Regular( Au_Obj_t * p ) { return (Au_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } static inline Au_Obj_t * Au_Not( Au_Obj_t * p ) { return (Au_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } static inline Au_Obj_t * Au_NotCond( Au_Obj_t * p, int c ) { return (Au_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } static inline int Au_IsComplement( Au_Obj_t * p ) { return (int)((ABC_PTRUINT_T)(p) & 01); } static inline char * Au_UtilStrsav( char * s ) { return s ? strcpy(ABC_ALLOC(char, strlen(s)+1), s) : NULL; } static inline char * Au_ManName( Au_Man_t * p ) { return p->pName; } static inline int Au_ManNtkNum( Au_Man_t * p ) { return Vec_PtrSize(&p->vNtks) - 1; } static inline Au_Ntk_t * Au_ManNtk( Au_Man_t * p, int i ) { return (Au_Ntk_t *)Vec_PtrEntry(&p->vNtks, i); } static inline Au_Ntk_t * Au_ManNtkRoot( Au_Man_t * p ) { return Au_ManNtk( p, 1 ); } static inline char * Au_NtkName( Au_Ntk_t * p ) { return p->pName; } static inline Au_Man_t * Au_NtkMan( Au_Ntk_t * p ) { return p->pMan; } static inline int Au_NtkPiNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_PI]; } static inline int Au_NtkPoNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_PO]; } static inline int Au_NtkFanNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_FAN]; } static inline int Au_NtkFlopNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_FLOP]; } static inline int Au_NtkBoxNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_BOX]; } static inline int Au_NtkNodeNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_NODE]; } static inline int Au_NtkObjNumMax( Au_Ntk_t * p ) { return (Vec_PtrSize(&p->vPages) - 1) * (1 << 12) + p->iHandle; } static inline int Au_NtkObjNum( Au_Ntk_t * p ) { return Vec_IntSize(&p->vObjs); } static inline Au_Obj_t * Au_NtkObj( Au_Ntk_t * p, int h ) { return (Au_Obj_t *)p->vPages.pArray[h >> 12] + (h & 0xFFF); } static inline Au_Obj_t * Au_NtkPi( Au_Ntk_t * p, int i ) { return Au_NtkObj(p, Vec_IntEntry(&p->vPis, i)); } static inline Au_Obj_t * Au_NtkPo( Au_Ntk_t * p, int i ) { return Au_NtkObj(p, Vec_IntEntry(&p->vPos, i)); } static inline Au_Obj_t * Au_NtkObjI( Au_Ntk_t * p, int i ) { return Au_NtkObj(p, Vec_IntEntry(&p->vObjs, i)); } static inline int Au_ObjIsNone( Au_Obj_t * p ) { return p->Type == AU_OBJ_NONE; } static inline int Au_ObjIsConst0( Au_Obj_t * p ) { return p->Type == AU_OBJ_CONST0; } static inline int Au_ObjIsPi( Au_Obj_t * p ) { return p->Type == AU_OBJ_PI; } static inline int Au_ObjIsPo( Au_Obj_t * p ) { return p->Type == AU_OBJ_PO; } static inline int Au_ObjIsFan( Au_Obj_t * p ) { return p->Type == AU_OBJ_FAN; } static inline int Au_ObjIsFlop( Au_Obj_t * p ) { return p->Type == AU_OBJ_FLOP; } static inline int Au_ObjIsBox( Au_Obj_t * p ) { return p->Type == AU_OBJ_BOX; } static inline int Au_ObjIsNode( Au_Obj_t * p ) { return p->Type == AU_OBJ_NODE; } static inline int Au_ObjIsTerm( Au_Obj_t * p ) { return p->Type >= AU_OBJ_PI && p->Type <= AU_OBJ_FLOP; } static inline char * Au_ObjBase( Au_Obj_t * p ) { return (char *)p - ((ABC_PTRINT_T)p & 0x3FF); } static inline Au_Ntk_t * Au_ObjNtk( Au_Obj_t * p ) { return ((Au_Ntk_t **)Au_ObjBase(p))[0]; } static inline int Au_ObjId( Au_Obj_t * p ) { return ((int *)Au_ObjBase(p))[2] | (((ABC_PTRINT_T)p & 0x3FF) >> 4); } static inline int Au_ObjPioNum( Au_Obj_t * p ) { assert(Au_ObjIsTerm(p)); return p->Fanins[p->nFanins]; } static inline int Au_ObjFunc( Au_Obj_t * p ) { return p->Func; } static inline Au_Ntk_t * Au_ObjModel( Au_Obj_t * p ) { assert(Au_ObjIsFan(p)||Au_ObjIsBox(p)); return Au_ManNtk(Au_NtkMan(Au_ObjNtk(p)), p->Func); } static inline int Au_ObjFaninNum( Au_Obj_t * p ) { return p->nFanins; } static inline int Au_ObjFaninId( Au_Obj_t * p, int i ) { assert(i >= 0 && i < (int)p->nFanins && p->Fanins[i]); return Au_Lit2Var(p->Fanins[i]); } static inline int Au_ObjFaninId0( Au_Obj_t * p ) { return Au_ObjFaninId(p, 0); } static inline int Au_ObjFaninId1( Au_Obj_t * p ) { return Au_ObjFaninId(p, 1); } static inline int Au_ObjFaninId2( Au_Obj_t * p ) { return Au_ObjFaninId(p, 2); } static inline Au_Obj_t * Au_ObjFanin( Au_Obj_t * p, int i ) { return Au_NtkObj(Au_ObjNtk(p), Au_ObjFaninId(p, i)); } static inline Au_Obj_t * Au_ObjFanin0( Au_Obj_t * p ) { return Au_ObjFanin( p, 0 ); } static inline Au_Obj_t * Au_ObjFanin1( Au_Obj_t * p ) { return Au_ObjFanin( p, 1 ); } static inline Au_Obj_t * Au_ObjFanin2( Au_Obj_t * p ) { return Au_ObjFanin( p, 2 ); } static inline int Au_ObjFaninC( Au_Obj_t * p, int i ) { assert(i >= 0 && i < (int)p->nFanins && p->Fanins[i]); return Au_LitIsCompl(p->Fanins[i]); } static inline int Au_ObjFaninC0( Au_Obj_t * p ) { return Au_ObjFaninC(p, 0); } static inline int Au_ObjFaninC1( Au_Obj_t * p ) { return Au_ObjFaninC(p, 1); } static inline int Au_ObjFaninC2( Au_Obj_t * p ) { return Au_ObjFaninC(p, 2); } static inline int Au_ObjFaninLit( Au_Obj_t * p, int i ) { assert(i >= 0 && i < (int)p->nFanins && p->Fanins[i]); return p->Fanins[i]; } static inline void Au_ObjSetFanin( Au_Obj_t * p, int i, int f ) { assert(f > 0 && p->Fanins[i] == 0); p->Fanins[i] = Au_Var2Lit(f,0); } static inline void Au_ObjSetFaninLit( Au_Obj_t * p, int i, int f){ assert(f >= 0 && p->Fanins[i] == 0); p->Fanins[i] = f; } static inline int Au_BoxFanoutNum( Au_Obj_t * p ) { assert(Au_ObjIsBox(p)); return p->Fanins[p->nFanins]; } static inline int Au_BoxFanoutId( Au_Obj_t * p, int i ) { assert(i >= 0 && i < Au_BoxFanoutNum(p)); return p->Fanins[p->nFanins+1+i]; } static inline Au_Obj_t * Au_BoxFanout( Au_Obj_t * p, int i ) { return Au_NtkObj(Au_ObjNtk(p), Au_BoxFanoutId(p, i)); } static inline int Au_ObjCopy( Au_Obj_t * p ) { return Vec_IntEntry( &Au_ObjNtk(p)->vCopies, Au_ObjId(p) ); } static inline void Au_ObjSetCopy( Au_Obj_t * p, int c ) { Vec_IntWriteEntry( &Au_ObjNtk(p)->vCopies, Au_ObjId(p), c ); } static inline int Au_ObjFanout( Au_Obj_t * p, int i ) { assert(p->Type == AU_OBJ_BOX && i >= 0 && i < p->Fanins[p->nFanins] && p->Fanins[i]); return p->Fanins[p->nFanins + 1 + i]; } static inline void Au_ObjSetFanout( Au_Obj_t * p, int i, int f ) { assert(p->Type == AU_OBJ_BOX && i >= 0 && i < p->Fanins[p->nFanins] && p->Fanins[i] == 0 && f > 0); p->Fanins[p->nFanins + 1 + i] = f; } static inline void Au_NtkIncrementTravId( Au_Ntk_t * p ) { if (p->vTravIds.pArray == NULL) Vec_IntFill(&p->vTravIds, Au_NtkObjNumMax(p)+500, 0); p->nTravIds++; assert(p->nTravIds < (1<<30)); } static inline void Au_ObjSetTravIdCurrent( Au_Obj_t * p ) { Vec_IntSetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p), Au_ObjNtk(p)->nTravIds ); } static inline void Au_ObjSetTravIdPrevious( Au_Obj_t * p ) { Vec_IntSetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p), Au_ObjNtk(p)->nTravIds-1 ); } static inline int Au_ObjIsTravIdCurrent( Au_Obj_t * p ) { return (Vec_IntGetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p)) == Au_ObjNtk(p)->nTravIds); } static inline int Au_ObjIsTravIdPrevious( Au_Obj_t * p ) { return (Vec_IntGetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p)) == Au_ObjNtk(p)->nTravIds-1); } static inline void Au_ObjSetTravIdCurrentId( Au_Ntk_t * p, int Id ) { Vec_IntSetEntry(&p->vTravIds, Id, p->nTravIds ); } static inline int Au_ObjIsTravIdCurrentId( Au_Ntk_t * p, int Id ) { return (Vec_IntGetEntry(&p->vTravIds, Id) == p->nTravIds); } #define Au_ManForEachNtk( p, pNtk, i ) \ for ( i = 1; (i < Vec_PtrSize(&p->vNtks)) && (((pNtk) = Au_ManNtk(p, i)), 1); i++ ) #define Au_ManForEachNtkReverse( p, pNtk, i ) \ for ( i = Vec_PtrSize(&p->vNtks) - 1;(i>=1) && (((pNtk) = Au_ManNtk(p, i)), 1); i-- ) #define Au_ObjForEachFaninId( pObj, hFanin, i ) \ for ( i = 0; (i < Au_ObjFaninNum(pObj)) && (((hFanin) = Au_ObjFaninId(pObj, i)), 1); i++ ) #define Au_BoxForEachFanoutId( pObj, hFanout, i) \ for ( i = 0; (i < Au_BoxFanoutNum(pObj)) && (((hFanout) = Au_BoxFanoutId(pObj, i)), 1); i++ ) #define Au_ObjForEachFanin( pObj, pFanin, i ) \ for ( i = 0; (i < Au_ObjFaninNum(pObj)) && (((pFanin) = Au_ObjFanin(pObj, i)), 1); i++ ) #define Au_BoxForEachFanout( pObj, pFanout, i) \ for ( i = 0; (i < Au_BoxFanoutNum(pObj)) && (((pFanout) = Au_BoxFanout(pObj, i)), 1); i++ ) #define Au_NtkForEachPi( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(&p->vPis)) && (((pObj) = Au_NtkPi(p, i)), 1); i++ ) #define Au_NtkForEachPo( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(&p->vPos)) && (((pObj) = Au_NtkPo(p, i)), 1); i++ ) #define Au_NtkForEachObj( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(&p->vObjs)) && (((pObj) = Au_NtkObjI(p, i)), 1); i++ ) #define Au_NtkForEachNode( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(&p->vObjs)) && (((pObj) = Au_NtkObjI(p, i)), 1); i++ ) if ( !Au_ObjIsNode(pObj) ) {} else #define Au_NtkForEachBox( p, pObj, i ) \ for ( i = 0; (i < Vec_IntSize(&p->vObjs)) && (((pObj) = Au_NtkObjI(p, i)), 1); i++ ) if ( !Au_ObjIsBox(pObj) ) {} else extern void Au_ManAddNtk( Au_Man_t * pMan, Au_Ntk_t * p ); extern void Au_ManFree( Au_Man_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Working with models.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Au_Ntk_t * Au_NtkAlloc( Au_Man_t * pMan, char * pName ) { Au_Ntk_t * p; p = ABC_CALLOC( Au_Ntk_t, 1 ); p->pName = Au_UtilStrsav( pName ); p->vChunks = Vec_PtrAlloc( 111 ); Vec_IntGrow( &p->vPis, 111 ); Vec_IntGrow( &p->vPos, 111 ); Vec_IntGrow( &p->vObjs, 1111 ); Vec_PtrGrow( &p->vPages, 11 ); Au_ManAddNtk( pMan, p ); return p; } void Au_NtkFree( Au_Ntk_t * p ) { Au_ManFree( p->pMan ); Vec_PtrFreeFree( p->vChunks ); ABC_FREE( p->vCopies.pArray ); ABC_FREE( p->vPages.pArray ); ABC_FREE( p->vObjs.pArray ); ABC_FREE( p->vPis.pArray ); ABC_FREE( p->vPos.pArray ); ABC_FREE( p->pHTable ); ABC_FREE( p->pName ); ABC_FREE( p ); } int Au_NtkMemUsage( Au_Ntk_t * p ) { int Mem = sizeof(Au_Ntk_t); Mem += 4 * p->vPis.nCap; Mem += 4 * p->vPos.nCap; Mem += 4 * p->vObjs.nCap; Mem += 16 * p->nObjsAlloc; return Mem; } void Au_NtkPrintStats( Au_Ntk_t * p ) { printf( "%-30s:", Au_NtkName(p) ); printf( " i/o =%6d/%6d", Au_NtkPiNum(p), Au_NtkPoNum(p) ); if ( Au_NtkFlopNum(p) ) printf( " lat =%5d", Au_NtkFlopNum(p) ); printf( " nd =%6d", Au_NtkNodeNum(p) ); // if ( Au_NtkBoxNum(p) ) printf( " box =%5d", Au_NtkBoxNum(p) ); printf( " obj =%7d", Au_NtkObjNum(p) ); // printf( " max =%7d", Au_NtkObjNumMax(p) ); // printf( " use =%7d", p->nObjsUsed ); printf( " %5.1f %%", 100.0 * (Au_NtkObjNumMax(p) - Au_NtkObjNum(p)) / Au_NtkObjNumMax(p) ); printf( " %6.1f MB", 1.0 * Au_NtkMemUsage(p) / (1 << 20) ); printf( " %5.1f %%", 100.0 * (p->nObjsAlloc - p->nObjsUsed) / p->nObjsAlloc ); printf( "\n" ); } void Au_NtkCleanCopy( Au_Ntk_t * p ) { Vec_IntFill( &p->vCopies, Au_NtkObjNumMax(p), -1 ); } int Au_NtkNodeNumFunc( Au_Ntk_t * p, int Func ) { Au_Obj_t * pObj; int i, Counter = 0; if ( p->pMan && p->pMan->pFuncs ) return 0; Au_NtkForEachNode( p, pObj, i ) { Counter += (pObj->Func == (unsigned)Func); // printf( "%d ", pObj->Func ); } // printf( "\n" ); return Counter; } /**Function************************************************************* Synopsis [Working with manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Au_Man_t * Au_ManAlloc( char * pName ) { Au_Man_t * p; p = ABC_CALLOC( Au_Man_t, 1 ); p->pName = Au_UtilStrsav( pName ); Vec_PtrGrow( &p->vNtks, 111 ); Vec_PtrPush( &p->vNtks, NULL ); return p; } void Au_ManFree( Au_Man_t * p ) { assert( p->nRefs > 0 ); if ( --p->nRefs > 0 ) return; if ( p->pFuncs ) Abc_NamStop( p->pFuncs ); ABC_FREE( p->vNtks.pArray ); ABC_FREE( p->pName ); ABC_FREE( p ); } void Au_ManDelete( Au_Man_t * p ) { Au_Ntk_t * pNtk; int i; Au_ManForEachNtk( p, pNtk, i ) Au_NtkFree( pNtk ); } int Au_ManFindNtk( Au_Man_t * p, char * pName ) { Au_Ntk_t * pNtk; int i; Au_ManForEachNtk( p, pNtk, i ) if ( !strcmp(Au_NtkName(pNtk), pName) ) return i; return -1; } Au_Ntk_t * Au_ManFindNtkP( Au_Man_t * p, char * pName ) { int iNtk = Au_ManFindNtk( p, pName ); if ( iNtk == -1 ) return NULL; return Au_ManNtk( p, iNtk ); } void Au_ManAddNtk( Au_Man_t * pMan, Au_Ntk_t * p ) { assert( Au_ManFindNtk(pMan, Au_NtkName(p)) == -1 ); p->pMan = pMan; pMan->nRefs++; p->Id = Vec_PtrSize( &pMan->vNtks ); Vec_PtrPush( &pMan->vNtks, p ); } int Au_ManMemUsage( Au_Man_t * p ) { Au_Ntk_t * pNtk; int i, Mem = 0; Au_ManForEachNtk( p, pNtk, i ) Mem += 16 * pNtk->nObjsAlloc; return Mem; } int Au_ManMemUsageUseful( Au_Man_t * p ) { Au_Ntk_t * pNtk; int i, Mem = 0; Au_ManForEachNtk( p, pNtk, i ) Mem += 16 * pNtk->nObjsUsed; return Mem; } void Au_ManPrintStats( Au_Man_t * p ) { Au_Ntk_t * pNtk; int i; if ( Vec_PtrSize(&p->vNtks) > 2 ) printf( "Design %-13s\n", Au_ManName(p) ); Au_ManForEachNtk( p, pNtk, i ) Au_NtkPrintStats( pNtk ); printf( "Different functions = %d. ", p->pFuncs ? Abc_NamObjNumMax(p->pFuncs) : 0 ); printf( "Memory = %.1f MB", 1.0 * Au_ManMemUsage(p) / (1 << 20) ); printf( " %5.1f %%", 100.0 * (Au_ManMemUsage(p) - Au_ManMemUsageUseful(p)) / Au_ManMemUsage(p) ); printf( "\n" ); // if ( p->pFuncs ) // Abc_NamPrint( p->pFuncs ); } void Au_ManReorderModels_rec( Au_Ntk_t * pNtk, Vec_Int_t * vOrder ) { Au_Ntk_t * pBoxModel; Au_Obj_t * pObj; int k; if ( pNtk->fMark ) return; pNtk->fMark = 1; Au_NtkForEachBox( pNtk, pObj, k ) { pBoxModel = Au_ObjModel(pObj); if ( pBoxModel == NULL || pBoxModel == pNtk ) continue; Au_ManReorderModels_rec( pBoxModel, vOrder ); } Vec_IntPush( vOrder, pNtk->Id ); } void Au_ManReorderModels( Au_Man_t * p, Au_Ntk_t * pRoot ) { Vec_Ptr_t * vNtksNew; Vec_Int_t * vOrder, * vTemp; Au_Ntk_t * pNtk, * pBoxModel; Au_Obj_t * pBox, * pFan; int i, k, j, Entry; Au_ManForEachNtk( p, pNtk, i ) pNtk->fMark = 0; // collect networks in the DFS order vOrder = Vec_IntAlloc( Au_ManNtkNum(p)+1 ); Vec_IntPush( vOrder, 0 ); Au_ManReorderModels_rec( pRoot, vOrder ); assert( Vec_IntEntryLast(vOrder) == pRoot->Id ); // add unconnected ones Vec_IntPop( vOrder ); Au_ManForEachNtk( p, pNtk, i ) if ( pNtk->fMark == 0 ) Vec_IntPush( vOrder, pNtk->Id ); Vec_IntPush( vOrder, pRoot->Id ); assert( Vec_IntSize(vOrder) == Au_ManNtkNum(p)+1 ); // reverse order vOrder->nSize--; vOrder->pArray++; Vec_IntReverseOrder( vOrder ); vOrder->pArray--; vOrder->nSize++; // compute new order vNtksNew = Vec_PtrAlloc( Au_ManNtkNum(p)+1 ); Vec_IntForEachEntry( vOrder, Entry, i ) Vec_PtrPush( vNtksNew, Au_ManNtk(p, Entry) ); // invert order assert( Vec_IntEntry(vOrder, 1) == pRoot->Id ); vOrder = Vec_IntInvert( vTemp = vOrder, 0 ); Vec_IntFree( vTemp ); assert( Vec_IntEntry(vOrder, 1) == pRoot->Id ); // update model numbers Au_ManForEachNtk( p, pNtk, i ) { pNtk->Id = Vec_IntEntry( vOrder, pNtk->Id ); Au_NtkForEachBox( pNtk, pBox, k ) { pBox->Func = Vec_IntEntry( vOrder, pBox->Func ); assert( pBox->Func > 0 ); Au_BoxForEachFanout( pBox, pFan, j ) pFan->Func = pBox->Func; } } // update ABC_FREE( p->vNtks.pArray ); p->vNtks.pArray = vNtksNew->pArray; vNtksNew->pArray = NULL; Vec_PtrFree( vNtksNew ); // verify Au_ManForEachNtk( p, pNtk, i ) Au_NtkForEachBox( pNtk, pBox, k ) { pBoxModel = Au_ObjModel(pBox); if ( pBoxModel == NULL || pBoxModel == pNtk ) continue; assert( !pBox->Func || pBox->Func >= (unsigned)pNtk->Id ); assert( Au_ObjFaninNum(pBox) == Au_NtkPiNum(pBoxModel) ); assert( Au_BoxFanoutNum(pBox) == Au_NtkPoNum(pBoxModel) ); } Vec_IntFree( vOrder ); } void Au_ManCountThings( Au_Man_t * p ) { Au_Ntk_t * pNtk, * pBoxModel; Au_Obj_t * pBox; int i, k;//, clk = Abc_Clock(); Au_ManForEachNtkReverse( p, pNtk, i ) { pNtk->nBoxes = Au_NtkBoxNum(pNtk); pNtk->nNodes = Au_NtkNodeNum(pNtk); pNtk->nPorts = Au_NtkPiNum(pNtk) + Au_NtkPoNum(pNtk); pNtk->nNodeAnds = Au_NtkNodeNumFunc( pNtk, 1 ); pNtk->nNodeXors = Au_NtkNodeNumFunc( pNtk, 2 ); pNtk->nNodeMuxs = Au_NtkNodeNumFunc( pNtk, 3 ); // assert( pNtk->nNodes == pNtk->nNodeAnds + pNtk->nNodeXors + pNtk->nNodeMuxs ); // printf( "adding %.0f nodes of model %s\n", pNtk->nNodes, Au_NtkName(pNtk) ); Au_NtkForEachBox( pNtk, pBox, k ) { pBoxModel = Au_ObjModel(pBox); if ( pBoxModel == NULL || pBoxModel == pNtk ) continue; assert( Au_ObjFaninNum(pBox) == Au_NtkPiNum(pBoxModel) ); assert( Au_BoxFanoutNum(pBox) == Au_NtkPoNum(pBoxModel) ); assert( pBoxModel->Id > pNtk->Id ); assert( pBoxModel->nPorts > 0 ); pNtk->nBoxes += pBoxModel->nBoxes; pNtk->nNodes += pBoxModel->nNodes; pNtk->nPorts += pBoxModel->nPorts; pNtk->nNodeAnds += pBoxModel->nNodeAnds; pNtk->nNodeXors += pBoxModel->nNodeXors; pNtk->nNodeMuxs += pBoxModel->nNodeMuxs; // printf( " adding %.0f nodes of model %s\n", pBoxModel->nNodes, Au_NtkName(pBoxModel) ); } // printf( "total %.0f nodes in model %s\n", pNtk->nNodes, Au_NtkName(pNtk) ); } pNtk = Au_ManNtkRoot(p); printf( "Total nodes = %15.0f. Total instances = %15.0f. Total ports = %15.0f.\n", // printf( "Total nodes = %.2e. Total instances = %.2e. Total ports = %.2e.\n", pNtk->nNodes, pNtk->nBoxes, pNtk->nPorts ); // printf( "Total ANDs = %15.0f. Total XORs = %15.0f. Total MUXes = %15.0f.\n", // printf( "Total ANDs = %.2e. Total XORs = %.2e. Total MUXes = %.2e. ", // pNtk->nNodeAnds, pNtk->nNodeXors, pNtk->nNodeMuxs ); printf( "Total ANDs = %15.0f.\n", pNtk->nNodeAnds ); printf( "Total XORs = %15.0f.\n", pNtk->nNodeXors ); printf( "Total MUXes = %15.0f.\n", pNtk->nNodeMuxs ); // Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } int Au_NtkCompareNames( Au_Ntk_t ** p1, Au_Ntk_t ** p2 ) { return strcmp( Au_NtkName(*p1), Au_NtkName(*p2) ); } void Au_ManPrintBoxInfo( Au_Ntk_t * pNtk ) { Vec_Ptr_t * vMods; Au_Ntk_t * pModel, * pBoxModel; Au_Obj_t * pObj; Vec_Int_t * vCounts; int i, k, Num; if ( pNtk->pMan == NULL ) { printf( "There is no hierarchy information.\n" ); return; } vMods = &pNtk->pMan->vNtks; /* vMods->nSize--; vMods->pArray++; // sort models by name 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) ); pBoxModel = (Au_Ntk_t *)Vec_PtrEntry(vMods, 0); Vec_PtrWriteEntry(vMods, 0, (Au_Ntk_t *)Vec_PtrEntry(vMods, Num) ); Vec_PtrWriteEntry(vMods, Num, pBoxModel ); vMods->pArray--; vMods->nSize++; */ // Vec_PtrForEachEntry( Au_Ntk_t *, vMods, pModel, i ) // printf( "%s\n", Au_NtkName(pModel) ); // print models vCounts = Vec_IntStart( Vec_PtrSize(vMods) ); Vec_PtrForEachEntryStart( Au_Ntk_t *, vMods, pModel, i, 1 ) { if ( Au_NtkBoxNum(pModel) == 0 ) continue; Vec_IntFill( vCounts, Vec_IntSize(vCounts), 0 ); Au_NtkForEachBox( pModel, pObj, k ) { pBoxModel = Au_ObjModel(pObj); if ( pBoxModel == NULL || pBoxModel == pModel ) continue; Num = Vec_PtrFind( vMods, pBoxModel ); assert( Num >= 0 && Num < Vec_PtrSize(vMods) ); Vec_IntAddToEntry( vCounts, Num, 1 ); } // Au_NtkPrintStats( pModel, 0, 0, 0, 0, 0, 0, 0 ); printf( "MODULE " ); printf( "%-30s : ", Au_NtkName(pModel) ); printf( "PI=%6d ", Au_NtkPiNum(pModel) ); printf( "PO=%6d ", Au_NtkPoNum(pModel) ); printf( "BB=%6d ", Au_NtkBoxNum(pModel) ); printf( "ND=%6d ", Au_NtkNodeNum(pModel) ); // sans constants // printf( "Lev=%5d ", Au_NtkLevel(pModel) ); printf( "\n" ); Vec_IntForEachEntry( vCounts, Num, k ) if ( Num ) printf( "%15d : %s\n", Num, Au_NtkName((Au_Ntk_t *)Vec_PtrEntry(vMods, k)) ); } Vec_IntFree( vCounts ); Vec_PtrForEachEntryStart( Au_Ntk_t *, vMods, pModel, i, 1 ) { if ( Au_NtkBoxNum(pModel) != 0 ) continue; printf( "MODULE " ); printf( "%-30s : ", Au_NtkName(pModel) ); printf( "PI=%6d ", Au_NtkPiNum(pModel) ); printf( "PO=%6d ", Au_NtkPoNum(pModel) ); printf( "BB=%6d ", Au_NtkBoxNum(pModel) ); printf( "ND=%6d ", Au_NtkNodeNum(pModel) ); // printf( "Lev=%5d ", Au_NtkLevel(pModel) ); printf( "\n" ); } } int Au_NtkCompareSign( Au_Ntk_t ** p1, Au_Ntk_t ** p2 ) { if ( Au_NtkPiNum(*p1) - Au_NtkPiNum(*p2) != 0 ) return Au_NtkPiNum(*p1) - Au_NtkPiNum(*p2); else return Au_NtkPoNum(*p1) - Au_NtkPoNum(*p2); } void Au_ManPrintBoxInfoSorted( Au_Ntk_t * pNtk ) { Vec_Ptr_t * vMods, * vModsNew; Au_Ntk_t * pModel; int i; if ( pNtk->pMan == NULL ) { printf( "There is no hierarchy information.\n" ); return; } vMods = &pNtk->pMan->vNtks; vMods->nSize--; vMods->pArray++; vModsNew = Vec_PtrDup( vMods ); vMods->pArray--; vMods->nSize++; Vec_PtrSort( vModsNew, (int(*)(const void *, const void *))Au_NtkCompareSign ); Vec_PtrForEachEntryStart( Au_Ntk_t *, vModsNew, pModel, i, 1 ) { printf( "MODULE " ); printf( "%-30s : ", Au_NtkName(pModel) ); printf( "PI=%6d ", Au_NtkPiNum(pModel) ); printf( "PO=%6d ", Au_NtkPoNum(pModel) ); printf( "BB=%6d ", Au_NtkBoxNum(pModel) ); printf( "ND=%6d ", Au_NtkNodeNum(pModel) ); printf( "\n" ); } Vec_PtrFree( vModsNew ); } int Au_NtkCheckRecursive( Au_Ntk_t * pNtk ) { Vec_Ptr_t * vMods; Au_Ntk_t * pModel; Au_Obj_t * pObj; int i, k, RetValue = 0; if ( pNtk->pMan == NULL ) { printf( "There is no hierarchy information.\n" ); return RetValue; } vMods = &pNtk->pMan->vNtks; Vec_PtrForEachEntryStart( Au_Ntk_t *, vMods, pModel, i, 1 ) { Au_NtkForEachObj( pModel, pObj, k ) if ( Au_ObjIsBox(pObj) && Au_ObjModel(pObj) == pModel ) { printf( "WARNING: Model \"%s\" contains a recursive definition.\n", Au_NtkName(pModel) ); RetValue = 1; break; } } return RetValue; } // count the number of support variables int Au_ObjSuppSize_rec( Au_Ntk_t * p, int Id ) { Au_Obj_t * pObj; int i, iFanin, Counter = 0; if ( Au_ObjIsTravIdCurrentId(p, Id) ) return 0; Au_ObjSetTravIdCurrentId(p, Id); pObj = Au_NtkObj( p, Id ); if ( Au_ObjIsPi(pObj) ) return 1; assert( Au_ObjIsNode(pObj) || Au_ObjIsBox(pObj) || Au_ObjIsFan(pObj) ); Au_ObjForEachFaninId( pObj, iFanin, i ) Counter += Au_ObjSuppSize_rec( p, iFanin ); return Counter; } int Au_ObjSuppSize( Au_Obj_t * pObj ) { Au_Ntk_t * p = Au_ObjNtk(pObj); Au_NtkIncrementTravId( p ); return Au_ObjSuppSize_rec( p, Au_ObjId(pObj) ); } /* // this version is 50% slower than above int Au_ObjSuppSize_rec( Au_Obj_t * pObj ) { Au_Obj_t * pFanin; int i, Counter = 0; if ( Au_ObjIsTravIdCurrent(pObj) ) return 0; Au_ObjSetTravIdCurrent(pObj); if ( Au_ObjIsPi(pObj) ) return 1; assert( Au_ObjIsNode(pObj) || Au_ObjIsBox(pObj) || Au_ObjIsFan(pObj) ); Au_ObjForEachFanin( pObj, pFanin, i ) Counter += Au_ObjSuppSize_rec( pFanin ); return Counter; } int Au_ObjSuppSize( Au_Obj_t * pObj ) { Au_NtkIncrementTravId( Au_ObjNtk(pObj) ); return Au_ObjSuppSize_rec( pObj ); } */ int Au_NtkSuppSizeTest( Au_Ntk_t * p ) { Au_Obj_t * pObj; int i, Counter = 0; Au_NtkForEachObj( p, pObj, i ) if ( Au_ObjIsNode(pObj) ) Counter += (Au_ObjSuppSize(pObj) <= 16); printf( "Nodes with small support %d (out of %d)\n", Counter, Au_NtkNodeNum(p) ); return Counter; } /**Function************************************************************* Synopsis [Returns memory for the next object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Au_NtkInsertHeader( Au_Ntk_t * p ) { Au_Obj_t * pMem = (Au_Obj_t *)Vec_PtrEntryLast( &p->vPages ); assert( (((ABC_PTRINT_T)(pMem + p->iHandle) & 0x3FF) >> 4) == 0 ); ((Au_Ntk_t **)(pMem + p->iHandle))[0] = p; ((int *)(pMem + p->iHandle))[2] = ((Vec_PtrSize(&p->vPages) - 1) << 12) | (p->iHandle & 0xFC0); p->iHandle++; } int Au_NtkAllocObj( Au_Ntk_t * p, int nFanins, int Type ) { Au_Obj_t * pMem, * pObj, * pTemp; int nObjInt = ((2+nFanins) >> 2) + (((2+nFanins) & 3) > 0); int Id, nObjIntReal = nObjInt; if ( nObjInt > 63 ) nObjInt = 63 + 64 * (((nObjInt-63) >> 6) + (((nObjInt-63) & 63) > 0)); if ( Vec_PtrSize(&p->vPages) == 0 || p->iHandle + nObjInt > (1 << 12) ) { if ( nObjInt + 64 > (1 << 12) ) pMem = ABC_CALLOC( Au_Obj_t, nObjInt + 64 ), p->nObjsAlloc += nObjInt + 64; else pMem = ABC_CALLOC( Au_Obj_t, (1 << 12) + 64 ), p->nObjsAlloc += (1 << 12) + 64; Vec_PtrPush( p->vChunks, pMem ); if ( ((ABC_PTRINT_T)pMem & 0xF) ) pMem = (Au_Obj_t *)((char *)pMem + 16 - ((ABC_PTRINT_T)pMem & 0xF)); assert( ((ABC_PTRINT_T)pMem & 0xF) == 0 ); p->iHandle = (((ABC_PTRINT_T)pMem & 0x3FF) >> 4); if ( p->iHandle ) { pMem += 64 - (p->iHandle & 63); p->iHandle = 0; } Vec_PtrPush( &p->vPages, pMem ); Au_NtkInsertHeader( p ); } else { pMem = (Au_Obj_t *)Vec_PtrEntryLast( &p->vPages ); if ( (p->iHandle & 63) == 0 || nObjInt > (64 - (p->iHandle & 63)) ) { if ( p->iHandle & 63 ) p->iHandle += 64 - (p->iHandle & 63); Au_NtkInsertHeader( p ); } if ( p->iHandle + nObjInt > (1 << 12) ) return Au_NtkAllocObj( p, nFanins, Type ); } pObj = pMem + p->iHandle; assert( *((int *)pObj) == 0 ); pObj->nFanins = nFanins; p->nObjs[pObj->Type = Type]++; if ( Type == AU_OBJ_PI ) { Au_ObjSetFaninLit( pObj, 0, Vec_IntSize(&p->vPis) ); Vec_IntPush( &p->vPis, Au_ObjId(pObj) ); } else if ( Type == AU_OBJ_PO ) { Au_ObjSetFaninLit( pObj, 1, Vec_IntSize(&p->vPos) ); Vec_IntPush( &p->vPos, Au_ObjId(pObj) ); } p->iHandle += nObjInt; p->nObjsUsed += nObjIntReal; Id = Au_ObjId(pObj); Vec_IntPush( &p->vObjs, Id ); pTemp = Au_NtkObj( p, Id ); assert( pTemp == pObj ); return Id; } int Au_NtkCreateConst0( Au_Ntk_t * pNtk ) { return Au_NtkAllocObj( pNtk, 0, AU_OBJ_CONST0 ); } int Au_NtkCreatePi( Au_Ntk_t * pNtk ) { return Au_NtkAllocObj( pNtk, 0, AU_OBJ_PI ); } int Au_NtkCreatePo( Au_Ntk_t * pNtk, int iFanin ) { int Id = Au_NtkAllocObj( pNtk, 1, AU_OBJ_PO ); if ( iFanin ) Au_ObjSetFaninLit( Au_NtkObj(pNtk, Id), 0, iFanin ); return Id; } int Au_NtkCreateFan( Au_Ntk_t * pNtk, int iFanin, int iFanout, int iModel ) { int Id = Au_NtkAllocObj( pNtk, 1, AU_OBJ_FAN ); Au_Obj_t * p = Au_NtkObj( pNtk, Id ); if ( iFanin ) Au_ObjSetFaninLit( p, 0, iFanin ); Au_ObjSetFaninLit( p, 1, iFanout ); p->Func = iModel; return Id; } int Au_NtkCreateNode( Au_Ntk_t * pNtk, Vec_Int_t * vFanins, int iFunc ) { int i, iFanin; int Id = Au_NtkAllocObj( pNtk, Vec_IntSize(vFanins), AU_OBJ_NODE ); Au_Obj_t * p = Au_NtkObj( pNtk, Id ); Vec_IntForEachEntry( vFanins, iFanin, i ) Au_ObjSetFaninLit( p, i, iFanin ); p->Func = iFunc; return Id; } int Au_NtkCreateBox( Au_Ntk_t * pNtk, Vec_Int_t * vFanins, int nFanouts, int iModel ) { int i, iFanin, nFanins = Vec_IntSize(vFanins); int Id = Au_NtkAllocObj( pNtk, nFanins + 1 + nFanouts, AU_OBJ_BOX ); Au_Obj_t * p = Au_NtkObj( pNtk, Id ); Vec_IntForEachEntry( vFanins, iFanin, i ) Au_ObjSetFaninLit( p, i, iFanin ); Au_ObjSetFaninLit( p, nFanins, nFanouts ); for ( i = 0; i < nFanouts; i++ ) Au_ObjSetFaninLit( p, nFanins + 1 + i, Au_NtkCreateFan(pNtk, Au_Var2Lit(Id,0), i, iModel) ); p->nFanins = nFanins; p->Func = iModel; assert( iModel > 0 ); return Id; } /* * 0/1 would denote false/true respectively. * Signals would be even numbers, and negation would be handled by xor with 1. * The output signal for each gate or subckt could be implicitly generated just use the next signal number. * For ranges, we could use "start:cnt" to denote the sequence "start, start+2, ..., start + 2*(cnt- 1)". - "cnt" seems more intuitive when signals are restricted to even numbers. * We'd have subckts and specialized gates .and, .xor, and .mux. Here is a small example: .model test .inputs 3 # Inputs 2 4 6 .subckt and3 3 1 2:3 # 8 is implicit output .outputs 1 8 .end .model and3 .inputs 3 # Inputs 2 4 6 .and 2 4 # 8 output .and 6 8 # 10 output .outputs 1 10 .end */ /**Function************************************************************* Synopsis [Reads one entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Au_NtkRemapNum( Vec_Int_t * vNum2Obj, int Num ) { return Au_Var2Lit(Vec_IntEntry(vNum2Obj, Au_Lit2Var(Num)), Au_LitIsCompl(Num)); } /**Function************************************************************* Synopsis [Reads one entry.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Au_NtkParseCBlifNum( Vec_Int_t * vFanins, char * pToken, Vec_Int_t * vNum2Obj ) { char * pCur; int Num1, Num2, i; assert( pToken[0] >= '0' && pToken[0] <= '9' ); Num1 = atoi( pToken ); for ( pCur = pToken; *pCur; pCur++ ) if ( *pCur == ':' ) { Num2 = atoi( pCur+1 ); for ( i = 0; i < Num2; i++ ) Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num1 + i + i) ); return; } else if ( *pCur == '*' ) { Num2 = atoi( pCur+1 ); for ( i = 0; i < Num2; i++ ) Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num1) ); return; } assert( *pCur == 0 ); Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num1) ); } /**Function************************************************************* Synopsis [Parses CBLIF file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Au_Ntk_t * Au_NtkParseCBlif( char * pFileName ) { FILE * pFile; Au_Man_t * pMan; Au_Ntk_t * pRoot = NULL; Au_Obj_t * pBox, * pFan; char * pBuffer, * pCur; Vec_Int_t * vLines, * vNum2Obj, * vFanins; int i, k, j, Id, nInputs, nOutputs; int Line, Num, Func; // read the file pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open file \"%s\".\n", pFileName ); return NULL; } pBuffer = Extra_FileRead( pFile ); fclose( pFile ); // split into lines vLines = Vec_IntAlloc( 1000 ); Vec_IntPush( vLines, 0 ); for ( pCur = pBuffer; *pCur; pCur++ ) if ( *pCur == '\n' ) { *pCur = 0; Vec_IntPush( vLines, pCur - pBuffer + 1 ); } // start the manager pMan = Au_ManAlloc( pFileName ); // parse the lines vNum2Obj = Vec_IntAlloc( 1000 ); vFanins = Vec_IntAlloc( 1000 ); Vec_IntForEachEntry( vLines, Line, i ) { pCur = strtok( pBuffer + Line, " \t\r" ); if ( pCur == NULL || *pCur == '#' ) continue; if ( *pCur != '.' ) { printf( "Cannot read directive in line %d: \"%s\".\n", i, pBuffer + Line ); continue; } Vec_IntClear( vFanins ); if ( !strcmp(pCur, ".and") ) { for ( k = 0; k < 2; k++ ) { pCur = strtok( NULL, " \t\r" ); Num = atoi( pCur ); Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num) ); } Id = Au_NtkCreateNode( pRoot, vFanins, 1 ); Vec_IntPush( vNum2Obj, Id ); } else if ( !strcmp(pCur, ".xor") ) { for ( k = 0; k < 2; k++ ) { pCur = strtok( NULL, " \t\r" ); Num = atoi( pCur ); Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num) ); } Id = Au_NtkCreateNode( pRoot, vFanins, 2 ); Vec_IntPush( vNum2Obj, Id ); } else if ( !strcmp(pCur, ".mux") ) { for ( k = 0; k < 3; k++ ) { pCur = strtok( NULL, " \t\r" ); Num = atoi( pCur ); Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num) ); } Id = Au_NtkCreateNode( pRoot, vFanins, 3 ); Vec_IntPush( vNum2Obj, Id ); } else if ( !strcmp(pCur, ".subckt") ) { pCur = strtok( NULL, " \t\r" ); Func = pCur - pBuffer; pCur = strtok( NULL, " \t\r" ); nInputs = atoi( pCur ); pCur = strtok( NULL, " \t\r" ); nOutputs = atoi( pCur ); while ( 1 ) { pCur = strtok( NULL, " \t\r" ); if ( pCur == NULL || *pCur == '#' ) break; Au_NtkParseCBlifNum( vFanins, pCur, vNum2Obj ); } assert( Vec_IntSize(vFanins) == nInputs ); Id = Au_NtkCreateBox( pRoot, vFanins, nOutputs, Func ); pBox = Au_NtkObj( pRoot, Id ); Au_BoxForEachFanoutId( pBox, Num, k ) Vec_IntPush( vNum2Obj, Num ); } else if ( !strcmp(pCur, ".model") ) { pCur = strtok( NULL, " \t\r" ); pRoot = Au_NtkAlloc( pMan, pCur ); Id = Au_NtkCreateConst0( pRoot ); Vec_IntClear( vNum2Obj ); Vec_IntPush( vNum2Obj, Id ); } else if ( !strcmp(pCur, ".inputs") ) { pCur = strtok( NULL, " \t\r" ); Num = atoi( pCur ); for ( k = 0; k < Num; k++ ) Vec_IntPush( vNum2Obj, Au_NtkCreatePi(pRoot) ); } else if ( !strcmp(pCur, ".outputs") ) { pCur = strtok( NULL, " \t\r" ); nOutputs = atoi( pCur ); while ( 1 ) { pCur = strtok( NULL, " \t\r" ); if ( pCur == NULL || *pCur == '#' ) break; Au_NtkParseCBlifNum( vFanins, pCur, vNum2Obj ); } assert( Vec_IntSize(vFanins) == nOutputs ); Vec_IntForEachEntry( vFanins, Num, k ) Au_NtkCreatePo( pRoot, Num ); } else if ( strcmp(pCur, ".end") ) printf( "Unknown directive in line %d: \"%s\".\n", i, pBuffer + Line ); } Vec_IntFree( vFanins ); Vec_IntFree( vNum2Obj ); Vec_IntFree( vLines ); // set pointers to models Au_ManForEachNtk( pMan, pRoot, i ) Au_NtkForEachBox( pRoot, pBox, k ) { pBox->Func = Au_ManFindNtk( pMan, pBuffer + pBox->Func ); assert( pBox->Func > 0 ); Au_BoxForEachFanout( pBox, pFan, j ) pFan->Func = pBox->Func; } ABC_FREE( pBuffer ); // order models in topological order pRoot = Au_ManNtkRoot( pMan ); Au_ManReorderModels( pMan, pRoot ); return pRoot; } ABC_NAMESPACE_IMPL_END #include "abc.h" #include "aig/gia/gia.h" ABC_NAMESPACE_IMPL_START extern Vec_Ptr_t * Abc_NtkDfsBoxes( Abc_Ntk_t * pNtk ); extern int Abc_NtkDeriveFlatGiaSop( Gia_Man_t * pGia, int * gFanins, char * pSop ); extern int Abc_NtkCheckRecursive( Abc_Ntk_t * pNtk ); /**Function************************************************************* Synopsis [Flattens the logic hierarchy of the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Au_NtkDeriveFlatGia_rec( Gia_Man_t * pGia, Au_Ntk_t * p ) { Au_Obj_t * pObj, * pTerm; int i, k, Lit = 0; Au_NtkForEachPi( p, pTerm, i ) assert( Au_ObjCopy(pTerm) >= 0 ); if ( strcmp(Au_NtkName(p), "ref_egcd") == 0 ) { printf( "Replacing one instance of recursive model \"%s\" by a black box.\n", "ref_egcd" ); Au_NtkForEachPo( p, pTerm, i ) Au_ObjSetCopy( pTerm, Gia_ManAppendCi(pGia) ); return; } Au_NtkForEachObj( p, pObj, i ) { if ( Au_ObjIsNode(pObj) ) { if ( p->pMan->pFuncs ) { int gFanins[16]; char * pSop = Abc_NamStr( p->pMan->pFuncs, pObj->Func ); assert( Au_ObjFaninNum(pObj) <= 16 ); assert( Au_ObjFaninNum(pObj) == Abc_SopGetVarNum(pSop) ); Au_ObjForEachFanin( pObj, pTerm, k ) { gFanins[k] = Au_ObjCopy(pTerm); assert( gFanins[k] >= 0 ); } Lit = Abc_NtkDeriveFlatGiaSop( pGia, gFanins, pSop ); } else { int Lit0, Lit1, Lit2; assert( pObj->Func >= 1 && pObj->Func <= 3 ); Lit0 = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin0(pObj)), Au_ObjFaninC0(pObj) ); Lit1 = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin1(pObj)), Au_ObjFaninC1(pObj) ); if ( pObj->Func == 1 ) Lit = Gia_ManHashAnd( pGia, Lit0, Lit1 ); else if ( pObj->Func == 2 ) Lit = Gia_ManHashXor( pGia, Lit0, Lit1 ); else if ( pObj->Func == 3 ) { Lit2 = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin2(pObj)), Au_ObjFaninC2(pObj) ); Lit = Gia_ManHashMux( pGia, Lit0, Lit1, Lit2 ); } else assert( 0 ); } assert( Lit >= 0 ); Au_ObjSetCopy( pObj, Lit ); } else if ( Au_ObjIsBox(pObj) ) { Au_Ntk_t * pModel = Au_ObjModel(pObj); Au_NtkCleanCopy( pModel ); // check the match between the number of actual and formal parameters assert( Au_ObjFaninNum(pObj) == Au_NtkPiNum(pModel) ); assert( Au_BoxFanoutNum(pObj) == Au_NtkPoNum(pModel) ); // assign PIs Au_ObjForEachFanin( pObj, pTerm, k ) Au_ObjSetCopy( Au_NtkPi(pModel, k), Au_ObjCopy(pTerm) ); // call recursively Au_NtkDeriveFlatGia_rec( pGia, pModel ); // assign POs Au_BoxForEachFanout( pObj, pTerm, k ) Au_ObjSetCopy( pTerm, Au_ObjCopy(Au_NtkPo(pModel, k)) ); } else if ( Au_ObjIsConst0(pObj) ) Au_ObjSetCopy( pObj, 0 ); } Au_NtkForEachPo( p, pTerm, i ) { Lit = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin0(pTerm)), Au_ObjFaninC0(pTerm) ); Au_ObjSetCopy( pTerm, Lit ); } Au_NtkForEachPo( p, pTerm, i ) assert( Au_ObjCopy(pTerm) >= 0 ); // p->pMan->nGiaObjMax = Abc_MaxInt( p->pMan->nGiaObjMax, Gia_ManObjNum(pGia) ); } /**Function************************************************************* Synopsis [Flattens the logic hierarchy of the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Au_NtkDeriveFlatGia( Au_Ntk_t * p ) { Gia_Man_t * pTemp, * pGia = NULL; Au_Obj_t * pTerm; int i; printf( "Collapsing model \"%s\"...\n", Au_NtkName(p) ); Au_NtkCleanCopy( p ); // start the network pGia = Gia_ManStart( (1<<16) ); pGia->pName = Abc_UtilStrsav( Au_NtkName(p) ); // pGia->pSpec = Abc_UtilStrsav( Au_NtkSpec(p) ); Gia_ManHashAlloc( pGia ); Gia_ManFlipVerbose( pGia ); // create PIs Au_NtkForEachPi( p, pTerm, i ) Au_ObjSetCopy( pTerm, Gia_ManAppendCi(pGia) ); // recursively flatten hierarchy Au_NtkDeriveFlatGia_rec( pGia, p ); // create POs Au_NtkForEachPo( p, pTerm, i ) Gia_ManAppendCo( pGia, Au_ObjCopy(pTerm) ); // prepare return value // Gia_ManHashProfile( pGia ); Gia_ManHashStop( pGia ); Gia_ManSetRegNum( pGia, 0 ); pGia = Gia_ManCleanup( pTemp = pGia ); Gia_ManStop( pTemp ); return pGia; } // ternary simulation #define AU_VAL0 1 #define AU_VAL1 2 #define AU_VALX 3 static inline void Au_ObjSetXsim( Au_Obj_t * pObj, int Value ) { pObj->Value = Value; } static inline int Au_ObjGetXsim( Au_Obj_t * pObj ) { return pObj->Value; } static inline int Au_XsimInv( int Value ) { if ( Value == AU_VAL0 ) return AU_VAL1; if ( Value == AU_VAL1 ) return AU_VAL0; assert( Value == AU_VALX ); return AU_VALX; } static inline int Au_XsimAnd( int Value0, int Value1 ) { if ( Value0 == AU_VAL0 || Value1 == AU_VAL0 ) return AU_VAL0; if ( Value0 == AU_VALX || Value1 == AU_VALX ) return AU_VALX; assert( Value0 == AU_VAL1 && Value1 == AU_VAL1 ); return AU_VAL1; } static inline int Au_XsimXor( int Value0, int Value1 ) { if ( Value0 == AU_VALX || Value1 == AU_VALX ) return AU_VALX; if ( (Value0 == AU_VAL0) == (Value1 == AU_VAL0) ) return AU_VAL0; return AU_VAL1; } static inline int Au_XsimMux( int ValueC, int Value1, int Value0 ) { if ( ValueC == AU_VAL0 ) return Value0; if ( ValueC == AU_VAL1 ) return Value1; if ( Value0 == AU_VAL0 && Value1 == AU_VAL0 ) return AU_VAL0; if ( Value0 == AU_VAL1 && Value1 == AU_VAL1 ) return AU_VAL1; return AU_VALX; } static inline int Au_ObjGetXsimFan0( Au_Obj_t * pObj ) { int Value = Au_ObjGetXsim( Au_ObjFanin0(pObj) ); return Au_ObjFaninC0(pObj) ? Au_XsimInv(Value) : Value; } static inline int Au_ObjGetXsimFan1( Au_Obj_t * pObj ) { int Value = Au_ObjGetXsim( Au_ObjFanin1(pObj) ); return Au_ObjFaninC1(pObj) ? Au_XsimInv(Value) : Value; } static inline int Au_ObjGetXsimFan2( Au_Obj_t * pObj ) { int Value = Au_ObjGetXsim( Au_ObjFanin2(pObj) ); return Au_ObjFaninC2(pObj) ? Au_XsimInv(Value) : Value; } /**Function************************************************************* Synopsis [Flattens the logic hierarchy of the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Au_NtkTerSimulate_rec( Au_Ntk_t * p ) { Au_Obj_t * pObj = NULL, * pTerm; int i, k; Au_NtkForEachPi( p, pTerm, i ) { assert( Au_ObjGetXsim(pTerm) > 0 ); if ( Au_ObjGetXsim(pTerm) == AU_VALX ) p->pMan->nPortsNC++; else if ( Au_ObjGetXsim(pTerm) == AU_VAL0 ) p->pMan->nPortsC0++; else p->pMan->nPortsC1++; } if ( strcmp(Au_NtkName(p), "ref_egcd") == 0 ) { printf( "Replacing one instance of recursive model \"%s\" by a black box.\n", "ref_egcd" ); Au_NtkForEachPo( p, pTerm, i ) Au_ObjSetXsim( pTerm, AU_VALX ); return; } Au_NtkForEachObj( p, pObj, i ) { if ( Au_ObjIsNode(pObj) ) { if ( pObj->Func == 1 ) Au_ObjSetXsim( pObj, Au_XsimAnd(Au_ObjGetXsimFan0(pObj), Au_ObjGetXsimFan1(pObj)) ); else if ( pObj->Func == 2 ) Au_ObjSetXsim( pObj, Au_XsimXor(Au_ObjGetXsimFan0(pObj), Au_ObjGetXsimFan1(pObj)) ); else if ( pObj->Func == 3 ) Au_ObjSetXsim( pObj, Au_XsimMux(Au_ObjGetXsimFan0(pObj), Au_ObjGetXsimFan1(pObj), Au_ObjGetXsimFan2(pObj)) ); else assert( 0 ); } else if ( Au_ObjIsBox(pObj) ) { Au_Ntk_t * pModel = Au_ObjModel(pObj); // check the match between the number of actual and formal parameters assert( Au_ObjFaninNum(pObj) == Au_NtkPiNum(pModel) ); assert( Au_BoxFanoutNum(pObj) == Au_NtkPoNum(pModel) ); // assign PIs Au_ObjForEachFanin( pObj, pTerm, k ) Au_ObjSetXsim( Au_NtkPi(pModel, k), Au_ObjGetXsim(pTerm) ); // call recursively Au_NtkTerSimulate_rec( pModel ); // assign POs Au_BoxForEachFanout( pObj, pTerm, k ) Au_ObjSetXsim( pTerm, Au_ObjGetXsim(Au_NtkPo(pModel, k)) ); } else if ( Au_ObjIsConst0(pObj) ) Au_ObjSetXsim( pObj, AU_VAL0 ); } Au_NtkForEachPo( p, pTerm, i ) Au_ObjSetXsim( pTerm, Au_ObjGetXsimFan0(pObj) ); Au_NtkForEachPo( p, pTerm, i ) { assert( Au_ObjGetXsim(pTerm) > 0 ); if ( Au_ObjGetXsim(pTerm) == AU_VALX ) p->pMan->nPortsNC++; else if ( Au_ObjGetXsim(pTerm) == AU_VAL0 ) p->pMan->nPortsC0++; else p->pMan->nPortsC1++; } } /**Function************************************************************* Synopsis [Flattens the logic hierarchy of the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Au_NtkTerSimulate( Au_Ntk_t * p ) { Au_Obj_t * pTerm; int i, Counter[2] = {0}; assert( p->pMan->pFuncs == NULL ); printf( "Collapsing model \"%s\"...\n", Au_NtkName(p) ); // create PIs Au_NtkForEachPi( p, pTerm, i ) Au_ObjSetXsim( pTerm, AU_VALX ); // recursively flatten hierarchy p->pMan->nPortsC0 = 0; p->pMan->nPortsC1 = 0; p->pMan->nPortsNC = 0; Au_NtkTerSimulate_rec( p ); // analyze outputs Au_NtkForEachPo( p, pTerm, i ) if ( Au_ObjGetXsim(pTerm) == AU_VAL0 ) Counter[0]++; else if ( Au_ObjGetXsim(pTerm) == AU_VAL1 ) Counter[1]++; // print results printf( "Const0 outputs =%15d. Const1 outputs =%15d. Total outputs =%15d.\n", Counter[0], Counter[1], Au_NtkPoNum(p) ); printf( "Const0 ports = %.0f. Const1 ports = %.0f. Non-const ports= %.0f. Total ports = %.0f.\n", p->pMan->nPortsC0, p->pMan->nPortsC1, p->pMan->nPortsNC, p->pMan->nPortsC0 + p->pMan->nPortsC1 + p->pMan->nPortsNC ); } /**Function************************************************************* Synopsis [Duplicates ABC network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Au_Ntk_t * Au_NtkDerive( Au_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vOrder ) { Au_Ntk_t * p; Au_Obj_t * pAuObj; Abc_Obj_t * pObj, * pTerm; // Vec_Ptr_t * vOrder; Vec_Int_t * vFanins; int i, k, iFunc; assert( Abc_NtkIsNetlist(pNtk) ); Abc_NtkCleanCopy( pNtk ); p = Au_NtkAlloc( pMan, Abc_NtkName(pNtk) ); // copy PIs Abc_NtkForEachPi( pNtk, pTerm, i ) Abc_ObjFanout0(pTerm)->iTemp = Au_NtkCreatePi(p); // copy nodes and boxes vFanins = Vec_IntAlloc( 100 ); // vOrder = Abc_NtkDfsBoxes( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) { Vec_IntClear( vFanins ); if ( Abc_ObjIsNode(pObj) ) { Abc_ObjForEachFanin( pObj, pTerm, k ) Vec_IntPush( vFanins, Au_Var2Lit(pTerm->iTemp, 0) ); iFunc = Abc_NamStrFindOrAdd( pMan->pFuncs, (char *)pObj->pData, NULL ); Abc_ObjFanout0(pObj)->iTemp = Au_NtkCreateNode(p, vFanins, iFunc); continue; } assert( Abc_ObjIsBox(pObj) ); Abc_ObjForEachFanin( pObj, pTerm, k ) Vec_IntPush( vFanins, Au_Var2Lit(Abc_ObjFanin0(pTerm)->iTemp, 0) ); pObj->iTemp = Au_NtkCreateBox(p, vFanins, Abc_ObjFanoutNum(pObj), ((Abc_Ntk_t *)pObj->pData)->iStep ); pAuObj = Au_NtkObj(p, pObj->iTemp); Abc_ObjForEachFanout( pObj, pTerm, k ) Abc_ObjFanout0(pTerm)->iTemp = Au_ObjFanout(pAuObj, k); } // Vec_PtrFree( vOrder ); Vec_IntFree( vFanins ); // copy POs Abc_NtkForEachPo( pNtk, pTerm, i ) Au_NtkCreatePo( p, Au_Var2Lit(Abc_ObjFanin0(pTerm)->iTemp, 0) ); // Au_NtkPrintStats( p ); return p; } Gia_Man_t * Au_ManDeriveTest( Abc_Ntk_t * pRoot ) { extern Vec_Ptr_t * Abc_NtkCollectHie( Abc_Ntk_t * pNtk ); // char * pModelName = NULL; char * pModelName = "path_0_r_x_lhs"; Gia_Man_t * pGia = NULL; Vec_Ptr_t * vOrder, * vModels; Abc_Ntk_t * pMod; Au_Man_t * pMan; Au_Ntk_t * pNtk = NULL; abctime clk1, clk2 = 0, clk3 = 0, clk = Abc_Clock(); int i; clk1 = Abc_Clock(); pMan = Au_ManAlloc( pRoot->pDesign ? pRoot->pDesign->pName : pRoot->pName ); pMan->pFuncs = Abc_NamStart( 100, 16 ); clk2 += Abc_Clock() - clk1; vModels = Abc_NtkCollectHie( pRoot ); Vec_PtrForEachEntry( Abc_Ntk_t *, vModels, pMod, i ) { vOrder = Abc_NtkDfsBoxes( pMod ); clk1 = Abc_Clock(); pNtk = Au_NtkDerive( pMan, pMod, vOrder ); pMod->iStep = pNtk->Id; pMod->pData = pNtk; clk2 += Abc_Clock() - clk1; Vec_PtrFree( vOrder ); } Vec_PtrFree( vModels ); // order models in topological order Au_ManReorderModels( pMan, pNtk ); // print statistics Au_ManPrintStats( pMan ); Au_ManCountThings( pNtk->pMan ); // select network if ( pModelName ) { pNtk = Au_ManFindNtkP( pMan, pModelName ); if ( pNtk == NULL ) printf( "Could not find module \"%s\".\n", pModelName ); } if ( pNtk == NULL ) pNtk = (Au_Ntk_t *)pRoot->pData; // if ( !Abc_NtkCheckRecursive(pRoot) ) { clk1 = Abc_Clock(); pGia = Au_NtkDeriveFlatGia( pNtk ); clk3 = Abc_Clock() - clk1; // printf( "GIA objects max = %d.\n", pMan->nGiaObjMax ); } // clk1 = Abc_Clock(); // Au_NtkSuppSizeTest( (Au_Ntk_t *)pRoot->pData ); // clk4 = Abc_Clock() - clk1; clk1 = Abc_Clock(); Au_ManDelete( pMan ); clk2 += Abc_Clock() - clk1; Abc_PrintTime( 1, "Time all ", Abc_Clock() - clk ); Abc_PrintTime( 1, "Time new ", clk2 ); Abc_PrintTime( 1, "Time GIA ", clk3 ); // Abc_PrintTime( 1, "Time supp", clk4 ); return pGia; } /**Function************************************************************* Synopsis [Performs hierarchical equivalence checking.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Abc_NtkHieCecTest2( char * pFileName, char * pModelName, int fVerbose ) { int fSimulation = 0; Gia_Man_t * pGia = NULL; Au_Ntk_t * pNtk, * pNtkClp = NULL; abctime clk1 = 0, clk = Abc_Clock(); // read hierarchical netlist pNtk = Au_NtkParseCBlif( pFileName ); if ( pNtk == NULL ) { printf( "Reading CBLIF file has failed.\n" ); return NULL; } if ( pNtk->pMan == NULL || pNtk->pMan->vNtks.pArray == NULL ) { printf( "There is no hierarchy information.\n" ); Au_NtkFree( pNtk ); return NULL; } Abc_PrintTime( 1, "Reading file", Abc_Clock() - clk ); if ( fVerbose ) { Au_ManPrintBoxInfo( pNtk ); // Au_ManPrintBoxInfoSorted( pNtk ); Au_ManPrintStats( pNtk->pMan ); } Au_ManCountThings( pNtk->pMan ); // select network if ( pModelName ) pNtkClp = Au_ManFindNtkP( pNtk->pMan, pModelName ); if ( pNtkClp == NULL ) pNtkClp = pNtk; // check if the model is recursive Au_NtkCheckRecursive( pNtkClp ); // collapse clk1 = Abc_Clock(); if ( fSimulation ) { Au_NtkTerSimulate( pNtkClp ); Abc_PrintTime( 1, "Time sim ", Abc_Clock() - clk1 ); } else { pGia = Au_NtkDeriveFlatGia( pNtkClp ); Abc_PrintTime( 1, "Time GIA ", Abc_Clock() - clk1 ); } // delete Au_ManDelete( pNtk->pMan ); Abc_PrintTime( 1, "Time all ", Abc_Clock() - clk ); return pGia; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcInt.h000066400000000000000000000037051477524141600160040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcInt.h] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Internal declarations.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifndef ABC__base__abc__abcInt_h #define ABC__base__abc__abcInt_h ABC_NAMESPACE_HEADER_START //////////////////////////////////////////////////////////////////////// /// INCLUDES /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// #define ABC_NUM_STEPS 10 //////////////////////////////////////////////////////////////////////// /// STRUCTURE DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// MACRO DEFINITIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DECLARATIONS /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_HEADER_END #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// abc-0.52/src/base/abc/abcLatch.c000066400000000000000000000611611477524141600163000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcLatch.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures working with latches.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcLatch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks if latches form self-loop.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkLatchIsSelfFeed_rec( Abc_Obj_t * pLatch, Abc_Obj_t * pLatchRoot ) { Abc_Obj_t * pFanin; assert( Abc_ObjIsLatch(pLatch) ); if ( pLatch == pLatchRoot ) return 1; pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) ) return 0; return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch ); } /**Function************************************************************* Synopsis [Checks if latches form self-loop.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch ) { Abc_Obj_t * pFanin; assert( Abc_ObjIsLatch(pLatch) ); pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) ) return 0; return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch ); } /**Function************************************************************* Synopsis [Checks if latches form self-loop.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pLatch; int i, Counter; Counter = 0; Abc_NtkForEachLatch( pNtk, pLatch, i ) { // if ( Abc_NtkLatchIsSelfFeed(pLatch) && Abc_ObjFanoutNum(pLatch) > 1 ) // printf( "Fanouts = %d.\n", Abc_ObjFanoutNum(pLatch) ); Counter += Abc_NtkLatchIsSelfFeed( pLatch ); } return Counter; } /**Function************************************************************* Synopsis [Replaces self-feeding latches by latches with constant inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pLatch, * pConst1; int i, Counter; Counter = 0; Abc_NtkForEachLatch( pNtk, pLatch, i ) { if ( Abc_NtkLatchIsSelfFeed( pLatch ) ) { if ( Abc_NtkIsStrash(pNtk) ) pConst1 = Abc_AigConst1(pNtk); else pConst1 = Abc_NtkCreateNodeConst1(pNtk); Abc_ObjPatchFanin( Abc_ObjFanin0(pLatch), Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pConst1 ); Counter++; } } return Counter; } /**Function************************************************************* Synopsis [Pipelines the network with latches.] Description [] SideEffects [Does not check the names of the added latches!!!] SeeAlso [] ***********************************************************************/ void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pFanin, * pFanout; int i, k, nTotal, nDigits; if ( nLatches < 1 ) return; nTotal = nLatches * Abc_NtkPiNum(pNtk); nDigits = Abc_Base10Log( nTotal ); vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachPi( pNtk, pObj, i ) { Abc_NodeCollectFanouts( pObj, vNodes ); 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 ); } Vec_PtrFree( vNodes ); Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); } /**Function************************************************************* Synopsis [Strashes one logic node using its SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkCollectLatchValues( Abc_Ntk_t * pNtk ) { Vec_Int_t * vValues; Abc_Obj_t * pLatch; int i; vValues = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachLatch( pNtk, pLatch, i ) Vec_IntPush( vValues, Abc_LatchIsInit1(pLatch) ); return vValues; } /**Function************************************************************* Synopsis [Derives latch init string.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_NtkCollectLatchValuesStr( Abc_Ntk_t * pNtk ) { char * pInits; Abc_Obj_t * pLatch; int i; pInits = ABC_ALLOC( char, Abc_NtkLatchNum(pNtk) + 1 ); Abc_NtkForEachLatch( pNtk, pLatch, i ) { if ( Abc_LatchIsInit0(pLatch) ) pInits[i] = '0'; else if ( Abc_LatchIsInit1(pLatch) ) pInits[i] = '1'; else if ( Abc_LatchIsInitDc(pLatch) ) pInits[i] = 'x'; else assert( 0 ); } pInits[i] = 0; return pInits; } /**Function************************************************************* Synopsis [Strashes one logic node using its SOP.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ) { Abc_Obj_t * pLatch; int i; Abc_NtkForEachLatch( pNtk, pLatch, i ) pLatch->pData = (void *)(ABC_PTRINT_T)(vValues? (Vec_IntEntry(vValues,i)? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC); } /**Function************************************************************* Synopsis [Creates latch with the given initial value.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkAddLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pDriver, Abc_InitType_t Init ) { Abc_Obj_t * pLatchOut, * pLatch, * pLatchIn; pLatchOut = Abc_NtkCreateBo(pNtk); pLatch = Abc_NtkCreateLatch(pNtk); pLatchIn = Abc_NtkCreateBi(pNtk); Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_lo" ); Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_li" ); Abc_ObjAddFanin( pLatchOut, pLatch ); Abc_ObjAddFanin( pLatch, pLatchIn ); if ( pDriver ) Abc_ObjAddFanin( pLatchIn, pDriver ); pLatch->pData = (void *)Init; return pLatchOut; } /**Function************************************************************* Synopsis [Creates MUX.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkNodeConvertToMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0, Abc_Obj_t * pMux ) { assert( Abc_NtkIsLogic(pNtk) ); Abc_ObjAddFanin( pMux, pNodeC ); Abc_ObjAddFanin( pMux, pNode1 ); Abc_ObjAddFanin( pMux, pNode0 ); if ( Abc_NtkHasSop(pNtk) ) pMux->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, "11- 1\n0-1 1\n" ); #ifdef ABC_USE_CUDD else if ( Abc_NtkHasBdd(pNtk) ) pMux->pData = Cudd_bddIte((DdManager *)pNtk->pManFunc,Cudd_bddIthVar((DdManager *)pNtk->pManFunc,0),Cudd_bddIthVar((DdManager *)pNtk->pManFunc,1),Cudd_bddIthVar((DdManager *)pNtk->pManFunc,2)), Cudd_Ref( (DdNode *)pMux->pData ); #endif else if ( Abc_NtkHasAig(pNtk) ) pMux->pData = Hop_Mux((Hop_Man_t *)pNtk->pManFunc,Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,0),Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,1),Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,2)); else assert( 0 ); } /**Function************************************************************* Synopsis [Converts registers with DC values into additional PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkConvertDcLatches( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pCtrl, * pLatch, * pMux, * pPi; Abc_InitType_t Init = ABC_INIT_ZERO; int i, fFound = 0, Counter; // check if there are latches with DC values Abc_NtkForEachLatch( pNtk, pLatch, i ) if ( Abc_LatchIsInitDc(pLatch) ) { fFound = 1; break; } if ( !fFound ) return; // add control latch pCtrl = Abc_NtkAddLatch( pNtk, Abc_NtkCreateNodeConst1(pNtk), Init ); // add fanouts for each latch with DC values Counter = 0; Abc_NtkForEachLatch( pNtk, pLatch, i ) { if ( !Abc_LatchIsInitDc(pLatch) ) continue; // change latch value pLatch->pData = (void *)Init; // if the latch output has the same name as a PO, rename it if ( Abc_NodeFindCoFanout( Abc_ObjFanout0(pLatch) ) ) { Nm_ManDeleteIdName( pLatch->pNtk->pManName, Abc_ObjFanout0(pLatch)->Id ); Abc_ObjAssignName( Abc_ObjFanout0(pLatch), Abc_ObjName(pLatch), "_lo" ); } // create new PIs pPi = Abc_NtkCreatePi( pNtk ); Abc_ObjAssignName( pPi, Abc_ObjName(pLatch), "_pi" ); // create a new node and transfer fanout from latch output to the new node pMux = Abc_NtkCreateNode( pNtk ); Abc_ObjTransferFanout( Abc_ObjFanout0(pLatch), pMux ); // convert the node into a mux Abc_NtkNodeConvertToMux( pNtk, pCtrl, Abc_ObjFanout0(pLatch), pPi, pMux ); Counter++; } printf( "The number of converted latches with DC values = %d.\n", Counter ); } /**Function************************************************************* Synopsis [Transfors the array of latch names into that of latch numbers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkConverLatchNamesIntoNumbers( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vResult, * vNames; Vec_Int_t * vNumbers; Abc_Obj_t * pObj; char * pName; int i, k, Num; if ( pNtk->vOnehots == NULL ) return NULL; // set register numbers Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->pNext = (Abc_Obj_t *)(ABC_PTRINT_T)i; // add the numbers vResult = Vec_PtrAlloc( Vec_PtrSize(pNtk->vOnehots) ); Vec_PtrForEachEntry( Vec_Ptr_t *, pNtk->vOnehots, vNames, i ) { vNumbers = Vec_IntAlloc( Vec_PtrSize(vNames) ); Vec_PtrForEachEntry( char *, vNames, pName, k ) { Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BO ); if ( Num < 0 ) continue; pObj = Abc_NtkObj( pNtk, Num ); if ( Abc_ObjFaninNum(pObj) != 1 || !Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) ) continue; Vec_IntPush( vNumbers, (int)(ABC_PTRINT_T)pObj->pNext ); } if ( Vec_IntSize( vNumbers ) > 1 ) { Vec_PtrPush( vResult, vNumbers ); printf( "Converted %d one-hot registers.\n", Vec_IntSize(vNumbers) ); } else Vec_IntFree( vNumbers ); } // clean the numbers Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->pNext = NULL; return vResult; } /**Function************************************************************* Synopsis [Converts registers with DC values into additional PIs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkConvertOnehot( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin, * pObjNew, * pObjLiNew, * pObjLoNew; int i, k, nFlops, nStates, iState, pfCompl[32]; assert( Abc_NtkIsLogic(pNtk) ); nFlops = Abc_NtkLatchNum(pNtk); if ( nFlops == 0 ) return Abc_NtkDup( pNtk ); if ( nFlops > 16 ) { 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 iState = 0; Abc_NtkForEachLatch( pNtk, pObj, i ) { if ( Abc_LatchIsInitDc(pObj) ) { printf( "Cannot process logic network with don't-care init values. Run \"zero\".\n" ); return NULL; } if ( Abc_LatchIsInit1(pObj) ) iState |= (1 << i); } // transfer logic to SOPs Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); // create new network pNtkNew = Abc_NtkStartFromNoLatches( pNtk, pNtk->ntkType, pNtk->ntkFunc ); nStates = (1 << nFlops); for ( i = 0; i < nStates; i++ ) { pObjNew = Abc_NtkCreateLatch( pNtkNew ); pObjLiNew = Abc_NtkCreateBi( pNtkNew ); pObjLoNew = Abc_NtkCreateBo( pNtkNew ); Abc_ObjAddFanin( pObjNew, pObjLiNew ); Abc_ObjAddFanin( pObjLoNew, pObjNew ); if ( i == iState ) Abc_LatchSetInit1( pObjNew ); else Abc_LatchSetInit0( pObjNew ); } Abc_NtkAddDummyBoxNames( pNtkNew ); assert( Abc_NtkLatchNum(pNtkNew) == nStates ); assert( Abc_NtkPiNum(pNtkNew) == Abc_NtkPiNum(pNtk) ); assert( Abc_NtkPoNum(pNtkNew) == Abc_NtkPoNum(pNtk) ); assert( Abc_NtkCiNum(pNtkNew) == Abc_NtkPiNum(pNtkNew) + nStates ); assert( Abc_NtkCoNum(pNtkNew) == Abc_NtkPoNum(pNtkNew) + nStates ); assert( Abc_NtkCiNum(pNtk) == Abc_NtkPiNum(pNtk) + nFlops ); assert( Abc_NtkCoNum(pNtk) == Abc_NtkPoNum(pNtk) + nFlops ); // create hot-to-log transformers for ( i = 0; i < nFlops; i++ ) { pObjNew = Abc_NtkCreateNode( pNtkNew ); for ( k = 0; k < nStates; k++ ) if ( (k >> i) & 1 ) Abc_ObjAddFanin( pObjNew, Abc_NtkCi(pNtkNew, Abc_NtkPiNum(pNtkNew)+k) ); assert( Abc_ObjFaninNum(pObjNew) == nStates/2 ); pObjNew->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNtkNew->pManFunc, nStates/2, NULL ); // save the new flop pObj = Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ); pObj->pCopy = pObjNew; } // duplicate the nodes vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { pObj->pCopy = Abc_NtkDupObj( pNtkNew, pObj, 1 ); Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } Vec_PtrFree( vNodes ); // connect the POs Abc_NtkForEachPo( pNtk, pObj, i ) Abc_ObjAddFanin( pObj->pCopy, Abc_ObjNotCond(Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj)) ); // write entries into the nodes Abc_NtkForEachCo( pNtk, pObj, i ) pObj->pCopy = Abc_ObjNotCond(Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj)); // create log-to-hot transformers for ( k = 0; k < nStates; k++ ) { pObjNew = Abc_NtkCreateNode( pNtkNew ); for ( i = 0; i < nFlops; i++ ) { pObj = Abc_NtkCo( pNtk, Abc_NtkPoNum(pNtk) + i ); Abc_ObjAddFanin( pObjNew, Abc_ObjRegular(pObj->pCopy) ); pfCompl[i] = Abc_ObjIsComplement(pObj->pCopy) ^ !((k >> i) & 1); } pObjNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, nFlops, pfCompl ); // connect it to the flop input Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, Abc_NtkPoNum(pNtkNew)+k), pObjNew ); } if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkConvertOnehot(): Network check has failed.\n" ); return pNtkNew; } ABC_NAMESPACE_IMPL_END #include "aig/gia/giaAig.h" ABC_NAMESPACE_IMPL_START /**Function************************************************************* Synopsis [Performs retiming with classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Abc_NtkRetimeWithClassesAig( Aig_Man_t * pMan, Vec_Int_t * vClasses, Vec_Int_t ** pvClasses, int fVerbose ) { Aig_Man_t * pManNew; Gia_Man_t * pGia, * pGiaNew; pGia = Gia_ManFromAigSimple( pMan ); assert( Gia_ManRegNum(pGia) == Vec_IntSize(vClasses) ); pGia->vFlopClasses = vClasses; pGiaNew = Gia_ManRetimeForward( pGia, 10, fVerbose ); *pvClasses = pGiaNew->vFlopClasses; pGiaNew->vFlopClasses = NULL; pManNew = Gia_ManToAig( pGiaNew, 0 ); Gia_ManStop( pGiaNew ); Gia_ManStop( pGia ); return pManNew; } /**Function************************************************************* Synopsis [Performs retiming with classes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkRetimeWithClassesNtk( Abc_Ntk_t * pNtk, Vec_Int_t * vClasses, Vec_Int_t ** pvClasses, int fVerbose ) { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); extern Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ); Abc_Ntk_t * pNtkAig, * pNtkAigRet, * pNtkRes; Aig_Man_t * pMan, * pManNew; pNtkAig = Abc_NtkStrash( pNtk, 0, 1, 0 ); pMan = Abc_NtkToDar( pNtkAig, 0, 1 ); pManNew = Abc_NtkRetimeWithClassesAig( pMan, vClasses, pvClasses, fVerbose ); pNtkAigRet = Abc_NtkFromDarSeqSweep( pNtkAig, pManNew ); pNtkRes = Abc_NtkToLogic( pNtkAigRet ); Abc_NtkDelete( pNtkAigRet ); Abc_NtkDelete( pNtkAig ); Aig_ManStop( pManNew ); Aig_ManStop( pMan ); return pNtkRes; } /**Function************************************************************* Synopsis [Returns self-loops back into the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTransformBack( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, Vec_Ptr_t * vControls, Vec_Int_t * vClasses ) { Abc_Obj_t * pObj, * pNodeNew, * pCtrl, * pDriver; int i, Class; assert( Abc_NtkPoNum(pNtkOld) == Abc_NtkPoNum(pNtkNew) ); // match the POs of the old into new Abc_NtkForEachPo( pNtkOld, pObj, i ) pObj->pCopy = Abc_NtkPo( pNtkNew, i ); // remap the flops Vec_PtrForEachEntry( Abc_Obj_t *, vControls, pObj, i ) { assert( Abc_ObjIsPo(pObj) && pObj->pNtk == pNtkOld ); Vec_PtrWriteEntry( vControls, i, pObj->pCopy ); } // create self-loops assert( Abc_NtkLatchNum(pNtkNew) == Vec_IntSize(vClasses) ); Abc_NtkForEachLatch( pNtkNew, pObj, i ) { Class = Vec_IntEntry( vClasses, i ); if ( Class == -1 ) continue; pDriver = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); pCtrl = (Abc_Obj_t *)Vec_PtrEntry( vControls, Class ); pCtrl = Abc_ObjFanin0( pCtrl ); pNodeNew = Abc_NtkCreateNode( pNtkNew ); Abc_ObjAddFanin( pNodeNew, pCtrl ); Abc_ObjAddFanin( pNodeNew, pDriver ); Abc_ObjAddFanin( pNodeNew, Abc_ObjFanout0(pObj) ); Abc_ObjSetData( pNodeNew, Abc_SopRegister((Mem_Flex_t *)pNtkNew->pManFunc, "0-1 1\n11- 1\n") ); Abc_ObjPatchFanin( Abc_ObjFanin0(pObj), pDriver, pNodeNew ); } // remove the useless POs Vec_PtrForEachEntry( Abc_Obj_t *, vControls, pObj, i ) Abc_NtkDeleteObj( pObj ); } /**Function************************************************************* Synopsis [Classify flops.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCRetime( Abc_Ntk_t * pNtk, int fVerbose ) { Abc_Ntk_t * pNtkNew; Vec_Ptr_t * vControls; Vec_Int_t * vFlopClasses, * vFlopClassesNew; Abc_Obj_t * pObj, * pDriver, * pFlopOut, * pObjPo; int i, iFlop, CountN = 0, Count2 = 0, Count1 = 0, Count0 = 0; // duplicate the AIG pNtk = Abc_NtkDup( pNtk ); // update registers vControls = Vec_PtrAlloc( 100 ); vFlopClasses = Vec_IntAlloc( 100 ); Abc_NtkForEachLatch( pNtk, pObj, i ) { pFlopOut = Abc_ObjFanout0(pObj); pDriver = Abc_ObjFanin0( Abc_ObjFanin0(pObj) ); if ( Abc_ObjFaninNum(pDriver) != 3 ) { Vec_IntPush( vFlopClasses, -1 ); CountN++; continue; } if ( Abc_ObjFanin(pDriver, 1) != pFlopOut && Abc_ObjFanin(pDriver, 2) != pFlopOut ) { Vec_IntPush( vFlopClasses, -1 ); Count2++; continue; } if ( Abc_ObjFanin(pDriver, 1) == pFlopOut ) { Vec_IntPush( vFlopClasses, -1 ); Count1++; continue; } assert( Abc_ObjFanin(pDriver, 2) == pFlopOut ); Count0++; Vec_PtrPushUnique( vControls, Abc_ObjFanin0(pDriver) ); // set the flop class iFlop = Vec_PtrFind( vControls, Abc_ObjFanin0(pDriver) ); Vec_IntPush( vFlopClasses, iFlop ); // update Abc_ObjPatchFanin( Abc_ObjFanin0(pObj), pDriver, Abc_ObjFanin(pDriver, 1) ); } if ( Count1 ) printf( "Opposite phase enable is present in %d flops (out of %d).\n", Count1, Abc_NtkLatchNum(pNtk) ); if ( fVerbose ) printf( "CountN = %4d. Count2 = %4d. Count1 = %4d. Count0 = %4d. Ctrls = %d.\n", CountN, Count2, Count1, Count0, Vec_PtrSize(vControls) ); // add the controls to the list of POs Vec_PtrForEachEntry( Abc_Obj_t *, vControls, pObj, i ) { pObjPo = Abc_NtkCreatePo( pNtk ); Abc_ObjAddFanin( pObjPo, pObj ); Abc_ObjAssignName( pObjPo, Abc_ObjName(pObjPo), NULL ); Vec_PtrWriteEntry( vControls, i, pObjPo ); } Abc_NtkOrderCisCos( pNtk ); Abc_NtkCleanup( pNtk, fVerbose ); // performs retiming with classes pNtkNew = Abc_NtkRetimeWithClassesNtk( pNtk, vFlopClasses, &vFlopClassesNew, fVerbose ); Abc_NtkTransformBack( pNtk, pNtkNew, vControls, vFlopClassesNew ); // assert( Abc_NtkPoNum(pNtkNew) == Abc_NtkPoNum(pNtk) ); Abc_NtkDelete( pNtk ); Vec_PtrFree( vControls ); // Vec_IntFree( vFlopClasses ); Vec_IntFree( vFlopClassesNew ); return pNtkNew; } /**Function************************************************************* Synopsis [Resimulates CEX and return the ID of the PO that failed.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkVerifyCex( Abc_Ntk_t * pNtk, Abc_Cex_t * p ) { Abc_Obj_t * pObj; int RetValue, i, k, iBit = 0; assert( Abc_NtkIsStrash(pNtk) ); assert( p->nPis == Abc_NtkPiNum(pNtk) ); // assert( p->nRegs == Abc_NtkLatchNum(pNtk) ); Abc_NtkCleanMarkC( pNtk ); Abc_AigConst1(pNtk)->fMarkC = 1; // initialize flops Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjFanout0(pObj)->fMarkC = Abc_InfoHasBit(p->pData, iBit++); // simulate timeframes iBit = p->nRegs; for ( i = 0; i <= p->iFrame; i++ ) { Abc_NtkForEachPi( pNtk, pObj, k ) pObj->fMarkC = Abc_InfoHasBit(p->pData, iBit++); Abc_NtkForEachNode( pNtk, pObj, k ) pObj->fMarkC = (Abc_ObjFanin0(pObj)->fMarkC ^ Abc_ObjFaninC0(pObj)) & (Abc_ObjFanin1(pObj)->fMarkC ^ Abc_ObjFaninC1(pObj)); Abc_NtkForEachCo( pNtk, pObj, k ) pObj->fMarkC = Abc_ObjFanin0(pObj)->fMarkC ^ Abc_ObjFaninC0(pObj); Abc_NtkForEachLatch( pNtk, pObj, k ) Abc_ObjFanout0(pObj)->fMarkC = Abc_ObjFanin0(pObj)->fMarkC; } assert( iBit == p->nBits ); // figure out the number of failed output RetValue = -1; Abc_NtkForEachPo( pNtk, pObj, i ) { if ( pObj->fMarkC ) { RetValue = i; break; } } Abc_NtkCleanMarkC( pNtk ); return RetValue; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcLib.c000066400000000000000000000264721477524141600157610ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcLib.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Functions to manipulate verilog libraries.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Create the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Des_t * Abc_DesCreate( char * pName ) { Abc_Des_t * p; p = ABC_ALLOC( Abc_Des_t, 1 ); memset( p, 0, sizeof(Abc_Des_t) ); p->pName = Abc_UtilStrsav( pName ); p->tModules = st__init_table( strcmp, st__strhash ); p->vTops = Vec_PtrAlloc( 100 ); p->vModules = Vec_PtrAlloc( 100 ); p->pManFunc = Hop_ManStart(); p->pLibrary = NULL; return p; } /**Function************************************************************* Synopsis [Removes all pointers to the manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_DesCleanManPointer( Abc_Des_t * p, void * pMan ) { Abc_Ntk_t * pTemp; int i; if ( p == NULL ) return; if ( p->pManFunc == pMan ) p->pManFunc = NULL; Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pTemp, i ) if ( pTemp->pManFunc == pMan ) pTemp->pManFunc = NULL; } /**Function************************************************************* Synopsis [Frees the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_DesFree( Abc_Des_t * p, Abc_Ntk_t * pNtkSave ) { Abc_Ntk_t * pNtk; int i; if ( p->pName ) ABC_FREE( p->pName ); if ( p->pManFunc ) Hop_ManStop( (Hop_Man_t *)p->pManFunc ); if ( p->tModules ) st__free_table( p->tModules ); if ( p->vModules ) { Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtk, i ) { if ( pNtk == pNtkSave ) continue; pNtk->pDesign = NULL; if ( (pNtkSave && pNtk->pManFunc == pNtkSave->pManFunc) || (pNtk->pManFunc == p->pManFunc) ) pNtk->pManFunc = NULL; Abc_NtkDelete( pNtk ); } Vec_PtrFree( p->vModules ); } if ( p->vTops ) Vec_PtrFree( p->vTops ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Duplicated the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Des_t * Abc_DesDup( Abc_Des_t * p ) { Abc_Des_t * pNew; Abc_Ntk_t * pTemp; Abc_Obj_t * pObj; int i, k; pNew = Abc_DesCreate( p->pName ); Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pTemp, i ) Abc_DesAddModel( pNew, Abc_NtkDup(pTemp) ); Vec_PtrForEachEntry( Abc_Ntk_t *, p->vTops, pTemp, i ) Vec_PtrPush( pNew->vTops, pTemp->pCopy ); Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pTemp, i ) pTemp->pCopy->pAltView = pTemp->pAltView ? pTemp->pAltView->pCopy : NULL; // update box models Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pTemp, i ) Abc_NtkForEachBox( pTemp, pObj, k ) if ( Abc_ObjIsWhitebox(pObj) || Abc_ObjIsBlackbox(pObj) ) pObj->pCopy->pData = Abc_ObjModel(pObj)->pCopy; return pNew; } /**Function************************************************************* Synopsis [Frees the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Des_t * Abc_DesDupBlackboxes( Abc_Des_t * p, Abc_Ntk_t * pNtkSave ) { Abc_Des_t * pNew; Abc_Ntk_t * pNtkTemp; int i; assert( Vec_PtrSize(p->vTops) > 0 ); assert( Vec_PtrSize(p->vModules) > 1 ); pNew = Abc_DesCreate( p->pName ); // pNew->pManFunc = pNtkSave->pManFunc; Vec_PtrPush( pNew->vTops, pNtkSave ); Vec_PtrPush( pNew->vModules, pNtkSave ); Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtkTemp, i ) if ( Abc_NtkHasBlackbox( pNtkTemp ) ) Vec_PtrPush( pNew->vModules, Abc_NtkDup(pNtkTemp) ); return pNew; } /**Function************************************************************* Synopsis [Prints the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_DesPrint( Abc_Des_t * p ) { Abc_Ntk_t * pNtk; Abc_Obj_t * pObj; int i, k; printf( "Models of design %s:\n", p->pName ); Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtk, i ) { printf( "%2d : %20s ", i+1, pNtk->pName ); printf( "nd = %6d lat = %6d whitebox = %3d blackbox = %3d\n", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk), Abc_NtkWhiteboxNum(pNtk), Abc_NtkBlackboxNum(pNtk) ); if ( Abc_NtkBlackboxNum(pNtk) == 0 ) continue; Abc_NtkForEachWhitebox( pNtk, pObj, k ) printf( " %20s (whitebox)\n", Abc_NtkName((Abc_Ntk_t *)pObj->pData) ); Abc_NtkForEachBlackbox( pNtk, pObj, k ) printf( " %20s (blackbox)\n", Abc_NtkName((Abc_Ntk_t *)pObj->pData) ); } } /**Function************************************************************* Synopsis [Create the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_DesAddModel( Abc_Des_t * p, Abc_Ntk_t * pNtk ) { if ( st__is_member( p->tModules, (char *)pNtk->pName ) ) return 0; st__insert( p->tModules, (char *)pNtk->pName, (char *)pNtk ); assert( pNtk->Id == 0 ); pNtk->Id = Vec_PtrSize(p->vModules); Vec_PtrPush( p->vModules, pNtk ); pNtk->pDesign = p; return 1; } /**Function************************************************************* Synopsis [Create the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_DesFindModelByName( Abc_Des_t * p, char * pName ) { Abc_Ntk_t * pNtk; if ( ! st__is_member( p->tModules, (char *)pName ) ) return NULL; st__lookup( p->tModules, (char *)pName, (char **)&pNtk ); return pNtk; } /**Function************************************************************* Synopsis [Frees the library.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_DesDeriveRoot( Abc_Des_t * p ) { Abc_Ntk_t * pNtk; if ( Vec_PtrSize(p->vModules) > 1 ) { printf( "The design includes more than one module and is currently not used.\n" ); return NULL; } pNtk = (Abc_Ntk_t *)Vec_PtrEntry( p->vModules, 0 ); Vec_PtrClear( p->vModules ); pNtk->pManFunc = p->pManFunc; p->pManFunc = NULL; return pNtk; } /**Function************************************************************* Synopsis [Detects the top-level models.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_DesFindTopLevelModels( Abc_Des_t * p ) { Abc_Ntk_t * pNtk, * pNtkBox; Abc_Obj_t * pObj; int i, k; assert( Vec_PtrSize( p->vModules ) > 0 ); // clear the models Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtk, i ) pNtk->fHieVisited = 0; // mark all the models reachable from other models Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtk, i ) { Abc_NtkForEachBox( pNtk, pObj, k ) { if ( Abc_ObjIsLatch(pObj) ) continue; if ( pObj->pData == NULL ) continue; pNtkBox = (Abc_Ntk_t *)pObj->pData; pNtkBox->fHieVisited = 1; } } // collect the models that are not marked Vec_PtrClear( p->vTops ); Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtk, i ) { if ( pNtk->fHieVisited == 0 ) Vec_PtrPush( p->vTops, pNtk ); else pNtk->fHieVisited = 0; } return Vec_PtrSize( p->vTops ); } /**Function************************************************************* Synopsis [Derive the AIG of the logic in the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeStrashUsingNetwork_rec( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; assert( !Abc_ObjIsNet(pObj) ); if ( pObj->pCopy ) return; // call for the fanins Abc_ObjForEachFanin( pObj, pFanin, i ) Abc_NodeStrashUsingNetwork_rec( pNtkAig, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)) ); // compute for the node pObj->pCopy = Abc_NodeStrash( pNtkAig, pObj, 0 ); // set for the fanout net Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; } /**Function************************************************************* Synopsis [Derive the AIG of the logic in the netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeStrashUsingNetwork( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pBox ) { Abc_Ntk_t * pNtkGate; Abc_Obj_t * pObj; unsigned * pPolarity; int i, fCompl; assert( Abc_ObjIsBox(pBox) ); pNtkGate = (Abc_Ntk_t *)pBox->pData; pPolarity = (unsigned *)pBox->pNext; assert( Abc_NtkIsNetlist(pNtkGate) ); assert( Abc_NtkLatchNum(pNtkGate) == 0 ); Abc_NtkCleanCopy( pNtkGate ); // set the PI values Abc_NtkForEachPi( pNtkGate, pObj, i ) { fCompl = (pPolarity && Abc_InfoHasBit(pPolarity, i)); pObj->pCopy = Abc_ObjNotCond( Abc_ObjFanin(pBox,i)->pCopy, fCompl ); Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; } // build recursively and set the PO values Abc_NtkForEachPo( pNtkGate, pObj, i ) { Abc_NodeStrashUsingNetwork_rec( pNtkAig, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)) ); Abc_ObjFanout(pBox,i)->pCopy = Abc_ObjFanin0(pObj)->pCopy; } //printf( "processing %d\n", pBox->Id ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcMinBase.c000066400000000000000000000734541477524141600165730ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcMinBase.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Makes nodes of the network minimum base.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcMinBase.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD extern int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Makes nodes minimum base.] Description [Returns the number of changed nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, Counter; assert( Abc_NtkIsBddLogic(pNtk) ); Counter = 0; Abc_NtkForEachNode( pNtk, pNode, i ) Counter += Abc_NodeMinimumBase( pNode ); return Counter; } /**Function************************************************************* Synopsis [Makes one node minimum base.] Description [Returns 1 if the node is changed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeMinimumBase_buggy( Abc_Obj_t * pNode ) { Vec_Str_t * vSupport; Vec_Ptr_t * vFanins; DdNode * bTemp; int i, nVars; 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 vFanins = Vec_PtrAlloc( Abc_ObjFaninNum(pNode) ); Abc_NodeCollectFanins( pNode, vFanins ); for ( i = 0; i < vFanins->nSize; i++ ) if ( vSupport->pArray[i] == 0 ) Abc_ObjDeleteFanin( pNode, (Abc_Obj_t *)vFanins->pArray[i] ); assert( nVars == Abc_ObjFaninNum(pNode) ); // update the function of the node pNode->pData = Extra_bddRemapUp( (DdManager *)pNode->pNtk->pManFunc, bTemp = (DdNode *)pNode->pData ); Cudd_Ref( (DdNode *)pNode->pData ); Cudd_RecursiveDeref( (DdManager *)pNode->pNtk->pManFunc, bTemp ); Vec_PtrFree( vFanins ); Vec_StrFree( vSupport ); 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.] Description [Returns the number of pairs of duplicated fanins.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, Counter; assert( Abc_NtkIsBddLogic(pNtk) ); Counter = 0; Abc_NtkForEachNode( pNtk, pNode, i ) Counter += Abc_NodeRemoveDupFanins( pNode ); return Counter; } /**Function************************************************************* Synopsis [Removes one pair of duplicated fanins if present.] Description [Returns 1 if the node is changed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeRemoveDupFanins_int( Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin1, * pFanin2; int i, k; assert( Abc_NtkIsBddLogic(pNode->pNtk) ); assert( Abc_ObjIsNode(pNode) ); // make sure fanins are not duplicated Abc_ObjForEachFanin( pNode, pFanin2, i ) { Abc_ObjForEachFanin( pNode, pFanin1, k ) { if ( k >= i ) break; if ( pFanin1 == pFanin2 ) { DdManager * dd = (DdManager *)pNode->pNtk->pManFunc; DdNode * bVar1 = Cudd_bddIthVar( dd, i ); DdNode * bVar2 = Cudd_bddIthVar( dd, k ); DdNode * bTrans, * bTemp; bTrans = Cudd_bddXnor( dd, bVar1, bVar2 ); Cudd_Ref( bTrans ); pNode->pData = Cudd_bddAndAbstract( dd, bTemp = (DdNode *)pNode->pData, bTrans, bVar2 ); Cudd_Ref( (DdNode *)pNode->pData ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bTrans ); Abc_NodeMinimumBase( pNode ); return 1; } } } return 0; } /**Function************************************************************* Synopsis [Removes duplicated fanins if present.] Description [Returns the number of fanins removed.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode ) { int Counter = 0; while ( Abc_NodeRemoveDupFanins_int(pNode) ) Counter++; return Counter; } /**Function************************************************************* Synopsis [Computes support of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeSupport_rec( DdNode * bFunc, Vec_Str_t * vSupport ) { if ( cuddIsConstant(bFunc) || Cudd_IsComplement(bFunc->next) ) return; vSupport->pArray[ bFunc->index ] = 1; Abc_NodeSupport_rec( cuddT(bFunc), vSupport ); Abc_NodeSupport_rec( Cudd_Regular(cuddE(bFunc)), vSupport ); bFunc->next = Cudd_Not(bFunc->next); } /**Function************************************************************* Synopsis [Computes support of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeSupportClear_rec( DdNode * bFunc ) { if ( !Cudd_IsComplement(bFunc->next) ) return; bFunc->next = Cudd_Regular(bFunc->next); if ( cuddIsConstant(bFunc) ) return; Abc_NodeSupportClear_rec( cuddT(bFunc) ); Abc_NodeSupportClear_rec( Cudd_Regular(cuddE(bFunc)) ); } /**Function************************************************************* Synopsis [Computes support of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars ) { int Counter, i; // compute the support by marking the BDD Vec_StrFill( vSupport, nVars, 0 ); Abc_NodeSupport_rec( bFunc, vSupport ); // clear the marak Abc_NodeSupportClear_rec( bFunc ); // get the number of support variables Counter = 0; for ( i = 0; i < nVars; i++ ) Counter += vSupport->pArray[i]; return Counter; } /**Function************************************************************* Synopsis [Find the number of unique variables after collapsing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCheckDupFanin( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, int * piFanin ) { Abc_Obj_t * pObj; int i, Counter = 0; Abc_ObjForEachFanin( pFanout, pObj, i ) if ( pObj == pFanin ) { if ( piFanin ) *piFanin = i; Counter++; } return Counter; } /**Function************************************************************* Synopsis [Find the number of unique variables after collapsing.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCollapseSuppSize( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins ) { Abc_Obj_t * pObj; int i; Vec_PtrClear( vFanins ); Abc_ObjForEachFanin( pFanout, pObj, i ) if ( pObj != pFanin ) Vec_PtrPushUnique( vFanins, pObj ); Abc_ObjForEachFanin( pFanin, pObj, i ) Vec_PtrPushUnique( vFanins, pObj ); return Vec_PtrSize( vFanins ); } /**Function************************************************************* Synopsis [Returns the index of the new fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjFaninNumberNew( Vec_Ptr_t * vFanins, Abc_Obj_t * pFanin ) { Abc_Obj_t * pObj; int i; Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) if ( pObj == pFanin ) return i; return -1; } /**Function************************************************************* Synopsis [Find the permutation map for the given node into the new order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCollapsePermMap( Abc_Obj_t * pNode, Abc_Obj_t * pSkip, Vec_Ptr_t * vFanins, int * pPerm ) { Abc_Obj_t * pFanin; int i; for ( i = 0; i < Vec_PtrSize(vFanins); i++ ) pPerm[i] = i; Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( pFanin == pSkip ) continue; pPerm[i] = Abc_ObjFaninNumberNew( vFanins, pFanin ); if ( pPerm[i] == -1 ) return 0; } return 1; } /**Function************************************************************* Synopsis [Eliminates the nodes into their fanouts if the node size does not exceed this number.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NodeCollapseFunc( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout ) { DdManager * dd = (DdManager *)pFanin->pNtk->pManFunc; DdNode * bVar, * bFunc0, * bFunc1, * bTemp, * bFanin, * bFanout; int RetValue, nSize, iFanin; // can only eliminate if fanin occurs in the fanin list of the fanout exactly once if ( Abc_NodeCheckDupFanin( pFanin, pFanout, &iFanin ) != 1 ) return NULL; // find the new number of fanins after collapsing nSize = Abc_NodeCollapseSuppSize( pFanin, pFanout, vFanins ); bVar = Cudd_bddIthVar( dd, nSize - 1 ); assert( nSize <= dd->size ); // find the permutation after collapsing RetValue = Abc_NodeCollapsePermMap( pFanin, NULL, vFanins, pPermFanin ); assert( RetValue ); RetValue = Abc_NodeCollapsePermMap( pFanout, pFanin, vFanins, pPermFanout ); assert( RetValue ); // cofactor the local function of the node bVar = Cudd_bddIthVar( dd, iFanin ); bFunc0 = Cudd_Cofactor( dd, (DdNode *)pFanout->pData, Cudd_Not(bVar) ); Cudd_Ref( bFunc0 ); bFunc1 = Cudd_Cofactor( dd, (DdNode *)pFanout->pData, bVar ); Cudd_Ref( bFunc1 ); // find the permutation after collapsing bFunc0 = Cudd_bddPermute( dd, bTemp = bFunc0, pPermFanout ); Cudd_Ref( bFunc0 ); Cudd_RecursiveDeref( dd, bTemp ); bFunc1 = Cudd_bddPermute( dd, bTemp = bFunc1, pPermFanout ); Cudd_Ref( bFunc1 ); Cudd_RecursiveDeref( dd, bTemp ); bFanin = Cudd_bddPermute( dd, (DdNode *)pFanin->pData, pPermFanin ); Cudd_Ref( bFanin ); // create the new function bFanout = Cudd_bddIte( dd, bFanin, bFunc1, bFunc0 ); Cudd_Ref( bFanout ); Cudd_RecursiveDeref( dd, bFanin ); Cudd_RecursiveDeref( dd, bFunc1 ); Cudd_RecursiveDeref( dd, bFunc0 ); Cudd_Deref( bFanout ); return bFanout; } int Abc_NodeCollapse( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout ) { Abc_Obj_t * pFanoutNew, * pObj; DdNode * bFanoutNew; int i; assert( Abc_NtkIsBddLogic(pFanin->pNtk) ); assert( Abc_ObjIsNode(pFanin) ); assert( Abc_ObjIsNode(pFanout) ); bFanoutNew = Abc_NodeCollapseFunc( pFanin, pFanout, vFanins, pPermFanin, pPermFanout ); if ( bFanoutNew == NULL ) return 0; Cudd_Ref( bFanoutNew ); // create the new node pFanoutNew = Abc_NtkCreateNode( pFanin->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) Abc_ObjAddFanin( pFanoutNew, pObj ); pFanoutNew->pData = bFanoutNew; // minimize the node Abc_NodeMinimumBase( pFanoutNew ); // transfer the fanout Abc_ObjTransferFanout( pFanout, pFanoutNew ); assert( Abc_ObjFanoutNum( pFanout ) == 0 ); Abc_NtkDeleteObj_rec( pFanout, 1 ); return 1; } int Abc_NtkEliminate( Abc_Ntk_t * pNtk, int nMaxSize, int fReverse, int fVerbose ) { extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); Vec_Ptr_t * vFanouts, * vFanins, * vNodes; Abc_Obj_t * pNode, * pFanout; int * pPermFanin, * pPermFanout; int RetValue, i, k; assert( nMaxSize > 0 ); assert( Abc_NtkIsLogic(pNtk) ); // convert network to BDD representation if ( !Abc_NtkToBdd(pNtk) ) { fprintf( stdout, "Converting to BDD has failed.\n" ); return 0; } // prepare nodes for sweeping //Abc_NtkRemoveDupFanins( pNtk ); Abc_NtkMinimumBase( pNtk ); Abc_NtkCleanup( pNtk, 0 ); // get the nodes in the given order vNodes = fReverse? Abc_NtkDfsReverse( pNtk ) : Abc_NtkDfs( pNtk, 0 ); // go through the nodes and decide is they can be eliminated pPermFanin = ABC_ALLOC( int, nMaxSize + 1000 ); pPermFanout = ABC_ALLOC( int, nMaxSize + 1000 ); vFanins = Vec_PtrAlloc( 1000 ); vFanouts = Vec_PtrAlloc( 1000 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( !Abc_ObjIsNode(pNode) ) // skip deleted nodes continue; if ( Abc_NodeFindCoFanout(pNode) != NULL ) continue; if ( Abc_ObjFaninNum(pNode) > nMaxSize ) continue; Abc_ObjForEachFanout( pNode, pFanout, k ) if ( Abc_NodeCollapseSuppSize(pNode, pFanout, vFanins) > nMaxSize ) break; if ( k < Abc_ObjFanoutNum(pNode) ) continue; // perform elimination Abc_NodeCollectFanouts( pNode, vFanouts ); Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, k ) { if ( fVerbose ) printf( "Collapsing fanin %5d (supp =%2d) into fanout %5d (supp =%2d) ", Abc_ObjId(pNode), Abc_ObjFaninNum(pNode), Abc_ObjId(pFanout), Abc_ObjFaninNum(pFanout) ); RetValue = Abc_NodeCollapse( pNode, pFanout, vFanins, pPermFanin, pPermFanout ); assert( RetValue ); if ( fVerbose ) { Abc_Obj_t * pNodeNew = Abc_NtkObj( pNtk, Abc_NtkObjNumMax(pNtk) - 1 ); if ( pNodeNew ) printf( "resulting in node %5d (supp =%2d).\n", Abc_ObjId(pNodeNew), Abc_ObjFaninNum(pNodeNew) ); } } } Abc_NtkBddReorder( pNtk, 0 ); Vec_PtrFree( vFanins ); Vec_PtrFree( vFanouts ); Vec_PtrFree( vNodes ); ABC_FREE( pPermFanin ); ABC_FREE( pPermFanout ); return 1; } /**Function************************************************************* Synopsis [Check how many times fanin appears in the FF of the fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCountAppearances( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout ) { Hop_Man_t * pMan = (Hop_Man_t *)pFanin->pNtk->pManFunc; int iFanin = Abc_NodeFindFanin( pFanout, pFanin ); assert( iFanin >= 0 && iFanin < Hop_ManPiNum(pMan) ); return Hop_ObjFanoutCount( (Hop_Obj_t *)pFanout->pData, Hop_IthVar(pMan, iFanin) ); } int Abc_NodeCountAppearancesAll( Abc_Obj_t * pNode ) { Abc_Obj_t * pFanout; int i, Count = 0; Abc_ObjForEachFanout( pNode, pFanout, i ) Count += Abc_NodeCountAppearances( pNode, pFanout ); return Count; } /**Function************************************************************* Synopsis [Performs traditional eliminate -1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Abc_NodeCollapseFunc1( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout ) { Hop_Man_t * pMan = (Hop_Man_t *)pFanin->pNtk->pManFunc; Hop_Obj_t * bFanin, * bFanout; int RetValue, nSize, iFanin; // can only eliminate if fanin occurs in the fanin list of the fanout exactly once if ( Abc_NodeCheckDupFanin( pFanin, pFanout, &iFanin ) != 1 ) return NULL; // find the new number of fanins after collapsing nSize = Abc_NodeCollapseSuppSize( pFanin, pFanout, vFanins ); Hop_IthVar( pMan, nSize ); // use additional var for fanin variable assert( nSize + 1 <= Hop_ManPiNum(pMan) ); // find the permutation after collapsing RetValue = Abc_NodeCollapsePermMap( pFanin, NULL, vFanins, pPermFanin ); assert( RetValue ); RetValue = Abc_NodeCollapsePermMap( pFanout, pFanin, vFanins, pPermFanout ); assert( RetValue ); // include fanin's variable pPermFanout[iFanin] = nSize; // create new function of fanin and fanout bFanin = Hop_Permute( pMan, (Hop_Obj_t *)pFanin->pData, Abc_ObjFaninNum(pFanin), pPermFanin ); bFanout = Hop_Permute( pMan, (Hop_Obj_t *)pFanout->pData, Abc_ObjFaninNum(pFanout), pPermFanout ); // compose fanin into fanout return Hop_Compose( pMan, bFanout, bFanin, nSize ); } int Abc_NodeCollapse1( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout ) { Abc_Obj_t * pFanoutNew, * pObj; Hop_Obj_t * bFanoutNew; int i; assert( Abc_NtkIsAigLogic(pFanin->pNtk) ); assert( Abc_ObjIsNode(pFanin) ); assert( Abc_ObjIsNode(pFanout) ); bFanoutNew = Abc_NodeCollapseFunc1( pFanin, pFanout, vFanins, pPermFanin, pPermFanout ); if ( bFanoutNew == NULL ) return 0; // create the new node pFanoutNew = Abc_NtkCreateNode( pFanin->pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) Abc_ObjAddFanin( pFanoutNew, pObj ); pFanoutNew->pData = bFanoutNew; // transfer the fanout Abc_ObjTransferFanout( pFanout, pFanoutNew ); assert( Abc_ObjFanoutNum( pFanout ) == 0 ); Abc_NtkDeleteObj_rec( pFanout, 1 ); return 1; } int Abc_NodeIsExor( Abc_Obj_t * pNode ) { Hop_Man_t * pMan; word Truth; if ( Abc_ObjFaninNum(pNode) < 3 || Abc_ObjFaninNum(pNode) > 6 ) return 0; pMan = (Hop_Man_t *)pNode->pNtk->pManFunc; Truth = Hop_ManComputeTruth6( pMan, (Hop_Obj_t *)pNode->pData, Abc_ObjFaninNum(pNode) ); if ( Truth == 0x6666666666666666 || Truth == 0x9999999999999999 || Truth == 0x9696969696969696 || Truth == 0x6969696969696969 || Truth == 0x6996699669966996 || Truth == 0x9669966996699669 || Truth == 0x9669699696696996 || Truth == 0x6996966969969669 || Truth == 0x6996966996696996 || Truth == 0x9669699669969669 ) return 1; return 0; } int Abc_NtkEliminate1One( Abc_Ntk_t * pNtk, int ElimValue, int nMaxSize, int fReverse, int fVerbose ) { Vec_Ptr_t * vFanouts, * vFanins, * vNodes; Abc_Obj_t * pNode, * pFanout; int * pPermFanin, * pPermFanout; int RetValue, i, k; assert( nMaxSize > 0 ); assert( Abc_NtkIsLogic(pNtk) ); // convert network to BDD representation if ( !Abc_NtkToAig(pNtk) ) { fprintf( stdout, "Converting to AIG has failed.\n" ); return 0; } // get the nodes in the given order vNodes = fReverse? Abc_NtkDfsReverse( pNtk ) : Abc_NtkDfs( pNtk, 0 ); // go through the nodes and decide is they can be eliminated pPermFanin = ABC_ALLOC( int, nMaxSize + 1000 ); pPermFanout = ABC_ALLOC( int, nMaxSize + 1000 ); vFanins = Vec_PtrAlloc( 1000 ); vFanouts = Vec_PtrAlloc( 1000 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( !Abc_ObjIsNode(pNode) ) // skip deleted nodes continue; if ( Abc_NodeFindCoFanout(pNode) != NULL ) continue; if ( Abc_ObjFaninNum(pNode) > nMaxSize ) continue; if ( Abc_NodeIsExor(pNode) ) continue; // skip nodes with more than one fanout // if ( Abc_ObjFanoutNum(pNode) != 1 ) // continue; // skip nodes that appear in the FF of their fanout more than once if ( Abc_NodeCountAppearancesAll( pNode ) > ElimValue + 2 ) continue; Abc_ObjForEachFanout( pNode, pFanout, k ) if ( Abc_NodeCollapseSuppSize(pNode, pFanout, vFanins) > nMaxSize ) break; if ( k < Abc_ObjFanoutNum(pNode) ) continue; // perform elimination Abc_NodeCollectFanouts( pNode, vFanouts ); Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, k ) { if ( fVerbose ) printf( "Collapsing fanin %5d (supp =%2d) into fanout %5d (supp =%2d) ", Abc_ObjId(pNode), Abc_ObjFaninNum(pNode), Abc_ObjId(pFanout), Abc_ObjFaninNum(pFanout) ); RetValue = Abc_NodeCollapse1( pNode, pFanout, vFanins, pPermFanin, pPermFanout ); assert( RetValue ); if ( fVerbose ) { Abc_Obj_t * pNodeNew = Abc_NtkObj( pNtk, Abc_NtkObjNumMax(pNtk) - 1 ); if ( pNodeNew ) printf( "resulting in node %5d (supp =%2d).\n", Abc_ObjId(pNodeNew), Abc_ObjFaninNum(pNodeNew) ); } } } Vec_PtrFree( vFanins ); Vec_PtrFree( vFanouts ); Vec_PtrFree( vNodes ); ABC_FREE( pPermFanin ); ABC_FREE( pPermFanout ); return 1; } int Abc_NtkEliminate1( Abc_Ntk_t * pNtk, int ElimValue, int nMaxSize, int nIterMax, int fReverse, int fVerbose ) { int i; for ( i = 0; i < nIterMax; i++ ) { int nNodes = Abc_NtkNodeNum(pNtk); // printf( "%d ", nNodes ); if ( !Abc_NtkEliminate1One(pNtk, ElimValue, nMaxSize, fReverse, fVerbose) ) return 0; if ( nNodes == Abc_NtkNodeNum(pNtk) ) break; } return 1; } /**Function************************************************************* Synopsis [Sort nodes in the reverse topo order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjCompareByNumber( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) { return Abc_ObjRegular(*pp1)->iTemp - Abc_ObjRegular(*pp2)->iTemp; } void Abc_ObjSortInReverseOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ) { Vec_Ptr_t * vOrder; Abc_Obj_t * pNode; int i; vOrder = Abc_NtkDfsReverse( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pNode, i ) pNode->iTemp = i; Vec_PtrSort( vNodes, (int (*)(const void *, const void *))Abc_ObjCompareByNumber ); Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pNode, i ) pNode->iTemp = 0; Vec_PtrFree( vOrder ); } /**Function************************************************************* Synopsis [Performs traditional eliminate -1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkEliminateSpecial( Abc_Ntk_t * pNtk, int nMaxSize, int fVerbose ) { extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); Vec_Ptr_t * vFanouts, * vFanins, * vNodes; Abc_Obj_t * pNode, * pFanout; int * pPermFanin, * pPermFanout; int RetValue, i, k; assert( nMaxSize > 0 ); assert( Abc_NtkIsLogic(pNtk) ); // convert network to BDD representation if ( !Abc_NtkToBdd(pNtk) ) { fprintf( stdout, "Converting to BDD has failed.\n" ); return 0; } // prepare nodes for sweeping //Abc_NtkRemoveDupFanins( pNtk ); Abc_NtkMinimumBase( pNtk ); Abc_NtkCleanup( pNtk, 0 ); // convert network to SOPs if ( !Abc_NtkToSop(pNtk, -1, ABC_INFINITY) ) { fprintf( stdout, "Converting to SOP has failed.\n" ); return 0; } // collect info about the nodes to be eliminated vNodes = Vec_PtrAlloc( 1000 ); Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_ObjFanoutNum(pNode) != 1 ) continue; pFanout = Abc_ObjFanout0(pNode); if ( !Abc_ObjIsNode(pFanout) ) continue; if ( Abc_SopGetCubeNum((char *)pNode->pData) != 1 ) continue; if ( Abc_SopGetCubeNum((char *)pFanout->pData) != 1 ) continue; // find the fanout's fanin RetValue = Abc_NodeFindFanin( pFanout, pNode ); assert( RetValue >= 0 && RetValue < Abc_ObjFaninNum(pFanout) ); // both pNode and pFanout are AND/OR type nodes if ( Abc_SopIsComplement((char *)pNode->pData) == Abc_SopGetIthCareLit((char *)pFanout->pData, RetValue) ) continue; Vec_PtrPush( vNodes, pNode ); } if ( Vec_PtrSize(vNodes) == 0 ) { Vec_PtrFree( vNodes ); return 1; } Abc_ObjSortInReverseOrder( pNtk, vNodes ); // convert network to BDD representation if ( !Abc_NtkToBdd(pNtk) ) { fprintf( stdout, "Converting to BDD has failed.\n" ); return 0; } // go through the nodes and decide is they can be eliminated pPermFanin = ABC_ALLOC( int, nMaxSize + 1000 ); pPermFanout = ABC_ALLOC( int, nMaxSize + 1000 ); vFanins = Vec_PtrAlloc( 1000 ); vFanouts = Vec_PtrAlloc( 1000 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { assert( Abc_ObjIsNode(pNode) ); assert( Abc_NodeFindCoFanout(pNode) == NULL ); // perform elimination Abc_NodeCollectFanouts( pNode, vFanouts ); Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, k ) { if ( fVerbose ) printf( "Collapsing fanin %5d (supp =%2d) into fanout %5d (supp =%2d) ", Abc_ObjId(pNode), Abc_ObjFaninNum(pNode), Abc_ObjId(pFanout), Abc_ObjFaninNum(pFanout) ); RetValue = Abc_NodeCollapse( pNode, pFanout, vFanins, pPermFanin, pPermFanout ); assert( RetValue ); if ( fVerbose ) { Abc_Obj_t * pNodeNew = Abc_NtkObj( pNtk, Abc_NtkObjNumMax(pNtk) - 1 ); if ( pNodeNew ) printf( "resulting in node %5d (supp =%2d).\n", Abc_ObjId(pNodeNew), Abc_ObjFaninNum(pNodeNew) ); } } } Abc_NtkBddReorder( pNtk, 0 ); Vec_PtrFree( vFanins ); Vec_PtrFree( vFanouts ); Vec_PtrFree( vNodes ); ABC_FREE( pPermFanin ); ABC_FREE( pPermFanout ); return 1; } #else int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk ) { return 0; } int Abc_NodeMinimumBase( Abc_Obj_t * pNode ) { return 0; } int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk ) { return 0; } int Abc_NtkEliminateSpecial( Abc_Ntk_t * pNtk, int nMaxSize, int fVerbose ) { return 0; } int Abc_NtkEliminate( Abc_Ntk_t * pNtk, int nMaxSize, int fReverse, int fVerbose ) { return 0; } int Abc_NtkEliminate1( Abc_Ntk_t * pNtk, int ElimValue, int nMaxSize, int nIterMax, int fReverse, int fVerbose ) { return 0; } #endif //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcNames.c000066400000000000000000000641151477524141600163120ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcNames.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures working with net and node names.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcNames.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" #include "misc/util/utilNam.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the unique name for the object.] Description [If the name previously did not exist, creates a new unique name but does not assign this name to the object. The temporary unique name is stored in a static buffer inside this procedure. It is important that the name is used before the function is called again!] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_ObjName( Abc_Obj_t * pObj ) { return Nm_ManCreateUniqueName( pObj->pNtk->pManName, pObj->Id ); } /**Function************************************************************* Synopsis [Assigns the given name to the object.] Description [The object should not have a name assigned. The same name may be used for several objects, which they share the same net in the original netlist. (For example, latch output and primary output may have the same name.) This procedure returns the pointer to the internally stored representation of the given name.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_ObjAssignName( Abc_Obj_t * pObj, char * pName, char * pSuffix ) { assert( pName != NULL ); return Nm_ManStoreIdName( pObj->pNtk->pManName, pObj->Id, pObj->Type, pName, pSuffix ); } /**Function************************************************************* Synopsis [Appends name to the prefix] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_ObjNamePrefix( Abc_Obj_t * pObj, char * pPrefix ) { static char Buffer[2000]; sprintf( Buffer, "%s%s", pPrefix, Abc_ObjName(pObj) ); return Buffer; } /**Function************************************************************* Synopsis [Appends suffic to the name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix ) { static char Buffer[2000]; sprintf( Buffer, "%s%s", Abc_ObjName(pObj), pSuffix ); return Buffer; } /**Function************************************************************* Synopsis [Returns the dummy PI name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits ) { static char Buffer[2000]; sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num ); return Buffer; } /**Function************************************************************* Synopsis [Tranfers names to the old network.] Description [Assumes that the new nodes are attached using pObj->pCopy.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTrasferNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { Abc_Obj_t * pObj; int i; assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); assert( Abc_NtkBoxNum(pNtk) == Abc_NtkBoxNum(pNtkNew) ); assert( Nm_ManNumEntries(pNtk->pManName) > 0 ); assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 ); // copy the CI/CO/box names Abc_NtkForEachCi( pNtk, pObj, i ) Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); Abc_NtkForEachCo( pNtk, pObj, i ) Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); Abc_NtkForEachBox( pNtk, pObj, i ) Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); } /**Function************************************************************* Synopsis [Tranfers names to the old network.] Description [Assumes that the new nodes are attached using pObj->pCopy.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { Abc_Obj_t * pObj; int i; assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); assert( Nm_ManNumEntries(pNtk->pManName) > 0 ); assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 ); // copy the CI/CO/box name and skip latches and theirs inputs/outputs Abc_NtkForEachCi( pNtk, pObj, i ) if ( Abc_ObjFaninNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) ) Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); Abc_NtkForEachCo( pNtk, pObj, i ) if ( Abc_ObjFanoutNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); Abc_NtkForEachBox( pNtk, pObj, i ) if ( !Abc_ObjIsLatch(pObj) ) Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); } /**Function************************************************************* Synopsis [Gets fanin node names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pFanin; int i; vNodes = Vec_PtrAlloc( 100 ); Abc_ObjForEachFanin( pNode, pFanin, i ) Vec_PtrPush( vNodes, Abc_UtilStrsav(Abc_ObjName(pFanin)) ); return vNodes; } /**Function************************************************************* Synopsis [Gets fanin node names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames ) { Vec_Ptr_t * vNames; char Buffer[5]; int i; vNames = Vec_PtrAlloc( nNames ); for ( i = 0; i < nNames; i++ ) { if ( nNames < 26 ) { Buffer[0] = 'a' + i; Buffer[1] = 0; } else { Buffer[0] = 'a' + i%26; Buffer[1] = '0' + i/26; Buffer[2] = 0; } Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) ); } return vNames; } /**Function************************************************************* Synopsis [Gets fanin node names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeFreeNames( Vec_Ptr_t * vNames ) { int i; if ( vNames == NULL ) return; for ( i = 0; i < vNames->nSize; i++ ) ABC_FREE( vNames->pArray[i] ); Vec_PtrFree( vNames ); } /**Function************************************************************* Synopsis [Collects the CI or CO names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char ** Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollectCos ) { Abc_Obj_t * pObj; char ** ppNames; int i; if ( fCollectCos ) { ppNames = ABC_ALLOC( char *, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) ppNames[i] = Abc_ObjName(pObj); } else { ppNames = ABC_ALLOC( char *, Abc_NtkCiNum(pNtk) ); Abc_NtkForEachCi( pNtk, pObj, i ) ppNames[i] = Abc_ObjName(pObj); } return ppNames; } /**Function************************************************************* Synopsis [Orders PIs/POs/latches alphabetically.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCompareNames( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) { int Diff = strcmp( (char *)(*pp1)->pCopy, (char *)(*pp2)->pCopy ); if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; Diff = (*pp1)->Id - (*pp2)->Id; if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; return 0; } void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb ) { Abc_Obj_t * pObj; int i; assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); // temporarily store the names in the copy field Abc_NtkForEachPi( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); Abc_NtkForEachPo( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); Abc_NtkForEachBox( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(Abc_ObjFanout0(pObj)); // order objects alphabetically 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), (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), (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 ); // clean the copy fields Abc_NtkForEachPi( pNtk, pObj, i ) pObj->pCopy = NULL; Abc_NtkForEachPo( pNtk, pObj, i ) pObj->pCopy = NULL; Abc_NtkForEachBox( pNtk, pObj, i ) pObj->pCopy = NULL; } /**Function************************************************************* Synopsis [Creates name manager storing input/output names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Nam_t * Abc_NtkNameMan( Abc_Ntk_t * p, int fOuts ) { if ( fOuts ) { Abc_Obj_t * pObj; int i; Abc_Nam_t * pStrsCo = Abc_NamStart( Abc_NtkCoNum(p), 24 ); Abc_NtkForEachCo( p, pObj, i ) Abc_NamStrFindOrAdd( pStrsCo, Abc_ObjName(pObj), NULL ); assert( Abc_NamObjNumMax(pStrsCo) == i + 1 ); return pStrsCo; } else { Abc_Obj_t * pObj; int i; Abc_Nam_t * pStrsCi = Abc_NamStart( Abc_NtkCiNum(p), 24 ); Abc_NtkForEachCi( p, pObj, i ) Abc_NamStrFindOrAdd( pStrsCi, Abc_ObjName(pObj), NULL ); assert( Abc_NamObjNumMax(pStrsCi) == i + 1 ); return pStrsCi; } } /**Function************************************************************* Synopsis [Orders PIs/POs/latches alphabetically.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCompareIndexes( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) { int Diff = (*pp1)->iTemp - (*pp2)->iTemp; if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; return 0; } void Abc_NtkTransferOrder( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ) { Abc_Obj_t * pObj; int i; Abc_Nam_t * pStrsCi = Abc_NtkNameMan( pNtkOld, 0 ); Abc_Nam_t * pStrsCo = Abc_NtkNameMan( pNtkOld, 1 ); assert( Abc_NtkPiNum(pNtkOld) == Abc_NtkPiNum(pNtkNew) ); assert( Abc_NtkPoNum(pNtkOld) == Abc_NtkPoNum(pNtkNew) ); assert( Abc_NtkLatchNum(pNtkOld) == Abc_NtkLatchNum(pNtkNew) ); // transfer to the new network Abc_NtkForEachCi( pNtkNew, pObj, i ) { pObj->iTemp = Abc_NamStrFind(pStrsCi, Abc_ObjName(pObj)); assert( pObj->iTemp > 0 && pObj->iTemp <= Abc_NtkCiNum(pNtkNew) ); } Abc_NtkForEachCo( pNtkNew, pObj, i ) { pObj->iTemp = Abc_NamStrFind(pStrsCo, Abc_ObjName(pObj)); assert( pObj->iTemp > 0 && pObj->iTemp <= Abc_NtkCoNum(pNtkNew) ); } Abc_NamDeref( pStrsCi ); Abc_NamDeref( pStrsCo ); // order PI/PO 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), (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), (size_t)Vec_PtrSize(pNtkNew->vCis), sizeof(Abc_Obj_t *), (int (*)(const void *, const void *)) Abc_NodeCompareIndexes ); 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 ); // clean the copy fields Abc_NtkForEachCi( pNtkNew, pObj, i ) pObj->iTemp = 0; Abc_NtkForEachCo( pNtkNew, pObj, i ) pObj->iTemp = 0; } /**Function************************************************************* Synopsis [Checks that the order and number of CI/CO is the same.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCompareCiCo( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ) { int i; if ( Abc_NtkPiNum(pNtkOld) != Abc_NtkPiNum(pNtkNew) ) return 0; if ( Abc_NtkPoNum(pNtkOld) != Abc_NtkPoNum(pNtkNew) ) return 0; if ( Abc_NtkLatchNum(pNtkOld) != Abc_NtkLatchNum(pNtkNew) ) return 0; for ( i = 0; i < Abc_NtkCiNum(pNtkOld); i++ ) if ( strcmp(Abc_ObjName(Abc_NtkCi(pNtkOld, i)), Abc_ObjName(Abc_NtkCi(pNtkNew, i))) ) return 0; for ( i = 0; i < Abc_NtkCoNum(pNtkOld); i++ ) if ( strcmp(Abc_ObjName(Abc_NtkCo(pNtkOld, i)), Abc_ObjName(Abc_NtkCo(pNtkNew, i))) ) return 0; return 1; } /**Function************************************************************* Synopsis [Adds dummy names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int nDigits, i; nDigits = Abc_Base10Log( Abc_NtkPiNum(pNtk) ); Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjAssignName( pObj, Abc_ObjNameDummy("pi", i, nDigits), NULL ); } /**Function************************************************************* Synopsis [Adds dummy names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int nDigits, i; nDigits = Abc_Base10Log( Abc_NtkPoNum(pNtk) ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_ObjAssignName( pObj, Abc_ObjNameDummy("po", i, nDigits), NULL ); } /**Function************************************************************* Synopsis [Adds dummy names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk ) { char * pName, PrefLi[100], PrefLo[100]; Abc_Obj_t * pObj; int nDigits, i, k, CountCur, CountMax = 0; // if PIs/POs already have nodes with what looks like latch names // we need to add different prefix for the new latches Abc_NtkForEachPi( pNtk, pObj, i ) { CountCur = 0; pName = Abc_ObjName(pObj); for ( k = 0; pName[k]; k++ ) if ( pName[k] == 'l' ) CountCur++; else break; CountMax = Abc_MaxInt( CountMax, CountCur ); } Abc_NtkForEachPo( pNtk, pObj, i ) { CountCur = 0; pName = Abc_ObjName(pObj); for ( k = 0; pName[k]; k++ ) if ( pName[k] == 'l' ) CountCur++; else break; CountMax = Abc_MaxInt( CountMax, CountCur ); } //printf( "CountMax = %d\n", CountMax ); assert( CountMax < 100-2 ); for ( i = 0; i <= CountMax; i++ ) PrefLi[i] = PrefLo[i] = 'l'; PrefLi[i] = 'i'; PrefLo[i] = 'o'; PrefLi[i+1] = 0; PrefLo[i+1] = 0; // create latch names assert( !Abc_NtkIsNetlist(pNtk) ); nDigits = Abc_Base10Log( Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachLatch( pNtk, pObj, i ) { Abc_ObjAssignName( pObj, Abc_ObjNameDummy("l", i, nDigits), NULL ); Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjNameDummy(PrefLi, i, nDigits), NULL ); Abc_ObjAssignName( Abc_ObjFanout0(pObj), Abc_ObjNameDummy(PrefLo, i, nDigits), NULL ); } /* nDigits = Abc_Base10Log( Abc_NtkBlackboxNum(pNtk) ); Abc_NtkForEachBlackbox( pNtk, pObj, i ) { pName = Abc_ObjAssignName( pObj, Abc_ObjNameDummy("B", i, nDigits), NULL ); nDigitsF = Abc_Base10Log( Abc_ObjFaninNum(pObj) ); Abc_ObjForEachFanin( pObj, pTerm, k ) Abc_ObjAssignName( Abc_ObjFanin0(pObj), pName, Abc_ObjNameDummy("i", k, nDigitsF) ); nDigitsF = Abc_Base10Log( Abc_ObjFanoutNum(pObj) ); Abc_ObjForEachFanout( pObj, pTerm, k ) Abc_ObjAssignName( Abc_ObjFanin0(pObj), pName, Abc_ObjNameDummy("o", k, nDigitsF) ); } */ } /**Function************************************************************* Synopsis [Replaces names by short names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkShortNames( Abc_Ntk_t * pNtk ) { Nm_ManFree( pNtk->pManName ); pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk) + Abc_NtkBoxNum(pNtk) ); Abc_NtkAddDummyPiNames( 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************************************************************* Synopsis [Moves names from the other network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRedirectCiCo( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pObjCi, * pFanin; int i, Count = 0; // if CO points to CI with the same name, remove buffer between them Abc_NtkForEachCo( pNtk, pObj, i ) { int nCiId = Nm_ManFindIdByNameTwoTypes( pNtk->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); if ( nCiId == -1 ) continue; pObjCi = Abc_NtkObj( pNtk, nCiId ); assert( !strcmp( Abc_ObjName(pObj), Abc_ObjName(pObjCi) ) ); pFanin = Abc_ObjFanin0(pObj); if ( pFanin == pObjCi ) continue; assert( Abc_NodeIsBuf(pFanin) ); Abc_ObjPatchFanin( pObj, pFanin, pObjCi ); if ( Abc_ObjFanoutNum(pFanin) == 0 ) Abc_NtkDeleteObj( pFanin ); Count++; } if ( Count ) printf( "Redirected %d POs from buffers to PIs with the same name.\n", Count ); } void Abc_NtkMoveNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pOld ) { Abc_Obj_t * pObj; int i; Nm_ManFree( pNtk->pManName ); pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk) + Abc_NtkBoxNum(pNtk) ); Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjAssignName( pObj, Abc_ObjName(Abc_NtkPi(pOld, i)), NULL ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_ObjAssignName( pObj, Abc_ObjName(Abc_NtkPo(pOld, i)), NULL ); Abc_NtkForEachLatch( pNtk, pObj, i ) { Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(Abc_ObjFanin0(Abc_NtkBox(pOld, i))), NULL ); Abc_ObjAssignName( Abc_ObjFanout0(pObj), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pOld, i))), NULL ); } Abc_NtkRedirectCiCo( pNtk ); } /**Function************************************************************* Synopsis [Saves name IDs into a file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkStartNameIds( Abc_Ntk_t * p ) { char pFileName[1000]; FILE * pFile; Abc_Obj_t * pObj, * pFanin; Vec_Ptr_t * vNodes; int i, Counter = 1; assert( Abc_NtkIsNetlist(p) ); assert( p->vNameIds == NULL ); assert( strlen(p->pSpec) < 1000 ); sprintf( pFileName, "%s_%s_names.txt", Extra_FileNameGenericAppend(p->pSpec,""), Extra_FileNameExtension(p->pSpec) ); pFile = fopen( pFileName, "wb" ); p->vNameIds = Vec_IntStart( Abc_NtkObjNumMax(p) ); // add inputs Abc_NtkForEachCi( p, pObj, i ) fprintf( pFile, "%s \n", Abc_ObjName(Abc_ObjFanout0(pObj)) ), Vec_IntWriteEntry(p->vNameIds, Abc_ObjId(pObj), 2*Counter++); // add outputs Abc_NtkForEachCo( p, pObj, i ) { pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); if ( !Vec_IntEntry(p->vNameIds, Abc_ObjId(pFanin)) ) fprintf( pFile, "%s \n", Abc_ObjName(Abc_ObjFanout0(pFanin)) ), Vec_IntWriteEntry(p->vNameIds, Abc_ObjId(pFanin), 2*Counter++); } // add nodes in a topo order vNodes = Abc_NtkDfs( p, 1 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) if ( !Vec_IntEntry(p->vNameIds, Abc_ObjId(pObj)) ) fprintf( pFile, "%s \n", Abc_ObjName(Abc_ObjFanout0(pObj)) ), Vec_IntWriteEntry(p->vNameIds, Abc_ObjId(pObj), 2*Counter++); Vec_PtrFree( vNodes ); fclose( pFile ); // transfer driver node names to COs Abc_NtkForEachCo( p, pObj, i ) { pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); Vec_IntWriteEntry( p->vNameIds, Abc_ObjId(pObj), Vec_IntEntry(p->vNameIds, Abc_ObjId(pFanin)) ); Vec_IntWriteEntry( p->vNameIds, Abc_ObjId(pFanin), 0 ); } } /**Function************************************************************* Synopsis [Remaps the AIG from the old manager into the new manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTransferNameIds( Abc_Ntk_t * p, Abc_Ntk_t * pNew ) { Abc_Obj_t * pObj, * pObjNew; int i; assert( p->vNameIds != NULL ); assert( pNew->vNameIds == NULL ); pNew->vNameIds = Vec_IntStart( Abc_NtkObjNumMax(pNew) ); // Abc_NtkForEachCi( p, pObj, i ) // printf( "%d ", Vec_IntEntry(p->vNameIds, Abc_ObjId(pObj)) ); // printf( "\n" ); Abc_NtkForEachObj( p, pObj, i ) if ( pObj->pCopy && i < Vec_IntSize(p->vNameIds) && Vec_IntEntry(p->vNameIds, i) ) { pObjNew = Abc_ObjRegular(pObj->pCopy); assert( Abc_ObjNtk(pObjNew) == pNew ); if ( Abc_ObjIsCi(pObjNew) && !Abc_ObjIsCi(pObj) ) // do not overwrite CI name by internal node name continue; Vec_IntWriteEntry( pNew->vNameIds, Abc_ObjId(pObjNew), Vec_IntEntry(p->vNameIds, i) ^ Abc_ObjIsComplement(pObj->pCopy) ); } } /**Function************************************************************* Synopsis [Updates file with name IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkUpdateNameIds( Abc_Ntk_t * p ) { char pFileName[1000]; Vec_Int_t * vStarts; Abc_Obj_t * pObj; FILE * pFile; int i, c, iVar, fCompl, fSeenSpace, Counter = 0; assert( !Abc_NtkIsNetlist(p) ); assert( strlen(p->pSpec) < 1000 ); assert( p->vNameIds != NULL ); sprintf( pFileName, "%s_%s_names.txt", Extra_FileNameGenericAppend(p->pSpec,""), Extra_FileNameExtension(p->pSpec) ); pFile = fopen( pFileName, "r+" ); // collect info about lines fSeenSpace = 0; vStarts = Vec_IntAlloc( 1000 ); Vec_IntPush( vStarts, -1 ); while ( (c = fgetc(pFile)) != EOF && ++Counter ) if ( c == ' ' && !fSeenSpace ) Vec_IntPush(vStarts, Counter), fSeenSpace = 1; else if ( c == '\n' ) fSeenSpace = 0; // add info about names Abc_NtkForEachObj( p, pObj, i ) { if ( i == 0 || i >= Vec_IntSize(p->vNameIds) || !Vec_IntEntry(p->vNameIds, i) ) continue; iVar = Abc_Lit2Var( Vec_IntEntry(p->vNameIds, i) ); fCompl = Abc_LitIsCompl( Vec_IntEntry(p->vNameIds, i) ); assert( iVar < Vec_IntSize(vStarts) ); fseek( pFile, Vec_IntEntry(vStarts, iVar), SEEK_SET ); fprintf( pFile, "%s%d", fCompl? "-":"", i ); } printf( "Saved %d names into file \"%s\".\n", Vec_IntSize(vStarts)-1, pFileName ); fclose( pFile ); Vec_IntFree( vStarts ); Vec_IntFreeP( &p->vNameIds ); // Abc_NtkForEachObj( p, pObj, i ) // Abc_ObjPrint( stdout, pObj ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcNetlist.c000066400000000000000000000436271477524141600166760ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcNetlist.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Transforms netlist into a logic network and vice versa.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcNetlist.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" #include "base/main/main.h" //#include "seq.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk ); static Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ); static Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk ); static Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Transform the netlist into a logic network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin; int i, k; // consider the case of the AIG if ( Abc_NtkIsStrash(pNtk) ) return Abc_NtkAigToLogicSop( pNtk ); assert( Abc_NtkIsNetlist(pNtk) ); // consider simple case when there is hierarchy // assert( pNtk->pDesign == NULL ); assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); assert( Abc_NtkBlackboxNum(pNtk) == 0 ); // start the network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, pNtk->ntkFunc ); // duplicate the nodes Abc_NtkForEachNode( pNtk, pObj, i ) { Abc_NtkDupObj(pNtkNew, pObj, 0); Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0(pObj)), NULL ); } // reconnect the internal nodes in the new network Abc_NtkForEachNode( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pFanin)->pCopy ); // collect the CO nodes Abc_NtkFinalize( pNtk, pNtkNew ); // fix the problem with CO pointing directly to CIs Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // duplicate EXDC if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkToLogic( pNtk->pExdc ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkToLogic(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Transform the logic network into a netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew, * pNtkTemp; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); if ( Abc_NtkIsStrash(pNtk) ) { pNtkTemp = Abc_NtkAigToLogicSop(pNtk); pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp ); Abc_NtkDelete( pNtkTemp ); return pNtkNew; } return Abc_NtkLogicToNetlist( pNtk ); } /**Function************************************************************* Synopsis [Converts the AIG into the netlist.] Description [This procedure does not copy the choices.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew, * pNtkTemp; assert( Abc_NtkIsStrash(pNtk) ); pNtkTemp = Abc_NtkAigToLogicSopBench( pNtk ); pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp ); Abc_NtkDelete( pNtkTemp ); return pNtkNew; } /**Function************************************************************* Synopsis [Transform the logic network into a netlist.] Description [The logic network given to this procedure should have exactly the same structure as the resulting netlist. The COs can only point to CIs if they have identical names. Otherwise, they should have a node between them, even if this node is inverter or buffer.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pNet, * pDriver, * pFanin; int i, k; assert( Abc_NtkIsLogic(pNtk) ); // remove dangling nodes Abc_NtkCleanup( pNtk, 0 ); // make sure the CO names are unique Abc_NtkCheckUniqueCiNames( pNtk ); Abc_NtkCheckUniqueCoNames( pNtk ); Abc_NtkCheckUniqueCioNames( pNtk ); // assert( Abc_NtkLogicHasSimpleCos(pNtk) ); if ( !Abc_NtkLogicHasSimpleCos(pNtk) ) { if ( !Abc_FrameReadFlag("silentmode") ) printf( "Abc_NtkLogicToNetlist() warning: The network is converted to have simple COs.\n" ); Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); } // start the netlist by creating PI/PO/Latch objects pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_NETLIST, pNtk->ntkFunc ); // create the CI nets and remember them in the new CI nodes Abc_NtkForEachCi( pNtk, pObj, i ) { pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); Abc_ObjAddFanin( pNet, pObj->pCopy ); pObj->pCopy->pCopy = pNet; } // duplicate all nodes Abc_NtkForEachNode( pNtk, pObj, i ) Abc_NtkDupObj(pNtkNew, pObj, 0); // first add the nets to the CO drivers Abc_NtkForEachCo( pNtk, pObj, i ) { pDriver = Abc_ObjFanin0(pObj); if ( Abc_ObjIsCi(pDriver) ) { assert( !strcmp( Abc_ObjName(pDriver), Abc_ObjName(pObj) ) ); Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy ); continue; } assert( Abc_ObjIsNode(pDriver) ); // if the CO driver has no net, create it if ( pDriver->pCopy->pCopy == NULL ) { // create the CO net and connect it to CO //if ( Abc_NtkFindNet(pNtkNew, Abc_ObjName(pDriver)) == NULL ) // pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pDriver) ); //else pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); Abc_ObjAddFanin( pObj->pCopy, pNet ); // connect the CO net to the new driver and remember it in the new driver Abc_ObjAddFanin( pNet, pDriver->pCopy ); pDriver->pCopy->pCopy = pNet; } else { assert( !strcmp( Abc_ObjName(pDriver->pCopy->pCopy), Abc_ObjName(pObj) ) ); Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy ); } } // 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 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; } // connect nodes to the fanins nets Abc_NtkForEachNode( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); // duplicate EXDC if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkToNetlist( pNtk->pExdc ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkLogicToNetlist(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Converts the AIG into the logic network with SOPs.] Description [Correctly handles the case of choice nodes.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk ) { extern int Abc_NtkLogicMakeSimpleCos2( Abc_Ntk_t * pNtk, int fDuplicate ); Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin, * pNodeNew; Vec_Int_t * vInts; int i, k, fChoices = 0; assert( Abc_NtkIsStrash(pNtk) ); // start the network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); // if the constant node is used, duplicate it pObj = Abc_AigConst1(pNtk); if ( Abc_ObjFanoutNum(pObj) > 0 ) pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew); // duplicate the nodes and create node functions Abc_NtkForEachNode( pNtk, pObj, i ) { Abc_NtkDupObj(pNtkNew, pObj, 0); pObj->pCopy->pData = Abc_SopCreateAnd2( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); } // create the choice nodes Abc_NtkForEachNode( pNtk, pObj, i ) { if ( !Abc_AigNodeIsChoice(pObj) ) continue; // create an OR gate pNodeNew = Abc_NtkCreateNode(pNtkNew); // add fanins vInts = Vec_IntAlloc( 10 ); for ( pFanin = pObj; pFanin; pFanin = (Abc_Obj_t *)pFanin->pData ) { Vec_IntPush( vInts, (int)(pObj->fPhase != pFanin->fPhase) ); Abc_ObjAddFanin( pNodeNew, pFanin->pCopy ); } // create the logic function pNodeNew->pData = Abc_SopCreateOrMultiCube( (Mem_Flex_t *)pNtkNew->pManFunc, Vec_IntSize(vInts), Vec_IntArray(vInts) ); // set the new node pObj->pCopy->pCopy = pNodeNew; Vec_IntFree( vInts ); fChoices = 1; } // connect the internal nodes Abc_NtkForEachNode( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) if ( pFanin->pCopy->pCopy ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); else Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); // connect the COs // Abc_NtkFinalize( pNtk, pNtkNew ); Abc_NtkForEachCo( pNtk, pObj, i ) { pFanin = Abc_ObjFanin0(pObj); if ( pFanin->pCopy->pCopy ) pNodeNew = Abc_ObjNotCond(pFanin->pCopy->pCopy, Abc_ObjFaninC0(pObj)); else pNodeNew = Abc_ObjNotCond(pFanin->pCopy, Abc_ObjFaninC0(pObj)); Abc_ObjAddFanin( pObj->pCopy, pNodeNew ); } // fix the problem with complemented and duplicated CO edges if ( fChoices ) Abc_NtkLogicMakeSimpleCos2( pNtkNew, 0 ); else Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // duplicate the EXDC Ntk if ( pNtk->pExdc ) { if ( Abc_NtkIsStrash(pNtk->pExdc) ) pNtkNew->pExdc = Abc_NtkAigToLogicSop( pNtk->pExdc ); else pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); } if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkAigToLogicSop(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Converts the AIG into the logic network with SOPs for bench writing.] Description [This procedure does not copy the choices.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin; Vec_Ptr_t * vNodes; int i, k; assert( Abc_NtkIsStrash(pNtk) ); if ( Abc_NtkGetChoiceNum(pNtk) ) printf( "Warning: Choice nodes are skipped.\n" ); // start the network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); // collect the nodes to be used (marks all nodes with current TravId) vNodes = Abc_NtkDfs( pNtk, 0 ); // create inverters for the constant node pObj = Abc_AigConst1(pNtk); if ( Abc_ObjFanoutNum(pObj) > 0 ) pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew); if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); // create inverters for the CIs Abc_NtkForEachCi( pNtk, pObj, i ) if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); // duplicate the nodes, create node functions, and inverters Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { Abc_NtkDupObj( pNtkNew, pObj, 0 ); pObj->pCopy->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, 2, NULL ); if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); } // connect the objects Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) { if ( Abc_ObjFaninC( pObj, k ) ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); else Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } Vec_PtrFree( vNodes ); // connect the COs Abc_NtkForEachCo( pNtk, pObj, i ) { pFanin = Abc_ObjFanin0(pObj); if ( Abc_ObjFaninC0( pObj ) ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); else Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } // fix the problem with complemented and duplicated CO edges Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // duplicate the EXDC Ntk if ( pNtk->pExdc ) printf( "Warning: The EXDc network is skipped.\n" ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkAigToLogicSopBench(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Converts the AIG into the logic network with SOPs for bench writing.] Description [This procedure does not copy the choices.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkAigToLogicSopNand( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin; Vec_Ptr_t * vNodes; int i, k; assert( Abc_NtkIsStrash(pNtk) ); if ( Abc_NtkGetChoiceNum(pNtk) ) printf( "Warning: Choice nodes are skipped.\n" ); // convert complemented edges Abc_NtkForEachObj( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) if ( Abc_ObjIsNode(pFanin) ) Abc_ObjXorFaninC( pObj, k ); // start the network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); // collect the nodes to be used (marks all nodes with current TravId) vNodes = Abc_NtkDfs( pNtk, 0 ); // create inverters for the constant node pObj = Abc_AigConst1(pNtk); if ( Abc_ObjFanoutNum(pObj) > 0 ) pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew); if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); // create inverters for the CIs Abc_NtkForEachCi( pNtk, pObj, i ) if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); // duplicate the nodes, create node functions, and inverters Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { Abc_NtkDupObj( pNtkNew, pObj, 0 ); pObj->pCopy->pData = Abc_SopCreateNand( (Mem_Flex_t *)pNtkNew->pManFunc, 2 ); if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); } // connect the objects Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) { if ( Abc_ObjFaninC( pObj, k ) ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); else Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } Vec_PtrFree( vNodes ); // connect the COs Abc_NtkForEachCo( pNtk, pObj, i ) { pFanin = Abc_ObjFanin0(pObj); if ( Abc_ObjFaninC0( pObj ) ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); else Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } // fix the problem with complemented and duplicated CO edges Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // convert complemented edges Abc_NtkForEachObj( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) if ( Abc_ObjIsNode(pFanin) ) Abc_ObjXorFaninC( pObj, k ); // duplicate the EXDC Ntk if ( pNtk->pExdc ) printf( "Warning: The EXDc network is skipped.\n" ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkAigToLogicSopBench(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Adds buffers for each PO.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pFanin, * pFaninNew; int i; assert( Abc_NtkIsStrash(pNtk) ); Abc_NtkForEachPo( pNtk, pObj, i ) { pFanin = Abc_ObjChild0(pObj); pFaninNew = Abc_NtkCreateNode(pNtk); Abc_ObjAddFanin( pFaninNew, pFanin ); Abc_ObjPatchFanin( pObj, pFanin, pFaninNew ); } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcNtk.c000066400000000000000000002514111477524141600160000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcNtk.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Network creation/duplication/deletion procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcNtk.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" #include "abcInt.h" #include "base/main/main.h" #include "map/mio/mio.h" #include "aig/gia/gia.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates a new Ntk.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan ) { Abc_Ntk_t * pNtk; pNtk = ABC_ALLOC( Abc_Ntk_t, 1 ); memset( pNtk, 0, sizeof(Abc_Ntk_t) ); pNtk->ntkType = Type; pNtk->ntkFunc = Func; // start the object storage pNtk->vObjs = Vec_PtrAlloc( 100 ); pNtk->vPios = Vec_PtrAlloc( 100 ); pNtk->vPis = Vec_PtrAlloc( 100 ); pNtk->vPos = Vec_PtrAlloc( 100 ); pNtk->vCis = Vec_PtrAlloc( 100 ); pNtk->vCos = Vec_PtrAlloc( 100 ); pNtk->vBoxes = Vec_PtrAlloc( 100 ); pNtk->vLtlProperties = Vec_PtrAlloc( 100 ); // start the memory managers pNtk->pMmObj = fUseMemMan? Mem_FixedStart( sizeof(Abc_Obj_t) ) : NULL; pNtk->pMmStep = fUseMemMan? Mem_StepStart( ABC_NUM_STEPS ) : NULL; // get ready to assign the first Obj ID pNtk->nTravIds = 1; // start the functionality manager if ( !Abc_NtkIsStrash(pNtk) ) Vec_PtrPush( pNtk->vObjs, NULL ); if ( Abc_NtkIsStrash(pNtk) ) pNtk->pManFunc = Abc_AigAlloc( pNtk ); else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) pNtk->pManFunc = Mem_FlexStart(); #ifdef ABC_USE_CUDD else if ( Abc_NtkHasBdd(pNtk) ) pNtk->pManFunc = Cudd_Init( 20, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); #endif else if ( Abc_NtkHasAig(pNtk) ) pNtk->pManFunc = Hop_ManStart(); else if ( Abc_NtkHasMapping(pNtk) ) pNtk->pManFunc = Abc_FrameReadLibGen(); else if ( !Abc_NtkHasBlackbox(pNtk) ) assert( 0 ); // name manager pNtk->pManName = Nm_ManCreate( 200 ); // attribute manager pNtk->vAttrs = Vec_PtrStart( VEC_ATTR_TOTAL_NUM ); // estimated AndGateDelay pNtk->AndGateDelay = 0.0; return pNtk; } /**Function************************************************************* Synopsis [Starts a new network using existing network as a model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj; int fCopyNames, i; if ( pNtk == NULL ) return NULL; // decide whether to copy the names fCopyNames = ( Type != ABC_NTK_NETLIST ); // start the network pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); pNtkNew->nConstrs = pNtk->nConstrs; pNtkNew->nBarBufs = pNtk->nBarBufs; // duplicate the name and the spec pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); // map the constant nodes if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); // clone CIs/CIs/boxes Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); Abc_NtkForEachBox( pNtk, pObj, i ) Abc_NtkDupBox( pNtkNew, pObj, fCopyNames ); // transfer logic level Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pCopy->Level = pObj->Level; // transfer the names // Abc_NtkTrasferNames( pNtk, pNtkNew ); Abc_ManTimeDup( pNtk, pNtkNew ); if ( pNtk->vOnehots ) pNtkNew->vOnehots = (Vec_Ptr_t *)Vec_VecDupInt( (Vec_Vec_t *)pNtk->vOnehots ); if ( pNtk->pSeqModel ) pNtkNew->pSeqModel = Abc_CexDup( pNtk->pSeqModel, Abc_NtkLatchNum(pNtk) ); if ( pNtk->vObjPerm ) pNtkNew->vObjPerm = Vec_IntDup( pNtk->vObjPerm ); pNtkNew->AndGateDelay = pNtk->AndGateDelay; if ( pNtkNew->pManTime && Abc_FrameReadLibGen() && pNtkNew->AndGateDelay == 0.0 ) pNtkNew->AndGateDelay = Mio_LibraryReadDelayAigNode((Mio_Library_t *)Abc_FrameReadLibGen()); // initialize logic level of the CIs if ( pNtk->AndGateDelay != 0.0 && pNtk->pManTime != NULL && pNtk->ntkType != ABC_NTK_STRASH && Type == ABC_NTK_STRASH ) { Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pCopy->Level = (int)(Abc_MaxFloat(0, Abc_NodeReadArrivalWorst(pObj)) / pNtk->AndGateDelay); } // check that the CI/CO/latches are copied correctly assert( Abc_NtkCiNum(pNtk) == Abc_NtkCiNum(pNtkNew) ); assert( Abc_NtkCoNum(pNtk) == Abc_NtkCoNum(pNtkNew) ); assert( Abc_NtkLatchNum(pNtk) == Abc_NtkLatchNum(pNtkNew) ); return pNtkNew; } /**Function************************************************************* Synopsis [Starts a new network using existing network as a model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkStartFromWithLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func, int nLatches ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pNode0, * pNode1; int fCopyNames, i; if ( pNtk == NULL ) return NULL; assert( Abc_NtkLatchNum(pNtk) == 0 ); // decide whether to copy the names fCopyNames = ( Type != ABC_NTK_NETLIST ); // start the network pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); pNtkNew->nConstrs = pNtk->nConstrs; pNtkNew->nBarBufs = pNtk->nBarBufs; // duplicate the name and the spec pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); // map the constant nodes if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); // clone CIs/CIs/boxes for ( i = 0; i < Abc_NtkPiNum(pNtk)-nLatches; i++ ) Abc_NtkDupObj( pNtkNew, Abc_NtkPi(pNtk, i), fCopyNames ); for ( i = 0; i < Abc_NtkPoNum(pNtk)-nLatches; i++ ) Abc_NtkDupObj( pNtkNew, Abc_NtkPo(pNtk, i), fCopyNames ); for ( i = 0; i < nLatches; i++ ) { pObj = Abc_NtkCreateLatch(pNtkNew); Abc_LatchSetInit0( pObj ); pNode0 = Abc_NtkCreateBi(pNtkNew); Abc_NtkPo(pNtk, Abc_NtkPoNum(pNtk)-nLatches+i)->pCopy = pNode0; pNode1 = Abc_NtkCreateBo(pNtkNew); Abc_NtkPi(pNtk, Abc_NtkPiNum(pNtk)-nLatches+i)->pCopy = pNode1; Abc_ObjAddFanin( pObj, pNode0 ); Abc_ObjAddFanin( pNode1, pObj ); Abc_ObjAssignName( pNode0, Abc_ObjName(pNode0), NULL ); Abc_ObjAssignName( pNode1, Abc_ObjName(pNode1), NULL ); } // transfer logic level // Abc_NtkForEachCi( pNtk, pObj, i ) // pObj->pCopy->Level = pObj->Level; // transfer the names // Abc_NtkTrasferNames( pNtk, pNtkNew ); Abc_ManTimeDup( pNtk, pNtkNew ); if ( pNtk->vOnehots ) pNtkNew->vOnehots = (Vec_Ptr_t *)Vec_VecDupInt( (Vec_Vec_t *)pNtk->vOnehots ); if ( pNtk->pSeqModel ) pNtkNew->pSeqModel = Abc_CexDup( pNtk->pSeqModel, Abc_NtkLatchNum(pNtk) ); if ( pNtk->vObjPerm ) pNtkNew->vObjPerm = Vec_IntDup( pNtk->vObjPerm ); pNtkNew->AndGateDelay = pNtk->AndGateDelay; // initialize logic level of the CIs if ( pNtk->AndGateDelay != 0.0 && pNtk->pManTime != NULL && pNtk->ntkType != ABC_NTK_STRASH && Type == ABC_NTK_STRASH ) { Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pCopy->Level = (int)(Abc_MaxFloat(0, Abc_NodeReadArrivalWorst(pObj)) / pNtk->AndGateDelay); } // check that the CI/CO/latches are copied correctly assert( Abc_NtkCiNum(pNtk) == Abc_NtkCiNum(pNtkNew) ); assert( Abc_NtkCoNum(pNtk) == Abc_NtkCoNum(pNtkNew) ); assert( nLatches == Abc_NtkLatchNum(pNtkNew) ); return pNtkNew; } /**Function************************************************************* Synopsis [Starts a new network using existing network as a model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj; int i; if ( pNtk == NULL ) return NULL; assert( Type != ABC_NTK_NETLIST ); // start the network pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); pNtkNew->nConstrs = pNtk->nConstrs; pNtkNew->nBarBufs = pNtk->nBarBufs; // duplicate the name and the spec pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); // map the constant nodes if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); // clone CIs/CIs/boxes Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 1 ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 1 ); Abc_NtkForEachBox( pNtk, pObj, i ) { if ( Abc_ObjIsLatch(pObj) ) continue; Abc_NtkDupBox(pNtkNew, pObj, 1); } if ( pNtk->vObjPerm ) pNtkNew->vObjPerm = Vec_IntDup( pNtk->vObjPerm ); pNtkNew->AndGateDelay = pNtk->AndGateDelay; // transfer the names // Abc_NtkTrasferNamesNoLatches( pNtk, pNtkNew ); Abc_ManTimeDup( pNtk, pNtkNew ); // check that the CI/CO/latches are copied correctly assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); return pNtkNew; } /**Function************************************************************* Synopsis [Finalizes the network using the existing network as a model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { Abc_Obj_t * pObj, * pDriver, * pDriverNew; int i; // set the COs of the strashed network Abc_NtkForEachCo( pNtk, pObj, i ) { pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pObj) ); pDriverNew = Abc_ObjNotCond(pDriver->pCopy, Abc_ObjFaninC0(pObj)); Abc_ObjAddFanin( pObj->pCopy, pDriverNew ); } // duplicate timing manager if ( pNtk->pManTime ) Abc_NtkTimeInitialize( pNtkNew, pNtk ); if ( pNtk->vPhases ) Abc_NtkTransferPhases( pNtkNew, pNtk ); if ( pNtk->pWLoadUsed ) pNtkNew->pWLoadUsed = Abc_UtilStrsav( pNtk->pWLoadUsed ); } /**Function************************************************************* Synopsis [Starts a new network using existing network as a model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkStartRead( char * pName ) { Abc_Ntk_t * pNtkNew; // allocate the empty network pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); // set the specs pNtkNew->pName = Extra_FileNameGeneric(pName); pNtkNew->pSpec = Extra_UtilStrsav(pName); if ( pNtkNew->pName == NULL || strlen(pNtkNew->pName) == 0 ) { ABC_FREE( pNtkNew->pName ); pNtkNew->pName = Extra_UtilStrsav("unknown"); } return pNtkNew; } /**Function************************************************************* Synopsis [Finalizes the network using the existing network as a model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pBox, * pObj, * pTerm, * pNet; int i; if ( Abc_NtkHasBlackbox(pNtk) && Abc_NtkBoxNum(pNtk) == 0 ) { pBox = Abc_NtkCreateBlackbox(pNtk); Abc_NtkForEachPi( pNtk, pObj, i ) { pTerm = Abc_NtkCreateBi(pNtk); Abc_ObjAddFanin( pTerm, Abc_ObjFanout0(pObj) ); Abc_ObjAddFanin( pBox, pTerm ); } Abc_NtkForEachPo( pNtk, pObj, i ) { pTerm = Abc_NtkCreateBo(pNtk); Abc_ObjAddFanin( pTerm, pBox ); Abc_ObjAddFanin( Abc_ObjFanin0(pObj), pTerm ); } return; } assert( Abc_NtkIsNetlist(pNtk) ); // check if constant 0 net is used pNet = Abc_NtkFindNet( pNtk, "1\'b0" ); if ( pNet ) { if ( Abc_ObjFanoutNum(pNet) == 0 ) Abc_NtkDeleteObj(pNet); else if ( Abc_ObjFaninNum(pNet) == 0 ) Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(pNtk) ); } // check if constant 1 net is used pNet = Abc_NtkFindNet( pNtk, "1\'b1" ); if ( pNet ) { if ( Abc_ObjFanoutNum(pNet) == 0 ) Abc_NtkDeleteObj(pNet); else if ( Abc_ObjFaninNum(pNet) == 0 ) Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst1(pNtk) ); } // fix the net drivers Abc_NtkFixNonDrivenNets( pNtk ); // reorder the CI/COs to PI/POs first Abc_NtkOrderCisCos( pNtk ); } /**Function************************************************************* Synopsis [Duplicate the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin; int i, k; if ( pNtk == NULL ) return NULL; // start the network pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); // copy the internal nodes if ( Abc_NtkIsStrash(pNtk) ) { // copy the AND gates Abc_AigForEachAnd( pNtk, pObj, i ) pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); // relink the choice nodes Abc_AigForEachAnd( pNtk, pObj, i ) if ( pObj->pData ) pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy; // relink the CO nodes Abc_NtkForEachCo( pNtk, pObj, i ) Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); // get the number of nodes before and after if ( Abc_NtkNodeNum(pNtk) != Abc_NtkNodeNum(pNtkNew) ) printf( "Warning: Structural hashing during duplication reduced %d nodes (this is a minor bug).\n", Abc_NtkNodeNum(pNtk) - Abc_NtkNodeNum(pNtkNew) ); } else { // duplicate the nets and nodes (CIs/COs/latches already dupped) Abc_NtkForEachObj( pNtk, pObj, i ) if ( pObj->pCopy == NULL ) Abc_NtkDupObj(pNtkNew, pObj, Abc_NtkHasBlackbox(pNtk) && Abc_ObjIsNet(pObj)); // reconnect all objects (no need to transfer attributes on edges) Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); // move object IDs if ( pNtk->vOrigNodeIds ) { pNtkNew->vOrigNodeIds = Vec_IntStartFull( Abc_NtkObjNumMax(pNtkNew) ); Abc_NtkForEachObj( pNtk, pObj, i ) if ( pObj->pCopy && Vec_IntEntry(pNtk->vOrigNodeIds, pObj->Id) > 0 ) Vec_IntWriteEntry( pNtkNew->vOrigNodeIds, pObj->pCopy->Id, Vec_IntEntry(pNtk->vOrigNodeIds, pObj->Id) ); } } // duplicate the EXDC Ntk if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); if ( pNtk->pExcare ) pNtkNew->pExcare = Abc_NtkDup( (Abc_Ntk_t *)pNtk->pExcare ); // duplicate timing manager if ( pNtk->pManTime ) Abc_NtkTimeInitialize( pNtkNew, pNtk ); if ( pNtk->vPhases ) Abc_NtkTransferPhases( pNtkNew, pNtk ); if ( pNtk->pWLoadUsed ) pNtkNew->pWLoadUsed = Abc_UtilStrsav( pNtk->pWLoadUsed ); // check correctness if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); pNtk->pCopy = pNtkNew; return pNtkNew; } Abc_Ntk_t * Abc_NtkDupDfs( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin; int i, k; if ( pNtk == NULL ) return NULL; assert( !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsNetlist(pNtk) ); // start the network pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); // copy the internal nodes vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 0 ); Vec_PtrFree( vNodes ); // reconnect all objects (no need to transfer attributes on edges) Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) Abc_ObjForEachFanin( pObj, pFanin, k ) if ( pObj->pCopy && pFanin->pCopy ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); // duplicate the EXDC Ntk if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); if ( pNtk->pExcare ) pNtkNew->pExcare = Abc_NtkDup( (Abc_Ntk_t *)pNtk->pExcare ); // duplicate timing manager if ( pNtk->pManTime ) Abc_NtkTimeInitialize( pNtkNew, pNtk ); if ( pNtk->vPhases ) Abc_NtkTransferPhases( pNtkNew, pNtk ); if ( pNtk->pWLoadUsed ) pNtkNew->pWLoadUsed = Abc_UtilStrsav( pNtk->pWLoadUsed ); // check correctness if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); pNtk->pCopy = pNtkNew; return pNtkNew; } Abc_Ntk_t * Abc_NtkDupDfsNoBarBufs( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin; int i, k; if ( pNtk == NULL ) return NULL; assert( Abc_NtkIsLogic(pNtk) ); assert( pNtk->nBarBufs2 > 0 ); // start the network pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); // copy the internal nodes vNodes = Abc_NtkDfs2( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) if ( Abc_ObjIsBarBuf(pObj) ) pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy; else Abc_NtkDupObj( pNtkNew, pObj, 0 ); Vec_PtrFree( vNodes ); // reconnect all objects (no need to transfer attributes on edges) Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) && !Abc_ObjIsBarBuf(pObj) ) Abc_ObjForEachFanin( pObj, pFanin, k ) if ( pObj->pCopy && pFanin->pCopy ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); // duplicate the EXDC Ntk if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); if ( pNtk->pExcare ) pNtkNew->pExcare = Abc_NtkDup( (Abc_Ntk_t *)pNtk->pExcare ); // duplicate timing manager if ( pNtk->pManTime ) Abc_NtkTimeInitialize( pNtkNew, pNtk ); if ( pNtk->vPhases ) Abc_NtkTransferPhases( pNtkNew, pNtk ); if ( pNtk->pWLoadUsed ) pNtkNew->pWLoadUsed = Abc_UtilStrsav( pNtk->pWLoadUsed ); // check correctness if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); pNtk->pCopy = pNtkNew; return pNtkNew; } /**Function************************************************************* Synopsis [Duplicate the AIG while adding latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkRestrashWithLatches( Abc_Ntk_t * pNtk, int nLatches ) { Abc_Ntk_t * pNtkAig; Abc_Obj_t * pObj; int i; assert( Abc_NtkIsStrash(pNtk) ); // start the new network (constants and CIs of the old network will point to the their counterparts in the new network) pNtkAig = Abc_NtkStartFromWithLatches( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG, nLatches ); // restrash the nodes (assuming a topological order of the old network) Abc_NtkForEachNode( pNtk, pObj, i ) pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); // finalize the network Abc_NtkFinalize( pNtk, pNtkAig ); // make sure everything is okay if ( !Abc_NtkCheck( pNtkAig ) ) { printf( "Abc_NtkStrash: The network check has failed.\n" ); Abc_NtkDelete( pNtkAig ); return NULL; } return pNtkAig; } /**Function************************************************************* Synopsis [Duplicate the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDupTransformMiter( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pObj2, * pMiter; int i; assert( Abc_NtkIsStrash(pNtk) ); // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); pNtkNew->nConstrs = pNtk->nConstrs; pNtkNew->nBarBufs = pNtk->nBarBufs; // duplicate the name and the spec pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); // map the constant nodes Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); // clone CIs/CIs/boxes Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 1 ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 1 ), i++; Abc_NtkForEachBox( pNtk, pObj, i ) Abc_NtkDupBox( pNtkNew, pObj, 1 ); // copy the AND gates Abc_AigForEachAnd( pNtk, pObj, i ) pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); // create new miters Abc_NtkForEachPo( pNtk, pObj, i ) { pObj2 = Abc_NtkPo( pNtk, ++i ); pMiter = Abc_AigXor( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Copy(pObj2) ); Abc_ObjAddFanin( pObj->pCopy, pMiter ); } Abc_NtkForEachLatchInput( pNtk, pObj, i ) Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); // cleanup Abc_AigCleanup( (Abc_Aig_t *)pNtkNew->pManFunc ); // check that the CI/CO/latches are copied correctly assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); assert( Abc_NtkPoNum(pNtk) == 2*Abc_NtkPoNum(pNtkNew) ); assert( Abc_NtkLatchNum(pNtk) == Abc_NtkLatchNum(pNtkNew) ); return pNtkNew; } /**Function************************************************************* Synopsis [Duplicate the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk ) { char Buffer[500]; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin; int i, k; assert( Abc_NtkIsLogic(pNtk) ); // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); sprintf( Buffer, "%s%s", pNtk->pName, "_2x" ); pNtkNew->pName = Extra_UtilStrsav(Buffer); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); // clone CIs/CIs/boxes Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_NtkForEachBox( pNtk, pObj, i ) Abc_NtkDupBox( pNtkNew, pObj, 0 ); // copy the internal nodes // duplicate the nets and nodes (CIs/COs/latches already dupped) Abc_NtkForEachObj( pNtk, pObj, i ) if ( pObj->pCopy == NULL ) Abc_NtkDupObj(pNtkNew, pObj, 0); // reconnect all objects (no need to transfer attributes on edges) Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); // clone CIs/CIs/boxes Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_NtkForEachBox( pNtk, pObj, i ) Abc_NtkDupBox( pNtkNew, pObj, 0 ); // copy the internal nodes // duplicate the nets and nodes (CIs/COs/latches already dupped) Abc_NtkForEachObj( pNtk, pObj, i ) if ( pObj->pCopy == NULL ) Abc_NtkDupObj(pNtkNew, pObj, 0); // reconnect all objects (no need to transfer attributes on edges) Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); // assign names Abc_NtkForEachCi( pNtk, pObj, i ) { Abc_ObjAssignName( Abc_NtkCi(pNtkNew, i), "1_", Abc_ObjName(pObj) ); Abc_ObjAssignName( Abc_NtkCi(pNtkNew, Abc_NtkCiNum(pNtk) + i), "2_", Abc_ObjName(pObj) ); } Abc_NtkForEachCo( pNtk, pObj, i ) { Abc_ObjAssignName( Abc_NtkCo(pNtkNew, i), "1_", Abc_ObjName(pObj) ); Abc_ObjAssignName( Abc_NtkCo(pNtkNew, Abc_NtkCoNum(pNtk) + i), "2_", Abc_ObjName(pObj) ); } Abc_NtkOrderCisCos( pNtkNew ); // perform the final check if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Duplicate the bottom levels of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkBottom( Abc_Ntk_t * pNtk, int Level ) { char Buffer[500]; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin; int i, k; assert( Abc_NtkIsLogic(pNtk) ); assert( Abc_NtkLatchNum(pNtk) == 0 ); // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); sprintf( Buffer, "%s%s", pNtk->pName, "_bot" ); pNtkNew->pName = Extra_UtilStrsav(Buffer); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); // clone CIs/CIs/boxes Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 1 ); // copy the internal nodes // duplicate the nets and nodes (CIs/COs/latches already dupped) Abc_NtkForEachObj( pNtk, pObj, i ) if ( pObj->pCopy == NULL && Abc_ObjIsNode(pObj) && Abc_ObjLevel(pObj) <= Level ) Abc_NtkDupObj(pNtkNew, pObj, 0); // reconnect all objects (no need to transfer attributes on edges) Abc_NtkForEachObj( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) if ( pObj->pCopy && pFanin->pCopy ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); // create new primary outputs Abc_NtkForEachObj( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) if ( !pObj->pCopy && pFanin->pCopy && Abc_ObjIsNode(pFanin) ) { Abc_Obj_t * pNodeNew = Abc_NtkCreatePo(pNtkNew); Abc_ObjAddFanin( pNodeNew, pFanin->pCopy ); Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNodeNew), NULL ); } // perform the final check if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkBottom(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Attaches the second network at the bottom of the first.] Description [Returns the first network. Deletes the second network.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkAttachBottom( Abc_Ntk_t * pNtkTop, Abc_Ntk_t * pNtkBottom ) { Abc_Obj_t * pObj, * pFanin, * pBuffer; Vec_Ptr_t * vNodes; int i, k; assert( pNtkBottom != NULL ); if ( pNtkTop == NULL ) return pNtkBottom; // make sure the networks are combinational assert( Abc_NtkPiNum(pNtkTop) == Abc_NtkCiNum(pNtkTop) ); assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkCiNum(pNtkBottom) ); // make sure the POs of the bottom correspond to the PIs of the top assert( Abc_NtkPoNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) ); assert( Abc_NtkPiNum(pNtkBottom) < Abc_NtkPiNum(pNtkTop) ); // add buffers for the PIs of the top - save results in the POs of the bottom Abc_NtkForEachPi( pNtkTop, pObj, i ) { pBuffer = Abc_NtkCreateNodeBuf( pNtkTop, NULL ); Abc_ObjTransferFanout( pObj, pBuffer ); Abc_NtkPo(pNtkBottom, i)->pCopy = pBuffer; } // remove useless PIs of the top for ( i = Abc_NtkPiNum(pNtkTop) - 1; i >= Abc_NtkPiNum(pNtkBottom); i-- ) Abc_NtkDeleteObj( Abc_NtkPi(pNtkTop, i) ); assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) ); // copy the bottom network Abc_NtkForEachPi( pNtkBottom, pObj, i ) Abc_NtkPi(pNtkBottom, i)->pCopy = Abc_NtkPi(pNtkTop, i); // construct all nodes vNodes = Abc_NtkDfs( pNtkBottom, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { Abc_NtkDupObj(pNtkTop, pObj, 0); Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } Vec_PtrFree( vNodes ); // connect the POs Abc_NtkForEachPo( pNtkBottom, pObj, i ) Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy ); // delete old network Abc_NtkDelete( pNtkBottom ); // return the network if ( !Abc_NtkCheck( pNtkTop ) ) fprintf( stdout, "Abc_NtkAttachBottom(): Network check has failed.\n" ); return pNtkTop; } /**Function************************************************************* Synopsis [Creates the network composed of one logic cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis ) { Abc_Ntk_t * pNtkNew; Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; char Buffer[1000]; int i, k; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); assert( Abc_ObjIsNode(pNode) || (Abc_NtkIsStrash(pNtk) && (Abc_AigNodeIsConst(pNode) || Abc_ObjIsCi(pNode))) ); // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); // set the name sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName ); pNtkNew->pName = Extra_UtilStrsav(Buffer); // establish connection between the constant nodes if ( Abc_NtkIsStrash(pNtk) ) Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); // collect the nodes in the TFI of the output (mark the TFI) vNodes = Abc_NtkDfsNodes( pNtk, &pNode, 1 ); // create the PIs Abc_NtkForEachCi( pNtk, pObj, i ) { if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS { pObj->pCopy = Abc_NtkCreatePi(pNtkNew); Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); } } // add the PO corresponding to this output pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL ); // copy the nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { // if it is an AIG, add to the hash table if ( Abc_NtkIsStrash(pNtk) ) { pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); } else { Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } } // connect the internal nodes to the new CO Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy ); Vec_PtrFree( vNodes ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Creates the network composed of several logic cones.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis ) { Abc_Ntk_t * pNtkNew; Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; char Buffer[1000]; int i, k; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); // set the name sprintf( Buffer, "%s_part", pNtk->pName ); pNtkNew->pName = Extra_UtilStrsav(Buffer); // establish connection between the constant nodes if ( Abc_NtkIsStrash(pNtk) ) Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); // collect the nodes in the TFI of the output (mark the TFI) vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) ); // create the PIs Abc_NtkForEachCi( pNtk, pObj, i ) { if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS { pObj->pCopy = Abc_NtkCreatePi(pNtkNew); Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); } } // copy the nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { // if it is an AIG, add to the hash table if ( Abc_NtkIsStrash(pNtk) ) { pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); } else { Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } } Vec_PtrFree( vNodes ); // add the POs corresponding to the root nodes Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { // create the PO node pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); // connect the internal nodes to the new CO if ( Abc_ObjIsCo(pObj) ) Abc_ObjAddFanin( pNodeCoNew, Abc_ObjChild0Copy(pObj) ); else Abc_ObjAddFanin( pNodeCoNew, pObj->pCopy ); // assign the name Abc_ObjAssignName( pNodeCoNew, Abc_ObjName(pObj), NULL ); } if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkCreateConeArray(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Adds new nodes to the cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i, iNodeId; assert( Abc_NtkIsStrash(pNtkNew) ); assert( Abc_NtkIsStrash(pNtk) ); // collect the nodes in the TFI of the output (mark the TFI) vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) ); // establish connection between the constant nodes Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); // create the PIs Abc_NtkForEachCi( pNtk, pObj, i ) { // skip CIs that are not used if ( !Abc_NodeIsTravIdCurrent(pObj) ) continue; // find the corresponding CI in the new network iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); if ( iNodeId == -1 ) { pObj->pCopy = Abc_NtkCreatePi(pNtkNew); Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); } else pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId ); } // copy the nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); Vec_PtrFree( vNodes ); // do not add the COs if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkAppendToCone(): Network check has failed.\n" ); } /**Function************************************************************* Synopsis [Creates the network composed of MFFC of one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; Vec_Ptr_t * vCone, * vSupp; char Buffer[1000]; int i, k; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); assert( Abc_ObjIsNode(pNode) ); // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); // set the name sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName ); pNtkNew->pName = Extra_UtilStrsav(Buffer); // establish connection between the constant nodes if ( Abc_NtkIsStrash(pNtk) ) Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); // collect the nodes in MFFC vCone = Vec_PtrAlloc( 100 ); vSupp = Vec_PtrAlloc( 100 ); Abc_NodeDeref_rec( pNode ); Abc_NodeMffcConeSupp( pNode, vCone, vSupp ); Abc_NodeRef_rec( pNode ); // create the PIs Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i ) { pObj->pCopy = Abc_NtkCreatePi(pNtkNew); Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); } // create the PO pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL ); // copy the nodes Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, i ) { // if it is an AIG, add to the hash table if ( Abc_NtkIsStrash(pNtk) ) { pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); } else { Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); } } // connect the topmost node Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy ); Vec_PtrFree( vCone ); Vec_PtrFree( vSupp ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkCreateMffc(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Creates the miter composed of one multi-output cone.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFinal, * pOther, * pNodePo; int i; assert( Abc_NtkIsLogic(pNtk) ); // start the network Abc_NtkCleanCopy( pNtk ); pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); // collect the nodes in the TFI of the output vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)vRoots->pArray, vRoots->nSize ); // create the PIs Abc_NtkForEachCi( pNtk, pObj, i ) { pObj->pCopy = Abc_NtkCreatePi(pNtkNew); Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); } // copy the nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->pCopy = Abc_NodeStrash( pNtkNew, pObj, 0 ); Vec_PtrFree( vNodes ); // add the PO pFinal = Abc_AigConst1( pNtkNew ); Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) { if ( Abc_ObjIsCo(pObj) ) pOther = Abc_ObjFanin0(pObj)->pCopy; else pOther = pObj->pCopy; if ( Vec_IntEntry(vValues, i) == 0 ) pOther = Abc_ObjNot(pOther); pFinal = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pFinal, pOther ); } // add the PO corresponding to this output pNodePo = Abc_NtkCreatePo( pNtkNew ); Abc_ObjAddFanin( pNodePo, pFinal ); Abc_ObjAssignName( pNodePo, "miter", NULL ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkCreateTarget(): Network check has failed.\n" ); return pNtkNew; } /**Function************************************************************* Synopsis [Creates the network composed of one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pFanin, * pNodePo; int i; // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); pNtkNew->pName = Extra_UtilStrsav(Abc_ObjName(pNode)); // add the PIs corresponding to the fanins of the node Abc_ObjForEachFanin( pNode, pFanin, i ) { pFanin->pCopy = Abc_NtkCreatePi( pNtkNew ); Abc_ObjAssignName( pFanin->pCopy, Abc_ObjName(pFanin), NULL ); } // duplicate and connect the node pNode->pCopy = Abc_NtkDupObj( pNtkNew, pNode, 0 ); Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_ObjAddFanin( pNode->pCopy, pFanin->pCopy ); // create the only PO pNodePo = Abc_NtkCreatePo( pNtkNew ); Abc_ObjAddFanin( pNodePo, pNode->pCopy ); Abc_ObjAssignName( pNodePo, Abc_ObjName(pNode), 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.] 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pFanin, * pNode, * pNodePo; Vec_Ptr_t * vNames; int i, nVars; // 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 pNode = Abc_NtkCreateNode( pNtkNew ); Abc_NtkForEachPi( pNtkNew, pFanin, i ) 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 ); Abc_ObjAssignName( pNodePo, "F", NULL ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkCreateWithNode(): Network check has failed.\n" ); 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 ); if ( Abc_SopGetVarNum(pSop) > 0 ) 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.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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; // free EXDC Ntk if ( pNtk->pExdc ) Abc_NtkDelete( pNtk->pExdc ); if ( pNtk->pExcare ) Abc_NtkDelete( (Abc_Ntk_t *)pNtk->pExcare ); // dereference the BDDs if ( Abc_NtkHasBdd(pNtk) ) { #ifdef ABC_USE_CUDD Abc_NtkForEachNode( pNtk, pObj, i ) Cudd_RecursiveDeref( (DdManager *)pNtk->pManFunc, (DdNode *)pObj->pData ); #endif } // make sure all the marks are clean Abc_NtkForEachObj( pNtk, pObj, i ) { // free large fanout arrays // if ( pNtk->pMmObj && pObj->vFanouts.nCap * 4 > LargePiece ) // 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 ); 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 ) { Abc_NtkForEachObj( pNtk, pObj, i ) { ABC_FREE( pObj->vFanouts.pArray ); ABC_FREE( pObj->vFanins.pArray ); } } if ( pNtk->pMmObj == NULL ) { Abc_NtkForEachObj( pNtk, pObj, i ) ABC_FREE( pObj ); } // free the arrays Vec_PtrFree( pNtk->vPios ); Vec_PtrFree( pNtk->vPis ); Vec_PtrFree( pNtk->vPos ); Vec_PtrFree( pNtk->vCis ); Vec_PtrFree( pNtk->vCos ); Vec_PtrFree( pNtk->vObjs ); Vec_PtrFree( pNtk->vBoxes ); ABC_FREE( pNtk->vTravIds.pArray ); if ( pNtk->vLevelsR ) Vec_IntFree( pNtk->vLevelsR ); ABC_FREE( pNtk->pModel ); ABC_FREE( pNtk->pSeqModel ); if ( pNtk->vSeqModelVec ) Vec_PtrFreeFree( pNtk->vSeqModelVec ); TotalMemory = 0; TotalMemory += pNtk->pMmObj? Mem_FixedReadMemUsage(pNtk->pMmObj) : 0; TotalMemory += pNtk->pMmStep? Mem_StepReadMemUsage(pNtk->pMmStep) : 0; // fprintf( stdout, "The total memory allocated internally by the network = %0.2f MB.\n", ((double)TotalMemory)/(1<<20) ); // free the storage if ( pNtk->pMmObj ) Mem_FixedStop( pNtk->pMmObj, 0 ); if ( pNtk->pMmStep ) Mem_StepStop ( pNtk->pMmStep, 0 ); // name manager Nm_ManFree( pNtk->pManName ); // free the timing manager if ( pNtk->pManTime ) Abc_ManTimeStop( pNtk->pManTime ); Vec_IntFreeP( &pNtk->vPhases ); // start the functionality manager if ( Abc_NtkIsStrash(pNtk) ) Abc_AigFree( (Abc_Aig_t *)pNtk->pManFunc ); else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) Mem_FlexStop( (Mem_Flex_t *)pNtk->pManFunc, 0 ); #ifdef ABC_USE_CUDD else if ( Abc_NtkHasBdd(pNtk) ) Extra_StopManager( (DdManager *)pNtk->pManFunc ); #endif else if ( Abc_NtkHasAig(pNtk) ) { if ( pNtk->pManFunc ) Hop_ManStop( (Hop_Man_t *)pNtk->pManFunc ); } else if ( Abc_NtkHasMapping(pNtk) ) pNtk->pManFunc = NULL; else if ( !Abc_NtkHasBlackbox(pNtk) ) assert( 0 ); // free the hierarchy if ( pNtk->pDesign ) { Abc_DesFree( pNtk->pDesign, pNtk ); pNtk->pDesign = NULL; } // if ( pNtk->pBlackBoxes ) // Vec_IntFree( pNtk->pBlackBoxes ); // free node attributes Vec_PtrForEachEntry( Abc_Obj_t *, pNtk->vAttrs, pAttrMan, i ) if ( pAttrMan ) Vec_AttFree( (Vec_Att_t *)pAttrMan, 1 ); assert( pNtk->pSCLib == NULL ); Vec_IntFreeP( &pNtk->vGates ); Vec_PtrFree( pNtk->vAttrs ); Vec_IntFreeP( &pNtk->vNameIds ); ABC_FREE( pNtk->pWLoadUsed ); ABC_FREE( pNtk->pName ); ABC_FREE( pNtk->pSpec ); ABC_FREE( pNtk->pLutTimes ); if ( pNtk->vOnehots ) Vec_VecFree( (Vec_Vec_t *)pNtk->vOnehots ); Vec_PtrFreeP( &pNtk->vLtlProperties ); Vec_IntFreeP( &pNtk->vObjPerm ); Vec_IntFreeP( &pNtk->vTopo ); Vec_IntFreeP( &pNtk->vFins ); Vec_IntFreeP( &pNtk->vOrigNodeIds ); ABC_FREE( pNtk ); } /**Function************************************************************* Synopsis [Reads the verilog file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNets; Abc_Obj_t * pNet, * pNode; int i; if ( Abc_NtkNodeNum(pNtk) == 0 && Abc_NtkBoxNum(pNtk) == 0 ) return; // special case pNet = Abc_NtkFindNet( pNtk, "[_c1_]" ); if ( pNet != NULL ) { pNode = Abc_NtkCreateNodeConst1( pNtk ); Abc_ObjAddFanin( pNet, pNode ); } // check for non-driven nets vNets = Vec_PtrAlloc( 100 ); Abc_NtkForEachNet( pNtk, pNet, i ) { if ( Abc_ObjFaninNum(pNet) > 0 ) continue; // add the constant 0 driver pNode = Abc_NtkCreateNodeConst0( pNtk ); // add the fanout net Abc_ObjAddFanin( pNet, pNode ); // add the net to those for which the warning will be printed Vec_PtrPush( vNets, pNet ); } // print the warning if ( vNets->nSize > 0 ) { printf( "Warning: Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pNtk->pName ); Vec_PtrForEachEntry( Abc_Obj_t *, vNets, pNet, i ) { printf( "%s%s", (i? ", ": ""), Abc_ObjName(pNet) ); if ( i == 3 ) { if ( Vec_PtrSize(vNets) > 3 ) printf( " ..." ); break; } } printf( "\n" ); } Vec_PtrFree( vNets ); } /**Function************************************************************* Synopsis [Converts the network to combinational.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMakeComb( Abc_Ntk_t * pNtk, int fRemoveLatches ) { Abc_Obj_t * pObj; int i; if ( Abc_NtkIsComb(pNtk) ) return; assert( !Abc_NtkIsNetlist(pNtk) ); assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); // detach the latches // Abc_NtkForEachLatch( pNtk, pObj, i ) Vec_PtrForEachEntryReverse( Abc_Obj_t *, pNtk->vBoxes, pObj, i ) Abc_NtkDeleteObj( pObj ); assert( Abc_NtkLatchNum(pNtk) == 0 ); assert( Abc_NtkBoxNum(pNtk) == 0 ); // move CIs to become PIs Vec_PtrClear( pNtk->vPis ); Abc_NtkForEachCi( pNtk, pObj, i ) { if ( Abc_ObjIsBo(pObj) ) { pObj->Type = ABC_OBJ_PI; pNtk->nObjCounts[ABC_OBJ_PI]++; pNtk->nObjCounts[ABC_OBJ_BO]--; } Vec_PtrPush( pNtk->vPis, pObj ); } assert( Abc_NtkBoNum(pNtk) == 0 ); if ( fRemoveLatches ) { // remove registers Vec_Ptr_t * vBos; vBos = Vec_PtrAlloc( 100 ); Vec_PtrClear( pNtk->vPos ); Abc_NtkForEachCo( pNtk, pObj, i ) if ( Abc_ObjIsBi(pObj) ) Vec_PtrPush( vBos, pObj ); else Vec_PtrPush( pNtk->vPos, pObj ); // remove COs Vec_PtrFree( pNtk->vCos ); pNtk->vCos = NULL; // remove the BOs Vec_PtrForEachEntry( Abc_Obj_t *, vBos, pObj, i ) Abc_NtkDeleteObj( pObj ); Vec_PtrFree( vBos ); // create COs pNtk->vCos = Vec_PtrDup( pNtk->vPos ); // cleanup if ( Abc_NtkIsLogic(pNtk) ) Abc_NtkCleanup( pNtk, 0 ); else if ( Abc_NtkIsStrash(pNtk) ) Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); else assert( 0 ); } else { // move COs to become POs Vec_PtrClear( pNtk->vPos ); Abc_NtkForEachCo( pNtk, pObj, i ) { if ( Abc_ObjIsBi(pObj) ) { pObj->Type = ABC_OBJ_PO; pNtk->nObjCounts[ABC_OBJ_PO]++; pNtk->nObjCounts[ABC_OBJ_BI]--; } Vec_PtrPush( pNtk->vPos, pObj ); } } assert( Abc_NtkBiNum(pNtk) == 0 ); if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkMakeComb(): Network check has failed.\n" ); } /**Function************************************************************* Synopsis [Converts the network to sequential.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMakeSeq( Abc_Ntk_t * pNtk, int nLatchesToAdd ) { Abc_Obj_t * pObjLi, * pObjLo, * pObj; int i; assert( Abc_NtkBoxNum(pNtk) == 0 ); if ( !Abc_NtkIsComb(pNtk) ) { printf( "The network is a not a combinational one.\n" ); return; } if ( nLatchesToAdd >= Abc_NtkPiNum(pNtk) ) { printf( "The number of latches is more or equal than the number of PIs.\n" ); return; } if ( nLatchesToAdd >= Abc_NtkPoNum(pNtk) ) { printf( "The number of latches is more or equal than the number of POs.\n" ); return; } // move the last PIs to become CIs Vec_PtrClear( pNtk->vPis ); Abc_NtkForEachCi( pNtk, pObj, i ) { if ( i < Abc_NtkCiNum(pNtk) - nLatchesToAdd ) { Vec_PtrPush( pNtk->vPis, pObj ); continue; } pObj->Type = ABC_OBJ_BO; pNtk->nObjCounts[ABC_OBJ_PI]--; pNtk->nObjCounts[ABC_OBJ_BO]++; } // move the last POs to become COs Vec_PtrClear( pNtk->vPos ); Abc_NtkForEachCo( pNtk, pObj, i ) { if ( i < Abc_NtkCoNum(pNtk) - nLatchesToAdd ) { Vec_PtrPush( pNtk->vPos, pObj ); continue; } pObj->Type = ABC_OBJ_BI; pNtk->nObjCounts[ABC_OBJ_PO]--; pNtk->nObjCounts[ABC_OBJ_BI]++; } // create latches for ( i = 0; i < nLatchesToAdd; i++ ) { pObjLo = Abc_NtkCi( pNtk, Abc_NtkCiNum(pNtk) - nLatchesToAdd + i ); pObjLi = Abc_NtkCo( pNtk, Abc_NtkCoNum(pNtk) - nLatchesToAdd + i ); pObj = Abc_NtkCreateLatch( pNtk ); Abc_ObjAddFanin( pObj, pObjLi ); Abc_ObjAddFanin( pObjLo, pObj ); Abc_LatchSetInit0( pObj ); } if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkMakeSeq(): Network check has failed.\n" ); } /**Function************************************************************* Synopsis [Keeps POs in the array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkSelectPos( Abc_Ntk_t * pNtkInit, Vec_Int_t * vPoIds ) { Abc_Ntk_t * pNtk; Vec_Ptr_t * vPosLeft; Vec_Ptr_t * vCosLeft; Abc_Obj_t * pNodePo; int i, Index; assert( !Abc_NtkIsNetlist(pNtkInit) ); assert( Abc_NtkHasOnlyLatchBoxes(pNtkInit) ); pNtk = Abc_NtkDup( pNtkInit ); if ( Abc_NtkPoNum(pNtk) == 1 ) return pNtk; vPosLeft = Vec_PtrAlloc( Vec_IntSize(vPoIds) ); Vec_IntForEachEntry( vPoIds, Index, i ) { Vec_PtrPush( vPosLeft, Abc_NtkPo(pNtk, Index) ); Vec_PtrWriteEntry( pNtk->vPos, Index, NULL ); } // filter COs vCosLeft = Vec_PtrDup( vPosLeft ); for ( i = Abc_NtkPoNum(pNtk); i < Abc_NtkCoNum(pNtk); i++ ) Vec_PtrPush( vCosLeft, Abc_NtkCo(pNtk, i) ); // remove remaiing POs Abc_NtkForEachPo( pNtk, pNodePo, i ) if ( pNodePo ) Abc_NtkDeleteObjPo( pNodePo ); // update arrays Vec_PtrFree( pNtk->vPos ); pNtk->vPos = vPosLeft; Vec_PtrFree( pNtk->vCos ); pNtk->vCos = vCosLeft; // clean the network if ( Abc_NtkIsStrash(pNtk) ) { Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); if ( Abc_NtkLatchNum(pNtk) ) printf( "Run sequential cleanup (\"scl\") to get rid of dangling logic.\n" ); } else { if ( Abc_NtkLatchNum(pNtk) ) printf( "Run sequential cleanup (\"st; scl\") to get rid of dangling logic.\n" ); } if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkMakeComb(): Network check has failed.\n" ); return pNtk; } /**Function************************************************************* Synopsis [Removes all POs, except one.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkMakeOnePo( Abc_Ntk_t * pNtkInit, int Output, int nRange ) { Abc_Ntk_t * pNtk; Vec_Ptr_t * vPosLeft; Vec_Ptr_t * vCosLeft; Abc_Obj_t * pNodePo; int i; assert( !Abc_NtkIsNetlist(pNtkInit) ); assert( Abc_NtkHasOnlyLatchBoxes(pNtkInit) ); if ( Output < 0 || Output >= Abc_NtkPoNum(pNtkInit) ) { printf( "PO index is incorrect.\n" ); return NULL; } pNtk = Abc_NtkDup( pNtkInit ); if ( Abc_NtkPoNum(pNtk) == 1 ) return pNtk; if ( nRange < 1 ) nRange = 1; // filter POs vPosLeft = Vec_PtrAlloc( nRange ); Abc_NtkForEachPo( pNtk, pNodePo, i ) if ( i < Output || i >= Output + nRange ) Abc_NtkDeleteObjPo( pNodePo ); else Vec_PtrPush( vPosLeft, pNodePo ); // filter COs vCosLeft = Vec_PtrDup( vPosLeft ); for ( i = Abc_NtkPoNum(pNtk); i < Abc_NtkCoNum(pNtk); i++ ) Vec_PtrPush( vCosLeft, Abc_NtkCo(pNtk, i) ); // update arrays Vec_PtrFree( pNtk->vPos ); pNtk->vPos = vPosLeft; Vec_PtrFree( pNtk->vCos ); pNtk->vCos = vCosLeft; // clean the network if ( Abc_NtkIsStrash(pNtk) ) { Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); if ( Abc_NtkLatchNum(pNtk) ) printf( "Run sequential cleanup (\"scl\") to get rid of dangling logic.\n" ); } else { if ( Abc_NtkLatchNum(pNtk) ) printf( "Run sequential cleanup (\"st; scl\") to get rid of dangling logic.\n" ); } if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkMakeComb(): Network check has failed.\n" ); return pNtk; } /**Function************************************************************* Synopsis [Removes POs with suppsize less than 2 and PIs without fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkTrim( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i, k, m; // filter POs k = m = 0; Abc_NtkForEachCo( pNtk, pObj, i ) { if ( Abc_ObjIsPo(pObj) ) { // remove constant nodes and PI pointers if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 0 ) { Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) ); if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 && !Abc_ObjIsPi(Abc_ObjFanin0(pObj)) ) Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 ); pNtk->vObjs->pArray[pObj->Id] = NULL; pObj->Id = (1<<26)-1; pNtk->nObjCounts[pObj->Type]--; pNtk->nObjs--; Abc_ObjRecycle( pObj ); continue; } // remove buffers/inverters of PIs if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 1 ) { if ( Abc_ObjIsPi(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) ) { Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) ); if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 ) Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 ); pNtk->vObjs->pArray[pObj->Id] = NULL; pObj->Id = (1<<26)-1; pNtk->nObjCounts[pObj->Type]--; pNtk->nObjs--; Abc_ObjRecycle( pObj ); continue; } } Vec_PtrWriteEntry( pNtk->vPos, m++, pObj ); } Vec_PtrWriteEntry( pNtk->vCos, k++, pObj ); } Vec_PtrShrink( pNtk->vPos, m ); Vec_PtrShrink( pNtk->vCos, k ); // filter PIs k = m = 0; Abc_NtkForEachCi( pNtk, pObj, i ) { if ( Abc_ObjIsPi(pObj) ) { if ( Abc_ObjFanoutNum(pObj) == 0 ) { pNtk->vObjs->pArray[pObj->Id] = NULL; pObj->Id = (1<<26)-1; pNtk->nObjCounts[pObj->Type]--; pNtk->nObjs--; Abc_ObjRecycle( pObj ); continue; } Vec_PtrWriteEntry( pNtk->vPis, m++, pObj ); } Vec_PtrWriteEntry( pNtk->vCis, k++, pObj ); } Vec_PtrShrink( pNtk->vPis, m ); Vec_PtrShrink( pNtk->vCis, k ); return Abc_NtkDup( pNtk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDropSatOutputs( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCexes, int fVerbose ) { Abc_Obj_t * pObj, * pConst0, * pFaninNew; int i, Counter = 0; assert( Vec_PtrSize(vCexes) == Abc_NtkPoNum(pNtk) ); pConst0 = Abc_ObjNot( Abc_AigConst1(pNtk) ); Abc_NtkForEachPo( pNtk, pObj, i ) { if ( Vec_PtrEntry( vCexes, i ) == NULL ) continue; Counter++; pFaninNew = Abc_ObjNotCond( pConst0, Abc_ObjFaninC0(pObj) ); Abc_ObjPatchFanin( pObj, Abc_ObjFanin0(pObj), pFaninNew ); assert( Abc_ObjChild0(pObj) == pConst0 ); // if a PO is driven by a latch, they have the same name... // if ( Abc_ObjIsBo(pObj) ) // Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pObj) ); } if ( fVerbose ) printf( "Logic cones of %d POs have been replaced by constant 0.\n", Counter ); Counter = Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); // printf( "Cleanup removed %d nodes.\n", Counter ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDropOneOutput( Abc_Ntk_t * pNtk, int iOutput, int fSkipSweep, int fUseConst1 ) { Abc_Obj_t * pObj, * pConst0, * pFaninNew; pObj = Abc_NtkPo( pNtk, iOutput ); if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pNtk) ) { if ( !Abc_ObjFaninC0(pObj) ^ fUseConst1 ) Abc_ObjXorFaninC( pObj, 0 ); return; } pConst0 = Abc_ObjNotCond( Abc_AigConst1(pNtk), !fUseConst1 ); pFaninNew = Abc_ObjNotCond( pConst0, Abc_ObjFaninC0(pObj) ); Abc_ObjPatchFanin( pObj, Abc_ObjFanin0(pObj), pFaninNew ); assert( Abc_ObjChild0(pObj) == pConst0 ); if ( fSkipSweep ) return; Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkSwapOneOutput( Abc_Ntk_t * pNtk, int iOutput ) { Abc_Obj_t * pObj1, * pObj2; Abc_Obj_t * pChild1Old, * pChild2Old; Abc_Obj_t * pChild1, * pChild2; if ( iOutput == 0 ) return; pObj1 = Abc_NtkPo( pNtk, 0 ); pObj2 = Abc_NtkPo( pNtk, iOutput ); if ( Abc_ObjFanin0(pObj1) == Abc_ObjFanin0(pObj2) ) { if ( Abc_ObjFaninC0(pObj1) ^ Abc_ObjFaninC0(pObj2) ) { Abc_ObjXorFaninC( pObj1, 0 ); Abc_ObjXorFaninC( pObj2, 0 ); } return; } pChild1Old = Abc_ObjChild0( pObj1 ); pChild2Old = Abc_ObjChild0( pObj2 ); pChild1 = Abc_ObjNotCond( pChild1Old, Abc_ObjFaninC0(pObj2) ); pChild2 = Abc_ObjNotCond( pChild2Old, Abc_ObjFaninC0(pObj1) ); Abc_ObjPatchFanin( pObj1, Abc_ObjFanin0(pObj1), pChild2 ); Abc_ObjPatchFanin( pObj2, Abc_ObjFanin0(pObj2), pChild1 ); assert( Abc_ObjChild0(pObj1) == pChild2Old ); assert( Abc_ObjChild0(pObj2) == pChild1Old ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRemovePo( Abc_Ntk_t * pNtk, int iOutput, int fRemoveConst0 ) { Abc_Obj_t * pObj = Abc_NtkPo(pNtk, iOutput); if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pNtk) && Abc_ObjFaninC0(pObj) == fRemoveConst0 ) Abc_NtkDeleteObj( pObj ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkReadSignalPerm2( char * pFileName, int nSignals ) { char Buffer[1000]; FILE * pFile; Vec_Int_t * vSignals; int iFlop = -1; pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open input file \"%s\".\n", pFileName ); return NULL; } vSignals = Vec_IntAlloc( nSignals ); while ( fgets( Buffer, 1000, pFile ) != NULL ) { if ( Buffer[0] == ' ' || Buffer[0] == '\r' || Buffer[0] == '\n' ) continue; iFlop = atoi( Buffer ); if ( iFlop < 0 || iFlop >= nSignals ) { printf( "The zero-based signal ID (%d) is out of range.\n", iFlop ); fclose( pFile ); Vec_IntFree( vSignals ); return NULL; } Vec_IntPush( vSignals, iFlop ); } fclose( pFile ); if ( Vec_IntSize(vSignals) != nSignals ) { printf( "The number of indexes read in from file (%d) is different from the number of signals in the circuit (%d).\n", Vec_IntSize(vSignals), nSignals ); Vec_IntFree( vSignals ); return NULL; } return vSignals; } Vec_Int_t * Abc_NtkReadSignalPerm( char * pFileName, int nSignals ) { int Num = -1; Vec_Int_t * vSignals; FILE * pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Cannot open input file \"%s\".\n", pFileName ); return NULL; } vSignals = Vec_IntAlloc( nSignals ); while ( fscanf( pFile, "%d", &Num ) == 1 ) { if ( Num <= 0 || Num > nSignals ) { printf( "The one-based signal ID (%d) is out of range (%d).\n", Num, nSignals ); fclose( pFile ); Vec_IntFree( vSignals ); return NULL; } Vec_IntPush( vSignals, Num-1 ); } fclose( pFile ); if ( Vec_IntSize(vSignals) != nSignals ) { printf( "The number of indexes read in from file (%d) is different from the number of signals in the circuit (%d).\n", Vec_IntSize(vSignals), nSignals ); Vec_IntFree( vSignals ); return NULL; } return vSignals; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPermute( Abc_Ntk_t * pNtk, int fInputs, int fOutputs, int fFlops, char * pInPermFile, char * pOutPermFile, char * pFlopPermFile ) { Abc_Obj_t * pTemp; Vec_Int_t * vInputs, * vOutputs, * vFlops, * vTemp; int i, k, Entry; // start permutation arrays if ( pInPermFile ) { vInputs = Abc_NtkReadSignalPerm( pInPermFile, Abc_NtkPiNum(pNtk) ); if ( vInputs == NULL ) return; fInputs = 1; } else vInputs = Vec_IntStartNatural( Abc_NtkPiNum(pNtk) ); if ( pOutPermFile ) { vOutputs = Abc_NtkReadSignalPerm( pOutPermFile, Abc_NtkPoNum(pNtk) ); if ( vOutputs == NULL ) return; fOutputs = 1; } else vOutputs = Vec_IntStartNatural( Abc_NtkPoNum(pNtk) ); if ( pFlopPermFile ) { vFlops = Abc_NtkReadSignalPerm( pFlopPermFile, Abc_NtkLatchNum(pNtk) ); if ( vFlops == NULL ) return; fFlops = 1; } else vFlops = Vec_IntStartNatural( Abc_NtkLatchNum(pNtk) ); // permute inputs Vec_Ptr_t * vCis = Vec_PtrDup(pNtk->vCis); Vec_Ptr_t * vCos = Vec_PtrDup(pNtk->vCos); Vec_Ptr_t * vFfs = Vec_PtrDup(pNtk->vBoxes); if ( fInputs ) for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) { if ( pInPermFile ) { k = Vec_IntEntry( vInputs, i ); pTemp = (Abc_Obj_t *)Vec_PtrEntry( vCis, k ); Vec_PtrWriteEntry( pNtk->vPis, i, pTemp ); Vec_PtrWriteEntry( pNtk->vCis, i, pTemp ); } else { k = rand() % Abc_NtkPiNum(pNtk); // swap indexes Entry = Vec_IntEntry( vInputs, i ); Vec_IntWriteEntry( vInputs, i, Vec_IntEntry(vInputs, k) ); Vec_IntWriteEntry( vInputs, k, Entry ); // swap PIs pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPis, i ); Vec_PtrWriteEntry( pNtk->vPis, i, Vec_PtrEntry(pNtk->vPis, k) ); Vec_PtrWriteEntry( pNtk->vPis, k, pTemp ); // swap CIs pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, i ); Vec_PtrWriteEntry( pNtk->vCis, i, Vec_PtrEntry(pNtk->vCis, k) ); Vec_PtrWriteEntry( pNtk->vCis, k, pTemp ); } //printf( "Swapping PIs %d and %d.\n", i, k ); } // permute outputs if ( fOutputs ) for ( i = 0; i < Abc_NtkPoNum(pNtk); i++ ) { if ( pOutPermFile ) { k = Vec_IntEntry( vOutputs, i ); pTemp = (Abc_Obj_t *)Vec_PtrEntry( vCos, k ); Vec_PtrWriteEntry( pNtk->vPos, i, pTemp ); Vec_PtrWriteEntry( pNtk->vCos, i, pTemp ); } else { k = rand() % Abc_NtkPoNum(pNtk); // swap indexes Entry = Vec_IntEntry( vOutputs, i ); Vec_IntWriteEntry( vOutputs, i, Vec_IntEntry(vOutputs, k) ); Vec_IntWriteEntry( vOutputs, k, Entry ); // swap POs pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPos, i ); Vec_PtrWriteEntry( pNtk->vPos, i, Vec_PtrEntry(pNtk->vPos, k) ); Vec_PtrWriteEntry( pNtk->vPos, k, pTemp ); // swap COs pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, i ); Vec_PtrWriteEntry( pNtk->vCos, i, Vec_PtrEntry(pNtk->vCos, k) ); Vec_PtrWriteEntry( pNtk->vCos, k, pTemp ); } //printf( "Swapping POs %d and %d.\n", i, k ); } // permute flops assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) ); if ( fFlops ) for ( i = 0; i < Abc_NtkLatchNum(pNtk); i++ ) { if ( pFlopPermFile ) { k = Vec_IntEntry( vFlops, i ); pTemp = (Abc_Obj_t *)Vec_PtrEntry( vFfs, k ); Vec_PtrWriteEntry( pNtk->vBoxes, i, pTemp ); pTemp = (Abc_Obj_t *)Vec_PtrEntry( vCis, Abc_NtkPiNum(pNtk)+k ); Vec_PtrWriteEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+i, pTemp ); pTemp = (Abc_Obj_t *)Vec_PtrEntry( vCos, Abc_NtkPoNum(pNtk)+k ); Vec_PtrWriteEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+i, pTemp ); } else { k = rand() % Abc_NtkLatchNum(pNtk); // swap indexes Entry = Vec_IntEntry( vFlops, i ); Vec_IntWriteEntry( vFlops, i, Vec_IntEntry(vFlops, k) ); Vec_IntWriteEntry( vFlops, k, Entry ); // swap flops pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vBoxes, i ); Vec_PtrWriteEntry( pNtk->vBoxes, i, Vec_PtrEntry(pNtk->vBoxes, k) ); Vec_PtrWriteEntry( pNtk->vBoxes, k, pTemp ); // swap CIs pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+i ); Vec_PtrWriteEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+i, Vec_PtrEntry(pNtk->vCis, Abc_NtkPiNum(pNtk)+k) ); Vec_PtrWriteEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+k, pTemp ); // swap COs pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+i ); Vec_PtrWriteEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+i, Vec_PtrEntry(pNtk->vCos, Abc_NtkPoNum(pNtk)+k) ); Vec_PtrWriteEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+k, pTemp ); } //printf( "Swapping flops %d and %d.\n", i, k ); } Vec_PtrFree(vCis); Vec_PtrFree(vCos); Vec_PtrFree(vFfs); // invert arrays vInputs = Vec_IntInvert( vTemp = vInputs, -1 ); Vec_IntFree( vTemp ); vOutputs = Vec_IntInvert( vTemp = vOutputs, -1 ); Vec_IntFree( vTemp ); vFlops = Vec_IntInvert( vTemp = vFlops, -1 ); Vec_IntFree( vTemp ); // pack the results into the output array Vec_IntFreeP( &pNtk->vObjPerm ); pNtk->vObjPerm = Vec_IntAlloc( Abc_NtkPiNum(pNtk) + Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk) ); Vec_IntForEachEntry( vInputs, Entry, i ) Vec_IntPush( pNtk->vObjPerm, Entry ); Vec_IntForEachEntry( vOutputs, Entry, i ) Vec_IntPush( pNtk->vObjPerm, Entry ); Vec_IntForEachEntry( vFlops, Entry, i ) Vec_IntPush( pNtk->vObjPerm, Entry ); // cleanup Vec_IntFree( vInputs ); Vec_IntFree( vOutputs ); Vec_IntFree( vFlops ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCompareByFanoutCount( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) { int Diff = Abc_ObjFanoutNum(*pp2) - Abc_ObjFanoutNum(*pp1); if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; Diff = strcmp( Abc_ObjName(*pp1), Abc_ObjName(*pp2) ); if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; return 0; } void Abc_NtkPermutePiUsingFanout( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i; 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 ) Vec_PtrPush( pNtk->vCis, pNode ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkUnpermute( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vTemp, * vTemp2, * vLatch; int i, * pInputs, * pOutputs, * pFlops; if ( pNtk->vObjPerm == NULL ) { printf( "Abc_NtkUnpermute(): Initial permutation is not available.\n" ); return; } assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) ); // get reverve permutation pInputs = Vec_IntArray( pNtk->vObjPerm ); pOutputs = pInputs + Abc_NtkPiNum(pNtk); pFlops = pOutputs + Abc_NtkPoNum(pNtk); // create new PI array vTemp = Vec_PtrAlloc( Abc_NtkPiNum(pNtk) ); for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) Vec_PtrPush( vTemp, Abc_NtkPi(pNtk, pInputs[i]) ); Vec_PtrFreeP( &pNtk->vPis ); pNtk->vPis = vTemp; // create new PO array vTemp = Vec_PtrAlloc( Abc_NtkPoNum(pNtk) ); for ( i = 0; i < Abc_NtkPoNum(pNtk); i++ ) Vec_PtrPush( vTemp, Abc_NtkPo(pNtk, pOutputs[i]) ); Vec_PtrFreeP( &pNtk->vPos ); pNtk->vPos = vTemp; // create new CI/CO arrays vTemp = Vec_PtrDup( pNtk->vPis ); vTemp2 = Vec_PtrDup( pNtk->vPos ); vLatch = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); for ( i = 0; i < Abc_NtkLatchNum(pNtk); i++ ) { //printf( "Setting flop %d to be %d.\n", i, pFlops[i] ); Vec_PtrPush( vTemp, Abc_NtkCi(pNtk, Abc_NtkPiNum(pNtk) + pFlops[i]) ); Vec_PtrPush( vTemp2, Abc_NtkCo(pNtk, Abc_NtkPoNum(pNtk) + pFlops[i]) ); Vec_PtrPush( vLatch, Abc_NtkBox(pNtk, pFlops[i]) ); } Vec_PtrFreeP( &pNtk->vCis ); Vec_PtrFreeP( &pNtk->vCos ); Vec_PtrFreeP( &pNtk->vBoxes ); pNtk->vCis = vTemp; pNtk->vCos = vTemp2; pNtk->vBoxes = vLatch; // cleanup Vec_IntFreeP( &pNtk->vObjPerm ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkNodeDup( Abc_Ntk_t * pNtkInit, int nLimit, int fVerbose ) { Vec_Ptr_t * vNodes, * vFanouts; Abc_Ntk_t * pNtk; Abc_Obj_t * pObj, * pObjNew, * pFanin, * pFanout; int i, k; pNtk = Abc_NtkDup( pNtkInit ); vNodes = Vec_PtrAlloc( 100 ); vFanouts = Vec_PtrAlloc( 100 ); do { Vec_PtrClear( vNodes ); Abc_NtkForEachNode( pNtk, pObj, i ) if ( Abc_ObjFanoutNum(pObj) >= nLimit ) Vec_PtrPush( vNodes, pObj ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { pObjNew = Abc_NtkDupObj( pNtk, pObj, 0 ); Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObjNew, pFanin ); Abc_NodeCollectFanouts( pObj, vFanouts ); Vec_PtrShrink( vFanouts, nLimit / 2 ); Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, k ) Abc_ObjPatchFanin( pFanout, pObj, pObjNew ); } if ( fVerbose ) printf( "Duplicated %d nodes.\n", Vec_PtrSize(vNodes) ); } while ( Vec_PtrSize(vNodes) > 0 ); Vec_PtrFree( vFanouts ); Vec_PtrFree( vNodes ); return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCreateFromSops( char * pName, Vec_Ptr_t * vSops ) { int i, k, nObjBeg; char * pSop = (char *)Vec_PtrEntry(vSops, 0); Abc_Ntk_t * pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); pNtk->pName = Extra_UtilStrsav( pName ); for ( k = 0; pSop[k] != ' '; k++ ) Abc_NtkCreatePi( pNtk ); nObjBeg = Abc_NtkObjNumMax(pNtk); Vec_PtrForEachEntry( char *, vSops, pSop, i ) { Abc_Obj_t * pObj = Abc_NtkCreateNode( pNtk ); pObj->pData = Abc_SopRegister( (Mem_Flex_t*)pNtk->pManFunc, pSop ); for ( k = 0; pSop[k] != ' '; k++ ) Abc_ObjAddFanin( pObj, Abc_NtkCi(pNtk, k) ); } for ( i = 0; i < Vec_PtrSize(vSops); i++ ) { Abc_Obj_t * pObj = Abc_NtkObj( pNtk, nObjBeg + i ); Abc_Obj_t * pObjPo = Abc_NtkCreatePo( pNtk ); Abc_ObjAddFanin( pObjPo, pObj ); } Abc_NtkAddDummyPiNames( pNtk ); Abc_NtkAddDummyPoNames( pNtk ); return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCreateFromGias( char * pName, Vec_Ptr_t * vGias, Gia_Man_t * pMulti ) { 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 ); 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 ); } 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 ); } } Abc_NtkAddDummyPiNames( pNtk ); Abc_NtkAddDummyPoNames( pNtk ); return pNtk; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcObj.c000066400000000000000000001017131477524141600157550ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcObj.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Object creation/duplication/deletion procedures.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcObj.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" #include "abcInt.h" #include "base/main/main.h" #include "map/mio/mio.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Creates a new object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ) { Abc_Obj_t * pObj; if ( pNtk->pMmObj ) pObj = (Abc_Obj_t *)Mem_FixedEntryFetch( pNtk->pMmObj ); else pObj = (Abc_Obj_t *)ABC_ALLOC( Abc_Obj_t, 1 ); memset( pObj, 0, sizeof(Abc_Obj_t) ); pObj->pNtk = pNtk; pObj->Type = Type; pObj->Id = -1; return pObj; } /**Function************************************************************* Synopsis [Recycles the object.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ObjRecycle( Abc_Obj_t * pObj ) { Abc_Ntk_t * pNtk = pObj->pNtk; // int LargePiece = (4 << ABC_NUM_STEPS); // free large fanout arrays // if ( pNtk->pMmStep && pObj->vFanouts.nCap * 4 > LargePiece ) // free( pObj->vFanouts.pArray ); if ( pNtk->pMmStep == NULL ) { ABC_FREE( pObj->vFanouts.pArray ); ABC_FREE( pObj->vFanins.pArray ); } // clean the memory to make deleted object distinct from the live one memset( pObj, 0, sizeof(Abc_Obj_t) ); // recycle the object if ( pNtk->pMmObj ) Mem_FixedEntryRecycle( pNtk->pMmObj, (char *)pObj ); else ABC_FREE( pObj ); } /**Function************************************************************* Synopsis [Adds the node to the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ) { Abc_Obj_t * pObj; // create new object, assign ID, and add to the array pObj = Abc_ObjAlloc( pNtk, Type ); pObj->Id = pNtk->vObjs->nSize; Vec_PtrPush( pNtk->vObjs, pObj ); pNtk->nObjCounts[Type]++; pNtk->nObjs++; // perform specialized operations depending on the object type switch (Type) { case ABC_OBJ_NONE: assert(0); break; case ABC_OBJ_CONST1: assert(0); break; case ABC_OBJ_PI: // pObj->iTemp = Vec_PtrSize(pNtk->vCis); Vec_PtrPush( pNtk->vPis, pObj ); Vec_PtrPush( pNtk->vCis, pObj ); break; case ABC_OBJ_PO: // pObj->iTemp = Vec_PtrSize(pNtk->vCos); Vec_PtrPush( pNtk->vPos, pObj ); Vec_PtrPush( pNtk->vCos, pObj ); break; case ABC_OBJ_BI: if ( pNtk->vCos ) Vec_PtrPush( pNtk->vCos, pObj ); break; case ABC_OBJ_BO: if ( pNtk->vCis ) Vec_PtrPush( pNtk->vCis, pObj ); break; case ABC_OBJ_NET: case ABC_OBJ_NODE: break; case ABC_OBJ_LATCH: pObj->pData = (void *)ABC_INIT_NONE; case ABC_OBJ_WHITEBOX: case ABC_OBJ_BLACKBOX: if ( pNtk->vBoxes ) Vec_PtrPush( pNtk->vBoxes, pObj ); break; default: assert(0); break; } return pObj; } /**Function************************************************************* Synopsis [Deletes the object from the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDeleteObj( Abc_Obj_t * pObj ) { Abc_Ntk_t * pNtk = pObj->pNtk; Vec_Ptr_t * vNodes; int i; assert( !Abc_ObjIsComplement(pObj) ); // remove from the table of names if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) ) Nm_ManDeleteIdName(pObj->pNtk->pManName, pObj->Id); // delete fanins and fanouts vNodes = Vec_PtrAlloc( 100 ); Abc_NodeCollectFanouts( pObj, vNodes ); for ( i = 0; i < vNodes->nSize; i++ ) Abc_ObjDeleteFanin( (Abc_Obj_t *)vNodes->pArray[i], pObj ); Abc_NodeCollectFanins( pObj, vNodes ); for ( i = 0; i < vNodes->nSize; i++ ) Abc_ObjDeleteFanin( pObj, (Abc_Obj_t *)vNodes->pArray[i] ); Vec_PtrFree( vNodes ); // remove from the list of objects Vec_PtrWriteEntry( pNtk->vObjs, pObj->Id, NULL ); pObj->Id = (1<<26)-1; pNtk->nObjCounts[pObj->Type]--; pNtk->nObjs--; // perform specialized operations depending on the object type switch (pObj->Type) { case ABC_OBJ_NONE: assert(0); break; case ABC_OBJ_CONST1: assert(0); break; case ABC_OBJ_PI: Vec_PtrRemove( pNtk->vPis, pObj ); Vec_PtrRemove( pNtk->vCis, pObj ); break; case ABC_OBJ_PO: Vec_PtrRemove( pNtk->vPos, pObj ); Vec_PtrRemove( pNtk->vCos, pObj ); break; case ABC_OBJ_BI: if ( pNtk->vCos ) Vec_PtrRemove( pNtk->vCos, pObj ); break; case ABC_OBJ_BO: if ( pNtk->vCis ) Vec_PtrRemove( pNtk->vCis, pObj ); break; case ABC_OBJ_NET: break; case ABC_OBJ_NODE: #ifdef ABC_USE_CUDD if ( Abc_NtkHasBdd(pNtk) ) Cudd_RecursiveDeref( (DdManager *)pNtk->pManFunc, (DdNode *)pObj->pData ); #endif pObj->pData = NULL; break; case ABC_OBJ_LATCH: case ABC_OBJ_WHITEBOX: case ABC_OBJ_BLACKBOX: if ( pNtk->vBoxes ) Vec_PtrRemove( pNtk->vBoxes, pObj ); break; default: assert(0); break; } // recycle the object memory Abc_ObjRecycle( pObj ); } /**Function************************************************************* Synopsis [Deletes the PO from the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDeleteObjPo( Abc_Obj_t * pObj ) { assert( Abc_ObjIsPo(pObj) ); // remove from the table of names if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) ) Nm_ManDeleteIdName(pObj->pNtk->pManName, pObj->Id); // delete fanins Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) ); // remove from the list of objects Vec_PtrWriteEntry( pObj->pNtk->vObjs, pObj->Id, NULL ); pObj->Id = (1<<26)-1; pObj->pNtk->nObjCounts[pObj->Type]--; pObj->pNtk->nObjs--; // recycle the object memory Abc_ObjRecycle( pObj ); } /**Function************************************************************* Synopsis [Deletes the node and MFFC of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDeleteObj_rec( Abc_Obj_t * pObj, int fOnlyNodes ) { Vec_Ptr_t * vNodes; int i; assert( !Abc_ObjIsComplement(pObj) ); assert( !Abc_ObjIsPi(pObj) ); assert( Abc_ObjFanoutNum(pObj) == 0 ); // delete fanins and fanouts vNodes = Vec_PtrAlloc( 100 ); Abc_NodeCollectFanins( pObj, vNodes ); Abc_NtkDeleteObj( pObj ); if ( fOnlyNodes ) { Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) Abc_NtkDeleteObj_rec( pObj, fOnlyNodes ); } else { Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) if ( !Abc_ObjIsPi(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) Abc_NtkDeleteObj_rec( pObj, fOnlyNodes ); } Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Deletes the node and MFFC of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj ) { Vec_Ptr_t * vNodes; int i; assert( !Abc_ObjIsComplement(pObj) ); assert( Abc_ObjFanoutNum(pObj) == 0 ); // delete fanins and fanouts vNodes = Vec_PtrAlloc( 100 ); Abc_NodeCollectFanins( pObj, vNodes ); Abc_NtkDeleteObj( pObj ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) if ( !Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) Abc_NtkDeleteAll_rec( pObj ); Vec_PtrFree( vNodes ); } /**Function************************************************************* Synopsis [Duplicate the Obj.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName ) { Abc_Obj_t * pObjNew; // create the new object pObjNew = Abc_NtkCreateObj( pNtkNew, (Abc_ObjType_t)pObj->Type ); // transfer names of the terminal objects if ( fCopyName ) { if ( Abc_ObjIsCi(pObj) ) { if ( !Abc_NtkIsNetlist(pNtkNew) ) Abc_ObjAssignName( pObjNew, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); } else if ( Abc_ObjIsCo(pObj) ) { if ( !Abc_NtkIsNetlist(pNtkNew) ) { if ( Abc_ObjIsPo(pObj) ) Abc_ObjAssignName( pObjNew, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); else { assert( Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ); Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); } } } else if ( Abc_ObjIsBox(pObj) || Abc_ObjIsNet(pObj) ) Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); } // copy functionality/names if ( Abc_ObjIsNode(pObj) ) // copy the function if functionality is compatible { if ( pNtkNew->ntkFunc == pObj->pNtk->ntkFunc ) { if ( Abc_NtkIsStrash(pNtkNew) ) {} else if ( Abc_NtkHasSop(pNtkNew) || Abc_NtkHasBlifMv(pNtkNew) ) pObjNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, (char *)pObj->pData ); #ifdef ABC_USE_CUDD else if ( Abc_NtkHasBdd(pNtkNew) ) pObjNew->pData = Cudd_bddTransfer((DdManager *)pObj->pNtk->pManFunc, (DdManager *)pNtkNew->pManFunc, (DdNode *)pObj->pData), Cudd_Ref((DdNode *)pObjNew->pData); #endif else if ( Abc_NtkHasAig(pNtkNew) ) pObjNew->pData = Hop_Transfer((Hop_Man_t *)pObj->pNtk->pManFunc, (Hop_Man_t *)pNtkNew->pManFunc, (Hop_Obj_t *)pObj->pData, Abc_ObjFaninNum(pObj)); else if ( Abc_NtkHasMapping(pNtkNew) ) pObjNew->pData = pObj->pData, pNtkNew->nBarBufs2 += !pObj->pData; else assert( 0 ); } } else if ( Abc_ObjIsNet(pObj) ) // copy the name { } 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 pObj->pCopy = pObjNew; return pObjNew; } /**Function************************************************************* Synopsis [Duplicates the latch with its input/output terminals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkDupBox( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pBox, int fCopyName ) { Abc_Obj_t * pTerm, * pBoxNew; int i; assert( Abc_ObjIsBox(pBox) ); // duplicate the box pBoxNew = Abc_NtkDupObj( pNtkNew, pBox, fCopyName ); // duplicate the fanins and connect them Abc_ObjForEachFanin( pBox, pTerm, i ) Abc_ObjAddFanin( pBoxNew, Abc_NtkDupObj(pNtkNew, pTerm, fCopyName) ); // duplicate the fanouts and connect them Abc_ObjForEachFanout( pBox, pTerm, i ) Abc_ObjAddFanin( Abc_NtkDupObj(pNtkNew, pTerm, fCopyName), pBoxNew ); return pBoxNew; } /**Function************************************************************* Synopsis [Clones the objects in the same network but does not assign its function.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCloneObj( Abc_Obj_t * pObj ) { Abc_Obj_t * pClone, * pFanin; int i; pClone = Abc_NtkCreateObj( pObj->pNtk, (Abc_ObjType_t)pObj->Type ); Abc_ObjForEachFanin( pObj, pFanin, i ) Abc_ObjAddFanin( pClone, pFanin ); return pClone; } /**Function************************************************************* Synopsis [Returns the net with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName ) { Abc_Obj_t * pObj; int Num; // try to find the terminal Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PO ); if ( Num >= 0 ) return Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BI ); if ( Num >= 0 ) return Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_NODE ); if ( Num >= 0 ) return Abc_NtkObj( pNtk, Num ); // find the internal node if ( pName[0] != 'n' ) { printf( "Name \"%s\" is not found among CO or node names (internal names often look as \"n\").\n", pName ); return NULL; } Num = atoi( pName + 1 ); if ( Num < 0 || Num >= Abc_NtkObjNumMax(pNtk) ) { printf( "The node \"%s\" with ID %d is not in the current network.\n", pName, Num ); return NULL; } pObj = Abc_NtkObj( pNtk, Num ); if ( pObj == NULL ) { printf( "The node \"%s\" with ID %d has been removed from the current network.\n", pName, Num ); return NULL; } if ( !Abc_ObjIsNode(pObj) ) { printf( "Object with ID %d is not a node.\n", Num ); return NULL; } return pObj; } /**Function************************************************************* Synopsis [Returns the net with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName ) { Abc_Obj_t * pNet; int ObjId; assert( Abc_NtkIsNetlist(pNtk) ); ObjId = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_NET ); if ( ObjId == -1 ) return NULL; pNet = Abc_NtkObj( pNtk, ObjId ); return pNet; } /**Function************************************************************* Synopsis [Returns CI with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkFindCi( Abc_Ntk_t * pNtk, char * pName ) { int Num; assert( !Abc_NtkIsNetlist(pNtk) ); Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PI ); if ( Num >= 0 ) return Abc_NtkObj( pNtk, Num ); Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BO ); if ( Num >= 0 ) return Abc_NtkObj( pNtk, Num ); return NULL; } /**Function************************************************************* Synopsis [Returns CO with the given name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName ) { int Num; assert( !Abc_NtkIsNetlist(pNtk) ); Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PO ); if ( Num >= 0 ) return Abc_NtkObj( pNtk, Num ); Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BI ); if ( Num >= 0 ) return Abc_NtkObj( pNtk, Num ); return NULL; } /**Function************************************************************* Synopsis [Finds or creates the net.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName ) { Abc_Obj_t * pNet; assert( Abc_NtkIsNetlist(pNtk) ); if ( pName && (pNet = Abc_NtkFindNet( pNtk, pName )) ) return pNet; //printf( "Creating net %s.\n", pName ); // create a new net pNet = Abc_NtkCreateNet( pNtk ); if ( pName ) Nm_ManStoreIdName( pNtk->pManName, pNet->Id, pNet->Type, pName, NULL ); return pNet; } /**Function************************************************************* Synopsis [Creates constant 0 node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); pNode = Abc_NtkCreateNode( pNtk ); if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 0\n" ); #ifdef ABC_USE_CUDD else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Cudd_ReadLogicZero((DdManager *)pNtk->pManFunc), Cudd_Ref( (DdNode *)pNode->pData ); #endif else if ( Abc_NtkHasAig(pNtk) ) pNode->pData = Hop_ManConst0((Hop_Man_t *)pNtk->pManFunc); else if ( Abc_NtkHasMapping(pNtk) ) pNode->pData = Mio_LibraryReadConst0((Mio_Library_t *)Abc_FrameReadLibGen()); else if ( !Abc_NtkHasBlackbox(pNtk) ) assert( 0 ); return pNode; } /**Function************************************************************* Synopsis [Creates constant 1 node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); pNode = Abc_NtkCreateNode( pNtk ); if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 1\n" ); #ifdef ABC_USE_CUDD else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Cudd_ReadOne((DdManager *)pNtk->pManFunc), Cudd_Ref( (DdNode *)pNode->pData ); #endif else if ( Abc_NtkHasAig(pNtk) ) pNode->pData = Hop_ManConst1((Hop_Man_t *)pNtk->pManFunc); else if ( Abc_NtkHasMapping(pNtk) ) pNode->pData = Mio_LibraryReadConst1((Mio_Library_t *)Abc_FrameReadLibGen()); else if ( !Abc_NtkHasBlackbox(pNtk) ) assert( 0 ); return pNode; } /**Function************************************************************* Synopsis [Creates inverter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) { Abc_Obj_t * pNode; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); pNode = Abc_NtkCreateNode( pNtk ); if ( pFanin ) Abc_ObjAddFanin( pNode, pFanin ); if ( Abc_NtkHasSop(pNtk) ) pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, "0 1\n" ); #ifdef ABC_USE_CUDD else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Cudd_Not(Cudd_bddIthVar((DdManager *)pNtk->pManFunc,0)), Cudd_Ref( (DdNode *)pNode->pData ); #endif else if ( Abc_NtkHasAig(pNtk) ) pNode->pData = Hop_Not(Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,0)); else if ( Abc_NtkHasMapping(pNtk) ) pNode->pData = Mio_LibraryReadInv((Mio_Library_t *)Abc_FrameReadLibGen()); else assert( 0 ); return pNode; } /**Function************************************************************* Synopsis [Creates buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) { Abc_Obj_t * pNode; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); pNode = Abc_NtkCreateNode( pNtk ); if ( pFanin ) Abc_ObjAddFanin( pNode, pFanin ); if ( Abc_NtkHasSop(pNtk) ) pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, "1 1\n" ); #ifdef ABC_USE_CUDD else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Cudd_bddIthVar((DdManager *)pNtk->pManFunc,0), Cudd_Ref( (DdNode *)pNode->pData ); #endif else if ( Abc_NtkHasAig(pNtk) ) pNode->pData = Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,0); else if ( Abc_NtkHasMapping(pNtk) ) pNode->pData = Mio_LibraryReadBuf((Mio_Library_t *)Abc_FrameReadLibGen()); else assert( 0 ); return pNode; } /**Function************************************************************* Synopsis [Creates AND.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) { Abc_Obj_t * pNode; int i; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); pNode = Abc_NtkCreateNode( pNtk ); for ( i = 0; i < vFanins->nSize; i++ ) Abc_ObjAddFanin( pNode, (Abc_Obj_t *)vFanins->pArray[i] ); if ( Abc_NtkHasSop(pNtk) ) pNode->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtk->pManFunc, Vec_PtrSize(vFanins), NULL ); #ifdef ABC_USE_CUDD else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Extra_bddCreateAnd( (DdManager *)pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref((DdNode *)pNode->pData); #endif else if ( Abc_NtkHasAig(pNtk) ) pNode->pData = Hop_CreateAnd( (Hop_Man_t *)pNtk->pManFunc, Vec_PtrSize(vFanins) ); else assert( 0 ); return pNode; } /**Function************************************************************* Synopsis [Creates OR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) { Abc_Obj_t * pNode; int i; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); pNode = Abc_NtkCreateNode( pNtk ); for ( i = 0; i < vFanins->nSize; i++ ) Abc_ObjAddFanin( pNode, (Abc_Obj_t *)vFanins->pArray[i] ); if ( Abc_NtkHasSop(pNtk) ) pNode->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNtk->pManFunc, Vec_PtrSize(vFanins), NULL ); #ifdef ABC_USE_CUDD else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Extra_bddCreateOr( (DdManager *)pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref((DdNode *)pNode->pData); #endif else if ( Abc_NtkHasAig(pNtk) ) pNode->pData = Hop_CreateOr( (Hop_Man_t *)pNtk->pManFunc, Vec_PtrSize(vFanins) ); else assert( 0 ); return pNode; } /**Function************************************************************* Synopsis [Creates EXOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) { Abc_Obj_t * pNode; int i; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); pNode = Abc_NtkCreateNode( pNtk ); for ( i = 0; i < vFanins->nSize; i++ ) Abc_ObjAddFanin( pNode, (Abc_Obj_t *)vFanins->pArray[i] ); if ( Abc_NtkHasSop(pNtk) ) pNode->pData = Abc_SopCreateXorSpecial( (Mem_Flex_t *)pNtk->pManFunc, Vec_PtrSize(vFanins) ); #ifdef ABC_USE_CUDD else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Extra_bddCreateExor( (DdManager *)pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref((DdNode *)pNode->pData); #endif else if ( Abc_NtkHasAig(pNtk) ) pNode->pData = Hop_CreateExor( (Hop_Man_t *)pNtk->pManFunc, Vec_PtrSize(vFanins) ); else assert( 0 ); return pNode; } /**Function************************************************************* Synopsis [Creates MUX.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 ) { Abc_Obj_t * pNode; assert( Abc_NtkIsLogic(pNtk) ); pNode = Abc_NtkCreateNode( pNtk ); Abc_ObjAddFanin( pNode, pNodeC ); Abc_ObjAddFanin( pNode, pNode1 ); Abc_ObjAddFanin( pNode, pNode0 ); if ( Abc_NtkHasSop(pNtk) ) pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, "11- 1\n0-1 1\n" ); #ifdef ABC_USE_CUDD else if ( Abc_NtkHasBdd(pNtk) ) pNode->pData = Cudd_bddIte((DdManager *)pNtk->pManFunc,Cudd_bddIthVar((DdManager *)pNtk->pManFunc,0),Cudd_bddIthVar((DdManager *)pNtk->pManFunc,1),Cudd_bddIthVar((DdManager *)pNtk->pManFunc,2)), Cudd_Ref( (DdNode *)pNode->pData ); #endif else if ( Abc_NtkHasAig(pNtk) ) pNode->pData = Hop_Mux((Hop_Man_t *)pNtk->pManFunc,Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,0),Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,1),Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,2)); else assert( 0 ); return pNode; } /**Function************************************************************* Synopsis [Returns 1 if the node is a constant 0 node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeIsConst( Abc_Obj_t * pNode ) { assert( Abc_NtkIsLogic(pNode->pNtk) || Abc_NtkIsNetlist(pNode->pNtk) ); return Abc_ObjIsNode(pNode) && Abc_ObjFaninNum(pNode) == 0; } /**Function************************************************************* Synopsis [Returns 1 if the node is a constant 0 node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeIsConst0( Abc_Obj_t * pNode ) { Abc_Ntk_t * pNtk = pNode->pNtk; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); assert( Abc_ObjIsNode(pNode) ); if ( !Abc_NodeIsConst(pNode) ) return 0; if ( Abc_NtkHasSop(pNtk) ) return Abc_SopIsConst0((char *)pNode->pData); #ifdef ABC_USE_CUDD if ( Abc_NtkHasBdd(pNtk) ) return Cudd_IsComplement(pNode->pData); #endif if ( Abc_NtkHasAig(pNtk) ) return Hop_IsComplement((Hop_Obj_t *)pNode->pData)? 1:0; if ( Abc_NtkHasMapping(pNtk) ) return pNode->pData == Mio_LibraryReadConst0((Mio_Library_t *)Abc_FrameReadLibGen()); assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Returns 1 if the node is a constant 1 node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeIsConst1( Abc_Obj_t * pNode ) { Abc_Ntk_t * pNtk = pNode->pNtk; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); assert( Abc_ObjIsNode(pNode) ); if ( !Abc_NodeIsConst(pNode) ) return 0; if ( Abc_NtkHasSop(pNtk) ) return Abc_SopIsConst1((char *)pNode->pData); #ifdef ABC_USE_CUDD if ( Abc_NtkHasBdd(pNtk) ) return !Cudd_IsComplement(pNode->pData); #endif if ( Abc_NtkHasAig(pNtk) ) return !Hop_IsComplement((Hop_Obj_t *)pNode->pData); if ( Abc_NtkHasMapping(pNtk) ) return pNode->pData == Mio_LibraryReadConst1((Mio_Library_t *)Abc_FrameReadLibGen()); assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Returns 1 if the node is a buffer.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeIsBuf( Abc_Obj_t * pNode ) { Abc_Ntk_t * pNtk = pNode->pNtk; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); assert( Abc_ObjIsNode(pNode) ); if ( Abc_ObjFaninNum(pNode) != 1 ) return 0; if ( Abc_NtkHasSop(pNtk) ) return Abc_SopIsBuf((char *)pNode->pData); #ifdef ABC_USE_CUDD if ( Abc_NtkHasBdd(pNtk) ) return !Cudd_IsComplement(pNode->pData); #endif if ( Abc_NtkHasAig(pNtk) ) return !Hop_IsComplement((Hop_Obj_t *)pNode->pData); if ( Abc_NtkHasMapping(pNtk) ) return pNode->pData == Mio_LibraryReadBuf((Mio_Library_t *)Abc_FrameReadLibGen()); assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Returns 1 if the node is an inverter.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeIsInv( Abc_Obj_t * pNode ) { Abc_Ntk_t * pNtk = pNode->pNtk; assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); assert( Abc_ObjIsNode(pNode) ); if ( Abc_ObjFaninNum(pNode) != 1 ) return 0; if ( Abc_NtkHasSop(pNtk) ) return Abc_SopIsInv((char *)pNode->pData); #ifdef ABC_USE_CUDD if ( Abc_NtkHasBdd(pNtk) ) return Cudd_IsComplement(pNode->pData); #endif if ( Abc_NtkHasAig(pNtk) ) return Hop_IsComplement((Hop_Obj_t *)pNode->pData)? 1:0; if ( Abc_NtkHasMapping(pNtk) ) return pNode->pData == Mio_LibraryReadInv((Mio_Library_t *)Abc_FrameReadLibGen()); assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Complements the local functions of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeComplement( Abc_Obj_t * pNode ) { assert( Abc_NtkIsLogic(pNode->pNtk) || Abc_NtkIsNetlist(pNode->pNtk) ); assert( Abc_ObjIsNode(pNode) ); if ( Abc_NtkHasSop(pNode->pNtk) ) Abc_SopComplement( (char *)pNode->pData ); else if ( Abc_NtkHasAig(pNode->pNtk) ) pNode->pData = Hop_Not( (Hop_Obj_t *)pNode->pData ); #ifdef ABC_USE_CUDD else if ( Abc_NtkHasBdd(pNode->pNtk) ) pNode->pData = Cudd_Not( pNode->pData ); #endif else assert( 0 ); } /**Function************************************************************* Synopsis [Changes the polarity of one fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) { int iFanin; if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 ) { printf( "Node %s should be among", Abc_ObjName(pFanin) ); printf( " the fanins of node %s...\n", Abc_ObjName(pNode) ); return; } if ( Abc_NtkHasSop(pNode->pNtk) ) Abc_SopComplementVar( (char *)pNode->pData, iFanin ); else if ( Abc_NtkHasAig(pNode->pNtk) ) pNode->pData = Hop_Complement( (Hop_Man_t *)pNode->pNtk->pManFunc, (Hop_Obj_t *)pNode->pData, iFanin ); #ifdef ABC_USE_CUDD else if ( Abc_NtkHasBdd(pNode->pNtk) ) { DdManager * dd = (DdManager *)pNode->pNtk->pManFunc; DdNode * bVar, * bCof0, * bCof1; bVar = Cudd_bddIthVar( dd, iFanin ); bCof0 = Cudd_Cofactor( dd, (DdNode *)pNode->pData, Cudd_Not(bVar) ); Cudd_Ref( bCof0 ); bCof1 = Cudd_Cofactor( dd, (DdNode *)pNode->pData, bVar ); Cudd_Ref( bCof1 ); Cudd_RecursiveDeref( dd, (DdNode *)pNode->pData ); pNode->pData = Cudd_bddIte( dd, bVar, bCof0, bCof1 ); Cudd_Ref( (DdNode *)pNode->pData ); Cudd_RecursiveDeref( dd, bCof0 ); Cudd_RecursiveDeref( dd, bCof1 ); } #endif else assert( 0 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcRefs.c000066400000000000000000000323171477524141600161450ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcRefs.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Procedures using reference counting of the AIG nodes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcRefs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Abc_NodeRefDeref( Abc_Obj_t * pNode, int fReference, int fLabel ); static int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, int fReference ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Returns the MFFC size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeMffcSize( Abc_Obj_t * pNode ) { int nConeSize1, nConeSize2; // assert( Abc_NtkIsStrash(pNode->pNtk) ); // assert( !Abc_ObjIsComplement( pNode ) ); assert( Abc_ObjIsNode( pNode ) ); if ( Abc_ObjFaninNum(pNode) == 0 ) return 0; nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0 ); // dereference nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference assert( nConeSize1 == nConeSize2 ); assert( nConeSize1 > 0 ); return nConeSize1; } /**Function************************************************************* Synopsis [Returns the MFFC size while stopping at the complemented edges.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode ) { int nConeSize1, nConeSize2; assert( Abc_NtkIsStrash(pNode->pNtk) ); assert( !Abc_ObjIsComplement( pNode ) ); assert( Abc_ObjIsNode( pNode ) ); if ( Abc_ObjFaninNum(pNode) == 0 ) return 0; nConeSize1 = Abc_NodeRefDerefStop( pNode, 0 ); // dereference nConeSize2 = Abc_NodeRefDerefStop( pNode, 1 ); // reference assert( nConeSize1 == nConeSize2 ); assert( nConeSize1 > 0 ); return nConeSize1; } /**Function************************************************************* Synopsis [Labels MFFC with the current traversal ID.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeMffcLabelAig( Abc_Obj_t * pNode ) { int nConeSize1, nConeSize2; assert( Abc_NtkIsStrash(pNode->pNtk) ); assert( !Abc_ObjIsComplement( pNode ) ); assert( Abc_ObjIsNode( pNode ) ); if ( Abc_ObjFaninNum(pNode) == 0 ) return 0; nConeSize1 = Abc_NodeRefDeref( pNode, 0, 1 ); // dereference nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference assert( nConeSize1 == nConeSize2 ); assert( nConeSize1 > 0 ); return nConeSize1; } /**Function************************************************************* Synopsis [References/references the node and returns MFFC size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeRefDeref( Abc_Obj_t * pNode, int fReference, int fLabel ) { Abc_Obj_t * pNode0, * pNode1; int Counter; // label visited nodes if ( fLabel ) Abc_NodeSetTravIdCurrent( pNode ); // skip the CI if ( Abc_ObjIsCi(pNode) ) return 0; // process the internal node pNode0 = Abc_ObjFanin0(pNode); pNode1 = Abc_ObjFanin1(pNode); Counter = 1; if ( fReference ) { if ( pNode0->vFanouts.nSize++ == 0 ) Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel ); if ( pNode1->vFanouts.nSize++ == 0 ) Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel ); } else { assert( pNode0->vFanouts.nSize > 0 ); assert( pNode1->vFanouts.nSize > 0 ); if ( --pNode0->vFanouts.nSize == 0 ) Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel ); if ( --pNode1->vFanouts.nSize == 0 ) Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel ); } return Counter; } /**Function************************************************************* Synopsis [References/references the node and returns MFFC size.] Description [Stops at the complemented edges.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, int fReference ) { Abc_Obj_t * pNode0, * pNode1; int Counter; // skip the CI if ( Abc_ObjIsCi(pNode) ) return 0; // process the internal node pNode0 = Abc_ObjFanin0(pNode); pNode1 = Abc_ObjFanin1(pNode); Counter = 1; if ( fReference ) { if ( !Abc_ObjFaninC0(pNode) && pNode0->vFanouts.nSize++ == 0 ) Counter += Abc_NodeRefDerefStop( pNode0, fReference ); if ( !Abc_ObjFaninC1(pNode) && pNode1->vFanouts.nSize++ == 0 ) Counter += Abc_NodeRefDerefStop( pNode1, fReference ); } else { assert( pNode0->vFanouts.nSize > 0 ); assert( pNode1->vFanouts.nSize > 0 ); if ( !Abc_ObjFaninC0(pNode) && --pNode0->vFanouts.nSize == 0 ) Counter += Abc_NodeRefDerefStop( pNode0, fReference ); if ( !Abc_ObjFaninC1(pNode) && --pNode1->vFanouts.nSize == 0 ) Counter += Abc_NodeRefDerefStop( pNode1, fReference ); } return Counter; } /**Function************************************************************* Synopsis [Dereferences the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeDeref_rec( Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; int i, Counter = 1; if ( Abc_ObjIsCi(pNode) ) return 0; Abc_ObjForEachFanin( pNode, pFanin, i ) { assert( pFanin->vFanouts.nSize > 0 ); if ( --pFanin->vFanouts.nSize == 0 ) Counter += Abc_NodeDeref_rec( pFanin ); } return Counter; } /**Function************************************************************* Synopsis [References the node's MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeRef_rec( Abc_Obj_t * pNode ) { Abc_Obj_t * pFanin; int i, Counter = 1; if ( Abc_ObjIsCi(pNode) ) return 0; Abc_ObjForEachFanin( pNode, pFanin, i ) { if ( pFanin->vFanouts.nSize++ == 0 ) Counter += Abc_NodeRef_rec( pFanin ); } return Counter; } /**Function************************************************************* Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeMffcConeSupp_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int fTopmost ) { Abc_Obj_t * pFanin; int i; // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pNode) ) return; Abc_NodeSetTravIdCurrent(pNode); // add to the new support nodes if ( !fTopmost && (Abc_ObjIsCi(pNode) || pNode->vFanouts.nSize > 0) ) { if ( vSupp ) Vec_PtrPush( vSupp, pNode ); return; } // recur on the children Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_NodeMffcConeSupp_rec( pFanin, vCone, vSupp, 0 ); // collect the internal node if ( vCone ) Vec_PtrPush( vCone, pNode ); // printf( "%d ", pNode->Id ); } /**Function************************************************************* Synopsis [Collects the support of the derefed MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeMffcConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ) { assert( Abc_ObjIsNode(pNode) ); assert( !Abc_ObjIsComplement(pNode) ); if ( vCone ) Vec_PtrClear( vCone ); if ( vSupp ) Vec_PtrClear( vSupp ); Abc_NtkIncrementTravId( pNode->pNtk ); Abc_NodeMffcConeSupp_rec( pNode, vCone, vSupp, 1 ); // printf( "\n" ); } /**Function************************************************************* Synopsis [Collects the support of the derefed MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeMffcConeSuppPrint( Abc_Obj_t * pNode ) { Vec_Ptr_t * vCone, * vSupp; Abc_Obj_t * pObj; int i; vCone = Vec_PtrAlloc( 100 ); vSupp = Vec_PtrAlloc( 100 ); Abc_NodeDeref_rec( pNode ); Abc_NodeMffcConeSupp( pNode, vCone, vSupp ); Abc_NodeRef_rec( pNode ); printf( "Node = %6s : Supp = %3d Cone = %3d (", Abc_ObjName(pNode), Vec_PtrSize(vSupp), Vec_PtrSize(vCone) ); Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, i ) printf( " %s", Abc_ObjName(pObj) ); printf( " )\n" ); Vec_PtrFree( vCone ); Vec_PtrFree( vSupp ); } /**Function************************************************************* Synopsis [Collects the internal nodes of the MFFC limited by cut.] Description [] SideEffects [Increments the trav ID and marks visited nodes.] SeeAlso [] ***********************************************************************/ int Abc_NodeMffcInside( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vInside ) { Abc_Obj_t * pObj; int i, Count1, Count2; // increment the fanout counters for the leaves Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) pObj->vFanouts.nSize++; // dereference the node Count1 = Abc_NodeDeref_rec( pNode ); // collect the nodes inside the MFFC Abc_NodeMffcConeSupp( pNode, vInside, NULL ); // reference it back Count2 = Abc_NodeRef_rec( pNode ); assert( Count1 == Count2 ); // remove the extra counters Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) pObj->vFanouts.nSize--; return Count1; } /**Function************************************************************* Synopsis [Collects the internal nodes of the MFFC limited by cut.] Description [] SideEffects [Increments the trav ID and marks visited nodes.] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NodeMffcInsideCollect( Abc_Obj_t * pNode ) { Vec_Ptr_t * vInside; int Count1, Count2; // dereference the node Count1 = Abc_NodeDeref_rec( pNode ); // collect the nodes inside the MFFC vInside = Vec_PtrAlloc( 10 ); Abc_NodeMffcConeSupp( pNode, vInside, NULL ); // reference it back Count2 = Abc_NodeRef_rec( pNode ); assert( Count1 == Count2 ); return vInside; } /**Function************************************************************* Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeMffcLabel_rec( Abc_Obj_t * pNode, int fTopmost, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanin; int i; // add to the new support nodes if ( !fTopmost && (Abc_ObjIsCi(pNode) || pNode->vFanouts.nSize > 0) ) return; // skip visited nodes if ( Abc_NodeIsTravIdCurrent(pNode) ) return; Abc_NodeSetTravIdCurrent(pNode); // recur on the children Abc_ObjForEachFanin( pNode, pFanin, i ) Abc_NodeMffcLabel_rec( pFanin, 0, vNodes ); // collect the internal node // printf( "%d ", pNode->Id ); if ( vNodes ) Vec_PtrPush( vNodes, pNode ); } /**Function************************************************************* Synopsis [Collects the internal nodes of the MFFC limited by cut.] Description [] SideEffects [Increments the trav ID and marks visited nodes.] SeeAlso [] ***********************************************************************/ 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, vNodes ); // reference it back Count2 = Abc_NodeRef_rec( pNode ); assert( Count1 == Count2 ); return Count1; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcShow.c000066400000000000000000000376461477524141600162000ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcShow.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Visualization procedures using DOT software and GSView.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcShow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #ifdef WIN32 #include #else #include #endif #include "abc.h" #include "base/main/main.h" #include "base/io/ioAbc.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); static void Abc_ShowGetFileName( char * pName, char * pBuffer ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// #ifdef ABC_USE_CUDD /**Function************************************************************* Synopsis [Visualizes BDD of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeShowBddOne( DdManager * dd, DdNode * bFunc ) { char * FileNameDot = "temp.dot"; FILE * pFile; if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) { fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); return; } Cudd_DumpDot( dd, 1, (DdNode **)&bFunc, NULL, NULL, pFile ); fclose( pFile ); Abc_ShowFile( FileNameDot, 0 ); } /**Function************************************************************* Synopsis [Visualizes BDD of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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 Abc_ShowGetFileName( Abc_ObjName(pNode), 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 vNamesIn = Abc_NodeGetFaninNames( pNode ); pNameOut = Abc_ObjName(pNode); 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, 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, int fCompl ) {} void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl, int fReorder ) {} #endif /**Function************************************************************* Synopsis [Visualizes a reconvergence driven cut at the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) { FILE * pFile; char FileNameDot[200]; Abc_ManCut_t * p; Vec_Ptr_t * vCutSmall; Vec_Ptr_t * vCutLarge; Vec_Ptr_t * vInside; Vec_Ptr_t * vNodesTfo; Abc_Obj_t * pTemp; int i; assert( Abc_NtkIsStrash(pNode->pNtk) ); // start the cut computation manager p = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, ABC_INFINITY ); // get the recovergence driven cut vCutSmall = Abc_NodeFindCut( p, pNode, 1 ); // get the containing cut vCutLarge = Abc_NtkManCutReadCutLarge( p ); // get the array for the inside nodes vInside = Abc_NtkManCutReadVisited( p ); // get the inside nodes of the containing cone Abc_NodeConeCollect( &pNode, 1, vCutLarge, vInside, 1 ); // add the nodes in the TFO vNodesTfo = Abc_NodeCollectTfoCands( p, pNode, vCutSmall, ABC_INFINITY ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodesTfo, pTemp, i ) Vec_PtrPushUnique( vInside, pTemp ); // create the file name Abc_ShowGetFileName( Abc_ObjName(pNode), 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; } // add the root node to the cone (for visualization) Vec_PtrPush( vCutSmall, pNode ); // write the DOT file Io_WriteDotNtk( pNode->pNtk, vInside, vCutSmall, FileNameDot, 0, 0, 0 ); // stop the cut computation manager Abc_NtkManCutStop( p ); // visualize the file Abc_ShowFile( FileNameDot, 0 ); } /**Function************************************************************* Synopsis [Visualizes AIG with choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkShow( Abc_Ntk_t * pNtk0, int fGateNames, int fSeq, int fUseReverse, int fKeepDot, int fAigIds ) { FILE * pFile; Abc_Ntk_t * pNtk; Abc_Obj_t * pNode; Vec_Ptr_t * vNodes; int nBarBufs; char FileNameDot[200]; int i; assert( Abc_NtkIsStrash(pNtk0) || Abc_NtkIsLogic(pNtk0) ); if ( Abc_NtkIsStrash(pNtk0) && Abc_NtkGetChoiceNum(pNtk0) ) { printf( "Temporarily visualization of AIGs with choice nodes is disabled.\n" ); return; } // create the file name Abc_ShowGetFileName( pNtk0->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; } fclose( pFile ); // convert to logic SOP pNtk = Abc_NtkDup( pNtk0 ); if ( Abc_NtkIsLogic(pNtk) && !Abc_NtkHasMapping(pNtk) ) Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); // collect all nodes in the network vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachObj( pNtk, pNode, i ) Vec_PtrPush( vNodes, pNode ); // write the DOT file nBarBufs = pNtk->nBarBufs; pNtk->nBarBufs = 0; if ( fSeq ) Io_WriteDotSeq( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse ); else Io_WriteDotNtk( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse, fAigIds ); pNtk->nBarBufs = nBarBufs; Vec_PtrFree( vNodes ); // visualize the file Abc_ShowFile( FileNameDot, fKeepDot ); Abc_NtkDelete( pNtk ); } /**Function************************************************************* Synopsis [Shows the given DOT file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ShowFile( char * FileNameDot, int fKeepDot ) { FILE * pFile; char * FileGeneric; char FileNamePs[200]; char CommandDot[1000]; char * pDotName; char * pDotNameWin = "dot.exe"; char * pDotNameUnix = "dot"; char * pGsNameWin = "gsview32.exe"; char * pGsNameUnix = "gv"; int RetValue; // get DOT names from the resource file if ( Abc_FrameReadFlag("dotwin") ) pDotNameWin = Abc_FrameReadFlag("dotwin"); if ( Abc_FrameReadFlag("dotunix") ) pDotNameUnix = Abc_FrameReadFlag("dotunix"); #ifdef WIN32 pDotName = pDotNameWin; #else pDotName = pDotNameUnix; #endif // check if the input DOT file is okay if ( (pFile = fopen( FileNameDot, "r" )) == NULL ) { fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); return; } fclose( pFile ); // create the PostScript file name FileGeneric = Extra_FileNameGeneric( FileNameDot ); sprintf( FileNamePs, "%s.ps", FileGeneric ); ABC_FREE( FileGeneric ); // generate the PostScript file using DOT sprintf( CommandDot, "%s -Tps -o %s %s", pDotName, FileNamePs, FileNameDot ); #if defined(__wasm) RetValue = -1; #else RetValue = system( CommandDot ); #endif if ( RetValue == -1 ) { fprintf( stdout, "Command \"%s\" did not succeed.\n", CommandDot ); return; } // check that the input PostScript file is okay if ( (pFile = fopen( FileNamePs, "r" )) == NULL ) { fprintf( stdout, "Cannot open intermediate file \"%s\".\n", FileNamePs ); return; } fclose( pFile ); // get GSVIEW names from the resource file if ( Abc_FrameReadFlag("gsviewwin") ) pGsNameWin = Abc_FrameReadFlag("gsviewwin"); if ( Abc_FrameReadFlag("gsviewunix") ) pGsNameUnix = Abc_FrameReadFlag("gsviewunix"); // spawn the viewer #ifdef WIN32 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 ) if ( _spawnl( _P_NOWAIT, "C:\\Program Files\\Ghostgum\\gsview\\gsview64.exe", "C:\\Program Files\\Ghostgum\\gsview\\gsview64.exe", FileNamePs, NULL ) == -1 ) { fprintf( stdout, "Cannot find \"%s\".\n", pGsNameWin ); return; } #else { char CommandPs[1000]; if ( !fKeepDot ) unlink( FileNameDot ); sprintf( CommandPs, "%s %s &", pGsNameUnix, FileNamePs ); #if defined(__wasm) if ( 1 ) #else if ( system( CommandPs ) == -1 ) #endif { fprintf( stdout, "Cannot execute \"%s\".\n", CommandPs ); return; } } #endif } /**Function************************************************************* Synopsis [Derives the DOT file name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ShowGetFileName( char * pName, char * pBuffer ) { char * pCur; // creat the file name sprintf( pBuffer, "%s.dot", pName ); // get rid of not-alpha-numeric characters for ( pCur = pBuffer; *pCur; pCur++ ) if ( !((*pCur >= '0' && *pCur <= '9') || (*pCur >= 'a' && *pCur <= 'z') || (*pCur >= 'A' && *pCur <= 'Z') || (*pCur == '.')) ) *pCur = '_'; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkWriteFlopDependency( Abc_Ntk_t * pNtk, char * pFileName ) { FILE * pFile; Vec_Ptr_t * vSupp; Abc_Obj_t * pObj, * pTemp; int i, k, Count; pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { printf( "Cannot open input file %s.\n", pFileName ); return; } fprintf( pFile, "# Flop dependency for \"%s\" generated by ABC on %s\n", Abc_NtkName(pNtk), Extra_TimeStamp() ); fprintf( pFile, "digraph G {\n" ); fprintf( pFile, " graph [splines=true overlap=false];\n" ); fprintf( pFile, " size = \"7.5,10\";\n" ); fprintf( pFile, " center = true;\n" ); // fprintf( pFile, " edge [len=3,dir=forward];\n" ); fprintf( pFile, " edge [dir=forward];\n" ); Abc_NtkForEachLatchInput( pNtk, pObj, i ) { Abc_ObjFanout0( Abc_ObjFanout0(pObj) )->iTemp = i; vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); Count = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pTemp, k ) Count += Abc_ObjIsPi(pTemp); Vec_PtrFree( vSupp ); fprintf( pFile, " { rank = same; %d [label=\"%d(%d)\"]; }\n", i, i, Count ); } Abc_NtkForEachLatchInput( pNtk, pObj, i ) { vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); Count = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pTemp, k ) if ( !Abc_ObjIsPi(pTemp) ) fprintf( pFile, " %4d -> %4d\n", pTemp->iTemp, i ); Vec_PtrFree( vSupp ); } fprintf( pFile, "}\n" ); fclose( pFile ); } /**Function************************************************************* Synopsis [Visualizes AIG with choices.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkShowFlopDependency( Abc_Ntk_t * pNtk ) { FILE * pFile; char FileNameDot[200]; assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); // 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; } fclose( pFile ); // write the DOT file Abc_NtkWriteFlopDependency( pNtk, FileNameDot ); // visualize the file Abc_ShowFile( FileNameDot, 0 ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcSop.c000066400000000000000000001144561477524141600160140ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcSop.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Implementation of a simple SOP representation of nodes.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcSop.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" #include "bool/kit/kit.h" #ifdef _MSC_VER # include # define __builtin_popcount __popcnt #endif ABC_NAMESPACE_IMPL_START /* The SOPs in this package are represented using char * strings. For example, the SOP of the node: .names c d0 d1 MUX 01- 1 1-1 1 is the string: "01- 1\n1-1 1\n" where '\n' is a single char. */ //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Registers the cube string with the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopRegister( Mem_Flex_t * pMan, const char * pName ) { char * pRegName; if ( pName == NULL ) return NULL; pRegName = Mem_FlexEntryFetch( pMan, strlen(pName) + 1 ); strcpy( pRegName, pName ); return pRegName; } /**Function************************************************************* Synopsis [Creates the constant 1 cover with the given number of variables and cubes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopStart( Mem_Flex_t * pMan, int nCubes, int nVars ) { char * pSopCover, * pCube; int i, Length; Length = nCubes * (nVars + 3); pSopCover = Mem_FlexEntryFetch( pMan, Length + 1 ); memset( pSopCover, '-', (size_t)Length ); pSopCover[Length] = 0; for ( i = 0; i < nCubes; i++ ) { pCube = pSopCover + i * (nVars + 3); pCube[nVars + 0] = ' '; pCube[nVars + 1] = '1'; pCube[nVars + 2] = '\n'; } return pSopCover; } /**Function************************************************************* Synopsis [Creates the constant 1 cover with 0 variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateConst1( Mem_Flex_t * pMan ) { return Abc_SopRegister( pMan, " 1\n" ); } /**Function************************************************************* Synopsis [Creates the constant 1 cover with 0 variables.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateConst0( Mem_Flex_t * pMan ) { return Abc_SopRegister( pMan, " 0\n" ); } /**Function************************************************************* Synopsis [Creates the AND2 cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateAnd2( Mem_Flex_t * pMan, int fCompl0, int fCompl1 ) { char Buffer[6]; Buffer[0] = '1' - fCompl0; Buffer[1] = '1' - fCompl1; Buffer[2] = ' '; Buffer[3] = '1'; Buffer[4] = '\n'; Buffer[5] = 0; return Abc_SopRegister( pMan, Buffer ); } /**Function************************************************************* Synopsis [Creates the multi-input AND cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateAnd( Mem_Flex_t * pMan, int nVars, int * pfCompl ) { char * pSop; int i; pSop = Abc_SopStart( pMan, 1, nVars ); for ( i = 0; i < nVars; i++ ) pSop[i] = '1' - (pfCompl? pfCompl[i] : 0); pSop[nVars + 1] = '1'; return pSop; } /**Function************************************************************* Synopsis [Creates the multi-input NAND cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateNand( Mem_Flex_t * pMan, int nVars ) { char * pSop; int i; pSop = Abc_SopStart( pMan, 1, nVars ); for ( i = 0; i < nVars; i++ ) pSop[i] = '1'; pSop[nVars + 1] = '0'; return pSop; } /**Function************************************************************* Synopsis [Creates the multi-input OR cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateOr( Mem_Flex_t * pMan, int nVars, int * pfCompl ) { char * pSop; int i; pSop = Abc_SopStart( pMan, 1, nVars ); for ( i = 0; i < nVars; i++ ) pSop[i] = '0' + (pfCompl? pfCompl[i] : 0); pSop[nVars + 1] = '0'; return pSop; } /**Function************************************************************* Synopsis [Creates the multi-input OR cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateOrMultiCube( Mem_Flex_t * pMan, int nVars, int * pfCompl ) { char * pSop, * pCube; int i; pSop = Abc_SopStart( pMan, nVars, nVars ); i = 0; Abc_SopForEachCube( pSop, nVars, pCube ) { pCube[i] = '1' - (pfCompl? pfCompl[i] : 0); i++; } return pSop; } /**Function************************************************************* Synopsis [Creates the multi-input NOR cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateNor( Mem_Flex_t * pMan, int nVars ) { char * pSop; int i; pSop = Abc_SopStart( pMan, 1, nVars ); for ( i = 0; i < nVars; i++ ) pSop[i] = '0'; return pSop; } /**Function************************************************************* Synopsis [Creates the multi-input XOR cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateXor( Mem_Flex_t * pMan, int nVars ) { assert( nVars == 2 ); return Abc_SopRegister(pMan, "01 1\n10 1\n"); } /**Function************************************************************* Synopsis [Creates the multi-input XOR cover (special case).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateXorSpecial( Mem_Flex_t * pMan, int nVars ) { char * pSop; pSop = Abc_SopCreateAnd( pMan, nVars, NULL ); pSop[nVars+1] = 'x'; assert( pSop[nVars+2] == '\n' ); return pSop; } /**Function************************************************************* Synopsis [Creates the multi-input XNOR cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateNxor( Mem_Flex_t * pMan, int nVars ) { assert( nVars == 2 ); return Abc_SopRegister(pMan, "11 1\n00 1\n"); } /**Function************************************************************* Synopsis [Creates the MUX cover.] Description [The first input of MUX is the control. The second input is DATA1. The third input is DATA0.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateMux( Mem_Flex_t * pMan ) { return Abc_SopRegister(pMan, "11- 1\n0-1 1\n"); } /**Function************************************************************* Synopsis [Creates the inv cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateInv( Mem_Flex_t * pMan ) { return Abc_SopRegister(pMan, "0 1\n"); } /**Function************************************************************* Synopsis [Creates the buf cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateBuf( Mem_Flex_t * pMan ) { return Abc_SopRegister(pMan, "1 1\n"); } /**Function************************************************************* Synopsis [Creates the arbitrary cover from the truth table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateFromTruth( Mem_Flex_t * pMan, int nVars, unsigned * pTruth ) { char * pSop, * pCube; int nMints, Counter, i, k; if ( nVars == 0 ) return pTruth[0] ? Abc_SopCreateConst1(pMan) : Abc_SopCreateConst0(pMan); // count the number of true minterms Counter = 0; nMints = (1 << nVars); for ( i = 0; i < nMints; i++ ) Counter += ((pTruth[i>>5] & (1 << (i&31))) > 0); // SOP is not well-defined if the truth table is constant 0 assert( Counter > 0 ); if ( Counter == 0 ) return NULL; // start the cover pSop = Abc_SopStart( pMan, Counter, nVars ); // create true minterms Counter = 0; for ( i = 0; i < nMints; i++ ) if ( (pTruth[i>>5] & (1 << (i&31))) > 0 ) { pCube = pSop + Counter * (nVars + 3); for ( k = 0; k < nVars; k++ ) pCube[k] = '0' + ((i & (1 << k)) > 0); Counter++; } return pSop; } /**Function************************************************************* Synopsis [Creates the cover from the ISOP computed from TT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateFromIsop( Mem_Flex_t * pMan, int nVars, Vec_Int_t * vCover ) { char * pSop, * pCube; int i, k, Entry, Literal; assert( Vec_IntSize(vCover) > 0 ); if ( Vec_IntSize(vCover) == 0 ) return NULL; // start the cover pSop = Abc_SopStart( pMan, Vec_IntSize(vCover), nVars ); // create cubes Vec_IntForEachEntry( vCover, Entry, i ) { pCube = pSop + i * (nVars + 3); for ( k = 0; k < nVars; k++ ) { Literal = 3 & (Entry >> (k << 1)); if ( Literal == 1 ) pCube[k] = '0'; else if ( Literal == 2 ) pCube[k] = '1'; else if ( Literal != 0 ) assert( 0 ); } } return pSop; } /**Function************************************************************* Synopsis [Creates the cover from the ISOP computed from TT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopCreateFromTruthIsop( Mem_Flex_t * pMan, int nVars, word * pTruth, Vec_Int_t * vCover ) { char * pSop = NULL; 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 ); assert( RetValue == 0 || RetValue == 1 ); pSop = Abc_SopCreateFromIsop( pMan, nVars, vCover ); if ( RetValue ) Abc_SopComplement( pSop ); } return pSop; } /**Function************************************************************* Synopsis [Creates the cover from the ISOP computed from TT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SopToIsop( char * pSop, Vec_Int_t * vCover ) { char * pCube; int k, nVars, Entry; nVars = Abc_SopGetVarNum( pSop ); assert( nVars > 0 ); // create cubes Vec_IntClear( vCover ); for ( pCube = pSop; *pCube; pCube += nVars + 3 ) { Entry = 0; for ( k = nVars - 1; k >= 0; k-- ) if ( pCube[k] == '0' ) Entry = (Entry << 2) | 1; else if ( pCube[k] == '1' ) Entry = (Entry << 2) | 2; else if ( pCube[k] == '-' ) Entry = (Entry << 2); else assert( 0 ); Vec_IntPush( vCover, Entry ); } } /**Function************************************************************* Synopsis [Reads the number of cubes in the cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SopGetCubeNum( char * pSop ) { char * pCur; int nCubes = 0; if ( pSop == NULL ) return 0; for ( pCur = pSop; *pCur; pCur++ ) nCubes += (*pCur == '\n'); return nCubes; } /**Function************************************************************* Synopsis [Reads the number of SOP literals in the cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SopGetLitNum( char * pSop ) { char * pCur; int nLits = 0; if ( pSop == NULL ) return 0; for ( pCur = pSop; *pCur; pCur++ ) { nLits -= (*pCur == '\n'); nLits += (*pCur == '0' || *pCur == '1'); } return nLits; } /**Function************************************************************* Synopsis [Reads the number of variables in the cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SopGetVarNum( char * pSop ) { char * pCur; for ( pCur = pSop; *pCur != '\n'; pCur++ ) if ( *pCur == 0 ) return -1; return pCur - pSop - 2; } /**Function************************************************************* Synopsis [Reads the phase of the cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SopGetPhase( char * pSop ) { int nVars = Abc_SopGetVarNum( pSop ); if ( pSop[nVars+1] == '0' || pSop[nVars+1] == 'n' ) return 0; if ( pSop[nVars+1] == '1' || pSop[nVars+1] == 'x' ) return 1; assert( 0 ); return -1; } /**Function************************************************************* Synopsis [Returns the i-th literal of the cover.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SopGetIthCareLit( char * pSop, int i ) { char * pCube; int nVars; nVars = Abc_SopGetVarNum( pSop ); Abc_SopForEachCube( pSop, nVars, pCube ) if ( pCube[i] != '-' ) return pCube[i] - '0'; return -1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SopComplement( char * pSop ) { char * pCur; for ( pCur = pSop; *pCur; pCur++ ) if ( *pCur == '\n' ) { if ( *(pCur - 1) == '0' ) *(pCur - 1) = '1'; else if ( *(pCur - 1) == '1' ) *(pCur - 1) = '0'; else if ( *(pCur - 1) == 'x' ) *(pCur - 1) = 'n'; else if ( *(pCur - 1) == 'n' ) *(pCur - 1) = 'x'; else assert( 0 ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SopComplementVar( char * pSop, int iVar ) { char * pCube; int nVars = Abc_SopGetVarNum(pSop); assert( iVar < nVars ); Abc_SopForEachCube( pSop, nVars, pCube ) { if ( pCube[iVar] == '0' ) pCube[iVar] = '1'; else if ( pCube[iVar] == '1' ) pCube[iVar] = '0'; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SopIsComplement( char * pSop ) { char * pCur; for ( pCur = pSop; *pCur; pCur++ ) if ( *pCur == '\n' ) return (int)(*(pCur - 1) == '0' || *(pCur - 1) == 'n'); assert( 0 ); return 0; } /**Function************************************************************* Synopsis [Checks if the cover is constant 0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SopIsConst0( char * pSop ) { return pSop[0] == ' ' && pSop[1] == '0'; } /**Function************************************************************* Synopsis [Checks if the cover is constant 1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SopIsConst1( char * pSop ) { return pSop[0] == ' ' && pSop[1] == '1'; } /**Function************************************************************* Synopsis [Checks if the cover is constant 1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SopIsBuf( char * pSop ) { if ( pSop[4] != 0 ) return 0; if ( (pSop[0] == '1' && pSop[2] == '1') || (pSop[0] == '0' && pSop[2] == '0') ) return 1; return 0; } /**Function************************************************************* Synopsis [Checks if the cover is constant 1.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SopIsInv( char * pSop ) { if ( pSop[4] != 0 ) return 0; if ( (pSop[0] == '0' && pSop[2] == '1') || (pSop[0] == '1' && pSop[2] == '0') ) return 1; return 0; } /**Function************************************************************* Synopsis [Checks if the cover is AND with possibly complemented inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SopIsAndType( char * pSop ) { char * pCur; if ( Abc_SopGetCubeNum(pSop) != 1 ) return 0; for ( pCur = pSop; *pCur != ' '; pCur++ ) if ( *pCur == '-' ) return 0; if ( pCur[1] != '1' ) return 0; return 1; } /**Function************************************************************* Synopsis [Checks if the cover is OR with possibly complemented inputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SopIsOrType( char * pSop ) { char * pCube, * pCur; int nVars, nLits; nVars = Abc_SopGetVarNum( pSop ); if ( nVars != Abc_SopGetCubeNum(pSop) ) return 0; Abc_SopForEachCube( pSop, nVars, pCube ) { // count the number of literals in the cube nLits = 0; for ( pCur = pCube; *pCur != ' '; pCur++ ) nLits += ( *pCur != '-' ); if ( nLits != 1 ) return 0; } return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SopIsExorType( char * pSop ) { char * pCur; for ( pCur = pSop; *pCur; pCur++ ) if ( *pCur == '\n' ) return (int)(*(pCur - 1) == 'x' || *(pCur - 1) == 'n'); assert( 0 ); return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_SopCheck( char * pSop, int nFanins ) { char * pCubes, * pCubesOld; int fFound0 = 0, fFound1 = 0; // check the logic function of the node for ( pCubes = pSop; *pCubes; pCubes++ ) { // get the end of the next cube for ( pCubesOld = pCubes; *pCubes != ' '; pCubes++ ); // compare the distance if ( pCubes - pCubesOld != nFanins ) { fprintf( stdout, "Abc_SopCheck: SOP has a mismatch between its cover size (%d) and its fanin number (%d).\n", (int)(ABC_PTRDIFF_T)(pCubes - pCubesOld), nFanins ); return 0; } // check the output values for this cube pCubes++; if ( *pCubes == '0' ) fFound0 = 1; else if ( *pCubes == '1' ) fFound1 = 1; else if ( *pCubes != 'x' && *pCubes != 'n' ) { fprintf( stdout, "Abc_SopCheck: SOP has a strange character (%c) in the output part of its cube.\n", *pCubes ); return 0; } // check the last symbol (new line) pCubes++; if ( *pCubes != '\n' ) { fprintf( stdout, "Abc_SopCheck: SOP has a cube without new line in the end.\n" ); return 0; } } if ( fFound0 && fFound1 ) { fprintf( stdout, "Abc_SopCheck: SOP has cubes in both phases.\n" ); return 0; } 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************************************************************* Synopsis [Derives SOP from the truth table representation.] Description [Truth table is expected to be in the hexadecimal notation.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopFromTruthBin( char * pTruth ) { char * pSopCover, * pCube; int nTruthSize, nVars, Digit, Length, Mint, i, b; Vec_Int_t * vMints; // get the number of variables nTruthSize = strlen(pTruth); nVars = Abc_Base2Log( nTruthSize ); if ( nTruthSize != (1 << (nVars)) ) { printf( "String %s does not look like a truth table of a %d-variable function.\n", pTruth, nVars ); return NULL; } // collect the on-set minterms vMints = Vec_IntAlloc( 100 ); for ( i = 0; i < nTruthSize; i++ ) { if ( pTruth[i] >= '0' && pTruth[i] <= '1' ) Digit = pTruth[i] - '0'; else { Vec_IntFree( vMints ); printf( "String %s does not look like a binary representation of the truth table.\n", pTruth ); return NULL; } 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; } */ if ( Vec_IntSize(vMints) == 0 || Vec_IntSize(vMints) == (1 << nVars) ) { 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************************************************************* Synopsis [Derives SOP from the truth table representation.] Description [Truth table is expected to be in the hexadecimal notation.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopFromTruthHex( char * pTruth ) { char * pSopCover, * pCube; int nTruthSize, nVars, Digit, Length, Mint, i, b; Vec_Int_t * vMints; // get the number of variables nTruthSize = strlen(pTruth); nVars = (nTruthSize < 2) ? 2 : Abc_Base2Log(nTruthSize) + 2; if ( nTruthSize != (1 << (nVars-2)) ) { printf( "String %s does not look like a truth table of a %d-variable function.\n", pTruth, nVars ); return NULL; } // collect the on-set minterms vMints = Vec_IntAlloc( 100 ); for ( i = 0; i < nTruthSize; i++ ) { if ( pTruth[i] >= '0' && pTruth[i] <= '9' ) Digit = pTruth[i] - '0'; else if ( pTruth[i] >= 'a' && pTruth[i] <= 'f' ) Digit = 10 + pTruth[i] - 'a'; else if ( pTruth[i] >= 'A' && pTruth[i] <= 'F' ) Digit = 10 + pTruth[i] - 'A'; else { printf( "String %s does not look like a hexadecimal representation of the truth table.\n", pTruth ); return NULL; } for ( b = 0; b < 4; b++ ) if ( Digit & (1 << b) ) Vec_IntPush( vMints, 4*(nTruthSize-1-i)+b ); } // create the SOP representation of the minterms if ( Vec_IntSize(vMints) == 0 || Vec_IntSize(vMints) == (1 << nVars) ) { pSopCover = ABC_ALLOC( char, 4 ); pSopCover[0] = ' '; pSopCover[1] = '0' + (Vec_IntSize(vMints) > 0); pSopCover[2] = '\n'; pSopCover[3] = 0; } else { 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_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; } Vec_Ptr_t * Abc_SopGenerateCounters( int nVars ) { int m, i, o, nOuts = Abc_Base2Log( nVars + 1 ); Vec_Ptr_t * vRes = Vec_PtrAlloc( nOuts ); for ( o = 0; o < nOuts; o++ ) { Vec_Str_t * vStr = Vec_StrAlloc( 1000 ); for ( m = 0; m < (1 << nVars); m++ ) { int nOnes = __builtin_popcount(m); if ( !((nOnes >> o) & 1) ) continue; for ( i = 0; i < nVars; i++ ) Vec_StrPush( vStr, ((m >> i) & 1) ? '1' : '0' ); Vec_StrPush( vStr, ' ' ); Vec_StrPush( vStr, '1' ); Vec_StrPush( vStr, '\n' ); } Vec_StrPush( vStr, '\0' ); //printf( "%s\n", Vec_StrArray(vStr) ); Vec_PtrPush( vRes, Vec_StrReleaseArray(vStr) ); Vec_StrFree( vStr ); } return vRes; } /**Function************************************************************* Synopsis [Creates one encoder node.] Description [Produces MV-SOP for BLIF-MV representation.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopEncoderPos( Mem_Flex_t * pMan, int iValue, int nValues ) { char Buffer[32]; assert( iValue < nValues ); sprintf( Buffer, "d0\n%d 1\n", iValue ); return Abc_SopRegister( pMan, Buffer ); } /**Function************************************************************* Synopsis [Creates one encoder node.] Description [Produces MV-SOP for BLIF-MV representation.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopEncoderLog( Mem_Flex_t * pMan, int iBit, int nValues ) { char * pResult; Vec_Str_t * vSop; int v, Counter, fFirst = 1, nBits = Abc_Base2Log(nValues); assert( iBit < nBits ); // count the number of literals Counter = 0; for ( v = 0; v < nValues; v++ ) Counter += ( (v & (1 << iBit)) > 0 ); // create the cover vSop = Vec_StrAlloc( 100 ); Vec_StrPrintStr( vSop, "d0\n" ); if ( Counter > 1 ) Vec_StrPrintStr( vSop, "(" ); for ( v = 0; v < nValues; v++ ) if ( v & (1 << iBit) ) { if ( fFirst ) fFirst = 0; else Vec_StrPush( vSop, ',' ); Vec_StrPrintNum( vSop, v ); } if ( Counter > 1 ) Vec_StrPrintStr( vSop, ")" ); Vec_StrPrintStr( vSop, " 1\n" ); Vec_StrPush( vSop, 0 ); pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) ); Vec_StrFree( vSop ); return pResult; } /**Function************************************************************* Synopsis [Creates the decoder node.] Description [Produces MV-SOP for BLIF-MV representation.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopDecoderPos( Mem_Flex_t * pMan, int nValues ) { char * pResult; Vec_Str_t * vSop; int i, k; assert( nValues > 1 ); vSop = Vec_StrAlloc( 100 ); for ( i = 0; i < nValues; i++ ) { for ( k = 0; k < nValues; k++ ) { if ( k == i ) Vec_StrPrintStr( vSop, "1 " ); else Vec_StrPrintStr( vSop, "- " ); } Vec_StrPrintNum( vSop, i ); Vec_StrPush( vSop, '\n' ); } Vec_StrPush( vSop, 0 ); pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) ); Vec_StrFree( vSop ); return pResult; } /**Function************************************************************* Synopsis [Creates the decover node.] Description [Produces MV-SOP for BLIF-MV representation.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_SopDecoderLog( Mem_Flex_t * pMan, int nValues ) { char * pResult; Vec_Str_t * vSop; int i, b, nBits = Abc_Base2Log(nValues); assert( nValues > 1 && nValues <= (1< 0) ); Vec_StrPush( vSop, ' ' ); } Vec_StrPrintNum( vSop, i ); Vec_StrPush( vSop, '\n' ); } Vec_StrPush( vSop, 0 ); pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) ); Vec_StrFree( vSop ); return pResult; } /**Function************************************************************* Synopsis [Computes truth table of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ word Abc_SopToTruth( char * pSop, int nInputs ) { static word Truth[8] = { ABC_CONST(0xAAAAAAAAAAAAAAAA), ABC_CONST(0xCCCCCCCCCCCCCCCC), ABC_CONST(0xF0F0F0F0F0F0F0F0), ABC_CONST(0xFF00FF00FF00FF00), ABC_CONST(0xFFFF0000FFFF0000), ABC_CONST(0xFFFFFFFF00000000), ABC_CONST(0x0000000000000000), ABC_CONST(0xFFFFFFFFFFFFFFFF) }; word Cube, Result = 0; int v, lit = 0; int nVars = Abc_SopGetVarNum(pSop); assert( nVars >= 0 && nVars <= 6 ); assert( nVars == nInputs ); do { Cube = Truth[7]; for ( v = 0; v < nVars; v++, lit++ ) { if ( pSop[lit] == '1' ) Cube &= Truth[v]; else if ( pSop[lit] == '0' ) Cube &= ~Truth[v]; else if ( pSop[lit] != '-' ) assert( 0 ); } Result |= Cube; assert( pSop[lit] == ' ' ); lit++; lit++; assert( pSop[lit] == '\n' ); lit++; } while ( pSop[lit] ); if ( Abc_SopIsComplement(pSop) ) Result = ~Result; return Result; } /**Function************************************************************* Synopsis [Computes truth table of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SopToTruth7( char * pSop, int nInputs, word r[2] ) { static word Truth[7][2] = { {ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA)}, {ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC)}, {ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0)}, {ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00)}, {ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000)}, {ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000)}, {ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF)}, }; word Cube[2]; int v, lit = 0; int nVars = Abc_SopGetVarNum(pSop); assert( nVars >= 0 && nVars <= 7 ); assert( nVars == nInputs ); r[0] = r[1] = 0; do { Cube[0] = Cube[1] = ~(word)0; for ( v = 0; v < nVars; v++, lit++ ) { if ( pSop[lit] == '1' ) { Cube[0] &= Truth[v][0]; Cube[1] &= Truth[v][1]; } else if ( pSop[lit] == '0' ) { Cube[0] &= ~Truth[v][0]; Cube[1] &= ~Truth[v][1]; } else if ( pSop[lit] != '-' ) assert( 0 ); } r[0] |= Cube[0]; r[1] |= Cube[1]; assert( pSop[lit] == ' ' ); lit++; lit++; assert( pSop[lit] == '\n' ); lit++; } while ( pSop[lit] ); if ( Abc_SopIsComplement(pSop) ) { r[0] = ~r[0]; r[1] = ~r[1]; } } /**Function************************************************************* Synopsis [Computes truth table of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_SopToTruthBig( char * pSop, int nInputs, word ** pVars, word * pCube, word * pRes ) { int nVars = Abc_SopGetVarNum(pSop); int nWords = nVars <= 6 ? 1 : 1 << (nVars-6); int v, i, lit = 0; assert( nVars >= 0 && nVars <= 16 ); assert( nVars == nInputs ); for ( i = 0; i < nWords; i++ ) pRes[i] = 0; do { for ( i = 0; i < nWords; i++ ) pCube[i] = ~(word)0; for ( v = 0; v < nVars; v++, lit++ ) { if ( pSop[lit] == '1' ) { for ( i = 0; i < nWords; i++ ) pCube[i] &= pVars[v][i]; } else if ( pSop[lit] == '0' ) { for ( i = 0; i < nWords; i++ ) pCube[i] &= ~pVars[v][i]; } else if ( pSop[lit] != '-' ) assert( 0 ); } for ( i = 0; i < nWords; i++ ) pRes[i] |= pCube[i]; assert( pSop[lit] == ' ' ); lit++; lit++; assert( pSop[lit] == '\n' ); lit++; } while ( pSop[lit] ); if ( Abc_SopIsComplement(pSop) ) { for ( i = 0; i < nWords; i++ ) pRes[i] = ~pRes[i]; } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abcUtil.c000066400000000000000000003362361477524141600161720ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abcUtil.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Various utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abcUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" #include "base/main/main.h" #include "map/mio/mio.h" #include "bool/dec/dec.h" #include "opt/fxu/fxu.h" #include "aig/miniaig/ndr.h" #include "misc/util/utilTruth.h" #ifdef ABC_USE_CUDD #include "bdd/extrab/extraBdd.h" #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Frees one attribute manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan ) { void * pUserMan; Vec_Att_t * pAttrMan; pAttrMan = (Vec_Att_t *)Vec_PtrEntry( pNtk->vAttrs, Attr ); Vec_PtrWriteEntry( pNtk->vAttrs, Attr, NULL ); pUserMan = Vec_AttFree( pAttrMan, fFreeMan ); return pUserMan; } /**Function************************************************************* Synopsis [Order CI/COs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkOrderCisCos( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pTerm; int i, k; Vec_PtrClear( pNtk->vCis ); Vec_PtrClear( pNtk->vCos ); Abc_NtkForEachPi( pNtk, pObj, i ) Vec_PtrPush( pNtk->vCis, pObj ); Abc_NtkForEachPo( pNtk, pObj, i ) Vec_PtrPush( pNtk->vCos, pObj ); Abc_NtkForEachBox( pNtk, pObj, i ) { if ( Abc_ObjIsLatch(pObj) ) continue; Abc_ObjForEachFanin( pObj, pTerm, k ) Vec_PtrPush( pNtk->vCos, pTerm ); Abc_ObjForEachFanout( pObj, pTerm, k ) Vec_PtrPush( pNtk->vCis, pTerm ); } Abc_NtkForEachBox( pNtk, pObj, i ) { if ( !Abc_ObjIsLatch(pObj) ) continue; Abc_ObjForEachFanin( pObj, pTerm, k ) Vec_PtrPush( pNtk->vCos, pTerm ); Abc_ObjForEachFanout( pObj, pTerm, k ) Vec_PtrPush( pNtk->vCis, pTerm ); } } /**Function************************************************************* Synopsis [Reads the number of cubes of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, nCubes = 0; assert( Abc_NtkHasSop(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_NodeIsConst(pNode) ) continue; assert( pNode->pData ); nCubes += Abc_SopGetCubeNum( (char *)pNode->pData ); } return nCubes; } /**Function************************************************************* Synopsis [Reads the number of cubes of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkGetCubePairNum( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i; word nCubes, nCubePairs = 0; assert( Abc_NtkHasSop(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_NodeIsConst(pNode) ) continue; assert( pNode->pData ); nCubes = (word)Abc_SopGetCubeNum( (char *)pNode->pData ); if ( nCubes > 1 ) nCubePairs += nCubes * (nCubes - 1) / 2; } return (int)(nCubePairs > (1<<30) ? (1<<30) : nCubePairs); } /**Function************************************************************* Synopsis [Reads the number of literals in the SOPs of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkGetLitNum( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, nLits = 0; assert( Abc_NtkHasSop(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { assert( pNode->pData ); nLits += Abc_SopGetLitNum( (char *)pNode->pData ); } return nLits; } /**Function************************************************************* Synopsis [Counts the number of literals in the factored forms.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkGetLitFactNum( Abc_Ntk_t * pNtk ) { Dec_Graph_t * pFactor; Abc_Obj_t * pNode; int nNodes, i; assert( Abc_NtkHasSop(pNtk) ); nNodes = 0; Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_NodeIsConst(pNode) ) continue; pFactor = Dec_Factor( (char *)pNode->pData ); nNodes += 1 + Dec_GraphNodeNum(pFactor); Dec_GraphFree( pFactor ); } return nNodes; } /**Function************************************************************* Synopsis [Counts the number of nodes with more than 1 reference.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkGetMultiRefNum( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int nNodes, i; assert( Abc_NtkIsStrash(pNtk) ); nNodes = 0; Abc_NtkForEachNode( pNtk, pNode, i ) nNodes += (int)(Abc_ObjFanoutNum(pNode) > 1); return nNodes; } /**Function************************************************************* Synopsis [Reads the number of BDD nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkGetBddNodeNum( Abc_Ntk_t * pNtk ) { int nNodes = 0; #ifdef ABC_USE_CUDD Abc_Obj_t * pNode; int i; assert( Abc_NtkIsBddLogic(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { assert( pNode->pData ); if ( Abc_ObjFaninNum(pNode) < 2 ) continue; nNodes += pNode->pData? -1 + Cudd_DagSize( (DdNode *)pNode->pData ) : 0; } #endif return nNodes; } /**Function************************************************************* Synopsis [Reads the number of BDD nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkGetAigNodeNum( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, nNodes = 0; assert( Abc_NtkIsAigLogic(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { assert( pNode->pData ); if ( Abc_ObjFaninNum(pNode) < 2 ) continue; //printf( "%d ", Hop_DagSize( pNode->pData ) ); nNodes += pNode->pData? Hop_DagSize( (Hop_Obj_t *)pNode->pData ) : 0; } return nNodes; } /**Function************************************************************* Synopsis [Reads the number of BDD nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkGetClauseNum( Abc_Ntk_t * pNtk ) { int nClauses = 0; #ifdef ABC_USE_CUDD extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ); Abc_Obj_t * pNode; DdNode * bCover, * zCover, * bFunc; DdManager * dd = (DdManager *)pNtk->pManFunc; int i; assert( Abc_NtkIsBddLogic(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { assert( pNode->pData ); bFunc = (DdNode *)pNode->pData; bCover = Cudd_zddIsop( dd, bFunc, bFunc, &zCover ); Cudd_Ref( bCover ); Cudd_Ref( zCover ); nClauses += Abc_CountZddCubes( dd, zCover ); Cudd_RecursiveDeref( dd, bCover ); Cudd_RecursiveDerefZdd( dd, zCover ); bCover = Cudd_zddIsop( dd, Cudd_Not(bFunc), Cudd_Not(bFunc), &zCover ); Cudd_Ref( bCover ); Cudd_Ref( zCover ); nClauses += Abc_CountZddCubes( dd, zCover ); Cudd_RecursiveDeref( dd, bCover ); Cudd_RecursiveDerefZdd( dd, zCover ); } #endif return nClauses; } /**Function************************************************************* Synopsis [Computes the area of the mapped circuit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; double TotalArea; int i; assert( Abc_NtkHasMapping(pNtk) ); TotalArea = 0.0; Abc_NtkForEachNode( pNtk, pObj, i ) { if ( Abc_ObjIsBarBuf(pObj) ) continue; // assert( pObj->pData ); if ( pObj->pData == NULL ) { printf( "Node without mapping is encountered.\n" ); continue; } TotalArea += Mio_GateReadArea( (Mio_Gate_t *)pObj->pData ); // assuming that twin gates follow each other if ( Abc_NtkFetchTwinNode(pObj) ) i++; } return TotalArea; } /**Function************************************************************* Synopsis [Counts the number of exors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, Counter = 0; Abc_NtkForEachNode( pNtk, pNode, i ) Counter += pNode->fExor; return Counter; } /**Function************************************************************* Synopsis [Counts the number of exors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, Counter = 0; Abc_NtkForEachNode( pNtk, pNode, i ) Counter += Abc_NodeIsMuxType(pNode); return Counter; } /**Function************************************************************* Synopsis [Counts the number of exors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkGetBufNum( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, Counter = 0; Abc_NtkForEachNode( pNtk, pNode, i ) Counter += (Abc_ObjFaninNum(pNode) == 1); return Counter; } /**Function************************************************************* Synopsis [Counts the number of exors.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkGetLargeNodeNum( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, Counter = 0; Abc_NtkForEachNode( pNtk, pNode, i ) Counter += (Abc_ObjFaninNum(pNode) > 1); return Counter; } /**Function************************************************************* Synopsis [Returns 1 if it is an AIG with choice nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, Counter; if ( !Abc_NtkIsStrash(pNtk) ) return 0; Counter = 0; Abc_NtkForEachNode( pNtk, pNode, i ) Counter += Abc_AigNodeIsChoice( pNode ); return Counter; } /**Function************************************************************* Synopsis [Reads the maximum number of fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, nFaninsMax = 0; Abc_NtkForEachNode( pNtk, pNode, i ) { if ( nFaninsMax < Abc_ObjFaninNum(pNode) ) nFaninsMax = Abc_ObjFaninNum(pNode); } return nFaninsMax; } int Abc_NtkGetFanoutMax( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, nFaninsMax = 0; Abc_NtkForEachNode( pNtk, pNode, i ) { if ( nFaninsMax < Abc_ObjFanoutNum(pNode) ) nFaninsMax = Abc_ObjFanoutNum(pNode); } return nFaninsMax; } /**Function************************************************************* Synopsis [Reads the total number of all fanins.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkGetTotalFanins( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, nFanins = 0; Abc_NtkForEachNode( pNtk, pNode, i ) nFanins += Abc_ObjFaninNum(pNode); return nFanins; } /**Function************************************************************* Synopsis [Cleans the copy field of all objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) pObj->pCopy = NULL; } void Abc_NtkCleanCopy_rec( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkCleanCopy( pNtk ); Abc_NtkForEachBox( pNtk, pObj, i ) Abc_NtkCleanCopy_rec( Abc_ObjModel(pObj) ); } /**Function************************************************************* Synopsis [Cleans the copy field of all objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCleanData( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) pObj->pData = NULL; } /**Function************************************************************* Synopsis [Cleans the copy field of all objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFillTemp( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) pObj->iTemp = -1; } /**Function************************************************************* Synopsis [Counts the number of nodes having non-trivial copies.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCountCopy( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i, Counter = 0; Abc_NtkForEachObj( pNtk, pObj, i ) { if ( Abc_ObjIsNode(pObj) ) Counter += (pObj->pCopy != NULL); } return Counter; } /**Function************************************************************* Synopsis [Saves copy field of the objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkSaveCopy( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vCopies; Abc_Obj_t * pObj; int i; vCopies = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachObj( pNtk, pObj, i ) Vec_PtrWriteEntry( vCopies, i, pObj->pCopy ); return vCopies; } /**Function************************************************************* Synopsis [Loads copy field of the objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Vec_PtrEntry( vCopies, i ); } /**Function************************************************************* Synopsis [Cleans the copy field of all objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCleanNext( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) pObj->pNext = NULL; } void Abc_NtkCleanNext_rec( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkCleanNext( pNtk ); Abc_NtkForEachBox( pNtk, pObj, i ) Abc_NtkCleanNext_rec( Abc_ObjModel(pObj) ); } /**Function************************************************************* Synopsis [Cleans the copy field of all objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCleanMarkA( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) pObj->fMarkA = 0; } /**Function************************************************************* Synopsis [Cleans the copy field of all objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCleanMarkB( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) pObj->fMarkB = 0; } /**Function************************************************************* Synopsis [Cleans the copy field of all objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCleanMarkC( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) pObj->fMarkC = 0; } /**Function************************************************************* Synopsis [Cleans the copy field of all objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCleanMarkAB( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) pObj->fMarkA = pObj->fMarkB = 0; } /**Function************************************************************* Synopsis [Cleans the copy field of all objects.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCleanMarkABC( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) pObj->fMarkA = pObj->fMarkB = pObj->fMarkC = 0; } /**Function************************************************************* Synopsis [Returns the index of the given fanin.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeFindFanin( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) { Abc_Obj_t * pThis; int i; Abc_ObjForEachFanin( pNode, pThis, i ) if ( pThis == pFanin ) return i; return -1; } /**Function************************************************************* Synopsis [Checks if the internal node has CO fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeFindCoFanout( Abc_Obj_t * pNode ) { Abc_Obj_t * pFanout; int i; Abc_ObjForEachFanout( pNode, pFanout, i ) if ( Abc_ObjIsCo(pFanout) ) return pFanout; return NULL; } /**Function************************************************************* Synopsis [Checks if the internal node has CO fanout.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode ) { Abc_Obj_t * pFanout; int i; Abc_ObjForEachFanout( pNode, pFanout, i ) if ( !Abc_ObjIsCo(pFanout) ) return pFanout; return NULL; } /**Function************************************************************* Synopsis [Checks if the internal node has CO drivers with the same name.] Description [Checks if the internal node can borrow its name from CO fanouts. This is possible if all COs with non-complemented fanin edge pointing to this node have the same name.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode ) { Abc_Obj_t * pFanout, * pFanoutCo; int i; pFanoutCo = NULL; Abc_ObjForEachFanout( pNode, pFanout, i ) { if ( !Abc_ObjIsCo(pFanout) ) continue; if ( Abc_ObjFaninC0(pFanout) ) continue; if ( pFanoutCo == NULL ) { assert( Abc_ObjFaninNum(pFanout) == 1 ); assert( Abc_ObjFanin0(pFanout) == pNode ); pFanoutCo = pFanout; continue; } if ( strcmp( Abc_ObjName(pFanoutCo), Abc_ObjName(pFanout) ) ) // they have diff names return NULL; } return pFanoutCo; } /**Function************************************************************* Synopsis [Fixes the CO driver problem.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFixCoDriverProblem( Abc_Obj_t * pDriver, Abc_Obj_t * pNodeCo, int fDuplicate ) { Abc_Ntk_t * pNtk = pDriver->pNtk; Abc_Obj_t * pDriverNew, * pFanin; int k; if ( fDuplicate && !Abc_ObjIsCi(pDriver) ) { pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 ); Abc_ObjForEachFanin( pDriver, pFanin, k ) Abc_ObjAddFanin( pDriverNew, pFanin ); if ( Abc_ObjFaninC0(pNodeCo) ) { // change polarity of the duplicated driver Abc_NodeComplement( pDriverNew ); Abc_ObjXorFaninC( pNodeCo, 0 ); } } else { // add inverters and buffers when necessary if ( Abc_ObjFaninC0(pNodeCo) ) { pDriverNew = Abc_NtkCreateNodeInv( pNtk, pDriver ); Abc_ObjXorFaninC( pNodeCo, 0 ); } else pDriverNew = Abc_NtkCreateNodeBuf( pNtk, pDriver ); } // update the fanin of the PO node Abc_ObjPatchFanin( pNodeCo, pDriver, pDriverNew ); assert( Abc_ObjFanoutNum(pDriverNew) == 1 ); // remove the old driver if it dangles // (this happens when the duplicated driver had only one complemented fanout) if ( Abc_ObjFanoutNum(pDriver) == 0 ) Abc_NtkDeleteObj( pDriver ); } /**Function************************************************************* Synopsis [Returns 1 if COs of a logic network are simple.] Description [The COs of a logic network are simple under three conditions: (1) The edge from CO to its driver is not complemented. (2) If CI is a driver of a CO, they have the same name.] (3) If two COs share the same driver, they have the same name.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode, * pDriver; int i; assert( Abc_NtkIsLogic(pNtk) ); Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachCo( pNtk, pNode, i ) { // if the driver is complemented, this is an error pDriver = Abc_ObjFanin0(pNode); if ( Abc_ObjFaninC0(pNode) ) return 0; // if the driver is a CI and has different name, this is an error if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) ) return 0; // if the driver is visited for the first time, remember the CO name if ( !Abc_NodeIsTravIdCurrent(pDriver) ) { pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode); Abc_NodeSetTravIdCurrent(pDriver); continue; } // the driver has second CO - if they have different name, this is an error if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names return 0; } return 1; } /**Function************************************************************* Synopsis [Transforms the network to have simple COs.] Description [The COs of a logic network are simple under three conditions: (1) The edge from CO to its driver is not complemented. (2) If CI is a driver of a CO, they have the same name.] (3) If two COs share the same driver, they have the same name. In some cases, such as FPGA mapping, we prevent the increase in delay by duplicating the driver nodes, rather than adding invs/bufs.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkLogicMakeSimpleCos2( Abc_Ntk_t * pNtk, int fDuplicate ) { Abc_Obj_t * pNode, * pDriver; int i, nDupGates = 0; assert( Abc_NtkIsLogic(pNtk) ); Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachCo( pNtk, pNode, i ) { // if the driver is complemented, this is an error pDriver = Abc_ObjFanin0(pNode); if ( Abc_ObjFaninC0(pNode) ) { Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate ); nDupGates++; continue; } // if the driver is a CI and has different name, this is an error if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) ) { Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate ); nDupGates++; continue; } // if the driver is visited for the first time, remember the CO name if ( !Abc_NodeIsTravIdCurrent(pDriver) ) { pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode); Abc_NodeSetTravIdCurrent(pDriver); continue; } // the driver has second CO - if they have different name, this is an error if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names { Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate ); nDupGates++; continue; } } assert( Abc_NtkLogicHasSimpleCos(pNtk) ); return nDupGates; } /**Function************************************************************* Synopsis [Transforms the network to have simple COs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkLogicMakeSimpleCosTest( Abc_Ntk_t * pNtk, int fDuplicate ) { int nObjs = Abc_NtkObjNumMax(pNtk); unsigned * pType = ABC_CALLOC( unsigned, nObjs ); Abc_Obj_t * pNode; int i, Counts[4] = {0}, Consts[2] = {0}, Inputs[2] = {0}; // collect info Abc_NtkForEachCo( pNtk, pNode, i ) { if ( Abc_ObjFaninId0(pNode) == 0 ) Consts[Abc_ObjFaninC0(pNode)]++; if ( Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) Inputs[Abc_ObjFaninC0(pNode)]++; pType[Abc_ObjFaninId0(pNode)] |= (1 << Abc_ObjFaninC0(pNode)); } // count the numbers for ( i = 0; i < nObjs; i++ ) Counts[pType[i]]++; for ( i = 0; i < 4; i++ ) printf( "%d = %d ", i, Counts[i] ); for ( i = 0; i < 2; i++ ) printf( "c%d = %d ", i, Consts[i] ); for ( i = 0; i < 2; i++ ) printf( "i%d = %d ", i, Inputs[i] ); printf( "\n" ); ABC_FREE( pType ); } /**Function************************************************************* Synopsis [Transforms the network to have simple COs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, int fDuplicate ) { int fAddBuffers = 1; Vec_Ptr_t * vDrivers, * vCoTerms; Abc_Obj_t * pNode, * pDriver, * pDriverNew, * pFanin; int i, k, LevelMax, nTotal = 0; assert( Abc_NtkIsLogic(pNtk) ); LevelMax = Abc_NtkLevel(pNtk); // Abc_NtkLogicMakeSimpleCosTest( pNtk, fDuplicate ); // fix constant drivers Abc_NtkForEachCo( pNtk, pNode, i ) { pDriver = Abc_ObjFanin0(pNode); if ( !Abc_NodeIsConst(pDriver) ) continue; pDriverNew = (Abc_ObjFaninC0(pNode) == Abc_NodeIsConst0(pDriver)) ? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk); if ( Abc_ObjFaninC0(pNode) ) Abc_ObjXorFaninC( pNode, 0 ); Abc_ObjPatchFanin( pNode, pDriver, pDriverNew ); if ( Abc_ObjFanoutNum(pDriver) == 0 ) Abc_NtkDeleteObj( pDriver ); } // collect drivers pointed by complemented edges vDrivers = Vec_PtrAlloc( 100 ); Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachCo( pNtk, pNode, i ) { if ( !Abc_ObjFaninC0(pNode) ) continue; pDriver = Abc_ObjFanin0(pNode); if ( Abc_NodeIsTravIdCurrent(pDriver) ) continue; Abc_NodeSetTravIdCurrent(pDriver); Vec_PtrPush( vDrivers, pDriver ); } // fix complemented drivers if ( Vec_PtrSize(vDrivers) > 0 ) { int nDupGates = 0, nDupInvs = 0, nDupChange = 0; Vec_Ptr_t * vFanouts = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Abc_Obj_t *, vDrivers, pDriver, i ) { int fHasDir = 0, fHasInv = 0, fHasOther = 0; Abc_ObjForEachFanout( pDriver, pNode, k ) { if ( !Abc_ObjIsCo(pNode) ) { assert( !Abc_ObjFaninC0(pNode) ); fHasOther = 1; continue; } if ( Abc_ObjFaninC0(pNode) ) fHasInv = 1; else //if ( Abc_ObjFaninC0(pNode) ) fHasDir = 1; } assert( fHasInv ); if ( Abc_ObjIsCi(pDriver) || fHasDir || (fHasOther && Abc_NtkHasMapping(pNtk)) ) // cannot change { // duplicate if critical if ( fDuplicate && Abc_ObjIsNode(pDriver) && Abc_ObjLevel(pDriver) == LevelMax ) { pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 ); Abc_ObjForEachFanin( pDriver, pFanin, k ) Abc_ObjAddFanin( pDriverNew, pFanin ); Abc_NodeComplement( pDriverNew ); nDupGates++; } else // add inverter { pDriverNew = Abc_NtkCreateNodeInv( pNtk, pDriver ); nDupInvs++; } // collect CO fanouts to be redirected to the new node Vec_PtrClear( vFanouts ); Abc_ObjForEachFanout( pDriver, pNode, k ) if ( Abc_ObjIsCo(pNode) && Abc_ObjFaninC0(pNode) ) Vec_PtrPush( vFanouts, pNode ); assert( Vec_PtrSize(vFanouts) > 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pNode, k ) { Abc_ObjXorFaninC( pNode, 0 ); Abc_ObjPatchFanin( pNode, pDriver, pDriverNew ); assert( Abc_ObjIsCi(pDriver) || Abc_ObjFanoutNum(pDriver) > 0 ); } } else // can change { // change polarity of the driver assert( Abc_ObjIsNode(pDriver) ); Abc_NodeComplement( pDriver ); Abc_ObjForEachFanout( pDriver, pNode, k ) { if ( Abc_ObjIsCo(pNode) ) { assert( Abc_ObjFaninC0(pNode) ); Abc_ObjXorFaninC( pNode, 0 ); } else if ( Abc_ObjIsNode(pNode) ) Abc_NodeComplementInput( pNode, pDriver ); else assert( 0 ); } nDupChange++; } } Vec_PtrFree( vFanouts ); // printf( "Resolving inverted CO drivers: Invs = %d. Dups = %d. Changes = %d.\n", // nDupInvs, nDupGates, nDupChange ); nTotal += nDupInvs + nDupGates; } Vec_PtrFree( vDrivers ); // collect COs that needs fixing by adding buffers or duplicating vCoTerms = Vec_PtrAlloc( 100 ); Abc_NtkIncrementTravId( pNtk ); // The following cases should be addressed only if the network is written // into a BLIF file. Otherwise, it is possible to skip them: // (1) if a CO points to a CI with a different name // (2) if an internal node drives more than one CO if ( fAddBuffers ) Abc_NtkForEachCo( pNtk, pNode, i ) { // if the driver is a CI and has different name, this is an error pDriver = Abc_ObjFanin0(pNode); if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) ) { Vec_PtrPush( vCoTerms, pNode ); continue; } // if the driver is visited for the first time, remember the CO name if ( !Abc_NodeIsTravIdCurrent(pDriver) ) { pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode); Abc_NodeSetTravIdCurrent(pDriver); continue; } // the driver has second CO - if they have different name, this is an error if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names { Vec_PtrPush( vCoTerms, pNode ); continue; } } // fix duplication problem if ( Vec_PtrSize(vCoTerms) > 0 ) { int nDupBufs = 0, nDupGates = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vCoTerms, pNode, i ) { pDriver = Abc_ObjFanin0(pNode); // duplicate if critical if ( fDuplicate && Abc_ObjIsNode(pDriver) && (Abc_NtkHasMapping(pNtk) || Abc_ObjLevel(pDriver) == LevelMax) ) { pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 ); Abc_ObjForEachFanin( pDriver, pFanin, k ) Abc_ObjAddFanin( pDriverNew, pFanin ); nDupGates++; } else // add buffer { pDriverNew = Abc_NtkCreateNodeBuf( pNtk, pDriver ); Abc_ObjAssignName( pDriverNew, Abc_ObjName(pDriver), "_buf" ); nDupBufs++; } // swing the PO Abc_ObjPatchFanin( pNode, pDriver, pDriverNew ); assert( Abc_ObjIsCi(pDriver) || Abc_ObjFanoutNum(pDriver) > 0 ); } // printf( "Resolving shared CO drivers: Bufs = %d. Dups = %d.\n", nDupBufs, nDupGates ); nTotal += nDupBufs + nDupGates; } Vec_PtrFree( vCoTerms ); return nTotal; } /**Function************************************************************* Synopsis [Inserts a new node in the order by levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode ) { Abc_Obj_t * pNode1, * pNode2; int i; if ( Vec_PtrPushUnique(p, pNode) ) return; // find the p of the node for ( i = p->nSize-1; i > 0; i-- ) { pNode1 = (Abc_Obj_t *)p->pArray[i ]; pNode2 = (Abc_Obj_t *)p->pArray[i-1]; if ( Abc_ObjRegular(pNode1)->Level <= Abc_ObjRegular(pNode2)->Level ) break; p->pArray[i ] = pNode2; p->pArray[i-1] = pNode1; } } /**Function************************************************************* Synopsis [Returns 1 if the node is the root of EXOR/NEXOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeIsExorType( Abc_Obj_t * pNode ) { Abc_Obj_t * pNode0, * pNode1; // check that the node is regular assert( !Abc_ObjIsComplement(pNode) ); // if the node is not AND, this is not EXOR if ( !Abc_AigNodeIsAnd(pNode) ) return 0; // if the children are not complemented, this is not EXOR if ( !Abc_ObjFaninC0(pNode) || !Abc_ObjFaninC1(pNode) ) return 0; // get children pNode0 = Abc_ObjFanin0(pNode); pNode1 = Abc_ObjFanin1(pNode); // if the children are not ANDs, this is not EXOR if ( Abc_ObjFaninNum(pNode0) != 2 || Abc_ObjFaninNum(pNode1) != 2 ) return 0; // this is AIG, which means the fanins should be ordered assert( Abc_ObjFaninId0(pNode0) != Abc_ObjFaninId1(pNode1) || Abc_ObjFaninId0(pNode1) != Abc_ObjFaninId1(pNode0) ); // if grand children are not the same, this is not EXOR if ( Abc_ObjFaninId0(pNode0) != Abc_ObjFaninId0(pNode1) || Abc_ObjFaninId1(pNode0) != Abc_ObjFaninId1(pNode1) ) return 0; // finally, if the complemented edges are matched, this is not EXOR if ( Abc_ObjFaninC0(pNode0) == Abc_ObjFaninC0(pNode1) || Abc_ObjFaninC1(pNode0) == Abc_ObjFaninC1(pNode1) ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeIsMuxType( Abc_Obj_t * pNode ) { Abc_Obj_t * pNode0, * pNode1; // check that the node is regular assert( !Abc_ObjIsComplement(pNode) ); // if the node is not AND, this is not MUX if ( !Abc_AigNodeIsAnd(pNode) ) return 0; // if the children are not complemented, this is not MUX if ( !Abc_ObjFaninC0(pNode) || !Abc_ObjFaninC1(pNode) ) return 0; // get children pNode0 = Abc_ObjFanin0(pNode); pNode1 = Abc_ObjFanin1(pNode); // if the children are not ANDs, this is not MUX if ( !Abc_AigNodeIsAnd(pNode0) || !Abc_AigNodeIsAnd(pNode1) ) return 0; // otherwise the node is MUX iff it has a pair of equal grandchildren with opposite polarity return (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC0(pNode1))) || (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC1(pNode1))) || (Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC0(pNode1))) || (Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC1(pNode1))); } /**Function************************************************************* Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCountMuxes( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i; int Counter = 0; Abc_NtkForEachNode( pNtk, pNode, i ) Counter += Abc_NodeIsMuxType( pNode ); return Counter; } /**Function************************************************************* Synopsis [Returns 1 if the node is the control type of the MUX.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeIsMuxControlType( Abc_Obj_t * pNode ) { Abc_Obj_t * pNode0, * pNode1; // check that the node is regular assert( !Abc_ObjIsComplement(pNode) ); // skip the node that do not have two fanouts if ( Abc_ObjFanoutNum(pNode) != 2 ) return 0; // get the fanouts pNode0 = Abc_ObjFanout( pNode, 0 ); pNode1 = Abc_ObjFanout( pNode, 1 ); // if they have more than one fanout, we are not interested if ( Abc_ObjFanoutNum(pNode0) != 1 || Abc_ObjFanoutNum(pNode1) != 1 ) return 0; // if the fanouts have the same fanout, this is MUX or EXOR (or a redundant gate (CA)(CB)) return Abc_ObjFanout0(pNode0) == Abc_ObjFanout0(pNode1); } /**Function************************************************************* Synopsis [Recognizes what nodes are control and data inputs of a MUX.] Description [If the node is a MUX, returns the control variable C. Assigns nodes T and E to be the then and else variables of the MUX. Node C is never complemented. Nodes T and E can be complemented. This function also recognizes EXOR/NEXOR gates as MUXes.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE ) { Abc_Obj_t * pNode0, * pNode1; assert( !Abc_ObjIsComplement(pNode) ); assert( Abc_NodeIsMuxType(pNode) ); // get children pNode0 = Abc_ObjFanin0(pNode); pNode1 = Abc_ObjFanin1(pNode); // find the control variable // if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) if ( Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC0(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p1) ) if ( Abc_ObjFaninC0(pNode0) ) { // pNode2->p1 is positive phase of C *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); return Abc_ObjChild0(pNode1);//pNode2->p1; } else { // pNode1->p1 is positive phase of C *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); return Abc_ObjChild0(pNode0);//pNode1->p1; } } // else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) else if ( Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC1(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p1) ) if ( Abc_ObjFaninC0(pNode0) ) { // pNode2->p2 is positive phase of C *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); return Abc_ObjChild1(pNode1);//pNode2->p2; } else { // pNode1->p1 is positive phase of C *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); return Abc_ObjChild0(pNode0);//pNode1->p1; } } // else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) else if ( Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC0(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p2) ) if ( Abc_ObjFaninC1(pNode0) ) { // pNode2->p1 is positive phase of C *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); return Abc_ObjChild0(pNode1);//pNode2->p1; } else { // pNode1->p2 is positive phase of C *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); return Abc_ObjChild1(pNode0);//pNode1->p2; } } // else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) else if ( Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC1(pNode1)) ) { // if ( Fraig_IsComplement(pNode1->p2) ) if ( Abc_ObjFaninC1(pNode0) ) { // pNode2->p2 is positive phase of C *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); return Abc_ObjChild1(pNode1);//pNode2->p2; } else { // pNode1->p2 is positive phase of C *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); return Abc_ObjChild1(pNode0);//pNode1->p2; } } assert( 0 ); // this is not MUX return NULL; } /**Function************************************************************* Synopsis [Prepares two network for a two-argument command similar to "verify".] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc, Abc_Ntk_t ** ppNtk1, Abc_Ntk_t ** ppNtk2, int * pfDelete1, int * pfDelete2, int fCheck ) { FILE * pFile; Abc_Ntk_t * pNtk1, * pNtk2, * pNtkTemp; int util_optind = 0; *pfDelete1 = 0; *pfDelete2 = 0; if ( argc == util_optind ) { // use the spec if ( pNtk == NULL ) { fprintf( pErr, "Empty current network.\n" ); return 0; } if ( pNtk->pSpec == NULL ) { fprintf( pErr, "The external spec is not given.\n" ); return 0; } pFile = fopen( pNtk->pSpec, "r" ); if ( pFile == NULL ) { fprintf( pErr, "Cannot open the external spec file \"%s\".\n", pNtk->pSpec ); return 0; } else fclose( pFile ); pNtk1 = Abc_NtkDup(pNtk); pNtk2 = Io_Read( pNtk->pSpec, Io_ReadFileType(pNtk->pSpec), fCheck, 0 ); if ( pNtk2 == NULL ) return 0; *pfDelete1 = 1; *pfDelete2 = 1; } else if ( argc == util_optind + 1 ) { if ( pNtk == NULL ) { fprintf( pErr, "Empty current network.\n" ); return 0; } pNtk1 = Abc_NtkDup(pNtk); pNtk2 = Io_Read( argv[util_optind], Io_ReadFileType(argv[util_optind]), fCheck, 0 ); if ( pNtk2 == NULL ) return 0; *pfDelete1 = 1; *pfDelete2 = 1; } else if ( argc == util_optind + 2 ) { pNtk1 = Io_Read( argv[util_optind], Io_ReadFileType(argv[util_optind]), fCheck, 0 ); if ( pNtk1 == NULL ) return 0; pNtk2 = Io_Read( argv[util_optind+1], Io_ReadFileType(argv[util_optind+1]), fCheck, 0 ); if ( pNtk2 == NULL ) { Abc_NtkDelete( pNtk1 ); return 0; } *pfDelete1 = 1; *pfDelete2 = 1; } else { fprintf( pErr, "Wrong number of arguments.\n" ); return 0; } // make sure the networks are strashed if ( !Abc_NtkIsStrash(pNtk1) ) { pNtkTemp = Abc_NtkStrash( pNtk1, 0, 1, 0 ); if ( *pfDelete1 ) Abc_NtkDelete( pNtk1 ); pNtk1 = pNtkTemp; *pfDelete1 = 1; } if ( !Abc_NtkIsStrash(pNtk2) ) { pNtkTemp = Abc_NtkStrash( pNtk2, 0, 1, 0 ); if ( *pfDelete2 ) Abc_NtkDelete( pNtk2 ); pNtk2 = pNtkTemp; *pfDelete2 = 1; } *ppNtk1 = pNtk1; *ppNtk2 = pNtk2; return 1; } /**Function************************************************************* Synopsis [Returns 1 if it is an AIG with choice nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanin; int i; Vec_PtrClear(vNodes); Abc_ObjForEachFanin( pNode, pFanin, i ) Vec_PtrPush( vNodes, pFanin ); } /**Function************************************************************* Synopsis [Returns 1 if it is an AIG with choice nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeCollectFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Abc_Obj_t * pFanout; int i; Vec_PtrClear(vNodes); Abc_ObjForEachFanout( pNode, pFanout, i ) Vec_PtrPush( vNodes, pFanout ); } /**Function************************************************************* Synopsis [Collects all latches in the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkCollectLatches( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vLatches; Abc_Obj_t * pObj; int i; vLatches = Vec_PtrAlloc( 10 ); Abc_NtkForEachObj( pNtk, pObj, i ) Vec_PtrPush( vLatches, pObj ); return vLatches; } /**Function************************************************************* Synopsis [Procedure used for sorting the nodes in increasing order of levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCompareLevelsIncrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) { int Diff = Abc_ObjRegular(*pp1)->Level - Abc_ObjRegular(*pp2)->Level; if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; Diff = Abc_ObjRegular(*pp1)->Id - Abc_ObjRegular(*pp2)->Id; if ( Diff < 0 ) return -1; if ( Diff > 0 ) return 1; return 0; } /**Function************************************************************* Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeCompareLevelsDecrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) { int Diff = Abc_ObjRegular(*pp1)->Level - Abc_ObjRegular(*pp2)->Level; if ( Diff > 0 ) return -1; if ( Diff < 0 ) return 1; Diff = Abc_ObjRegular(*pp1)->Id - Abc_ObjRegular(*pp2)->Id; if ( Diff > 0 ) return -1; if ( Diff < 0 ) return 1; return 0; } /**Function************************************************************* Synopsis [Creates the array of fanout counters.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkFanoutCounts( Abc_Ntk_t * pNtk ) { Vec_Int_t * vFanNums; Abc_Obj_t * pObj; int i; vFanNums = Vec_IntAlloc( 0 ); Vec_IntFill( vFanNums, Abc_NtkObjNumMax(pNtk), -1 ); Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsCi(pObj) || Abc_ObjIsNode(pObj) ) Vec_IntWriteEntry( vFanNums, i, Abc_ObjFanoutNum(pObj) ); return vFanNums; } /**Function************************************************************* Synopsis [Collects all objects into one array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pNode; int i; vNodes = Vec_PtrAlloc( 100 ); Abc_NtkForEachObj( pNtk, pNode, i ) Vec_PtrPush( vNodes, pNode ); return vNodes; } /**Function************************************************************* Synopsis [Returns the array of CI IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkGetCiIds( Abc_Ntk_t * pNtk ) { Vec_Int_t * vCiIds; Abc_Obj_t * pObj; int i; vCiIds = Vec_IntAlloc( Abc_NtkCiNum(pNtk) ); Abc_NtkForEachCi( pNtk, pObj, i ) Vec_IntPush( vCiIds, pObj->Id ); return vCiIds; } /**Function************************************************************* Synopsis [Puts the nodes into the DFS order and reassign their IDs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkReassignIds( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Vec_Ptr_t * vObjsNew; Abc_Obj_t * pNode, * pTemp, * pConst1; int i, k; assert( Abc_NtkIsStrash(pNtk) ); //printf( "Total = %d. Current = %d.\n", Abc_NtkObjNumMax(pNtk), Abc_NtkObjNum(pNtk) ); // start the array of objects with new IDs vObjsNew = Vec_PtrAlloc( pNtk->nObjs ); // put constant node first pConst1 = Abc_AigConst1(pNtk); assert( pConst1->Id == 0 ); Vec_PtrPush( vObjsNew, pConst1 ); // put PI nodes next Abc_NtkForEachPi( pNtk, pNode, i ) { pNode->Id = Vec_PtrSize( vObjsNew ); Vec_PtrPush( vObjsNew, pNode ); } // put PO nodes next Abc_NtkForEachPo( pNtk, pNode, i ) { pNode->Id = Vec_PtrSize( vObjsNew ); Vec_PtrPush( vObjsNew, pNode ); } // put latches and their inputs/outputs next Abc_NtkForEachBox( pNtk, pNode, i ) { pNode->Id = Vec_PtrSize( vObjsNew ); Vec_PtrPush( vObjsNew, pNode ); Abc_ObjForEachFanin( pNode, pTemp, k ) { pTemp->Id = Vec_PtrSize( vObjsNew ); Vec_PtrPush( vObjsNew, pTemp ); } Abc_ObjForEachFanout( pNode, pTemp, k ) { pTemp->Id = Vec_PtrSize( vObjsNew ); Vec_PtrPush( vObjsNew, pTemp ); } } // finally, internal nodes in the DFS order vNodes = Abc_AigDfs( pNtk, 1, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( pNode == pConst1 ) continue; pNode->Id = Vec_PtrSize( vObjsNew ); Vec_PtrPush( vObjsNew, pNode ); } Vec_PtrFree( vNodes ); assert( Vec_PtrSize(vObjsNew) == pNtk->nObjs ); // update the fanin/fanout arrays Abc_NtkForEachObj( pNtk, pNode, i ) { Abc_ObjForEachFanin( pNode, pTemp, k ) pNode->vFanins.pArray[k] = pTemp->Id; Abc_ObjForEachFanout( pNode, pTemp, k ) pNode->vFanouts.pArray[k] = pTemp->Id; } // replace the array of objs Vec_PtrFree( pNtk->vObjs ); pNtk->vObjs = vObjsNew; // rehash the AIG Abc_AigRehash( (Abc_Aig_t *)pNtk->pManFunc ); // update the name manager!!! } /**Function************************************************************* Synopsis [Detect cases when non-trivial FF matching is possible.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDetectMatching( Abc_Ntk_t * pNtk ) { /* Abc_Obj_t * pLatch, * pFanin; int i, nTFFs, nJKFFs; nTFFs = nJKFFs = 0; Abc_NtkForEachLatch( pNtk, pLatch, i ) { pFanin = Abc_ObjFanin0(pLatch); if ( Abc_ObjFaninNum(pFanin) != 2 ) continue; if ( Abc_NodeIsExorType(pLatch) ) { if ( Abc_ObjFanin0(Abc_ObjFanin0(pFanin)) == pLatch || Abc_ObjFanin1(Abc_ObjFanin0(pFanin)) == pLatch ) nTFFs++; } if ( Abc_ObjFaninNum( Abc_ObjFanin0(pFanin) ) != 2 || Abc_ObjFaninNum( Abc_ObjFanin1(pFanin) ) != 2 ) continue; if ( (Abc_ObjFanin0(Abc_ObjFanin0(pFanin)) == pLatch || Abc_ObjFanin1(Abc_ObjFanin0(pFanin)) == pLatch) && (Abc_ObjFanin0(Abc_ObjFanin1(pFanin)) == pLatch || Abc_ObjFanin1(Abc_ObjFanin1(pFanin)) == pLatch) ) { nJKFFs++; } } printf( "D = %6d. T = %6d. JK = %6d. (%6.2f %%)\n", Abc_NtkLatchNum(pNtk), nTFFs, nJKFFs, 100.0 * nJKFFs / Abc_NtkLatchNum(pNtk) ); */ } /**Function************************************************************* Synopsis [Compares the pointers.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjPointerCompare( void ** pp1, void ** pp2 ) { if ( *pp1 < *pp2 ) return -1; if ( *pp1 > *pp2 ) return 1; return 0; } /**Function************************************************************* Synopsis [Adjusts the copy pointers.] Description [This procedure assumes that the network was transformed into another network, which was in turn transformed into yet another network. It makes the pCopy pointers of the original network point to the objects of the yet another network.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTransferCopy( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_ObjIsNet(pObj) ) pObj->pCopy = pObj->pCopy? Abc_ObjCopyCond(pObj->pCopy) : NULL; } /**Function************************************************************* Synopsis [Increaments the cut counter.] Description [Returns 1 if it becomes equal to the ref counter.] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_ObjCrossCutInc( Abc_Obj_t * pObj ) { // pObj->pCopy = (void *)(((int)pObj->pCopy)++); int Value = (int)(ABC_PTRINT_T)pObj->pCopy; pObj->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)(Value + 1); return (int)(ABC_PTRINT_T)pObj->pCopy == Abc_ObjFanoutNum(pObj); } /**Function************************************************************* Synopsis [Computes cross-cut of the circuit.] Description [Returns 1 if it is the last visit to the node.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCrossCut_rec( Abc_Obj_t * pObj, int * pnCutSize, int * pnCutSizeMax ) { Abc_Obj_t * pFanin; int i, nDecrem = 0; int fReverse = 0; if ( Abc_ObjIsCi(pObj) ) return 0; // if visited, increment visit counter if ( Abc_NodeIsTravIdCurrent( pObj ) ) return Abc_ObjCrossCutInc( pObj ); Abc_NodeSetTravIdCurrent( pObj ); // visit the fanins if ( !Abc_ObjIsCi(pObj) ) { if ( fReverse ) { Abc_ObjForEachFanin( pObj, pFanin, i ) { pFanin = Abc_ObjFanin( pObj, Abc_ObjFaninNum(pObj) - 1 - i ); nDecrem += Abc_NtkCrossCut_rec( pFanin, pnCutSize, pnCutSizeMax ); } } else { Abc_ObjForEachFanin( pObj, pFanin, i ) nDecrem += Abc_NtkCrossCut_rec( pFanin, pnCutSize, pnCutSizeMax ); } } // count the node (*pnCutSize)++; if ( *pnCutSizeMax < *pnCutSize ) *pnCutSizeMax = *pnCutSize; (*pnCutSize) -= nDecrem; return Abc_ObjCrossCutInc( pObj ); } /**Function************************************************************* Synopsis [Computes cross-cut of the circuit.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCrossCut( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int nCutSize = 0, nCutSizeMax = 0; int i; Abc_NtkCleanCopy( pNtk ); Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachCo( pNtk, pObj, i ) { Abc_NtkCrossCut_rec( pObj, &nCutSize, &nCutSizeMax ); nCutSize--; } assert( nCutSize == 0 ); printf( "Max cross cut size = %6d. Ratio = %6.2f %%\n", nCutSizeMax, 100.0 * nCutSizeMax/Abc_NtkObjNum(pNtk) ); return nCutSizeMax; } /**Function************************************************************* Synopsis [Prints all 3-var functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrint256() { FILE * pFile; unsigned i; pFile = fopen( "4varfs.txt", "w" ); for ( i = 1; i < (1<<16)-1; i++ ) { fprintf( pFile, "read_truth " ); Extra_PrintBinary( pFile, &i, 16 ); fprintf( pFile, "; clp; st; w 1.blif; map; cec 1.blif\n" ); } fclose( pFile ); } static int * pSupps; /**Function************************************************************* Synopsis [Compares the supergates by their level.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCompareConesCompare( int * pNum1, int * pNum2 ) { if ( pSupps[*pNum1] > pSupps[*pNum2] ) return -1; if ( pSupps[*pNum1] < pSupps[*pNum2] ) return 1; return 0; } /**Function************************************************************* Synopsis [Analyze choice node support.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCompareCones( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vSupp, * vNodes, * vReverse; Abc_Obj_t * pObj, * pTemp; int Iter, i, k, Counter, CounterCos, CounterCosNew; int * pPerms; // sort COs by support size pPerms = ABC_ALLOC( int, Abc_NtkCoNum(pNtk) ); pSupps = ABC_ALLOC( int, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) { pPerms[i] = i; vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); pSupps[i] = Vec_PtrSize(vSupp); Vec_PtrFree( vSupp ); } qsort( (void *)pPerms, (size_t)Abc_NtkCoNum(pNtk), sizeof(int), (int (*)(const void *, const void *)) Abc_NtkCompareConesCompare ); // consider COs in this order Iter = 0; Abc_NtkForEachCo( pNtk, pObj, i ) { pObj = Abc_NtkCo( pNtk, pPerms[i] ); if ( pObj->fMarkA ) continue; Iter++; vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 ); vReverse = Abc_NtkDfsReverseNodesContained( pNtk, (Abc_Obj_t **)Vec_PtrArray(vSupp), Vec_PtrSize(vSupp) ); // count the number of nodes in the reverse cone Counter = 0; for ( k = 1; k < Vec_PtrSize(vReverse) - 1; k++ ) for ( pTemp = (Abc_Obj_t *)Vec_PtrEntry(vReverse, k); pTemp; pTemp = (Abc_Obj_t *)pTemp->pCopy ) Counter++; CounterCos = CounterCosNew = 0; for ( pTemp = (Abc_Obj_t *)Vec_PtrEntryLast(vReverse); pTemp; pTemp = (Abc_Obj_t *)pTemp->pCopy ) { assert( Abc_ObjIsCo(pTemp) ); CounterCos++; if ( pTemp->fMarkA == 0 ) CounterCosNew++; pTemp->fMarkA = 1; } // print statistics printf( "%4d CO %5d : Supp = %5d. Lev = %3d. Cone = %5d. Rev = %5d. COs = %3d (%3d).\n", Iter, pPerms[i], Vec_PtrSize(vSupp), Abc_ObjLevel(Abc_ObjFanin0(pObj)), Vec_PtrSize(vNodes), Counter, CounterCos, CounterCosNew ); if ( Vec_PtrSize(vSupp) < 10 ) { // free arrays Vec_PtrFree( vSupp ); Vec_PtrFree( vNodes ); Vec_PtrFree( vReverse ); break; } // free arrays Vec_PtrFree( vSupp ); Vec_PtrFree( vNodes ); Vec_PtrFree( vReverse ); } Abc_NtkForEachCo( pNtk, pObj, i ) pObj->fMarkA = 0; ABC_FREE( pPerms ); ABC_FREE( pSupps ); } /**Function************************************************************* Synopsis [Analyze choice node support.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCompareSupports( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vSupp; Abc_Obj_t * pObj, * pTemp; int i, nNodesOld; assert( Abc_NtkIsStrash(pNtk) ); Abc_AigForEachAnd( pNtk, pObj, i ) { if ( !Abc_AigNodeIsChoice(pObj) ) continue; vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); nNodesOld = Vec_PtrSize(vSupp); Vec_PtrFree( vSupp ); for ( pTemp = (Abc_Obj_t *)pObj->pData; pTemp; pTemp = (Abc_Obj_t *)pTemp->pData ) { vSupp = Abc_NtkNodeSupport( pNtk, &pTemp, 1 ); if ( nNodesOld != Vec_PtrSize(vSupp) ) printf( "Choice orig = %3d Choice new = %3d\n", nNodesOld, Vec_PtrSize(vSupp) ); Vec_PtrFree( vSupp ); } } } /**Function************************************************************* Synopsis [Complements the constraint outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkInvertConstraints( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; if ( Abc_NtkConstrNum(pNtk) == 0 ) return; Abc_NtkForEachPo( pNtk, pObj, i ) { if ( i >= Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk) ) Abc_ObjXorFaninC( pObj, 0 ); } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintCiLevels( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachCi( pNtk, pObj, i ) printf( "%c=%d ", 'a'+i, pObj->Level ); printf( "\n" ); } /**Function************************************************************* Synopsis [Returns 1 if all other fanouts of pFanin are below pNode.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkAddBuffsEval( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) { Abc_Obj_t * pFanout; int i; Abc_ObjForEachFanout( pFanin, pFanout, i ) if ( pFanout != pNode && pFanout->Level >= pNode->Level ) return 0; return 1; } /**Function************************************************************* Synopsis [Returns 1 if there exist a fanout of pFanin higher than pNode.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkAddBuffsEval2( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) { Abc_Obj_t * pFanout; int i; Abc_ObjForEachFanout( pFanin, pFanout, i ) if ( pFanout != pNode && pFanout->Level > pNode->Level ) return 1; return 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkAddBuffsOne( Vec_Ptr_t * vBuffs, Abc_Obj_t * pFanin, int Level, int nLevelMax ) { Abc_Obj_t * pBuffer; assert( Level - 1 >= Abc_ObjLevel(pFanin) ); pBuffer = (Abc_Obj_t *)Vec_PtrEntry( vBuffs, Abc_ObjId(pFanin) * nLevelMax + Level ); if ( pBuffer == NULL ) { if ( Level - 1 == Abc_ObjLevel(pFanin) ) pBuffer = pFanin; else pBuffer = Abc_NtkAddBuffsOne( vBuffs, pFanin, Level - 1, nLevelMax ); pBuffer = Abc_NtkCreateNodeBuf( Abc_ObjNtk(pFanin), pBuffer ); Vec_PtrWriteEntry( vBuffs, Abc_ObjId(pFanin) * nLevelMax + Level, pBuffer ); } return pBuffer; } Abc_Ntk_t * Abc_NtkAddBuffsInt( Abc_Ntk_t * pNtkInit, int fReverse, int nImprove, int fVerbose ) { Vec_Ptr_t * vBuffs; Abc_Ntk_t * pNtk = Abc_NtkDup( pNtkInit ); Abc_Obj_t * pObj, * pFanin, * pBuffer; int i, k, Iter, nLevelMax = Abc_NtkLevel( pNtk ); Abc_NtkForEachCo( pNtk, pObj, i ) pObj->Level = nLevelMax + 1; if ( fReverse ) { Vec_Ptr_t * vNodes = Abc_NtkDfs( pNtk, 1 ); assert( nLevelMax < (1<<18) ); Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pObj, i ) { pObj->Level = (1<<18); Abc_ObjForEachFanout( pObj, pFanin, k ) pObj->Level = Abc_MinInt( pFanin->Level - 1, pObj->Level ); assert( pObj->Level > 0 ); } Abc_NtkForEachCi( pNtk, pObj, i ) pObj->Level = 0; // move the nodes down one step at a time for ( Iter = 0; Iter < nImprove; Iter++ ) { int Counter = 0, TotalGain = 0; Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { int CountGain = -1; assert( pObj->Level > 0 ); Abc_ObjForEachFanin( pObj, pFanin, k ) { assert( pFanin->Level < pObj->Level ); if ( pFanin->Level + 1 == pObj->Level ) break; } if ( k < Abc_ObjFaninNum(pObj) ) // cannot move continue; Abc_ObjForEachFanin( pObj, pFanin, k ) CountGain += Abc_NtkAddBuffsEval( pObj, pFanin ); if ( CountGain >= 0 ) // can move { pObj->Level--; Counter++; TotalGain += CountGain; } } if ( fVerbose ) printf( "Shifted %5d nodes down with total gain %5d.\n", Counter, TotalGain ); if ( Counter == 0 ) break; } Vec_PtrFree( vNodes ); } else { // move the nodes up one step at a time Vec_Ptr_t * vNodes = Abc_NtkDfs( pNtk, 1 ); for ( Iter = 0; Iter < nImprove; Iter++ ) { int Counter = 0, TotalGain = 0; Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pObj, i ) { int CountGain = 1; assert( pObj->Level <= (unsigned)nLevelMax ); Abc_ObjForEachFanout( pObj, pFanin, k ) { assert( pFanin->Level > pObj->Level ); if ( pFanin->Level == pObj->Level + 1 ) break; } if ( k < Abc_ObjFanoutNum(pObj) ) // cannot move continue; Abc_ObjForEachFanin( pObj, pFanin, k ) CountGain -= !Abc_NtkAddBuffsEval2( pObj, pFanin ); if ( CountGain >= 0 ) // can move { pObj->Level++; Counter++; TotalGain += CountGain; } } if ( fVerbose ) printf( "Shifted %5d nodes up with total gain %5d.\n", Counter, TotalGain ); if ( Counter == 0 ) break; } Vec_PtrFree( vNodes ); } vBuffs = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) * (nLevelMax + 1) ); Abc_NtkForEachObj( pNtk, pObj, i ) { if ( i == Vec_PtrSize(vBuffs) / (nLevelMax + 1) ) break; if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsCo(pObj) ) continue; Abc_ObjForEachFanin( pObj, pFanin, k ) { assert( Abc_ObjLevel(pObj) - 1 >= Abc_ObjLevel(pFanin) ); if ( Abc_ObjLevel(pObj) - 1 == Abc_ObjLevel(pFanin) ) continue; pBuffer = Abc_NtkAddBuffsOne( vBuffs, pFanin, Abc_ObjLevel(pObj) - 1, nLevelMax ); Abc_ObjPatchFanin( pObj, pFanin, pBuffer ); } } Vec_PtrFree( vBuffs ); Abc_NtkForEachCo( pNtk, pObj, i ) pObj->Level = 0; return pNtk; } Abc_Ntk_t * Abc_NtkAddBuffs( Abc_Ntk_t * pNtkInit, int fDirect, int fReverse, int nImprove, int fVerbose ) { Abc_Ntk_t * pNtkD, * pNtkR; if ( fDirect ) return Abc_NtkAddBuffsInt( pNtkInit, 0, nImprove, fVerbose ); if ( fReverse ) return Abc_NtkAddBuffsInt( pNtkInit, 1, nImprove, fVerbose ); pNtkD = Abc_NtkAddBuffsInt( pNtkInit, 0, nImprove, fVerbose ); pNtkR = Abc_NtkAddBuffsInt( pNtkInit, 1, nImprove, fVerbose ); if ( Abc_NtkNodeNum(pNtkD) < Abc_NtkNodeNum(pNtkR) ) { Abc_NtkDelete( pNtkR ); return pNtkD; } else { Abc_NtkDelete( pNtkD ); return pNtkR; } } /**Function************************************************************* Synopsis [Computes max delay using log(n) delay model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Abc_NtkComputeDelay( Abc_Ntk_t * pNtk ) { static double GateDelays[20] = { 1.00, 1.00, 2.00, 2.58, 3.00, 3.32, 3.58, 3.81, 4.00, 4.17, 4.32, 4.46, 4.58, 4.70, 4.81, 4.91, 5.00, 5.09, 5.17, 5.25 }; Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pFanin; float DelayMax, Delays[15] = {0}; int nFaninMax, i, k; // calculate relative gate delays nFaninMax = Abc_NtkGetFaninMax( pNtk ); assert( nFaninMax > 1 && nFaninMax < 15 ); for ( i = 0; i <= nFaninMax; i++ ) Delays[i] = GateDelays[i]/GateDelays[nFaninMax]; // set max CI delay Abc_NtkForEachCi( pNtk, pObj, i ) pObj->dTemp = 0.0; // compute delays for each node vNodes = Abc_NtkDfs( pNtk, 1 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { pObj->dTemp = 0.0; Abc_ObjForEachFanin( pObj, pFanin, k ) pObj->dTemp = Abc_MaxFloat( pObj->dTemp, pFanin->dTemp ); pObj->dTemp += Delays[Abc_ObjFaninNum(pObj)]; } Vec_PtrFree( vNodes ); DelayMax = 0.0; // find max CO delay Abc_NtkForEachCo( pNtk, pObj, i ) DelayMax = Abc_MaxFloat( DelayMax, Abc_ObjFanin0(pObj)->dTemp ); return DelayMax; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeSopToCubes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew, int fXor ) { Abc_Obj_t * pNodeOr, * pNodeNew, * pFanin; char * pCube, * pSop = (char *)pNodeOld->pData; int v, Value, nVars = Abc_ObjFaninNum(pNodeOld), nFanins; // create the root node if ( Abc_SopGetCubeNum(pSop) < 2 ) { pNodeNew = Abc_NtkDupObj( pNtkNew, pNodeOld, 0 ); Abc_ObjForEachFanin( pNodeOld, pFanin, v ) Abc_ObjAddFanin( pNodeNew, pFanin->pCopy ); assert( pNodeOld->pCopy == pNodeNew ); return; } // add the OR gate pNodeOr = Abc_NtkCreateNode( pNtkNew ); if ( fXor ) pNodeOr->pData = Abc_SopCreateXorSpecial( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_SopGetCubeNum(pSop) ); else pNodeOr->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_SopGetCubeNum(pSop), NULL ); // check the logic function of the node Abc_SopForEachCube( pSop, nVars, pCube ) { nFanins = 0; Abc_CubeForEachVar( pCube, Value, v ) if ( Value == '0' || Value == '1' ) nFanins++; if ( nFanins == 0 ) // const1 cube in ESOP { pNodeNew = Abc_NtkCreateNodeConst1( pNtkNew ); Abc_ObjAddFanin( pNodeOr, pNodeNew ); continue; } assert( nFanins > 0 ); // create node pNodeNew = Abc_NtkCreateNode( pNtkNew ); pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, nFanins, NULL ); nFanins = 0; Abc_CubeForEachVar( pCube, Value, v ) { if ( Value != '0' && Value != '1' ) continue; Abc_ObjAddFanin( pNodeNew, Abc_ObjFanin(pNodeOld, v)->pCopy ); if ( Value == '0' ) Abc_SopComplementVar( (char *)pNodeNew->pData, nFanins ); nFanins++; } Abc_ObjAddFanin( pNodeOr, pNodeNew ); } // check the complement if ( Abc_SopIsComplement(pSop) ) Abc_SopComplement( (char *)pNodeOr->pData ); // mark the old node with the new one assert( pNodeOld->pCopy == NULL ); pNodeOld->pCopy = pNodeOr; } Abc_Ntk_t * Abc_NtkSopToCubes( Abc_Ntk_t * pNtk, int fXor ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pNode; Vec_Ptr_t * vNodes; int i; assert( Abc_NtkIsSopLogic(pNtk) ); Abc_NtkCleanCopy( pNtk ); pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); // perform conversion in the topological order vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) Abc_NodeSopToCubes( pNode, pNtkNew, fXor ); Vec_PtrFree( vNodes ); // make sure everything is okay Abc_NtkFinalize( pNtk, pNtkNew ); if ( !Abc_NtkCheck( pNtkNew ) ) { printf( "Abc_NtkSopToCubes: The network check has failed.\n" ); Abc_NtkDelete( pNtkNew ); return NULL; } return pNtkNew; } /**Function************************************************************* Synopsis [Creates precomputed reverse topological order for each node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline int Abc_NtkTopoHasBeg( Abc_Obj_t * p ) { return Vec_IntEntry(p->pNtk->vTopo, 2*Abc_ObjId(p) ); } static inline int Abc_NtkTopoHasEnd( Abc_Obj_t * p ) { return Vec_IntEntry(p->pNtk->vTopo, 2*Abc_ObjId(p)+1); } static inline void Abc_NtkTopoSetBeg( Abc_Obj_t * p ) { Vec_IntWriteEntry(p->pNtk->vTopo, 2*Abc_ObjId(p) , Vec_IntSize(p->pNtk->vTopo)); } static inline void Abc_NtkTopoSetEnd( Abc_Obj_t * p ) { Vec_IntWriteEntry(p->pNtk->vTopo, 2*Abc_ObjId(p)+1, Vec_IntSize(p->pNtk->vTopo)); } void Abc_NtkReverseTopoOrder_rec( Abc_Obj_t * pObj, int fThisIsPivot ) { Abc_Obj_t * pNext, * pPivot = NULL; int i; if ( Abc_NodeIsTravIdCurrent( pObj ) ) return; Abc_NodeSetTravIdCurrent( pObj ); if ( Abc_ObjIsPo(pObj) ) { Vec_IntPush( pObj->pNtk->vTopo, Abc_ObjId(pObj) ); return; } assert( Abc_ObjIsNode(pObj) ); // mark begining if ( fThisIsPivot ) Abc_NtkTopoSetBeg( pObj ); // find fanout without topo Abc_ObjForEachFanout( pObj, pNext, i ) if ( !Abc_NtkTopoHasBeg(pNext) ) { assert( !Abc_NtkTopoHasEnd(pNext) ); Abc_NtkReverseTopoOrder_rec( pNext, 1 ); pPivot = pNext; break; } Abc_ObjForEachFanout( pObj, pNext, i ) if ( pNext != pPivot ) Abc_NtkReverseTopoOrder_rec( pNext, 0 ); // mark end if ( fThisIsPivot ) Abc_NtkTopoSetEnd( pObj ); // save current node Vec_IntPush( pObj->pNtk->vTopo, Abc_ObjId(pObj) ); } void Abc_NtkReverseTopoOrder( Abc_Ntk_t * p ) { Abc_Obj_t * pObj; int i; assert( p->vTopo == NULL ); p->vTopo = Vec_IntAlloc( 10 * Abc_NtkObjNumMax(p) ); Vec_IntFill( p->vTopo, 2 * Abc_NtkObjNumMax(p), 0 ); Abc_NtkForEachNode( p, pObj, i ) { if ( Abc_NtkTopoHasBeg(pObj) ) continue; Abc_NtkIncrementTravId( p ); Abc_NtkReverseTopoOrder_rec( pObj, 1 ); } printf( "Nodes = %d. Size = %d. Ratio = %f.\n", Abc_NtkNodeNum(p), Vec_IntSize(p->vTopo), 1.0*Vec_IntSize(p->vTopo)/Abc_NtkNodeNum(p) ); } void Abc_NtkReverse_rec( Abc_Obj_t * pObj, Vec_Int_t * vVisited ) { Abc_Obj_t * pNext; int i; if ( Abc_NodeIsTravIdCurrent( pObj ) ) return; Abc_NodeSetTravIdCurrent( pObj ); Abc_ObjForEachFanout( pObj, pNext, i ) Abc_NtkReverse_rec( pNext, vVisited ); Vec_IntPush( vVisited, Abc_ObjId(pObj) ); } void Abc_NtkReverseTopoOrderTest( Abc_Ntk_t * p ) { Vec_Int_t * vVisited; Abc_Obj_t * pObj; int i;//, k, iBeg, iEnd; abctime clk = Abc_Clock(); Abc_NtkReverseTopoOrder( p ); /* printf( "Reverse topological order for nodes:\n" ); Abc_NtkForEachNode( p, pObj, i ) { iBeg = Abc_NtkTopoHasBeg( pObj ); iEnd = Abc_NtkTopoHasEnd( pObj ); printf( "Node %4d : ", Abc_ObjId(pObj) ); for ( k = iEnd - 1; k >= iBeg; k-- ) printf( "%d ", Vec_IntEntry(p->vTopo, k) ); printf( "\n" ); } */ Vec_IntFreeP( &p->vTopo ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // compute regular fanout orders clk = Abc_Clock(); vVisited = Vec_IntAlloc( 1000 ); Abc_NtkForEachNode( p, pObj, i ) { Vec_IntClear( vVisited ); Abc_NtkIncrementTravId( p ); Abc_NtkReverse_rec( pObj, vVisited ); } Vec_IntFree( vVisited ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [Converts multi-output PLA into an AIG with logic sharing.] Description [The first argument is an array of char*-strings representing individual output of a multi-output PLA. The number of inputs (nInputs) and the number of outputs (nOutputs) are the second and third arguments. This procedure returns the AIG manager with the given number of inputs and outputs representing the PLA as a logic network with sharing. For example, if the original PLA is 1000 10 0110 01 0011 01 the individual PLA for each the two outputs should be 1000 1 and 0110 1 0011 1 Reprsentation in terms of two char*-strings will be: char * pPlas[2] = { "1000 1\n", "0110 1\n0011 1\n" }; The call to the procedure may look as follows: Abc_Ntk_t * pNtkAig = Abc_NtkFromPla( pPlas, 4, 2 );] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromPla( char ** pPlas, int nInputs, int nOutputs ) { Fxu_Data_t Params, * p = &Params; Abc_Ntk_t * pNtkSop, * pNtkAig; Abc_Obj_t * pNode, * pFanin; int i, k; // allocate logic network with SOP local functions pNtkSop = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); pNtkSop->pName = Extra_FileNameGeneric("pla"); // create primary inputs/outputs for ( i = 0; i < nInputs; i++ ) Abc_NtkCreatePi( pNtkSop ); for ( i = 0; i < nOutputs; i++ ) Abc_NtkCreatePo( pNtkSop ); Abc_NtkAddDummyPiNames( pNtkSop ); Abc_NtkAddDummyPoNames( pNtkSop ); // create internal nodes for ( i = 0; i < nOutputs; i++ ) { pNode = Abc_NtkCreateNode( pNtkSop ); Abc_NtkForEachPi( pNtkSop, pFanin, k ) Abc_ObjAddFanin( pNode, pFanin ); pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkSop->pManFunc, pPlas[i] ); Abc_ObjAddFanin( Abc_NtkPo(pNtkSop, i), pNode ); // check that the number of inputs is the same assert( Abc_SopGetVarNum((char*)pNode->pData) == nInputs ); } if ( !Abc_NtkCheck( pNtkSop ) ) fprintf( stdout, "Abc_NtkFromPla(): Network check has failed.\n" ); // perform fast_extract Abc_NtkSetDefaultFxParams( p ); Abc_NtkFastExtract( pNtkSop, p ); Abc_NtkFxuFreeInfo( p ); // convert to an AIG pNtkAig = Abc_NtkStrash( pNtkSop, 0, 1, 0 ); Abc_NtkDelete( pNtkSop ); return pNtkAig; } void Abc_NtkFromPlaTest() { char * pPlas[2] = { "1000 1\n", "0110 1\n0011 1\n" }; Abc_Ntk_t * pNtkAig = Abc_NtkFromPla( pPlas, 4, 2 ); Io_WriteBlifLogic( pNtkAig, "temp.blif", 0 ); Abc_NtkDelete( pNtkAig ); } /**Function************************************************************* Synopsis [Checks if the logic network is in the topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkSplitSop( Abc_Ntk_t * pNtk, int nCubesMax, int fVerbose ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin, * pObjNew, * pObjNewRoot; int i, k, j, nCubes, nCubesThis, nSplits; char * pSopStr, * pSopStr2, * pTempSop, Symb; if ( pNtk == NULL ) return NULL; assert( !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsNetlist(pNtk) ); // start the network pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); // copy the internal nodes vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { assert( Abc_ObjIsNode(pObj) ); pObjNewRoot = Abc_NtkDupObj( pNtkNew, pObj, 0 ); nCubes = Abc_SopGetCubeNum( (char *)pObj->pData ); if ( nCubes <= nCubesMax ) { Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); continue; } nSplits = (nCubes / nCubesMax) + (int)(nCubes % nCubesMax > 0); pSopStr = (char *)pObjNewRoot->pData; pObjNewRoot->pData = Abc_SopCreateOr((Mem_Flex_t *)pNtkNew->pManFunc, nSplits, NULL); if ( Abc_SopIsComplement(pSopStr) ) { Abc_SopComplement( pSopStr ); Abc_SopComplement( (char *)pObjNewRoot->pData ); } pTempSop = (char *)pObj->pData; pObj->pData = (char *)"?"; for ( j = 0; j < nSplits; j++ ) { // clone the node pObjNew = Abc_NtkDupObj( pNtkNew, pObj, 0 ); Abc_ObjAddFanin( pObjNewRoot, pObjNew ); // get its cubes Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); // create SOP for this node nCubesThis = (j < nCubes / nCubesMax) ? nCubesMax : nCubes % nCubesMax; pSopStr2 = pSopStr + (Abc_ObjFaninNum(pObj) + 3) * nCubesThis; Symb = *pSopStr2; *pSopStr2 = 0; pObjNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, pSopStr ); *pSopStr2 = Symb; pSopStr = pSopStr2; } // update pObj->pData = pTempSop; pObj->pCopy = pObjNewRoot; } Vec_PtrFree( vNodes ); Abc_NtkFinalize( pNtk, pNtkNew ); // check correctness if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); pNtk->pCopy = pNtkNew; return pNtkNew; } /**Function************************************************************* Synopsis [Checks if the logic network is in the topological order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkIsTopo( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pFanin; int i, k, Counter = 0; Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachCi( pNtk, pObj, i ) Abc_NodeSetTravIdCurrent(pObj); Abc_NtkForEachNode( pNtk, pObj, i ) { // check if fanins are in the topo order Abc_ObjForEachFanin( pObj, pFanin, k ) if ( !Abc_NodeIsTravIdCurrent(pFanin) ) break; if ( k != Abc_ObjFaninNum(pObj) ) { if ( Counter++ == 0 ) printf( "Node %d is out of topo order.\n", Abc_ObjId(pObj) ); } Abc_NodeSetTravIdCurrent(pObj); } if ( Counter ) printf( "Topological order does not hold for %d internal nodes.\n", Counter ); return (int)(Counter == 0); } /**Function************************************************************* Synopsis [Transfers phase information to the new network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTransferPhases( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; assert( pNtk->vPhases != NULL ); assert( Vec_IntSize(pNtk->vPhases) == Abc_NtkObjNumMax(pNtk) ); assert( pNtkNew->vPhases == NULL ); pNtkNew->vPhases = Vec_IntStart( Abc_NtkObjNumMax(pNtkNew) ); Abc_NtkForEachObj( pNtk, pObj, i ) if ( pObj->pCopy && !Abc_ObjIsNone( (Abc_Obj_t *)pObj->pCopy ) ) Vec_IntWriteEntry( pNtkNew->vPhases, Abc_ObjId( (Abc_Obj_t *)pObj->pCopy ), Vec_IntEntry(pNtk->vPhases, i) ); } /**Function************************************************************* Synopsis [Starts a new network using existing network as a model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkDeriveWithOnePo( Abc_Ntk_t * pNtk, Vec_Int_t * vNodeIds, Vec_Int_t * vNodeValues ) { int fCopyNames = 1; Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin, * pObjNew, * pOutputNew; Vec_Ptr_t * vFanins = Vec_PtrAlloc( 100 ); int i, k, Id, Value; // start the network pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); // duplicate the name and the spec pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); // map the constant nodes if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); // clone CIs/CIs/boxes Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); //Abc_NtkForEachPo( pNtk, pObj, i ) // Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); // create one PO pObjNew = Abc_NtkCreateObj( pNtkNew, ABC_OBJ_PO ); Abc_ObjAssignName( pObjNew, "monitor", NULL ); // create boxes Abc_NtkForEachBox( pNtk, pObj, i ) Abc_NtkDupBox( pNtkNew, pObj, fCopyNames ); // duplicate nodes (CIs/COs/latches are already duplicated) Abc_NtkForEachObj( pNtk, pObj, i ) if ( pObj->pCopy == NULL && !Abc_ObjIsPo(pObj) ) Abc_NtkDupObj(pNtkNew, pObj, 0); // reconnect all objects except boxes (they are already connected) and POs (they will be connected later) Abc_NtkForEachObj( pNtk, pObj, i ) if ( !Abc_ObjIsPo(pObj) && !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); // AND nodes (with interters if needed) pOutputNew = NULL; Vec_IntForEachEntryTwo( vNodeIds, vNodeValues, Id, Value, i ) { pObjNew = Abc_NtkObj( pNtk, Id )->pCopy; if ( Value == 0 ) // negative polarity - add inverter pObjNew = Abc_NtkCreateNodeInv( pNtkNew, pObjNew ); if ( pOutputNew == NULL ) pOutputNew = pObjNew; else { Vec_PtrFillTwo( vFanins, 2, pOutputNew, pObjNew ); pOutputNew = Abc_NtkCreateNodeAnd( pNtkNew, vFanins ); } } Vec_PtrFree( vFanins ); // create the only POs, which is the AND of the corresponding nodes Abc_ObjAddFanin( Abc_NtkPo(pNtkNew, 0), pOutputNew ); // check that the CI/CO/latches are copied correctly assert( Abc_NtkPoNum(pNtkNew) == 1 ); assert( Abc_NtkCiNum(pNtkNew) == Abc_NtkCiNum(pNtk) ); assert( Abc_NtkLatchNum(pNtkNew) == Abc_NtkLatchNum(pNtk) ); return pNtkNew; } /**Function************************************************************* Synopsis [Derives the AIG representing a property.] Description [Given is a sequential logic network (Abc_Ntk_t) and an array of nodes (vector of object IDs) and their values (vector of 0s or 1s). This procedure creates a sequential AIG (Abc_Ntk_t), which can be given to a sequential model checker (in particular "pdr") to prove that the given combination of values never appears at the intenal nodes of the network, or produce a counter-example showing that it can appear.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCreatePropertyMonitor( Abc_Ntk_t * p, Vec_Int_t * vNodeIds, Vec_Int_t * vNodeValues ) { Abc_Ntk_t * pMonitor, * pStrashed, * pResult; // sequential cleanup parameters int fLatchConst = 1; int fLatchEqual = 1; int fSaveNames = 1; int fUseMvSweep = 0; int nFramesSymb = 1; int nFramesSatur = 512; int fVerbose = 0; int fVeryVerbose = 0; // expecting sequential logic network assert( Abc_NtkIsLogic(p) ); assert( Abc_NtkLatchNum(p) > 0 ); assert( Vec_IntSize(vNodeIds) > 0 ); assert( Vec_IntSize(vNodeIds) == Vec_IntSize(vNodeValues) ); // derive ABC network whose only output is 1 iff the given nodes have the given values pMonitor = Abc_NtkDeriveWithOnePo( p, vNodeIds, vNodeValues ); // perform structural hashing pStrashed = Abc_NtkStrash( pMonitor, 0, 1, 0 ); Abc_NtkDelete( pMonitor ); // it is a good idea to run sequential cleanup before giving the network to PDR pResult = Abc_NtkDarLatchSweep( pStrashed, fLatchConst, fLatchEqual, fSaveNames, fUseMvSweep, nFramesSymb, nFramesSatur, fVerbose, fVeryVerbose ); Abc_NtkDelete( pStrashed ); return pResult; } /**Function************************************************************* Synopsis [Testbench.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkCreatePropertyMonitorTest( Abc_Ntk_t * p ) { Abc_Ntk_t * pNtk; Vec_Int_t * vNodeIds = Vec_IntAlloc( 100 ); Vec_Int_t * vNodeValues = Vec_IntAlloc( 100 ); // this test will only work for the network, which has nodes with internal IDs such as these Vec_IntPush( vNodeIds, 90 ); Vec_IntPush( vNodeIds, 80 ); Vec_IntPush( vNodeIds, 100 ); Vec_IntPush( vNodeValues, 1 ); Vec_IntPush( vNodeValues, 0 ); Vec_IntPush( vNodeValues, 1 ); pNtk = Abc_NtkCreatePropertyMonitor( p, vNodeIds, vNodeValues ); Vec_IntFree( vNodeIds ); Vec_IntFree( vNodeValues ); return pNtk; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_GateToType( Abc_Obj_t * pObj ) { char * pGateName = Mio_GateReadName((Mio_Gate_t *)pObj->pData); if ( !strncmp(pGateName, "buf", 3) ) return ABC_OPER_BIT_BUF; if ( !strncmp(pGateName, "inv", 3) ) return ABC_OPER_BIT_INV; if ( !strncmp(pGateName, "and", 3) ) return ABC_OPER_BIT_AND; if ( !strncmp(pGateName, "nand", 4) ) return ABC_OPER_BIT_NAND; if ( !strncmp(pGateName, "or", 2) ) return ABC_OPER_BIT_OR; if ( !strncmp(pGateName, "nor", 3) ) return ABC_OPER_BIT_NOR; if ( !strncmp(pGateName, "xor", 3) ) return ABC_OPER_BIT_XOR; if ( !strncmp(pGateName, "xnor", 4) ) return ABC_OPER_BIT_NXOR; if ( !strncmp(pGateName, "zero", 4) ) return ABC_OPER_CONST_F; if ( !strncmp(pGateName, "one", 3) ) return ABC_OPER_CONST_T; assert( 0 ); return -1; } Vec_Wec_t * Abc_SopSynthesize( Vec_Ptr_t * vSops ) { Vec_Wec_t * vRes = NULL; Abc_Ntk_t * pNtk = Abc_NtkCreateFromSops( "top", vSops ); Abc_Ntk_t * pNtkNew; 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" ); 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 ) pObj->iTemp = iNode++; Abc_NtkForEachNode( pNtkNew, pObj, i ) { Vec_Int_t * vNode = Vec_WecEntry(vRes, iNode); Vec_IntPush( vNode, Abc_GateToType(pObj) ); Vec_IntPush( vNode, iNode ); Abc_ObjForEachFanin( pObj, pFanin, k ) Vec_IntPush( vNode, pFanin->iTemp ); pObj->iTemp = iNode++; } Abc_NtkForEachPo( pNtkNew, pObj, i ) Vec_IntPushTwo( Vec_WecEntry(vRes, iNode++), ABC_OPER_BIT_BUF, Abc_ObjFanin0(pObj)->iTemp ); assert( Vec_WecSize(vRes) == iNode ); return vRes; } 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, pMulti ); Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin; int i, k, iNode = 0; Abc_FrameReplaceCurrentNetwork( Abc_FrameReadGlobalFrame(), pNtk ); 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 ) pObj->iTemp = iNode++; Abc_NtkForEachNode( pNtkNew, pObj, i ) { Vec_Int_t * vNode = Vec_WecEntry(vRes, iNode); Vec_IntPush( vNode, Abc_GateToType(pObj) ); Vec_IntPush( vNode, iNode ); Abc_ObjForEachFanin( pObj, pFanin, k ) Vec_IntPush( vNode, pFanin->iTemp ); pObj->iTemp = iNode++; } Abc_NtkForEachPo( pNtkNew, pObj, i ) Vec_IntPushTwo( Vec_WecEntry(vRes, iNode++), ABC_OPER_BIT_BUF, Abc_ObjFanin0(pObj)->iTemp ); assert( Vec_WecSize(vRes) == iNode ); return vRes; } 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, NULL ); Vec_PtrFree( vGias ); Abc_FrameReplaceCurrentNetwork( Abc_FrameReadGlobalFrame(), pNtk ); Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "balance; collapse; muxes; strash; dc2" ); pNtkNew = Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ); return Abc_NtkClpGia( pNtkNew ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkClpOneGia_rec( Gia_Man_t * pNew, Abc_Obj_t * pNode ) { int iLit0, iLit1; if ( Abc_NodeIsTravIdCurrent(pNode) || Abc_ObjFaninNum(pNode) == 0 || Abc_ObjIsCi(pNode) ) return pNode->iTemp; assert( Abc_ObjIsNode( pNode ) ); Abc_NodeSetTravIdCurrent( pNode ); iLit0 = Abc_NtkClpOneGia_rec( pNew, Abc_ObjFanin0(pNode) ); iLit1 = Abc_NtkClpOneGia_rec( pNew, Abc_ObjFanin1(pNode) ); iLit0 = Abc_LitNotCond( iLit0, Abc_ObjFaninC0(pNode) ); iLit1 = Abc_LitNotCond( iLit1, Abc_ObjFaninC1(pNode) ); return (pNode->iTemp = Gia_ManHashAnd(pNew, iLit0, iLit1)); } Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk ) { int i, iLit; Abc_Obj_t * pNode; Gia_Man_t * pNew, * pTemp; assert( Abc_NtkIsStrash(pNtk) ); Abc_NtkForEachObj( pNtk, pNode, i ) pNode->iTemp = -1; // start new manager pNew = Gia_ManStart( Abc_NtkObjNum(pNtk) ); pNew->pName = Abc_UtilStrsav( pNtk->pName ); pNew->pSpec = Abc_UtilStrsav( pNtk->pSpec ); Gia_ManHashStart( pNew ); // primary inputs Abc_AigConst1(pNtk)->iTemp = 1; Abc_NtkForEachCi( pNtk, pNode, i ) pNode->iTemp = Gia_ManAppendCi(pNew); // create the first cone Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachCo( pNtk, pNode, i ) { iLit = Abc_NtkClpOneGia_rec( pNew, Abc_ObjFanin0(pNode) ); iLit = Abc_LitNotCond( iLit, Abc_ObjFaninC0(pNode) ); Gia_ManAppendCo( pNew, iLit ); } // perform cleanup pNew = Gia_ManCleanup( pTemp = pNew ); Gia_ManStop( pTemp ); return pNew; } Gia_Man_t * Abc_SopSynthesizeOne( char * pSop, int fClp ) { Abc_Ntk_t * pNtkNew, * pNtk; Vec_Ptr_t * vSops; if ( strlen(pSop) == 3 ) { Gia_Man_t * pNew = Gia_ManStart( 1 ); pNew->pName = Abc_UtilStrsav( "top" ); //Gia_ManAppendCi( pNew ); assert( pSop[1] == '0' || pSop[1] == '1' ); Gia_ManAppendCo( pNew, pSop[1] == '1' ); return pNew; } vSops = Vec_PtrAlloc( 1 ); Vec_PtrPush( vSops, pSop ); 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; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_PrintAT( Vec_Int_t * vRanks ) { int i, Entry; Vec_IntForEachEntryReverse( vRanks, Entry, i ) if ( Entry == 0 ) printf( " " ); else printf( "%4d", Entry ); //printf( "\n" ); } int Abc_NtkMatchGpcPattern( Vec_Int_t * vRanks, int i, char * pGPC ) { int k, Cur, Min = ABC_INFINITY; for ( k = 0; pGPC[k] != ':' && i+k < Vec_IntSize(vRanks); k++ ) { if ( Abc_TtReadHexDigit(pGPC[k]) == 0 ) continue; Cur = Vec_IntEntry(vRanks, i+k) / Abc_TtReadHexDigit(pGPC[k]); if ( Min > Cur ) Min = Cur; } return Min; } void Abc_NtkUpdateGpcPattern( Vec_Int_t * vRank, int i, char * pGPC, int nGpcs, Vec_Int_t * vRank2, Vec_Int_t * vLevel ) { int k; char * pOut = strstr(pGPC, ":"); assert( pOut && pOut[0] == ':' ); pOut++; Vec_IntAddToEntry( vLevel, i, nGpcs ); for ( k = 0; pGPC[k] != ':'; k++ ) Vec_IntAddToEntry( vRank, i+k, -nGpcs * Abc_TtReadHexDigit(pGPC[k]) ); for ( k = 0; pOut[k] != ':'; k++ ) Vec_IntAddToEntry( vRank2, i+k, nGpcs * Abc_TtReadHexDigit(pOut[k]) ); } int Abc_NtkGetGpcLutCount( char * pGPC ) { char * pOut = strstr(pGPC, ":"); char * pLut = strstr(pOut+1, ":"); return atoi(pLut+1); } static inline int Vec_WecSum( Vec_Wec_t * p ) { Vec_Int_t * vVec; int i, Counter = 0; Vec_WecForEachLevel( p, vVec, i ) Counter += Vec_IntSum(vVec); return Counter; } char ** Abc_NtkTransformGPCs( char ** pGPCs, int nGPCs ) { char * pOut, * pLut, ** pRes = ABC_ALLOC( char *, nGPCs ); int i, k, nLength; for ( i = 0; i < nGPCs; i++ ) { pRes[i] = Abc_UtilStrsav(pGPCs[i]); pOut = strstr(pRes[i], ":"); nLength = (int)(pOut-pRes[i]); for ( k = 0; k < nLength/2; k++ ) ABC_SWAP( char, pRes[i][k], pRes[i][nLength-1-k] ) pLut = strstr(pOut+1, ":"); nLength = (int)(pLut-pOut-1); for ( k = 0; k < nLength/2; k++ ) ABC_SWAP( char, pOut[1+k], pOut[1+nLength-1-k] ) } return pRes; } int Abc_NtkCheckGpc( char * pGPC, char * pGPC0 ) { int RetValue = 0, k, Sum[2] = {0}; char * pOut = strstr(pGPC, ":"); for ( k = 0; pGPC[k] != ':'; k++ ) Sum[0] += (1 << k) * Abc_TtReadHexDigit(pGPC[k]); for ( k = 0; pOut[1+k] != ':'; k++ ) Sum[1] += (1 << k) * Abc_TtReadHexDigit(pOut[1+k]); //printf( "GPC %s has input sum %d and output sum %d\n", pGPC0, Sum[0], Sum[1] ); if ( Sum[0]+1 > (1 << Abc_Base2Log(Sum[1]+1)) ) printf( "The largest value of GPC inputs (%d) exceeds the capacity of outputs (%d) for GPC %s.\n", Sum[0], Sum[1], pGPC0 ); else if ( Sum[1]+1 > (1 << Abc_Base2Log(Sum[0]+1)) ) printf( "The largest value of GPC outputs (%d) exceeds the capacity of inputs (%d) for GPC %s.\n", Sum[1], Sum[0], pGPC0 ); else RetValue = 1; return RetValue; } void Abc_NtkATMap( int nXVars, int nYVars, int nAdder, char ** pGPCs0, int nGPCs, int fReturn, int fVerbose ) { abctime clkStart = Abc_Clock(); char ** pGPCs = Abc_NtkTransformGPCs(pGPCs0, nGPCs); int i, nGPCluts[100] = {0}; for ( i = 0; i < nGPCs; i++ ) if ( !Abc_NtkCheckGpc(pGPCs[i], pGPCs0[i]) ) return; for ( i = 0; i < nGPCs; i++ ) nGPCluts[i] = Abc_NtkGetGpcLutCount(pGPCs[i]); int x, n, Entry, iLevel = 0, Sum = 0, nGpcs = 0, nBits, fFinished, nRcaLuts = 0, nLuts = 0; for ( x = 0; x < nXVars; x++ ) Sum += (1 << x) * nYVars; nBits = Abc_Base2Log( Sum+1 ); printf( "Rectangular adder tree (X=%d Y=%d Sum=%d Out=%d) mapped with", nXVars, nYVars, Sum, nBits ); for ( i = 0; i < nGPCs; i++ ) printf( " GPC%d=%s", i, pGPCs0[i] ); printf( "\n" ); Vec_Int_t * vLevel; Vec_Int_t * vRank[3] = { Vec_IntAlloc(100), Vec_IntAlloc(100), Vec_IntAlloc(100) }; Vec_Wec_t ** vGPCs = ABC_ALLOC( Vec_Wec_t *, nGPCs ); for ( i = 0; i < nGPCs; i++ ) vGPCs[i] = Vec_WecAlloc(100); Vec_IntFill( vRank[0], nBits, 0 ); for ( x = 0; x < nXVars; x++ ) Vec_IntAddToEntry( vRank[0], x, nYVars ); if ( fVerbose ) { printf( "Ranks: " ); for ( i = nBits-1; i >= 0; i-- ) printf( "%4d", i ); printf( " : " ); for ( i = nBits-1; i >= 0; i-- ) printf( "%4d", i ); printf( " LUT6\n" ); } for ( n = 0; n < nGPCs; n++ ) for ( i = 0, fFinished = 0; !fFinished; i++ ) { int fAdded = 0; vLevel = Vec_WecPushLevel( vGPCs[n] ); Vec_IntFill( vLevel, nBits, 0 ); Vec_IntFill( vRank[1], nBits, 0 ); Vec_IntClear( vRank[2] ); Vec_IntAppend( vRank[2], vRank[0] ); fFinished = 1; if ( Vec_IntFindMax(vRank[0]) > nAdder ) { for ( x = 0; x < nBits; x++ ) if ( (nGpcs = Abc_NtkMatchGpcPattern(vRank[0], x, pGPCs[n])) ) Abc_NtkUpdateGpcPattern(vRank[0], x, pGPCs[n], nGpcs, vRank[1], vLevel), fFinished = 0, fAdded = 1; nLuts += Vec_IntSum(vLevel) * nGPCluts[n]; Vec_IntForEachEntry( vRank[1], Entry, x ) Vec_IntAddToEntry( vRank[0], x, Entry ); } if ( fVerbose && (fAdded || Vec_IntFindMax(vRank[2]) <= nAdder ) ) { printf( "Lev%02d: ", iLevel++ ); Abc_PrintAT( vRank[2] ); if ( fAdded ) { printf( " GPC%d: ", n ); Abc_PrintAT( vLevel ); printf( " %4d", Vec_IntSum(vLevel) * nGPCluts[n] ); } else if ( Vec_IntFindMax(vRank[2]) <= nAdder ) { printf( " ADD%d: ", nAdder ); for ( x = 0; x < nBits; x++ ) if ( Vec_IntEntry(vRank[2], x) > 1 ) break; for ( i = nBits-1; i >= x; i-- ) printf( "%4d", 1 ); for ( ; i >= 0; i-- ) printf( " " ); printf( " %4d", (nBits-x)*(nAdder == 4 ? 2 : 1) ); } printf( "\n" ); } if ( fAdded ) { if ( fReturn ) { fFinished = 1; n = -1; } } else if ( Vec_IntFindMax(vRank[2]) <= nAdder ) { fFinished = 1; n = nGPCs; } } if ( Vec_IntFindMax(vRank[0]) > nAdder ) printf( "Synthesis of the adder tree is incomplete. Try using the full adder \"3:11:1\" as the last GPC.\n" ); else if ( fVerbose && Vec_IntFindMax(vRank[0]) <= nAdder ) { printf( "Lev%02d: ", iLevel++ ); for ( i = nBits-1; i >= 0; i-- ) printf( "%4d", 1 ); printf( "\n" ); } printf( "Statistics: " ); for ( n = 0; n < nGPCs; n++ ) printf( "GPC%d = %d. ", n, Vec_WecSum(vGPCs[n]) ); for ( x = 0; x < nBits; x++ ) if ( Vec_IntEntry(vRank[0], x) > 1 ) break; nRcaLuts = (nBits-x)*(nAdder == 4 ? 2 : 1); printf( "ADD%d = %d. ", nAdder, nRcaLuts ); printf( "Total LUT count = %d. ", nLuts+nRcaLuts ); for ( i = 0; i < 3; i++ ) Vec_IntFree( vRank[i] ); for ( i = 0; i < nGPCs; i++ ) Vec_WecFree( vGPCs[i] ); ABC_FREE( vGPCs ); for ( i = 0; i < nGPCs; i++ ) ABC_FREE( pGPCs[i] ); ABC_FREE( pGPCs ); Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/abc_.c000066400000000000000000000026471477524141600154670ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abc_.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "abc.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END abc-0.52/src/base/abc/module.make000066400000000000000000000012601477524141600165510ustar00rootroot00000000000000SRC += src/base/abc/abcAig.c \ src/base/abc/abcBarBuf.c \ src/base/abc/abcBlifMv.c \ src/base/abc/abcCheck.c \ src/base/abc/abcDfs.c \ src/base/abc/abcFanio.c \ src/base/abc/abcFanOrder.c \ src/base/abc/abcFunc.c \ src/base/abc/abcHie.c \ src/base/abc/abcHieCec.c \ src/base/abc/abcHieGia.c \ src/base/abc/abcHieNew.c \ src/base/abc/abcLatch.c \ src/base/abc/abcLib.c \ src/base/abc/abcMinBase.c \ src/base/abc/abcNames.c \ src/base/abc/abcNetlist.c \ src/base/abc/abcNtk.c \ src/base/abc/abcObj.c \ src/base/abc/abcRefs.c \ src/base/abc/abcShow.c \ src/base/abc/abcSop.c \ src/base/abc/abcUtil.c abc-0.52/src/base/abci/000077500000000000000000000000001477524141600145775ustar00rootroot00000000000000abc-0.52/src/base/abci/abc.c000066400000000000000000075003701477524141600155040ustar00rootroot00000000000000/**CFile**************************************************************** FileName [abc.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Network and node package.] Synopsis [Command file.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: abc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "base/abc/abc.h" #include "base/main/main.h" #include "base/main/mainInt.h" #include "proof/fraig/fraig.h" #include "opt/fxu/fxu.h" #include "opt/fxch/Fxch.h" #include "opt/cut/cut.h" #include "map/fpga/fpga.h" #include "map/if/if.h" #include "opt/sim/sim.h" #include "opt/res/res.h" #include "opt/lpk/lpk.h" #include "aig/gia/giaAig.h" #include "opt/dar/dar.h" #include "opt/mfs/mfs.h" #include "proof/fra/fra.h" #include "aig/saig/saig.h" #include "proof/int/int.h" #include "proof/dch/dch.h" #include "proof/ssw/ssw.h" #include "opt/cgt/cgt.h" #include "bool/kit/kit.h" #include "map/amap/amap.h" #include "opt/ret/retInt.h" #include "sat/xsat/xsat.h" #include "sat/satoko/satoko.h" #include "sat/cnf/cnf.h" #include "proof/cec/cec.h" #include "proof/acec/acec.h" #include "proof/pdr/pdr.h" #include "misc/tim/tim.h" #include "bdd/llb/llb.h" #include "bdd/bbr/bbr.h" #include "map/cov/cov.h" #include "base/cmd/cmd.h" #include "proof/abs/abs.h" #include "sat/bmc/bmc.h" #include "proof/ssc/ssc.h" #include "opt/sfm/sfm.h" #include "opt/sbd/sbd.h" #include "bool/rpo/rpo.h" #include "map/mpm/mpm.h" #include "map/mio/mio.h" #include "opt/fret/fretime.h" #include "opt/nwk/nwkMerge.h" #include "base/acb/acbPar.h" #include "misc/extra/extra.h" #include "opt/eslim/eSLIM.h" #ifndef _WIN32 #include #endif ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //#define USE_MINISAT22 static int Abc_CommandPrintStats ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintExdc ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintIo ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintLatch ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintFanio ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintMffc ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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 ); static int Abc_CommandPrintKMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintGates ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintSharing ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintXCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintDsd ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintCone ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintStatus ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPrintDelay ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandShow ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandShowBdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandShowCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCollapse ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSatClp ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandStrash ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBalance ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMuxStruct ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMulti ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRenode ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFastExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFxch ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandEliminate ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDisjoint ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSparsify ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLutpack ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLutmin ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandImfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMfs2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMfs3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMfse ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLogicPush ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTrace ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandGlitch ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSpeedup ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPowerdown ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAddBuffs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMerge ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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_CommandTestTruth ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestSupp ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestRand ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRunSat ( 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_CommandResubUnate ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandResubCore ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandResubCheck ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLutCasDec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLutCas ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBsEval ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandVarMin ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFaultClasses ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBmsStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBmsStop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBmsPs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMajExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTwoExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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_CommandAIGAugmentation ( 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 ); static int Abc_CommandZeroPo ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSwapPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRemovePo ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDropSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAddPi ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAddFlop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAppend ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPutOnTop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFrames ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDFrames ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandReorder ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBidec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandOrder ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMuxes ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCubes ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExpand ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSplitSop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExtSeqDcs ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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 ); static int Abc_CommandMoveNames ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExdcFree ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExdcGet ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExdcSet ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCareSet ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandEspresso ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandGenTF ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandGenAT ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandGenFsm ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCover ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDouble ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandInter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBb2Wb ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandOutdec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandNodeDup ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandWrap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestColor ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandQuaVar ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandQuaRel ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandQuaReach ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSenseInput ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandNpnLoad ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandNpnSave ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSendAig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSendStatus ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBackup ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRestore ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMinisat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMinisimp ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandIStrash ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandICut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandIRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDc2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDChoice ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDch ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDrwsat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandIRewriteSeq ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandIResyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandISat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandIFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSimSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMatch ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandHaig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandQbf ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFraigTrust ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFraigStore ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFraigRestore ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFraigClean ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFraigSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFraigDress ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDumpEquiv ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecStart3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecStop3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecPs3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecAdd3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecDump3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRecMerge3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPhaseMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandStochMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandUnmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAttach ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSuperChoice ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSuperChoiceLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTimeScale ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRewire ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandFpga ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandFpgaFast ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandIf ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandIfif ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDsdSave ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDsdLoad ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDsdFree ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDsdPs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDsdMatch ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDsdMerge ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDsdFilter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandScut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandInit ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandZero ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandUndc ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandOneHot ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPipe ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSeq ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandUnseq ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandRetime ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDRetime ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFlowRetime ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCRetime ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSeqFpga ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSeqMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSeqSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSeqSweep2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestSeqSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestScorr ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLcorr ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSeqCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCycle ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandXsim ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSim3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDarPhase ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSynch ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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_CommandATMap ( 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 ); static int Abc_CommandDSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandXSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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 ); static int Abc_CommandDebug ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandEco ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBmc2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBmc3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBmcInter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandIndcut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandEnlarge ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTempor ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandInduction ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandConstr ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandUnfold ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFold ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandUnfold2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFold2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBm ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBm2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandSaucy ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandTestCex ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandPdr ( Abc_Frame_t * pAbc, int argc, char ** argv ); #ifdef ABC_USE_CUDD static int Abc_CommandReconcile ( Abc_Frame_t * pAbc, int argc, char ** argv ); #endif static int Abc_CommandCexSave ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCexLoad ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCexCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandCexMerge ( Abc_Frame_t * pAbc, int argc, char ** argv ); //static int Abc_CommandCexMin ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandDualRail ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandBlockPo ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandIso ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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 ); static int Abc_CommandAbc9Load ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Load2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9LoadAig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Read ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9ReadBlif ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9ReadCBlif ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9ReadStg ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9ReadVer ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9WriteVer ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Write ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9WriteLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Ps ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9PFan ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Pms ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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 ); static int Abc_CommandAbc9Show ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SetRegNum ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Strash ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Topand ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Add1Hot ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Cof ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Cofs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Trim ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Dfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Sim ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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 ); static int Abc_CommandAbc9Equiv2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Equiv3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Semi ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Times ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Frames ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Retime ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Enable ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Dc2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Dsd ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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 ); static int Abc_CommandAbc9Synch2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9False ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Miter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Miter2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Append ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Scl ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Lcorr ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Scorr ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Choice ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Sat ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SatEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9AdvGenSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Fraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9CFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Srm ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Srm2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Filter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Reduce ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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 ); static int Abc_CommandAbc9Embed ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Sopb ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Dsdb ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Flow ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Flow2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Flow3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9If ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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 ); static int Abc_CommandAbc9Mf ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Nf ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Of ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Simap ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Exmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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 ); static int Abc_CommandAbc9Rrr ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Rewire ( 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 ); static int Abc_CommandAbc9Speedup ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Era ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Dch ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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 ); static int Abc_CommandAbc9ReachN ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9ReachY ( Abc_Frame_t * pAbc, int argc, char ** argv ); #endif static int Abc_CommandAbc9Undo ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Mesh ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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_CommandAbc9Store ( 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 ); static int Abc_CommandAbc9Slice ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9PoPart ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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_CommandAbc9SProve ( 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 ); static int Abc_CommandAbc9BCore ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9ICheck ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9SatTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9FFTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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 ); static int Abc_CommandAbc9Maxi ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Bmci ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9PoXsim ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Demiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Fadds ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9ATree ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Polyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Acec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Anorm ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Decla ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Esop ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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_CommandAbc9RandSyn ( 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 ); static int Abc_CommandAbc9GlaRefine ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GlaShrink ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Gla ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Vta ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Vta2Gla ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Gla2Vta ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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_CommandAbc9GenHie ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9PutOnTop ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9BRecover ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9StrEco ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenCex ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Odc ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenRel ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenMux ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenComp ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenSorter ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9GenNeuron ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Window ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9FunAbs ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9DsdInfo ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9FunTrace ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9MulFind ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandAbc9eSLIM ( Abc_Frame_t * pAbc, int argc, char ** argv ); extern int Abc_CommandAbcLivenessToSafety ( Abc_Frame_t * pAbc, int argc, char ** argv ); extern int Abc_CommandAbcLivenessToSafetySim ( Abc_Frame_t * pAbc, int argc, char ** argv ); extern int Abc_CommandAbcLivenessToSafetyWithLTL( Abc_Frame_t * pAbc, int argc, char ** argv ); extern int Abc_CommandCS_kLiveness ( Abc_Frame_t * pAbc, int argc, char ** argv ); extern int Abc_CommandNChooseK ( Abc_Frame_t * pAbc, int argc, char ** argv ); 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 /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameReplaceCex( Abc_Frame_t * pAbc, Abc_Cex_t ** ppCex ) { // update CEX ABC_FREE( pAbc->pCex ); pAbc->pCex = *ppCex; *ppCex = NULL; // remove CEX vector if ( pAbc->vCexVec ) { Vec_PtrFreeFree( pAbc->vCexVec ); pAbc->vCexVec = NULL; } } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameReplaceCexVec( Abc_Frame_t * pAbc, Vec_Ptr_t ** pvCexVec ) { // update CEX vector if ( pAbc->vCexVec ) Vec_PtrFreeFree( pAbc->vCexVec ); pAbc->vCexVec = *pvCexVec; *pvCexVec = NULL; // remove CEX ABC_FREE( pAbc->pCex ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameReplacePoEquivs( Abc_Frame_t * pAbc, Vec_Ptr_t ** pvPoEquivs ) { if ( pAbc->vPoEquivs ) Vec_VecFree( (Vec_Vec_t *)pAbc->vPoEquivs ); pAbc->vPoEquivs = *pvPoEquivs; *pvPoEquivs = NULL; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameReplacePoStatuses( Abc_Frame_t * pAbc, Vec_Int_t ** pvStatuses ) { if ( pAbc->vStatuses ) Vec_IntFree( pAbc->vStatuses ); pAbc->vStatuses = *pvStatuses; *pvStatuses = NULL; } /**Function************************************************************* Synopsis [Derives array of statuses from the array of CEXes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_FrameDeriveStatusArray( 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 != NULL ) 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************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameClearDesign() { } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_FrameUpdateGia( Abc_Frame_t * pAbc, Gia_Man_t * pNew ) { if ( pNew == NULL ) { Abc_Print( -1, "Abc_FrameUpdateGia(): Transformation has failed.\n" ); return; } if ( Gia_ManPoNum(pNew) == 0 ) Abc_Print( 0, "The current GIA has no primary outputs. Some commands may not work correctly.\n" ); if ( pNew == pAbc->pGia ) return; // transfer names if (!pNew->vNamesIn && pAbc->pGia && pAbc->pGia->vNamesIn && Gia_ManCiNum(pNew) == Vec_PtrSize(pAbc->pGia->vNamesIn)) { pNew->vNamesIn = pAbc->pGia->vNamesIn; pAbc->pGia->vNamesIn = NULL; } if (!pNew->vNamesOut && pAbc->pGia && pAbc->pGia->vNamesOut && Gia_ManCoNum(pNew) == Vec_PtrSize(pAbc->pGia->vNamesOut)) { 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 ); pAbc->pGia2 = pAbc->pGia; pAbc->pGia = pNew; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Abc_FrameGetGia( Abc_Frame_t * pAbc ) { Gia_Man_t * pGia; if ( pAbc->pGia2 ) Gia_ManStop( pAbc->pGia2 ); pAbc->pGia2 = NULL; pGia = pAbc->pGia; pAbc->pGia = NULL; return pGia; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_Init( Abc_Frame_t * pAbc ) { Cmd_CommandAdd( pAbc, "Printing", "ps", Abc_CommandPrintStats, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_stats", Abc_CommandPrintStats, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_exdc", Abc_CommandPrintExdc, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_io", Abc_CommandPrintIo, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_latch", Abc_CommandPrintLatch, 0 ); Cmd_CommandAdd( pAbc, "Printing", "pfan", Abc_CommandPrintFanio, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_fanio", Abc_CommandPrintFanio, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_mffc", Abc_CommandPrintMffc, 0 ); Cmd_CommandAdd( pAbc, "Printing", "pf", Abc_CommandPrintFactor, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_factor", Abc_CommandPrintFactor, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_level", Abc_CommandPrintLevel, 0 ); Cmd_CommandAdd( pAbc, "Printing", "psu", Abc_CommandPrintSupport, 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 ); Cmd_CommandAdd( pAbc, "Printing", "print_kmap", Abc_CommandPrintKMap, 0 ); Cmd_CommandAdd( pAbc, "Printing", "pg", Abc_CommandPrintGates, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_gates", Abc_CommandPrintGates, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_sharing", Abc_CommandPrintSharing, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_xcut", Abc_CommandPrintXCut, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_dsd", Abc_CommandPrintDsd, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_cone", Abc_CommandPrintCone, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_miter", Abc_CommandPrintMiter, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_status", Abc_CommandPrintStatus, 0 ); Cmd_CommandAdd( pAbc, "Printing", "print_delay", Abc_CommandPrintDelay, 0 ); Cmd_CommandAdd( pAbc, "Printing", "show", Abc_CommandShow, 0 ); Cmd_CommandAdd( pAbc, "Printing", "show_bdd", Abc_CommandShowBdd, 0 ); Cmd_CommandAdd( pAbc, "Printing", "show_cut", Abc_CommandShowCut, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "clp", Abc_CommandCollapse, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "collapse", Abc_CommandCollapse, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "satclp", Abc_CommandSatClp, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "st", Abc_CommandStrash, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "strash", Abc_CommandStrash, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "b", Abc_CommandBalance, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "balance", Abc_CommandBalance, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "mux_struct", Abc_CommandMuxStruct, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "multi", Abc_CommandMulti, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "renode", Abc_CommandRenode, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "cleanup", Abc_CommandCleanup, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "sweep", Abc_CommandSweep, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "fx", Abc_CommandFastExtract, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "fxch", Abc_CommandFxch, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "eliminate", Abc_CommandEliminate, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "dsd", Abc_CommandDisjoint, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "sparsify", Abc_CommandSparsify, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "lutpack", Abc_CommandLutpack, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "lutmin", Abc_CommandLutmin, 1 ); // Cmd_CommandAdd( pAbc, "Synthesis", "imfs", Abc_CommandImfs, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "mfs", Abc_CommandMfs, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "mfs2", Abc_CommandMfs2, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "mfs3", Abc_CommandMfs3, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "mfse", Abc_CommandMfse, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "logicpush", Abc_CommandLogicPush, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "trace", Abc_CommandTrace, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "glitch", Abc_CommandGlitch, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "speedup", Abc_CommandSpeedup, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "powerdown", Abc_CommandPowerdown, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "addbuffs", Abc_CommandAddBuffs, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "merge", Abc_CommandMerge, 1 ); 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", "testtruth", Abc_CommandTestTruth, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "testsupp", Abc_CommandTestSupp, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "testrand", Abc_CommandTestRand, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "runsat", Abc_CommandRunSat, 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_unate", Abc_CommandResubUnate, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "resub_core", Abc_CommandResubCore, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "resub_check", Abc_CommandResubCheck, 0 ); // Cmd_CommandAdd( pAbc, "Synthesis", "rr", Abc_CommandRr, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "lutcasdec", Abc_CommandLutCasDec, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "lutcas", Abc_CommandLutCas, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "bseval", Abc_CommandBsEval, 0 ); 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, "Synthesis", "aigaug", Abc_CommandAIGAugmentation, 1 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_start", Abc_CommandBmsStart, 0 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_stop", Abc_CommandBmsStop, 0 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_ps", Abc_CommandBmsPs, 0 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "majexact", Abc_CommandMajExact, 0 ); Cmd_CommandAdd( pAbc, "Exact synthesis", "twoexact", Abc_CommandTwoExact, 0 ); 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 ); Cmd_CommandAdd( pAbc, "Various", "zeropo", Abc_CommandZeroPo, 1 ); Cmd_CommandAdd( pAbc, "Various", "swappos", Abc_CommandSwapPos, 1 ); Cmd_CommandAdd( pAbc, "Various", "removepo", Abc_CommandRemovePo, 1 ); Cmd_CommandAdd( pAbc, "Various", "dropsat", Abc_CommandDropSat, 1 ); Cmd_CommandAdd( pAbc, "Various", "addpi", Abc_CommandAddPi, 1 ); Cmd_CommandAdd( pAbc, "Various", "addflop", Abc_CommandAddFlop, 1 ); Cmd_CommandAdd( pAbc, "Various", "append", Abc_CommandAppend, 1 ); Cmd_CommandAdd( pAbc, "Various", "putontop", Abc_CommandPutOnTop, 1 ); Cmd_CommandAdd( pAbc, "Various", "frames", Abc_CommandFrames, 1 ); Cmd_CommandAdd( pAbc, "Various", "dframes", Abc_CommandDFrames, 1 ); Cmd_CommandAdd( pAbc, "Various", "sop", Abc_CommandSop, 0 ); Cmd_CommandAdd( pAbc, "Various", "bdd", Abc_CommandBdd, 0 ); Cmd_CommandAdd( pAbc, "Various", "aig", Abc_CommandAig, 0 ); Cmd_CommandAdd( pAbc, "Various", "reorder", Abc_CommandReorder, 0 ); Cmd_CommandAdd( pAbc, "Various", "bidec", Abc_CommandBidec, 1 ); Cmd_CommandAdd( pAbc, "Various", "order", Abc_CommandOrder, 0 ); Cmd_CommandAdd( pAbc, "Various", "muxes", Abc_CommandMuxes, 1 ); Cmd_CommandAdd( pAbc, "Various", "cubes", Abc_CommandCubes, 1 ); Cmd_CommandAdd( pAbc, "Various", "expand", Abc_CommandExpand, 1 ); Cmd_CommandAdd( pAbc, "Various", "splitsop", Abc_CommandSplitSop, 1 ); Cmd_CommandAdd( pAbc, "Various", "ext_seq_dcs", Abc_CommandExtSeqDcs, 0 ); 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", "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 ); Cmd_CommandAdd( pAbc, "Various", "exdc_free", Abc_CommandExdcFree, 1 ); Cmd_CommandAdd( pAbc, "Various", "exdc_get", Abc_CommandExdcGet, 1 ); Cmd_CommandAdd( pAbc, "Various", "exdc_set", Abc_CommandExdcSet, 1 ); Cmd_CommandAdd( pAbc, "Various", "care_set", Abc_CommandCareSet, 1 ); Cmd_CommandAdd( pAbc, "Various", "cut", Abc_CommandCut, 0 ); Cmd_CommandAdd( pAbc, "Various", "espresso", Abc_CommandEspresso, 1 ); Cmd_CommandAdd( pAbc, "Various", "gen", Abc_CommandGen, 0 ); Cmd_CommandAdd( pAbc, "Various", "gentf", Abc_CommandGenTF, 0 ); Cmd_CommandAdd( pAbc, "Various", "genat", Abc_CommandGenAT, 0 ); Cmd_CommandAdd( pAbc, "Various", "genfsm", Abc_CommandGenFsm, 0 ); Cmd_CommandAdd( pAbc, "Various", "cover", Abc_CommandCover, 1 ); Cmd_CommandAdd( pAbc, "Various", "double", Abc_CommandDouble, 1 ); Cmd_CommandAdd( pAbc, "Various", "inter", Abc_CommandInter, 1 ); Cmd_CommandAdd( pAbc, "Various", "bb2wb", Abc_CommandBb2Wb, 0 ); Cmd_CommandAdd( pAbc, "Various", "outdec", Abc_CommandOutdec, 1 ); Cmd_CommandAdd( pAbc, "Various", "nodedup", Abc_CommandNodeDup, 1 ); Cmd_CommandAdd( pAbc, "Various", "wrap", Abc_CommandWrap, 0 ); Cmd_CommandAdd( pAbc, "Various", "testcolor", Abc_CommandTestColor, 0 ); Cmd_CommandAdd( pAbc, "Various", "test", Abc_CommandTest, 0 ); // Cmd_CommandAdd( pAbc, "Various", "qbf_solve", Abc_CommandTest, 0 ); Cmd_CommandAdd( pAbc, "Various", "qvar", Abc_CommandQuaVar, 1 ); Cmd_CommandAdd( pAbc, "Various", "qrel", Abc_CommandQuaRel, 1 ); Cmd_CommandAdd( pAbc, "Various", "qreach", Abc_CommandQuaReach, 1 ); Cmd_CommandAdd( pAbc, "Various", "senseinput", Abc_CommandSenseInput, 1 ); Cmd_CommandAdd( pAbc, "Various", "npnload", Abc_CommandNpnLoad, 0 ); Cmd_CommandAdd( pAbc, "Various", "npnsave", Abc_CommandNpnSave, 0 ); Cmd_CommandAdd( pAbc, "Various", "send_aig", Abc_CommandSendAig, 0 ); Cmd_CommandAdd( pAbc, "Various", "send_status", Abc_CommandSendStatus, 0 ); Cmd_CommandAdd( pAbc, "Various", "backup", Abc_CommandBackup, 0 ); Cmd_CommandAdd( pAbc, "Various", "restore", Abc_CommandRestore, 0 ); Cmd_CommandAdd( pAbc, "Various", "minisat", Abc_CommandMinisat, 0 ); Cmd_CommandAdd( pAbc, "Various", "minisimp", Abc_CommandMinisimp, 0 ); Cmd_CommandAdd( pAbc, "New AIG", "istrash", Abc_CommandIStrash, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "icut", Abc_CommandICut, 0 ); Cmd_CommandAdd( pAbc, "New AIG", "irw", Abc_CommandIRewrite, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "drw", Abc_CommandDRewrite, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "drf", Abc_CommandDRefactor, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "dc2", Abc_CommandDc2, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "dchoice", Abc_CommandDChoice, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "dch", Abc_CommandDch, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "drwsat", Abc_CommandDrwsat, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "irws", Abc_CommandIRewriteSeq, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "iresyn", Abc_CommandIResyn, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "isat", Abc_CommandISat, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "ifraig", Abc_CommandIFraig, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "dfraig", Abc_CommandDFraig, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "csweep", Abc_CommandCSweep, 1 ); // Cmd_CommandAdd( pAbc, "New AIG", "haig", Abc_CommandHaig, 1 ); Cmd_CommandAdd( pAbc, "New AIG", "qbf", Abc_CommandQbf, 0 ); Cmd_CommandAdd( pAbc, "Fraiging", "fraig", Abc_CommandFraig, 1 ); Cmd_CommandAdd( pAbc, "Fraiging", "fraig_trust", Abc_CommandFraigTrust, 1 ); Cmd_CommandAdd( pAbc, "Fraiging", "fraig_store", Abc_CommandFraigStore, 0 ); Cmd_CommandAdd( pAbc, "Fraiging", "fraig_restore", Abc_CommandFraigRestore, 1 ); Cmd_CommandAdd( pAbc, "Fraiging", "fraig_clean", Abc_CommandFraigClean, 0 ); Cmd_CommandAdd( pAbc, "Fraiging", "fraig_sweep", Abc_CommandFraigSweep, 1 ); Cmd_CommandAdd( pAbc, "Fraiging", "dress", Abc_CommandFraigDress, 1 ); Cmd_CommandAdd( pAbc, "Fraiging", "dump_equiv", Abc_CommandDumpEquiv, 0 ); Cmd_CommandAdd( pAbc, "Choicing", "rec_start3", Abc_CommandRecStart3, 0 ); Cmd_CommandAdd( pAbc, "Choicing", "rec_stop3", Abc_CommandRecStop3, 0 ); Cmd_CommandAdd( pAbc, "Choicing", "rec_ps3", Abc_CommandRecPs3, 0 ); Cmd_CommandAdd( pAbc, "Choicing", "rec_add3", Abc_CommandRecAdd3, 0 ); Cmd_CommandAdd( pAbc, "Choicing", "rec_dump3", Abc_CommandRecDump3, 0 ); Cmd_CommandAdd( pAbc, "Choicing", "rec_merge3", Abc_CommandRecMerge3, 0 ); Cmd_CommandAdd( pAbc, "SC mapping", "map", Abc_CommandMap, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "amap", Abc_CommandAmap, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "phase_map", Abc_CommandPhaseMap, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "stochmap", Abc_CommandStochMap, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "unmap", Abc_CommandUnmap, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "attach", Abc_CommandAttach, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "superc", Abc_CommandSuperChoice, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "supercl", Abc_CommandSuperChoiceLut, 1 ); Cmd_CommandAdd( pAbc, "SC mapping", "timescale", Abc_CommandTimeScale, 0 ); Cmd_CommandAdd( pAbc, "SC mapping", "rewire", Abc_CommandRewire, 1 ); // Cmd_CommandAdd( pAbc, "FPGA mapping", "fpga", Abc_CommandFpga, 1 ); // Cmd_CommandAdd( pAbc, "FPGA mapping", "ffpga", Abc_CommandFpgaFast, 1 ); Cmd_CommandAdd( pAbc, "FPGA mapping", "if", Abc_CommandIf, 1 ); Cmd_CommandAdd( pAbc, "FPGA mapping", "ifif", Abc_CommandIfif, 1 ); Cmd_CommandAdd( pAbc, "DSD manager", "dsd_save", Abc_CommandDsdSave, 0 ); Cmd_CommandAdd( pAbc, "DSD manager", "dsd_load", Abc_CommandDsdLoad, 0 ); Cmd_CommandAdd( pAbc, "DSD manager", "dsd_free", Abc_CommandDsdFree, 0 ); Cmd_CommandAdd( pAbc, "DSD manager", "dsd_ps", Abc_CommandDsdPs, 0 ); Cmd_CommandAdd( pAbc, "DSD manager", "dsd_match", Abc_CommandDsdMatch, 0 ); Cmd_CommandAdd( pAbc, "DSD manager", "dsd_merge", Abc_CommandDsdMerge, 0 ); Cmd_CommandAdd( pAbc, "DSD manager", "dsd_filter", Abc_CommandDsdFilter, 0 ); // Cmd_CommandAdd( pAbc, "Sequential", "scut", Abc_CommandScut, 0 ); Cmd_CommandAdd( pAbc, "Sequential", "init", Abc_CommandInit, 1 ); 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", "retime", Abc_CommandRetime, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "dretime", Abc_CommandDRetime, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "fretime", Abc_CommandFlowRetime, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "cretime", Abc_CommandCRetime, 1 ); // Cmd_CommandAdd( pAbc, "Sequential", "sfpga", Abc_CommandSeqFpga, 1 ); // Cmd_CommandAdd( pAbc, "Sequential", "smap", Abc_CommandSeqMap, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "ssweep", Abc_CommandSeqSweep, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "scorr", Abc_CommandSeqSweep2, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "testssw", Abc_CommandTestSeqSweep, 0 ); Cmd_CommandAdd( pAbc, "Sequential", "testscorr", Abc_CommandTestScorr, 0 ); Cmd_CommandAdd( pAbc, "Sequential", "lcorr", Abc_CommandLcorr, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "scleanup", Abc_CommandSeqCleanup, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "cycle", Abc_CommandCycle, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "xsim", Abc_CommandXsim, 0 ); Cmd_CommandAdd( pAbc, "Sequential", "sim", Abc_CommandSim, 0 ); Cmd_CommandAdd( pAbc, "Sequential", "sim3", Abc_CommandSim3, 0 ); Cmd_CommandAdd( pAbc, "Sequential", "phase", Abc_CommandDarPhase, 1 ); Cmd_CommandAdd( pAbc, "Sequential", "synch", Abc_CommandSynch, 1 ); 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", "atmap", Abc_CommandATMap, 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 ); Cmd_CommandAdd( pAbc, "Verification", "dsec", Abc_CommandDSec, 0 ); Cmd_CommandAdd( pAbc, "Verification", "dprove", Abc_CommandDProve, 0 ); Cmd_CommandAdd( pAbc, "Verification", "absec", Abc_CommandAbSec, 0 ); Cmd_CommandAdd( pAbc, "Verification", "simsec", Abc_CommandSimSec, 0 ); Cmd_CommandAdd( pAbc, "Verification", "match", Abc_CommandMatch, 0 ); Cmd_CommandAdd( pAbc, "Verification", "sat", Abc_CommandSat, 0 ); Cmd_CommandAdd( pAbc, "Verification", "dsat", Abc_CommandDSat, 0 ); Cmd_CommandAdd( pAbc, "Verification", "xsat", Abc_CommandXSat, 0 ); 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 ); Cmd_CommandAdd( pAbc, "Verification", "debug", Abc_CommandDebug, 0 ); Cmd_CommandAdd( pAbc, "Verification", "eco", Abc_CommandEco, 0 ); Cmd_CommandAdd( pAbc, "Verification", "bmc", Abc_CommandBmc, 0 ); Cmd_CommandAdd( pAbc, "Verification", "bmc2", Abc_CommandBmc2, 0 ); Cmd_CommandAdd( pAbc, "Verification", "bmc3", Abc_CommandBmc3, 1 ); Cmd_CommandAdd( pAbc, "Verification", "int", Abc_CommandBmcInter, 1 ); Cmd_CommandAdd( pAbc, "Verification", "indcut", Abc_CommandIndcut, 0 ); Cmd_CommandAdd( pAbc, "Verification", "enlarge", Abc_CommandEnlarge, 1 ); Cmd_CommandAdd( pAbc, "Verification", "tempor", Abc_CommandTempor, 1 ); Cmd_CommandAdd( pAbc, "Verification", "ind", Abc_CommandInduction, 0 ); Cmd_CommandAdd( pAbc, "Verification", "constr", Abc_CommandConstr, 0 ); Cmd_CommandAdd( pAbc, "Verification", "unfold", Abc_CommandUnfold, 1 ); Cmd_CommandAdd( pAbc, "Verification", "fold", Abc_CommandFold, 1 ); Cmd_CommandAdd( pAbc, "Verification", "unfold2", Abc_CommandUnfold2, 1 ); // jlong Cmd_CommandAdd( pAbc, "Verification", "fold2", Abc_CommandFold2, 1 ); // jlong Cmd_CommandAdd( pAbc, "Verification", "bm", Abc_CommandBm, 1 ); Cmd_CommandAdd( pAbc, "Verification", "bm2", Abc_CommandBm2, 1 ); Cmd_CommandAdd( pAbc, "Verification", "saucy3", Abc_CommandSaucy, 1 ); Cmd_CommandAdd( pAbc, "Verification", "testcex", Abc_CommandTestCex, 0 ); Cmd_CommandAdd( pAbc, "Verification", "pdr", Abc_CommandPdr, 0 ); #ifdef ABC_USE_CUDD Cmd_CommandAdd( pAbc, "Verification", "reconcile", Abc_CommandReconcile, 1 ); #endif Cmd_CommandAdd( pAbc, "Verification", "cexsave", Abc_CommandCexSave, 0 ); Cmd_CommandAdd( pAbc, "Verification", "cexload", Abc_CommandCexLoad, 0 ); Cmd_CommandAdd( pAbc, "Verification", "cexcut", Abc_CommandCexCut, 0 ); Cmd_CommandAdd( pAbc, "Verification", "cexmerge", Abc_CommandCexMerge, 0 ); // Cmd_CommandAdd( pAbc, "Verification", "cexmin", Abc_CommandCexMin, 0 ); Cmd_CommandAdd( pAbc, "Verification", "dualrail", Abc_CommandDualRail, 1 ); 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 ); Cmd_CommandAdd( pAbc, "ABC9", "&load", Abc_CommandAbc9Load, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&load2", Abc_CommandAbc9Load2, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&loadaig", Abc_CommandAbc9LoadAig, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&r", Abc_CommandAbc9Read, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&read", Abc_CommandAbc9Read, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&read_blif", Abc_CommandAbc9ReadBlif, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&read_cblif", Abc_CommandAbc9ReadCBlif, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&read_stg", Abc_CommandAbc9ReadStg, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&read_ver", Abc_CommandAbc9ReadVer, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&write_ver", Abc_CommandAbc9WriteVer, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&w", Abc_CommandAbc9Write, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&write", Abc_CommandAbc9Write, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&wlut", Abc_CommandAbc9WriteLut, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&ps", Abc_CommandAbc9Ps, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&pfan", Abc_CommandAbc9PFan, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&pms", Abc_CommandAbc9Pms, 0 ); 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 ); Cmd_CommandAdd( pAbc, "ABC9", "&show", Abc_CommandAbc9Show, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&setregnum", Abc_CommandAbc9SetRegNum, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&st", Abc_CommandAbc9Strash, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&topand", Abc_CommandAbc9Topand, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&add1hot", Abc_CommandAbc9Add1Hot, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cof", Abc_CommandAbc9Cof, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cofs", Abc_CommandAbc9Cofs, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&trim", Abc_CommandAbc9Trim, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&dfs", Abc_CommandAbc9Dfs, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sim", Abc_CommandAbc9Sim, 0 ); 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 ); Cmd_CommandAdd( pAbc, "ABC9", "&equiv2", Abc_CommandAbc9Equiv2, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&equiv3", Abc_CommandAbc9Equiv3, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&semi", Abc_CommandAbc9Semi, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "×", Abc_CommandAbc9Times, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&frames", Abc_CommandAbc9Frames, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&retime", Abc_CommandAbc9Retime, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&enable", Abc_CommandAbc9Enable, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&dc2", Abc_CommandAbc9Dc2, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&dsd", Abc_CommandAbc9Dsd, 0 ); 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 ); Cmd_CommandAdd( pAbc, "ABC9", "&synch2", Abc_CommandAbc9Synch2, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&false", Abc_CommandAbc9False, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&miter", Abc_CommandAbc9Miter, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&miter2", Abc_CommandAbc9Miter2, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&append", Abc_CommandAbc9Append, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&scl", Abc_CommandAbc9Scl, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&lcorr", Abc_CommandAbc9Lcorr, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&scorr", Abc_CommandAbc9Scorr, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&choice", Abc_CommandAbc9Choice, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sat", Abc_CommandAbc9Sat, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&satenum", Abc_CommandAbc9SatEnum, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&adv_sim_gen", Abc_CommandAbc9AdvGenSim, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&fraig", Abc_CommandAbc9Fraig, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&cfraig", Abc_CommandAbc9CFraig, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&srm", Abc_CommandAbc9Srm, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&srm2", Abc_CommandAbc9Srm2, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&filter", Abc_CommandAbc9Filter, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&reduce", Abc_CommandAbc9Reduce, 0 ); 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 ); Cmd_CommandAdd( pAbc, "ABC9", "&embed", Abc_CommandAbc9Embed, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sopb", Abc_CommandAbc9Sopb, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&dsdb", Abc_CommandAbc9Dsdb, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&flow", Abc_CommandAbc9Flow, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&flow2", Abc_CommandAbc9Flow2, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&flow3", Abc_CommandAbc9Flow3, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&if", Abc_CommandAbc9If, 0 ); 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 ); Cmd_CommandAdd( pAbc, "ABC9", "&mf", Abc_CommandAbc9Mf, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&nf", Abc_CommandAbc9Nf, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&of", Abc_CommandAbc9Of, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&simap", Abc_CommandAbc9Simap, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&exmap", Abc_CommandAbc9Exmap, 0 ); 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 ); Cmd_CommandAdd( pAbc, "ABC9", "&rrr", Abc_CommandAbc9Rrr, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&rewire" , Abc_CommandAbc9Rewire, 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 ); Cmd_CommandAdd( pAbc, "ABC9", "&speedup", Abc_CommandAbc9Speedup, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&era", Abc_CommandAbc9Era, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&dch", Abc_CommandAbc9Dch, 0 ); 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 ); Cmd_CommandAdd( pAbc, "ABC9", "&reachn", Abc_CommandAbc9ReachN, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&reachy", Abc_CommandAbc9ReachY, 0 ); #endif Cmd_CommandAdd( pAbc, "ABC9", "&undo", Abc_CommandAbc9Undo, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&mesh", Abc_CommandAbc9Mesh, 0 ); 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", "&store", Abc_CommandAbc9Store, 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 ); Cmd_CommandAdd( pAbc, "ABC9", "&slice", Abc_CommandAbc9Slice, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&popart", Abc_CommandAbc9PoPart, 0 ); 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", "&sprove", Abc_CommandAbc9SProve, 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 ); Cmd_CommandAdd( pAbc, "ABC9", "&bcore", Abc_CommandAbc9BCore, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&icheck", Abc_CommandAbc9ICheck, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&sattest", Abc_CommandAbc9SatTest, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&fftest", Abc_CommandAbc9FFTest, 0 ); 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 ); Cmd_CommandAdd( pAbc, "ABC9", "&maxi", Abc_CommandAbc9Maxi, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&bmci", Abc_CommandAbc9Bmci, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&poxsim", Abc_CommandAbc9PoXsim, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&demiter", Abc_CommandAbc9Demiter, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&fadds", Abc_CommandAbc9Fadds, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&atree", Abc_CommandAbc9ATree, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&polyn", Abc_CommandAbc9Polyn, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&acec", Abc_CommandAbc9Acec, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&anorm", Abc_CommandAbc9Anorm, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&decla", Abc_CommandAbc9Decla, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&esop", Abc_CommandAbc9Esop, 0 ); 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", "&randsyn", Abc_CommandAbc9RandSyn, 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 ); Cmd_CommandAdd( pAbc, "Abstraction", "&gla_refine", Abc_CommandAbc9GlaRefine, 0 ); Cmd_CommandAdd( pAbc, "Abstraction", "&gla_shrink", Abc_CommandAbc9GlaShrink, 0 ); Cmd_CommandAdd( pAbc, "Abstraction", "&gla", Abc_CommandAbc9Gla, 0 ); Cmd_CommandAdd( pAbc, "Abstraction", "&vta", Abc_CommandAbc9Vta, 0 ); Cmd_CommandAdd( pAbc, "Abstraction", "&vta_gla", Abc_CommandAbc9Vta2Gla, 0 ); Cmd_CommandAdd( pAbc, "Abstraction", "&gla_vta", Abc_CommandAbc9Gla2Vta, 0 ); Cmd_CommandAdd( pAbc, "Abstraction", "&fla_gla", Abc_CommandAbc9Fla2Gla, 0 ); Cmd_CommandAdd( pAbc, "Abstraction", "&gla_fla", Abc_CommandAbc9Gla2Fla, 0 ); Cmd_CommandAdd( pAbc, "Liveness", "l2s", Abc_CommandAbcLivenessToSafety, 0 ); Cmd_CommandAdd( pAbc, "Liveness", "l2ssim", Abc_CommandAbcLivenessToSafetySim, 0 ); Cmd_CommandAdd( pAbc, "Liveness", "l3s", Abc_CommandAbcLivenessToSafetyWithLTL, 0 ); 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", "&gen_hie", Abc_CommandAbc9GenHie, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&putontop", Abc_CommandAbc9PutOnTop, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&brecover", Abc_CommandAbc9BRecover, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&str_eco", Abc_CommandAbc9StrEco, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&gencex", Abc_CommandAbc9GenCex, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&odc", Abc_CommandAbc9Odc, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&genrel", Abc_CommandAbc9GenRel, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&genmux", Abc_CommandAbc9GenMux, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&gencomp", Abc_CommandAbc9GenComp, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&gensorter", Abc_CommandAbc9GenSorter, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&genneuron", Abc_CommandAbc9GenNeuron, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&window", Abc_CommandAbc9Window, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&funabs", Abc_CommandAbc9FunAbs, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&dsdinfo", Abc_CommandAbc9DsdInfo, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&funtrace", Abc_CommandAbc9FunTrace, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&mulfind", Abc_CommandAbc9MulFind, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); Cmd_CommandAdd( pAbc, "ABC9", "&eslim", Abc_CommandAbc9eSLIM, 0 ); { // extern Mf_ManTruthCount(); // Mf_ManTruthCount(); } { extern void Dar_LibStart(); Dar_LibStart(); } { // extern void Dau_DsdTest(); // Dau_DsdTest(); // extern void If_ManSatTest(); // If_ManSatTest(); } // if ( Sdm_ManCanRead() ) // Sdm_ManRead(); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_End( Abc_Frame_t * pAbc ) { extern Abc_Frame_t * Abc_FrameGetGlobalFrame(); Abc_FrameClearDesign(); Cnf_ManFree(); { extern int Abc_NtkCompareAndSaveBest( Abc_Ntk_t * pNtk ); Abc_NtkCompareAndSaveBest( NULL ); } { extern void Dar_LibStop(); Dar_LibStop(); } { extern void Aig_RManQuit(); Aig_RManQuit(); } { extern void Npn_ManClean(); Npn_ManClean(); } { extern void Sdm_ManQuit(); Sdm_ManQuit(); } Abc_NtkFraigStoreClean(); Gia_ManStopP( &pAbc->pGia ); Gia_ManStopP( &pAbc->pGia2 ); Gia_ManStopP( &pAbc->pGiaBest ); Gia_ManStopP( &pAbc->pGiaBest2 ); Gia_ManStopP( &pAbc->pGiaSaved ); if ( Abc_NtkRecIsRunning3() ) Abc_NtkRecStop3(); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int fFactor; int fSaveBest; int fDumpResult; int fUseLutLib; int fPrintTime; int fPrintMuxes; int fPower; int fGlitch; int fSkipBuf; int fSkipSmall; int fPrintMem; int c; pNtk = Abc_FrameReadNtk(pAbc); // set the defaults fFactor = 0; fSaveBest = 0; fDumpResult = 0; fUseLutLib = 0; fPrintTime = 0; fPrintMuxes = 0; fPower = 0; fGlitch = 0; fSkipBuf = 0; fSkipSmall = 0; fPrintMem = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "fbdltmpgscuh" ) ) != EOF ) { switch ( c ) { case 'f': fFactor ^= 1; break; case 'b': fSaveBest ^= 1; break; case 'd': fDumpResult ^= 1; break; case 'l': fUseLutLib ^= 1; break; case 't': fPrintTime ^= 1; break; case 'm': fPrintMuxes ^= 1; break; case 'p': fPower ^= 1; break; case 'g': fGlitch ^= 1; break; case 's': fSkipBuf ^= 1; break; case 'c': fSkipSmall ^= 1; break; case 'u': fPrintMem ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsLogic(pNtk) && fUseLutLib ) { Abc_Print( -1, "Cannot print LUT delay for a non-logic network.\n" ); return 1; } Abc_NtkPrintStats( pNtk, fFactor, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fSkipSmall, fPrintMem ); if ( fPrintTime ) { pAbc->TimeTotal += pAbc->TimeCommand; Abc_Print( 1, "elapse: %3.2f seconds, total: %3.2f seconds\n", pAbc->TimeCommand, pAbc->TimeTotal ); pAbc->TimeCommand = 0.0; } return 0; usage: Abc_Print( -2, "usage: print_stats [-fbdltmpgscuh]\n" ); Abc_Print( -2, "\t prints the network statistics\n" ); Abc_Print( -2, "\t-f : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" ); Abc_Print( -2, "\t-b : toggles saving the best logic network in \"best.blif\" [default = %s]\n", fSaveBest? "yes": "no" ); Abc_Print( -2, "\t-d : toggles dumping statistics about the network into file [default = %s]\n", fDumpResult? "yes": "no" ); Abc_Print( -2, "\t-l : toggles printing delay of LUT mapping using LUT library [default = %s]\n", fUseLutLib? "yes": "no" ); Abc_Print( -2, "\t-t : toggles printing runtime statistics [default = %s]\n", fPrintTime? "yes": "no" ); Abc_Print( -2, "\t-m : toggles printing MUX statistics [default = %s]\n", fPrintMuxes? "yes": "no" ); Abc_Print( -2, "\t-p : toggles printing power dissipation due to switching [default = %s]\n", fPower? "yes": "no" ); Abc_Print( -2, "\t-g : toggles printing percentage of increased power due to glitching [default = %s]\n", fGlitch? "yes": "no" ); Abc_Print( -2, "\t-s : toggles not counting single-output nodes as nodes [default = %s]\n", fSkipBuf? "yes": "no" ); Abc_Print( -2, "\t-c : toggles not counting constants and single-output nodes as nodes [default = %s]\n", fSkipSmall? "yes": "no" ); Abc_Print( -2, "\t-u : toggles printing memory usage [default = %s]\n", fPrintMem? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintExdc( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkTemp; double Percentage; int fShort; int c; int fPrintDc; extern double Abc_NtkSpacePercentage( Abc_Obj_t * pNode ); pNtk = Abc_FrameReadNtk(pAbc); // set the defaults fShort = 1; fPrintDc = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "sdh" ) ) != EOF ) { switch ( c ) { case 's': fShort ^= 1; break; case 'd': fPrintDc ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( pNtk->pExdc == NULL ) { Abc_Print( -1, "Network has no EXDC.\n" ); return 1; } if ( fPrintDc ) { if ( !Abc_NtkIsStrash(pNtk->pExdc) ) { pNtkTemp = Abc_NtkStrash(pNtk->pExdc, 0, 0, 0); Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtkTemp, 0) ) ); Abc_NtkDelete( pNtkTemp ); } else Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtk->pExdc, 0) ) ); Abc_Print( 1, "EXDC network statistics: " ); Abc_Print( 1, "(" ); if ( Percentage > 0.05 && Percentage < 99.95 ) Abc_Print( 1, "%.2f", Percentage ); else if ( Percentage > 0.000005 && Percentage < 99.999995 ) Abc_Print( 1, "%.6f", Percentage ); else Abc_Print( 1, "%f", Percentage ); Abc_Print( 1, " %% don't-cares)\n" ); } else Abc_Print( 1, "EXDC network statistics: \n" ); Abc_NtkPrintStats( pNtk->pExdc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); return 0; usage: Abc_Print( -2, "usage: print_exdc [-dh]\n" ); Abc_Print( -2, "\t prints the EXDC network statistics\n" ); Abc_Print( -2, "\t-d : toggles printing don't-care percentage [default = %s]\n", fPrintDc? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pNode; int c, fPrintFlops = 1; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "fh" ) ) != EOF ) { switch ( c ) { case 'f': fPrintFlops ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( argc > globalUtilOptind + 1 ) { Abc_Print( -1, "Wrong number of auguments.\n" ); goto usage; } if ( argc == globalUtilOptind + 1 ) { pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } Abc_NodePrintFanio( stdout, pNode ); return 0; } // print the nodes Abc_NtkPrintIo( stdout, pNtk, fPrintFlops ); return 0; usage: Abc_Print( -2, "usage: print_io [-fh] \n" ); Abc_Print( -2, "\t prints the PIs/POs/flops or fanins/fanouts of a node\n" ); Abc_Print( -2, "\t-f : toggles printing flops [default = %s]\n", fPrintFlops? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tnode : the node to print fanins/fanouts\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintLatch( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fPrintSccs; extern void Abc_NtkPrintSccs( Abc_Ntk_t * pNtk, int fVerbose ); // set defaults fPrintSccs = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF ) { switch ( c ) { case 's': fPrintSccs ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } // print the nodes Abc_NtkPrintLatch( stdout, pNtk ); if ( fPrintSccs ) Abc_NtkPrintSccs( pNtk, 0 ); return 0; usage: Abc_Print( -2, "usage: print_latch [-sh]\n" ); Abc_Print( -2, "\t prints information about latches\n" ); Abc_Print( -2, "\t-s : toggles printing SCCs of registers [default = %s]\n", fPrintSccs? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintFanio( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fUseFanio = 0; int fUsePio = 0; int fUseSupp = 0; int fUseCone = 0; int fMffc = 0; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "fiscmvh" ) ) != EOF ) { switch ( c ) { case 'f': fUseFanio ^= 1; break; case 'i': fUsePio ^= 1; break; case 's': fUseSupp ^= 1; break; case 'c': fUseCone ^= 1; break; case 'm': fMffc ^= 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; } // print the nodes if ( fMffc || !fVerbose ) Abc_NtkPrintFanioNew( stdout, pNtk, fMffc ); else { if ( fUseFanio + fUsePio + fUseSupp + fUseCone == 1 ) Abc_NtkPrintFanio( stdout, pNtk, fUseFanio, fUsePio, fUseSupp, fUseCone ); else printf( "Exactly one of the switches \"-f\", \"-i\", \"-s\", \"-c\" should be enabled.\n" ); } return 0; usage: Abc_Print( -2, "usage: print_fanio [-fiscmvh]\n" ); Abc_Print( -2, "\t prints the statistics about different objects in the network\n" ); Abc_Print( -2, "\t-f : toggles considering fanins/fanouts of all nodes [default = %s]\n", fUseFanio? "yes": "no" ); Abc_Print( -2, "\t-i : toggles considering fanins/fanouts of CI/CO [default = %s]\n", fUsePio? "yes": "no" ); Abc_Print( -2, "\t-s : toggles considering TFO/TFI support sizes of CI/CO [default = %s]\n", fUseSupp? "yes": "no" ); Abc_Print( -2, "\t-c : toggles considering TFO/TFI cone sizes of CI/CO [default = %s]\n", fUseCone? "yes": "no" ); Abc_Print( -2, "\t-m : toggles printing MFFC sizes instead of fanouts [default = %s]\n", fMffc? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose way of printing the stats [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_CommandPrintMffc( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; extern void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk ); // 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; } // print the nodes Abc_NtkPrintMffc( stdout, pNtk ); return 0; usage: Abc_Print( -2, "usage: print_mffc [-h]\n" ); Abc_Print( -2, "\t prints the MFFC of each node in the network\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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, fSop = 0; int fUseRealNames; // set defaults fUseRealNames = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "snh" ) ) != EOF ) { switch ( c ) { case 's': fSop ^= 1; break; case 'n': fUseRealNames ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsSopLogic(pNtk) ) { Abc_Print( -1, "Printing factored forms can be done for SOP networks.\n" ); return 1; } if ( argc > globalUtilOptind + 1 ) { Abc_Print( -1, "Wrong number of auguments.\n" ); goto usage; } if ( argc == globalUtilOptind + 1 ) { pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } if ( fSop ) Abc_NodePrintSop( stdout, pNode, fUseRealNames ); else Abc_NodePrintFactor( stdout, pNode, fUseRealNames ); return 0; } // print the nodes if ( fSop ) Abc_NtkPrintSop( stdout, pNtk, fUseRealNames ); else Abc_NtkPrintFactor( stdout, pNtk, fUseRealNames ); return 0; usage: 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"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pNode; int c; int fListNodes; int fProfile; int fOutputs; int fVerbose; // set defaults fListNodes = 0; fProfile = 1; fOutputs = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "npovh" ) ) != EOF ) { switch ( c ) { case 'n': fListNodes ^= 1; break; case 'p': fProfile ^= 1; break; case 'o': fOutputs ^= 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 ( !fProfile && !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for AIGs (run \"strash\").\n" ); return 1; } if ( argc > globalUtilOptind + 1 ) { Abc_Print( -1, "Wrong number of auguments.\n" ); goto usage; } if ( argc == globalUtilOptind + 1 ) { pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } Abc_NodePrintLevel( stdout, pNode ); return 0; } // process all COs Abc_NtkPrintLevel( stdout, pNtk, fProfile, fListNodes, fOutputs, fVerbose ); return 0; usage: Abc_Print( -2, "usage: print_level [-npovh] \n" ); Abc_Print( -2, "\t prints information about node level and cone size\n" ); Abc_Print( -2, "\t-n : toggles printing nodes by levels [default = %s]\n", fListNodes? "yes": "no" ); Abc_Print( -2, "\t-p : toggles printing level profile [default = %s]\n", fProfile? "yes": "no" ); Abc_Print( -2, "\t-o : toggles printing output levels [default = %s]\n", fOutputs? "yes": "no" ); Abc_Print( -2, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tnode : (optional) one node to consider\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv ) { Vec_Ptr_t * vSuppFun; Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fStruct; int fVerbose; int fVeryVerbose; extern Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose ); extern void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk, int fMatrix ); // set defaults fStruct = 1; fVerbose = 0; fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "svwh" ) ) != EOF ) { switch ( c ) { case 's': fStruct ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } // print support information if ( fStruct ) { Abc_NtkPrintStrSupports( pNtk, fVeryVerbose ); return 0; } if ( !Abc_NtkIsComb(pNtk) ) { Abc_Print( -1, "This command works only for combinational networks (run \"comb\").\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for AIGs (run \"strash\").\n" ); return 1; } vSuppFun = Sim_ComputeFunSupp( pNtk, fVerbose ); ABC_FREE( vSuppFun->pArray[0] ); Vec_PtrFree( vSuppFun ); return 0; usage: Abc_Print( -2, "usage: print_supp [-svwh]\n" ); Abc_Print( -2, "\t prints the supports of the CO nodes\n" ); Abc_Print( -2, "\t-s : toggle printing structural support only [default = %s].\n", fStruct? "yes": "no" ); Abc_Print( -2, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : enable printing CI/CO dependency matrix [default = %s].\n", fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); 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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fUseBdds; int fNaive; int fReorder; int fVerbose; extern void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose ); // set defaults fUseBdds = 0; fNaive = 0; fReorder = 1; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "bnrvh" ) ) != EOF ) { switch ( c ) { case 'b': fUseBdds ^= 1; break; case 'n': fNaive ^= 1; break; case 'r': fReorder ^= 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_NtkIsComb(pNtk) ) { Abc_Print( -1, "This command works only for combinational networks (run \"comb\").\n" ); return 1; } if ( Abc_NtkIsStrash(pNtk) ) Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose ); else { pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose ); Abc_NtkDelete( pNtk ); } return 0; usage: Abc_Print( -2, "usage: print_symm [-bnrvh]\n" ); Abc_Print( -2, "\t computes symmetries of the PO functions\n" ); Abc_Print( -2, "\t-b : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" ); Abc_Print( -2, "\t-n : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" ); Abc_Print( -2, "\t-r : enable dynamic BDD variable reordering [default = %s].\n", fReorder? "yes": "no" ); 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; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintUnate( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fUseBdds; int fUseNaive; int fVerbose; extern void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose ); // set defaults fUseBdds = 1; fUseNaive = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "bnvh" ) ) != EOF ) { switch ( c ) { case 'b': fUseBdds ^= 1; break; case 'n': fUseNaive ^= 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for AIGs (run \"strash\").\n" ); return 1; } Abc_NtkPrintUnate( pNtk, fUseBdds, fUseNaive, fVerbose ); return 0; usage: Abc_Print( -2, "usage: print_unate [-bnvh]\n" ); Abc_Print( -2, "\t computes unate variables of the PO functions\n" ); Abc_Print( -2, "\t-b : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" ); Abc_Print( -2, "\t-n : toggle naive BDD-based computation [default = %s].\n", fUseNaive? "yes": "no" ); 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; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintAuto( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int Output; int fNaive; int fVerbose; extern void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose ); // set defaults Output = -1; fNaive = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Onvh" ) ) != EOF ) { switch ( c ) { case 'O': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); goto usage; } Output = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( Output < 0 ) goto usage; break; case 'n': fNaive ^= 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for AIGs (run \"strash\").\n" ); return 1; } Abc_NtkAutoPrint( pNtk, Output, fNaive, fVerbose ); return 0; usage: Abc_Print( -2, "usage: print_auto [-O ] [-nvh]\n" ); Abc_Print( -2, "\t computes autosymmetries of the PO functions\n" ); Abc_Print( -2, "\t-O : (optional) the 0-based number of the output [default = all]\n"); Abc_Print( -2, "\t-n : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" ); 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; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pNode; int c; int fUseRealNames; extern void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames ); // set defaults fUseRealNames = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) { switch ( c ) { case 'n': fUseRealNames ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc == globalUtilOptind + 2 ) { Abc_NtkShow6VarFunc( argv[globalUtilOptind], argv[globalUtilOptind+1] ); return 0; } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "Visualization of Karnaugh maps works for logic networks.\n" ); return 1; } if ( argc > globalUtilOptind + 1 ) { Abc_Print( -1, "Wrong number of auguments.\n" ); goto usage; } if ( argc == globalUtilOptind ) { pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); if ( !Abc_ObjIsNode(pNode) ) { Abc_Print( -1, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) ); return 1; } } else { pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } } Abc_NtkToBdd(pNtk); Abc_NodePrintKMap( pNode, fUseRealNames ); return 0; usage: Abc_Print( -2, "usage: print_kmap [-nh] \n" ); Abc_Print( -2, "\t shows the truth table of the node\n" ); 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, "\t: the node to consider (default = the driver of the first PO)\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintGates( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fUseLibrary; int fUpdateProfile; extern void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary, int fUpdateProfile ); // set defaults fUseLibrary = 1; fUpdateProfile = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "luh" ) ) != EOF ) { switch ( c ) { case 'l': fUseLibrary ^= 1; break; case 'u': fUpdateProfile ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Abc_NtkHasAig(pNtk) ) { Abc_Print( -1, "Printing gates does not work for AIGs and sequential AIGs.\n" ); return 1; } Abc_NtkPrintGates( pNtk, fUseLibrary, fUpdateProfile ); return 0; usage: Abc_Print( -2, "usage: print_gates [-luh]\n" ); Abc_Print( -2, "\t prints statistics about gates used in the network\n" ); Abc_Print( -2, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); Abc_Print( -2, "\t-u : update profile before printing it[default = %s]\n", fUpdateProfile? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintSharing( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fUseLibrary; extern void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk ); // set defaults fUseLibrary = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) { switch ( c ) { case 'l': fUseLibrary ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } Abc_NtkPrintSharing( pNtk ); return 0; usage: Abc_Print( -2, "usage: print_sharing [-h]\n" ); Abc_Print( -2, "\t prints the number of shared nodes in the TFI cones of the COs\n" ); // Abc_Print( -2, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintXCut( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fUseLibrary; extern int Abc_NtkCrossCut( Abc_Ntk_t * pNtk ); // set defaults fUseLibrary = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) { switch ( c ) { case 'l': fUseLibrary ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } Abc_NtkCrossCut( pNtk ); return 0; usage: Abc_Print( -2, "usage: print_xcut [-h]\n" ); Abc_Print( -2, "\t prints the size of the cross cut of the current network\n" ); // Abc_Print( -2, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintDsd( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fCofactor; int nCofLevel; int fProfile; int fPrintDec; extern void Kit_DsdTest( unsigned * pTruth, int nVars ); extern void Kit_DsdPrintCofactors( unsigned * pTruth, int nVars, int nCofLevel, int fVerbose ); extern void Dau_DecTrySets( word * p, int nVars, int fVerbose ); // set defaults nCofLevel = 1; fCofactor = 0; fProfile = 0; fPrintDec = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Npcdh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } nCofLevel = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCofLevel < 0 ) goto usage; break; case 'p': fProfile ^= 1; break; case 'c': fCofactor ^= 1; break; case 'd': fPrintDec ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } // get the truth table of the first output if ( !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "Currently works only for logic networks.\n" ); return 1; } Abc_NtkToAig( pNtk ); // convert it to truth table { Abc_Obj_t * pObj = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); Vec_Int_t * vMemory; unsigned * pTruth; if ( !Abc_ObjIsNode(pObj) ) { Abc_Print( -1, "The fanin of the first PO node does not have a logic function.\n" ); return 1; } if ( Abc_ObjFaninNum(pObj) > 16 ) { Abc_Print( -1, "Currently works only for up to 16 inputs.\n" ); return 1; } vMemory = Vec_IntAlloc(0); pTruth = Hop_ManConvertAigToTruth( (Hop_Man_t *)pNtk->pManFunc, Hop_Regular((Hop_Obj_t *)pObj->pData), Abc_ObjFaninNum(pObj), vMemory, 0 ); if ( Hop_IsComplement((Hop_Obj_t *)pObj->pData) ) Extra_TruthNot( pTruth, pTruth, Abc_ObjFaninNum(pObj) ); // Extra_PrintBinary( stdout, pTruth, 1 << Abc_ObjFaninNum(pObj) ); // Abc_Print( -1, "\n" ); if ( fPrintDec )//&&Abc_ObjFaninNum(pObj) <= 6 ) { word * pTruthW = (word *)pTruth; if ( Abc_ObjFaninNum(pObj) < 6 ) pTruthW[0] = Abc_Tt6Stretch( pTruthW[0], Abc_ObjFaninNum(pObj) ); Dau_DecTrySets( (word *)pTruth, Abc_ObjFaninNum(pObj), 1 ); } if ( fProfile ) Kit_TruthPrintProfile( pTruth, Abc_ObjFaninNum(pObj) ); else if ( fCofactor ) Kit_DsdPrintCofactors( pTruth, Abc_ObjFaninNum(pObj), nCofLevel, 1 ); else Kit_DsdTest( pTruth, Abc_ObjFaninNum(pObj) ); Vec_IntFree( vMemory ); } return 0; usage: Abc_Print( -2, "usage: print_dsd [-pcdh] [-N ]\n" ); Abc_Print( -2, "\t print DSD formula for a single-output function with less than 16 variables\n" ); Abc_Print( -2, "\t-p : toggle printing profile [default = %s]\n", fProfile? "yes": "no" ); Abc_Print( -2, "\t-c : toggle recursive cofactoring [default = %s]\n", fCofactor? "yes": "no" ); Abc_Print( -2, "\t-d : toggle printing decompositions [default = %s]\n", fPrintDec? "yes": "no" ); Abc_Print( -2, "\t-N : the number of levels to cofactor [default = %d]\n", nCofLevel ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintCone( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fUseLibrary; // set defaults fUseLibrary = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) { switch ( c ) { case 'l': fUseLibrary ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Abc_NtkLatchNum(pNtk) == 0 ) { Abc_Print( -1, "The network is combinational.\n" ); return 1; } Abc_NtkDarPrintCone( pNtk ); return 0; usage: Abc_Print( -2, "usage: print_cone [-h]\n" ); Abc_Print( -2, "\t prints cones of influence info for each primary output\n" ); // Abc_Print( -2, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fUseLibrary; extern void Abc_NtkPrintMiter( Abc_Ntk_t * pNtk ); // set defaults fUseLibrary = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) { switch ( c ) { case 'l': fUseLibrary ^= 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, "The network is should be structurally hashed.\n" ); return 1; } Abc_NtkPrintMiter( pNtk ); return 0; usage: Abc_Print( -2, "usage: print_miter [-h]\n" ); Abc_Print( -2, "\t prints the status of the miter\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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, "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; case 's': fShort ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( fOutStatus ) { if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } Abc_NtkPrintPoEquivs( pNtk ); return 0; } 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 { if ( pAbc->pCex ) Abc_CexPrintStats( pAbc->pCex ); if ( pAbc->vCexVec ) { Abc_Cex_t * pTemp; int nCexes = 0; int Counter = 0; //printf( "\n" ); Vec_PtrForEachEntry( Abc_Cex_t *, pAbc->vCexVec, pTemp, c ) { if ( pTemp == (void *)(ABC_PTRINT_T)1 ) { Counter++; continue; } if ( pTemp ) { printf( "%4d : ", ++nCexes ); 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 ( pAbc->vStatuses ) { 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), Vec_IntCountEntry(pAbc->vStatuses, -1), Vec_IntSize(pAbc->vStatuses) ); } else { int i, Entry; Vec_IntForEachEntry( pAbc->vStatuses, Entry, i ) printf( "%d=%d ", i, Entry ); } printf( "\n" ); } return 0; usage: 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; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPrintDelay( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pObjIn = NULL, * pObjOut = NULL; int c; // 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_NtkIsMappedLogic(pNtk) ) { Abc_Print( -1, "Delay trace works only for network mapped into standard cells.\n" ); return 1; } if ( argc > globalUtilOptind + 2 ) { Abc_Print( -1, "Wrong number of auguments.\n" ); goto usage; } // collect the first name (PO name) if ( argc >= globalUtilOptind + 1 ) { int Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind], ABC_OBJ_PO ); if ( Num < 0 ) Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind], ABC_OBJ_BI ); if ( Num >= 0 ) pObjOut = Abc_NtkObj( pNtk, Num ); if ( pObjOut == NULL ) { Abc_Print( 1, "Cannot find combinational output \"%s\".\n", argv[globalUtilOptind] ); return 1; } } // collect the second name (PI name) if ( argc == globalUtilOptind + 2 ) { int Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind+1], ABC_OBJ_PI ); if ( Num < 0 ) Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind+1], ABC_OBJ_BO ); if ( Num >= 0 ) pObjIn = Abc_NtkObj( pNtk, Num ); if ( pObjIn == NULL ) { Abc_Print( 1, "Cannot find combinational input \"%s\".\n", argv[globalUtilOptind+1] ); return 1; } } Abc_NtkDelayTrace( pNtk, pObjOut, pObjIn, 1 ); return 0; usage: Abc_Print( -2, "usage: print_delay [-h] \n" ); Abc_Print( -2, "\t prints one critical path of the mapped network\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : (optional) the sink of the critical path (primary output or flop input)\n"); Abc_Print( -2, "\t : (optional) the source of the critical path (primary input or flop output)\n"); Abc_Print( -2, "\t (if CO and/or CI are not given, uses the most critical ones)\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fSeq; int fGateNames; int fUseReverse; int fFlopDep; int fKeepDot; int fAigIds; extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse, int fKeepDot, int fAigIds ); extern void Abc_NtkShowFlopDependency( Abc_Ntk_t * pNtk ); // set defaults fSeq = 0; fGateNames = 0; fUseReverse = 1; fFlopDep = 0; fKeepDot = 0; fAigIds = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "rsgfdih" ) ) != EOF ) { switch ( c ) { case 'r': fUseReverse ^= 1; break; case 's': fSeq ^= 1; break; case 'g': fGateNames ^= 1; break; case 'f': fFlopDep ^= 1; break; case 'd': fKeepDot ^= 1; break; case 'i': fAigIds ^= 1; break; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( fFlopDep ) Abc_NtkShowFlopDependency( pNtk ); else Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse, fKeepDot, fAigIds ); return 0; usage: Abc_Print( -2, "usage: show [-srgfdih]\n" ); Abc_Print( -2, " visualizes the network structure using DOT and GSVIEW\n" ); #ifdef WIN32 Abc_Print( -2, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); Abc_Print( -2, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); #endif Abc_Print( -2, "\t-s : toggles visualization of sequential networks [default = %s].\n", fSeq? "yes": "no" ); 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-i : toggles using original AIG object IDs as node labels [default = %s].\n", fAigIds? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pNode; int c, fCompl = 0, fGlobal = 0, fReorder = 1, fWidth = 0; extern void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ); extern void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl, int fReorder ); extern void Abc_NtkBddDecExplore( Abc_Obj_t * pNode ); // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "cgrwh" ) ) != EOF ) { switch ( c ) { case 'c': fCompl ^= 1; break; case 'g': fGlobal ^= 1; break; case 'r': fReorder ^= 1; break; case 'w': fWidth ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); 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" ); goto usage; } if ( argc == globalUtilOptind ) { pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); if ( !Abc_ObjIsNode(pNode) ) { Abc_Print( -1, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) ); return 1; } } else { pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } } if ( fWidth ) Abc_NtkBddDecExplore( pNode ); else Abc_NodeShowBdd( pNode, fCompl ); return 0; usage: Abc_Print( -2, "usage: show_bdd [-cgrwh] \n" ); Abc_Print( -2, " uses DOT and GSVIEW to visualize the global BDDs of primary outputs\n" ); Abc_Print( -2, " in terms of primary inputs or the local BDD of a node in terms of its fanins\n" ); #ifdef WIN32 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: (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-w : toggles printing width profile of the node's BDD [default = %s]\n", fWidth? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pNode; int c; int nNodeSizeMax; int nConeSizeMax; extern void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ); // set defaults nNodeSizeMax = 10; nConeSizeMax = ABC_INFINITY; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NCh" ) ) != 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 '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 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Visualizing cuts only works for AIGs (run \"strash\").\n" ); return 1; } if ( argc != globalUtilOptind + 1 ) { Abc_Print( -1, "Wrong number of auguments.\n" ); goto usage; } pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax ); return 0; usage: Abc_Print( -2, "usage: show_cut [-N ] [-C ] [-h] \n" ); Abc_Print( -2, " visualizes the cut of a node using DOT and GSVIEW\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-N : the max size of the cut to be computed [default = %d]\n", nNodeSizeMax ); Abc_Print( -2, "\t-C : the max support of the containing cone [default = %d]\n", nConeSizeMax ); Abc_Print( -2, "\t : the node to consider\n"); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int fVerbose; 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, "BLrodxvh" ) ) != EOF ) { switch ( c ) { case 'B': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); goto usage; } fBddSizeMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( fBddSizeMax < 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': fReorder ^= 1; break; case 'o': fReverse ^= 1; break; 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; 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_NtkCollapseSat( pNtk, nCubeLim, nBTLimit, nCostMax, fCanon, fReverse, fCnfShared, fVerbose ); else { pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); pNtkRes = Abc_NtkCollapseSat( pNtk, nCubeLim, nBTLimit, nCostMax, fCanon, fReverse, fCnfShared, fVerbose ); Abc_NtkDelete( pNtk ); } if ( pNtkRes == NULL ) { Abc_Print( -1, "Collapsing has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: satclp [-CLZ num] [-crsvh]\n" ); Abc_Print( -2, "\t performs SAT based collapsing\n" ); Abc_Print( -2, "\t-C num : the limit on the SOP size of one output [default = %d]\n", nCubeLim ); Abc_Print( -2, "\t-L num : the limit on the number of conflicts in one SAT call [default = %d]\n", nBTLimit ); Abc_Print( -2, "\t-Z num : the limit on the cost of the largest output [default = %d]\n", nCostMax ); Abc_Print( -2, "\t-c : toggles using canonical ISOP computation [default = %s]\n", fCanon? "yes": "no" ); Abc_Print( -2, "\t-r : toggles using reverse veriable ordering [default = %s]\n", fReverse? "yes": "no" ); Abc_Print( -2, "\t-s : toggles shared CNF computation (non-canonical only) [default = %s]\n", fCnfShared? "yes": "no" ); Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; Abc_Obj_t * pObj; int c; int fAllNodes; int fRecord; int fCleanup; int fComplOuts; pNtk = Abc_FrameReadNtk(pAbc); // set defaults fAllNodes = 0; fCleanup = 1; fRecord = 0; fComplOuts= 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "acrih" ) ) != EOF ) { switch ( c ) { case 'a': fAllNodes ^= 1; break; case 'c': fCleanup ^= 1; break; case 'r': fRecord ^= 1; break; case 'i': fComplOuts ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } // get the new network pNtkRes = Abc_NtkStrash( pNtk, fAllNodes, fCleanup, fRecord ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Strashing has failed.\n" ); return 1; } if ( fComplOuts ) Abc_NtkForEachPo( pNtkRes, pObj, c ) Abc_ObjXorFaninC( pObj, 0 ); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: strash [-acrih]\n" ); Abc_Print( -2, "\t transforms combinational logic into an AIG\n" ); Abc_Print( -2, "\t-a : toggles between using all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "DFS" ); Abc_Print( -2, "\t-c : toggles cleanup to remove the dangling AIG nodes [default = %s]\n", fCleanup? "all": "DFS" ); Abc_Print( -2, "\t-r : toggles using the record of AIG subgraphs [default = %s]\n", fRecord? "yes": "no" ); Abc_Print( -2, "\t-i : toggles complementing the POs of the AIG [default = %s]\n", fComplOuts? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp; int c; int fDuplicate; int fSelective; int fUpdateLevel; int fExor; int fVerbose; pNtk = Abc_FrameReadNtk(pAbc); // set defaults fDuplicate = 0; fSelective = 0; fUpdateLevel = 1; fExor = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ldsxvh" ) ) != EOF ) { switch ( c ) { case 'l': fUpdateLevel ^= 1; break; case 'd': fDuplicate ^= 1; break; case 's': fSelective ^= 1; break; case 'x': fExor ^= 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; } // get the new network if ( Abc_NtkIsStrash(pNtk) ) { if ( fExor ) pNtkRes = Abc_NtkBalanceExor( pNtk, fUpdateLevel, fVerbose ); else pNtkRes = Abc_NtkBalance( pNtk, fDuplicate, fSelective, fUpdateLevel ); } else { pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); if ( pNtkTemp == NULL ) { Abc_Print( -1, "Strashing before balancing has failed.\n" ); return 1; } if ( fExor ) pNtkRes = Abc_NtkBalanceExor( pNtkTemp, fUpdateLevel, fVerbose ); else pNtkRes = Abc_NtkBalance( pNtkTemp, fDuplicate, fSelective, fUpdateLevel ); Abc_NtkDelete( pNtkTemp ); } // check if balancing worked if ( pNtkRes == NULL ) { Abc_Print( -1, "Balancing has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: balance [-ldsxvh]\n" ); Abc_Print( -2, "\t transforms the current network into a well-balanced AIG\n" ); Abc_Print( -2, "\t-l : toggle minimizing the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); Abc_Print( -2, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); Abc_Print( -2, "\t-s : toggle duplication on the critical paths [default = %s]\n", fSelective? "yes": "no" ); Abc_Print( -2, "\t-x : toggle balancing multi-input EXORs [default = %s]\n", fExor? "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_CommandMuxStruct( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; int fVerbose; extern Abc_Ntk_t * Abc_NtkMuxRestructure( Abc_Ntk_t * pNtk, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults 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 ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } // get the new network if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Does not work for a logic network.\n" ); return 1; } // check if balancing worked // pNtkRes = Abc_NtkMuxRestructure( pNtk, fVerbose ); pNtkRes = NULL; if ( pNtkRes == NULL ) { Abc_Print( -1, "MUX restructuring has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: mux_struct [-vh]\n" ); Abc_Print( -2, "\t performs MUX restructuring of the current network\n" ); 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_CommandMulti( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int nThresh, nFaninMax, c; int fCnf; int fMulti; int fSimple; int fFactor; extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nThresh = 1; nFaninMax = 20; fCnf = 0; fMulti = 1; fSimple = 0; fFactor = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "TFmcsfh" ) ) != EOF ) { switch ( c ) { case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); goto usage; } nThresh = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nThresh < 0 ) goto usage; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nFaninMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFaninMax < 0 ) goto usage; break; case 'c': fCnf ^= 1; break; case 'm': fMulti ^= 1; break; case 's': fSimple ^= 1; break; case 'f': fFactor ^= 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, "Cannot renode a network that is not an AIG (run \"strash\").\n" ); return 1; } // get the new network pNtkRes = Abc_NtkMulti( pNtk, nThresh, nFaninMax, fCnf, fMulti, fSimple, fFactor ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Renoding has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: multi [-TF ] [-msfch]\n" ); Abc_Print( -2, "\t transforms an AIG into a logic network by creating larger nodes\n" ); Abc_Print( -2, "\t-F : the maximum fanin size after renoding [default = %d]\n", nFaninMax ); Abc_Print( -2, "\t-T : the threshold for AIG node duplication [default = %d]\n", nThresh ); Abc_Print( -2, "\t (an AIG node is the root of a new node after renoding\n" ); Abc_Print( -2, "\t if this leads to duplication of no more than %d AIG nodes,\n", nThresh ); Abc_Print( -2, "\t that is, if [(numFanouts(Node)-1) * size(MFFC(Node))] <= %d)\n", nThresh ); Abc_Print( -2, "\t-m : creates multi-input AND graph [default = %s]\n", fMulti? "yes": "no" ); Abc_Print( -2, "\t-s : creates a simple AIG (no renoding) [default = %s]\n", fSimple? "yes": "no" ); Abc_Print( -2, "\t-f : creates a factor-cut network [default = %s]\n", fFactor? "yes": "no" ); Abc_Print( -2, "\t-c : performs renoding to derive the CNF [default = %s]\n", fCnf? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int nLutSize, nCutsMax, c; int nFlowIters, nAreaIters; int fArea; int fUseBdds; int fUseSops; int fUseCnfs; int fUseMv; int fVerbose; extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nLutSize, int nCutsMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nLutSize = 8; nCutsMax = 4; nFlowIters = 1; nAreaIters = 1; fArea = 0; fUseBdds = 0; fUseSops = 0; fUseCnfs = 0; fUseMv = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAabscivh" ) ) != EOF ) { switch ( c ) { case 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLutSize < 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; } nCutsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCutsMax < 0 ) goto usage; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by a positive integer.\n" ); goto usage; } nFlowIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFlowIters < 0 ) goto usage; break; case 'A': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-A\" should be followed by a positive integer.\n" ); goto usage; } nAreaIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nAreaIters < 0 ) goto usage; break; case 'a': fArea ^= 1; break; case 'b': fUseBdds ^= 1; break; case 's': fUseSops ^= 1; break; case 'c': fUseCnfs ^= 1; break; case 'i': fUseMv ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( fUseBdds + fUseSops + fUseCnfs + fUseMv > 1 ) { Abc_Print( -1, "Cannot optimize two parameters at the same time.\n" ); return 1; } if ( nLutSize < 2 || nLutSize > IF_MAX_FUNC_LUTSIZE ) { Abc_Print( -1, "Incorrect LUT size (%d).\n", nLutSize ); return 1; } if ( nCutsMax < 1 || nCutsMax >= (1<<12) ) { Abc_Print( -1, "Incorrect number of cuts.\n" ); return 1; } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Cannot renode a network that is not an AIG (run \"strash\").\n" ); return 1; } // get the new network pNtkRes = Abc_NtkRenode( pNtk, nLutSize, nCutsMax, nFlowIters, nAreaIters, fArea, fUseBdds, fUseSops, fUseCnfs, fUseMv, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Renoding has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: renode [-KCFA ] [-sbciav]\n" ); Abc_Print( -2, "\t transforms the AIG into a logic network with larger nodes\n" ); Abc_Print( -2, "\t while minimizing the number of FF literals of the node SOPs\n" ); Abc_Print( -2, "\t-K : the max cut size for renoding (2 < num < %d) [default = %d]\n", IF_MAX_FUNC_LUTSIZE+1, nLutSize ); Abc_Print( -2, "\t-C : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCutsMax ); Abc_Print( -2, "\t-F : the number of area flow recovery iterations (num >= 0) [default = %d]\n", nFlowIters ); Abc_Print( -2, "\t-A : the number of exact area recovery iterations (num >= 0) [default = %d]\n", nAreaIters ); Abc_Print( -2, "\t-s : toggles minimizing SOP cubes instead of FF lits [default = %s]\n", fUseSops? "yes": "no" ); Abc_Print( -2, "\t-b : toggles minimizing BDD nodes instead of FF lits [default = %s]\n", fUseBdds? "yes": "no" ); Abc_Print( -2, "\t-c : toggles minimizing CNF clauses instead of FF lits [default = %s]\n", fUseCnfs? "yes": "no" ); Abc_Print( -2, "\t-i : toggles minimizing MV-SOP instead of FF lits [default = %s]\n", fUseMv? "yes": "no" ); Abc_Print( -2, "\t-a : toggles area-oriented mapping [default = %s]\n", fArea? "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_CommandCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; int fCleanupPis; int fCleanupPos; int fVerbose; extern Abc_Ntk_t * Abc_NtkDarCleanupAig( Abc_Ntk_t * pNtk, int fCleanupPis, int fCleanupPos, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fCleanupPis = 1; fCleanupPos = 1; fVerbose = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "iovh" ) ) != EOF ) { switch ( c ) { case 'i': fCleanupPis ^= 1; break; case 'o': fCleanupPos ^= 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_NtkIsStrash(pNtk) ) { if ( !fCleanupPis && !fCleanupPos ) { Abc_Print( -1, "Cleanup for PIs and POs is not enabled.\n" ); pNtkRes = Abc_NtkDup( pNtk ); } else pNtkRes = Abc_NtkDarCleanupAig( pNtk, fCleanupPis, fCleanupPos, fVerbose ); } else { Abc_NtkCleanup( pNtk, fVerbose ); pNtkRes = Abc_NtkDup( pNtk ); } if ( pNtkRes == NULL ) { Abc_Print( -1, "Cleanup has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: cleanup [-iovh]\n" ); Abc_Print( -2, "\t for logic networks, removes dangling combinatinal logic\n" ); Abc_Print( -2, "\t for AIGs, removes PIs w/o fanout and POs driven by const-0\n" ); Abc_Print( -2, "\t-i : toggles removing PIs without fanout [default = %s]\n", fCleanupPis? "yes": "no" ); Abc_Print( -2, "\t-o : toggles removing POs with const-0 drivers [default = %s]\n", fCleanupPos? "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_CommandSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fSingle = 0; int fVerbose = 0; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) { switch ( c ) { case 's': fSingle ^= 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_Print( -1, "The classical (SIS-like) sweep can only be performed on a logic network.\n" ); return 1; } // modify the current network if ( fSingle ) Abc_NtkSweepBufsInvs( pNtk, fVerbose ); else Abc_NtkSweep( pNtk, fVerbose ); return 0; usage: Abc_Print( -2, "usage: sweep [-svh]\n" ); Abc_Print( -2, "\t removes dangling nodes; propagates constant, buffers, inverters\n" ); Abc_Print( -2, "\t-s : toggle sweeping buffers/inverters only [default = %s]\n", fSingle? "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_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_NtkFxPerform( Abc_Ntk_t * pNtk, int nNewNodesMax, int nLitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Fxu_Data_t Params, * p = &Params; int c, fNewAlgo = 1; int nPairsLimit = 1000000000; // set the defaults Abc_NtkSetDefaultFxParams( p ); Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "SDNWMPsdzcnxvwh")) != EOF ) { switch (c) { case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } p->nSingleMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( p->nSingleMax < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } p->nPairsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( p->nPairsMax < 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; } p->nNodesExt = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( p->nNodesExt < 0 ) goto usage; break; case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } p->WeightMin = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( p->WeightMin < 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; } p->LitCountMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( p->LitCountMax < 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; } nPairsLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nPairsLimit < 0 ) goto usage; break; case 's': p->fOnlyS ^= 1; break; case 'd': p->fOnlyD ^= 1; break; case 'z': p->fUse0 ^= 1; break; case 'c': p->fUseCompl ^= 1; break; case 'n': fNewAlgo ^= 1; break; case 'x': p->fCanonDivs ^= 1; break; case 'v': p->fVerbose ^= 1; break; case 'w': p->fVeryVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Abc_NtkNodeNum(pNtk) == 0 || Abc_NtkPiNum(pNtk) == 0 ) { Abc_Print( 0, "The network does not have internal nodes.\n" ); return 0; } if ( !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "Fast extract can only be applied to a logic network (run \"renode\" or \"if\").\n" ); return 1; } if ( !Abc_NtkIsSopLogic(pNtk) ) { Abc_Print( -1, "Fast extract can only be applied to a logic network with SOP local functions (run \"bdd; sop\").\n" ); return 1; } if ( Abc_NtkGetCubePairNum(pNtk) > nPairsLimit ) { Abc_Print( -1, "Cannot perform \"fx\" because the number cube pairs exceeds the limit (%d).\n", nPairsLimit ); return 1; } // the nodes to be merged are linked into the special linked list if ( fNewAlgo ) Abc_NtkFxPerform( pNtk, p->nNodesExt, p->LitCountMax, p->fCanonDivs, p->fVerbose, p->fVeryVerbose ); else Abc_NtkFastExtract( pNtk, p ); Abc_NtkFxuFreeInfo( p ); return 0; usage: Abc_Print( -2, "usage: fx [-SDNWMP ] [-sdzcnxvwh]\n"); Abc_Print( -2, "\t performs unate fast extract on the current network\n"); Abc_Print( -2, "\t-S : max number of single-cube divisors to consider [default = %d]\n", p->nSingleMax ); Abc_Print( -2, "\t-D : max number of double-cube divisors to consider [default = %d]\n", p->nPairsMax ); Abc_Print( -2, "\t-N : max number of divisors to extract during this run [default = %d]\n", p->nNodesExt ); Abc_Print( -2, "\t-W : lower bound on the weight of divisors to extract [default = %d]\n", p->WeightMin ); Abc_Print( -2, "\t-M : upper bound on literal count of divisors to extract [default = %d]\n", p->LitCountMax ); Abc_Print( -2, "\t-P : skip \"fx\" if cube pair count exceeds this limit [default = %d]\n", nPairsLimit ); Abc_Print( -2, "\t-s : use only single-cube divisors [default = %s]\n", p->fOnlyS? "yes": "no" ); Abc_Print( -2, "\t-d : use only double-cube divisors [default = %s]\n", p->fOnlyD? "yes": "no" ); Abc_Print( -2, "\t-z : use zero-weight divisors [default = %s]\n", p->fUse0? "yes": "no" ); Abc_Print( -2, "\t-c : use complement in the binary case [default = %s]\n", p->fUseCompl? "yes": "no" ); Abc_Print( -2, "\t-n : use new implementation of fast extract [default = %s]\n", fNewAlgo? "yes": "no" ); Abc_Print( -2, "\t-x : use only canonical divisors (AND, XOR, MUX) [default = %s]\n", p->fCanonDivs? "yes": "no" ); Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", p->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : print additional information [default = %s]\n", p->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static int Abc_CommandFxch( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_NtkFxchPerform( Abc_Ntk_t * pNtk, int nMaxDivExt, int fVerbose, int fVeryVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c, nMaxDivExt = 0, fVerbose = 0, fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "Nvwh")) != EOF ) { switch (c) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } nMaxDivExt = atoi( argv[globalUtilOptind] ); globalUtilOptind++; if ( nMaxDivExt < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Abc_NtkNodeNum( pNtk ) == 0 ) { Abc_Print( -1, "The network does not have internal nodes.\n" ); return 1; } if ( !Abc_NtkIsLogic( pNtk ) ) { Abc_Print( -1, "Fast extract can only be applied to a logic network (run \"renode\" or \"if\").\n" ); return 1; } if ( !Abc_NtkIsSopLogic( pNtk ) ) { Abc_Print( -1, "Fast extract can only be applied to a logic network with SOP local functions (run \"bdd; sop\").\n" ); return 1; } Abc_NtkFxchPerform( pNtk, nMaxDivExt, fVerbose, fVeryVerbose ); return 0; usage: Abc_Print( -2, "usage: fxch [-N ] [-svwh]\n"); Abc_Print( -2, "\t performs fast extract with cube hashing on the current network\n"); Abc_Print( -2, "\t-N : max number of divisors to extract during this run [default = unused]\n" ); Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : print additional 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 This command was contributed by Bruno Schmitt from UFRGS in May 2016.\n" ); Abc_Print( -2, "\t The author can be contacted as boschmitt at inf.ufrgs.br\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandEliminate( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int ElimValue; int nMaxSize; int nIterMax; int fGreedy; int fReverse; int fSpecial; int fVerbose; int c; extern int Abc_NtkEliminate( Abc_Ntk_t * pNtk, int nMaxSize, int fReverse, int fVerbose ); extern int Abc_NtkEliminate1( Abc_Ntk_t * pNtk, int ElimValue, int nMaxSize, int nIterMax, int fReverse, int fVerbose ); extern int Abc_NtkEliminateSpecial( Abc_Ntk_t * pNtk, int nMaxSize, int fVerbose ); // set the defaults ElimValue = -1; nMaxSize = 12; nIterMax = 1; fGreedy = 0; fReverse = 0; fSpecial = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( (c = Extra_UtilGetopt(argc, argv, "VNIgrsvh")) != EOF ) { switch (c) { case 'V': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer that is -1 or larger.\n" ); goto usage; } ElimValue = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( ElimValue < -1 ) 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; } 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 a positive integer.\n" ); goto usage; } nIterMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nIterMax <= 0 ) goto usage; break; case 'g': fGreedy ^= 1; break; case 'r': fReverse ^= 1; break; case 's': fSpecial ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Abc_NtkNodeNum(pNtk) == 0 ) { Abc_Print( -1, "The network does not have internal nodes.\n" ); return 1; } if ( !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "This command can only be applied to a logic network (run \"renode\" or \"if\").\n" ); return 1; } if ( fSpecial ) Abc_NtkEliminateSpecial( pNtk, 1000, fVerbose ); else if ( fGreedy ) Abc_NtkEliminate( pNtk, nMaxSize, fReverse, fVerbose ); else Abc_NtkEliminate1( pNtk, ElimValue, nMaxSize, nIterMax, fReverse, fVerbose ); return 0; usage: Abc_Print( -2, "usage: eliminate [-VNI ] [-grsvh]\n"); Abc_Print( -2, "\t traditional \"eliminate -1\", which collapses the node into its fanout\n"); Abc_Print( -2, "\t if the node's variable appears in the fanout's factored form only once\n"); Abc_Print( -2, "\t-V : the \"value\" parameter used by \"eliminate\" in SIS [default = %d]\n", ElimValue ); Abc_Print( -2, "\t-N : the maximum node support after collapsing [default = %d]\n", nMaxSize ); Abc_Print( -2, "\t-I : the maximum number of iterations [default = %d]\n", nIterMax ); Abc_Print( -2, "\t-g : toggle using greedy eliminate (without \"value\") [default = %s]\n", fGreedy? "yes": "no" ); Abc_Print( -2, "\t-r : use the reverse topological order [default = %s]\n", fReverse? "yes": "no" ); Abc_Print( -2, "\t-s : toggle eliminating similar nodes [default = %s]\n", fSpecial? "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_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes, * pNtkNew; int fGlobal, fRecursive, fVerbose, fPrint, fShort, c; extern Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, int fVerbose, int fPrint, int fShort ); extern int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, int fVerbose, int fRecursive ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fGlobal = 1; fRecursive = 0; fVerbose = 0; fPrint = 0; fShort = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "grvpsh" ) ) != EOF ) { switch ( c ) { case 'g': fGlobal ^= 1; break; case 'r': fRecursive ^= 1; break; case 'v': fVerbose ^= 1; break; case 'p': fPrint ^= 1; break; case 's': fShort ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( fGlobal ) { // Abc_Print( 0, "Performing DSD of global functions of the network.\n" ); // get the new network if ( !Abc_NtkIsStrash(pNtk) ) { pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 ); pNtkRes = Abc_NtkDsdGlobal( pNtkNew, fVerbose, fPrint, fShort ); Abc_NtkDelete( pNtkNew ); } else { pNtkRes = Abc_NtkDsdGlobal( pNtk, fVerbose, fPrint, fShort ); } if ( pNtkRes == NULL ) { Abc_Print( -1, "Global DSD has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); } else if ( fRecursive ) { if ( !Abc_NtkIsBddLogic( pNtk ) ) { Abc_Print( -1, "This command is only applicable to logic BDD networks.\n" ); return 1; } if ( fVerbose ) Abc_Print( 1, "Performing recursive DSD and MUX decomposition of local functions.\n" ); if ( !Abc_NtkDsdLocal( pNtk, fVerbose, fRecursive ) ) Abc_Print( -1, "Recursive DSD has failed.\n" ); } else { if ( !Abc_NtkIsBddLogic( pNtk ) ) { Abc_Print( -1, "This command is only applicable to logic BDD networks (run \"bdd\").\n" ); return 1; } if ( fVerbose ) Abc_Print( 1, "Performing simple non-recursive DSD of local functions.\n" ); if ( !Abc_NtkDsdLocal( pNtk, fVerbose, fRecursive ) ) Abc_Print( -1, "Simple DSD of local functions has failed.\n" ); } return 0; usage: Abc_Print( -2, "usage: dsd [-grvpsh]\n" ); Abc_Print( -2, "\t decomposes the network using disjoint-support decomposition\n" ); Abc_Print( -2, "\t-g : toggle DSD of global and local functions [default = %s]\n", fGlobal? "global": "local" ); Abc_Print( -2, "\t-r : toggle recursive DSD/MUX and simple DSD [default = %s]\n", fRecursive? "recursive DSD/MUX": "simple DSD" ); Abc_Print( -2, "\t-v : prints DSD statistics and runtime [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-p : prints DSD structure to the standard output [default = %s]\n", fPrint? "yes": "no" ); Abc_Print( -2, "\t-s : use short PI names when printing DSD structure [default = %s]\n", fShort? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSparsify( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkSparsify( Abc_Ntk_t * pNtk, int nPerc, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkNew; int nPerc, fVerbose, c; // set defaults nPerc = 10; 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; } nPerc = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nPerc < 1 || nPerc > 100 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; break; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsBddLogic( pNtk ) ) { Abc_Print( -1, "This command is only applicable to logic BDD networks (run \"bdd\").\n" ); return 1; } if ( Abc_NtkCiNum(pNtk) > 16 ) { Abc_Print( -1, "The number of primary inputs is more than 16.\n" ); return 1; } pNtkNew = Abc_NtkSparsify( pNtk, nPerc, fVerbose ); if ( pNtkNew == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); return 0; usage: Abc_Print( -2, "usage: sparsify [-N num] [-vh]\n" ); Abc_Print( -2, "\t creates incompletely-specified function\n" ); Abc_Print( -2, "\t-N : the percentage of on-set and off-set minterms (1 <= num <= 100) [default = %d]\n", nPerc ); Abc_Print( -2, "\t-v : prints 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_CommandLutpack( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Lpk_Par_t Pars, * pPars = &Pars; int c; pNtk = Abc_FrameReadNtk(pAbc); // set defaults memset( pPars, 0, sizeof(Lpk_Par_t) ); pPars->nLutsMax = 4; // (N) the maximum number of LUTs in the structure pPars->nLutsOver = 3; // (Q) the maximum number of LUTs not in the MFFC pPars->nVarsShared = 0; // (S) the maximum number of shared variables (crossbars) pPars->nGrowthLevel = 0; // (L) the maximum number of increased levels pPars->fSatur = 1; pPars->fZeroCost = 0; pPars->fFirst = 0; pPars->fOldAlgo = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NQSLszfovwh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } pPars->nLutsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLutsMax < 2 || pPars->nLutsMax > 16 ) goto usage; break; case 'Q': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" ); goto usage; } pPars->nLutsOver = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLutsOver < 0 || pPars->nLutsOver > 8 ) 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->nVarsShared = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 4 ) goto usage; break; case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY ) goto usage; break; case 's': pPars->fSatur ^= 1; break; case 'z': pPars->fZeroCost ^= 1; break; case 'f': pPars->fFirst ^= 1; break; case 'o': pPars->fOldAlgo ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 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_Print( -1, "This command can only be applied to a logic network.\n" ); return 1; } if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 3 ) { Abc_Print( -1, "The number of shared variables (%d) is not in the range 0 <= S <= 3.\n", pPars->nVarsShared ); return 1; } // modify the current network if ( !Lpk_Resynthesize( pNtk, pPars ) ) { Abc_Print( -1, "Resynthesis has failed.\n" ); return 1; } return 0; usage: Abc_Print( -2, "usage: lutpack [-NQSL ] [-szfovwh]\n" ); 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, \"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 ); Abc_Print( -2, "\t-L : max level increase after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); Abc_Print( -2, "\t-s : toggle iteration till saturation [default = %s]\n", pPars->fSatur? "yes": "no" ); Abc_Print( -2, "\t-z : toggle zero-cost replacements [default = %s]\n", pPars->fZeroCost? "yes": "no" ); Abc_Print( -2, "\t-f : toggle using only first node and first cut [default = %s]\n", pPars->fFirst? "yes": "no" ); Abc_Print( -2, "\t-o : toggle using old implementation [default = %s]\n", pPars->fOldAlgo? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle detailed printout of decomposed functions [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_CommandLutmin( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtk, int nLutSize, int fReorder, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; int c; int nLutSize = 4; int fReorder = 1; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Krvh" ) ) != 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++; break; case 'r': fReorder ^= 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; } // modify the current network pNtkRes = Abc_NtkLutmin( pNtk, nLutSize, fReorder, fVerbose ); 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: lutmin [-K ] [-rvh]\n" ); Abc_Print( -2, "\t perform FPGA mapping while minimizing the LUT count\n" ); Abc_Print( -2, "\t as described in the paper T. Sasao and A. Mishchenko:\n" ); Abc_Print( -2, "\t \"On the number of LUTs to implement logic functions\".\n" ); Abc_Print( -2, "\t-K : the LUT size to use for the mapping (2 <= num) [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-r : toggle using BDD variable reordering [default = %s]\n", fReorder? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } #if 0 /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandImfs( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Res_Par_t Pars, * pPars = &Pars; int c; // set defaults pPars->nWindow = 62; pPars->nCands = 5; pPars->nSimWords = 4; pPars->nGrowthLevel = 0; pPars->fArea = 0; pPars->fVerbose = 0; pPars->fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "WSCLavwh" ) ) != EOF ) { switch ( c ) { case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } pPars->nWindow = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nWindow < 1 || pPars->nWindow > 99 ) 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->nSimWords = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nSimWords < 1 || pPars->nSimWords > 256 ) 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->nCands = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCands < 0 || pPars->nCands > ABC_INFINITY ) goto usage; break; case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY ) goto usage; break; case 'a': pPars->fArea ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 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_Print( -1, "This command can only be applied to a logic network.\n" ); return 1; } // modify the current network if ( !Abc_NtkResynthesize( pNtk, pPars ) ) { Abc_Print( -1, "Resynthesis has failed.\n" ); return 1; } return 0; usage: Abc_Print( -2, "usage: imfs [-W ] [-LCS ] [-avwh]\n" ); Abc_Print( -2, "\t performs resubstitution-based resynthesis with interpolation\n" ); Abc_Print( -2, "\t (there is another command for resynthesis after LUT mapping, \"lutpack\")\n" ); Abc_Print( -2, "\t-W : fanin/fanout levels (NxM) of the window (00 <= NM <= 99) [default = %d%d]\n", pPars->nWindow/10, pPars->nWindow%10 ); Abc_Print( -2, "\t-C : the max number of resub candidates (1 <= n) [default = %d]\n", pPars->nCands ); Abc_Print( -2, "\t-S : the number of simulation words (1 <= n <= 256) [default = %d]\n", pPars->nSimWords ); Abc_Print( -2, "\t-L : the max increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); Abc_Print( -2, "\t-a : toggle optimization for area only [default = %s]\n", pPars->fArea? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printout subgraph statistics [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } #endif /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandMfs( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Mfs_Par_t Pars, * pPars = &Pars; int c; // set defaults Abc_NtkMfsParsDefault( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCdraestpgvwh" ) ) != EOF ) { switch ( c ) { case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } pPars->nWinTfoLevs = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nWinTfoLevs < 0 ) goto usage; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFanoutsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFanoutsMax < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } pPars->nDepthMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nDepthMax < 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->nWinMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nWinMax < 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; } pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY ) 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 'd': pPars->fRrOnly ^= 1; break; case 'r': pPars->fResub ^= 1; break; case 'a': pPars->fArea ^= 1; break; case 'e': pPars->fMoreEffort ^= 1; break; case 's': pPars->fSwapEdge ^= 1; break; case 't': pPars->fOneHotness ^= 1; break; case 'p': pPars->fPower ^= 1; break; case 'g': pPars->fGiaSat ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 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_Print( -1, "This command can only be applied to a logic network.\n" ); return 1; } // modify the current network if ( !Abc_NtkMfs( pNtk, pPars ) ) { Abc_Print( -1, "Resynthesis has failed.\n" ); return 1; } return 0; usage: Abc_Print( -2, "usage: mfs [-WFDMLC ] [-draestpgvh]\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->nWinTfoLevs ); Abc_Print( -2, "\t-F : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutsMax ); Abc_Print( -2, "\t-D : the max depth nodes to try (0 = no limit) [default = %d]\n", pPars->nDepthMax ); Abc_Print( -2, "\t-M : the max node count of windows to consider (0 = no limit) [default = %d]\n", pPars->nWinMax ); Abc_Print( -2, "\t-L : the max increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); Abc_Print( -2, "\t-C : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-d : toggle performing redundancy removal [default = %s]\n", pPars->fRrOnly? "yes": "no" ); Abc_Print( -2, "\t-r : toggle resubstitution and dc-minimization [default = %s]\n", pPars->fResub? "resub": "dc-min" ); 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-s : toggle evaluation of edge swapping [default = %s]\n", pPars->fSwapEdge? "yes": "no" ); Abc_Print( -2, "\t-t : toggle using artificial one-hotness conditions [default = %s]\n", pPars->fOneHotness? "yes": "no" ); Abc_Print( -2, "\t-p : toggle power-aware optimization [default = %s]\n", pPars->fPower? "yes": "no" ); Abc_Print( -2, "\t-g : toggle using new SAT solver [default = %s]\n", pPars->fGiaSat? "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"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandMfs2( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_NtkPerformMfs( Abc_Ntk_t * pNtk, Sfm_Par_t * pPars ); extern int Abc_NtkMfsAfterICheck( Abc_Ntk_t * p, int nFrames, int nFramesAdd, Vec_Int_t * vFlops, Sfm_Par_t * pPars ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Sfm_Par_t Pars, * pPars = &Pars; int c, fIndDCs = 0, fUseAllFfs = 0, nFramesAdd = 0; // set defaults Sfm_ParSetDefault( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCZNIdaeijlvwh" ) ) != EOF ) { switch ( c ) { case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } pPars->nTfoLevMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTfoLevMax < 0 ) goto usage; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFanoutMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFanoutMax < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } pPars->nDepthMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nDepthMax < 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->nWinSizeMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nWinSizeMax < 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; } pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nGrowthLevel < -ABC_INFINITY || pPars->nGrowthLevel > ABC_INFINITY ) 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 'Z': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-Z\" should be followed by an integer.\n" ); goto usage; } pPars->nFirstFixed = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFirstFixed < 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->nNodesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nNodesMax < 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; } nFramesAdd = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFramesAdd < 0 ) goto usage; break; case 'd': pPars->fRrOnly ^= 1; break; case 'a': pPars->fArea ^= 1; break; case 'e': pPars->fMoreEffort ^= 1; break; case 'i': fIndDCs ^= 1; break; case 'j': fUseAllFfs ^= 1; break; case 'l': pPars->fUseDcs ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 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_Print( -1, "This command can only be applied to a logic network.\n" ); return 1; } if ( fIndDCs ) { if ( fUseAllFfs ) { pAbc->nIndFrames = 1; Vec_IntFreeP( &pAbc->vIndFlops ); pAbc->vIndFlops = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); Vec_IntFill( pAbc->vIndFlops, Abc_NtkLatchNum(pNtk), 1 ); } if ( pAbc->nIndFrames <= 0 ) { Abc_Print( -1, "The number of k-inductive frames is not specified.\n" ); return 0; } if ( pAbc->vIndFlops == NULL ) { Abc_Print( -1, "The set of k-inductive flops is not specified.\n" ); return 0; } if ( Vec_IntSize(pAbc->vIndFlops) != Abc_NtkLatchNum(pNtk) ) { Abc_Print( -1, "The saved flop count (%d) does not match that of the current network (%d).\n", Vec_IntSize(pAbc->vIndFlops), Abc_NtkLatchNum(pNtk) ); return 0; } // modify the current network if ( !Abc_NtkMfsAfterICheck( pNtk, pAbc->nIndFrames, nFramesAdd, pAbc->vIndFlops, pPars ) ) { Abc_Print( -1, "Resynthesis has failed.\n" ); return 1; } if ( fUseAllFfs ) { pAbc->nIndFrames = 0; Vec_IntFreeP( &pAbc->vIndFlops ); } } else { // modify the current network if ( !Abc_NtkPerformMfs( pNtk, pPars ) ) { Abc_Print( -1, "Resynthesis has failed.\n" ); return 1; } } return 0; usage: 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 ); Abc_Print( -2, "\t-D : the max depth nodes to try (0 = no limit) [default = %d]\n", pPars->nDepthMax ); Abc_Print( -2, "\t-M : the max node count of windows to consider (0 = no limit) [default = %d]\n", pPars->nWinSizeMax ); Abc_Print( -2, "\t-L : the max increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); Abc_Print( -2, "\t-C : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-Z : treat the first logic nodes as fixed (0 = none) [default = %d]\n", pPars->nFirstFixed ); Abc_Print( -2, "\t-N : the max number of nodes to try (0 = all) [default = %d]\n", pPars->nNodesMax ); 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-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"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandMfs3( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkPerformMfs3( Abc_Ntk_t * pNtk, Sfm_Par_t * pPars ); extern void Sfm_ParSetDefault3( Sfm_Par_t * pPars ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Sfm_Par_t Pars, * pPars = &Pars; int c; // set defaults Sfm_ParSetDefault3( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "IOVFKLHRMCNPWDEarmzoespdlvwh" ) ) != EOF ) { switch ( c ) { case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } pPars->nTfiLevMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTfiLevMax < 1 ) { Abc_Print( -1, "The number of TFI levels (switch \"-I\") should be at least 1.\n" ); goto usage; } break; case 'O': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); goto usage; } pPars->nTfoLevMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTfoLevMax < 0 ) goto usage; break; case 'V': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer.\n" ); goto usage; } pPars->nTfiLevMax = pPars->nTfoLevMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTfiLevMax < 1 ) goto usage; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFanoutMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFanoutMax < 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; } pPars->nVarMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nVarMax < 2 || pPars->nVarMax > 8 ) goto usage; break; case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } pPars->nMffcMin = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nMffcMin < 0 ) goto usage; break; case 'H': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-H\" should be followed by an integer.\n" ); goto usage; } pPars->nMffcMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nMffcMax < 0 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } pPars->nDecMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nDecMax < 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->nWinSizeMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nWinSizeMax < 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 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } pPars->nNodesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nNodesMax < 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->iNodeOne = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->iNodeOne < 0 ) goto usage; break; case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } pPars->nTimeWin = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTimeWin < 0 || pPars->nTimeWin > 100 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } pPars->DeltaCrit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->DeltaCrit < 0 ) goto usage; break; case 'E': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-E\" should be followed by an integer.\n" ); goto usage; } pPars->DelAreaRatio = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->DelAreaRatio < 0 ) goto usage; break; case 'a': pPars->fArea ^= 1; break; case 'r': pPars->fAreaRev ^= 1; break; case 'm': pPars->fUseAndOr ^= 1; break; case 'z': pPars->fZeroCost ^= 1; break; case 'o': pPars->fRrOnly ^= 1; break; case 'e': pPars->fMoreEffort ^= 1; break; case 's': pPars->fUseSim ^= 1; break; case 'p': pPars->fPrintDecs ^= 1; break; case 'd': pPars->fDelayVerbose ^= 1; break; case 'l': pPars->fLibVerbose ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsMappedLogic(pNtk) ) { Abc_Print( -1, "This command can only be applied to a mapped logic network.\n" ); return 1; } // modify the current network Abc_NtkPerformMfs3( pNtk, pPars ); return 0; usage: Abc_Print( -2, "usage: mfs3 [-IOVFKLHRMCNPWDE ] [-armzespdlvwh]\n" ); Abc_Print( -2, "\t performs don't-care-based optimization of mapped networks\n" ); Abc_Print( -2, "\t-I : the number of levels in the TFI cone (1 <= num) [default = %d]\n", pPars->nTfiLevMax ); Abc_Print( -2, "\t-O : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nTfoLevMax ); Abc_Print( -2, "\t-V : the number of levels in the TFI/TFO cone (1 <= num) [default = %d]\n", pPars->nTfiLevMax ); Abc_Print( -2, "\t-F : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutMax ); Abc_Print( -2, "\t-K : the max number of variables (2 <= num <= 8 ) [default = %d]\n", pPars->nVarMax ); Abc_Print( -2, "\t-L : the min size of max fanout-free cone (MFFC) (area-only) [default = %d]\n", pPars->nMffcMin ); Abc_Print( -2, "\t-H : the max size of max fanout-free cone (MFFC) (area-only) [default = %d]\n", pPars->nMffcMax ); Abc_Print( -2, "\t-R : the max number of decomposition rounds (1 <= num <= 4) [default = %d]\n", pPars->nDecMax ); Abc_Print( -2, "\t-M : the max node count of windows to consider (0 = no limit) [default = %d]\n", pPars->nWinSizeMax ); Abc_Print( -2, "\t-C : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-N : the max number of nodes to try (0 = all) [default = %d]\n", pPars->nNodesMax ); Abc_Print( -2, "\t-P : one particular node to try (0 = none) [default = %d]\n", pPars->iNodeOne ); Abc_Print( -2, "\t-W : size of timing window in percents (0 <= num <= 100) [default = %d]\n", pPars->nTimeWin ); Abc_Print( -2, "\t-D : size of critical-timing delay-delta (in picoseconds) [default = %d]\n", pPars->DeltaCrit ); Abc_Print( -2, "\t-E : delay-area tradeoff (in picoseconds per area-unit) [default = %d]\n", pPars->DelAreaRatio ); Abc_Print( -2, "\t-a : toggle area minimization [default = %s]\n", pPars->fArea? "yes": "no" ); Abc_Print( -2, "\t-r : toggle using reverse topo order for area minimization [default = %s]\n", pPars->fAreaRev? "yes": "no" ); Abc_Print( -2, "\t-m : toggle detecting multi-input AND/OR gates [default = %s]\n", pPars->fUseAndOr? "yes": "no" ); Abc_Print( -2, "\t-z : toggle zero-cost replacements [default = %s]\n", pPars->fZeroCost? "yes": "no" ); Abc_Print( -2, "\t-e : toggle using more effort [default = %s]\n", pPars->fMoreEffort? "yes": "no" ); Abc_Print( -2, "\t-s : toggle using simulation [default = %s]\n", pPars->fUseSim? "yes": "no" ); Abc_Print( -2, "\t-p : toggle printing decompositions [default = %s]\n", pPars->fPrintDecs? "yes": "no" ); Abc_Print( -2, "\t-d : toggle printing delay profile statistics [default = %s]\n", pPars->fDelayVerbose? "yes": "no" ); Abc_Print( -2, "\t-l : toggle printing library usage statistics [default = %s]\n", pPars->fLibVerbose? "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"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandMfse( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkOptMfse( Abc_Ntk_t * pNtk, Acb_Par_t * pPars ); Abc_Ntk_t * pNtkNew, * pNtk = Abc_FrameReadNtk(pAbc); Acb_Par_t Pars, * pPars = &Pars; int c; Acb_ParSetDefault( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "IOWFLCadvwh" ) ) != EOF ) { switch ( c ) { case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } pPars->nTfiLevMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTfiLevMax < 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; } pPars->nTfoLevMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nTfoLevMax < 0 ) goto usage; break; case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } pPars->nWinNodeMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nWinNodeMax < 0 ) goto usage; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nFanoutMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nFanoutMax < 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; } pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nGrowthLevel < -ABC_INFINITY || pPars->nGrowthLevel > ABC_INFINITY ) 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 'a': pPars->fArea ^= 1; break; case 'd': pPars->fUseAshen ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 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_Print( -1, "This command can only be applied to a logic network.\n" ); return 1; } pPars->nLutSize = Abc_NtkGetFaninMax( pNtk ); if ( pPars->nLutSize > 6 ) { Abc_Print( -1, "Command is only applicable to LUT size no more than 6.\n" ); return 1; } Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); pNtkNew = Abc_NtkOptMfse( pNtk, pPars ); if ( pNtkNew == NULL ) { Abc_Print( -1, "Command \"mfse\" has failed.\n" ); return 1; } Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); return 0; usage: Abc_Print( -2, "usage: mfse [-IOWFLC ] [-advwh]\n" ); Abc_Print( -2, "\t performs don't-care-based optimization of logic networks\n" ); Abc_Print( -2, "\t-I : the number of levels in the TFI cone (2 <= num) [default = %d]\n", pPars->nTfiLevMax ); Abc_Print( -2, "\t-O : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nTfoLevMax ); Abc_Print( -2, "\t-W : the max number of nodes in the window (1 <= num) [default = %d]\n", pPars->nWinNodeMax ); Abc_Print( -2, "\t-F : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutMax ); Abc_Print( -2, "\t-L : the max increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); Abc_Print( -2, "\t-C : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n", pPars->nBTLimit ); Abc_Print( -2, "\t-a : toggle minimizing area [default = %s]\n", pPars->fArea? "area": "delay" ); Abc_Print( -2, "\t-d : toggle using Ashenhurst decomposition [default = %s]\n", pPars->fUseAshen? "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"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandLogicPush( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkOptPush( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Ntk_t * pNtkRes; int nLutSize = 4; int fVerbose = 0; int c; 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 a positive integer.\n" ); goto usage; } nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLutSize < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "This command can only be applied to a logic network.\n" ); return 1; } nLutSize = Abc_MaxInt( nLutSize, Abc_NtkGetFaninMax(pNtk) ); Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); pNtkRes = Abc_NtkOptPush( pNtk, nLutSize, fVerbose ); Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: logicpush [-K num] [-vh]\n" ); Abc_Print( -2, "\t performs logic pushing to reduce structural bias\n" ); Abc_Print( -2, "\t-K : the LUT size used in the mapping [default = %d]\n", nLutSize ); 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_CommandTrace( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fUseLutLib; int fVerbose; extern void Abc_NtkDelayTracePrint( Abc_Ntk_t * pNtk, int fUseLutLib, int fVerbose ); // set defaults fUseLutLib = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "lvh" ) ) != EOF ) { switch ( c ) { case 'l': fUseLutLib ^= 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_Print( -1, "This command can only be applied to a logic network.\n" ); return 1; } // modify the current network Abc_NtkDelayTracePrint( pNtk, fUseLutLib, fVerbose ); return 0; usage: Abc_Print( -2, "usage: trace [-lvh]\n" ); Abc_Print( -2, "\t performs delay trace of LUT-mapped network\n" ); Abc_Print( -2, "\t-l : toggle using unit- or LUT-library-delay model [default = %s]\n", fUseLutLib? "lib": "unit" ); 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_CommandGlitch( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int nPats = 4000; int Prob = 8; int fVerbose = 1; int c; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NPvh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } nPats = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nPats < 1 ) goto usage; break; case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } Prob = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( Prob < 1 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "This command can only be applied to a mapped logic network.\n" ); return 1; } if ( Abc_NtkIsMappedLogic(pNtk) || Abc_NtkGetFaninMax(pNtk) <= 6 ) Abc_Print( 1, "Glitching adds %7.2f %% of signal transitions, compared to switching.\n", Abc_NtkMfsTotalGlitching(pNtk, nPats, Prob, fVerbose) ); else printf( "Currently computes glitching only for K-LUT networks with K <= 6.\n" ); return 0; usage: Abc_Print( -2, "usage: glitch [-NP ] [-vh]\n" ); Abc_Print( -2, "\t comparing glitching activity to switching activity\n" ); Abc_Print( -2, "\t-N : the number of random patterns to use (0 < num < 1000000) [default = %d]\n", nPats ); Abc_Print( -2, "\t-P : once in how many cycles an input changes its value [default = %d]\n", Prob ); 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_CommandSpeedup( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; int fUseLutLib; int Percentage; int Degree; int fVerbose; int fVeryVerbose; extern Abc_Ntk_t * Abc_NtkSpeedup( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fUseLutLib = 0; Percentage = 5; Degree = 2; fVerbose = 0; fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "PNlvwh" ) ) != EOF ) { switch ( c ) { case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } Percentage = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( Percentage < 1 || Percentage > 100 ) goto usage; break; case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } Degree = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( Degree < 1 || Degree > 5 ) goto usage; break; case 'l': fUseLutLib ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 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_Print( -1, "This command can only be applied to a logic network.\n" ); return 1; } // modify the current network pNtkRes = Abc_NtkSpeedup( pNtk, fUseLutLib, Percentage, Degree, fVerbose, fVeryVerbose ); 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: speedup [-PN ] [-lvwh]\n" ); Abc_Print( -2, "\t transforms LUT-mapped network into an AIG with choices;\n" ); Abc_Print( -2, "\t the choices are added to speedup the next round of mapping\n" ); Abc_Print( -2, "\t-P : delay delta defining critical path for library model [default = %d%%]\n", Percentage ); Abc_Print( -2, "\t-N : the max critical path degree for resynthesis (0 < num < 6) [default = %d]\n", Degree ); Abc_Print( -2, "\t-l : toggle using unit- or LUT-library-delay model [default = %s]\n", fUseLutLib? "lib" : "unit" ); Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [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_CommandPowerdown( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; int fUseLutLib; int Percentage; int Degree; int fVerbose; int fVeryVerbose; extern Abc_Ntk_t * Abc_NtkPowerdown( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fUseLutLib = 0; Percentage =10; Degree = 2; fVerbose = 0; fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "PNlvwh" ) ) != EOF ) { switch ( c ) { case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } Percentage = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( Percentage < 1 || Percentage > 100 ) goto usage; break; case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } Degree = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( Degree < 1 || Degree > 5 ) goto usage; break; case 'l': fUseLutLib ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 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_Print( -1, "This command can only be applied to a logic network.\n" ); return 1; } // modify the current network pNtkRes = Abc_NtkPowerdown( pNtk, fUseLutLib, Percentage, Degree, fVerbose, fVeryVerbose ); 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: powerdown [-PN ] [-vwh]\n" ); Abc_Print( -2, "\t transforms LUT-mapped network into an AIG with choices;\n" ); Abc_Print( -2, "\t the choices are added to power down the next round of mapping\n" ); Abc_Print( -2, "\t-P : switching propability delta defining power critical edges [default = %d%%]\n", Percentage ); Abc_Print( -2, "\t (e.g. 5% means hot wires switch with probability: 0.45 <= p <= 0.50 (max)\n" ); Abc_Print( -2, "\t-N : the max critical path degree for resynthesis (0 < num < 6) [default = %d]\n", Degree ); // Abc_Print( -2, "\t-l : toggle using unit- or LUT-library-delay model [default = %s]\n", fUseLutLib? "lib" : "unit" ); Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [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_CommandAddBuffs( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkAddBuffs( Abc_Ntk_t * pNtk, int fDirect, int fReverse, int nImprove, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Ntk_t * pNtkRes; int fDirect; int fReverse; int nImprove; int c, fVerbose; fDirect = 0; fReverse = 0; nImprove = 1000; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Idrvh" ) ) != 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; } nImprove = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nImprove < 0 ) goto usage; break; case 'd': fDirect ^= 1; break; case 'r': fReverse ^= 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_Print( -1, "This command can only be applied to a logic network.\n" ); return 1; } // modify the current network pNtkRes = Abc_NtkAddBuffs( pNtk, fDirect, fReverse, nImprove, fVerbose ); 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: addbuffs [-I num] [-drvh]\n" ); Abc_Print( -2, "\t adds buffers to create balanced CI/CO paths\n" ); Abc_Print( -2, "\t-I : the number of refinement iterations [default = %d]\n", nImprove ); Abc_Print( -2, "\t-d : toggle using only CI-to-CO levelized order [default = %s]\n", fDirect? "yes": "no" ); Abc_Print( -2, "\t-r : toggle using only CO-to-C1 levelized order [default = %s]\n", fReverse? "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; } //#if 0 /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandMerge( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Nwk_LMPars_t Pars, * pPars = &Pars; Vec_Int_t * vResult; int c; extern Vec_Int_t * Abc_NtkLutMerge( Abc_Ntk_t * pNtk, Nwk_LMPars_t * pPars ); // set defaults memset( pPars, 0, sizeof(Nwk_LMPars_t) ); pPars->nMaxLutSize = 5; // the max LUT size for merging (N=5) pPars->nMaxSuppSize = 5; // the max total support size after merging (S=5) pPars->nMaxDistance = 3; // the max number of nodes separating LUTs pPars->nMaxLevelDiff = 2; // the max difference in levels pPars->nMaxFanout = 100; // the max number of fanouts to traverse pPars->fUseDiffSupp = 0; // enables the use of nodes with different support pPars->fUseTfiTfo = 0; // enables the use of TFO/TFO nodes as candidates pPars->fVeryVerbose = 0; // enables additional verbose output pPars->fVerbose = 1; // enables verbose output Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NSDLFscvwh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } pPars->nMaxLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nMaxLutSize < 2 ) 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->nMaxSuppSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nMaxSuppSize < 2 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } pPars->nMaxDistance = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nMaxDistance < 2 ) goto usage; break; case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } pPars->nMaxLevelDiff = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nMaxLevelDiff < 2 ) goto usage; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nMaxFanout = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nMaxFanout < 2 ) goto usage; break; case 's': pPars->fUseDiffSupp ^= 1; break; case 'c': pPars->fUseTfiTfo ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL || !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "Abc_CommandMerge(): There is no mapped network to merge LUTs.\n" ); return 1; } vResult = Abc_NtkLutMerge( pNtk, pPars ); Vec_IntFree( vResult ); return 0; usage: Abc_Print( -2, "usage: merge [-NSDLF ] [-scwvh]\n" ); Abc_Print( -2, "\t creates pairs of topologically-related LUTs\n" ); Abc_Print( -2, "\t-N : the max LUT size for merging (1 < num) [default = %d]\n", pPars->nMaxLutSize ); Abc_Print( -2, "\t-S : the max total support size after merging (1 < num) [default = %d]\n", pPars->nMaxSuppSize ); Abc_Print( -2, "\t-D : the max distance in terms of LUTs (0 < num) [default = %d]\n", pPars->nMaxDistance ); Abc_Print( -2, "\t-L : the max difference in levels (0 <= num) [default = %d]\n", pPars->nMaxLevelDiff ); Abc_Print( -2, "\t-F : the max number of fanouts to stop traversal (0 < num) [default = %d]\n", pPars->nMaxFanout ); Abc_Print( -2, "\t-s : toggle the use of nodes without support overlap [default = %s]\n", pPars->fUseDiffSupp? "yes" : "no" ); Abc_Print( -2, "\t-c : toggle the use of TFI/TFO nodes as candidates [default = %s]\n", pPars->fUseTfiTfo? "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-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } //#endif /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandTestDec( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_DecTest( char * pFileName, int DecType, int nVarNum, int fVerbose ); char * pFileName; int c; int fVerbose = 0; int DecType = 0; int nVarNum = -1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ANvh" ) ) != EOF ) { switch ( c ) { case 'A': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" ); goto usage; } DecType = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( DecType < 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; } nVarNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nVarNum < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { Abc_Print( 1,"Input file is not given.\n" ); return 0; } if ( nVarNum >= 0 && nVarNum < 6 ) { Abc_Print( 1,"The number of variables cannot be less than 6.\n" ); return 0; } // get the output file name pFileName = argv[globalUtilOptind]; // call the testbench Abc_DecTest( pFileName, DecType, nVarNum, fVerbose ); return 0; usage: Abc_Print( -2, "usage: testdec [-AN ] [-vh] \n" ); Abc_Print( -2, "\t testbench for Boolean decomposition algorithms\n" ); Abc_Print( -2, "\t-A : decomposition algorithm [default = %d]\n", DecType ); Abc_Print( -2, "\t 0: none (reading and writing the file)\n" ); Abc_Print( -2, "\t 1: algebraic factoring applied to ISOP\n" ); Abc_Print( -2, "\t 2: bi-decomposition with cofactoring\n" ); Abc_Print( -2, "\t 3: disjoint-support decomposition with cofactoring\n" ); Abc_Print( -2, "\t 4: updated disjoint-support decomposition with cofactoring\n" ); Abc_Print( -2, "\t 5: enumerating decomposable variable sets\n" ); Abc_Print( -2, "\t 6: disjoint-support decomposition with cofactoring and boolean difference analysis\n" ); Abc_Print( -2, "\t from V. Callegaro, F. S. Marranghello, M. G. A. Martins, R. P. Ribas and A. I. Reis,\n"); Abc_Print( -2, "\t \"Bottom-up disjoint-support decomposition based on cofactor and boolean difference analysis,\" ICCD'15.\n" ); Abc_Print( -2, "\t-N : the number of support variables (binary files only) [default = unused]\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"); Abc_Print( -2, "\t : a text file with truth tables in hexadecimal, listed one per line,\n"); Abc_Print( -2, "\t or a binary file with an array of truth tables (in this case,\n"); Abc_Print( -2, "\t -N is required to determine how many functions are stored)\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandTestNpn( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_NpnTest( char * pFileName, int NpnType, int nVarNum, int fDumpRes, int fBinary, int fVerbose ); char * pFileName; int c; int fVerbose = 0; int NpnType = 0; int nVarNum = -1; int fDumpRes = 0; int fBinary = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ANdbvh" ) ) != EOF ) { switch ( c ) { case 'A': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" ); goto usage; } NpnType = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( NpnType < 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; } nVarNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nVarNum < 0 ) goto usage; break; case 'd': fDumpRes ^= 1; break; case 'b': fBinary ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { Abc_Print( 1,"Input file is not given.\n" ); return 0; } if ( nVarNum >= 0 && nVarNum < 6 ) { Abc_Print( 1,"The number of variables cannot be less than 6.\n" ); return 0; } // get the output file name pFileName = argv[globalUtilOptind]; // call the testbench Abc_NpnTest( pFileName, NpnType, nVarNum, fDumpRes, fBinary, fVerbose ); return 0; 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 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" ); Abc_Print( -2, "\t 2: semi-canonical form by counting 1s in cofactors\n" ); Abc_Print( -2, "\t 3: Jake's hybrid semi-canonical form (fast)\n" ); Abc_Print( -2, "\t 4: Jake's hybrid semi-canonical form (high-effort)\n" ); 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 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" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : a text file with truth tables in hexadecimal, listed one per line,\n"); Abc_Print( -2, "\t or a binary file with an array of truth tables (in this case,\n"); Abc_Print( -2, "\t -N is required to determine how many functions are stored)\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandTestRPO(Abc_Frame_t * pAbc, int argc, char ** argv) { extern int Abc_RpoTest(char * pFileName, int nVarNum, int nThreshold, int fVerbose); char * pFileName; int c; int nVarNum = -1; int fVerbose = 0; int nThreshold = -1; Extra_UtilGetoptReset(); while ((c = Extra_UtilGetopt(argc, argv, "TNvh")) != EOF) { switch (c) { case 'N': if (globalUtilOptind >= argc) { Abc_Print(-1, "Command line switch \"-N\" should be followed by an integer.\n"); goto usage; } nVarNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if (nVarNum < 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; } nThreshold = atoi(argv[globalUtilOptind]); globalUtilOptind++; if (nThreshold < 0) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if (argc != globalUtilOptind + 1) { Abc_Print(1, "Input file is not given.\n"); goto usage; } // get the output file name pFileName = argv[globalUtilOptind]; // call the testbench Abc_RpoTest( pFileName, nVarNum, nThreshold, fVerbose ); return 0; usage: Abc_Print(-2, "usage: testrpo [-NT ] [-vh] \n"); Abc_Print(-2, "\t RPO algorithm developed and implemented by Mayler G. A. Martins,\n"); Abc_Print(-2, "\t Vinicius Callegaro, Renato P. Ribas and Andre' I. Reis\n"); Abc_Print(-2, "\t at Federal University of Rio Grande do Sul, Porto Alegre, Brazil\n"); Abc_Print(-2, "\t-N : the number of support variables (binary files only) [default = unused]\n"); Abc_Print(-2, "\t-T : the number of recursions accepted before abort [default = INFINITE]\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"); Abc_Print(-2, "\t : a text file with truth tables in hexadecimal, listed one per line,\n"); Abc_Print(-2, "\t or a binary file with an array of truth tables (in this case,\n"); Abc_Print(-2, "\t -N is required to determine how many functions are stored)\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandTestTruth( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int * Kit_TruthTest( char * pFileName ); int * pResult = NULL; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { Abc_Print( 1,"Input file is not given.\n" ); return 0; } pResult = Kit_TruthTest( argv[globalUtilOptind] ); ABC_FREE( pResult ); return 0; usage: 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; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandTestSupp( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkSuppMinFile( char * pFileName ); 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 ( argc != globalUtilOptind + 1 ) { Abc_Print( 1,"Input file is not given.\n" ); return 0; } Abc_NtkSuppMinFile( argv[globalUtilOptind] ); return 0; usage: Abc_Print( -2, "usage: testsupp [-vh] \n" ); Abc_Print( -2, "\t reads truth tables from file and support-minimizes them\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"); Abc_Print( -2, "\t : file to read the truth tables from\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandTestRand( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkRandFile( char * pFileName, int nVars, int nFuncs, int nMints ); int c, nVars = 0, nFuncs = 0, nMints = 0, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NFMvh" ) ) != 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 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nFuncs = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } nMints = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { Abc_Print( 1,"Input file is not given.\n" ); return 0; } Abc_NtkRandFile( argv[globalUtilOptind], nVars, nFuncs, nMints ); return 0; usage: Abc_Print( -2, "usage: testrand [-NFMvh] \n" ); Abc_Print( -2, "\t generates truth tables and writes them into a file\n" ); Abc_Print( -2, "\t-N : the number of input variables [default = %d]\n", nVars ); Abc_Print( -2, "\t-F : the number of random functions to generate [default = %d]\n", nFuncs ); Abc_Print( -2, "\t-M : the number of positive minterms in the random function [default = %d]\n", nMints ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : file to write the truth tables to\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandRunSat( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pFile = NULL; char * pFileCnf = NULL; int c, i, fWalk = 0, fKissat = 0, nIters = 10, fVerbose = 0; abctime clk; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Ikwvh" ) ) != 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 'k': fKissat ^= 1; break; case 'w': fWalk ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( fKissat + fWalk != 1 ) { printf( "Exactly one SAT solver should be selected.\n" ); return 1; } if ( argc != globalUtilOptind + 1 ) goto usage; pFileCnf = argv[globalUtilOptind]; pFile = fopen( pFileCnf, "rb" ); if ( pFile == NULL ) { printf( "The file \"%s\" cannot be found.\n", pFileCnf ); return 1; } fclose( pFile ); clk = Abc_Clock(); for ( i = 0; i < nIters; i++ ) { char pCommand[1000]; if ( fKissat ) sprintf( pCommand, "kissat -q --seed=%d %s", i, pFileCnf ); else if ( fWalk ) sprintf( pCommand, "walk -s%d %s", i, pFileCnf ); #if defined(__wasm) if (1) { #else if (system(pCommand) == -1) { #endif fprintf(stdout, "Command \"%s\" did not succeed.\n", pCommand); return 0; } } printf( "Performed %d iterations of SAT solving. ", nIters ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); return 0; usage: Abc_Print( -2, "usage: runsat [-I num] [-kwvh] \n" ); Abc_Print( -2, "\t performs randomized iterations of SAT solving\n" ); Abc_Print( -2, "\t-I num : the number of iterations [default = %d]\n", nIters ); Abc_Print( -2, "\t-k : toggle using Kissat (binary name \"kissat\") [default = %s]\n", fKissat? "yes": "no" ); Abc_Print( -2, "\t-w : toggle using WalkSat (binary name \"walk\") [default = %s]\n", fWalk? "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_CommandRunEco( Abc_Frame_t * pAbc, int argc, char ** argv ) { 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, "Tcriuvwh" ) ) != EOF ) { switch ( c ) { case 'T': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); goto usage; } nTimeout = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nTimeout < 0 ) goto usage; break; case 'c': fCheck ^= 1; break; case 'r': fRandom ^= 1; break; case 'i': fInputs ^= 1; break; case 'u': fUnitW ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } // pArgvNew = argv + globalUtilOptind; // nArgcNew = argc - globalUtilOptind; if ( argc - globalUtilOptind < 2 || argc - globalUtilOptind > 3 ) { Abc_Print( 1, "Expecting three file names on the command line.\n" ); goto usage; } for ( c = 0; c < argc - globalUtilOptind; c++ ) { 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]; } 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( int nInputs, int nMints, int nFuncs, int Seed, int fVerbose, char * pScript ); int c, nInputs = 10, nMints = 10, nFuncs = 10, Seed = 0, fVerbose = 0; char * pScript = NULL; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "IMRSCvh" ) ) != EOF ) { switch ( c ) { case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } nInputs = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } nMints = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } nFuncs = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } Seed = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by a script.\n" ); goto usage; } pScript = argv[globalUtilOptind]; globalUtilOptind++; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pScript == NULL ) { Abc_Print( -1, "Command line switch \"-C\" should be specified and followed by a string.\n" ); goto usage; } Acb_NtkRunGen( nInputs, nMints, nFuncs, Seed, fVerbose, pScript ); return 0; usage: Abc_Print( -2, "usage: rungen [-IMRS num] [-C script] [-vh]\n" ); Abc_Print( -2, "\t running the script on a set of randomly generated functions\n" ); Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", nInputs ); Abc_Print( -2, "\t-M : the number of positive minterms in the random function [default = %d]\n", nMints ); Abc_Print( -2, "\t-R : the number of random functions to try [default = %d]\n", nFuncs ); Abc_Print( -2, "\t-S : the random seed [default = %d]\n", Seed ); Abc_Print( -2, "\t-C : the script to apply [default = provided by the user]\n" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**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 ) { 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: 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; } /**Function************************************************************* Synopsis [] Description [Orchestration synthesis] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandOrchestrate( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pDup; int c, RetValue; int nNodeSizeMax; int nConeSizeMax; int fUpdateLevel; int fUseZeros_rwr; int fUseZeros_ref; int fUseDcs; 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_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, "KNFZzlvwh" ) ) != EOF ) { switch ( c ) { 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; } nNodesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nNodesMax < 0 ) goto usage; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nLevelsOdc = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLevelsOdc < 0 ) goto usage; break; case 'l': fUpdateLevel ^= 1; break; case 'z': fUseZeros_rwr ^= 1; break; case 'Z': fUseZeros_ref ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': 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" ); 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_NtkOrchLocal( pNtk, fUseZeros_rwr, fUseZeros_ref, fPlaceEnable, nCutsMax, nNodesMax, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose, nNodeSizeMax, nConeSizeMax, fUseDcs ); 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, "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 [AIG RTL Augmentation] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAIGAugmentation( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pDup; int c, RetValue; int nNodeSizeMax; int nConeSizeMax; int fUpdateLevel; int fUseZeros_rwr; int fUseZeros_ref; int fUseDcs; int fVerbose; int RS_CUT_MIN = 4; int RS_CUT_MAX = 16; int fPrecompute; int fPlaceEnable; int nNodesMax; int nCutsMax; int nLevelsOdc; int fVeryVerbose; int Rand_Seed; //int sOpsOrder; size_t NtkSize; char *DecisionFile = NULL; Vec_Int_t *DecisionMask; Vec_Int_t *pGain_rwr; Vec_Int_t *pGain_res; Vec_Int_t *pGain_ref; //FILE *maskFile; extern void Rwr_Precompute(); extern int Abc_NtkOrchRand( Abc_Ntk_t * pNtk, Vec_Int_t **pGain_rwr, Vec_Int_t **pGain_res,Vec_Int_t **pGain_ref, Vec_Int_t **DecisionMask, char *DecisionFile, int Rand_Seed, 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_rwr = 0; fUseZeros_ref = 0; fUseDcs = 0; fVerbose = 0; fVeryVerbose = 0; fPlaceEnable = 0; fPrecompute = 0; nCutsMax = 8; nNodesMax = 1; nLevelsOdc = 0; Rand_Seed = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "zZdsh" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; break; case 'z': fUseZeros_rwr ^= 1; break; case 'Z': fUseZeros_ref ^= 1; break; case 'd': if ( globalUtilOptind >= argc ) { goto usage; } DecisionFile = argv[globalUtilOptind]; globalUtilOptind++; break; case 's': if ( globalUtilOptind >= argc ) { goto usage; } Rand_Seed = atoi(argv[globalUtilOptind]); globalUtilOptind++; 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" ); 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; } NtkSize = Abc_NtkObjNumMax(pNtk); DecisionMask = Vec_IntAlloc(1); for (int i=0; inSize, DecisionList->pArray[0]); 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, "Orchestration evaluation for RL has failed.\n" ); return 1; } } // Vec_IntPrint(pGain_rwr); return 0; usage: Abc_Print( -2, "usage: aigaug [-s ] [-d ][-zZdsh]\n" ); Abc_Print( -2, "\t performs technology-independent AIG random synthesis (node level) for RTL augmentation\n" ); Abc_Print( -2, "\t-z : toggle using zero-cost replacements for rwr for aigaug [default = %s]\n", fUseZeros_rwr? "yes": "no" ); Abc_Print( -2, "\t-Z : toggle using zero-cost replacements for ref for aigaug [default = %s]\n", fUseZeros_ref? "yes": "no" ); Abc_Print( -2, "\t-d : record random synthesis decision made during augmentation [required filename; e.g., test.csv]\n"); Abc_Print( -2, "\t-s : set the random seed for random augmentation\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"); Abc_Print( -2, "\tExample : read i10.aig;st;aigaug -s 1 -d test.csv;write i10_arg_1.aig;cec i10.aig i10_arg_1.aig\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: 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" ); // Abc_Print( -2, "\t-d : toggle using don't-cares [default = %s]\n", fUseDcs? "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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandRestructure( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int nCutsMax; int fUpdateLevel; int fUseZeros; int fVerbose; extern int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutsMax, int fUpdateLevel, int fUseZeros, int fVerbose ); // set defaults nCutsMax = 5; fUpdateLevel = 0; fUseZeros = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Klzvh" ) ) != EOF ) { switch ( c ) { 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 'l': fUpdateLevel ^= 1; break; case 'z': fUseZeros ^= 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 ( nCutsMax < 4 || nCutsMax > CUT_SIZE_MAX ) { Abc_Print( -1, "Can only compute the cuts for %d <= K <= %d.\n", 4, CUT_SIZE_MAX ); 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 if ( !Abc_NtkRestructure( pNtk, nCutsMax, fUpdateLevel, fUseZeros, fVerbose ) ) { Abc_Print( -1, "Refactoring has failed.\n" ); return 1; } return 0; usage: Abc_Print( -2, "usage: restructure [-K ] [-lzvh]\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", CUT_SIZE_MIN, CUT_SIZE_MAX, nCutsMax ); 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-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int RS_CUT_MIN = 4; int RS_CUT_MAX = 16; int c; 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 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, "KNMFlzvwh" ) ) != EOF ) { switch ( c ) { 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; } nNodesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; 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 ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nLevelsOdc = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLevelsOdc < 0 ) goto usage; break; case 'l': fUpdateLevel ^= 1; break; case 'z': fUseZeros ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 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 ( 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 ( nNodesMax < 0 || nNodesMax > 3 ) { Abc_Print( -1, "Can only resubstitute at most 3 nodes.\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 if ( !Abc_NtkResubstitute( pNtk, nCutsMax, nNodesMax, nMinSaved, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose ) ) { Abc_Print( -1, "Refactoring has failed.\n" ); return 1; } return 0; usage: 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" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle verbose printout of ODC computation [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_CommandResubUnate( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManResubUnateOne( char * pFileName, int nLimit, int nDivMax, int fWriteSol, int fVerbose ); Gia_Man_t * pTemp; int nLimit = 16; int nDivMax = 50; int fWriteSol = 0; int fVerbose = 0, c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "LDsvh" ) ) != EOF ) { switch ( c ) { case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } nLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLimit < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } nDivMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nDivMax < 0 ) goto usage; break; case 's': fWriteSol ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { Abc_Print( -1, "Input file should be given on the command line.\n" ); return 1; } pTemp = Gia_ManResubUnateOne( argv[globalUtilOptind], nLimit, nDivMax, fWriteSol, fVerbose ); if ( pTemp ) { Aig_Man_t * pMan = Gia_ManToAig( pTemp, 0 ); Abc_Ntk_t * pNtk = Abc_NtkFromAigPhase( pMan ); Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Aig_ManStop( pMan ); Gia_ManStop( pTemp ); return 0; } Abc_Print( 0, "The networks is not generated.\n" ); return 0; usage: Abc_Print( -2, "usage: resub_unate [-LD ] [-svh] \n" ); Abc_Print( -2, "\t solves one instance of the resub problem\n" ); Abc_Print( -2, "\t-L num : the limit on the number of nodes [default = %d]\n", nLimit ); Abc_Print( -2, "\t-D num : the maximum number of binate divisors to consider [default = %d]\n", nDivMax ); Abc_Print( -2, "\t-s : toggle saving the result in the input file [default = %s]\n", fWriteSol? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : resub problem file name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandResubCore( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Supp_ManSolveOne( char * pFileName, int nIters, int nRounds, int fWriteSol, int fVerbose ); Gia_Man_t * pTemp; int nIters = 1; int nRounds = 1; int fWriteSol = 0; int fVerbose = 0, c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "IRsvh" ) ) != EOF ) { switch ( c ) { case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } nIters = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nIters < 0 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } nRounds = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nRounds < 0 ) goto usage; break; case 's': fWriteSol ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { Abc_Print( -1, "Input file should be given on the command line.\n" ); return 1; } pTemp = Supp_ManSolveOne( argv[globalUtilOptind], nIters, nRounds, fWriteSol, fVerbose ); if ( pTemp ) { Aig_Man_t * pMan = Gia_ManToAig( pTemp, 0 ); Abc_Ntk_t * pNtk = Abc_NtkFromAigPhase( pMan ); Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); Aig_ManStop( pMan ); Gia_ManStop( pTemp ); return 0; } Abc_Print( 0, "The networks is not generated.\n" ); return 0; usage: Abc_Print( -2, "usage: resub_core [-IR ] [-svh] \n" ); Abc_Print( -2, "\t solves one instance of the resub problem\n" ); Abc_Print( -2, "\t-I num : the number of iterations [default = %d]\n", nIters ); Abc_Print( -2, "\t-R num : the number of rounds in each iteration [default = %d]\n", nRounds ); Abc_Print( -2, "\t-s : toggle saving the result in the input file [default = %s]\n", fWriteSol? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : resub problem file name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandResubCheck( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Res6_ManResubCheck( char * pFileNameRes, char * pFileNameSol, int fVerbose ); extern void Res6_ManResubCheckPla( char * pFileName, int fVerbose ); char * pFileR = NULL, * pFileS = NULL; int fVerbose = 0, c; Extra_UtilGetoptReset(); 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; } if ( !strcmp(pFileR + strlen(pFileR) - 3, "pla") ) Res6_ManResubCheckPla( pFileR, fVerbose ); else 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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandRr( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c, Window; int nFaninLevels; int nFanoutLevels; int fUseFanouts; int fVerbose; extern int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose ); // set defaults nFaninLevels = 3; nFanoutLevels = 3; fUseFanouts = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Wfvh" ) ) != EOF ) { switch ( c ) { case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } Window = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( Window < 0 ) goto usage; nFaninLevels = Window / 10; nFanoutLevels = Window % 10; break; case 'f': fUseFanouts ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } printf( "This command is obsolete." ); printf( "To perform pure redudancy removal, try \"mfs -r\".\n" ); printf( "To perform something a little stronger try \"mfs2\"\n" ); printf( "When working with an AIG, use \"logic\" before and \"strash\" after this command.\n" ); 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 if ( !Abc_NtkRR( pNtk, nFaninLevels, nFanoutLevels, fUseFanouts, fVerbose ) ) { Abc_Print( -1, "Redundancy removal has failed.\n" ); return 1; } return 0; usage: Abc_Print( -2, "usage: rr [-W NM] [-fvh]\n" ); Abc_Print( -2, "\t removes combinational redundancies in the current network\n" ); Abc_Print( -2, "\t-W NM : window size: TFI (N) and TFO (M) logic levels [default = %d%d]\n", nFaninLevels, nFanoutLevels ); Abc_Print( -2, "\t-f : toggle RR w.r.t. fanouts [default = %s]\n", fUseFanouts? "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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, nLutSize; int fCheck; int fVerbose; extern Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nLutSize = 12; fCheck = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Kcvh" ) ) != 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 'c': fCheck ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty neAtwork.\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_NtkCascade( pNtk, nLutSize, fCheck, fVerbose ); else { pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); pNtkRes = Abc_NtkCascade( pNtk, nLutSize, fCheck, fVerbose ); Abc_NtkDelete( pNtk ); } if ( pNtkRes == NULL ) { Abc_Print( -1, "Cascade synthesis has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: cascade [-K ] [-cvh]\n" ); Abc_Print( -2, "\t performs LUT cascade synthesis for the current network\n" ); Abc_Print( -2, "\t-K : the number of LUT inputs [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-c : check equivalence after synthesis [default = %s]\n", fCheck? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t \n"); Abc_Print( -2, " A lookup-table cascade is a programmable architecture developed by\n"); Abc_Print( -2, " Professor Tsutomu Sasao (sasao@cse.kyutech.ac.jp) at Kyushu Institute\n"); Abc_Print( -2, " of Technology. This work received Takeda Techno-Entrepreneurship Award:\n"); Abc_Print( -2, " http://www.lsi-cad.com/sasao/photo/takeda.html\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkLutCascadeGen( int nLutSize, int nStages, int nRails, int nShared, int fVerbose ); extern Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose, char * pGuide ); extern void Abc_NtkLutCascadeFile( char * pFileName, int nVarNum, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose, int fVeryVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; char * pGuide = NULL, * pFileName = NULL; int c, nVarNum = -1, nLutSize = 6, nStages = 8, nRails = 1, nShared = 2, nIters = 10, fGen = 0, fVerbose = 0, fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KMRSINFgvwh" ) ) != 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 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } nStages = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nStages < 0 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } nRails = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nRails < 0 ) goto usage; break; case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } nShared = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nShared < 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 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } nVarNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nVarNum < 0 ) goto usage; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by a file name.\n" ); goto usage; } pFileName = argv[globalUtilOptind]; globalUtilOptind++; break; case 'g': fGen ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pFileName ) { if ( nVarNum == -1 ) { Abc_Print( -1, "The number of variables should be given on the command line using switch \"-N \".\n" ); return 1; } Abc_NtkLutCascadeFile( pFileName, nVarNum, nLutSize, nStages, nRails, nIters, fVerbose, fVeryVerbose ); return 1; } if ( fGen ) { pNtkRes = Abc_NtkLutCascadeGen( nLutSize, nStages, nRails, nShared, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "LUT cascade generation failed.\n" ); return 1; } Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Abc_NtkCoNum(pNtk) != 1 ) { Abc_Print( -1, "This command is currently applicable only to single-output networks.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Run command \"strash\" to convert the network into an AIG.\n" ); return 1; } if ( Abc_NtkCiNum(pNtk) > nLutSize + (nLutSize - nRails) * (nStages - 1) ) { Abc_Print( -1, "Cannot decompose %d-input function into a %d-rail cascade of %d %d-LUTs (max suppose size = %d).\n", Abc_NtkCiNum(pNtk), nRails, nStages, nLutSize, nLutSize + (nLutSize - nRails) * (nStages - 1) ); return 1; } if ( argc == globalUtilOptind + 1 ) pGuide = argv[globalUtilOptind]; pNtkRes = Abc_NtkLutCascade2( pNtk, nLutSize, nStages, nRails, nIters, fVerbose, pGuide ); if ( pNtkRes == NULL ) { Abc_Print( -1, "LUT cascade mapping failed.\n" ); return 1; } Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: lutcasdec [-KMRSIN ] [-F ] [-vwh]\n" ); Abc_Print( -2, "\t decomposes the primary output functions into LUT cascades\n" ); Abc_Print( -2, "\t-K : the number of LUT inputs [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-M : the maximum delay (the number of stages) [default = %d]\n", nStages ); Abc_Print( -2, "\t-R : the number of direct connections (rails) [default = %d]\n", nRails ); Abc_Print( -2, "\t-S : the number of shared variables in each stage [default = %d]\n", nShared ); Abc_Print( -2, "\t-I : the number of iterations when looking for a solution [default = %d]\n", nIters ); Abc_Print( -2, "\t-N : the number of support variables (for truth table files only) [default = unused]\n" ); Abc_Print( -2, "\t-F : a text file with truth tables in hexadecimal listed one per line\n"); Abc_Print( -2, "\t-g : toggle generating random cascade with these parameters [default = %s]\n", fGen? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle additional verbose printout [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_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkLutCascadeMap( Abc_Ntk_t * pNtk, int nLutsMax, int nIters, int fDelayLut, int fDelayRoute, int fDelayDirect, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; int c, nLutSize = 6, nLutsMax = 8, nIters = 1000, Seed = 0, fVerbose = 0; int fDelayLut = 10, fDelayRoute = 30, fDelayDirect = 3; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KMISLWDfvh" ) ) != 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 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } nLutsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLutsMax < 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 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } fDelayLut = atof(argv[globalUtilOptind]); globalUtilOptind++; if ( fDelayLut < 0 ) goto usage; break; case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } fDelayRoute = atof(argv[globalUtilOptind]); globalUtilOptind++; if ( fDelayRoute < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } fDelayDirect = atof(argv[globalUtilOptind]); globalUtilOptind++; if ( fDelayDirect < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "Run command \"if\" or any other LUT mapper to map the current network into LUTs.\n" ); return 1; } if ( Abc_NtkGetFaninMax(pNtk) > nLutSize ) { Abc_Print( -1, "The current network contains nodes with fanin count (%d) exceeding the LUT size (%d).\n", Abc_NtkGetFaninMax(pNtk), nLutSize ); return 1; } srand( Seed ); pNtkRes = Abc_NtkLutCascadeMap( pNtk, nLutsMax, nIters, fDelayLut, fDelayRoute, fDelayDirect, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "LUT cascade mapping failed.\n" ); return 1; } Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: lutcas [-KMISLWD ] [-vh]\n" ); Abc_Print( -2, "\t decomposes the current network into LUT cascades\n" ); Abc_Print( -2, "\t-K : the number of LUT inputs [default = %d]\n", nLutSize ); Abc_Print( -2, "\t-M : the maximum number of LUTs in the cascade [default = %d]\n", nLutsMax ); Abc_Print( -2, "\t-I : the number of iterations when looking for a solution [default = %d]\n", nIters ); Abc_Print( -2, "\t-S : the random seed used to randimize solutions [default = %d]\n", Seed ); Abc_Print( -2, "\t-L : the intrinsic LUT delay [default = %d]\n", fDelayLut ); Abc_Print( -2, "\t-W : the routable wire delay [default = %d]\n", fDelayRoute ); Abc_Print( -2, "\t-D : the non-routable wire delay [default = %d]\n", fDelayDirect ); 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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBsEval( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_BSEvalOneTest( word * pT, int nVars, int nBVars, int fVerbose ); extern void Abc_BSEvalBestTest( word * pIn, int nVars, int nBVars, int fShared, int fVerbose ); extern void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryAll, int fShared, int fVerbose ); int c, nVars = 0, nBVars = 0, nSVars = 0, nFuncs = 0, nMints = 0, fTryAll = 0, fVerbose = 0; char * pTtStr = NULL; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "IBSRMavh" ) ) != EOF ) { switch ( c ) { 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 < 2 || nVars > 16 ) goto usage; break; case 'B': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); goto usage; } nBVars = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nBVars < 1 || nBVars > 16 ) goto usage; break; case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } nSVars = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nSVars < 0 || nSVars > 16 ) goto usage; break; case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } nFuncs = atoi(argv[globalUtilOptind]); if ( nFuncs < 1 ) goto usage; globalUtilOptind++; break; case 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } nMints = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'a': fTryAll ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc == globalUtilOptind + 1 ) pTtStr = argv[globalUtilOptind]; if ( pTtStr ) { nVars = Abc_Base2Log((int)strlen(pTtStr)) + 2; if ( (1 << (nVars-2)) != (int)strlen(pTtStr) ) { Abc_Print( -1, "Truth table is expected to have %d hex digits (instead of %d).\n", (1 << (nVars-2)), strlen(pTtStr) ); return 1; } } if ( nVars == 0 ) { Abc_Print( -1, "The number of variables should be specified on the command line.\n" ); return 1; } if ( nBVars == 0 ) { Abc_Print( -1, "The bound set size should be specified on the command line.\n" ); return 1; } if ( nFuncs ) Abc_BSEvalBestGen( nVars, nBVars, nFuncs, nMints, fTryAll, nSVars == 1, fVerbose ); else if ( pTtStr ) { word pTruth[1024] = {0}; Abc_TtReadHex( pTruth, pTtStr ); if ( fTryAll ) Abc_BSEvalBestTest( pTruth, nVars, nBVars, nSVars == 1, fVerbose ); else Abc_BSEvalOneTest( pTruth, nVars, nBVars, fVerbose ); } return 0; usage: Abc_Print( -2, "usage: bseval [-IBSRM ] [-avh] \n" ); Abc_Print( -2, "\t bound set evaluation\n" ); Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", nVars ); Abc_Print( -2, "\t-B : the number of bound set variables [default = %d]\n", nBVars ); Abc_Print( -2, "\t-S : the number of shared variables [default = %d]\n", nSVars ); Abc_Print( -2, "\t-R : the number of random functions to try [default = unused]\n" ); Abc_Print( -2, "\t-M : the number of positive minterms in the random function [default = unused]\n" ); Abc_Print( -2, "\t-a : toggle trying all bound sets of this size [default = %s]\n", fTryAll ? "yes" : "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" ); Abc_Print( -2, "\t-h : print the command usage\n" ); Abc_Print( -2, "\t : truth table in hex notation\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandExtract( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkShareXor( Abc_Ntk_t * pNtk, int nMultiSize, int fAnd, int fVerbose ); Abc_Ntk_t * pNtk, * pNtkRes; int c, nMultiSize, fAnd, fVerbose; pNtk = Abc_FrameReadNtk(pAbc); // set defaults nMultiSize = 3; fAnd = 0; 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': fAnd ^= 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Can only collapse a logic network or an AIG.\n" ); return 1; } // get the new network pNtkRes = Abc_NtkShareXor( pNtk, nMultiSize, fAnd, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Cascade synthesis has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: extract [-K ] [-avh]\n" ); Abc_Print( -2, "\t extracts shared logic from multi-input gates\n" ); Abc_Print( -2, "\t-K : the minimum gate size to consider for extraction [default = %d]\n", nMultiSize ); Abc_Print( -2, "\t-a : toggle multi-input XOR vs multi-input AND [default = %s]\n", fAnd? "AND": "XOR" ); 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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandVarMin( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_SuppTest( int nOnes, int nVars, int fUseSimple, int fCheck, int fVerbose ); extern void Abc_SuppReadMinTest( char * pFileName ); int nOnes = 4; int nVars = 20; int fUseSimple = 0; int fCheck = 0; int fVerbose = 0; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "MNocvh" ) ) != EOF ) { switch ( c ) { case 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } nOnes = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nOnes < 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 'o': fUseSimple ^= 1; break; case 'c': fCheck ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } // get the file name if ( argc == globalUtilOptind + 1 ) { Abc_SuppReadMinTest( argv[globalUtilOptind] ); return 0; } Abc_SuppTest( nOnes, nVars, fUseSimple, fCheck, fVerbose ); return 0; usage: Abc_Print( -2, "usage: varmin [-MN ] [-ocvh]\n" ); Abc_Print( -2, "\t performs support minimization\n" ); Abc_Print( -2, "\t-M : the number of ones in the combination [default = %d]\n", nOnes ); Abc_Print( -2, "\t-N : the number of variables in the problem [default = %d]\n", nVars ); Abc_Print( -2, "\t-o : toggle computing reduced difference matrix [default = %s]\n", fUseSimple? "yes": "no" ); Abc_Print( -2, "\t-c : toggle verifying the final result [default = %s]\n", fCheck? "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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandFaultClasses( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose, int fVeryVerbose ); extern void Abc_NtkGenFaultList( Abc_Ntk_t * pNtk, char * pFileName, int fStuckAt ); Abc_Ntk_t * pNtk; int c, fGen = 0, fStuckAt = 0, fSeq = 0, fVerbose = 0, fVeryVerbose = 0; pNtk = Abc_FrameReadNtk(pAbc); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "gcsvwh" ) ) != EOF ) { switch ( c ) { case 'g': fGen ^= 1; break; case 'c': fStuckAt ^= 1; break; case 's': fSeq ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 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, "Only applicable to a logic network.\n" ); return 1; } if ( fGen ) { char * pFileName = Extra_FileNameGenericAppend(Abc_NtkSpec(pNtk), "_faults.txt"); Abc_NtkGenFaultList( pNtk, pFileName, fStuckAt ); } else Abc_NtkDetectClassesTest( pNtk, fSeq, fVerbose, fVeryVerbose ); return 0; usage: Abc_Print( -2, "usage: faultclasses [-gcsvwh]\n" ); Abc_Print( -2, "\t computes equivalence classes of faults in the given mapped netlist;\n" ); Abc_Print( -2, "\t the fault list with faults in the format: \n" ); Abc_Print( -2, "\t should be read by command \"read_fins\" before calling this command\n" ); Abc_Print( -2, "\t-g : toggle generating a fault list for the current mapped network [default = %s]\n", fGen? "yes": "no" ); Abc_Print( -2, "\t-c : toggle using only stuck-at faults in the generated fault list [default = %s]\n", fStuckAt? "yes": "no" ); Abc_Print( -2, "\t-s : toggle detecting sequential equivalence classes [default = %s]\n", fSeq? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout during computation [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing of resulting fault equivalence classes [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_CommandExact( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Gia_Man_t * Gia_ManFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrivalTimes, int nBTLimit, int nStartGates, int fVerbose ); int c, nMaxDepth = -1, fMakeAIG = 0, fTest = 0, fVerbose = 0, nVars = 0, nVarsTmp, nFunc = 0, nStartGates = 1, nBTLimit = 400000; char * p1, * p2; word pTruth[64]; int pArrTimeProfile[8], fHasArrTimeProfile = 0; Abc_Ntk_t * pNtkRes; Gia_Man_t * pGiaRes; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "DASCatvh" ) ) != EOF ) { switch ( c ) { case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } nMaxDepth = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nMaxDepth < 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; } fHasArrTimeProfile = 1; p1 = p2 = argv[globalUtilOptind++]; while ( true ) { if ( *p2 == ',' ) { *p2 = '\0'; pArrTimeProfile[nVars++] = atoi( p1 ); *p2++ = ','; p1 = p2; } else if ( *p2 == '\0' ) { pArrTimeProfile[nVars++] = atoi( p1 ); break; } else ++p2; } break; case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } nStartGates = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nStartGates < 1 ) goto usage; break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } nBTLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'a': fMakeAIG ^= 1; break; case 't': fTest ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( fTest ) { extern void Abc_ExactTest( int fVerbose ); extern void Abc_ExactStoreTest( int fVerbose ); printf( "run test suite, ignore all other settings\n" ); Abc_ExactTest( fVerbose ); Abc_ExactStoreTest( fVerbose ); return 0; } if ( argc == globalUtilOptind ) goto usage; memset( pTruth, 0, 64 * sizeof(word) ); while ( globalUtilOptind < argc ) { if ( nFunc == 16 ) { Abc_Print( -1, "Too many functions (at most 16 supported).\n" ); goto usage; } nVarsTmp = Abc_TtReadHex( &pTruth[nFunc << 2], argv[globalUtilOptind++] ); nFunc++; if ( nVars == 0 ) nVars = nVarsTmp; else if ( nVars > 8 ) { Abc_Print( -1, "Only 8-variable functions are supported.\n" ); goto usage; } else if ( nVars != nVarsTmp ) { Abc_Print( -1, "All functions need to have the same size.\n" ); goto usage; } } if ( fMakeAIG ) { pGiaRes = Gia_ManFindExact( pTruth, nVars, nFunc, nMaxDepth, fHasArrTimeProfile ? pArrTimeProfile : NULL, nBTLimit, nStartGates - 1, fVerbose ); if ( pGiaRes ) Abc_FrameUpdateGia( pAbc, pGiaRes ); else Abc_Print( 0, "Could not find AIG within given resource constraints, retry with different value for -C.\n" ); } else { pNtkRes = Abc_NtkFindExact( pTruth, nVars, nFunc, nMaxDepth, fHasArrTimeProfile ? pArrTimeProfile : NULL, nBTLimit, nStartGates - 1, fVerbose ); if ( pNtkRes ) { Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); Abc_FrameClearVerifStatus( pAbc ); } else Abc_Print( 0, "Could not find network within given resource constraints, retry with different value for -C.\n" ); } return 0; usage: Abc_Print( -2, "usage: exact [-DSC ] [-A ] [-atvh] ...\n" ); Abc_Print( -2, "\t finds optimum networks using SAT-based exact synthesis for hex truth tables ...\n" ); Abc_Print( -2, "\t-D : constrain maximum depth (if too low, algorithm may not terminate)\n" ); Abc_Print( -2, "\t-A : input arrival times (comma separated list)\n" ); Abc_Print( -2, "\t-S : number of start gates in search [default = %d]\n", nStartGates ); Abc_Print( -2, "\t-C : the limit on the number of conflicts; turn off with 0 [default = %d]\n", nBTLimit ); Abc_Print( -2, "\t-a : toggle create AIG [default = %s]\n", fMakeAIG ? "yes" : "no" ); Abc_Print( -2, "\t-t : run test suite\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" ); Abc_Print( -2, "\t\n" ); Abc_Print( -2, "\t This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBmsStart( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_ExactIsRunning(); extern void Abc_ExactStart( int nBTLimit, int fMakeAIG, int fVerbose, int fVeryVerbose, const char *pFilename ); int c, fMakeAIG = 0, fVerbose = 0, fVeryVerbose = 0, nBTLimit = 100; char * pFilename = NULL; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Cavwh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } nBTLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'a': fMakeAIG ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc > globalUtilOptind ) { pFilename = argv[globalUtilOptind++]; } if ( Abc_ExactIsRunning() ) { Abc_Print( -1, "BMS manager is already started." ); return 1; } Abc_ExactStart( nBTLimit, fMakeAIG, fVerbose, fVeryVerbose, pFilename ); return 0; usage: Abc_Print( -2, "usage: bms_start [-C ] [-avwh] []\n" ); Abc_Print( -2, "\t starts BMS manager for recording optimum networks\n" ); Abc_Print( -2, "\t if is specified, store entries are read from that file\n" ); Abc_Print( -2, "\t-C : the limit on the number of conflicts [default = %d]\n", nBTLimit ); Abc_Print( -2, "\t-a : toggle create AIG [default = %s]\n", fMakeAIG ? "yes" : "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" ); Abc_Print( -2, "\t-w : toggle very verbose printout [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 This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBmsStop( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_ExactIsRunning(); extern void Abc_ExactStop( const char *pFilename ); int c; char * pFilename = NULL; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( argc > globalUtilOptind ) { pFilename = argv[globalUtilOptind++]; } if ( !Abc_ExactIsRunning() ) { Abc_Print( -1, "BMS manager is not started." ); return 1; } Abc_ExactStop( pFilename ); return 0; usage: Abc_Print( -2, "usage: bms_stop [-C ] [-vh] []\n" ); Abc_Print( -2, "\t stops BMS manager for recording optimum networks\n" ); Abc_Print( -2, "\t if is specified, store entries are written to that file\n" ); Abc_Print( -2, "\t-h : print the command usage\n" ); Abc_Print( -2, "\t\n" ); Abc_Print( -2, "\t This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBmsPs( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Abc_ExactIsRunning(); extern void Abc_ExactStats(); int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( !Abc_ExactIsRunning() ) { Abc_Print( -1, "BMS manager is not started." ); return 1; } Abc_ExactStats(); return 0; usage: Abc_Print( -2, "usage: bms_ps [-h]\n" ); Abc_Print( -2, "\t shows statistics about BMS manager\n" ); Abc_Print( -2, "\t-h : print the command usage\n" ); Abc_Print( -2, "\t\n" ); Abc_Print( -2, "\t This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandMajExact( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Maj_ManExactSynthesis( int nVars, int nNodes, int fUseConst, int fUseLine, int fVerbose ); extern int Maj_ManExactSynthesis2( int nVars, int nNodes, int fUseConst, int fUseLine, int fUseRand, int nRands, int fVerbose ); int c, nVars = 3, nNodes = 1, fUseConst = 0, fUseLine = 0, fGlucose = 0, fUseRand = 0, nRands = 0, fVerbose = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "INRfcrgvh" ) ) != EOF ) { switch ( c ) { 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 '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 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } nRands = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nRands < 0 ) goto usage; break; case 'f': fUseConst ^= 1; break; case 'c': fUseLine ^= 1; break; case 'r': fUseRand ^= 1; break; case 'g': fGlucose ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( (nVars & 1) == 0 ) { Abc_Print( -1, "Cannot sythesize MAJ gate with an even number of inputs (%d).\n", nVars ); return 1; } if ( fGlucose ) Maj_ManExactSynthesis( nVars, nNodes, fUseConst, fUseLine, fVerbose ); else Maj_ManExactSynthesis2( nVars, nNodes, fUseConst, fUseLine, fUseRand, nRands, fVerbose ); return 0; usage: Abc_Print( -2, "usage: majexact [-INR ] [-fcrgvh]\n" ); Abc_Print( -2, "\t exact synthesis of multi-input MAJ using MAJ3 gates\n" ); Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", nVars ); Abc_Print( -2, "\t-N : the number of MAJ3 nodes [default = %d]\n", nNodes ); Abc_Print( -2, "\t-R : the number of additional connections [default = %d]\n", nRands ); Abc_Print( -2, "\t-f : toggle using constant fanins [default = %s]\n", fUseConst ? "yes" : "no" ); Abc_Print( -2, "\t-c : toggle using cascade topology [default = %s]\n", fUseLine ? "yes" : "no" ); Abc_Print( -2, "\t-r : toggle using random topology [default = %s]\n", fUseRand ? "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 printout [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_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 ); 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 ); extern void Exa_ManExactSynthesis7( Bmc_EsPar_t * pPars, int GateSize ); int c, fKissat = 0, fKissat2 = 0, fUseNands = 0, GateSize = 0; Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "INTGSabdconugklmvh" ) ) != EOF ) { switch ( c ) { case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } pPars->nVars = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nVars < 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->nNodes = atoi(argv[globalUtilOptind]); globalUtilOptind++; 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 'G': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" ); goto usage; } GateSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( GateSize < 0 ) goto usage; break; case 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by a file name.\n" ); goto usage; } pPars->pGuide = argv[globalUtilOptind]; globalUtilOptind++; break; case 'a': pPars->fOnlyAnd ^= 1; break; case 'b': fUseNands ^= 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 'm': pPars->fCard ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } 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" ); return 1; } if ( pPars->nVars >= 2 && (1 << (pPars->nVars-2)) != (int)strlen(pPars->pTtStr) ) { Abc_Print( -1, "Truth table is expected to have %d hex digits (instead of %d).\n", (1 << (pPars->nVars-2)), strlen(pPars->pTtStr) ); return 1; } if ( pPars->nVars > pPars->nNodes * (2 - 1) + 1 ) { Abc_Print( -1, "Function with %d variales cannot be implemented with %d two-input gates.\n", pPars->nVars, pPars->nNodes ); return 1; } if ( pPars->nVars > 10 ) { Abc_Print( -1, "Function should not have more than 10 inputs.\n" ); return 1; } if ( fUseNands ) Exa_ManExactSynthesis7( pPars, GateSize ); else if ( fKissat || pPars->fCard ) 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 [-INTG ] [-S str] [-abdconugklmvh] \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 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-G : the largest allowed gate size (NANDs only) [default = %d]\n", GateSize ); Abc_Print( -2, "\t-S : structural guidance from the user [default = %s]\n", pPars->pGuide ? pPars->pGuide : "unknown" ); Abc_Print( -2, "\t-a : toggle using only AND-gates (without XOR-gates) [default = %s]\n", pPars->fOnlyAnd ? "yes" : "no" ); Abc_Print( -2, "\t-b : toggle using only NAND-gates [default = %s]\n", fUseNands ? "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-m : toggle using CaDiCaL by Armin Biere [default = %s]\n", pPars->fCard ? "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" ); Abc_Print( -2, "\t \n" ); Abc_Print( -2, "\t For example, command line \"twoexact -g -I 5 -N 12 169AE443\"\n" ); Abc_Print( -2, "\t synthesizes the smallest circuit composed of two-input gates\n" ); Abc_Print( -2, "\t for the only NPN class of 5-input functions that requires 12 gates;\n" ); Abc_Print( -2, "\t all other functions can be realized with 11 two-input gates or less\n" ); Abc_Print( -2, "\t (see Section 7.1.2 \"Boolean evaluation\" in the book The Art of Computer Programming by Donald Knuth)\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ); extern void Exa3_ManExactSynthesis2( Bmc_EsPar_t * pPars ); extern void Exa3_ManExactSynthesisRand( Bmc_EsPar_t * pPars ); int c; Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "INKTSFMiaocgvh" ) ) != EOF ) { switch ( c ) { case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } pPars->nVars = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nVars < 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->nNodes = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nNodes < 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; } pPars->nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; 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 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } pPars->pSymStr = argv[globalUtilOptind]; globalUtilOptind++; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nRandFuncs = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } pPars->nMintNum = atoi(argv[globalUtilOptind]); globalUtilOptind++; break; case 'i': pPars->fUseIncr ^= 1; break; case 'a': pPars->fOnlyAnd ^= 1; break; case 'o': pPars->fFewerVars ^= 1; break; case 'c': pPars->fLutCascade ^= 1; break; case 'g': pPars->fGlucose ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc == globalUtilOptind + 1 ) pPars->pTtStr = argv[globalUtilOptind]; if ( pPars->pTtStr == NULL && pPars->pSymStr == NULL && pPars->nRandFuncs == 0 ) { Abc_Print( -1, "Truth table should be given on the command line.\n" ); return 1; } if ( pPars->pTtStr && (1 << (pPars->nVars-2)) != (int)strlen(pPars->pTtStr) ) { Abc_Print( -1, "Truth table is expected to have %d hex digits (instead of %d).\n", (1 << (pPars->nVars-2)), strlen(pPars->pTtStr) ); return 1; } if ( pPars->pSymStr && pPars->nVars+1 != strlen(pPars->pSymStr) ) { Abc_Print( -1, "The char string of the %d-variable symmetric function should have %d zeros and ones (instead of %d).\n", pPars->nVars, pPars->nVars+1, strlen(pPars->pSymStr) ); return 1; } if ( pPars->nVars > pPars->nNodes * (pPars->nLutSize - 1) + 1 ) { Abc_Print( -1, "Function with %d variales cannot be implemented with %d %d-input LUTs.\n", pPars->nVars, pPars->nNodes, pPars->nLutSize ); return 1; } if ( pPars->nVars > 10 ) { Abc_Print( -1, "Function should not have more than 10 inputs.\n" ); return 1; } if ( pPars->nLutSize > 6 ) { Abc_Print( -1, "Node size should not be more than 6 inputs.\n" ); return 1; } if ( pPars->nRandFuncs ) { pPars->fGlucose = 1; Exa3_ManExactSynthesisRand( pPars ); } else if ( pPars->fGlucose ) Exa3_ManExactSynthesis( pPars ); else Exa3_ManExactSynthesis2( pPars ); return 0; usage: Abc_Print( -2, "usage: lutexact [-INKTFM ] [-S string] [-iaocgvh] \n" ); Abc_Print( -2, "\t exact synthesis of I-input function using N K-input gates\n" ); Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", pPars->nVars ); Abc_Print( -2, "\t-N : the number of K-input nodes [default = %d]\n", pPars->nNodes ); Abc_Print( -2, "\t-K : the number of node fanins [default = %d]\n", pPars->nLutSize ); Abc_Print( -2, "\t-T : the runtime limit in seconds [default = %d]\n", pPars->RuntimeLim ); Abc_Print( -2, "\t-F : the number of random functions to try [default = unused]\n" ); Abc_Print( -2, "\t-M : the number of positive minterms in the random function [default = unused]\n" ); Abc_Print( -2, "\t-S : charasteristic string of a symmetric function [default = %d]\n", pPars->pSymStr ); Abc_Print( -2, "\t-i : toggle using incremental solving [default = %s]\n", pPars->fUseIncr ? "yes" : "no" ); Abc_Print( -2, "\t-a : toggle using only AND-gates when K = 2 [default = %s]\n", pPars->fOnlyAnd ? "yes" : "no" ); Abc_Print( -2, "\t-o : toggle using additional optimizations [default = %s]\n", pPars->fFewerVars ? "yes" : "no" ); Abc_Print( -2, "\t-c : toggle synthesizing a single-rail cascade [default = %s]\n", pPars->fLutCascade ? "yes" : "no" ); Abc_Print( -2, "\t-g : toggle using Glucose 3.0 by Gilles Audemard and Laurent Simon [default = %s]\n", pPars->fGlucose ? "yes" : "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose ? "yes" : "no" ); Abc_Print( -2, "\t-h : print the command usage\n" ); Abc_Print( -2, "\t : truth table in hex notation\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAllExact( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Zyx_ManExactSynthesis( Bmc_EsPar_t * pPars ); int c; Bmc_EsPar_t Pars, * pPars = &Pars; Bmc_EsParSetDefault( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "MINKianegvh" ) ) != EOF ) { switch ( c ) { case 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); goto usage; } pPars->nMajSupp = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nMajSupp < 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; } pPars->nVars = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nVars < 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->nNodes = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nNodes < 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; } pPars->nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLutSize < 0 ) goto usage; break; case 'i': pPars->fUseIncr ^= 1; break; case 'a': pPars->fOnlyAnd ^= 1; break; case 'n': pPars->fOrderNodes ^= 1; break; case 'e': pPars->fEnumSols ^= 1; break; case 'g': pPars->fGlucose ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pPars->nMajSupp > 0 ) { if ( pPars->nMajSupp != 5 && pPars->nMajSupp != 7 && pPars->nMajSupp != 9 ) { Abc_Print( -1, "Currently only support majority with 5, 7 or 9 inputs.\n" ); return 1; } pPars->nVars = pPars->nMajSupp; pPars->nLutSize = 3; pPars->fMajority = 1; pPars->fUseIncr = 1; if ( pPars->nNodes == 0 ) { if ( pPars->nMajSupp == 5 ) pPars->nNodes = 4; if ( pPars->nMajSupp == 7 ) pPars->nNodes = 7; if ( pPars->nMajSupp == 9 ) pPars->nNodes = 10; } } else { if ( pPars->nVars == 0 ) { Abc_Print( -1, "The number of variables (-I num) needs to be specified on the command line.\n" ); return 1; } if ( pPars->nNodes == 0 ) { Abc_Print( -1, "The number of nodes (-N num) needs to be specified on the command line.\n" ); return 1; } if ( argc == globalUtilOptind + 1 ) pPars->pTtStr = argv[globalUtilOptind]; if ( pPars->pTtStr == NULL ) { Abc_Print( -1, "Truth table should be given on the command line.\n" ); return 1; } if ( (1 << (pPars->nVars-2)) != (int)strlen(pPars->pTtStr) ) { Abc_Print( -1, "Truth table is expected to have %d hex digits (instead of %d).\n", (1 << (pPars->nVars-2)), strlen(pPars->pTtStr) ); return 1; } } if ( pPars->nVars > pPars->nNodes * (pPars->nLutSize - 1) + 1 ) { Abc_Print( -1, "Function with %d variales cannot be implemented with %d %d-input LUTs.\n", pPars->nVars, pPars->nNodes, pPars->nLutSize ); return 1; } if ( pPars->nVars > 10 ) { Abc_Print( -1, "Function should not have more than 10 inputs.\n" ); return 1; } if ( pPars->nLutSize > 6 ) { Abc_Print( -1, "Node size should not be more than 6 inputs.\n" ); return 1; } if ( !pPars->fUseIncr ) { if ( pPars->fMajority ) { Abc_Print( -1, "Cannot synthesize majority in the non-incremental mode (use \'-i\').\n" ); return 1; } if ( pPars->nLutSize > 3 ) { Abc_Print( -1, "Cannot synthesize LUT4 and larger in non-incremental mode (use \'-i\').\n" ); return 1; } } Zyx_ManExactSynthesis( pPars ); return 0; usage: 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 ); Abc_Print( -2, "\t-K : the number of node fanins [default = %d]\n", pPars->nLutSize ); 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-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" ); Abc_Print( -2, "\t-h : print the command usage\n" ); Abc_Print( -2, "\t : truth table in hex notation\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandTestExact( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Zyx_TestExact( char * pFileName ); char * pFileName = NULL; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc == globalUtilOptind + 1 ) pFileName = argv[globalUtilOptind]; if ( pFileName == NULL ) { Abc_Print( -1, "File name is not given on the command line.\n" ); return 1; } Zyx_TestExact( pFileName ); return 0; usage: Abc_Print( -2, "usage: testexact \n" ); Abc_Print( -2, "\t tests solution of the exact synthesis problem\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" ); Abc_Print( -2, "\t : file name in the specified format\n" ); 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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; 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_NtkIsStrash( pNtk ) ) { Abc_Print( -1, "This command is only applicable to strashed networks.\n" ); return 1; } // get the new network pNtkRes = Abc_NtkToLogic( pNtk ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Converting to a logic network has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: logic [-h]\n" ); Abc_Print( -2, "\t transforms an AIG into a logic network with SOPs\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandComb( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; int fRemoveLatches; int nLatchesToAdd; extern void Abc_NtkMakeSeq( Abc_Ntk_t * pNtk, int nLatchesToAdd ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fRemoveLatches = 0; nLatchesToAdd = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Llh" ) ) != EOF ) { switch ( c ) { case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } nLatchesToAdd = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLatchesToAdd < 0 ) goto usage; break; case 'l': fRemoveLatches ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Abc_NtkIsComb(pNtk) && nLatchesToAdd == 0 ) { Abc_Print( -1, "The network is already combinational.\n" ); return 0; } if ( !Abc_NtkIsComb(pNtk) && nLatchesToAdd != 0 ) { Abc_Print( -1, "The network is already combinational.\n" ); return 0; } // get the new network pNtkRes = Abc_NtkDup( pNtk ); if ( nLatchesToAdd ) Abc_NtkMakeSeq( pNtkRes, nLatchesToAdd ); else Abc_NtkMakeComb( pNtkRes, fRemoveLatches ); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: comb [-L ] [-lh]\n" ); Abc_Print( -2, "\t converts comb network into seq, and vice versa\n" ); Abc_Print( -2, "\t-L : number of latches to add to comb network (0 = do not add) [default = %d]\n", nLatchesToAdd ); Abc_Print( -2, "\t-l : toggle converting latches to PIs/POs or removing them [default = %s]\n", fRemoveLatches? "remove": "convert" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) { char Buffer[32]; Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes; int fDelete1, fDelete2; char ** pArgvNew; int nArgcNew; int c; int fCheck; int fComb; int fImplic; int fMulti; int nPartSize; int fTrans; int fIgnoreNames; pNtk = Abc_FrameReadNtk(pAbc); // set defaults fComb = 0; fCheck = 1; fImplic = 0; fMulti = 0; nPartSize = 0; fTrans = 0; fIgnoreNames = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Pcmitnh" ) ) != EOF ) { switch ( c ) { case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } nPartSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nPartSize < 0 ) goto usage; break; case 'c': fComb ^= 1; break; case 'm': fMulti ^= 1; break; case 'i': fImplic ^= 1; break; case 't': fTrans ^= 1; break; case 'n': fIgnoreNames ^= 1; break; default: goto usage; } } if ( fTrans ) { if ( (Abc_NtkPoNum(pNtk) & 1) == 1 ) { Abc_Print( -1, "Abc_CommandMiter(): The number of outputs should be even.\n" ); return 0; } // replace the current network pNtkRes = Abc_NtkDupTransformMiter( pNtk ); Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); Abc_Print( 1, "The miter (current network) is transformed by XORing POs pair-wise.\n" ); return 0; } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2, 1 ) ) return 1; if ( fIgnoreNames ) { if ( !fDelete1 ) { pNtk1 = Abc_NtkStrash( pNtk1, 0, 1, 0 ); fDelete1 = 1; } if ( !fDelete2 ) { pNtk2 = Abc_NtkStrash( pNtk2, 0, 1, 0 ); fDelete2 = 1; } Abc_NtkShortNames( pNtk1 ); Abc_NtkShortNames( pNtk2 ); } // compute the miter pNtkRes = Abc_NtkMiter( pNtk1, pNtk2, fComb, nPartSize, fImplic, fMulti ); if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); // get the new network if ( pNtkRes == NULL ) { Abc_Print( -1, "Miter computation has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: if ( nPartSize == 0 ) strcpy( Buffer, "unused" ); else sprintf(Buffer, "%d", nPartSize ); Abc_Print( -2, "usage: miter [-P ] [-cimtnh] \n" ); Abc_Print( -2, "\t computes the miter of the two circuits\n" ); Abc_Print( -2, "\t-P : output partition size [default = %s]\n", Buffer ); Abc_Print( -2, "\t-c : toggles deriving combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); Abc_Print( -2, "\t-i : toggles deriving implication miter (file1 => file2) [default = %s]\n", fImplic? "yes": "no" ); Abc_Print( -2, "\t-m : toggles creating multi-output miter [default = %s]\n", fMulti? "yes": "no" ); Abc_Print( -2, "\t-t : toggle XORing pair-wise POs of the miter [default = %s]\n", fTrans? "yes": "no" ); Abc_Print( -2, "\t-n : toggle ignoring names when matching CIs/COs [default = %s]\n", fIgnoreNames? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tfile1 : (optional) the file with the first network\n"); Abc_Print( -2, "\tfile2 : (optional) the file with the second network\n"); Abc_Print( -2, "\t if no files are given, uses the current network and its spec\n"); Abc_Print( -2, "\t if one file is given, uses the current network and the file\n\n"); Abc_Print( -2, "\t Please note that, when used without \"-n\", this command tries to match\n" ); Abc_Print( -2, "\t primary inputs by name and, to achieve this, it will order them alphabetically,\n" ); Abc_Print( -2, "\t which results in incorrect QBF miters and confusing counter-examples.\n" ); return 1; } /**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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDemiter( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c, fDual, fVerbose; extern int Abc_NtkDarDemiter( Abc_Ntk_t * pNtk ); extern int Abc_NtkDarDemiterDual( Abc_Ntk_t * pNtk, int fVerbose ); // set defaults fDual = 0; fVerbose = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "dvh" ) ) != EOF ) { switch ( c ) { case 'd': fDual ^= 1; break; case 'v': fVerbose ^= 1; break; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "The network is not strashed.\n" ); return 1; } if ( fDual ) { if ( (Abc_NtkPoNum(pNtk) & 1) ) { Abc_Print( -1, "The number of POs should be even.\n" ); return 0; } if ( !Abc_NtkDarDemiterDual( pNtk, fVerbose ) ) { Abc_Print( -1, "Demitering has failed.\n" ); return 1; } return 0; } /* if ( Abc_NtkPoNum(pNtk) != 1 ) { Abc_Print( -1, "The network is not a single-output miter.\n" ); return 1; } if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) ) { Abc_Print( -1, "The miter's PO is not an EXOR.\n" ); return 1; } if ( !Abc_NtkDemiter( pNtk ) ) { Abc_Print( -1, "Demitering has failed.\n" ); return 1; } */ // get the new network if ( !Abc_NtkDarDemiter( pNtk ) ) { Abc_Print( -1, "Demitering has failed.\n" ); return 1; } // replace the current network // Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: demiter [-dvh]\n" ); Abc_Print( -2, "\t splits sequential miter into two circuits\n" ); Abc_Print( -2, "\t-d : expects a dual-output miter (without XORs) [default = %s]\n", fDual? "yes": "no" ); Abc_Print( -2, "\t-v : toggles outputting 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_CommandOrPos( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);//, * pNtkRes; int fReverse = 0; int fComb = 0; int fXor = 0; int c; extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd, int fXor ); // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "rxh" ) ) != EOF ) { switch ( c ) { case 'r': fReverse ^= 1; break; case 'x': fXor ^= 1; break; case 'c': fComb ^= 1; break; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "The network is not strashed.\n" ); return 1; } // get the new network if ( fReverse ) { extern Aig_Man_t * Abc_NtkToDarBmc( Abc_Ntk_t * pNtk, Vec_Int_t ** pvMap ); Aig_Man_t * pMan = Abc_NtkToDarBmc( pNtk, NULL ); Abc_Ntk_t * pNtkRes = Abc_NtkFromAigPhase( pMan ); Aig_ManStop( pMan ); // perform expansion if ( Abc_NtkPoNum(pNtk) != Abc_NtkPoNum(pNtkRes) ) Abc_Print( 1,"Expanded %d outputs into %d outputs using OR decomposition.\n", Abc_NtkPoNum(pNtk), Abc_NtkPoNum(pNtkRes) ); else Abc_Print( 1,"The output(s) cannot be structurally decomposed.\n" ); // clear counter-example if ( pAbc->pCex ) ABC_FREE( pAbc->pCex ); // replace the current network ABC_FREE( pNtkRes->pName ); pNtkRes->pName = Extra_UtilStrsav(pNtk->pName); Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); } else { if ( !Abc_NtkCombinePos( pNtk, 0, fXor ) ) { Abc_Print( -1, "ORing the POs has failed.\n" ); return 1; } // update counter-example if ( pAbc->pCex ) pAbc->pCex->iPo = 0; // replace the current network // Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); } return 0; usage: Abc_Print( -2, "usage: orpos [-rxh]\n" ); Abc_Print( -2, "\t creates single-output miter by ORing the POs of the current network\n" ); Abc_Print( -2, "\t-r : performs the reverse transform (OR decomposition) [default = %s]\n", fReverse? "yes": "no" ); Abc_Print( -2, "\t-x : toggles combining the PO using XOR [default = %s]\n", fXor? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAndPos( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);//, * pNtkRes; int fComb = 0; int c; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { case 'c': fComb ^= 1; break; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "The network is not strashed.\n" ); return 1; } if ( Abc_NtkPoNum(pNtk) == 1 ) { Abc_Print( -1, "The network already has one PO.\n" ); return 1; } if ( Abc_NtkLatchNum(pNtk) ) { Abc_Print( -1, "The miter has latches. ORing is not performed.\n" ); return 1; } // get the new network if ( !Abc_NtkCombinePos( pNtk, 1, 0 ) ) { Abc_Print( -1, "ANDing the POs has failed.\n" ); return 1; } // replace the current network // Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: andpos [-h]\n" ); Abc_Print( -2, "\t creates single-output miter by ANDing the POs of the current network\n" ); // Abc_Print( -2, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandZeroPo( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);//, * pNtkRes = NULL; int c, iOutput = -1; int fSkipSweep = 0; int fUseConst1 = 0; extern void Abc_NtkDropOneOutput( Abc_Ntk_t * pNtk, int iOutput, int fSkipSweep, int fUseConst1 ); // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Nsoh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } iOutput = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iOutput < 0 ) goto usage; break; case 's': fSkipSweep ^= 1; break; case 'o': fUseConst1 ^= 1; break; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "The network is not strashed.\n" ); return 1; } if ( iOutput < 0 ) { Abc_Print( -1, "The output index is not specified.\n" ); return 1; } if ( iOutput >= Abc_NtkPoNum(pNtk) ) { Abc_Print( -1, "The output index is larger than the allowed POs.\n" ); return 1; } // get the new network // pNtkRes = Abc_NtkDup( pNtk ); // Abc_NtkDropOneOutput( pNtkRes, iOutput ); // Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); Abc_NtkDropOneOutput( pNtk, iOutput, fSkipSweep, fUseConst1 ); return 0; usage: Abc_Print( -2, "usage: zeropo [-N ] [-soh]\n" ); Abc_Print( -2, "\t replaces the PO driver by constant 0\n" ); Abc_Print( -2, "\t-N : the zero-based index of the PO to replace [default = %d]\n", iOutput ); Abc_Print( -2, "\t-s : performs comb sweep after removimg a PO [default = %s]\n", !fSkipSweep? "yes": "no" ); Abc_Print( -2, "\t-o : toggles using const 1 instead of const 0 [default = %s]\n", fUseConst1? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSwapPos( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; int c, iOutput = -1; extern void Abc_NtkSwapOneOutput( Abc_Ntk_t * pNtk, int iOutput ); // set defaults 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; } iOutput = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iOutput < 0 ) goto usage; break; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "The network is not strashed.\n" ); return 1; } if ( iOutput < 0 ) { Abc_Print( -1, "The output index is not specified.\n" ); return 1; } if ( iOutput >= Abc_NtkPoNum(pNtk) ) { Abc_Print( -1, "The output index is larger than the allowed POs.\n" ); return 1; } // get the new network pNtkRes = Abc_NtkDup( pNtk ); Abc_NtkSwapOneOutput( pNtkRes, iOutput ); Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: swappos [-N ] [-h]\n" ); Abc_Print( -2, "\t swap the 0-th PO with the -th PO\n" ); Abc_Print( -2, "\t-N : the zero-based index of the PO to swap [default = %d]\n", iOutput ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandRemovePo( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);//, * pNtkRes = NULL; int c, iOutput = -1; int fRemoveConst0 = 1; extern void Abc_NtkRemovePo( Abc_Ntk_t * pNtk, int iOutput, int fRemoveConst0 ); // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Nzh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } iOutput = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iOutput < 0 ) goto usage; break; case 'z': fRemoveConst0 ^= 1; break; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "The network is not strashed.\n" ); return 1; } if ( iOutput < 0 ) { Abc_Print( -1, "The output index is not specified.\n" ); return 1; } if ( iOutput >= Abc_NtkPoNum(pNtk) ) { Abc_Print( -1, "The output index is larger than the allowed POs.\n" ); return 1; } // get the new network // pNtkRes = Abc_NtkDup( pNtk ); // Abc_NtkRemovePo( pNtkRes, iOutput ); // Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); Abc_NtkRemovePo( pNtk, iOutput, fRemoveConst0 ); return 0; usage: Abc_Print( -2, "usage: removepo [-N ] [-zh]\n" ); Abc_Print( -2, "\t remove PO with number if it is const0\n" ); Abc_Print( -2, "\t-N : the zero-based index of the PO to remove [default = %d]\n", iOutput ); Abc_Print( -2, "\t-z : toggle removing const1 instead of const0 [default = %s]\n", fRemoveConst0? "const0": "const1" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDropSat( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkDropSatOutputs( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCexes, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes = NULL; int fNoSweep = 0; int c, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) { switch ( c ) { case 's': fNoSweep ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': 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 AIGs (run \"strash\").\n" ); return 1; } if ( pAbc->vCexVec == NULL ) { Abc_Print( -1, "CEX array is not defined. Run \"bmc3 -az\", \"sim3 -az\", or \"pdr -az\".\n" ); return 1; } if ( Vec_PtrSize(pAbc->vCexVec) != Abc_NtkPoNum(pNtk) ) { Abc_Print( -1, "CEX array size (%d) does not match the number of outputs (%d).\n", Vec_PtrSize(pAbc->vCexVec), Abc_NtkPoNum(pNtk) ); return 1; } Abc_NtkDropSatOutputs( pNtk, pAbc->vCexVec, fVerbose ); if ( !fNoSweep ) { pNtkRes = Abc_NtkDarLatchSweep( pNtk, 1, 1, 1, 0, -1, -1, 0, 0 ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Removing SAT outputs has failed.\n" ); return 1; } Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); } return 0; usage: Abc_Print( -2, "usage: dropsat [-sh]\n" ); Abc_Print( -2, "\t replaces satisfiable POs by constant 0 and cleans up the AIG\n" ); Abc_Print( -2, "\t-s : toggles skipping sequential sweep [default = %s]\n", fNoSweep? "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; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAddPi( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } // get the new network if ( Abc_NtkPiNum(pNtk) == 0 ) { Abc_Ntk_t * pNtkRes = Abc_NtkDup( pNtk ); Abc_Obj_t * pObj = Abc_NtkCreatePi( pNtkRes ); Abc_ObjAssignName( pObj, "dummy_pi", NULL ); Abc_NtkOrderCisCos( pNtkRes ); Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); } return 0; usage: Abc_Print( -2, "usage: addpi [-h]\n" ); Abc_Print( -2, "\t if the network has no PIs, add one dummy PI\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAddFlop( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -2, "The current network is not an AIG (run \"strash\").\n"); return 0; } // get the new network if ( Abc_NtkLatchNum(pNtk) == 0 ) { Abc_Ntk_t * pNtkRes = Abc_NtkDup( pNtk ); Abc_NtkAddLatch( pNtkRes, Abc_AigConst1(pNtkRes), ABC_INIT_ONE ); Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); } return 0; usage: Abc_Print( -2, "usage: addflop [-h]\n" ); Abc_Print( -2, "\t if the network has no flops, add one dummy flop\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAppend( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtk2; char * FileName; int fComb = 0; int c; pNtk = Abc_FrameReadNtk(pAbc); // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { case 'c': fComb ^= 1; break; default: goto usage; } } // get the second network if ( argc != globalUtilOptind + 1 ) { Abc_Print( -1, "The network to append is not given.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "The base network should be strashed for the appending to work.\n" ); return 1; } // read the second network FileName = argv[globalUtilOptind]; pNtk2 = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 ); if ( pNtk2 == NULL ) return 1; // check if the second network is combinational if ( Abc_NtkLatchNum(pNtk2) ) { Abc_NtkDelete( pNtk2 ); Abc_Print( -1, "The second network has latches. Appending does not work for such networks.\n" ); return 0; } // get the new network if ( !Abc_NtkAppend( pNtk, pNtk2, 1 ) ) { Abc_NtkDelete( pNtk2 ); Abc_Print( -1, "Appending the networks failed.\n" ); return 1; } Abc_NtkDelete( pNtk2 ); // sweep dangling logic Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); // replace the current network // Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: append [-h] \n" ); Abc_Print( -2, "\t appends a combinational network on top of the current network\n" ); // Abc_Print( -2, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : file name with the second network\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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 = NULL; char * FileName; int fComb = 0; int c; pNtk = Abc_FrameReadNtk(pAbc); // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) { switch ( c ) { case 'c': fComb ^= 1; break; default: goto usage; } } 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 ) { Abc_Print( -1, "The network to append is not given.\n" ); return 1; } if ( !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "The base network should be in the logic form.\n" ); return 1; } // check if the second network is combinational if ( Abc_NtkLatchNum(pNtk) ) { Abc_Print( -1, "The current network has latches. This command does not work for such networks.\n" ); return 0; } // read the second network FileName = argv[globalUtilOptind]; pNtk2 = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 ); if ( pNtk2 == NULL ) return 1; // check if the second network is combinational if ( Abc_NtkLatchNum(pNtk2) ) { Abc_NtkDelete( pNtk2 ); Abc_Print( -1, "The second network has latches. This command does not work for such networks.\n" ); return 0; } // compare inputs/outputs if ( Abc_NtkPoNum(pNtk) != Abc_NtkPiNum(pNtk2) ) { Abc_NtkDelete( pNtk2 ); Abc_Print( -1, "The PO count (%d) of the first network is not equal to PI count (%d) of the second network.\n", Abc_NtkPoNum(pNtk), Abc_NtkPiNum(pNtk2) ); return 0; } // get the new network 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 ); return 0; usage: Abc_Print( -2, "usage: putontop [-h] \n" ); 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; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkTemp, * pNtkRes; int nFrames; int fInitial; int fVerbose; int c; pNtk = Abc_FrameReadNtk(pAbc); // set defaults nFrames = 5; fInitial = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Fivh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nFrames = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFrames <= 0 ) goto usage; break; case 'i': fInitial ^= 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; } // get the new network if ( !Abc_NtkIsStrash(pNtk) ) { pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); pNtkRes = Abc_NtkFrames( pNtkTemp, nFrames, fInitial, fVerbose ); Abc_NtkDelete( pNtkTemp ); } else pNtkRes = Abc_NtkFrames( pNtk, nFrames, fInitial, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Unrolling the network has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: frames [-F ] [-ivh]\n" ); Abc_Print( -2, "\t unrolls the network for a number of time frames\n" ); Abc_Print( -2, "\t-F : the number of frames to unroll [default = %d]\n", nFrames ); Abc_Print( -2, "\t-i : toggles initializing the first frame [default = %s]\n", fInitial? "yes": "no" ); Abc_Print( -2, "\t-v : toggles outputting 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_CommandDFrames( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkTemp, * pNtkRes; int nPrefix; int nFrames; int fInitial; int fVerbose; int c; extern Abc_Ntk_t * Abc_NtkDarFrames( Abc_Ntk_t * pNtk, int nPrefix, int nFrames, int fInitial, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nPrefix = 5; nFrames = 5; fInitial = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NFivh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } nPrefix = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nPrefix <= 0 ) goto usage; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nFrames = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFrames <= 0 ) goto usage; break; case 'i': fInitial ^= 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 ( nPrefix > nFrames ) { Abc_Print( -1, "Prefix (%d) cannot be more than the number of frames (%d).\n", nPrefix, nFrames ); return 1; } // get the new network if ( !Abc_NtkIsStrash(pNtk) ) { pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); pNtkRes = Abc_NtkDarFrames( pNtkTemp, nPrefix, nFrames, fInitial, fVerbose ); Abc_NtkDelete( pNtkTemp ); } else pNtkRes = Abc_NtkDarFrames( pNtk, nPrefix, nFrames, fInitial, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Unrolling the network has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: dframes [-NF ] [-ivh]\n" ); Abc_Print( -2, "\t unrolls the network with simplification\n" ); Abc_Print( -2, "\t-N num : the number of frames to use as prefix [default = %d]\n", nPrefix ); Abc_Print( -2, "\t-F num : the number of frames to unroll [default = %d]\n", nFrames ); Abc_Print( -2, "\t-i : toggles initializing the first frame [default = %s]\n", fInitial? "yes": "no" ); Abc_Print( -2, "\t-v : toggles outputting 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_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, fCubeSort = 1, fMode = -1, nCubeLimit = 1000000; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Csdnh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } nCubeLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCubeLimit < 0 ) goto usage; break; case 's': fCubeSort ^= 1; break; case 'd': fMode = 1; break; case 'n': fMode = 0; break; 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, "Converting to SOP is possible only for logic networks.\n" ); return 1; } if ( fCubeSort && Abc_NtkHasSop(pNtk) ) { Abc_NtkSortSops(pNtk); return 0; } if ( !fCubeSort && Abc_NtkHasBdd(pNtk) && !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 0) ) { Abc_Print( -1, "Converting to SOP has failed.\n" ); 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] [-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"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int fReorder = 1, fBdd2Sop = 0; int c; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "rsh" ) ) != EOF ) { switch ( c ) { case 'r': fReorder ^= 1; break; case 's': fBdd2Sop ^= 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_Print( -1, "Converting to BDD is possible only for logic networks.\n" ); return 1; } if ( fBdd2Sop && Abc_NtkHasSop(pNtk) ) return !Abc_NtkSopToBdd(pNtk); if ( Abc_NtkIsBddLogic(pNtk) ) { Abc_Print( -1, "The logic network is already in the BDD form.\n" ); return 0; } if ( !Abc_NtkToBdd(pNtk) ) { Abc_Print( -1, "Converting to BDD has failed.\n" ); return 1; } return 0; usage: Abc_Print( -2, "usage: bdd [-rsh]\n" ); Abc_Print( -2, "\t converts node functions to BDD\n" ); Abc_Print( -2, "\t-r : toggles enabling dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); Abc_Print( -2, "\t-s : toggles constructing BDDs directly from SOPs [default = %s]\n", fBdd2Sop? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAig( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "Converting to AIG is possible only for logic networks.\n" ); return 1; } if ( Abc_NtkIsAigLogic(pNtk) ) { Abc_Print( -1, "The logic network is already in the AIG form.\n" ); return 0; } if ( !Abc_NtkToAig(pNtk) ) { Abc_Print( -1, "Converting to AIG has failed.\n" ); return 1; } return 0; usage: Abc_Print( -2, "usage: aig [-h]\n" ); Abc_Print( -2, "\t converts node functions to AIG\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandReorder( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fVerbose; extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); // set defaults 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 ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } // get the new network if ( !Abc_NtkIsBddLogic(pNtk) ) { Abc_Print( -1, "Variable reordering is possible when node functions are BDDs (run \"bdd\").\n" ); return 1; } Abc_NtkBddReorder( pNtk, fVerbose ); return 0; usage: Abc_Print( -2, "usage: reorder [-vh]\n" ); Abc_Print( -2, "\t reorders local functions of the nodes using sifting\n" ); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBidec( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fVerbose; extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose ); // set defaults 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 ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } // get the new network if ( !Abc_NtkIsAigLogic(pNtk) ) { Abc_Print( -1, "Bi-decomposition only works when node functions are AIGs (run \"aig\").\n" ); return 1; } Abc_NtkBidecResyn( pNtk, fVerbose ); return 0; usage: Abc_Print( -2, "usage: bidec [-vh]\n" ); Abc_Print( -2, "\t applies bi-decomposition to local functions of the nodes\n" ); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandOrder( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pFile; Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); char * pFileName; int c; int fReverse; int fVerbose; extern void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose ); extern void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose ); // set defaults fReverse = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF ) { switch ( c ) { case 'r': fReverse ^= 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_NtkLatchNum(pNtk) > 0 ) // { // Abc_Print( -1, "Currently this procedure does not work for sequential networks.\n" ); // return 1; // } // if the var order file is given, implement this order pFileName = NULL; if ( argc == globalUtilOptind + 1 ) { pFileName = argv[globalUtilOptind]; pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { Abc_Print( -1, "Cannot open file \"%s\" with the BDD variable order.\n", pFileName ); return 1; } fclose( pFile ); } if ( pFileName ) Abc_NtkImplementCiOrder( pNtk, pFileName, fReverse, fVerbose ); else Abc_NtkFindCiOrder( pNtk, fReverse, fVerbose ); return 0; usage: Abc_Print( -2, "usage: order [-rvh] \n" ); Abc_Print( -2, "\t computes a good static CI variable order\n" ); Abc_Print( -2, "\t-r : toggle reverse ordering [default = %s]\n", fReverse? "yes": "no" ); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : (optional) file with the given variable order\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, fGlobal = 0, fUseAdd = 0, Limit = 1000000; pNtk = Abc_FrameReadNtk(pAbc); // set defaults Extra_UtilGetoptReset(); 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: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( fGlobal ) { 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, fGlobal, Limit, fUseAdd ); if ( pNtkRes == NULL ) { 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 [-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; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandCubes( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkSopToCubes( Abc_Ntk_t * pNtk, int fXor ); Abc_Ntk_t * pNtk, * pNtkRes; int c, fXor = 0; pNtk = Abc_FrameReadNtk(pAbc); // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "xh" ) ) != EOF ) { switch ( c ) { case 'x': fXor ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsSopLogic(pNtk) ) { Abc_Print( -1, "Only a SOP logic network can be transformed into cubes.\n" ); return 1; } // get the new network pNtkRes = Abc_NtkSopToCubes( pNtk, fXor ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Converting to cubes has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: cubes [-xh]\n" ); Abc_Print( -2, "\t converts the current network into a network derived by creating\n" ); Abc_Print( -2, "\t a separate node for each product and sum in the local SOPs\n" ); Abc_Print( -2, "\t-x : toggle using XOR instead of OR [default = %s]\n", fXor? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandExpand( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkExpandCubes( Abc_Ntk_t * pNtk, Gia_Man_t * pGia, int fVerbose ); Abc_Ntk_t * pStrash, * pNtk2, * pNtk = Abc_FrameReadNtk(pAbc); 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 ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsSopLogic(pNtk) ) { Abc_Print( -1, "Only a SOP logic network can be transformed into cubes.\n" ); return 1; } if ( Abc_NtkLevel(pNtk) > 1 ) { Abc_Print( -1, "The number of logic levels is more than 1 (collapse the network and try again).\n" ); return 1; } // read the offset representation if ( argc != globalUtilOptind + 1 ) { Abc_Print( 0, "Using the complement of the current network as its offset.\n" ); pNtk2 = Abc_NtkDup( pNtk ); } else { char * FileName = argv[globalUtilOptind]; pNtk2 = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 ); if ( pNtk2 == NULL ) { Abc_Print( -1, "Failed to read the current network from file \"%s\".\n", FileName ); return 1; } } // strash the network pStrash = Abc_NtkStrash( pNtk2, 0, 1, 0 ); Abc_NtkDelete( pNtk2 ); // convert it into an AIG pGia = Abc_NtkClpGia( pStrash ); //Gia_AigerWrite( pGia, "aig_dump.aig", 0, 0, 0 ); Abc_NtkDelete( pStrash ); // get the new network Abc_NtkExpandCubes( pNtk, pGia, fVerbose ); Gia_ManStop( pGia ); return 0; usage: Abc_Print( -2, "usage: expand [-vh] \n" ); Abc_Print( -2, "\t expands cubes against the offset\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, "\tfile : (optional) representation of on-set plus dc-set\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSplitSop( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkSplitSop( Abc_Ntk_t * pNtk, int nCubesMax, int fVerbose ); Abc_Ntk_t * pNtk, * pNtkRes; int c, fVerbose = 0, nCubesMax = 100; pNtk = Abc_FrameReadNtk(pAbc); // set defaults 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; } nCubesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCubesMax < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsSopLogic(pNtk) ) { Abc_Print( -1, "Only a SOP logic network can be transformed into cubes.\n" ); return 1; } // get the new network pNtkRes = Abc_NtkSplitSop( pNtk, nCubesMax, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Converting to cubes has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: splitsop [-N num] [-vh]\n" ); Abc_Print( -2, "\t splits nodes whose SOP size is larger than the given one\n" ); Abc_Print( -2, "\t-N num : the maximum number of cubes after splitting [default = %d]\n", nCubesMax ); Abc_Print( -2, "\t-v : prints 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_CommandExtSeqDcs( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fVerbose; extern int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNet, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults 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 ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Abc_NtkLatchNum(pNtk) == 0 ) { Abc_Print( -1, "The current network has no latches.\n" ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Extracting sequential don't-cares works only for AIGs (run \"strash\").\n" ); return 0; } if ( !Abc_NtkExtractSequentialDcs( pNtk, fVerbose ) ) { Abc_Print( -1, "Extracting sequential don't-cares has failed.\n" ); return 1; } return 0; usage: Abc_Print( -2, "usage: ext_seq_dcs [-vh]\n" ); Abc_Print( -2, "\t create EXDC network using unreachable states\n" ); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandReach( Abc_Frame_t * pAbc, int argc, char ** argv ) { Saig_ParBbr_t Pars, * pPars = &Pars; Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; char * pLogFileName = NULL; extern int Abc_NtkDarReach( Abc_Ntk_t * pNtk, Saig_ParBbr_t * pPars ); // set defaults Bbr_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "TBFLproyvh" ) ) != EOF ) { switch ( c ) { 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 'B': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); goto usage; } pPars->nBddMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nBddMax < 0 ) goto usage; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pPars->nIterMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nIterMax < 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 'p': pPars->fPartition ^= 1; break; case 'r': pPars->fReorder ^= 1; break; case 'o': pPars->fReorderImage ^= 1; break; case 'y': pPars->fSkipOutCheck ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Abc_NtkLatchNum(pNtk) == 0 ) { Abc_Print( -1, "The current network has no latches.\n" ); return 0; } if ( !Abc_NtkIsStrash(pNtk) ) { 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 ); if ( pLogFileName ) Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "reach" ); return 0; usage: Abc_Print( -2, "usage: reach [-TBF num] [-L file] [-proyvh]\n" ); Abc_Print( -2, "\t verifies sequential miter using BDD-based reachability\n" ); Abc_Print( -2, "\t-T num : approximate time limit in seconds (0=infinite) [default = %d]\n", pPars->TimeLimit ); Abc_Print( -2, "\t-B num : max number of nodes in the intermediate BDDs [default = %d]\n", pPars->nBddMax ); Abc_Print( -2, "\t-F num : max number of reachability iterations [default = %d]\n", pPars->nIterMax ); Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); Abc_Print( -2, "\t-p : enable partitioned image computation [default = %s]\n", pPars->fPartition? "yes": "no" ); Abc_Print( -2, "\t-r : enable dynamic BDD variable reordering [default = %s]\n", pPars->fReorder? "yes": "no" ); Abc_Print( -2, "\t-o : toggles BDD variable reordering during image computation [default = %s]\n", pPars->fReorderImage? "yes": "no" ); Abc_Print( -2, "\t-y : skip checking property outputs [default = %s]\n", pPars->fSkipOutCheck? "yes": "no" ); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } Vec_Int_t * Vec_IntReadList( char * pStr, char Separ ) { Vec_Int_t * vRes = Vec_IntAlloc( 10 ); Vec_IntPush( vRes, atoi(pStr) ); for ( int c = 0; c < strlen(pStr); c++ ) if ( pStr[c] == Separ ) Vec_IntPush( vRes, atoi(pStr+c+1) ); return vRes; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandCone( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; Abc_Obj_t * pNode, * pNodeCo; Vec_Int_t * vPoIds = NULL; int c; int fUseAllCis; int fUseMffc; int Output; int nRange; extern Abc_Ntk_t * Abc_NtkSelectPos( Abc_Ntk_t * pNtkInit, Vec_Int_t * vPoIds ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fUseAllCis = 0; fUseMffc = 0; Output = -1; nRange = -1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ORNmah" ) ) != EOF ) { switch ( c ) { case 'O': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); goto usage; } Output = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( Output < 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; } nRange = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nRange < 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; } vPoIds = Vec_IntReadList( argv[globalUtilOptind], ',' ); globalUtilOptind++; if ( vPoIds == NULL ) goto usage; break; case 'm': fUseMffc ^= 1; break; case 'a': fUseAllCis ^= 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, "Currently can only be applied to the logic network or an AIG.\n" ); return 1; } if ( argc > globalUtilOptind + 1 ) { Abc_Print( -1, "Wrong number of auguments.\n" ); goto usage; } pNodeCo = NULL; if ( argc == globalUtilOptind + 1 ) { pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } if ( fUseMffc ) pNtkRes = Abc_NtkCreateMffc( pNtk, pNode, argv[globalUtilOptind] ); else pNtkRes = Abc_NtkCreateCone( pNtk, pNode, argv[globalUtilOptind], fUseAllCis ); } else if ( vPoIds ) { pNtkRes = Abc_NtkSelectPos( pNtk, vPoIds ); Vec_IntFree( vPoIds ); } else if ( nRange > 0 ) { if ( Output == -1 ) { Abc_Print( -1, "The starting PO ID is not specified.\n" ); return 1; } if ( Output >= Abc_NtkPoNum(pNtk) ) { Abc_Print( -1, "The 0-based output number (%d) is larger than the number of primary outputs (%d).\n", Output, Abc_NtkPoNum(pNtk) ); return 1; } assert( vPoIds == NULL ); vPoIds = Vec_IntAlloc( nRange ); for ( c = Output; c < Output + nRange; c++ ) Vec_IntPush( vPoIds, c ); pNtkRes = Abc_NtkSelectPos( pNtk, vPoIds ); Vec_IntFree( vPoIds ); } else if ( Output >= 0 ) { if ( Output >= Abc_NtkPoNum(pNtk) ) { Abc_Print( -1, "The 0-based output number (%d) is larger than the number of primary outputs (%d).\n", Output, Abc_NtkPoNum(pNtk) ); return 1; } assert( vPoIds == NULL ); vPoIds = Vec_IntAlloc( 1 ); Vec_IntPush( vPoIds, Output ); pNtkRes = Abc_NtkSelectPos( pNtk, vPoIds ); Vec_IntFree( vPoIds ); } else { if ( Output == -1 ) { Abc_Print( -1, "The starting PO ID is not specified.\n" ); return 1; } if ( Output >= Abc_NtkCoNum(pNtk) ) { Abc_Print( -1, "The 0-based output number (%d) is larger than the number of combinational outputs (%d).\n", Output, Abc_NtkCoNum(pNtk) ); return 1; } pNodeCo = Abc_NtkCo( pNtk, Output ); if ( fUseMffc ) pNtkRes = Abc_NtkCreateMffc( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo) ); else pNtkRes = Abc_NtkCreateCone( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo), fUseAllCis ); } if ( pNodeCo && Abc_ObjFaninC0(pNodeCo) ) { Abc_NtkPo(pNtkRes, 0)->fCompl0 ^= 1; // Abc_Print( -1, "The extracted cone represents the complement function of the CO.\n" ); } if ( pNtkRes == NULL ) { Abc_Print( -1, "Writing the logic cone of one node has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: cone [-ORN num] [-amh] \n" ); Abc_Print( -2, "\t replaces the current network by one or more logic cones\n" ); Abc_Print( -2, "\t-a : toggle keeping all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" ); Abc_Print( -2, "\t-m : toggle keeping only MFFC or complete TFI cone [default = %s]\n", fUseMffc? "MFFC": "TFI cone" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t-O num : (optional) the 0-based number of the CO to extract\n"); Abc_Print( -2, "\t-R num : (optional) the number of outputs to extract\n"); Abc_Print( -2, "\t-N : (optional) a comma-separated list of zero-based primary output indexes\n"); Abc_Print( -2, "\tname : (optional) the name of the node to extract\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandNode( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; Abc_Obj_t * pNode; int c; 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 + 1 ) { Abc_Print( -1, "Wrong number of auguments.\n" ); goto usage; } pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); if ( pNode == NULL ) { Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); return 1; } pNtkRes = Abc_NtkCreateFromNode( pNtk, pNode ); // pNtkRes = Abc_NtkDeriveFromBdd( pNtk->pManFunc, pNode->pData, NULL, NULL ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Splitting one node has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: node [-h] \n" ); Abc_Print( -2, "\t replaces the current network by the network composed of one node\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tname : the node name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_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************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandTopmost( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, nLevels; extern Abc_Ntk_t * Abc_NtkTopmost( 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_NtkTopmost( 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: topmost [-N num] [-h]\n" ); Abc_Print( -2, "\t replaces the current network by several of its topmost levels\n" ); Abc_Print( -2, "\t-N num : max number of levels [default = %d]\n", nLevels ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tname : the node name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBottommost( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, nLevels; extern Abc_Ntk_t * Abc_NtkBottommost( Abc_Ntk_t * pNtk, int nLevels ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nLevels = 10; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } nLevels = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLevels < 0 ) goto usage; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); return 0; } if ( Abc_NtkLatchNum(pNtk) > 0 ) { Abc_Print( -1, "Currently only works for combinational circuits.\n" ); return 0; } pNtkRes = Abc_NtkBottommost( pNtk, nLevels ); if ( pNtkRes == NULL ) { Abc_Print( -1, "The command has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: bottommost [-N num] [-h]\n" ); Abc_Print( -2, "\t replaces the current network by several of its bottommost levels\n" ); Abc_Print( -2, "\t-N num : max number of levels [default = %d]\n", nLevels ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tname : the node name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandTopAnd( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; extern Abc_Ntk_t * Abc_NtkTopAnd( Abc_Ntk_t * pNtk ); 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); return 0; } 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" ); return 0; } if ( Abc_ObjFaninC0(Abc_NtkPo(pNtk, 0)) ) { Abc_Print( -1, "The PO driver is complemented. AND-decomposition is impossible.\n" ); return 0; } if ( !Abc_ObjIsNode(Abc_ObjChild0(Abc_NtkPo(pNtk, 0))) ) { Abc_Print( -1, "The PO driver is not a node. AND-decomposition is impossible.\n" ); return 0; } pNtkRes = Abc_NtkTopAnd( pNtk ); 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: topand [-h]\n" ); Abc_Print( -2, "\t performs AND-decomposition of single-output combinational miter\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\tname : the node name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandTrim( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; Gia_Man_t * pGia, * pNew; Aig_Man_t * pAig; int c; pNtk = Abc_FrameReadNtk(pAbc); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != 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, "Trimming works only for AIGs (run \"strash\").\n" ); return 1; } // convert to GIA pAig = Abc_NtkToDar( pNtk, 0, 1 ); pGia = Gia_ManFromAigSimple( pAig ); Aig_ManStop( pAig ); // perform trimming pNew = Gia_ManDupTrimmed( pGia, 1, 1, 0, -1 ); Gia_ManStop( pGia ); // convert back pAig = Gia_ManToAigSimple( pNew ); Gia_ManStop( pNew ); pNtkRes = Abc_NtkFromAigPhase( pAig ); Aig_ManStop( pAig ); // duplicate the name and the spec ABC_FREE( pNtkRes->pName ); ABC_FREE( pNtkRes->pSpec ); pNtkRes->pName = Extra_UtilStrsav(pNtk->pName); pNtkRes->pSpec = Extra_UtilStrsav(pNtk->pSpec); Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: trim [-h]\n" ); Abc_Print( -2, "\t removes POs fed by constants and PIs w/o fanout\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c, fKeepIo = 0; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "kh" ) ) != EOF ) { switch ( c ) { case 'k': fKeepIo ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( fKeepIo ) Abc_NtkCleanNames( pNtk ); else Abc_NtkShortNames( pNtk ); return 0; usage: 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; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandMoveNames( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkMoveNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pOld ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Ntk_t * pNtk2; char * FileName; int c; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } // get the second network if ( argc != globalUtilOptind + 1 ) { Abc_Print( -1, "The network to take names from is not given.\n" ); return 1; } // read the second network FileName = argv[globalUtilOptind]; pNtk2 = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 ); if ( pNtk2 == NULL ) return 1; // compare inputs/outputs if ( Abc_NtkPiNum(pNtk) != Abc_NtkPiNum(pNtk2) ) { Abc_NtkDelete( pNtk2 ); Abc_Print( -1, "The PI count (%d) of the first network is not equal to PI count (%d) of the second network.\n", Abc_NtkPiNum(pNtk), Abc_NtkPiNum(pNtk2) ); return 0; } // compare inputs/outputs if ( Abc_NtkPoNum(pNtk) != Abc_NtkPoNum(pNtk2) ) { Abc_NtkDelete( pNtk2 ); Abc_Print( -1, "The PO count (%d) of the first network is not equal to PO count (%d) of the second network.\n", Abc_NtkPoNum(pNtk), Abc_NtkPoNum(pNtk2) ); return 0; } // compare inputs/outputs if ( Abc_NtkLatchNum(pNtk) != Abc_NtkLatchNum(pNtk2) ) { Abc_NtkDelete( pNtk2 ); Abc_Print( -1, "The flop count (%d) of the first network is not equal to flop count (%d) of the second network.\n", Abc_NtkLatchNum(pNtk), Abc_NtkLatchNum(pNtk2) ); return 0; } Abc_NtkMoveNames( pNtk, pNtk2 ); Abc_NtkDelete( pNtk2 ); return 0; usage: Abc_Print( -2, "usage: move_names [-h] \n" ); Abc_Print( -2, "\t moves PI/PO/latch names from the other network\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : file with network that has required names\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandExdcFree( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; 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 ( pNtk->pExdc == NULL ) { Abc_Print( -1, "The network has no EXDC.\n" ); return 1; } Abc_NtkDelete( pNtk->pExdc ); pNtk->pExdc = NULL; // replace the current network pNtkRes = Abc_NtkDup( pNtk ); Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: exdc_free [-h]\n" ); Abc_Print( -2, "\t frees the EXDC network of the current network\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandExdcGet( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; 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 ( pNtk->pExdc == NULL ) { Abc_Print( -1, "The network has no EXDC.\n" ); return 1; } // replace the current network pNtkRes = Abc_NtkDup( pNtk->pExdc ); Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: exdc_get [-h]\n" ); Abc_Print( -2, "\t replaces the current network by the EXDC of the current network\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandExdcSet( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pFile; Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes; char * FileName; int c; 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 ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); if ( (FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" )) ) Abc_Print( 1, "Did you mean \"%s\"?", FileName ); Abc_Print( 1, "\n" ); return 1; } fclose( pFile ); // set the new network pNtkNew = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 ); if ( pNtkNew == NULL ) { Abc_Print( -1, "Reading network from file has failed.\n" ); return 1; } // replace the EXDC if ( pNtk->pExdc ) { Abc_NtkDelete( pNtk->pExdc ); pNtk->pExdc = NULL; } pNtkRes = Abc_NtkDup( pNtk ); pNtkRes->pExdc = pNtkNew; // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: exdc_set [-h] \n" ); Abc_Print( -2, "\t sets the network from file as EXDC for the current network\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : file with the new EXDC network\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandCareSet( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * pFile; Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes; char * FileName; int c; 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 ( argc != globalUtilOptind + 1 ) { goto usage; } // get the input file name FileName = argv[globalUtilOptind]; if ( (pFile = fopen( FileName, "r" )) == NULL ) { Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); if ( (FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" )) ) Abc_Print( 1, "Did you mean \"%s\"?", FileName ); Abc_Print( 1, "\n" ); return 1; } fclose( pFile ); // set the new network pNtkNew = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 ); if ( pNtkNew == NULL ) { Abc_Print( -1, "Reading network from file has failed.\n" ); return 1; } // replace the EXDC if ( pNtk->pExcare ) { Abc_NtkDelete( (Abc_Ntk_t *)pNtk->pExcare ); pNtk->pExcare = NULL; } pNtkRes = Abc_NtkDup( pNtk ); pNtkRes->pExcare = pNtkNew; // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: care_set [-h] \n" ); Abc_Print( -2, "\t sets the network from file as a care for the current network\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : file with the new care network\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cut_Params_t Params, * pParams = &Params; Cut_Man_t * pCutMan; Cut_Oracle_t * pCutOracle = NULL; Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fOracle; extern Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); extern void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * pCutOracle ); // set defaults fOracle = 0; memset( pParams, 0, sizeof(Cut_Params_t) ); pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts) pParams->nKeepMax = 1000; // the max number of cuts kept at a node pParams->fTruth = 1; // compute truth tables pParams->fFilter = 1; // filter dominated cuts pParams->fDrop = 0; // drop cuts on the fly pParams->fDag = 1; // compute DAG cuts pParams->fTree = 0; // compute tree cuts pParams->fGlobal = 0; // compute global cuts pParams->fLocal = 0; // compute local cuts pParams->fFancy = 0; // compute something fancy pParams->fRecordAig = 1; // compute something fancy pParams->fMap = 0; // compute mapping delay pParams->fAdjust = 0; // removes useless fanouts pParams->fNpnSave = 0; // enables dumping truth tables pParams->fVerbose = 0; // the verbosiness flag Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdxyglzamjvosh" ) ) != EOF ) { switch ( c ) { case 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); goto usage; } pParams->nVarsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pParams->nVarsMax < 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; } pParams->nKeepMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pParams->nKeepMax < 0 ) goto usage; break; case 't': pParams->fTruth ^= 1; break; case 'f': pParams->fFilter ^= 1; break; case 'd': pParams->fDrop ^= 1; break; case 'x': pParams->fDag ^= 1; break; case 'y': pParams->fTree ^= 1; break; case 'g': pParams->fGlobal ^= 1; break; case 'l': pParams->fLocal ^= 1; break; case 'z': pParams->fFancy ^= 1; break; case 'a': pParams->fRecordAig ^= 1; break; case 'm': pParams->fMap ^= 1; break; case 'j': pParams->fAdjust ^= 1; break; case 'v': pParams->fVerbose ^= 1; break; case 'o': fOracle ^= 1; break; case 's': pParams->fNpnSave ^= 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, "Cut computation is available only for AIGs (run \"strash\").\n" ); return 1; } if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX ) { Abc_Print( -1, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX ); return 1; } if ( pParams->fDag && pParams->fTree ) { Abc_Print( -1, "Cannot compute both DAG cuts and tree cuts at the same time.\n" ); return 1; } if ( pParams->fNpnSave ) { pParams->nVarsMax = 6; pParams->fTruth = 1; } if ( fOracle ) pParams->fRecord = 1; pCutMan = Abc_NtkCuts( pNtk, pParams ); if ( fOracle ) pCutOracle = Cut_OracleStart( pCutMan ); Cut_ManStop( pCutMan ); if ( fOracle ) { assert(pCutOracle); Abc_NtkCutsOracle( pNtk, pCutOracle ); Cut_OracleStop( pCutOracle ); } return 0; usage: Abc_Print( -2, "usage: cut [-K num] [-M num] [-tfdcovamjsvh]\n" ); Abc_Print( -2, "\t computes k-feasible cuts for the AIG\n" ); Abc_Print( -2, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax ); Abc_Print( -2, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax ); Abc_Print( -2, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); Abc_Print( -2, "\t-f : toggle filtering of duplicated/dominated [default = %s]\n", pParams->fFilter? "yes": "no" ); Abc_Print( -2, "\t-d : toggle dropping when fanouts are done [default = %s]\n", pParams->fDrop? "yes": "no" ); Abc_Print( -2, "\t-x : toggle computing only DAG cuts [default = %s]\n", pParams->fDag? "yes": "no" ); Abc_Print( -2, "\t-y : toggle computing only tree cuts [default = %s]\n", pParams->fTree? "yes": "no" ); Abc_Print( -2, "\t-g : toggle computing only global cuts [default = %s]\n", pParams->fGlobal? "yes": "no" ); Abc_Print( -2, "\t-l : toggle computing only local cuts [default = %s]\n", pParams->fLocal? "yes": "no" ); Abc_Print( -2, "\t-z : toggle fancy computations [default = %s]\n", pParams->fFancy? "yes": "no" ); Abc_Print( -2, "\t-a : toggle recording cut functions [default = %s]\n", pParams->fRecordAig?"yes": "no" ); Abc_Print( -2, "\t-m : toggle delay-oriented FPGA mapping [default = %s]\n", pParams->fMap? "yes": "no" ); Abc_Print( -2, "\t-j : toggle removing fanouts due to XOR/MUX [default = %s]\n", pParams->fAdjust? "yes": "no" ); Abc_Print( -2, "\t-s : toggle creating library of 6-var functions [default = %s]\n", pParams->fNpnSave? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandScut( Abc_Frame_t * pAbc, int argc, char ** argv ) { Cut_Params_t Params, * pParams = &Params; Cut_Man_t * pCutMan; Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); // set defaults memset( pParams, 0, sizeof(Cut_Params_t) ); pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts) pParams->nKeepMax = 1000; // the max number of cuts kept at a node pParams->fTruth = 0; // compute truth tables pParams->fFilter = 1; // filter dominated cuts pParams->fSeq = 1; // compute sequential cuts pParams->fVerbose = 0; // the verbosiness flag Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KMtvh" ) ) != EOF ) { switch ( c ) { case 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); goto usage; } pParams->nVarsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pParams->nVarsMax < 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; } pParams->nKeepMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pParams->nKeepMax < 0 ) goto usage; break; case 't': pParams->fTruth ^= 1; break; case 'v': pParams->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } /* if ( !Abc_NtkIsSeq(pNtk) ) { Abc_Print( -1, "Sequential cuts can be computed for sequential AIGs (run \"seq\").\n" ); return 1; } */ if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX ) { Abc_Print( -1, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX ); return 1; } pCutMan = Abc_NtkSeqCuts( pNtk, pParams ); Cut_ManStop( pCutMan ); return 0; usage: Abc_Print( -2, "usage: scut [-K num] [-M num] [-tvh]\n" ); Abc_Print( -2, "\t computes k-feasible cuts for the sequential AIG\n" ); Abc_Print( -2, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax ); Abc_Print( -2, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax ); Abc_Print( -2, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandEspresso( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fVerbose; extern void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose ); if ( argc == 2 && !strcmp(argv[1], "-h") ) { Abc_Print( -2, "The espresso command is currently disabled.\n" ); return 1; } Abc_Print( -1, "This command is currently disabled.\n" ); return 0; // set defaults 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 ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "SOP minimization is possible for logic networks (run \"renode\").\n" ); return 1; } // Abc_NtkEspresso( pNtk, fVerbose ); return 0; usage: Abc_Print( -2, "usage: espresso [-vh]\n" ); Abc_Print( -2, "\t minimizes SOPs of the local functions using Espresso\n" ); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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]; extern void Abc_GenAdder( char * pFileName, int nVars ); 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, "NAKLatsembfnrgvh" ) ) != 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 '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 ) { 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 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } nLuts = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLuts < 0 ) goto usage; break; case 'a': fAdder ^= 1; break; case 't': fAdderTree ^= 1; break; case 's': fSorter ^= 1; break; case 'e': fMesh ^= 1; break; case 'm': fMulti ^= 1; break; case 'b': fBooth ^= 1; break; case 'f': fFpga ^= 1; break; case 'n': fOneHot ^= 1; break; case 'r': fRandom ^= 1; break; case 'g': fGraph ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { goto usage; } if ( nVars < 1 ) { Abc_Print( -1, "The number of variables should be a positive integer.\n" ); return 0; } // get the input file name FileName = argv[globalUtilOptind]; if ( fAdder ) Abc_GenAdder( FileName, nVars ); else if ( fSorter ) Abc_GenSorter( FileName, nVars ); else if ( fMesh ) 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 ); // Abc_GenFpga( FileName, 3, 2, 5 ); else if ( fOneHot ) 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" ); return 0; } // read the file just produced sprintf(Command, "read %s", FileName ); Cmd_CommandExecute( pAbc, Command ); return 0; usage: 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-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"); Abc_Print( -2, "\t : output file name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandGenTF( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_GenThresh( char * pFileName, int nBits, Vec_Int_t * vNums, int nLutSize, char * pArch ); int c, nBits = 0, nLutSize = -1, fVerbose = 0, nSum = 0; char Command[1000], * pFileName = "out.blif", * pArch = NULL; Vec_Int_t * vNums = NULL; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "WKAvh" ) ) != EOF ) { switch ( c ) { case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } nBits = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nBits < 0 ) goto usage; break; case 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); goto usage; } nLutSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLutSize < 0 ) goto usage; break; case 'A': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-A\" should be followed by a file name.\n" ); goto usage; } pArch = argv[globalUtilOptind]; globalUtilOptind++; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc == globalUtilOptind ) goto usage; if ( nBits == 0 ) { Abc_Print( -1, "Bit-width should be specified.\n" ); return 0; } if ( nLutSize != -1 && nLutSize != 4 && nLutSize != 6 ) { Abc_Print( -1, "LUT size %d is not supported.\n", nLutSize ); return 0; } if ( pArch ) { int Counts[2] = {0}; for ( c = 0; c < strlen(pArch); c++ ) if ( pArch[c] == '(' ) Counts[0]++; else if ( pArch[c] == ')' ) Counts[1]++; else if ( pArch[c] >= '1' && pArch[c] <= '9' ) nSum += pArch[c] - '0'; else if ( pArch[c] >= 'A' && pArch[c] <= 'Z' ) nSum += pArch[c] - 'A' + 10; else { Abc_Print( -1, "Architecture description contains a wrong symbol (%c).\n", pArch[c] ); return 0; } if ( Counts[0] != Counts[1] ) { Abc_Print( -1, "Mismatching number of opening and closing parentheses (%d and %d).\n", Counts[0], Counts[1] ); return 0; } } vNums = Vec_IntAlloc( argc ); for ( c = globalUtilOptind; c < argc; c++ ) Vec_IntPush( vNums, atoi(argv[c]) ); if ( Vec_IntSize(vNums) < 3 ) { Abc_Print( -1, "Expecting that at least two weights and a threshold are specified on the command line.\n" ); Vec_IntFree( vNums ); return 0; } if ( pArch && nSum != Vec_IntSize(vNums)-1 ) { Abc_Print( -1, "The architecture assumes %d sum inputs while there are %d weights.\n", nSum, Vec_IntSize(vNums)-1 ); Vec_IntFree( vNums ); return 0; } printf( "Generating threshold function with %d inputs and bit-width %d.\n", Vec_IntSize(vNums)-1, nBits ); Abc_GenThresh( pFileName, nBits, vNums, nLutSize, pArch ); if ( nLutSize == 4 || nLutSize == 6 ) sprintf(Command, "read %s; strash; if -K %d -am; mfs2 -W 10 -L 10 -M 1000", pFileName, nLutSize ); else sprintf(Command, "read %s", pFileName ); Cmd_CommandExecute( pAbc, Command ); Vec_IntFree( vNums ); return 0; usage: Abc_Print( -2, "usage: gentf [-WK num] [-A str] [-vh] ... \n" ); Abc_Print( -2, "\t generates threshold function\n" ); Abc_Print( -2, "\t-W num : the bit-width [default = none]\n" ); Abc_Print( -2, "\t-K num : the LUT size [default = none]\n" ); Abc_Print( -2, "\t-A str : the circuit architecture [default = none]\n"); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : weights and threshold\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandGenAT( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_GenAT( char * pFileName, Vec_Int_t * vNums ); extern void Abc_GenATDual( char * pFileName, Vec_Int_t * vNums ); int c, fDual = 0, fVerbose = 0; char Command[1000], * pFileName = "out.blif"; Vec_Int_t * vNums = NULL; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "dvh" ) ) != EOF ) { switch ( c ) { case 'd': fDual ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc == globalUtilOptind ) goto usage; vNums = Vec_IntAlloc( argc ); for ( c = globalUtilOptind; c < argc; c++ ) Vec_IntPush( vNums, atoi(argv[c]) ); if ( fDual ) Abc_GenATDual( pFileName, vNums ); else Abc_GenAT( pFileName, vNums ); sprintf(Command, "read %s", pFileName ); Cmd_CommandExecute( pAbc, Command ); Vec_IntFree( vNums ); return 0; usage: Abc_Print( -2, "usage: genat [-dvh] ... \n" ); Abc_Print( -2, "\t generates the adder tree\n" ); Abc_Print( -2, "\t-d : toggle building dual tree [default = %s]\n", fDual? "yes": "no" ); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : input counts by rank\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandGenFsm( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_GenFsm( char * pFileName, int nIns, int nOuts, int nStates, int nLines, int ProbI, int ProbO ); int c, nIns, nOuts, nStates, nLines, ProbI, ProbO, fVerbose; char * FileName; // set defaults nIns = 30; nOuts = 1; nStates = 20; nLines = 100; ProbI = 10; ProbO = 100; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "IOSLPQvh" ) ) != EOF ) { switch ( c ) { case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } nIns = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nIns < 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 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } nStates = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nStates < 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; } nLines = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLines < 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; } ProbI = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( ProbI < 0 ) goto usage; break; case 'Q': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" ); goto usage; } ProbO = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( ProbO < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) { goto usage; } if ( nIns < 1 || nStates < 1 || nLines < 1 || ProbI < 1 || ProbO < 1 ) { Abc_Print( -1, "The number of inputs. states, lines, and probablity should be positive integers.\n" ); goto usage; } // get the input file name FileName = argv[globalUtilOptind]; Abc_GenFsm( FileName, nIns, nOuts, nStates, nLines, ProbI, ProbO ); return 0; usage: Abc_Print( -2, "usage: genfsm [-IOSLPQ num] [-vh] \n" ); Abc_Print( -2, "\t generates random FSM in KISS format\n" ); Abc_Print( -2, "\t-I num : the number of input variables [default = %d]\n", nIns ); Abc_Print( -2, "\t-O num : the number of output variables [default = %d]\n", nOuts ); Abc_Print( -2, "\t-S num : the number of state variables [default = %d]\n", nStates ); Abc_Print( -2, "\t-L num : the number of lines (product terms) [default = %d]\n", nLines ); Abc_Print( -2, "\t-P num : percentage propability of a variable present in the input cube [default = %d]\n", ProbI ); Abc_Print( -2, "\t-Q num : percentage propability of a variable present in the output cube [default = %d]\n", ProbO ); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : output file name\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandCover( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; int fVerbose; int fUseSop; int fUseEsop; int fUseInvs; int nFaninMax; int nCubesMax; pNtk = Abc_FrameReadNtk(pAbc); // set defaults fUseSop = 1; fUseEsop = 0; fVerbose = 0; fUseInvs = 1; nFaninMax = 8; nCubesMax = 8; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "IPsxivh" ) ) != EOF ) { switch ( c ) { case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } nFaninMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFaninMax < 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; } nCubesMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCubesMax < 0 ) goto usage; break; case 's': fUseSop ^= 1; break; case 'x': fUseEsop ^= 1; break; case 'i': fUseInvs ^= 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Only works for strashed networks.\n" ); return 1; } // run the command pNtkRes = Abc_NtkSopEsopCover( pNtk, nFaninMax, nCubesMax, fUseEsop, fUseSop, fUseInvs, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: cover [-IP num] [-sxvh]\n" ); Abc_Print( -2, "\t decomposition into a network of SOP/ESOP PLAs\n" ); Abc_Print( -2, "\t (this command is known to have bugs)\n"); Abc_Print( -2, "\t-I num : maximum number of inputs [default = %d]\n", nFaninMax ); Abc_Print( -2, "\t-P num : maximum number of products [default = %d]\n", nCubesMax ); Abc_Print( -2, "\t-s : toggle the use of SOPs [default = %s]\n", fUseSop? "yes": "no" ); Abc_Print( -2, "\t-x : toggle the use of ESOPs [default = %s]\n", fUseEsop? "yes": "no" ); // Abc_Print( -2, "\t-i : toggle the use of interters [default = %s]\n", fUseInvs? "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_CommandInter( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes = NULL; char ** pArgvNew; int nArgcNew; int c, fDelete1, fDelete2; int fRelation; int fVerbose; extern Abc_Ntk_t * Abc_NtkInter( Abc_Ntk_t * pNtkOn, Abc_Ntk_t * pNtkOff, int fRelation, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fRelation = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF ) { switch ( c ) { case 'r': fRelation ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2, 1 ) ) return 1; if ( nArgcNew == 0 ) { Abc_Obj_t * pObj; int i; Abc_Print( -1, "Deriving new circuit structure for the current network.\n" ); Abc_NtkForEachPo( pNtk2, pObj, i ) Abc_ObjXorFaninC( pObj, 0 ); } if ( fRelation && Abc_NtkCoNum(pNtk1) != 1 ) { Abc_Print( -1, "Computation of interplants as a relation only works for single-output functions.\n" ); Abc_Print( -1, "Use command \"cone\" to extract one output cone from the multi-output network.\n" ); } else pNtkRes = Abc_NtkInter( pNtk1, pNtk2, fRelation, fVerbose ); if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: inter [-rvh] \n" ); Abc_Print( -2, "\t derives interpolant of two networks representing onset and offset;\n" ); Abc_Print( -2, "\t-r : toggle computing interpolant as a relation [default = %s]\n", fRelation? "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 \n" ); Abc_Print( -2, "\t Comments:\n" ); Abc_Print( -2, "\t \n" ); Abc_Print( -2, "\t The networks given on the command line should have the same CIs/COs.\n" ); Abc_Print( -2, "\t If only one network is given on the command line, this network\n" ); Abc_Print( -2, "\t is assumed to be the offset, while the current network is the onset.\n" ); Abc_Print( -2, "\t If no network is given on the command line, the current network is\n" ); Abc_Print( -2, "\t assumed to be the onset and its complement is taken to be the offset.\n" ); Abc_Print( -2, "\t The resulting interpolant is stored as the current network.\n" ); Abc_Print( -2, "\t To verify that the interpolant agrees with the onset and the offset,\n" ); Abc_Print( -2, "\t save it in file \"inter.blif\" and run the following:\n" ); Abc_Print( -2, "\t (a) \"miter -i ; iprove\"\n" ); Abc_Print( -2, "\t (b) \"miter -i ; iprove\"\n" ); Abc_Print( -2, "\t where is the network derived by complementing the\n" ); Abc_Print( -2, "\t outputs of : \"r ; st -i; w \"\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDouble( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; int nFrames; int fVerbose; extern Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nFrames = 50; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } nFrames = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nFrames < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsSopLogic(pNtk) ) { Abc_Print( -1, "Only works for logic SOP networks.\n" ); return 1; } pNtkRes = Abc_NtkDouble( pNtk ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: double [-vh]\n" ); Abc_Print( -2, "\t puts together two parallel copies of the current network\n" ); // Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); 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_CommandBb2Wb( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkConvertBb2Wb( char * pFileNameIn, char * pFileNameOut, int fSeq, int fVerbose ); int c; int fSeq; int fVerbose; // set defaults fSeq = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) { switch ( c ) { case 's': fSeq ^= 1; break; case 'v': fVerbose ^= 1; break; default: goto usage; } } if ( argc != globalUtilOptind + 2 ) { Abc_Print( -1, "Expecting two files names on the command line.\n" ); goto usage; } Abc_NtkConvertBb2Wb( argv[globalUtilOptind], argv[globalUtilOptind+1], fSeq, fVerbose ); return 0; usage: Abc_Print( -2, "usage: bb2wb [-svh] \n" ); Abc_Print( -2, "\t replaces black boxes by white boxes with AND functions\n" ); Abc_Print( -2, "\t (file names should have standard extensions, e.g. \"blif\")\n" ); Abc_Print( -2, "\t-s : toggle using sequential white boxes [default = %s]\n", fSeq? "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 : input file with design containing black boxes\n"); Abc_Print( -2, "\t : output file with design containing white boxes\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandOutdec( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkDarOutdec( Abc_Ntk_t * pNtk, int nLits, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Ntk_t * pNtkRes; int c, nLits = 1; int fVerbose = 0; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Lvh" ) ) != EOF ) { switch ( c ) { case 'L': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); goto usage; } nLits = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLits < 1 || nLits > 2 ) { Abc_Print( 1,"Currently, command \"outdec\" works for 1-lit and 2-lit primes only.\n" ); goto usage; } break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Only works for strashed networks.\n" ); return 1; } pNtkRes = Abc_NtkDarOutdec( pNtk, nLits, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: outdec [-Lvh]\n" ); Abc_Print( -2, "\t performs prime decomposition of the first output\n" ); Abc_Print( -2, "\t-L num : the number of literals in the primes [default = %d]\n", nLits ); 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_CommandNodeDup( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern Abc_Ntk_t * Abc_NtkNodeDup( Abc_Ntk_t * pNtk, int nLimit, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Ntk_t * pNtkRes; int c, nLimit = 30; int fVerbose = 0; // set defaults 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; } nLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "Only works for logic networks.\n" ); return 1; } if ( nLimit < 2 ) { Abc_Print( -1, "The fanout limit should be more than 1.\n" ); return 1; } pNtkRes = Abc_NtkNodeDup( pNtk, nLimit, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: nodedup [-Nvh]\n" ); Abc_Print( -2, "\t duplicates internal nodes with high fanout\n" ); Abc_Print( -2, "\t-N num : the number of fanouts to start duplication [default = %d]\n", nLimit ); 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_CommandWrap( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * pFileName = NULL, * pFileName2 = NULL; FILE * pFile = NULL, * pFile2 = NULL; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 2 ) { Abc_Print( 1,"Two file names are expected on the command line.\n" ); return 0; } pFileName = argv[globalUtilOptind]; pFileName2 = argv[globalUtilOptind+1]; pFile = fopen( pFileName, "rb" ); pFile2 = fopen( pFileName2, "wb" ); if ( pFile && pFile2 ) { char Buffer[1000]; while ( fgets( Buffer, 1000, pFile ) != NULL ) { if ( Buffer[strlen(Buffer)-1] == '\n' ) Buffer[strlen(Buffer)-1] = 0; if ( Buffer[strlen(Buffer)-1] == '\r' ) Buffer[strlen(Buffer)-1] = 0; fprintf( pFile2, " printf(\"%s\\n\");\n", Buffer ); } } if ( pFile ) fclose(pFile); if ( pFile2 ) fclose(pFile2); return 0; usage: Abc_Print( -2, "usage: wrap [-h] \n" ); Abc_Print( -2, "\t wrapping lines\n" ); Abc_Print( -2, "\t : input text file\n"); Abc_Print( -2, "\t : output text file\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandTestColor( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_ColorTest(); Abc_ColorTest(); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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 = 3; int nNumOnes = 0; int fNewAlgo = 0; int fNewOrder = 0; int fVerbose = 0; int fVeryVerbose = 0; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CKDNMaovwh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } nCutMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCutMax < 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; } nLeafMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLeafMax < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } nDivMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nDivMax < 0 ) goto usage; break; case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } nDecMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nDecMax < 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; } nNumOnes = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nNumOnes < 0 ) goto usage; break; case 'a': fNewAlgo ^= 1; break; case 'o': fNewOrder ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 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.\n" ); return 1; } */ /* if ( Abc_NtkLatchNum(pNtk) == 0 ) { Abc_Print( -1, "Only works for sequential networks.\n" ); return 1; } */ /* if ( pNtk ) { extern Abc_Ntk_t * Au_ManPerformTest( Abc_Ntk_t * p, int nCutMax, int nLeafMax, int nDivMax, int nDecMax, int fVerbose, int fVeryVerbose ); Abc_Ntk_t * pNtkRes = Au_ManPerformTest( pNtk, nCutMax, nLeafMax, nDivMax, nDecMax, fVerbose, fVeryVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 1; } Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); } */ /* if ( pNtk ) { Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 ); Saig_ManBmcTerSimTestPo( pAig ); Aig_ManStop( pAig ); } */ /* if ( !Abc_NtkIsTopo(pNtk) ) { Abc_Print( -1, "Current network is not in a topological order.\n" ); return 1; } */ // if ( pNtk ) // Abc_NtkMakeLegit( pNtk ); { // extern void Ifd_ManDsdTest(); // Ifd_ManDsdTest(); } /* { extern void Abc_EnumerateCubeStates(); extern void Abc_EnumerateCubeStatesZdd(); if ( fNewAlgo ) Abc_EnumerateCubeStatesZdd(); else Abc_EnumerateCubeStates(); return 0; } */ { // extern void Abc_EnumerateFuncs( int nDecMax, int nDivMax, int fVerbose ); // Abc_EnumerateFuncs( 4, 7, 0 ); } /* if ( fNewAlgo ) { extern void Abc_SuppTest( int nOnes, int nVars, int fUseSimple, int fCheck, int fVerbose ); Abc_SuppTest( nNumOnes, nDecMax, fNewOrder, 0, fVerbose ); } else { extern void Bmc_EcoMiterTest(); Bmc_EcoMiterTest(); } */ { // extern void Nf_ManPrepareLibraryTest(); // Nf_ManPrepareLibraryTest(); // return 0; } /* if ( pNtk ) { // extern Abc_Ntk_t * Abc_NtkBarBufsOnOffTest( Abc_Ntk_t * pNtk ); // Abc_Ntk_t * pNtkRes = Abc_NtkBarBufsOnOffTest( pNtk ); extern Abc_Ntk_t * Abc_NtkPcmTest( Abc_Ntk_t * pNtk, int fNewAlgo, int fVerbose ); // extern Abc_Ntk_t * Abc_NtkPcmTestAig( Abc_Ntk_t * pNtk, int fVerbose ); Abc_Ntk_t * pNtkRes; // if ( Abc_NtkIsLogic(pNtk) ) pNtkRes = Abc_NtkPcmTest( pNtk, fNewAlgo, fVerbose ); // else // pNtkRes = Abc_NtkPcmTestAig( pNtk, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 1; } Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); } */ /* { extern void Abc_IsopTestNew(); Abc_IsopTestNew(); } */ { // extern void Cba_PrsReadBlifTest(); // Cba_PrsReadBlifTest(); } // Abc_NtkComputePaths( Abc_FrameReadNtk(pAbc) ); //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 ); } */ //Gia_ManTestProblem(); //Abc_ReadPlaTest( "resub2.pla" ); return 0; usage: Abc_Print( -2, "usage: test [-CKDNM] [-aovwh] \n" ); Abc_Print( -2, "\t testbench for new procedures\n" ); Abc_Print( -2, "\t-C num : the max number of cuts [default = %d]\n", nCutMax ); Abc_Print( -2, "\t-K num : the max number of leaves [default = %d]\n", nLeafMax ); Abc_Print( -2, "\t-D num : the max number of divisors [default = %d]\n", nDivMax ); Abc_Print( -2, "\t-N num : the max number of node inputs [default = %d]\n", nDecMax ); Abc_Print( -2, "\t-M num : the max number of ones in the vector [default = %d]\n", nNumOnes ); Abc_Print( -2, "\t-a : toggle using new algorithm [default = %s]\n", fNewAlgo? "yes": "no" ); Abc_Print( -2, "\t-o : toggle using new ordering [default = %s]\n", fNewOrder? "yes": "no" ); Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle printing very 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_CommandQuaVar( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, iVar, fUniv, fVerbose, RetValue; extern int Abc_NtkQuantify( Abc_Ntk_t * pNtk, int fUniv, int iVar, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults iVar = 0; fUniv = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Iuvh" ) ) != EOF ) { switch ( c ) { case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } iVar = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iVar < 0 ) goto usage; break; case 'u': fUniv ^= 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_NtkGetChoiceNum( pNtk ) ) { Abc_Print( -1, "This command cannot be applied to an AIG with choice nodes.\n" ); return 1; } // get the strashed network pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); RetValue = Abc_NtkQuantify( pNtkRes, fUniv, iVar, fVerbose ); // clean temporary storage for the cofactors Abc_NtkCleanData( pNtkRes ); Abc_AigCleanup( (Abc_Aig_t *)pNtkRes->pManFunc ); // check the result if ( !RetValue ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: qvar [-I num] [-uvh]\n" ); Abc_Print( -2, "\t quantifies one variable using the AIG\n" ); Abc_Print( -2, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar ); Abc_Print( -2, "\t-u : toggle universal quantification [default = %s]\n", fUniv? "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_CommandQuaRel( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, iVar, fInputs, fVerbose; extern Abc_Ntk_t * Abc_NtkTransRel( Abc_Ntk_t * pNtk, int fInputs, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults iVar = 0; fInputs = 1; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Iqvh" ) ) != EOF ) { switch ( c ) { case 'I': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); goto usage; } iVar = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( iVar < 0 ) goto usage; break; case 'q': fInputs ^= 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_NtkGetChoiceNum( pNtk ) ) { Abc_Print( -1, "This command cannot be applied to an AIG with choice nodes.\n" ); return 1; } if ( Abc_NtkIsComb(pNtk) ) { Abc_Print( -1, "This command works only for sequential circuits.\n" ); return 1; } // get the strashed network if ( !Abc_NtkIsStrash(pNtk) ) { pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 ); pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose ); Abc_NtkDelete( pNtk ); } else pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose ); // check if the result is available if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: qrel [-qvh]\n" ); Abc_Print( -2, "\t computes transition relation of the sequential network\n" ); // Abc_Print( -2, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar ); Abc_Print( -2, "\t-q : perform quantification of inputs [default = %s]\n", fInputs? "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_CommandQuaReach( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, nIters, fVerbose; extern Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtk, int nIters, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nIters = 256; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != 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 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Abc_NtkGetChoiceNum( pNtk ) ) { Abc_Print( -1, "This command cannot be applied to an AIG with choice nodes.\n" ); return 1; } if ( !Abc_NtkIsComb(pNtk) ) { Abc_Print( -1, "This command works only for combinational transition relations.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for strashed networks.\n" ); return 1; } if ( Abc_NtkPoNum(pNtk) > 1 ) { Abc_Print( -1, "The transition relation should have one output.\n" ); return 1; } if ( Abc_NtkPiNum(pNtk) % 2 != 0 ) { Abc_Print( -1, "The transition relation should have an even number of inputs.\n" ); return 1; } pNtkRes = Abc_NtkReachability( pNtk, nIters, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: qreach [-I num] [-vh]\n" ); Abc_Print( -2, "\t computes unreachable states using AIG-based quantification\n" ); Abc_Print( -2, "\t assumes that the current network is a transition relation\n" ); Abc_Print( -2, "\t assumes that the initial state is composed of all zeros\n" ); Abc_Print( -2, "\t-I num : the number of image computations to perform [default = %d]\n", nIters ); 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_CommandSenseInput( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Vec_Int_t * vResult; int c, nConfLim, fVerbose; extern Vec_Int_t * Abc_NtkSensitivity( Abc_Ntk_t * pNtk, int nConfLim, int fVerbose ); // set defaults nConfLim = 1000; fVerbose = 1; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Cvh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } nConfLim = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nConfLim < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Abc_NtkGetChoiceNum( pNtk ) ) { Abc_Print( -1, "This command cannot be applied to an AIG with choice nodes.\n" ); return 1; } if ( !Abc_NtkIsComb(pNtk) ) { Abc_Print( -1, "This command works only for combinational transition relations.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for strashed networks.\n" ); return 1; } if ( Abc_NtkPoNum(pNtk) < 2 ) { Abc_Print( -1, "The network should have at least two outputs.\n" ); return 1; } vResult = Abc_NtkSensitivity( pNtk, nConfLim, fVerbose ); Vec_IntFree( vResult ); return 0; usage: Abc_Print( -2, "usage: senseinput [-C num] [-vh]\n" ); Abc_Print( -2, "\t computes sensitivity of POs to PIs under constraint\n" ); Abc_Print( -2, "\t constraint should be represented as the last PO\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nConfLim ); 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_CommandIStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp; int c; extern Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk ); 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_NtkIsStrash(pNtk) ) { pNtkTemp = Abc_NtkStrash( pNtk, 0, 1, 0 ); pNtkRes = Abc_NtkIvyStrash( pNtkTemp ); Abc_NtkDelete( pNtkTemp ); } else pNtkRes = Abc_NtkIvyStrash( pNtk ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: istrash [-h]\n" ); Abc_Print( -2, "\t perform sequential structural hashing\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandICut( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c, nInputs; extern void Abc_NtkIvyCuts( Abc_Ntk_t * pNtk, int nInputs ); // set defaults nInputs = 5; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Kh" ) ) != EOF ) { switch ( c ) { case 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); goto usage; } nInputs = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nInputs < 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, "This command works only for strashed networks.\n" ); return 1; } Abc_NtkIvyCuts( pNtk, nInputs ); return 0; usage: Abc_Print( -2, "usage: icut [-K num] [-h]\n" ); Abc_Print( -2, "\t computes sequential cuts of the given size\n" ); Abc_Print( -2, "\t-K num : the number of cut inputs (2 <= num <= 6) [default = %d]\n", nInputs ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandIRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, fUpdateLevel, fUseZeroCost, fVerbose; extern Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroCost, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fUpdateLevel = 1; fUseZeroCost = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF ) { switch ( c ) { case 'l': fUpdateLevel ^= 1; break; case 'z': fUseZeroCost ^= 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for strashed networks.\n" ); return 1; } pNtkRes = Abc_NtkIvyRewrite( pNtk, fUpdateLevel, fUseZeroCost, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: irw [-lzvh]\n" ); Abc_Print( -2, "\t perform combinational AIG rewriting\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", fUseZeroCost? "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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; Dar_RwrPar_t Pars, * pPars = &Pars; int c; extern Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults Dar_ManDefaultRwrParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CNMflzrvwh" ) ) != 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->nCutsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->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; } pPars->nSubgMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; 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; case 'l': pPars->fUpdateLevel ^= 1; break; case 'z': pPars->fUseZeros ^= 1; break; case 'r': pPars->fRecycle ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pPars->fUseZeros ) pPars->nMinSaved = 0; if ( pPars->nMinSaved == 0 ) pPars->fUseZeros = 1; if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for strashed networks.\n" ); return 1; } pNtkRes = Abc_NtkDRewrite( pNtk, pPars ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: 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" ); Abc_Print( -2, "\t-r : toggle using cut recycling [default = %s]\n", pPars->fRecycle? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle very verbose printout [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_CommandDRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; Dar_RefPar_t Pars, * pPars = &Pars; int c; extern Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults Dar_ManDefaultRefParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "MKCelzvwh" ) ) != EOF ) { switch ( c ) { case 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } pPars->nMffcMin = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nMffcMin < 0 ) goto usage; break; case 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } pPars->nLeafMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nLeafMax < 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->nCutsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCutsMax < 0 ) goto usage; break; case 'e': pPars->fExtend ^= 1; break; case 'l': pPars->fUpdateLevel ^= 1; break; case 'z': pPars->fUseZeros ^= 1; break; case 'v': pPars->fVerbose ^= 1; break; case 'w': pPars->fVeryVerbose ^= 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 strashed networks.\n" ); return 1; } if ( pPars->nLeafMax < 4 || pPars->nLeafMax > 15 ) { Abc_Print( -1, "This command only works for cut sizes 4 <= K <= 15.\n" ); return 1; } pNtkRes = Abc_NtkDRefactor( pNtk, pPars ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: drf [-M num] [-K num] [-C num] [-elzvwh]\n" ); Abc_Print( -2, "\t performs combinational AIG refactoring\n" ); Abc_Print( -2, "\t-M num : the min MFFC size to attempt refactoring [default = %d]\n", pPars->nMffcMin ); Abc_Print( -2, "\t-K num : the max number of cuts leaves [default = %d]\n", pPars->nLeafMax ); Abc_Print( -2, "\t-C num : the max number of cuts to try at a node [default = %d]\n", pPars->nCutsMax ); Abc_Print( -2, "\t-e : toggle extending tbe cut below MFFC [default = %s]\n", pPars->fExtend? "yes": "no" ); Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" ); Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : toggle very verbose printout [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_CommandDc2( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int fBalance, fVerbose, fUpdateLevel, fFanout, fPower, c; extern Abc_Ntk_t * Abc_NtkDC2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fBalance = 0; fVerbose = 0; fUpdateLevel = 0; fFanout = 1; fPower = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "blfpvh" ) ) != EOF ) { switch ( c ) { case 'b': fBalance ^= 1; break; case 'l': fUpdateLevel ^= 1; break; case 'f': fFanout ^= 1; break; case 'p': fPower ^= 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for strashed networks.\n" ); return 1; } pNtkRes = Abc_NtkDC2( pNtk, fBalance, fUpdateLevel, fFanout, fPower, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: dc2 [-blfpvh]\n" ); Abc_Print( -2, "\t performs combinational AIG optimization\n" ); Abc_Print( -2, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); Abc_Print( -2, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" ); Abc_Print( -2, "\t-f : toggle representing fanouts [default = %s]\n", fFanout? "yes": "no" ); Abc_Print( -2, "\t-p : toggle power-aware rewriting [default = %s]\n", fPower? "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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDChoice( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int fBalance, fVerbose, fUpdateLevel, fConstruct, c; int nConfMax, nLevelMax; extern Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fBalance = 1; fUpdateLevel = 1; fConstruct = 0; nConfMax = 1000; nLevelMax = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CLblcvh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } nConfMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nConfMax < 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; } nLevelMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLevelMax < 0 ) goto usage; break; case 'b': fBalance ^= 1; break; case 'l': fUpdateLevel ^= 1; break; case 'c': fConstruct ^= 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for strashed networks.\n" ); return 1; } pNtkRes = Abc_NtkDChoice( pNtk, fBalance, fUpdateLevel, fConstruct, nConfMax, nLevelMax, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: dchoice [-C num] [-L num] [-blcvh]\n" ); Abc_Print( -2, "\t performs partitioned choicing using new AIG package\n" ); Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nConfMax ); Abc_Print( -2, "\t-L num : the max level of nodes to consider (0 = not used) [default = %d]\n", nLevelMax ); Abc_Print( -2, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); Abc_Print( -2, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" ); Abc_Print( -2, "\t-c : toggle constructive computation of choices [default = %s]\n", fConstruct? "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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDch( Abc_Frame_t * pAbc, int argc, char ** argv ) { Dch_Pars_t Pars, * pPars = &Pars; Abc_Ntk_t * pNtk, * pNtkRes; int c; extern Abc_Ntk_t * Abc_NtkDch( Abc_Ntk_t * pNtk, Dch_Pars_t * pPars ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults Dch_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptgcfrxvh" ) ) != EOF ) { switch ( c ) { case 'W': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); goto usage; } pPars->nWords = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nWords < 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 'S': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); goto usage; } pPars->nSatVarMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nSatVarMax < 0 ) goto usage; break; case 's': pPars->fSynthesis ^= 1; break; case 'p': pPars->fPower ^= 1; break; case 't': pPars->fSimulateTfo ^= 1; break; case 'g': pPars->fUseGia ^= 1; break; case 'c': pPars->fUseCSat ^= 1; break; case 'f': pPars->fLightSynth ^= 1; break; case 'r': pPars->fSkipRedSupp ^= 1; break; case 'x': pPars->fUseNew ^= 1; break; case 'v': pPars->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 strashed networks.\n" ); return 1; } pNtkRes = Abc_NtkDch( pNtk, pPars ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: 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 ); Abc_Print( -2, "\t-S num : the max number of SAT variables [default = %d]\n", pPars->nSatVarMax ); Abc_Print( -2, "\t-s : toggle synthesizing three snapshots [default = %s]\n", pPars->fSynthesis? "yes": "no" ); Abc_Print( -2, "\t-p : toggle power-aware rewriting [default = %s]\n", pPars->fPower? "yes": "no" ); Abc_Print( -2, "\t-t : toggle simulation of the TFO classes [default = %s]\n", pPars->fSimulateTfo? "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-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; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDrwsat( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int fBalance, fVerbose, c; extern Abc_Ntk_t * Abc_NtkDrwsat( Abc_Ntk_t * pNtk, int fBalance, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fBalance = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "bvh" ) ) != EOF ) { switch ( c ) { case 'b': fBalance ^= 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for strashed networks.\n" ); return 1; } pNtkRes = Abc_NtkDrwsat( pNtk, fBalance, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: drwsat [-bvh]\n" ); Abc_Print( -2, "\t performs combinational AIG optimization for SAT\n" ); Abc_Print( -2, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandIRewriteSeq( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, fUpdateLevel, fUseZeroCost, fVerbose; extern Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fUpdateLevel = 0; fUseZeroCost = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF ) { switch ( c ) { case 'l': fUpdateLevel ^= 1; break; case 'z': fUseZeroCost ^= 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for strashed networks.\n" ); return 1; } pNtkRes = Abc_NtkIvyRewriteSeq( pNtk, fUseZeroCost, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: irws [-zvh]\n" ); Abc_Print( -2, "\t perform sequential AIG rewriting\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", fUseZeroCost? "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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandIResyn( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, fUpdateLevel, fVerbose; extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fUpdateLevel = 1; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF ) { switch ( c ) { case 'l': fUpdateLevel ^= 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for strashed networks.\n" ); return 1; } pNtkRes = Abc_NtkIvyResyn( pNtk, fUpdateLevel, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: iresyn [-lvh]\n" ); Abc_Print( -2, "\t performs combinational resynthesis\n" ); Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandISat( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, fUpdateLevel, fVerbose; int nConfLimit; extern Abc_Ntk_t * Abc_NtkIvySat( Abc_Ntk_t * pNtk, int nConfLimit, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nConfLimit = 100000; fUpdateLevel = 1; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Clzvh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } nConfLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nConfLimit < 0 ) goto usage; break; case 'l': fUpdateLevel ^= 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for strashed networks.\n" ); return 1; } pNtkRes = Abc_NtkIvySat( pNtk, nConfLimit, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: isat [-C num] [-vh]\n" ); Abc_Print( -2, "\t tries to prove the miter constant 0\n" ); Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); // Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandIFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, fProve, fVerbose, fDoSparse; int nConfLimit; int nPartSize; int nLevelMax; extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose ); extern Abc_Ntk_t * Abc_NtkDarFraigPart( Abc_Ntk_t * pNtk, int nPartSize, int nConfLimit, int nLevelMax, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nPartSize = 0; nLevelMax = 0; nConfLimit = 100; fDoSparse = 1; fProve = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "PCLspvh" ) ) != EOF ) { switch ( c ) { case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } nPartSize = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nPartSize < 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; } nConfLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nConfLimit < 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; } nLevelMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLevelMax < 0 ) goto usage; break; case 's': fDoSparse ^= 1; break; case 'p': fProve ^= 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for strashed networks.\n" ); return 1; } if ( nPartSize > 0 ) pNtkRes = Abc_NtkDarFraigPart( pNtk, nPartSize, nConfLimit, nLevelMax, fVerbose ); else pNtkRes = Abc_NtkIvyFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: ifraig [-P num] [-C num] [-L num] [-spvh]\n" ); Abc_Print( -2, "\t performs fraiging using a new method\n" ); Abc_Print( -2, "\t-P num : partition size (0 = partitioning is not used) [default = %d]\n", nPartSize ); Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); Abc_Print( -2, "\t-L num : limit on node level to fraig (0 = fraig all nodes) [default = %d]\n", nLevelMax ); Abc_Print( -2, "\t-s : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" ); Abc_Print( -2, "\t-p : toggle proving the miter outputs [default = %s]\n", fProve? "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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandDFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, nConfLimit, fDoSparse, fProve, fSpeculate, fChoicing, fVerbose; extern Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fSpeculate, int fChoicing, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nConfLimit = 100; fDoSparse = 1; fProve = 0; fSpeculate = 0; fChoicing = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Csprcvh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } nConfLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nConfLimit < 0 ) goto usage; break; case 's': fDoSparse ^= 1; break; case 'p': fProve ^= 1; break; case 'r': fSpeculate ^= 1; break; case 'c': fChoicing ^= 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_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for strashed networks.\n" ); return 1; } pNtkRes = Abc_NtkDarFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fSpeculate, fChoicing, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: dfraig [-C num] [-sprcvh]\n" ); Abc_Print( -2, "\t performs fraiging using a new method\n" ); Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); Abc_Print( -2, "\t-s : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" ); Abc_Print( -2, "\t-p : toggle proving the miter outputs [default = %s]\n", fProve? "yes": "no" ); Abc_Print( -2, "\t-r : toggle speculative reduction [default = %s]\n", fSpeculate? "yes": "no" ); Abc_Print( -2, "\t-c : toggle accumulation of choices [default = %s]\n", fChoicing? "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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandCSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c, nCutsMax, nLeafMax, fVerbose; extern Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nCutsMax = 8; nLeafMax = 6; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "CKvh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } nCutsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCutsMax < 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; } nLeafMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nLeafMax < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( nCutsMax < 2 ) { Abc_Print( -1, "The number of cuts cannot be less than 2.\n" ); return 1; } if ( nLeafMax < 3 || nLeafMax > 16 ) { Abc_Print( -1, "The number of leaves is infeasible.\n" ); return 1; } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for strashed networks.\n" ); return 1; } pNtkRes = Abc_NtkCSweep( pNtk, nCutsMax, nLeafMax, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: csweep [-C num] [-K num] [-vh]\n" ); Abc_Print( -2, "\t performs cut sweeping using a new method\n" ); Abc_Print( -2, "\t-C num : limit on the number of cuts (C >= 2) [default = %d]\n", nCutsMax ); Abc_Print( -2, "\t-K num : limit on the cut size (3 <= K <= 16) [default = %d]\n", nLeafMax ); 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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ 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 ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults Prove_ParamsSetDefault( pParams ); pParams->fUseRewriting = 1; pParams->fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NCFGMILrfbvh" ) ) != EOF ) { switch ( c ) { case 'N': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); goto usage; } pParams->nItersMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pParams->nItersMax < 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; } pParams->nMiteringLimitStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pParams->nMiteringLimitStart < 0 ) goto usage; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); goto usage; } pParams->nFraigingLimitStart = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pParams->nFraigingLimitStart < 0 ) goto usage; break; case 'G': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" ); goto usage; } pParams->nFraigingLimitMulti = (float)atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pParams->nFraigingLimitMulti < 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; } pParams->nMiteringLimitLast = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pParams->nMiteringLimitLast < 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; } pParams->nTotalInspectLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; 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; case 'f': pParams->fUseFraiging ^= 1; break; case 'b': pParams->fUseBdds ^= 1; break; case 'v': pParams->fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Abc_NtkLatchNum(pNtk) > 0 ) { Abc_Print( -1, "The network has registers. Use \"dprove\".\n" ); return 1; } clk = Abc_Clock(); if ( Abc_NtkIsStrash(pNtk) ) pNtkTemp = Abc_NtkDup( pNtk ); else pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); RetValue = Abc_NtkIvyProve( &pNtkTemp, pParams ); // verify that the pattern is correct if ( RetValue == 0 ) { Abc_Obj_t * pObj; int i; int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel ); Abc_NtkForEachCo( pNtk, pObj, i ) if ( pSimInfo[i] == 1 ) { iOut = i; break; } if ( i == Abc_NtkCoNum(pNtk) ) Abc_Print( 1, "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); ABC_FREE( pSimInfo ); } pAbc->Status = RetValue; if ( RetValue == -1 ) Abc_Print( 1, "UNDECIDED " ); else if ( RetValue == 0 ) Abc_Print( 1, "SATISFIABLE (output = %d) ", iOut ); else Abc_Print( 1, "UNSATISFIABLE " ); //Abc_Print( -1, "\n" ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp ); // update counter example if ( RetValue == 0 && Abc_NtkLatchNum(pNtkTemp) == 0 ) { 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 [-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-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" ); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ /* int Abc_CommandHaig( Abc_Frame_t * pAbc, int argc, char ** argv ) { FILE * stdout, * pErr; Abc_Ntk_t * pNtk, * pNtkRes; int c; int nIters; int nSteps; int fRetimingOnly; int fAddBugs; int fUseCnf; int fVerbose; extern Abc_Ntk_t * Abc_NtkDarHaigRecord( Abc_Ntk_t * pNtk, int nIters, int nSteps, int fRetimingOnly, int fAddBugs, int fUseCnf, int fVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults nIters = 3; nSteps = 3000; fRetimingOnly = 0; fAddBugs = 0; fUseCnf = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ISrbcvh" ) ) != 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; } 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 a positive integer.\n" ); goto usage; } nSteps = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nSteps < 0 ) goto usage; break; case 'r': fRetimingOnly ^= 1; break; case 'b': fAddBugs ^= 1; break; case 'c': fUseCnf ^= 1; break; case 'v': fUseCnf ^= 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 strashed networks.\n" ); return 1; } pNtkRes = Abc_NtkDarHaigRecord( pNtk, nIters, nSteps, fRetimingOnly, fAddBugs, fUseCnf, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Command has failed.\n" ); return 0; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: haig [-IS num] [-rbcvh]\n" ); Abc_Print( -2, "\t run a few rounds of comb+seq synthesis to test HAIG recording\n" ); Abc_Print( -2, "\t the current network is set to be the result of synthesis performed\n" ); Abc_Print( -2, "\t (this network can be verified using command \"dsec\")\n" ); Abc_Print( -2, "\t HAIG is written out into the file \"haig.blif\"\n" ); Abc_Print( -2, "\t (this HAIG can be proved using \"r haig.blif; st; dprove -abc -F 16\")\n" ); Abc_Print( -2, "\t-I num : the number of rounds of comb+seq synthesis [default = %d]\n", nIters ); Abc_Print( -2, "\t-S num : the number of forward retiming moves performed [default = %d]\n", nSteps ); Abc_Print( -2, "\t-r : toggle the use of retiming only [default = %s]\n", fRetimingOnly? "yes": "no" ); Abc_Print( -2, "\t-b : toggle bug insertion [default = %s]\n", fAddBugs? "yes": "no" ); Abc_Print( -2, "\t-c : enable CNF-based proof (no speculative reduction) [default = %s]\n", fUseCnf? "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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandQbf( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int nPars; int nIters; int fDumpCnf; int fVerbose; extern void Abc_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int nIters, int fDumpCnf, int fVerbose ); // set defaults nPars = -1; nIters = 500; fDumpCnf = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "PIdvh" ) ) != EOF ) { switch ( c ) { case 'P': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); goto usage; } nPars = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nPars < 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 'd': fDumpCnf ^= 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_NtkIsComb(pNtk) ) { Abc_Print( -1, "Works only for combinational networks.\n" ); return 1; } if ( Abc_NtkPoNum(pNtk) != 1 ) { Abc_Print( -1, "The miter should have one primary output.\n" ); return 1; } if ( !(nPars > 0 && nPars < Abc_NtkPiNum(pNtk)) ) { Abc_Print( -1, "The number of parameter variables is invalid (should be > 0 and < PI num).\n" ); return 1; } if ( Abc_NtkIsStrash(pNtk) ) Abc_NtkQbf( pNtk, nPars, nIters, fDumpCnf, fVerbose ); else { pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 ); Abc_NtkQbf( pNtk, nPars, nIters, fDumpCnf, fVerbose ); Abc_NtkDelete( pNtk ); } return 0; usage: Abc_Print( -2, "usage: qbf [-PI num] [-dvh]\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", nIters ); Abc_Print( -2, "\t-d : toggle dumping QDIMACS file instead of solving [default = %s]\n", fDumpCnf? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t\n" ); Abc_Print( -2, "\t Consider specification of the two-input XOR and its implementation in the form of a 4:1 MUX:\n\n" ); Abc_Print( -2, "\t > # file s.blif\n" ); Abc_Print( -2, "\t > .model xor2\n" ); Abc_Print( -2, "\t > .inputs d0 d1 d2 d3 a b\n" ); Abc_Print( -2, "\t > .outputs F\n" ); Abc_Print( -2, "\t > .names a b F\n" ); Abc_Print( -2, "\t > 01 1\n" ); Abc_Print( -2, "\t > 10 1\n" ); Abc_Print( -2, "\t > .end\n\n" ); Abc_Print( -2, "\t > # file i.blif\n" ); Abc_Print( -2, "\t > .model mux21\n" ); Abc_Print( -2, "\t > .inputs d0 d1 d2 d3 a b\n" ); Abc_Print( -2, "\t > .outputs F\n" ); Abc_Print( -2, "\t > .names d0 d1 d2 d3 a b F\n" ); Abc_Print( -2, "\t > 1---00 1\n" ); Abc_Print( -2, "\t > -1--10 1\n" ); Abc_Print( -2, "\t > --1-01 1\n" ); Abc_Print( -2, "\t > ---111 1\n" ); Abc_Print( -2, "\t > .end\n\n" ); Abc_Print( -2, "\t The following run shows how to assign data inputs to the MUX (the first 4 inputs of the miter) to get the XOR:\n\n" ); Abc_Print( -2, "\t > abc 51> miter -n i.blif s.blif; st -i; ps\n" ); Abc_Print( -2, "\t > i_s_miter: i/o = 6/ 1 lat = 0 and = 15 lev = 6\n\n" ); Abc_Print( -2, "\t > abc 53> qbf -P 4\n" ); Abc_Print( -2, "\t > Parameters: 0110 Statistics: 0=2 1=2\n" ); Abc_Print( -2, "\t > Solved after 1 iterations. Total runtime = 0.00 sec\n\n" ); Abc_Print( -2, "\t > abc 53> &get; &qbf -P 4\n" ); Abc_Print( -2, "\t > Parameters: 0110 Statistics: 0=2 1=2\n" ); Abc_Print( -2, "\t > The problem is SAT after 2 iterations. Time = 0.00 sec\n\n" ); Abc_Print( -2, "\t What we synthesized is the truth table of the XOR gate!\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandNpnLoad( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Npn_ManLoad( char * pFileName ); char * pFileName; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; pFileName = argv[globalUtilOptind]; Npn_ManLoad( pFileName ); return 0; usage: Abc_Print( -2, "usage: npnload \n" ); Abc_Print( -2, "\t loads previously saved 6-input function library from file\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandNpnSave( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Npn_ManSave( char * pFileName ); char * pFileName; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 1 ) goto usage; pFileName = argv[globalUtilOptind]; Npn_ManSave( pFileName ); return 0; usage: Abc_Print( -2, "usage: npnsave \n" ); Abc_Print( -2, "\t saves current 6-input function library into file\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSendAig( Abc_Frame_t * pAbc, int argc, char ** argv ) { // const int BRIDGE_NETLIST = 106; // const int BRIDGE_ABS_NETLIST = 107; int c, fAndSpace = 1, fAbsNetlist = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF ) { switch ( c ) { case 'a': fAndSpace ^= 1; break; case 'b': fAbsNetlist ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( !Abc_FrameIsBridgeMode() ) { Abc_Print( -1, "The bridge mode is not available.\n" ); return 1; } if ( fAndSpace ) { if ( pAbc->pGia == NULL ) { Abc_Print( -1, "There is no AIG in the &-space.\n" ); return 1; } Gia_ManToBridgeAbsNetlist( stdout, pAbc->pGia, fAbsNetlist ? BRIDGE_ABS_NETLIST : BRIDGE_NETLIST ); } else { Aig_Man_t * pAig; Gia_Man_t * pGia; if ( pAbc->pNtkCur == NULL ) { Abc_Print( -1, "There is no network in the main-space.\n" ); return 1; } if ( !Abc_NtkIsStrash(pAbc->pNtkCur) ) { Abc_Print( -1, "The main-space network is not an AIG.\n" ); return 1; } pAig = Abc_NtkToDar( pAbc->pNtkCur, 0, 1 ); pGia = Gia_ManFromAig( pAig ); Aig_ManStop( pAig ); Gia_ManToBridgeAbsNetlist( stdout, pGia, fAbsNetlist ? BRIDGE_ABS_NETLIST : BRIDGE_NETLIST ); Gia_ManStop( pGia ); } return 0; usage: Abc_Print( -2, "usage: send_aig -a\n" ); Abc_Print( -2, "\t sends current AIG to the bridge\n" ); Abc_Print( -2, "\t-a : toggle sending AIG from &-space [default = %s]\n", fAndSpace? "yes": "no" ); Abc_Print( -2, "\t-b : toggle sending netlist tagged as \"abstraction\". [default = %s]\n", fAbsNetlist? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandSendStatus( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern int Gia_ManToBridgeResult( FILE * pFile, int Result, Abc_Cex_t * pCex, int iPoProved ); int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( !Abc_FrameIsBridgeMode() ) { Abc_Print( -1, "The bridge mode is not available.\n" ); return 1; } if ( pAbc->Status == 0 && pAbc->pCex == NULL ) { Abc_Print( -1, "Status is \"sat\", but current CEX is not available.\n" ); return 1; } Gia_ManToBridgeResult( stdout, pAbc->Status, pAbc->pCex, 0 ); return 0; usage: Abc_Print( -2, "usage: send_status\n" ); Abc_Print( -2, "\t sends current status to the bridge\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandBackup( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( pAbc->pNtkBackup ) Abc_NtkDelete( pAbc->pNtkBackup ); pAbc->pNtkBackup = Abc_NtkDup( pNtk ); return 0; usage: Abc_Print( -2, "usage: backup [-h]\n" ); Abc_Print( -2, "\t backs up the current network\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } int Abc_CommandRestore( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( pAbc->pNtkBackup == NULL ) { Abc_Print( -1, "There is no backup network.\n" ); return 1; } Abc_FrameReplaceCurrentNetwork( pAbc, Abc_NtkDup(pAbc->pNtkBackup) ); pAbc->nFrames = -1; pAbc->Status = -1; return 0; usage: Abc_Print( -2, "usage: restore [-h]\n" ); Abc_Print( -2, "\t restores the current network\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandMinisat( Abc_Frame_t * pAbc, int argc, char ** argv ) { #ifdef USE_MINISAT22 extern int MainSat(int argc, char** argv); MainSat( argc, argv ); #else printf( "This command is currently disabled.\n" ); #endif return 1; } int Abc_CommandMinisimp( Abc_Frame_t * pAbc, int argc, char ** argv ) { #ifdef USE_MINISAT22 extern int MainSimp(int argc, char** argv); MainSimp( argc, argv ); #else printf( "This command is currently disabled.\n" ); #endif return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) { char Buffer[100]; Fraig_Params_t Params, * pParams = &Params; Abc_Ntk_t * pNtk, * pNtkRes; int fAllNodes; int fExdc; int c; int fPartition = 0; extern void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fExdc = 0; fAllNodes = 0; memset( pParams, 0, sizeof(Fraig_Params_t) ); pParams->nPatsRand = 2048; // the number of words of random simulation info pParams->nPatsDyna = 2048; // the number of words of dynamic simulation info pParams->nBTLimit = 100; // the max number of backtracks to perform pParams->fFuncRed = 1; // performs only one level hashing pParams->fFeedBack = 1; // enables solver feedback pParams->fDist1Pats = 1; // enables distance-1 patterns pParams->fDoSparse = 1; // performs equiv tests for sparse functions pParams->fChoicing = 0; // enables recording structural choices pParams->fTryProve = 0; // tries to solve the final miter pParams->fVerbose = 0; // the verbosiness flag pParams->fVerboseP = 0; // the verbosiness flag Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "RDCrscptvaeh" ) ) != EOF ) { switch ( c ) { case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } pParams->nPatsRand = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pParams->nPatsRand < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } pParams->nPatsDyna = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pParams->nPatsDyna < 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; } pParams->nBTLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pParams->nBTLimit < 0 ) goto usage; break; case 'r': pParams->fFuncRed ^= 1; break; case 's': pParams->fDoSparse ^= 1; break; case 'c': pParams->fChoicing ^= 1; break; case 'p': pParams->fTryProve ^= 1; break; case 'v': pParams->fVerbose ^= 1; break; case 't': fPartition ^= 1; break; case 'a': fAllNodes ^= 1; break; case 'e': fExdc ^= 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 fraig a logic network or an AIG.\n" ); return 1; } // report the proof pParams->fVerboseP = pParams->fTryProve; // get the new network if ( fPartition ) { pNtkRes = Abc_NtkDup( pNtk ); if ( Abc_NtkIsStrash(pNtk) ) Abc_NtkFraigPartitionedTime( pNtk, &Params ); else { pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 ); Abc_NtkFraigPartitionedTime( pNtk, &Params ); Abc_NtkDelete( pNtk ); } } else { if ( Abc_NtkIsStrash(pNtk) ) pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc ); else { pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 ); pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc ); Abc_NtkDelete( pNtk ); } } if ( pNtkRes == NULL ) { Abc_Print( -1, "Fraiging has failed.\n" ); return 1; } if ( pParams->fTryProve ) // report the result Abc_NtkMiterReport( pNtkRes ); // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: sprintf(Buffer, "%d", pParams->nBTLimit ); Abc_Print( -2, "usage: fraig [-R num] [-D num] [-C num] [-rscpvtah]\n" ); Abc_Print( -2, "\t transforms a logic network into a functionally reduced AIG\n" ); Abc_Print( -2, "\t (known bugs: takes an UNSAT miter and returns a SAT one)\n"); Abc_Print( -2, "\t (there are newer fraiging commands, \"ifraig\" and \"dfraig\")\n" ); Abc_Print( -2, "\t-R num : number of random patterns (127 < num < 32769) [default = %d]\n", pParams->nPatsRand ); Abc_Print( -2, "\t-D num : number of systematic patterns (127 < num < 32769) [default = %d]\n", pParams->nPatsDyna ); Abc_Print( -2, "\t-C num : number of backtracks for one SAT problem [default = %s]\n", pParams->nBTLimit==-1? "infinity" : Buffer ); Abc_Print( -2, "\t-r : toggle functional reduction [default = %s]\n", pParams->fFuncRed? "yes": "no" ); Abc_Print( -2, "\t-s : toggle considering sparse functions [default = %s]\n", pParams->fDoSparse? "yes": "no" ); Abc_Print( -2, "\t-c : toggle accumulation of choices [default = %s]\n", pParams->fChoicing? "yes": "no" ); Abc_Print( -2, "\t-p : toggle proving the miter outputs [default = %s]\n", pParams->fTryProve? "yes": "no" ); Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", pParams->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-e : toggle functional sweeping using EXDC [default = %s]\n", fExdc? "yes": "no" ); Abc_Print( -2, "\t-a : toggle between all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "dfs" ); Abc_Print( -2, "\t-t : toggle using partitioned representation [default = %s]\n", fPartition? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandFraigTrust( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; int fDuplicate; pNtk = Abc_FrameReadNtk(pAbc); // set defaults fDuplicate = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) { switch ( c ) { case 'd': fDuplicate ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } // get the new network pNtkRes = Abc_NtkFraigTrust( pNtk ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Fraiging in the trust mode has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: fraig_trust [-h]\n" ); Abc_Print( -2, "\t transforms the current network into an AIG assuming it is FRAIG with choices\n" ); // Abc_Print( -2, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandFraigStore( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fDuplicate; // set defaults fDuplicate = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) { switch ( c ) { case 'd': fDuplicate ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } // get the new network if ( !Abc_NtkFraigStore( pNtk ) ) { Abc_Print( -1, "Fraig storing has failed.\n" ); return 1; } return 0; usage: Abc_Print( -2, "usage: fraig_store [-h]\n" ); Abc_Print( -2, "\t saves the current network in the AIG database\n" ); // Abc_Print( -2, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandFraigRestore( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; int c; int nPatsRand = 0; // the number of words of random simulation info int nPatsDyna = 0; // the number of words of dynamic simulation info int nBTLimit = 1000; // the max number of backtracks to perform pNtk = Abc_FrameReadNtk(pAbc); // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "RDCh" ) ) != EOF ) { switch ( c ) { case 'R': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); goto usage; } nPatsRand = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nPatsRand < 0 ) goto usage; break; case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); goto usage; } nPatsDyna = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nPatsDyna < 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; } nBTLimit = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nBTLimit < 0 ) goto usage; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } // get the new network pNtkRes = Abc_NtkFraigRestore( nPatsRand, nPatsDyna, nBTLimit ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Fraig restoring has failed.\n" ); return 1; } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: fraig_restore [-RDC num] [-h]\n" ); Abc_Print( -2, "\t makes the current network by fraiging the AIG database\n" ); Abc_Print( -2, "\t-R num : number of random patterns (127 < num < 32769) [default = design-dependent]\n" ); Abc_Print( -2, "\t-D num : number of systematic patterns (127 < num < 32769) [default = design-dependent]\n" ); Abc_Print( -2, "\t-C num : number of backtracks for one SAT problem [default = %d]\n", nBTLimit ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandFraigClean( Abc_Frame_t * pAbc, int argc, char ** argv ) { // Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fDuplicate; // set defaults fDuplicate = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) { switch ( c ) { case 'd': fDuplicate ^= 1; break; case 'h': goto usage; default: goto usage; } } Abc_NtkFraigStoreClean(); return 0; usage: Abc_Print( -2, "usage: fraig_clean [-h]\n" ); Abc_Print( -2, "\t cleans the internal FRAIG storage\n" ); // Abc_Print( -2, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fUseInv; int fExdc; int fVerbose; int fVeryVerbose; extern int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); // set defaults fUseInv = 1; fExdc = 0; fVerbose = 0; fVeryVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ievwh" ) ) != EOF ) { switch ( c ) { case 'i': fUseInv ^= 1; break; case 'e': fExdc ^= 1; break; case 'v': fVerbose ^= 1; break; case 'w': fVeryVerbose ^= 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, "Cannot sweep AIGs (use \"fraig\").\n" ); return 1; } if ( !Abc_NtkIsLogic(pNtk) ) { Abc_Print( -1, "Transform the current network into a logic network.\n" ); return 1; } // modify the current network if ( !Abc_NtkFraigSweep( pNtk, fUseInv, fExdc, fVerbose, fVeryVerbose ) ) { Abc_Print( -1, "Sweeping has failed.\n" ); return 1; } return 0; usage: Abc_Print( -2, "usage: fraig_sweep [-evwh]\n" ); Abc_Print( -2, "\t performs technology-dependent sweep\n" ); Abc_Print( -2, "\t-e : toggle functional sweeping using EXDC [default = %s]\n", fExdc? "yes": "no" ); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-w : prints equivalence class 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_CommandFraigDress( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkDress( Abc_Ntk_t * pNtk, char * pFileName, int fVerbose ); extern void Abc_NtkDress2( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConflictLimit, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtk2; char * pFileName; int c; int nConfs; int fVerbose; // set defaults nConfs = 1000; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Cvh" ) ) != EOF ) { switch ( c ) { case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } nConfs = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nConfs < 0 ) goto usage; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works only for logic networks.\n" ); return 1; } if ( argc != globalUtilOptind && argc != globalUtilOptind + 1 ) goto usage; if ( argc == globalUtilOptind && Abc_NtkSpec(pNtk) == NULL ) { Abc_Print( -1, "The current network has no spec.\n" ); return 1; } // get the input file name pFileName = (argc == globalUtilOptind + 1) ? argv[globalUtilOptind] : Abc_NtkSpec(pNtk); // modify the current network // Abc_NtkDress( pNtk, pFileName, fVerbose ); pNtk2 = Io_Read( pFileName, Io_ReadFileType(pFileName), 1, 0 ); Abc_NtkDress2( pNtk, pNtk2, nConfs, fVerbose ); Abc_NtkDelete( pNtk2 ); return 0; usage: Abc_Print( -2, "usage: dress [-C num] [-vh] \n" ); Abc_Print( -2, "\t transfers internal node names from file to the current network\n" ); Abc_Print( -2, "\t : network with names (if not given, the current network spec is used)\n" ); Abc_Print( -2, "\t-C num : the maximum number of conflicts at each node [default = %d]\n", nConfs ); Abc_Print( -2, "\t-v : prints 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_CommandDumpEquiv( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkDumpEquiv( Abc_Ntk_t * pNtks[2], char * pFileName, int nConfs, int fByName, int fVerbose ); Abc_Ntk_t * pNtks[2] = {NULL}; char * pFileName[2], * pFileNameOut; int c, nConfs = 1000, fByName = 1, fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "Cnvh" ) ) != 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 'n': fByName ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( argc != globalUtilOptind + 3 ) { Abc_Print( -1, "Expecting three file names on the command line.\n" ); goto usage; } pFileName[0] = argv[globalUtilOptind]; pFileName[1] = argv[globalUtilOptind+1]; pFileNameOut = argv[globalUtilOptind+2]; for ( c = 0; c < 2; c++ ) { pNtks[c] = Io_Read( pFileName[c], Io_ReadFileType(pFileName[c]), 1, 0 ); if ( pNtks[c] == NULL ) goto usage; Abc_NtkToAig( pNtks[c] ); } // if ( Abc_NtkCiNum(pNtks[0]) != Abc_NtkCiNum(pNtks[1]) ) // Abc_Print( -1, "The number of primary inputs of networks \"%s\" and \"%s\" does not match.\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]) ); // else if ( Abc_NtkCoNum(pNtks[0]) != Abc_NtkCoNum(pNtks[1]) ) // Abc_Print( -1, "The number of primary outputs of networks \"%s\" and \"%s\" does not match.\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]) ); // else Abc_NtkDumpEquiv( pNtks, pFileNameOut, nConfs, fByName, fVerbose ); Abc_NtkDelete( pNtks[0] ); Abc_NtkDelete( pNtks[1] ); return 0; usage: Abc_Print( -2, "usage: dump_equiv [-C num] [-nvh] \n" ); Abc_Print( -2, "\t computes equivalence classes of nodes in and \n" ); Abc_Print( -2, "\t By default this procedure performs matching of primary inputs by name.\n" ); Abc_Print( -2, "\t Those inputs that cannot be matched are treated as free variables.\n" ); Abc_Print( -2, "\t There is no effort to match primary outputs. Indeed, if two outputs\n" ); Abc_Print( -2, "\t are equivalent, they will belong to the same equivalence class in the end.\n" ); Abc_Print( -2, "\t-C num : the maximum number of conflicts at each node [default = %d]\n", nConfs ); Abc_Print( -2, "\t-n : enable matching of primary inputs by name [default = %s]\n", fByName? "yes": "no" ); Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : first network whose nodes are considered\n" ); Abc_Print( -2, "\t : second network whose nodes are considered\n" ); Abc_Print( -2, "\t : text file with node equivalence classes\n" ); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandRecStart3( Abc_Frame_t * pAbc, int argc, char ** argv ) { char * FileName, * pTemp; char ** pArgvNew; int c, nArgcNew; FILE * pFile; Gia_Man_t * pGia = NULL; int nVars = 6; int nCuts = 32; int fFuncOnly = 0; int fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "KCfvh" ) ) != EOF ) { switch ( c ) { case 'K': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); goto usage; } nVars = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nVars < 1 ) goto usage; break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); goto usage; } nCuts = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nCuts < 1 ) goto usage; break; case 'f': fFuncOnly ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( !(nVars >= 3 && nVars <= 16) ) { Abc_Print( -1, "The range of allowed values is 3 <= K <= 16.\n" ); return 0; } if ( Abc_NtkRecIsRunning3() ) { Abc_Print( -1, "The AIG subgraph recording is already started.\n" ); return 0; } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) Abc_Print( 1, "File name is not given on the command line. Starting a new record.\n" ); else { // 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", NULL, NULL, NULL, NULL )) ) Abc_Print( 1, "Did you mean \"%s\"?", FileName ); Abc_Print( 1, "\n" ); return 1; } fclose( pFile ); pGia = Gia_AigerRead( FileName, 0, 1, 0 ); if ( pGia == NULL ) { Abc_Print( -1, "Reading AIGER has failed.\n" ); return 0; } } Abc_NtkRecStart3( pGia, nVars, nCuts, fFuncOnly, fVerbose ); return 0; usage: Abc_Print( -2, "usage: rec_start3 [-K num] [-C num] [-fvh] \n" ); Abc_Print( -2, "\t starts recording AIG subgraphs (should be called for\n" ); Abc_Print( -2, "\t an empty network or after reading in a previous record)\n" ); Abc_Print( -2, "\t-K num : the largest number of inputs [default = %d]\n", nVars ); Abc_Print( -2, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCuts ); Abc_Print( -2, "\t-f : toggles recording functions without AIG subgraphs [default = %s]\n", fFuncOnly? "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 : AIGER file with the library\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandRecStop3( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( !Abc_NtkRecIsRunning3() ) { Abc_Print( -1, "This command works only after calling \"rec_start3\".\n" ); return 0; } Abc_NtkRecStop3(); return 0; usage: Abc_Print( -2, "usage: rec_stop3 [-h]\n" ); Abc_Print( -2, "\t cleans the internal storage for AIG subgraphs\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandRecPs3( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c, fPrintLib = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "ph" ) ) != EOF ) { switch ( c ) { case 'p': fPrintLib ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( !Abc_NtkRecIsRunning3() ) { Abc_Print( -1, "This command works for AIGs only after calling \"rec_start3\".\n" ); return 0; } Abc_NtkRecPs3(fPrintLib); return 0; usage: Abc_Print( -2, "usage: rec_ps3 [-h]\n" ); Abc_Print( -2, "\t prints statistics about the recorded AIG subgraphs\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandRecAdd3( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int c; int fUseSOPB = 0; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "gh" ) ) != EOF ) { switch ( c ) { case 'g': fUseSOPB = 1; break; case 'h': goto usage; default: goto usage; } } if ( !Abc_NtkIsStrash(pNtk) ) { Abc_Print( -1, "This command works for AIGs.\n" ); return 0; } if ( !Abc_NtkRecIsRunning3() ) { Abc_Print( -1, "This command works for AIGs after calling \"rec_start3\".\n" ); return 0; } Abc_NtkRecAdd3( pNtk, fUseSOPB ); return 0; usage: Abc_Print( -2, "usage: rec_add3 [-h]\n" ); Abc_Print( -2, "\t adds subgraphs from the current network to the set\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandRecDump3( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkRecDumpTt3( char * pFileName, int fBinary ); char * FileName; char ** pArgvNew; int nArgcNew; Gia_Man_t * pGia; int fAscii = 0; int fBinary = 0; int c; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "abh" ) ) != EOF ) { switch ( c ) { case 'a': fAscii ^= 1; break; case 'b': fBinary ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( !Abc_NtkRecIsRunning3() ) { Abc_Print( -1, "The AIG subgraph recording is not started.\n" ); return 1; } pArgvNew = argv + globalUtilOptind; nArgcNew = argc - globalUtilOptind; if ( nArgcNew != 1 ) { Abc_Print( -1, "File name is not given on the command line.\n" ); return 1; } // get the input file name FileName = pArgvNew[0]; if ( fAscii ) Abc_NtkRecDumpTt3( FileName, 0 ); else if ( fBinary ) Abc_NtkRecDumpTt3( FileName, 1 ); else { pGia = Abc_NtkRecGetGia3(); if( pGia == NULL ) { Abc_Print( 0, "Library AIG is not available.\n" ); return 1; } if( Gia_ManPoNum(pGia) == 0 ) { Abc_Print( 0, "No structure in the library.\n" ); return 1; } Gia_AigerWrite( pGia, FileName, 0, 0, 0 ); } return 0; usage: Abc_Print( -2, "usage: rec_dump3 [-abh] \n" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t-a : toggles dumping TTs into an ASCII file [default = %s]\n", fAscii? "yes": "no" ); Abc_Print( -2, "\t-b : toggles dumping TTs into a binary file [default = %s]\n", fBinary? "yes": "no" ); Abc_Print( -2, "\t : AIGER file to write the library\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandRecMerge3( Abc_Frame_t * pAbc, int argc, char ** argv ) { int c; char * FileName, * pTemp; char ** pArgvNew; int nArgcNew; FILE * pFile; Gia_Man_t * pGia = NULL; // set defaults Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) { switch ( c ) { case 'h': goto usage; default: goto usage; } } if ( !Abc_NtkRecIsRunning3() ) { Abc_Print( -1, "This command works for AIGs only after calling \"rec_start3\".\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; } else { // 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", NULL, NULL, NULL, NULL )) ) Abc_Print( 1, "Did you mean \"%s\"?", FileName ); Abc_Print( 1, "\n" ); return 1; } fclose( pFile ); pGia = Gia_AigerRead( FileName, 0, 1, 0 ); if ( pGia == NULL ) { Abc_Print( -1, "Reading AIGER has failed.\n" ); return 0; } } Abc_NtkRecLibMerge3(pGia); Gia_ManStop( pGia ); return 0; usage: Abc_Print( -2, "usage: rec_merge3 [-h] \n" ); Abc_Print( -2, "\t merge libraries\n" ); Abc_Print( -2, "\t-h : print the command usage\n"); Abc_Print( -2, "\t : AIGER file with the library\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk, * pNtkRes; char Buffer[100]; double DelayTarget; double AreaMulti; double DelayMulti; float LogFan = 0; float Slew = 0; // choose based on the library float Gain = 250; int nGatesMin = 0; int fAreaOnly; int fRecovery; int fSweep; int fSwitching; int fSkipFanout; int fUseProfile; int fUseBuffs; int fVerbose; int c; extern Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, Mio_Library_t* userLib, double DelayTarget, double AreaMulti, double DelayMulti, float LogFan, float Slew, float Gain, int nGatesMin, int fRecovery, int fSwitching, int fSkipFanout, int fUseProfile, int fUseBuffs, int fVerbose ); extern int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults DelayTarget =-1; AreaMulti = 0; DelayMulti = 0; fAreaOnly = 0; fRecovery = 1; fSweep = 0; fSwitching = 0; fSkipFanout = 0; fUseProfile = 0; fUseBuffs = 0; fVerbose = 0; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "DABFSGMarspfuovh" ) ) != EOF ) { switch ( c ) { case 'D': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" ); goto usage; } DelayTarget = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( DelayTarget <= 0.0 ) goto usage; break; case 'A': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-A\" should be followed by a floating point number.\n" ); goto usage; } AreaMulti = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; break; case 'B': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-B\" should be followed by a floating point number.\n" ); goto usage; } DelayMulti = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; break; case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by a floating point number.\n" ); goto usage; } LogFan = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( LogFan < 0.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" ); goto usage; } Slew = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( Slew <= 0.0 ) goto usage; break; case 'G': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-G\" should be followed by a floating point number.\n" ); goto usage; } Gain = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( Gain <= 0.0 ) goto usage; break; case 'M': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-M\" should be followed by a positive integer.\n" ); goto usage; } nGatesMin = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( nGatesMin < 0 ) goto usage; break; case 'a': fAreaOnly ^= 1; break; case 'r': fRecovery ^= 1; break; case 's': fSweep ^= 1; break; case 'p': fSwitching ^= 1; break; case 'f': fSkipFanout ^= 1; break; case 'u': fUseProfile ^= 1; break; case 'o': fUseBuffs ^= 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 ( fAreaOnly ) DelayTarget = ABC_INFINITY; if ( !Abc_NtkIsStrash(pNtk) ) { pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); if ( pNtk == NULL ) { Abc_Print( -1, "Strashing before mapping has failed.\n" ); return 1; } pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); Abc_NtkDelete( pNtkRes ); if ( pNtk == NULL ) { Abc_Print( -1, "Balancing before mapping has failed.\n" ); return 1; } Abc_Print( 0, "The network was strashed and balanced before mapping.\n" ); // get the new network pNtkRes = Abc_NtkMap( pNtk, /*userLib=*/NULL, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, fUseBuffs, fVerbose ); if ( pNtkRes == NULL ) { Abc_NtkDelete( pNtk ); Abc_Print( -1, "Mapping has failed.\n" ); return 1; } Abc_NtkDelete( pNtk ); } else { // get the new network pNtkRes = Abc_NtkMap( pNtk, /*userLib=*/NULL, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, fUseBuffs, fVerbose ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Mapping has failed.\n" ); return 1; } } if ( fSweep ) { Abc_NtkFraigSweep( pNtkRes, 0, 0, 0, 0 ); if ( Abc_NtkHasMapping(pNtkRes) ) { pNtkRes = Abc_NtkDupDfs( pNtk = pNtkRes ); Abc_NtkDelete( pNtk ); } } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: if ( DelayTarget == -1 ) sprintf(Buffer, "not used" ); else sprintf(Buffer, "%.3f", DelayTarget ); 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 ); Abc_Print( -2, "\t-B float : \"delay multiplier\" to bias gate selection [default = %.2f]\n", DelayMulti ); Abc_Print( -2, "\t-F float : the logarithmic fanout delay parameter [default = %.2f]\n", LogFan ); Abc_Print( -2, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew ); Abc_Print( -2, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain ); Abc_Print( -2, "\t-M num : skip gate classes whose size is less than this [default = %d]\n", nGatesMin ); Abc_Print( -2, "\t-a : toggles area-only mapping [default = %s]\n", fAreaOnly? "yes": "no" ); Abc_Print( -2, "\t-r : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" ); Abc_Print( -2, "\t-s : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" ); 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; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandAmap( Abc_Frame_t * pAbc, int argc, char ** argv ) { Amap_Par_t Pars, * pPars = &Pars; Abc_Ntk_t * pNtk, * pNtkRes; int fSweep; int c; extern Abc_Ntk_t * Abc_NtkDarAmap( Abc_Ntk_t * pNtk, Amap_Par_t * pPars ); extern int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); pNtk = Abc_FrameReadNtk(pAbc); // set defaults fSweep = 0; Amap_ManSetDefaultParams( pPars ); Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "FACEQmxisvh" ) ) != EOF ) { switch ( c ) { case 'F': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-F\" should be followed by a floating point number.\n" ); goto usage; } pPars->nIterFlow = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nIterFlow < 0 ) goto usage; break; case 'A': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-A\" should be followed by a floating point number.\n" ); goto usage; } pPars->nIterArea = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nIterArea < 0 ) goto usage; break; case 'C': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-C\" should be followed by a floating point number.\n" ); goto usage; } pPars->nCutsMax = atoi(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->nCutsMax < 0 ) goto usage; break; case 'E': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-E\" should be followed by a floating point number.\n" ); goto usage; } pPars->fEpsilon = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->fEpsilon < 0.0 || pPars->fEpsilon > 1.0 ) goto usage; break; case 'Q': if ( globalUtilOptind >= argc ) { Abc_Print( -1, "Command line switch \"-Q\" should be followed by a floating point number.\n" ); goto usage; } pPars->fADratio = (float)atof(argv[globalUtilOptind]); globalUtilOptind++; if ( pPars->fADratio < 0.0 ) goto usage; break; case 'm': pPars->fUseMuxes ^= 1; break; case 'x': pPars->fUseXors ^= 1; break; case 'i': pPars->fFreeInvs ^= 1; break; case 's': fSweep ^= 1; break; case 'v': pPars->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) ) { pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); if ( pNtk == NULL ) { Abc_Print( -1, "Strashing before mapping has failed.\n" ); return 1; } pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); Abc_NtkDelete( pNtkRes ); if ( pNtk == NULL ) { Abc_Print( -1, "Balancing before mapping has failed.\n" ); return 1; } Abc_Print( 0, "The network was strashed and balanced before mapping.\n" ); // get the new network pNtkRes = Abc_NtkDarAmap( pNtk, pPars ); if ( pNtkRes == NULL ) { Abc_NtkDelete( pNtk ); Abc_Print( -1, "Mapping has failed.\n" ); return 1; } Abc_NtkDelete( pNtk ); } else { // get the new network pNtkRes = Abc_NtkDarAmap( pNtk, pPars ); if ( pNtkRes == NULL ) { Abc_Print( -1, "Mapping has failed.\n" ); return 1; } } if ( fSweep ) { Abc_NtkFraigSweep( pNtkRes, 0, 0, 0, 0 ); if ( Abc_NtkHasMapping(pNtkRes) ) { pNtkRes = Abc_NtkDupDfs( pNtk = pNtkRes ); Abc_NtkDelete( pNtk ); } } // replace the current network Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); return 0; usage: Abc_Print( -2, "usage: amap [-FAC ] [-EQ ] [-mxisvh]\n" ); Abc_Print( -2, "\t performs standard cell mapping of the current network\n" ); Abc_Print( -2, "\t-F num : the number of iterations of area flow [default = %d]\n", pPars->nIterFlow ); Abc_Print( -2, "\t-A num : the number of iterations of exact area [default = %d]\n", pPars->nIterArea ); Abc_Print( -2, "\t-C num : the maximum number of cuts at a node [default = %d]\n", pPars->nCutsMax ); Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->fEpsilon ); Abc_Print( -2, "\t-Q float : area/delay preference ratio [default = %.2f (area-only)] \n", pPars->fADratio ); Abc_Print( -2, "\t-m : toggles using MUX matching [default = %s]\n", pPars->fUseMuxes? "yes": "no" ); Abc_Print( -2, "\t-x : toggles using XOR matching [default = %s]\n", pPars->fUseXors? "yes": "no" ); Abc_Print( -2, "\t-i : toggles assuming inverters are free [default = %s]\n", pPars->fFreeInvs? "yes": "no" ); Abc_Print( -2, "\t-s : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" ); Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); Abc_Print( -2, "\t-h : print the command usage\n"); return 1; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandPhaseMap( Abc_Frame_t * pAbc, int argc, char ** argv ) { extern void Abc_NtkChangePerform( Abc_Ntk_t * pNtk, int fVerbose ); Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); int fVerbose = 0, c; // 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; } } if ( pNtk == NULL ) { Abc_Print( -1, "Empty network.\n" ); return 1; } if ( !Abc_NtkHasMapping(pNtk) ) { Abc_Print( -1, "Cannot unmap the network that is not mapped.\n" ); return 1; } Abc_NtkChangePerform( pNtk, fVerbose ); return 0; usage: Abc_Print( -2, "usage: phase_map [-vh]\n" ); Abc_Print( -2, "\t tries to replace each gate by its complement (area-only)\n" ); 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; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_CommandStochMap( Abc_Frame_t * pAbc, int argc, char ** argv ) { Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); extern void Abc_NtkStochMap( int nSuppMax, int nIters, int TimeOut, int Seed, int fOverlap, int fVerbose, char * pScript, int nProcs ); int c, nMaxSize = 14, nIters = 1, TimeOut = 0, Seed = 0, nProcs = 1, fOverlap = 0, fVerbose = 0; char * pScript; Extra_UtilGetoptReset(); while ( ( c = Extra_UtilGetopt( argc, argv, "NITSPovh" ) ) != 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 'o': fOverlap ^= 1; break; case 'v': fVerbose ^= 1; break; case 'h': goto usage; default: goto usage; } } if ( pNtk == NULL ) { Abc_Print( -1, "Abc_CommandStochMap(): There is no AIG.\n" ); return 0; } if ( !Abc_NtkIsMappedLogic(pNtk) ) { Abc_Print( -1, "Abc_CommandStochMap(): Expecting a mapped current newtork as input.\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] ); Abc_NtkStochMap( nMaxSize, nIters, TimeOut, Seed, fOverlap, fVerbose, pScript, nProcs ); ABC_FREE( pScript ); return 0; usage: Abc_Print( -2, "usage: stochmap [-NITSP ] [-ovh]